]>
git.saurik.com Git - apple/network_cmds.git/blob - routed.tproj/startup.c
098fe2a46527611adb2f653019781519913aac8b
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1983, 1988, 1993
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgment:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * @(#)defs.h 8.1 (Berkeley) 6/5/93
60 * Routing Table Management Daemon
63 #include <sys/ioctl.h>
64 #include <sys/sysctl.h>
66 #include <net/if_dl.h>
69 #include "pathnames.h"
71 struct interface
*ifnet
;
72 struct interface
**ifnext
= &ifnet
;
73 int lookforinterfaces
= 1;
74 int externalinterfaces
= 0; /* # of remote and local interfaces */
75 int foundloopback
; /* valid flag for loopaddr */
76 struct sockaddr loopaddr
; /* our address on loopback */
86 (void) fprintf(stderr
, "route: ");
88 (void) fprintf(stderr
, "%s: ", s
);
89 (void) fprintf(stderr
, "%s\n", strerror(sverrno
));
94 struct rt_addrinfo info
;
95 /* Sleazy use of local variables throughout file, warning!!!! */
96 #define netmask info.rti_info[RTAX_NETMASK]
97 #define ifaaddr info.rti_info[RTAX_IFA]
98 #define brdaddr info.rti_info[RTAX_BRD]
101 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
102 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
105 rt_xaddrs(cp
, cplim
, rtinfo
)
106 register caddr_t cp
, cplim
;
107 register struct rt_addrinfo
*rtinfo
;
109 register struct sockaddr
*sa
;
112 memset(rtinfo
->rti_info
, 0, sizeof(rtinfo
->rti_info
));
113 for (i
= 0; (i
< RTAX_MAX
) && (cp
< cplim
); i
++) {
114 if ((rtinfo
->rti_addrs
& (1 << i
)) == 0)
116 rtinfo
->rti_info
[i
] = sa
= (struct sockaddr
*)cp
;
122 * Find the network interfaces which have configured themselves.
123 * If the interface is present but not yet up (for example an
124 * ARPANET IMP), set the lookforinterfaces flag so we'll
125 * come back later and look again.
129 struct interface ifs
, *ifp
;
131 int mib
[6], no_ipaddr
= 0, flags
= 0;
132 char *buf
, *cplim
, *cp
;
133 register struct if_msghdr
*ifm
;
134 register struct ifa_msghdr
*ifam
;
135 struct sockaddr_dl
*sdl
;
136 struct sockaddr_in
*sin
;
143 mib
[4] = NET_RT_IFLIST
;
145 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
146 quit("route-sysctl-estimate");
147 if ((buf
= malloc(needed
)) == NULL
)
149 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0)
150 quit("actual retrieval of interface table");
151 lookforinterfaces
= 0;
152 cplim
= buf
+ needed
;
153 for (cp
= buf
; cp
< cplim
; cp
+= ifm
->ifm_msglen
) {
154 ifm
= (struct if_msghdr
*)cp
;
155 if (ifm
->ifm_type
== RTM_IFINFO
) {
156 memset(&ifs
, 0, sizeof(ifs
));
157 ifs
.int_flags
= flags
= (0xffff & ifm
->ifm_flags
) | IFF_INTERFACE
;
158 if ((flags
& IFF_UP
) == 0 || no_ipaddr
)
159 lookforinterfaces
= 1;
160 sdl
= (struct sockaddr_dl
*) (ifm
+ 1);
161 sdl
->sdl_data
[sdl
->sdl_nlen
] = 0;
165 if (ifm
->ifm_type
!= RTM_NEWADDR
)
166 quit("ifinit: out of sync");
167 if ((flags
& IFF_UP
) == 0)
169 ifam
= (struct ifa_msghdr
*)ifm
;
170 info
.rti_addrs
= ifam
->ifam_addrs
;
171 rt_xaddrs((char *)(ifam
+ 1), cp
+ ifam
->ifam_msglen
, &info
);
173 syslog(LOG_ERR
, "%s: (get addr)", sdl
->sdl_data
);
176 ifs
.int_addr
= *ifaaddr
;
177 if (ifs
.int_addr
.sa_family
!= AF_INET
)
180 if (ifs
.int_flags
& IFF_POINTOPOINT
) {
182 syslog(LOG_ERR
, "%s: (get dstaddr)",
186 if (brdaddr
->sa_family
== AF_UNSPEC
) {
187 lookforinterfaces
= 1;
190 ifs
.int_dstaddr
= *brdaddr
;
193 * already known to us?
194 * This allows multiple point-to-point links
195 * to share a source address (possibly with one
196 * other link), but assumes that there will not be
197 * multiple links with the same destination address.
199 if (ifs
.int_flags
& IFF_POINTOPOINT
) {
200 if (if_ifwithdstaddr(&ifs
.int_dstaddr
))
202 } else if (if_ifwithaddr(&ifs
.int_addr
))
204 if (ifs
.int_flags
& IFF_LOOPBACK
) {
205 ifs
.int_flags
|= IFF_PASSIVE
;
207 loopaddr
= ifs
.int_addr
;
208 for (ifp
= ifnet
; ifp
; ifp
= ifp
->int_next
)
209 if (ifp
->int_flags
& IFF_POINTOPOINT
)
210 add_ptopt_localrt(ifp
);
212 if (ifs
.int_flags
& IFF_BROADCAST
) {
214 syslog(LOG_ERR
, "%s: (get broadaddr)",
218 ifs
.int_dstaddr
= *brdaddr
;
221 * Use a minimum metric of one;
222 * treat the interface metric (default 0)
223 * as an increment to the hop count of one.
225 ifs
.int_metric
= ifam
->ifam_metric
+ 1;
227 syslog(LOG_ERR
, "%s: (get netmask)",
231 sin
= (struct sockaddr_in
*)netmask
;
232 ifs
.int_subnetmask
= ntohl(sin
->sin_addr
.s_addr
);
233 sin
= (struct sockaddr_in
*)&ifs
.int_addr
;
234 i
= ntohl(sin
->sin_addr
.s_addr
);
236 ifs
.int_netmask
= IN_CLASSA_NET
;
237 else if (IN_CLASSB(i
))
238 ifs
.int_netmask
= IN_CLASSB_NET
;
240 ifs
.int_netmask
= IN_CLASSC_NET
;
241 ifs
.int_net
= i
& ifs
.int_netmask
;
242 ifs
.int_subnet
= i
& ifs
.int_subnetmask
;
243 if (ifs
.int_subnetmask
!= ifs
.int_netmask
)
244 ifs
.int_flags
|= IFF_SUBNET
;
245 ifp
= (struct interface
*)
246 malloc(sdl
->sdl_nlen
+ 1 + sizeof(ifs
));
248 printf("routed: out of memory\n");
249 lookforinterfaces
= 1;
254 * Count the # of directly connected networks
255 * and point to point links which aren't looped
256 * back to ourself. This is used below to
257 * decide if we should be a routing ``supplier''.
259 if ((ifs
.int_flags
& IFF_LOOPBACK
) == 0 &&
260 ((ifs
.int_flags
& IFF_POINTOPOINT
) == 0 ||
261 if_ifwithaddr(&ifs
.int_dstaddr
) == 0))
262 externalinterfaces
++;
264 * If we have a point-to-point link, we want to act
265 * as a supplier even if it's our only interface,
266 * as that's the only way our peer on the other end
267 * can tell that the link is up.
269 if ((ifs
.int_flags
& IFF_POINTOPOINT
) && supplier
< 0)
271 ifp
->int_name
= (char *)(ifp
+ 1);
272 strcpy(ifp
->int_name
, sdl
->sdl_data
);
274 ifnext
= &ifp
->int_next
;
278 if (externalinterfaces
> 1 && supplier
< 0)
284 * Add route for interface if not currently installed.
285 * Create route to other end if a point-to-point link,
286 * otherwise a route to this (sub)network.
290 register struct interface
*ifp
;
292 struct sockaddr_in net
;
293 struct sockaddr
*dst
;
295 register struct rt_entry
*rt
;
297 if (ifp
->int_flags
& IFF_POINTOPOINT
)
298 dst
= &ifp
->int_dstaddr
;
300 memset(&net
, 0, sizeof (net
));
301 net
.sin_family
= AF_INET
;
302 net
.sin_addr
= inet_makeaddr(ifp
->int_subnet
, INADDR_ANY
);
303 dst
= (struct sockaddr
*)&net
;
307 (rt
->rt_state
& (RTS_INTERFACE
| RTS_INTERNAL
)) == RTS_INTERFACE
)
312 * If interface on subnetted network,
313 * install route to network as well.
314 * This is meant for external viewers.
316 if ((ifp
->int_flags
& (IFF_SUBNET
|IFF_POINTOPOINT
)) == IFF_SUBNET
) {
317 struct in_addr subnet
;
319 subnet
= net
.sin_addr
;
320 net
.sin_addr
= inet_makeaddr(ifp
->int_net
, INADDR_ANY
);
323 rtadd(dst
, &ifp
->int_addr
, ifp
->int_metric
,
324 ((ifp
->int_flags
& (IFF_INTERFACE
|IFF_REMOTE
)) |
325 RTS_PASSIVE
| RTS_INTERNAL
| RTS_SUBNET
));
326 else if ((rt
->rt_state
& (RTS_INTERNAL
|RTS_SUBNET
)) ==
327 (RTS_INTERNAL
|RTS_SUBNET
) &&
328 ifp
->int_metric
< rt
->rt_metric
)
329 rtchange(rt
, &rt
->rt_router
, ifp
->int_metric
);
330 net
.sin_addr
= subnet
;
332 if (ifp
->int_transitions
++ > 0)
333 syslog(LOG_ERR
, "re-installing interface %s", ifp
->int_name
);
334 state
= ifp
->int_flags
&
335 (IFF_INTERFACE
| IFF_PASSIVE
| IFF_REMOTE
| IFF_SUBNET
);
336 if (ifp
->int_flags
& IFF_POINTOPOINT
&&
337 (ntohl(((struct sockaddr_in
*)&ifp
->int_dstaddr
)->sin_addr
.s_addr
) &
338 ifp
->int_netmask
) != ifp
->int_net
)
339 state
&= ~RTS_SUBNET
;
340 if (ifp
->int_flags
& IFF_LOOPBACK
)
341 state
|= RTS_EXTERNAL
;
342 rtadd(dst
, &ifp
->int_addr
, ifp
->int_metric
, state
);
343 if (ifp
->int_flags
& IFF_POINTOPOINT
&& foundloopback
)
344 add_ptopt_localrt(ifp
);
348 * Add route to local end of point-to-point using loopback.
349 * If a route to this network is being sent to neighbors on other nets,
350 * mark this route as subnet so we don't have to propagate it too.
352 add_ptopt_localrt(ifp
)
353 register struct interface
*ifp
;
356 struct sockaddr
*dst
;
357 struct sockaddr_in net
;
360 state
= RTS_INTERFACE
| RTS_PASSIVE
;
362 /* look for route to logical network */
363 memset(&net
, 0, sizeof (net
));
364 net
.sin_family
= AF_INET
;
365 net
.sin_addr
= inet_makeaddr(ifp
->int_net
, INADDR_ANY
);
366 dst
= (struct sockaddr
*)&net
;
368 if (rt
&& rt
->rt_state
& RTS_INTERNAL
)
371 dst
= &ifp
->int_addr
;
372 if (rt
= rtfind(dst
)) {
373 if (rt
&& rt
->rt_state
& RTS_INTERFACE
)
377 rtadd(dst
, &loopaddr
, 1, state
);
381 * As a concession to the ARPANET we read a list of gateways
382 * from /etc/gateways and add them to our tables. This file
383 * exists at each ARPANET gateway and indicates a set of ``remote''
384 * gateways (i.e. a gateway which we can't immediately determine
385 * if it's present or not as we can do for those directly connected
386 * at the hardware level). If a gateway is marked ``passive''
387 * in the file, then we assume it doesn't have a routing process
388 * of our design and simply assume it's always present. Those
389 * not marked passive are treated as if they were directly
390 * connected -- they're added into the interface list so we'll
391 * send them routing updates.
393 * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP.
397 struct sockaddr_in dst
, gate
;
399 char *type
, *dname
, *gname
, *qual
, buf
[BUFSIZ
];
400 struct interface
*ifp
;
402 struct rt_entry route
;
404 fp
= fopen(_PATH_GATEWAYS
, "r");
409 gname
= buf
+ ((BUFSIZ
- 64) / 3);
410 type
= buf
+ (((BUFSIZ
- 64) * 2) / 3);
411 memset(&dst
, 0, sizeof (dst
));
412 memset(&gate
, 0, sizeof (gate
));
413 memset(&route
, 0, sizeof(route
));
414 /* format: {net | host} XX gateway XX metric DD [passive | external]\n */
415 #define readentry(fp) \
416 fscanf((fp), "%s %s gateway %s metric %d %s\n", \
417 type, dname, gname, &metric, qual)
419 if ((n
= readentry(fp
)) == EOF
)
421 if (!getnetorhostname(type
, dname
, &dst
))
423 if (!gethostnameornumber(gname
, &gate
))
425 if (metric
== 0) /* XXX */
427 if (strcmp(qual
, "passive") == 0) {
429 * Passive entries aren't placed in our tables,
430 * only the kernel's, so we don't copy all of the
431 * external routing information within a net.
432 * Internal machines should use the default
433 * route to a suitable gateway (like us).
435 route
.rt_dst
= *(struct sockaddr
*) &dst
;
436 route
.rt_router
= *(struct sockaddr
*) &gate
;
437 route
.rt_flags
= RTF_UP
;
438 if (strcmp(type
, "host") == 0)
439 route
.rt_flags
|= RTF_HOST
;
441 route
.rt_flags
|= RTF_GATEWAY
;
442 (void) rtioctl(ADD
, &route
.rt_rt
);
445 if (strcmp(qual
, "external") == 0) {
447 * Entries marked external are handled
448 * by other means, e.g. EGP,
449 * and are placed in our tables only
450 * to prevent overriding them
451 * with something else.
453 rtadd(&dst
, &gate
, metric
, RTS_EXTERNAL
|RTS_PASSIVE
);
456 /* assume no duplicate entries */
457 externalinterfaces
++;
458 ifp
= (struct interface
*)malloc(sizeof (*ifp
));
459 memset(ifp
, 0, sizeof (*ifp
));
460 ifp
->int_flags
= IFF_REMOTE
;
461 /* can't identify broadcast capability */
462 ifp
->int_net
= inet_netof(dst
.sin_addr
);
463 if (strcmp(type
, "host") == 0) {
464 ifp
->int_flags
|= IFF_POINTOPOINT
;
465 ifp
->int_dstaddr
= *((struct sockaddr
*)&dst
);
467 ifp
->int_addr
= *((struct sockaddr
*)&gate
);
468 ifp
->int_metric
= metric
;
469 ifp
->int_next
= ifnet
;
476 getnetorhostname(type
, name
, sin
)
478 struct sockaddr_in
*sin
;
481 if (strcmp(type
, "net") == 0) {
482 struct netent
*np
= getnetbyname(name
);
486 n
= inet_network(name
);
488 if (np
->n_addrtype
!= AF_INET
)
492 * getnetbyname returns right-adjusted value.
495 n
<<= IN_CLASSA_NSHIFT
;
497 n
<<= IN_CLASSB_NSHIFT
;
499 n
<<= IN_CLASSC_NSHIFT
;
501 sin
->sin_family
= AF_INET
;
502 sin
->sin_addr
= inet_makeaddr(n
, INADDR_ANY
);
505 if (strcmp(type
, "host") == 0) {
506 struct hostent
*hp
= gethostbyname(name
);
509 sin
->sin_addr
.s_addr
= inet_addr(name
);
511 if (hp
->h_addrtype
!= AF_INET
)
513 memmove(&sin
->sin_addr
, hp
->h_addr
, hp
->h_length
);
515 sin
->sin_family
= AF_INET
;
521 gethostnameornumber(name
, sin
)
523 struct sockaddr_in
*sin
;
527 hp
= gethostbyname(name
);
529 memmove(&sin
->sin_addr
, hp
->h_addr
, hp
->h_length
);
530 sin
->sin_family
= hp
->h_addrtype
;
533 sin
->sin_addr
.s_addr
= inet_addr(name
);
534 sin
->sin_family
= AF_INET
;
535 return (sin
->sin_addr
.s_addr
!= -1);