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