Commit | Line | Data |
---|---|---|
18916298 RG |
1 | /* |
2 | * Copyright (c) 1985 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
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, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by the University of | |
19 | * California, Berkeley and its contributors. | |
20 | * 4. Neither the name of the University nor the names of its contributors | |
21 | * may be used to endorse or promote products derived from this software | |
22 | * without specific prior written permission. | |
23 | * | |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
35 | */ | |
36 | ||
37 | #ifndef lint | |
38 | static char sccsid[] = "@(#)startup.c 5.11 (Berkeley) 2/26/91"; | |
39 | #endif /* not lint */ | |
40 | ||
41 | /* | |
42 | * Routing Table Management Daemon | |
43 | */ | |
44 | #include "defs.h" | |
45 | #include <sys/ioctl.h> | |
46 | #include <net/if.h> | |
47 | #include <nlist.h> | |
48 | #include <stdlib.h> | |
49 | ||
50 | struct interface *ifnet; | |
51 | int lookforinterfaces = 1; | |
52 | int performnlist = 1; | |
53 | int gateway = 0; | |
54 | int externalinterfaces = 0; /* # of remote and local interfaces */ | |
55 | char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
56 | ||
57 | ||
58 | /* | |
59 | * Find the network interfaces which have configured themselves. | |
60 | * If the interface is present but not yet up (for example an | |
61 | * ARPANET IMP), set the lookforinterfaces flag so we'll | |
62 | * come back later and look again. | |
63 | */ | |
64 | ifinit() | |
65 | { | |
66 | struct interface ifs, *ifp; | |
67 | int s; | |
68 | struct ifconf ifc; | |
69 | char buf[BUFSIZ], *cp, *cplim; | |
70 | struct ifreq ifreq, *ifr; | |
71 | u_long i; | |
72 | ||
73 | if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) { | |
74 | syslog(LOG_ERR, "socket: %m"); | |
75 | exit(1); | |
76 | } | |
77 | ifc.ifc_len = sizeof (buf); | |
78 | ifc.ifc_buf = buf; | |
79 | if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { | |
80 | syslog(LOG_ERR, "ioctl (get interface configuration)"); | |
81 | close(s); | |
82 | exit(1); | |
83 | } | |
84 | ifr = ifc.ifc_req; | |
85 | lookforinterfaces = 0; | |
86 | #ifdef RTM_ADD | |
87 | #define max(a, b) (a > b ? a : b) | |
88 | #define size(p) max((p).sa_len, sizeof(p)) | |
89 | #else | |
90 | #define size(p) (sizeof (p)) | |
91 | #endif | |
92 | cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ | |
93 | for (cp = buf; cp < cplim; | |
94 | cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { | |
95 | ifr = (struct ifreq *)cp; | |
96 | bzero((char *)&ifs, sizeof(ifs)); | |
97 | ifs.int_addr = ifr->ifr_addr; | |
98 | ifreq = *ifr; | |
99 | if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { | |
100 | syslog(LOG_ERR, "ioctl (get interface flags)"); | |
101 | continue; | |
102 | } | |
103 | ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; | |
104 | if ((ifs.int_flags & IFF_UP) == 0 || | |
105 | ifr->ifr_addr.sa_family == AF_UNSPEC) { | |
106 | lookforinterfaces = 1; | |
107 | continue; | |
108 | } | |
109 | if (ifs.int_addr.sa_family != AF_NS) | |
110 | continue; | |
111 | if (ifs.int_flags & IFF_POINTOPOINT) { | |
112 | if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { | |
113 | syslog(LOG_ERR, "ioctl (get dstaddr): %m"); | |
114 | continue; | |
115 | } | |
116 | ifs.int_dstaddr = ifreq.ifr_dstaddr; | |
117 | } | |
118 | if (ifs.int_flags & IFF_BROADCAST) { | |
119 | if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { | |
120 | syslog(LOG_ERR, "ioctl (get broadaddr: %m"); | |
121 | continue; | |
122 | } | |
123 | ifs.int_broadaddr = ifreq.ifr_broadaddr; | |
124 | } | |
125 | /* | |
126 | * already known to us? | |
127 | * what makes a POINTOPOINT if unique is its dst addr, | |
128 | * NOT its source address | |
129 | */ | |
130 | if ( ((ifs.int_flags & IFF_POINTOPOINT) && | |
131 | if_ifwithdstaddr(&ifs.int_dstaddr)) || | |
132 | ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && | |
133 | if_ifwithaddr(&ifs.int_addr))) | |
134 | continue; | |
135 | /* no one cares about software loopback interfaces */ | |
136 | if (strncmp(ifr->ifr_name,"lo", 2)==0) | |
137 | continue; | |
138 | ifp = (struct interface *)malloc(sizeof (struct interface)); | |
139 | if (ifp == 0) { | |
140 | syslog(LOG_ERR,"XNSrouted: out of memory\n"); | |
141 | break; | |
142 | } | |
143 | *ifp = ifs; | |
144 | /* | |
145 | * Count the # of directly connected networks | |
146 | * and point to point links which aren't looped | |
147 | * back to ourself. This is used below to | |
148 | * decide if we should be a routing ``supplier''. | |
149 | */ | |
150 | if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || | |
151 | if_ifwithaddr(&ifs.int_dstaddr) == 0) | |
152 | externalinterfaces++; | |
153 | /* | |
154 | * If we have a point-to-point link, we want to act | |
155 | * as a supplier even if it's our only interface, | |
156 | * as that's the only way our peer on the other end | |
157 | * can tell that the link is up. | |
158 | */ | |
159 | if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) | |
160 | supplier = 1; | |
161 | ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); | |
162 | if (ifp->int_name == 0) { | |
163 | syslog(LOG_ERR,"XNSrouted: out of memory\n"); | |
164 | exit(1); | |
165 | } | |
166 | strcpy(ifp->int_name, ifr->ifr_name); | |
167 | ifp->int_metric = 0; | |
168 | ifp->int_next = ifnet; | |
169 | ifnet = ifp; | |
170 | traceinit(ifp); | |
171 | addrouteforif(ifp); | |
172 | } | |
173 | if (externalinterfaces > 1 && supplier < 0) | |
174 | supplier = 1; | |
175 | close(s); | |
176 | } | |
177 | ||
178 | addrouteforif(ifp) | |
179 | struct interface *ifp; | |
180 | { | |
181 | struct sockaddr_ns net; | |
182 | struct sockaddr *dst; | |
183 | int state, metric; | |
184 | struct rt_entry *rt; | |
185 | ||
186 | if (ifp->int_flags & IFF_POINTOPOINT) { | |
187 | int (*match)(); | |
188 | register struct interface *ifp2 = ifnet; | |
189 | register struct interface *ifprev = ifnet; | |
190 | ||
191 | dst = &ifp->int_dstaddr; | |
192 | ||
193 | /* Search for interfaces with the same net */ | |
194 | ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); | |
195 | match = afswitch[dst->sa_family].af_netmatch; | |
196 | if (match) | |
197 | for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { | |
198 | if (ifp->int_flags & IFF_POINTOPOINT == 0) | |
199 | continue; | |
200 | if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { | |
201 | insque(&ifp2->int_sq,&ifp->int_sq); | |
202 | break; | |
203 | } | |
204 | } | |
205 | } else { | |
206 | dst = &ifp->int_broadaddr; | |
207 | } | |
208 | rt = rtlookup(dst); | |
209 | if (rt) | |
210 | rtdelete(rt); | |
211 | if (tracing) | |
212 | fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); | |
213 | if (ifp->int_transitions++ > 0) | |
214 | syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); | |
215 | rtadd(dst, &ifp->int_addr, ifp->int_metric, | |
216 | ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); | |
217 | } | |
218 |