]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. | |
7 | * | |
8 | * This file contains Original Code and/or Modifications of Original Code | |
9 | * as defined in and that are subject to the Apple Public Source License | |
10 | * Version 2.0 (the 'License'). You may not use this file except in | |
11 | * compliance with the License. Please obtain a copy of the License at | |
12 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
13 | * file. | |
14 | * | |
15 | * The Original Code and all software distributed under the License are | |
16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
19 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
20 | * Please see the License for the specific language governing rights and | |
21 | * limitations under the License. | |
22 | * | |
23 | * @APPLE_LICENSE_HEADER_END@ | |
24 | */ | |
25 | /* | |
26 | * Copyright (c) 1983, 1988, 1993 | |
27 | * The Regents of the University of California. All rights reserved. | |
28 | * | |
29 | * Redistribution and use in source and binary forms, with or without | |
30 | * modification, are permitted provided that the following conditions | |
31 | * are met: | |
32 | * 1. Redistributions of source code must retain the above copyright | |
33 | * notice, this list of conditions and the following disclaimer. | |
34 | * 2. Redistributions in binary form must reproduce the above copyright | |
35 | * notice, this list of conditions and the following disclaimer in the | |
36 | * documentation and/or other materials provided with the distribution. | |
37 | * 3. All advertising materials mentioning features or use of this software | |
38 | * must display the following acknowledgment: | |
39 | * This product includes software developed by the University of | |
40 | * California, Berkeley and its contributors. | |
41 | * 4. Neither the name of the University nor the names of its contributors | |
42 | * may be used to endorse or promote products derived from this software | |
43 | * without specific prior written permission. | |
44 | * | |
45 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
46 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
47 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
48 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
49 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
50 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
51 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
52 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
53 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
54 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
55 | * SUCH DAMAGE. | |
56 | * | |
57 | * @(#)defs.h 8.1 (Berkeley) 6/5/93 | |
58 | */ | |
59 | ||
60 | ||
61 | /* | |
62 | * Routing Table Management Daemon | |
63 | */ | |
64 | #include "defs.h" | |
65 | #include <sys/ioctl.h> | |
66 | #include <sys/sysctl.h> | |
67 | #include <net/if.h> | |
68 | #include <net/if_dl.h> | |
69 | #include <syslog.h> | |
70 | #include <stdlib.h> | |
71 | #include "pathnames.h" | |
72 | ||
73 | struct interface *ifnet; | |
74 | struct interface **ifnext = &ifnet; | |
75 | int lookforinterfaces = 1; | |
76 | int externalinterfaces = 0; /* # of remote and local interfaces */ | |
77 | int foundloopback; /* valid flag for loopaddr */ | |
78 | struct sockaddr loopaddr; /* our address on loopback */ | |
79 | ||
80 | ||
81 | void | |
82 | quit(s) | |
83 | char *s; | |
84 | { | |
85 | extern int errno; | |
86 | int sverrno = errno; | |
87 | ||
88 | (void) fprintf(stderr, "route: "); | |
89 | if (s) | |
90 | (void) fprintf(stderr, "%s: ", s); | |
91 | (void) fprintf(stderr, "%s\n", strerror(sverrno)); | |
92 | exit(1); | |
93 | /* NOTREACHED */ | |
94 | } | |
95 | ||
96 | struct rt_addrinfo info; | |
97 | /* Sleazy use of local variables throughout file, warning!!!! */ | |
98 | #define netmask info.rti_info[RTAX_NETMASK] | |
99 | #define ifaaddr info.rti_info[RTAX_IFA] | |
100 | #define brdaddr info.rti_info[RTAX_BRD] | |
101 | ||
102 | #define ROUNDUP(a) \ | |
103 | ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) | |
104 | #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) | |
105 | ||
106 | void | |
107 | rt_xaddrs(cp, cplim, rtinfo) | |
108 | register caddr_t cp, cplim; | |
109 | register struct rt_addrinfo *rtinfo; | |
110 | { | |
111 | register struct sockaddr *sa; | |
112 | register int i; | |
113 | ||
114 | memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); | |
115 | for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { | |
116 | if ((rtinfo->rti_addrs & (1 << i)) == 0) | |
117 | continue; | |
118 | rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; | |
119 | ADVANCE(cp, sa); | |
120 | } | |
121 | } | |
122 | ||
123 | /* | |
124 | * Find the network interfaces which have configured themselves. | |
125 | * If the interface is present but not yet up (for example an | |
126 | * ARPANET IMP), set the lookforinterfaces flag so we'll | |
127 | * come back later and look again. | |
128 | */ | |
129 | ifinit() | |
130 | { | |
131 | struct interface ifs, *ifp; | |
132 | size_t needed; | |
133 | int mib[6], no_ipaddr = 0, flags = 0; | |
134 | char *buf, *cplim, *cp; | |
135 | register struct if_msghdr *ifm; | |
136 | register struct ifa_msghdr *ifam; | |
137 | struct sockaddr_dl *sdl; | |
138 | struct sockaddr_in *sin; | |
139 | u_long i; | |
140 | ||
141 | mib[0] = CTL_NET; | |
142 | mib[1] = PF_ROUTE; | |
143 | mib[2] = 0; | |
144 | mib[3] = AF_INET; | |
145 | mib[4] = NET_RT_IFLIST; | |
146 | mib[5] = 0; | |
147 | if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) | |
148 | quit("route-sysctl-estimate"); | |
149 | if ((buf = malloc(needed)) == NULL) | |
150 | quit("malloc"); | |
151 | if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) | |
152 | quit("actual retrieval of interface table"); | |
153 | lookforinterfaces = 0; | |
154 | cplim = buf + needed; | |
155 | for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) { | |
156 | ifm = (struct if_msghdr *)cp; | |
157 | if (ifm->ifm_type == RTM_IFINFO) { | |
158 | memset(&ifs, 0, sizeof(ifs)); | |
159 | ifs.int_flags = flags = (0xffff & ifm->ifm_flags) | IFF_INTERFACE; | |
160 | if ((flags & IFF_UP) == 0 || no_ipaddr) | |
161 | lookforinterfaces = 1; | |
162 | sdl = (struct sockaddr_dl *) (ifm + 1); | |
163 | sdl->sdl_data[sdl->sdl_nlen] = 0; | |
164 | no_ipaddr = 1; | |
165 | continue; | |
166 | } | |
167 | if (ifm->ifm_type != RTM_NEWADDR) | |
168 | quit("ifinit: out of sync"); | |
169 | if ((flags & IFF_UP) == 0) | |
170 | continue; | |
171 | ifam = (struct ifa_msghdr *)ifm; | |
172 | info.rti_addrs = ifam->ifam_addrs; | |
173 | rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info); | |
174 | if (ifaaddr == 0) { | |
175 | syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data); | |
176 | continue; | |
177 | } | |
178 | ifs.int_addr = *ifaaddr; | |
179 | if (ifs.int_addr.sa_family != AF_INET) | |
180 | continue; | |
181 | no_ipaddr = 0; | |
182 | if (ifs.int_flags & IFF_POINTOPOINT) { | |
183 | if (brdaddr == 0) { | |
184 | syslog(LOG_ERR, "%s: (get dstaddr)", | |
185 | sdl->sdl_data); | |
186 | continue; | |
187 | } | |
188 | if (brdaddr->sa_family == AF_UNSPEC) { | |
189 | lookforinterfaces = 1; | |
190 | continue; | |
191 | } | |
192 | ifs.int_dstaddr = *brdaddr; | |
193 | } | |
194 | /* | |
195 | * already known to us? | |
196 | * This allows multiple point-to-point links | |
197 | * to share a source address (possibly with one | |
198 | * other link), but assumes that there will not be | |
199 | * multiple links with the same destination address. | |
200 | */ | |
201 | if (ifs.int_flags & IFF_POINTOPOINT) { | |
202 | if (if_ifwithdstaddr(&ifs.int_dstaddr)) | |
203 | continue; | |
204 | } else if (if_ifwithaddr(&ifs.int_addr)) | |
205 | continue; | |
206 | if (ifs.int_flags & IFF_LOOPBACK) { | |
207 | ifs.int_flags |= IFF_PASSIVE; | |
208 | foundloopback = 1; | |
209 | loopaddr = ifs.int_addr; | |
210 | for (ifp = ifnet; ifp; ifp = ifp->int_next) | |
211 | if (ifp->int_flags & IFF_POINTOPOINT) | |
212 | add_ptopt_localrt(ifp); | |
213 | } | |
214 | if (ifs.int_flags & IFF_BROADCAST) { | |
215 | if (brdaddr == 0) { | |
216 | syslog(LOG_ERR, "%s: (get broadaddr)", | |
217 | sdl->sdl_data); | |
218 | continue; | |
219 | } | |
220 | ifs.int_dstaddr = *brdaddr; | |
221 | } | |
222 | /* | |
223 | * Use a minimum metric of one; | |
224 | * treat the interface metric (default 0) | |
225 | * as an increment to the hop count of one. | |
226 | */ | |
227 | ifs.int_metric = ifam->ifam_metric + 1; | |
228 | if (netmask == 0) { | |
229 | syslog(LOG_ERR, "%s: (get netmask)", | |
230 | sdl->sdl_data); | |
231 | continue; | |
232 | } | |
233 | sin = (struct sockaddr_in *)netmask; | |
234 | ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr); | |
235 | sin = (struct sockaddr_in *)&ifs.int_addr; | |
236 | i = ntohl(sin->sin_addr.s_addr); | |
237 | if (IN_CLASSA(i)) | |
238 | ifs.int_netmask = IN_CLASSA_NET; | |
239 | else if (IN_CLASSB(i)) | |
240 | ifs.int_netmask = IN_CLASSB_NET; | |
241 | else | |
242 | ifs.int_netmask = IN_CLASSC_NET; | |
243 | ifs.int_net = i & ifs.int_netmask; | |
244 | ifs.int_subnet = i & ifs.int_subnetmask; | |
245 | if (ifs.int_subnetmask != ifs.int_netmask) | |
246 | ifs.int_flags |= IFF_SUBNET; | |
247 | ifp = (struct interface *) | |
248 | malloc(sdl->sdl_nlen + 1 + sizeof(ifs)); | |
249 | if (ifp == 0) { | |
250 | printf("routed: out of memory\n"); | |
251 | lookforinterfaces = 1; | |
252 | break; | |
253 | } | |
254 | *ifp = ifs; | |
255 | /* | |
256 | * Count the # of directly connected networks | |
257 | * and point to point links which aren't looped | |
258 | * back to ourself. This is used below to | |
259 | * decide if we should be a routing ``supplier''. | |
260 | */ | |
261 | if ((ifs.int_flags & IFF_LOOPBACK) == 0 && | |
262 | ((ifs.int_flags & IFF_POINTOPOINT) == 0 || | |
263 | if_ifwithaddr(&ifs.int_dstaddr) == 0)) | |
264 | externalinterfaces++; | |
265 | /* | |
266 | * If we have a point-to-point link, we want to act | |
267 | * as a supplier even if it's our only interface, | |
268 | * as that's the only way our peer on the other end | |
269 | * can tell that the link is up. | |
270 | */ | |
271 | if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) | |
272 | supplier = 1; | |
273 | ifp->int_name = (char *)(ifp + 1); | |
274 | strcpy(ifp->int_name, sdl->sdl_data); | |
275 | *ifnext = ifp; | |
276 | ifnext = &ifp->int_next; | |
277 | traceinit(ifp); | |
278 | addrouteforif(ifp); | |
279 | } | |
280 | if (externalinterfaces > 1 && supplier < 0) | |
281 | supplier = 1; | |
282 | free(buf); | |
283 | } | |
284 | ||
285 | /* | |
286 | * Add route for interface if not currently installed. | |
287 | * Create route to other end if a point-to-point link, | |
288 | * otherwise a route to this (sub)network. | |
289 | * INTERNET SPECIFIC. | |
290 | */ | |
291 | addrouteforif(ifp) | |
292 | register struct interface *ifp; | |
293 | { | |
294 | struct sockaddr_in net; | |
295 | struct sockaddr *dst; | |
296 | int state; | |
297 | register struct rt_entry *rt; | |
298 | ||
299 | if (ifp->int_flags & IFF_POINTOPOINT) | |
300 | dst = &ifp->int_dstaddr; | |
301 | else { | |
302 | memset(&net, 0, sizeof (net)); | |
303 | net.sin_family = AF_INET; | |
304 | net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY); | |
305 | dst = (struct sockaddr *)&net; | |
306 | } | |
307 | rt = rtfind(dst); | |
308 | if (rt && | |
309 | (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE) | |
310 | return; | |
311 | if (rt) | |
312 | rtdelete(rt); | |
313 | /* | |
314 | * If interface on subnetted network, | |
315 | * install route to network as well. | |
316 | * This is meant for external viewers. | |
317 | */ | |
318 | if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) { | |
319 | struct in_addr subnet; | |
320 | ||
321 | subnet = net.sin_addr; | |
322 | net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); | |
323 | rt = rtfind(dst); | |
324 | if (rt == 0) | |
325 | rtadd(dst, &ifp->int_addr, ifp->int_metric, | |
326 | ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) | | |
327 | RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET)); | |
328 | else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) == | |
329 | (RTS_INTERNAL|RTS_SUBNET) && | |
330 | ifp->int_metric < rt->rt_metric) | |
331 | rtchange(rt, &rt->rt_router, ifp->int_metric); | |
332 | net.sin_addr = subnet; | |
333 | } | |
334 | if (ifp->int_transitions++ > 0) | |
335 | syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); | |
336 | state = ifp->int_flags & | |
337 | (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET); | |
338 | if (ifp->int_flags & IFF_POINTOPOINT && | |
339 | (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) & | |
340 | ifp->int_netmask) != ifp->int_net) | |
341 | state &= ~RTS_SUBNET; | |
342 | if (ifp->int_flags & IFF_LOOPBACK) | |
343 | state |= RTS_EXTERNAL; | |
344 | rtadd(dst, &ifp->int_addr, ifp->int_metric, state); | |
345 | if (ifp->int_flags & IFF_POINTOPOINT && foundloopback) | |
346 | add_ptopt_localrt(ifp); | |
347 | } | |
348 | ||
349 | /* | |
350 | * Add route to local end of point-to-point using loopback. | |
351 | * If a route to this network is being sent to neighbors on other nets, | |
352 | * mark this route as subnet so we don't have to propagate it too. | |
353 | */ | |
354 | add_ptopt_localrt(ifp) | |
355 | register struct interface *ifp; | |
356 | { | |
357 | struct rt_entry *rt; | |
358 | struct sockaddr *dst; | |
359 | struct sockaddr_in net; | |
360 | int state; | |
361 | ||
362 | state = RTS_INTERFACE | RTS_PASSIVE; | |
363 | ||
364 | /* look for route to logical network */ | |
365 | memset(&net, 0, sizeof (net)); | |
366 | net.sin_family = AF_INET; | |
367 | net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); | |
368 | dst = (struct sockaddr *)&net; | |
369 | rt = rtfind(dst); | |
370 | if (rt && rt->rt_state & RTS_INTERNAL) | |
371 | state |= RTS_SUBNET; | |
372 | ||
373 | dst = &ifp->int_addr; | |
374 | if (rt = rtfind(dst)) { | |
375 | if (rt && rt->rt_state & RTS_INTERFACE) | |
376 | return; | |
377 | rtdelete(rt); | |
378 | } | |
379 | rtadd(dst, &loopaddr, 1, state); | |
380 | } | |
381 | ||
382 | /* | |
383 | * As a concession to the ARPANET we read a list of gateways | |
384 | * from /etc/gateways and add them to our tables. This file | |
385 | * exists at each ARPANET gateway and indicates a set of ``remote'' | |
386 | * gateways (i.e. a gateway which we can't immediately determine | |
387 | * if it's present or not as we can do for those directly connected | |
388 | * at the hardware level). If a gateway is marked ``passive'' | |
389 | * in the file, then we assume it doesn't have a routing process | |
390 | * of our design and simply assume it's always present. Those | |
391 | * not marked passive are treated as if they were directly | |
392 | * connected -- they're added into the interface list so we'll | |
393 | * send them routing updates. | |
394 | * | |
395 | * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP. | |
396 | */ | |
397 | gwkludge() | |
398 | { | |
399 | struct sockaddr_in dst, gate; | |
400 | FILE *fp; | |
401 | char *type, *dname, *gname, *qual, buf[BUFSIZ]; | |
402 | struct interface *ifp; | |
403 | int metric, n; | |
404 | struct rt_entry route; | |
405 | ||
406 | fp = fopen(_PATH_GATEWAYS, "r"); | |
407 | if (fp == NULL) | |
408 | return; | |
409 | qual = buf; | |
410 | dname = buf + 64; | |
411 | gname = buf + ((BUFSIZ - 64) / 3); | |
412 | type = buf + (((BUFSIZ - 64) * 2) / 3); | |
413 | memset(&dst, 0, sizeof (dst)); | |
414 | memset(&gate, 0, sizeof (gate)); | |
415 | memset(&route, 0, sizeof(route)); | |
416 | /* format: {net | host} XX gateway XX metric DD [passive | external]\n */ | |
417 | #define readentry(fp) \ | |
418 | fscanf((fp), "%s %s gateway %s metric %d %s\n", \ | |
419 | type, dname, gname, &metric, qual) | |
420 | for (;;) { | |
421 | if ((n = readentry(fp)) == EOF) | |
422 | break; | |
423 | if (!getnetorhostname(type, dname, &dst)) | |
424 | continue; | |
425 | if (!gethostnameornumber(gname, &gate)) | |
426 | continue; | |
427 | if (metric == 0) /* XXX */ | |
428 | metric = 1; | |
429 | if (strcmp(qual, "passive") == 0) { | |
430 | /* | |
431 | * Passive entries aren't placed in our tables, | |
432 | * only the kernel's, so we don't copy all of the | |
433 | * external routing information within a net. | |
434 | * Internal machines should use the default | |
435 | * route to a suitable gateway (like us). | |
436 | */ | |
437 | route.rt_dst = *(struct sockaddr *) &dst; | |
438 | route.rt_router = *(struct sockaddr *) &gate; | |
439 | route.rt_flags = RTF_UP; | |
440 | if (strcmp(type, "host") == 0) | |
441 | route.rt_flags |= RTF_HOST; | |
442 | if (metric) | |
443 | route.rt_flags |= RTF_GATEWAY; | |
444 | (void) rtioctl(ADD, &route.rt_rt); | |
445 | continue; | |
446 | } | |
447 | if (strcmp(qual, "external") == 0) { | |
448 | /* | |
449 | * Entries marked external are handled | |
450 | * by other means, e.g. EGP, | |
451 | * and are placed in our tables only | |
452 | * to prevent overriding them | |
453 | * with something else. | |
454 | */ | |
455 | rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE); | |
456 | continue; | |
457 | } | |
458 | /* assume no duplicate entries */ | |
459 | externalinterfaces++; | |
460 | ifp = (struct interface *)malloc(sizeof (*ifp)); | |
461 | memset(ifp, 0, sizeof (*ifp)); | |
462 | ifp->int_flags = IFF_REMOTE; | |
463 | /* can't identify broadcast capability */ | |
464 | ifp->int_net = inet_netof(dst.sin_addr); | |
465 | if (strcmp(type, "host") == 0) { | |
466 | ifp->int_flags |= IFF_POINTOPOINT; | |
467 | ifp->int_dstaddr = *((struct sockaddr *)&dst); | |
468 | } | |
469 | ifp->int_addr = *((struct sockaddr *)&gate); | |
470 | ifp->int_metric = metric; | |
471 | ifp->int_next = ifnet; | |
472 | ifnet = ifp; | |
473 | addrouteforif(ifp); | |
474 | } | |
475 | fclose(fp); | |
476 | } | |
477 | ||
478 | getnetorhostname(type, name, sin) | |
479 | char *type, *name; | |
480 | struct sockaddr_in *sin; | |
481 | { | |
482 | ||
483 | if (strcmp(type, "net") == 0) { | |
484 | struct netent *np = getnetbyname(name); | |
485 | int n; | |
486 | ||
487 | if (np == 0) | |
488 | n = inet_network(name); | |
489 | else { | |
490 | if (np->n_addrtype != AF_INET) | |
491 | return (0); | |
492 | n = np->n_net; | |
493 | /* | |
494 | * getnetbyname returns right-adjusted value. | |
495 | */ | |
496 | if (n < 128) | |
497 | n <<= IN_CLASSA_NSHIFT; | |
498 | else if (n < 65536) | |
499 | n <<= IN_CLASSB_NSHIFT; | |
500 | else | |
501 | n <<= IN_CLASSC_NSHIFT; | |
502 | } | |
503 | sin->sin_family = AF_INET; | |
504 | sin->sin_addr = inet_makeaddr(n, INADDR_ANY); | |
505 | return (1); | |
506 | } | |
507 | if (strcmp(type, "host") == 0) { | |
508 | struct hostent *hp = gethostbyname(name); | |
509 | ||
510 | if (hp == 0) | |
511 | sin->sin_addr.s_addr = inet_addr(name); | |
512 | else { | |
513 | if (hp->h_addrtype != AF_INET) | |
514 | return (0); | |
515 | memmove(&sin->sin_addr, hp->h_addr, hp->h_length); | |
516 | } | |
517 | sin->sin_family = AF_INET; | |
518 | return (1); | |
519 | } | |
520 | return (0); | |
521 | } | |
522 | ||
523 | gethostnameornumber(name, sin) | |
524 | char *name; | |
525 | struct sockaddr_in *sin; | |
526 | { | |
527 | struct hostent *hp; | |
528 | ||
529 | hp = gethostbyname(name); | |
530 | if (hp) { | |
531 | memmove(&sin->sin_addr, hp->h_addr, hp->h_length); | |
532 | sin->sin_family = hp->h_addrtype; | |
533 | return (1); | |
534 | } | |
535 | sin->sin_addr.s_addr = inet_addr(name); | |
536 | sin->sin_family = AF_INET; | |
537 | return (sin->sin_addr.s_addr != -1); | |
538 | } |