Commit | Line | Data |
---|---|---|
4a10c08d | 1 | /* |
3565c602 KB |
2 | * Copyright (c) 1985 The Regents of the University of California. |
3 | * All rights reserved. | |
4a10c08d | 4 | * |
3565c602 KB |
5 | * This file includes significant work done at Cornell University by |
6 | * Bill Nesheim. That work included by permission. | |
7 | * | |
8 | * Redistribution and use in source and binary forms are permitted | |
9 | * provided that the above copyright notice and this paragraph are | |
10 | * duplicated in all such forms and that any documentation, | |
11 | * advertising materials, and other materials related to such | |
12 | * distribution and use acknowledge that the software was developed | |
13 | * by the University of California, Berkeley. The name of the | |
14 | * University may not be used to endorse or promote products derived | |
15 | * from this software without specific prior written permission. | |
16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
17 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
18 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
4a10c08d KS |
19 | */ |
20 | ||
5e838d4d | 21 | #ifndef lint |
3565c602 KB |
22 | static char sccsid[] = "@(#)startup.c 5.6 (Berkeley) %G%"; |
23 | #endif /* not lint */ | |
5e838d4d KS |
24 | |
25 | /* | |
26 | * Routing Table Management Daemon | |
27 | */ | |
28 | #include "defs.h" | |
29 | #include <sys/ioctl.h> | |
30 | #include <net/if.h> | |
31 | #include <nlist.h> | |
48681466 | 32 | #include <syslog.h> |
5e838d4d KS |
33 | |
34 | struct interface *ifnet; | |
5e838d4d KS |
35 | int lookforinterfaces = 1; |
36 | int performnlist = 1; | |
84f93e8f | 37 | int gateway = 0; |
5e838d4d | 38 | int externalinterfaces = 0; /* # of remote and local interfaces */ |
5e838d4d KS |
39 | char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
40 | ||
5e838d4d KS |
41 | |
42 | /* | |
48681466 KS |
43 | * Find the network interfaces which have configured themselves. |
44 | * If the interface is present but not yet up (for example an | |
5e838d4d KS |
45 | * ARPANET IMP), set the lookforinterfaces flag so we'll |
46 | * come back later and look again. | |
47 | */ | |
48 | ifinit() | |
49 | { | |
48681466 KS |
50 | struct interface ifs, *ifp; |
51 | int s, n; | |
48681466 | 52 | struct ifconf ifc; |
053f3ae9 | 53 | char buf[(sizeof (struct ifreq ) * 20)]; |
48681466 KS |
54 | struct ifreq ifreq, *ifr; |
55 | u_long i; | |
5e838d4d | 56 | |
48681466 KS |
57 | if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) { |
58 | syslog(LOG_ERR, "socket: %m"); | |
59 | exit(1); | |
5e838d4d | 60 | } |
48681466 KS |
61 | ifc.ifc_len = sizeof (buf); |
62 | ifc.ifc_buf = buf; | |
63 | if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { | |
64 | syslog(LOG_ERR, "ioctl (get interface configuration)"); | |
65 | close(s); | |
66 | return (0); | |
67 | } | |
68 | ifr = ifc.ifc_req; | |
5e838d4d | 69 | lookforinterfaces = 0; |
48681466 KS |
70 | for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) { |
71 | bzero((char *)&ifs, sizeof(ifs)); | |
72 | ifs.int_addr = ifr->ifr_addr; | |
73 | ifreq = *ifr; | |
74 | if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { | |
75 | syslog(LOG_ERR, "ioctl (get interface flags)"); | |
76 | continue; | |
77 | } | |
78 | ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; | |
79 | if ((ifs.int_flags & IFF_UP) == 0 || | |
80 | ifr->ifr_addr.sa_family == AF_UNSPEC) { | |
5e838d4d KS |
81 | lookforinterfaces = 1; |
82 | continue; | |
83 | } | |
48681466 KS |
84 | if (ifs.int_addr.sa_family != AF_NS) |
85 | continue; | |
86 | if (ifs.int_flags & IFF_POINTOPOINT) { | |
87 | if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { | |
053f3ae9 | 88 | syslog(LOG_ERR, "ioctl (get dstaddr): %m"); |
48681466 KS |
89 | continue; |
90 | } | |
91 | ifs.int_dstaddr = ifreq.ifr_dstaddr; | |
92 | } | |
93 | if (ifs.int_flags & IFF_BROADCAST) { | |
94 | if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { | |
053f3ae9 | 95 | syslog(LOG_ERR, "ioctl (get broadaddr: %m"); |
48681466 KS |
96 | continue; |
97 | } | |
98 | ifs.int_broadaddr = ifreq.ifr_broadaddr; | |
5e838d4d | 99 | } |
84f93e8f KS |
100 | /* |
101 | * already known to us? | |
102 | * what makes a POINTOPOINT if unique is its dst addr, | |
103 | * NOT its source address | |
104 | */ | |
105 | if ( ((ifs.int_flags & IFF_POINTOPOINT) && | |
106 | if_ifwithdstaddr(&ifs.int_dstaddr)) || | |
107 | ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && | |
108 | if_ifwithaddr(&ifs.int_addr))) | |
109 | continue; | |
48681466 | 110 | /* no one cares about software loopback interfaces */ |
84f93e8f | 111 | if (strncmp(ifr->ifr_name,"lo", 2)==0) |
48681466 | 112 | continue; |
5e838d4d KS |
113 | ifp = (struct interface *)malloc(sizeof (struct interface)); |
114 | if (ifp == 0) { | |
053f3ae9 | 115 | syslog(LOG_ERR,"XNSrouted: out of memory\n"); |
5e838d4d KS |
116 | break; |
117 | } | |
48681466 | 118 | *ifp = ifs; |
5e838d4d KS |
119 | /* |
120 | * Count the # of directly connected networks | |
121 | * and point to point links which aren't looped | |
122 | * back to ourself. This is used below to | |
123 | * decide if we should be a routing ``supplier''. | |
124 | */ | |
48681466 KS |
125 | if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || |
126 | if_ifwithaddr(&ifs.int_dstaddr) == 0) | |
5e838d4d | 127 | externalinterfaces++; |
84f93e8f KS |
128 | /* |
129 | * If we have a point-to-point link, we want to act | |
130 | * as a supplier even if it's our only interface, | |
131 | * as that's the only way our peer on the other end | |
132 | * can tell that the link is up. | |
133 | */ | |
134 | if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) | |
135 | supplier = 1; | |
48681466 | 136 | ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); |
5e838d4d | 137 | if (ifp->int_name == 0) { |
053f3ae9 | 138 | syslog(LOG_ERR,"XNSrouted: out of memory\n"); |
5e838d4d KS |
139 | goto bad; /* ??? */ |
140 | } | |
48681466 | 141 | strcpy(ifp->int_name, ifr->ifr_name); |
5e838d4d KS |
142 | ifp->int_metric = 0; |
143 | ifp->int_next = ifnet; | |
5e838d4d KS |
144 | ifnet = ifp; |
145 | traceinit(ifp); | |
146 | addrouteforif(ifp); | |
147 | } | |
148 | if (externalinterfaces > 1 && supplier < 0) | |
149 | supplier = 1; | |
48681466 | 150 | close(s); |
5e838d4d KS |
151 | return; |
152 | bad: | |
153 | sleep(60); | |
48681466 | 154 | close(s); |
053f3ae9 | 155 | sleep(60); |
5e838d4d KS |
156 | execv("/etc/XNSrouted", argv0); |
157 | _exit(0177); | |
158 | } | |
159 | ||
160 | addrouteforif(ifp) | |
161 | struct interface *ifp; | |
162 | { | |
48681466 | 163 | struct sockaddr_ns net; |
5e838d4d KS |
164 | struct sockaddr *dst; |
165 | int state, metric; | |
166 | struct rt_entry *rt; | |
167 | ||
4a10c08d KS |
168 | if (ifp->int_flags & IFF_POINTOPOINT) { |
169 | int (*match)(); | |
170 | register struct interface *ifp2 = ifnet; | |
171 | register struct interface *ifprev = ifnet; | |
172 | ||
5e838d4d | 173 | dst = &ifp->int_dstaddr; |
4a10c08d KS |
174 | |
175 | /* Search for interfaces with the same net */ | |
176 | ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); | |
177 | match = afswitch[dst->sa_family].af_netmatch; | |
178 | if (match) | |
179 | for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { | |
180 | if (ifp->int_flags & IFF_POINTOPOINT == 0) | |
181 | continue; | |
182 | if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { | |
183 | insque(&ifp2->int_sq,&ifp->int_sq); | |
184 | break; | |
185 | } | |
186 | } | |
187 | } else { | |
48681466 | 188 | dst = &ifp->int_broadaddr; |
5e838d4d KS |
189 | } |
190 | rt = rtlookup(dst); | |
5e838d4d KS |
191 | if (rt) |
192 | rtdelete(rt); | |
84f93e8f KS |
193 | if (tracing) |
194 | fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); | |
195 | if (ifp->int_transitions++ > 0) | |
196 | syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); | |
48681466 KS |
197 | rtadd(dst, &ifp->int_addr, ifp->int_metric, |
198 | ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); | |
5e838d4d | 199 | } |
84f93e8f | 200 |