]>
Commit | Line | Data |
---|---|---|
b7080c8e A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
a2c93a76 A |
6 | * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 1.0 (the 'License'). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
b7080c8e A |
13 | * |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
a2c93a76 A |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License." | |
b7080c8e A |
21 | * |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | /* | |
25 | * Copyright (c) 1983, 1988, 1993 | |
26 | * The Regents of the University of California. All rights reserved. | |
27 | * | |
28 | * Redistribution and use in source and binary forms, with or without | |
29 | * modification, are permitted provided that the following conditions | |
30 | * are met: | |
31 | * 1. Redistributions of source code must retain the above copyright | |
32 | * notice, this list of conditions and the following disclaimer. | |
33 | * 2. Redistributions in binary form must reproduce the above copyright | |
34 | * notice, this list of conditions and the following disclaimer in the | |
35 | * documentation and/or other materials provided with the distribution. | |
36 | * 3. All advertising materials mentioning features or use of this software | |
37 | * must display the following acknowledgment: | |
38 | * This product includes software developed by the University of | |
39 | * California, Berkeley and its contributors. | |
40 | * 4. Neither the name of the University nor the names of its contributors | |
41 | * may be used to endorse or promote products derived from this software | |
42 | * without specific prior written permission. | |
43 | * | |
44 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
45 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
46 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
47 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
48 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
49 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
50 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
51 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
52 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
53 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
54 | * SUCH DAMAGE. | |
55 | * | |
56 | * @(#)defs.h 8.1 (Berkeley) 6/5/93 | |
57 | */ | |
58 | ||
59 | ||
60 | /* | |
61 | * Routing Table Management Daemon | |
62 | */ | |
63 | #include "defs.h" | |
64 | #include <sys/ioctl.h> | |
65 | #include <sys/sysctl.h> | |
66 | #include <net/if.h> | |
67 | #include <net/if_dl.h> | |
68 | #include <syslog.h> | |
69 | #include <stdlib.h> | |
70 | #include "pathnames.h" | |
71 | ||
72 | struct interface *ifnet; | |
73 | struct interface **ifnext = &ifnet; | |
74 | int lookforinterfaces = 1; | |
75 | int externalinterfaces = 0; /* # of remote and local interfaces */ | |
76 | int foundloopback; /* valid flag for loopaddr */ | |
77 | struct sockaddr loopaddr; /* our address on loopback */ | |
78 | ||
79 | ||
80 | void | |
81 | quit(s) | |
82 | char *s; | |
83 | { | |
84 | extern int errno; | |
85 | int sverrno = errno; | |
86 | ||
87 | (void) fprintf(stderr, "route: "); | |
88 | if (s) | |
89 | (void) fprintf(stderr, "%s: ", s); | |
90 | (void) fprintf(stderr, "%s\n", strerror(sverrno)); | |
91 | exit(1); | |
92 | /* NOTREACHED */ | |
93 | } | |
94 | ||
95 | struct rt_addrinfo info; | |
96 | /* Sleazy use of local variables throughout file, warning!!!! */ | |
97 | #define netmask info.rti_info[RTAX_NETMASK] | |
98 | #define ifaaddr info.rti_info[RTAX_IFA] | |
99 | #define brdaddr info.rti_info[RTAX_BRD] | |
100 | ||
101 | #define ROUNDUP(a) \ | |
102 | ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) | |
103 | #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) | |
104 | ||
105 | void | |
106 | rt_xaddrs(cp, cplim, rtinfo) | |
107 | register caddr_t cp, cplim; | |
108 | register struct rt_addrinfo *rtinfo; | |
109 | { | |
110 | register struct sockaddr *sa; | |
111 | register int i; | |
112 | ||
113 | memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); | |
114 | for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { | |
115 | if ((rtinfo->rti_addrs & (1 << i)) == 0) | |
116 | continue; | |
117 | rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; | |
118 | ADVANCE(cp, sa); | |
119 | } | |
120 | } | |
121 | ||
122 | /* | |
123 | * Find the network interfaces which have configured themselves. | |
124 | * If the interface is present but not yet up (for example an | |
125 | * ARPANET IMP), set the lookforinterfaces flag so we'll | |
126 | * come back later and look again. | |
127 | */ | |
b8dff150 | 128 | void |
b7080c8e A |
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; | |
b8dff150 | 137 | struct sockaddr_dl *sdl = NULL; |
b7080c8e A |
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 | */ | |
b8dff150 | 291 | void |
b7080c8e A |
292 | addrouteforif(ifp) |
293 | register struct interface *ifp; | |
294 | { | |
295 | struct sockaddr_in net; | |
296 | struct sockaddr *dst; | |
297 | int state; | |
298 | register struct rt_entry *rt; | |
299 | ||
300 | if (ifp->int_flags & IFF_POINTOPOINT) | |
301 | dst = &ifp->int_dstaddr; | |
302 | else { | |
303 | memset(&net, 0, sizeof (net)); | |
304 | net.sin_family = AF_INET; | |
305 | net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY); | |
306 | dst = (struct sockaddr *)&net; | |
307 | } | |
308 | rt = rtfind(dst); | |
309 | if (rt && | |
310 | (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE) | |
311 | return; | |
312 | if (rt) | |
313 | rtdelete(rt); | |
314 | /* | |
315 | * If interface on subnetted network, | |
316 | * install route to network as well. | |
317 | * This is meant for external viewers. | |
318 | */ | |
319 | if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) { | |
320 | struct in_addr subnet; | |
321 | ||
322 | subnet = net.sin_addr; | |
323 | net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); | |
324 | rt = rtfind(dst); | |
325 | if (rt == 0) | |
326 | rtadd(dst, &ifp->int_addr, ifp->int_metric, | |
327 | ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) | | |
328 | RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET)); | |
329 | else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) == | |
330 | (RTS_INTERNAL|RTS_SUBNET) && | |
331 | ifp->int_metric < rt->rt_metric) | |
332 | rtchange(rt, &rt->rt_router, ifp->int_metric); | |
333 | net.sin_addr = subnet; | |
334 | } | |
335 | if (ifp->int_transitions++ > 0) | |
336 | syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); | |
337 | state = ifp->int_flags & | |
338 | (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET); | |
339 | if (ifp->int_flags & IFF_POINTOPOINT && | |
340 | (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) & | |
341 | ifp->int_netmask) != ifp->int_net) | |
342 | state &= ~RTS_SUBNET; | |
343 | if (ifp->int_flags & IFF_LOOPBACK) | |
344 | state |= RTS_EXTERNAL; | |
345 | rtadd(dst, &ifp->int_addr, ifp->int_metric, state); | |
346 | if (ifp->int_flags & IFF_POINTOPOINT && foundloopback) | |
347 | add_ptopt_localrt(ifp); | |
348 | } | |
349 | ||
350 | /* | |
351 | * Add route to local end of point-to-point using loopback. | |
352 | * If a route to this network is being sent to neighbors on other nets, | |
353 | * mark this route as subnet so we don't have to propagate it too. | |
354 | */ | |
b8dff150 | 355 | void |
b7080c8e A |
356 | add_ptopt_localrt(ifp) |
357 | register struct interface *ifp; | |
358 | { | |
359 | struct rt_entry *rt; | |
360 | struct sockaddr *dst; | |
361 | struct sockaddr_in net; | |
362 | int state; | |
363 | ||
364 | state = RTS_INTERFACE | RTS_PASSIVE; | |
365 | ||
366 | /* look for route to logical network */ | |
367 | memset(&net, 0, sizeof (net)); | |
368 | net.sin_family = AF_INET; | |
369 | net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); | |
370 | dst = (struct sockaddr *)&net; | |
371 | rt = rtfind(dst); | |
372 | if (rt && rt->rt_state & RTS_INTERNAL) | |
373 | state |= RTS_SUBNET; | |
374 | ||
375 | dst = &ifp->int_addr; | |
376 | if (rt = rtfind(dst)) { | |
377 | if (rt && rt->rt_state & RTS_INTERFACE) | |
378 | return; | |
379 | rtdelete(rt); | |
380 | } | |
381 | rtadd(dst, &loopaddr, 1, state); | |
382 | } | |
383 | ||
384 | /* | |
385 | * As a concession to the ARPANET we read a list of gateways | |
386 | * from /etc/gateways and add them to our tables. This file | |
387 | * exists at each ARPANET gateway and indicates a set of ``remote'' | |
388 | * gateways (i.e. a gateway which we can't immediately determine | |
389 | * if it's present or not as we can do for those directly connected | |
390 | * at the hardware level). If a gateway is marked ``passive'' | |
391 | * in the file, then we assume it doesn't have a routing process | |
392 | * of our design and simply assume it's always present. Those | |
393 | * not marked passive are treated as if they were directly | |
394 | * connected -- they're added into the interface list so we'll | |
395 | * send them routing updates. | |
396 | * | |
397 | * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP. | |
398 | */ | |
b8dff150 | 399 | void |
b7080c8e A |
400 | gwkludge() |
401 | { | |
402 | struct sockaddr_in dst, gate; | |
403 | FILE *fp; | |
404 | char *type, *dname, *gname, *qual, buf[BUFSIZ]; | |
405 | struct interface *ifp; | |
406 | int metric, n; | |
407 | struct rt_entry route; | |
408 | ||
409 | fp = fopen(_PATH_GATEWAYS, "r"); | |
410 | if (fp == NULL) | |
411 | return; | |
412 | qual = buf; | |
413 | dname = buf + 64; | |
414 | gname = buf + ((BUFSIZ - 64) / 3); | |
415 | type = buf + (((BUFSIZ - 64) * 2) / 3); | |
416 | memset(&dst, 0, sizeof (dst)); | |
417 | memset(&gate, 0, sizeof (gate)); | |
418 | memset(&route, 0, sizeof(route)); | |
419 | /* format: {net | host} XX gateway XX metric DD [passive | external]\n */ | |
420 | #define readentry(fp) \ | |
421 | fscanf((fp), "%s %s gateway %s metric %d %s\n", \ | |
422 | type, dname, gname, &metric, qual) | |
423 | for (;;) { | |
424 | if ((n = readentry(fp)) == EOF) | |
425 | break; | |
426 | if (!getnetorhostname(type, dname, &dst)) | |
427 | continue; | |
428 | if (!gethostnameornumber(gname, &gate)) | |
429 | continue; | |
430 | if (metric == 0) /* XXX */ | |
431 | metric = 1; | |
432 | if (strcmp(qual, "passive") == 0) { | |
433 | /* | |
434 | * Passive entries aren't placed in our tables, | |
435 | * only the kernel's, so we don't copy all of the | |
436 | * external routing information within a net. | |
437 | * Internal machines should use the default | |
438 | * route to a suitable gateway (like us). | |
439 | */ | |
440 | route.rt_dst = *(struct sockaddr *) &dst; | |
441 | route.rt_router = *(struct sockaddr *) &gate; | |
442 | route.rt_flags = RTF_UP; | |
443 | if (strcmp(type, "host") == 0) | |
444 | route.rt_flags |= RTF_HOST; | |
445 | if (metric) | |
446 | route.rt_flags |= RTF_GATEWAY; | |
447 | (void) rtioctl(ADD, &route.rt_rt); | |
448 | continue; | |
449 | } | |
450 | if (strcmp(qual, "external") == 0) { | |
451 | /* | |
452 | * Entries marked external are handled | |
453 | * by other means, e.g. EGP, | |
454 | * and are placed in our tables only | |
455 | * to prevent overriding them | |
456 | * with something else. | |
457 | */ | |
b8dff150 | 458 | rtadd((struct sockaddr *)&dst, (struct sockaddr *)&gate, metric, RTS_EXTERNAL|RTS_PASSIVE); |
b7080c8e A |
459 | continue; |
460 | } | |
461 | /* assume no duplicate entries */ | |
462 | externalinterfaces++; | |
463 | ifp = (struct interface *)malloc(sizeof (*ifp)); | |
464 | memset(ifp, 0, sizeof (*ifp)); | |
465 | ifp->int_flags = IFF_REMOTE; | |
466 | /* can't identify broadcast capability */ | |
467 | ifp->int_net = inet_netof(dst.sin_addr); | |
468 | if (strcmp(type, "host") == 0) { | |
469 | ifp->int_flags |= IFF_POINTOPOINT; | |
470 | ifp->int_dstaddr = *((struct sockaddr *)&dst); | |
471 | } | |
472 | ifp->int_addr = *((struct sockaddr *)&gate); | |
473 | ifp->int_metric = metric; | |
474 | ifp->int_next = ifnet; | |
475 | ifnet = ifp; | |
476 | addrouteforif(ifp); | |
477 | } | |
478 | fclose(fp); | |
479 | } | |
480 | ||
b8dff150 | 481 | int |
b7080c8e A |
482 | getnetorhostname(type, name, sin) |
483 | char *type, *name; | |
484 | struct sockaddr_in *sin; | |
485 | { | |
486 | ||
487 | if (strcmp(type, "net") == 0) { | |
488 | struct netent *np = getnetbyname(name); | |
489 | int n; | |
490 | ||
491 | if (np == 0) | |
492 | n = inet_network(name); | |
493 | else { | |
494 | if (np->n_addrtype != AF_INET) | |
495 | return (0); | |
496 | n = np->n_net; | |
497 | /* | |
498 | * getnetbyname returns right-adjusted value. | |
499 | */ | |
500 | if (n < 128) | |
501 | n <<= IN_CLASSA_NSHIFT; | |
502 | else if (n < 65536) | |
503 | n <<= IN_CLASSB_NSHIFT; | |
504 | else | |
505 | n <<= IN_CLASSC_NSHIFT; | |
506 | } | |
507 | sin->sin_family = AF_INET; | |
508 | sin->sin_addr = inet_makeaddr(n, INADDR_ANY); | |
509 | return (1); | |
510 | } | |
511 | if (strcmp(type, "host") == 0) { | |
512 | struct hostent *hp = gethostbyname(name); | |
513 | ||
514 | if (hp == 0) | |
515 | sin->sin_addr.s_addr = inet_addr(name); | |
516 | else { | |
517 | if (hp->h_addrtype != AF_INET) | |
518 | return (0); | |
519 | memmove(&sin->sin_addr, hp->h_addr, hp->h_length); | |
520 | } | |
521 | sin->sin_family = AF_INET; | |
522 | return (1); | |
523 | } | |
524 | return (0); | |
525 | } | |
526 | ||
b8dff150 | 527 | int |
b7080c8e A |
528 | gethostnameornumber(name, sin) |
529 | char *name; | |
530 | struct sockaddr_in *sin; | |
531 | { | |
532 | struct hostent *hp; | |
533 | ||
534 | hp = gethostbyname(name); | |
535 | if (hp) { | |
536 | memmove(&sin->sin_addr, hp->h_addr, hp->h_length); | |
537 | sin->sin_family = hp->h_addrtype; | |
538 | return (1); | |
539 | } | |
540 | sin->sin_addr.s_addr = inet_addr(name); | |
541 | sin->sin_family = AF_INET; | |
542 | return (sin->sin_addr.s_addr != -1); | |
543 | } |