routed/af.h, version 5.1
[unix-history] / usr / src / sbin / XNSrouted / startup.c
CommitLineData
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
22static 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
34struct interface *ifnet;
5e838d4d
KS
35int lookforinterfaces = 1;
36int performnlist = 1;
84f93e8f 37int gateway = 0;
5e838d4d 38int externalinterfaces = 0; /* # of remote and local interfaces */
5e838d4d
KS
39char 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 */
48ifinit()
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;
152bad:
153 sleep(60);
48681466 154 close(s);
053f3ae9 155 sleep(60);
5e838d4d
KS
156 execv("/etc/XNSrouted", argv0);
157 _exit(0177);
158}
159
160addrouteforif(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