Mercurial > illumos > onarm
annotate usr/src/cmd/cmd-inet/usr.lib/in.ripngd/main.c @ 4:1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Mon, 31 Aug 2009 14:38:03 +0900 |
parents | c9caec207d52 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * CDDL HEADER START | |
3 * | |
4 * The contents of this file are subject to the terms of the | |
5 * Common Development and Distribution License, Version 1.0 only | |
6 * (the "License"). You may not use this file except in compliance | |
7 * with the License. | |
8 * | |
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
10 * or http://www.opensolaris.org/os/licensing. | |
11 * See the License for the specific language governing permissions | |
12 * and limitations under the License. | |
13 * | |
14 * When distributing Covered Code, include this CDDL HEADER in each | |
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
16 * If applicable, add the following below this CDDL HEADER, with the | |
17 * fields enclosed by brackets "[]" replaced with your own identifying | |
18 * information: Portions Copyright [yyyy] [name of copyright owner] | |
19 * | |
20 * CDDL HEADER END | |
21 */ | |
22 /* | |
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. | |
24 * Use is subject to license terms. | |
25 */ | |
26 | |
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ | |
28 /* All Rights Reserved */ | |
29 | |
30 /* | |
31 * Portions of this source code were derived from Berkeley 4.3 BSD | |
32 * under license from the Regents of the University of California. | |
33 */ | |
34 | |
4
1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
Koji Uno <koji.uno@sun.com>
parents:
0
diff
changeset
|
35 #pragma ident "%Z%%M% %I% %E% SMI" |
0 | 36 |
37 #include "defs.h" | |
38 | |
39 struct sockaddr_in6 allrouters; | |
40 char *control; | |
41 boolean_t dopoison = _B_TRUE; /* Do poison reverse */ | |
42 int iocsoc; | |
43 struct timeval lastfullupdate; /* last time full table multicast */ | |
44 struct timeval lastmcast; /* last time all/changes multicast */ | |
45 int max_poll_ifs = START_POLL_SIZE; | |
46 struct rip6 *msg; | |
47 boolean_t needupdate; /* true if need update at nextmcast */ | |
48 struct timeval nextmcast; /* time to wait before changes mcast */ | |
49 struct timeval now; /* current idea of time */ | |
50 char *packet; | |
51 struct pollfd *poll_ifs = NULL; | |
52 int poll_ifs_num = 0; | |
53 int rip6_port; | |
54 boolean_t supplier = _B_TRUE; /* process should supply updates */ | |
55 | |
56 struct in6_addr allrouters_in6 = { | |
57 /* BEGIN CSTYLED */ | |
58 { 0xff, 0x2, 0x0, 0x0, | |
59 0x0, 0x0, 0x0, 0x0, | |
60 0x0, 0x0, 0x0, 0x0, | |
61 0x0, 0x0, 0x0, 0x9 } | |
62 /* END CSTYLED */ | |
63 }; | |
64 | |
65 static void timevalsub(struct timeval *t1, struct timeval *t2); | |
66 | |
67 static void | |
68 usage(char *fname) | |
69 { | |
70 (void) fprintf(stderr, | |
71 "usage: " | |
72 "%s [ -P ] [ -p port ] [ -q ] [ -s ] [ -t ] [ -v ] [<logfile>]\n", | |
73 fname); | |
74 exit(EXIT_FAILURE); | |
75 } | |
76 | |
77 int | |
78 main(int argc, char *argv[]) | |
79 { | |
80 int i, n; | |
81 struct interface *ifp; | |
82 int c; | |
83 struct timeval waittime; | |
84 int timeout; | |
85 boolean_t daemon = _B_TRUE; /* Fork off a detached daemon */ | |
86 FILE *pidfp; | |
87 mode_t pidmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* 0644 */ | |
88 | |
89 rip6_port = htons(IPPORT_ROUTESERVER6); | |
90 allrouters.sin6_family = AF_INET6; | |
91 allrouters.sin6_port = rip6_port; | |
92 allrouters.sin6_addr = allrouters_in6; | |
93 | |
94 while ((c = getopt(argc, argv, "nsqvTtdgPp:")) != EOF) { | |
95 switch (c) { | |
96 case 'n': | |
97 install = _B_FALSE; | |
98 break; | |
99 case 's': | |
100 supplier = _B_TRUE; | |
101 break; | |
102 case 'q': | |
103 supplier = _B_FALSE; | |
104 break; | |
105 case 'v': | |
106 tracing |= ACTION_BIT; | |
107 break; | |
108 case 'T': | |
109 daemon = _B_FALSE; | |
110 break; | |
111 case 't': | |
112 tracepackets = _B_TRUE; | |
113 daemon = _B_FALSE; | |
114 tracing |= (INPUT_BIT | OUTPUT_BIT); | |
115 break; | |
116 case 'd': | |
117 break; | |
118 case 'P': | |
119 dopoison = _B_FALSE; | |
120 break; | |
121 case 'p': | |
122 rip6_port = htons(atoi(optarg)); | |
123 allrouters.sin6_port = rip6_port; | |
124 break; | |
125 default: | |
126 usage(argv[0]); | |
127 /* NOTREACHED */ | |
128 } | |
129 } | |
130 | |
131 /* | |
132 * Any extra argument is considered | |
133 * a tracing log file. | |
134 */ | |
135 if (optind < argc) { | |
136 traceon(argv[optind]); | |
137 } else if (tracing && !daemon) { | |
138 traceonfp(stdout); | |
139 } else if (tracing) { | |
140 (void) fprintf(stderr, "Need logfile with -v\n"); | |
141 usage(argv[0]); | |
142 /* NOTREACHED */ | |
143 } | |
144 | |
145 if (daemon) { | |
146 int t; | |
147 | |
148 if (fork()) | |
149 exit(EXIT_SUCCESS); | |
150 for (t = 0; t < 20; t++) { | |
151 if (!tracing || (t != fileno(ftrace))) | |
152 (void) close(t); | |
153 } | |
154 (void) open("/", 0); | |
155 (void) dup2(0, 1); | |
156 (void) dup2(0, 2); | |
157 (void) setsid(); | |
158 } | |
159 | |
160 /* Store our process id, blow away any existing file if it exists. */ | |
161 if ((pidfp = fopen(PATH_PID, "w")) == NULL) { | |
162 (void) fprintf(stderr, "%s: unable to open " PATH_PID ": %s\n", | |
163 argv[0], strerror(errno)); | |
164 } else { | |
165 (void) fprintf(pidfp, "%ld\n", getpid()); | |
166 (void) fclose(pidfp); | |
167 (void) chmod(PATH_PID, pidmode); | |
168 } | |
169 | |
170 | |
171 iocsoc = socket(AF_INET6, SOCK_DGRAM, 0); | |
172 if (iocsoc < 0) { | |
173 syslog(LOG_ERR, "main: socket: %m"); | |
174 exit(EXIT_FAILURE); | |
175 } | |
176 | |
177 setup_rtsock(); | |
178 | |
179 /* | |
180 * Allocate the buffer to hold the RIPng packet. In reality, it will be | |
181 * smaller than IPV6_MAX_PACKET octets due to (at least) the IPv6 and | |
182 * UDP headers but IPV6_MAX_PACKET is a convenient size. | |
183 */ | |
184 packet = (char *)malloc(IPV6_MAX_PACKET); | |
185 if (packet == NULL) { | |
186 syslog(LOG_ERR, "main: malloc: %m"); | |
187 exit(EXIT_FAILURE); | |
188 } | |
189 msg = (struct rip6 *)packet; | |
190 | |
191 /* | |
192 * Allocate the buffer to hold the ancillary data. This data is used to | |
193 * insure that the incoming hop count of a RIPCMD6_RESPONSE message is | |
194 * IPV6_MAX_HOPS which indicates that it came from a direct neighbor | |
195 * (namely, no intervening router decremented it). | |
196 */ | |
197 control = (char *)malloc(IPV6_MAX_PACKET); | |
198 if (control == NULL) { | |
199 syslog(LOG_ERR, "main: malloc: %m"); | |
200 exit(EXIT_FAILURE); | |
201 } | |
202 | |
203 openlog("in.ripngd", LOG_PID | LOG_CONS, LOG_DAEMON); | |
204 | |
205 (void) gettimeofday(&now, (struct timezone *)NULL); | |
206 | |
207 initifs(); | |
208 solicitall(&allrouters); | |
209 | |
210 if (supplier) | |
211 supplyall(&allrouters, 0, (struct interface *)NULL, _B_TRUE); | |
212 | |
213 (void) sigset(SIGALRM, (void (*)(int))timer); | |
214 (void) sigset(SIGHUP, (void (*)(int))initifs); | |
215 (void) sigset(SIGTERM, (void (*)(int))term); | |
216 (void) sigset(SIGUSR1, (void (*)(int))if_dump); | |
217 (void) sigset(SIGUSR2, (void (*)(int))rtdump); | |
218 | |
219 /* | |
220 * Seed the pseudo-random number generator for GET_RANDOM(). | |
221 */ | |
222 srandom((uint_t)gethostid()); | |
223 | |
224 timer(); | |
225 | |
226 for (;;) { | |
227 if (needupdate) { | |
228 waittime = nextmcast; | |
229 timevalsub(&waittime, &now); | |
230 if (waittime.tv_sec < 0) { | |
231 timeout = 0; | |
232 } else { | |
233 timeout = TIME_TO_MSECS(waittime); | |
234 } | |
235 if (tracing & ACTION_BIT) { | |
236 (void) fprintf(ftrace, | |
237 "poll until dynamic update in %d msec\n", | |
238 timeout); | |
239 (void) fflush(ftrace); | |
240 } | |
241 } else { | |
242 timeout = INFTIM; | |
243 } | |
244 | |
245 if ((n = poll(poll_ifs, poll_ifs_num, timeout)) < 0) { | |
246 if (errno == EINTR) | |
247 continue; | |
248 syslog(LOG_ERR, "main: poll: %m"); | |
249 exit(EXIT_FAILURE); | |
250 } | |
251 (void) sighold(SIGALRM); | |
252 (void) sighold(SIGHUP); | |
253 /* | |
254 * Poll timed out. | |
255 */ | |
256 if (n == 0) { | |
257 if (needupdate) { | |
258 TRACE_ACTION("send delayed dynamic update", | |
259 (struct rt_entry *)NULL); | |
260 (void) gettimeofday(&now, | |
261 (struct timezone *)NULL); | |
262 supplyall(&allrouters, RTS_CHANGED, | |
263 (struct interface *)NULL, _B_TRUE); | |
264 lastmcast = now; | |
265 needupdate = _B_FALSE; | |
266 nextmcast.tv_sec = 0; | |
267 } | |
268 (void) sigrelse(SIGHUP); | |
269 (void) sigrelse(SIGALRM); | |
270 continue; | |
271 } | |
272 (void) gettimeofday(&now, (struct timezone *)NULL); | |
273 for (i = 0; i < poll_ifs_num; i++) { | |
274 /* | |
275 * This case should never happen. | |
276 */ | |
277 if (poll_ifs[i].revents & POLLERR) { | |
278 syslog(LOG_ERR, | |
279 "main: poll returned a POLLERR event"); | |
280 continue; | |
281 } | |
282 if (poll_ifs[i].revents & POLLIN) { | |
283 for (ifp = ifnet; ifp != NULL; | |
284 ifp = ifp->int_next) { | |
285 if (poll_ifs[i].fd == ifp->int_sock) | |
286 in_data(ifp); | |
287 } | |
288 } | |
289 } | |
290 (void) sigrelse(SIGHUP); | |
291 (void) sigrelse(SIGALRM); | |
292 } | |
293 | |
294 return (0); | |
295 } | |
296 | |
297 void | |
298 timevaladd(struct timeval *t1, struct timeval *t2) | |
299 { | |
300 t1->tv_sec += t2->tv_sec; | |
301 if ((t1->tv_usec += t2->tv_usec) > 1000000) { | |
302 t1->tv_sec++; | |
303 t1->tv_usec -= 1000000; | |
304 } | |
305 } | |
306 | |
307 void | |
308 timevalsub(struct timeval *t1, struct timeval *t2) | |
309 { | |
310 t1->tv_sec -= t2->tv_sec; | |
311 if ((t1->tv_usec -= t2->tv_usec) < 0) { | |
312 t1->tv_sec--; | |
313 t1->tv_usec += 1000000; | |
314 } | |
315 } |