Commit | Line | Data |
---|---|---|
fdd0ed12 SL |
1 | #ifndef lint |
2 | static char sccsid[] = "@(#)main.c 4.1 %G%"; | |
3 | #endif | |
4 | ||
5 | /* | |
6 | * Routing Table Management Daemon | |
7 | */ | |
8 | #include "router.h" | |
9 | #include <sys/ioctl.h> | |
10 | #include <net/if.h> | |
11 | #include <errno.h> | |
12 | #include <nlist.h> | |
13 | #include <signal.h> | |
14 | #include <time.h> | |
15 | ||
16 | int supplier = -1; /* process should supply updates */ | |
17 | ||
18 | struct rip *msg = (struct rip *)packet; | |
19 | ||
20 | main(argc, argv) | |
21 | int argc; | |
22 | char *argv[]; | |
23 | { | |
24 | int cc; | |
25 | struct sockaddr from; | |
26 | ||
27 | argv0 = argv; | |
28 | #ifndef DEBUG | |
29 | if (fork()) | |
30 | exit(0); | |
31 | for (cc = 0; cc < 10; cc++) | |
32 | (void) close(cc); | |
33 | (void) open("/", 0); | |
34 | (void) dup2(0, 1); | |
35 | (void) dup2(0, 2); | |
36 | { int t = open("/dev/tty", 2); | |
37 | if (t >= 0) { | |
38 | ioctl(t, TIOCNOTTY, (char *)0); | |
39 | (void) close(t); | |
40 | } | |
41 | } | |
42 | #endif | |
43 | if (tracing) | |
44 | traceon("/etc/routerlog"); | |
45 | ||
46 | /* | |
47 | * We use two sockets. One for which outgoing | |
48 | * packets are routed and for which they're not. | |
49 | * The latter allows us to delete routing table | |
50 | * entries in the kernel for network interfaces | |
51 | * attached to our host which we believe are down | |
52 | * while still polling it to see when/if it comes | |
53 | * back up. With the new ipc interface we'll be | |
54 | * able to specify ``don't route'' as an option | |
55 | * to send, but until then we utilize a second port. | |
56 | */ | |
57 | sp = getservbyname("router", "udp"); | |
58 | if (sp == 0) { | |
59 | fprintf(stderr, "routed: udp/router: unknown service\n"); | |
60 | exit(1); | |
61 | } | |
62 | routingaddr.sin_family = AF_INET; | |
63 | routingaddr.sin_port = htons(sp->s_port); | |
64 | noroutingaddr.sin_family = AF_INET; | |
65 | noroutingaddr.sin_port = htons(sp->s_port + 1); | |
66 | again: | |
67 | s = socket(SOCK_DGRAM, 0, &routingaddr, 0); | |
68 | if (s < 0) { | |
69 | perror("socket"); | |
70 | sleep(30); | |
71 | goto again; | |
72 | } | |
73 | again2: | |
74 | snoroute = socket(SOCK_DGRAM, 0, &noroutingaddr, SO_DONTROUTE); | |
75 | if (snoroute < 0) { | |
76 | perror("socket"); | |
77 | sleep(30); | |
78 | goto again2; | |
79 | } | |
80 | argv++, argc--; | |
81 | while (argc > 0 && **argv == '-') { | |
82 | if (!strcmp(*argv, "-s") == 0) { | |
83 | supplier = 1; | |
84 | argv++, argc--; | |
85 | continue; | |
86 | } | |
87 | if (!strcmp(*argv, "-q") == 0) { | |
88 | supplier = 0; | |
89 | argv++, argc--; | |
90 | continue; | |
91 | } | |
92 | goto usage; | |
93 | } | |
94 | if (argc > 0) { | |
95 | usage: | |
96 | fprintf(stderr, "usage: routed [ -s ] [ -q ]\n"); | |
97 | exit(1); | |
98 | } | |
99 | /* | |
100 | * Collect an initial view of the world by | |
101 | * snooping in the kernel and the gateway kludge | |
102 | * file. Then, send a request packet on all | |
103 | * directly connected networks to find out what | |
104 | * everyone else thinks. | |
105 | */ | |
106 | rtinit(); | |
107 | gwkludge(); | |
108 | ifinit(); | |
109 | if (supplier < 0) | |
110 | supplier = 0; | |
111 | msg->rip_cmd = RIPCMD_REQUEST; | |
112 | msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; | |
113 | msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; | |
114 | toall(sendmsg); | |
115 | sigset(SIGALRM, timer); | |
116 | timer(); | |
117 | ||
118 | #define INFINITY 1000000 | |
119 | for (;;) { | |
120 | int ibits; | |
121 | register int n; | |
122 | ||
123 | ibits = (1 << s) | (1 << snoroute); | |
124 | n = select(32, &ibits, 0, INFINITY); | |
125 | if (n < 0) | |
126 | continue; | |
127 | if (ibits & (1 << s)) | |
128 | process(s); | |
129 | if (ibits & (1 << snoroute)) | |
130 | process(snoroute); | |
131 | } | |
132 | } | |
133 | ||
134 | process(fd) | |
135 | int fd; | |
136 | { | |
137 | register int cc; | |
138 | struct sockaddr from; | |
139 | ||
140 | cc = receive(fd, &from, packet, sizeof (packet)); | |
141 | if (cc <= 0) { | |
142 | if (cc < 0 && errno != EINTR) | |
143 | perror("receive"); | |
144 | return; | |
145 | } | |
146 | sighold(SIGALRM); | |
147 | rip_input(&from, cc); | |
148 | sigrelse(SIGALRM); | |
149 | } |