Commit | Line | Data |
---|---|---|
5ff67f98 | 1 | /* |
7b3729cc | 2 | * Copyright (c) 1983, 1989 The Regents of the University of California. |
fca7493d KB |
3 | * All rights reserved. |
4 | * | |
70ab3c27 | 5 | * %sccs.include.redist.c% |
5ff67f98 DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
9 | char copyright[] = | |
7d5f817b | 10 | "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ |
5ff67f98 | 11 | All rights reserved.\n"; |
fca7493d | 12 | #endif /* not lint */ |
5ff67f98 | 13 | |
4bec325f | 14 | #ifndef lint |
ac62fbdc | 15 | static char sccsid[] = "@(#)route.c 5.29 (Berkeley) %G%"; |
fca7493d | 16 | #endif /* not lint */ |
4bec325f | 17 | |
a2280e64 | 18 | #include <sys/param.h> |
4bec325f BJ |
19 | #include <sys/socket.h> |
20 | #include <sys/ioctl.h> | |
5c7868a2 | 21 | #include <sys/file.h> |
63c817da | 22 | #include <sys/mbuf.h> |
9eb5d442 | 23 | #include <sys/kinfo.h> |
94a2d2a7 | 24 | |
4bec325f | 25 | #include <net/route.h> |
31bd2db6 | 26 | #include <net/if_dl.h> |
94a2d2a7 | 27 | #include <netinet/in.h> |
eac76d14 | 28 | #include <netns/ns.h> |
7d5f817b | 29 | #include <netiso/iso.h> |
94a2d2a7 | 30 | |
5c7868a2 | 31 | #include <netdb.h> |
94a2d2a7 | 32 | #include <stdio.h> |
4bec325f BJ |
33 | #include <errno.h> |
34 | #include <ctype.h> | |
505837c5 | 35 | #include <paths.h> |
4bec325f | 36 | |
31bd2db6 KS |
37 | struct keytab { |
38 | char *kt_cp; | |
39 | int kt_i; | |
40 | } keywords[] = { | |
41 | #include "keywords.h" | |
42 | {0, 0} | |
43 | }; | |
44 | ||
57cacc90 | 45 | struct ortentry route; |
31bd2db6 | 46 | union sockunion { |
7d5f817b KS |
47 | struct sockaddr sa; |
48 | struct sockaddr_in sin; | |
49 | struct sockaddr_ns sns; | |
50 | struct sockaddr_iso siso; | |
31bd2db6 KS |
51 | struct sockaddr_dl sdl; |
52 | } so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp, *so_addrs[] = | |
ac62fbdc | 53 | { &so_dst, &so_gate, &so_mask, &so_genmask, &so_ifp, &so_ifa, 0}; |
31bd2db6 KS |
54 | typedef union sockunion *sup; |
55 | int pid, rtm_addrs; | |
4bec325f | 56 | int s; |
31bd2db6 | 57 | int forcehost, forcenet, doflush, nflag, af, qflag, Cflag, keyword(); |
eb03b231 | 58 | int iflag, verbose, aflen = sizeof (struct sockaddr_in); |
7cd60aa5 | 59 | int locking, lockrest, debugonly; |
b268b889 | 60 | struct sockaddr_in sin = { sizeof(sin), AF_INET }; |
7cd60aa5 | 61 | struct rt_metrics rt_metrics; |
7d8dd943 | 62 | u_long rtm_inits; |
379dcc38 | 63 | struct in_addr inet_makeaddr(); |
31bd2db6 KS |
64 | char *malloc(), *routename(), *netname(); |
65 | extern char *iso_ntoa(), *link_ntoa(); | |
4bec325f | 66 | |
31bd2db6 KS |
67 | usage(cp) |
68 | char *cp; | |
69 | { | |
70 | fprintf(stderr, | |
71 | "usage: route [ -nqCv ] cmd [[ -<qualifers> ] args ]\n"); | |
72 | if (cp) fprintf(stderr, "(botched keyword: %s)\n", cp); | |
73 | ||
74 | exit(1); | |
75 | } | |
7d8dd943 | 76 | |
4bec325f BJ |
77 | main(argc, argv) |
78 | int argc; | |
79 | char *argv[]; | |
80 | { | |
81 | ||
b268b889 | 82 | char *argvp; |
4bec325f | 83 | if (argc < 2) |
31bd2db6 | 84 | usage((char *)0); |
4bec325f | 85 | argc--, argv++; |
b3933da8 | 86 | for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { |
b268b889 | 87 | for (argvp = argv[0]++; *argvp; argvp++) |
b3933da8 | 88 | switch (*argv[0]) { |
b3933da8 | 89 | case 'n': |
a2280e64 | 90 | nflag++; |
b3933da8 | 91 | break; |
ae578a19 KS |
92 | case 'q': |
93 | qflag++; | |
94 | break; | |
5c7868a2 KS |
95 | case 'C': |
96 | Cflag++; /* Use old ioctls */ | |
57cacc90 | 97 | break; |
7d5f817b KS |
98 | case 'v': |
99 | verbose++; | |
b3933da8 MK |
100 | } |
101 | } | |
5c7868a2 KS |
102 | pid = getpid(); |
103 | if (Cflag) | |
57cacc90 | 104 | s = socket(AF_INET, SOCK_RAW, 0); |
5c7868a2 KS |
105 | else |
106 | s = socket(PF_ROUTE, SOCK_RAW, 0); | |
57cacc90 KS |
107 | if (s < 0) { |
108 | perror("route: socket"); | |
109 | exit(1); | |
110 | } | |
31bd2db6 | 111 | if (argc > 0) switch (keyword(*argv)) { |
ac62fbdc | 112 | case K_GET: |
31bd2db6 KS |
113 | case K_ADD: |
114 | case K_CHANGE: | |
115 | case K_DELETE: | |
63c817da | 116 | newroute(argc, argv); |
31bd2db6 | 117 | case K_MONITOR: |
5c7868a2 | 118 | monitor(); |
31bd2db6 KS |
119 | case K_FLUSH: |
120 | flushroutes(argc, argv); | |
121 | } | |
122 | usage(*argv); | |
63c817da SL |
123 | } |
124 | ||
125 | /* | |
126 | * Purge all entries in the routing tables not | |
127 | * associated with network interfaces. | |
128 | */ | |
31bd2db6 KS |
129 | flushroutes(argc, argv) |
130 | char *argv[]; | |
b268b889 | 131 | { |
9eb5d442 KS |
132 | int bufsize, needed, seqno, rlen; |
133 | char *buf, *next, *lim; | |
134 | register struct rt_msghdr *rtm; | |
9eb5d442 | 135 | |
104e26d6 | 136 | shutdown(s, 0); /* Don't want to read back our messages */ |
31bd2db6 KS |
137 | if (argc > 1) { |
138 | argv++; | |
eb03b231 KS |
139 | if (argc == 2 && **argv == '-') switch (keyword(1 + *argv)) { |
140 | case K_INET: af = AF_INET; break; | |
141 | case K_XNS: af = AF_NS; break; | |
142 | case K_LINK: af = AF_LINK; break; | |
143 | case K_ISO: case K_OSI: af = AF_ISO; break; | |
31bd2db6 KS |
144 | default: goto bad; |
145 | } else | |
146 | bad: usage(*argv); | |
147 | } | |
9eb5d442 KS |
148 | if ((needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0)) < 0) |
149 | { perror("route-getkerninfo-estimate"); exit(1);} | |
150 | if ((buf = malloc(needed)) == 0) | |
151 | { printf("out of space\n");; exit(1);} | |
152 | if ((rlen = getkerninfo(KINFO_RT_DUMP, buf, &needed, 0)) < 0) | |
153 | { perror("actual retrieval of routing table"); exit(1);} | |
154 | lim = buf + rlen; | |
155 | for (next = buf; next < lim; next += rtm->rtm_msglen) { | |
156 | rtm = (struct rt_msghdr *)next; | |
eb03b231 | 157 | if ((rtm->rtm_flags & RTF_GATEWAY) == 0) |
9eb5d442 | 158 | continue; |
31bd2db6 KS |
159 | if (af) { |
160 | struct sockaddr *sa = (struct sockaddr *)(rtm + 1); | |
161 | if (sa->sa_family != af) | |
162 | continue; | |
163 | } | |
9eb5d442 KS |
164 | rtm->rtm_type = RTM_DELETE; |
165 | rtm->rtm_seq = seqno; | |
ac62fbdc KS |
166 | rlen = write(s, next, rtm->rtm_msglen); |
167 | if (rlen < (int)rtm->rtm_msglen) { | |
9eb5d442 KS |
168 | perror("writing to routing socket"); |
169 | printf("got only %d for rlen\n", rlen); | |
31bd2db6 | 170 | break; |
b268b889 | 171 | } |
9eb5d442 KS |
172 | seqno++; |
173 | if (qflag) | |
174 | continue; | |
175 | if (verbose) { | |
31bd2db6 | 176 | print_rtmsg(rtm, rlen); |
9eb5d442 | 177 | } else { |
039256d2 | 178 | struct sockaddr *sa = (struct sockaddr *)(rtm + 1); |
9eb5d442 KS |
179 | printf("%-20.20s ", (rtm->rtm_flags & RTF_HOST) ? |
180 | routename(sa) : netname(sa)); | |
181 | sa = (struct sockaddr *)(sa->sa_len + (char *)sa); | |
182 | printf("%-20.20s ", routename(sa)); | |
183 | printf("done\n"); | |
57cacc90 KS |
184 | } |
185 | } | |
31bd2db6 | 186 | exit(0); |
57cacc90 | 187 | } |
9eb5d442 | 188 | |
63c817da | 189 | char * |
eac76d14 MK |
190 | routename(sa) |
191 | struct sockaddr *sa; | |
63c817da | 192 | { |
a2280e64 | 193 | register char *cp; |
63c817da | 194 | static char line[50]; |
6edb1941 | 195 | struct hostent *hp; |
a2280e64 MK |
196 | static char domain[MAXHOSTNAMELEN + 1]; |
197 | static int first = 1; | |
198 | char *index(); | |
eac76d14 | 199 | char *ns_print(); |
63c817da | 200 | |
a2280e64 MK |
201 | if (first) { |
202 | first = 0; | |
203 | if (gethostname(domain, MAXHOSTNAMELEN) == 0 && | |
204 | (cp = index(domain, '.'))) | |
205 | (void) strcpy(domain, cp + 1); | |
206 | else | |
207 | domain[0] = 0; | |
208 | } | |
eac76d14 MK |
209 | switch (sa->sa_family) { |
210 | ||
211 | case AF_INET: | |
212 | { struct in_addr in; | |
213 | in = ((struct sockaddr_in *)sa)->sin_addr; | |
214 | ||
215 | cp = 0; | |
216 | if (in.s_addr == INADDR_ANY) | |
217 | cp = "default"; | |
218 | if (cp == 0 && !nflag) { | |
219 | hp = gethostbyaddr(&in, sizeof (struct in_addr), | |
220 | AF_INET); | |
221 | if (hp) { | |
222 | if ((cp = index(hp->h_name, '.')) && | |
223 | !strcmp(cp + 1, domain)) | |
224 | *cp = 0; | |
225 | cp = hp->h_name; | |
226 | } | |
a2280e64 | 227 | } |
eac76d14 MK |
228 | if (cp) |
229 | strcpy(line, cp); | |
230 | else { | |
a2280e64 | 231 | #define C(x) ((x) & 0xff) |
eac76d14 | 232 | in.s_addr = ntohl(in.s_addr); |
9bd38ba8 | 233 | (void)sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), |
eac76d14 MK |
234 | C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); |
235 | } | |
236 | break; | |
237 | } | |
238 | ||
239 | case AF_NS: | |
240 | return (ns_print((struct sockaddr_ns *)sa)); | |
241 | ||
31bd2db6 KS |
242 | case AF_LINK: |
243 | return (link_ntoa((struct sockaddr_dl *)sa)); | |
244 | ||
245 | case AF_ISO: | |
246 | (void) sprintf(line, "iso %s", | |
247 | iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr)); | |
248 | break; | |
249 | ||
eac76d14 MK |
250 | default: |
251 | { u_short *s = (u_short *)sa->sa_data; | |
31bd2db6 KS |
252 | u_short *slim = s + ((sa->sa_len + 1)>>1); |
253 | char *cp = line + sprintf(line, "(%d)", sa->sa_family); | |
254 | int n; | |
eac76d14 | 255 | |
31bd2db6 KS |
256 | while (s < slim) { |
257 | n = sprintf(cp, " %x", *s); | |
258 | s++; cp += n; | |
259 | } | |
eac76d14 MK |
260 | break; |
261 | } | |
a2280e64 MK |
262 | } |
263 | return (line); | |
264 | } | |
265 | ||
266 | /* | |
267 | * Return the name of the network whose address is given. | |
268 | * The address is assumed to be that of a net or subnet, not a host. | |
269 | */ | |
270 | char * | |
eac76d14 MK |
271 | netname(sa) |
272 | struct sockaddr *sa; | |
a2280e64 MK |
273 | { |
274 | char *cp = 0; | |
275 | static char line[50]; | |
276 | struct netent *np = 0; | |
277 | u_long net, mask; | |
e2fe1192 | 278 | register u_long i; |
a2280e64 | 279 | int subnetshift; |
a48a48cc | 280 | char *ns_print(); |
a2280e64 | 281 | |
eac76d14 MK |
282 | switch (sa->sa_family) { |
283 | ||
284 | case AF_INET: | |
285 | { struct in_addr in; | |
286 | in = ((struct sockaddr_in *)sa)->sin_addr; | |
287 | ||
e2fe1192 | 288 | i = in.s_addr = ntohl(in.s_addr); |
eac76d14 MK |
289 | if (in.s_addr == 0) |
290 | cp = "default"; | |
291 | else if (!nflag) { | |
292 | if (IN_CLASSA(i)) { | |
293 | mask = IN_CLASSA_NET; | |
294 | subnetshift = 8; | |
295 | } else if (IN_CLASSB(i)) { | |
296 | mask = IN_CLASSB_NET; | |
297 | subnetshift = 8; | |
298 | } else { | |
299 | mask = IN_CLASSC_NET; | |
300 | subnetshift = 4; | |
301 | } | |
302 | /* | |
303 | * If there are more bits than the standard mask | |
304 | * would suggest, subnets must be in use. | |
305 | * Guess at the subnet mask, assuming reasonable | |
306 | * width subnet fields. | |
307 | */ | |
308 | while (in.s_addr &~ mask) | |
309 | mask = (long)mask >> subnetshift; | |
310 | net = in.s_addr & mask; | |
311 | while ((mask & 1) == 0) | |
312 | mask >>= 1, net >>= 1; | |
313 | np = getnetbyaddr(net, AF_INET); | |
314 | if (np) | |
315 | cp = np->n_name; | |
a2280e64 | 316 | } |
eac76d14 MK |
317 | if (cp) |
318 | strcpy(line, cp); | |
319 | else if ((in.s_addr & 0xffffff) == 0) | |
9bd38ba8 | 320 | (void)sprintf(line, "%u", C(in.s_addr >> 24)); |
eac76d14 | 321 | else if ((in.s_addr & 0xffff) == 0) |
9bd38ba8 | 322 | (void)sprintf(line, "%u.%u", C(in.s_addr >> 24), |
eac76d14 MK |
323 | C(in.s_addr >> 16)); |
324 | else if ((in.s_addr & 0xff) == 0) | |
9bd38ba8 | 325 | (void)sprintf(line, "%u.%u.%u", C(in.s_addr >> 24), |
eac76d14 MK |
326 | C(in.s_addr >> 16), C(in.s_addr >> 8)); |
327 | else | |
9bd38ba8 | 328 | (void)sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), |
eac76d14 MK |
329 | C(in.s_addr >> 16), C(in.s_addr >> 8), |
330 | C(in.s_addr)); | |
331 | break; | |
332 | } | |
333 | ||
334 | case AF_NS: | |
335 | return (ns_print((struct sockaddr_ns *)sa)); | |
336 | break; | |
337 | ||
31bd2db6 KS |
338 | case AF_LINK: |
339 | return (link_ntoa((struct sockaddr_dl *)sa)); | |
340 | ||
341 | case AF_ISO: | |
342 | (void) sprintf(line, "iso %s", | |
343 | iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr)); | |
344 | break; | |
345 | ||
eac76d14 MK |
346 | default: |
347 | { u_short *s = (u_short *)sa->sa_data; | |
31bd2db6 KS |
348 | u_short *slim = s + ((sa->sa_len + 1)>>1); |
349 | char *cp = line + sprintf(line, "af %d:", sa->sa_family); | |
350 | int n; | |
eac76d14 | 351 | |
31bd2db6 KS |
352 | while (s < slim) { |
353 | n = sprintf(cp, " %x", *s); | |
354 | s++; cp += n; | |
355 | } | |
eac76d14 MK |
356 | break; |
357 | } | |
63c817da SL |
358 | } |
359 | return (line); | |
4bec325f BJ |
360 | } |
361 | ||
7cd60aa5 KS |
362 | set_metric(value, key) |
363 | char *value; | |
364 | { | |
365 | int flag = 0; | |
366 | u_long noval, *valp = &noval; | |
367 | ||
368 | switch (key) { | |
369 | #define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break | |
370 | caseof(K_MTU, RTV_MTU, rmx_mtu); | |
371 | caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount); | |
372 | caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire); | |
373 | caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe); | |
374 | caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe); | |
375 | caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh); | |
376 | caseof(K_RTT, RTV_RTT, rmx_rtt); | |
377 | caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar); | |
378 | } | |
7d8dd943 | 379 | rtm_inits |= flag; |
7cd60aa5 KS |
380 | if (lockrest || locking) |
381 | rt_metrics.rmx_locks |= flag; | |
382 | if (locking) | |
383 | locking = 0; | |
384 | *valp = atoi(value); | |
385 | } | |
386 | ||
4bec325f BJ |
387 | newroute(argc, argv) |
388 | int argc; | |
31bd2db6 | 389 | register char **argv; |
4bec325f BJ |
390 | { |
391 | struct sockaddr_in *sin; | |
57cacc90 | 392 | char *cmd, *dest, *gateway, *mask; |
31bd2db6 | 393 | int ishost, metric = 0, ret, attempts, oerrno, flags = 0, next; |
7cd60aa5 | 394 | int key; |
31bd2db6 | 395 | struct hostent *hp = 0; |
792b0612 | 396 | extern int errno; |
4bec325f | 397 | |
183ef13b | 398 | cmd = argv[0]; |
ac62fbdc KS |
399 | if (*cmd != 'g') |
400 | shutdown(s, 0); /* Don't want to read back our messages */ | |
31bd2db6 KS |
401 | while (--argc > 0) { |
402 | if (**(++argv)== '-') { | |
7cd60aa5 | 403 | switch(key = keyword(1 + *argv)) { |
31bd2db6 KS |
404 | case K_LINK: |
405 | af = AF_LINK; | |
eb03b231 | 406 | aflen = sizeof(struct sockaddr_dl); |
31bd2db6 KS |
407 | break; |
408 | case K_OSI: | |
eb03b231 | 409 | case K_ISO: |
31bd2db6 | 410 | af = AF_ISO; |
eb03b231 | 411 | aflen = sizeof(struct sockaddr_iso); |
31bd2db6 KS |
412 | break; |
413 | case K_INET: | |
414 | af = AF_INET; | |
eb03b231 | 415 | aflen = sizeof(struct sockaddr_in); |
31bd2db6 KS |
416 | break; |
417 | case K_XNS: | |
418 | af = AF_NS; | |
eb03b231 | 419 | aflen = sizeof(struct sockaddr_ns); |
31bd2db6 KS |
420 | break; |
421 | case K_IFACE: | |
7cd60aa5 | 422 | case K_INTERFACE: |
31bd2db6 KS |
423 | iflag++; |
424 | break; | |
7cd60aa5 KS |
425 | case K_LOCK: |
426 | locking = 1; | |
427 | break; | |
428 | case K_LOCKREST: | |
429 | lockrest = 1; | |
430 | break; | |
31bd2db6 KS |
431 | case K_HOST: |
432 | forcehost++; | |
433 | break; | |
039256d2 KS |
434 | case K_REJECT: |
435 | flags |= RTF_REJECT; | |
436 | break; | |
7cd60aa5 KS |
437 | case K_CLONING: |
438 | flags |= RTF_CLONING; | |
439 | break; | |
440 | case K_XRESOLVE: | |
441 | flags |= RTF_XRESOLVE; | |
442 | break; | |
ac62fbdc KS |
443 | case K_IFA: |
444 | argc--; | |
445 | (void) getaddr(RTA_IFA, *++argv, 0); | |
446 | break; | |
447 | case K_IFP: | |
448 | argc--; | |
449 | (void) getaddr(RTA_IFP, *++argv, 0); | |
450 | break; | |
31bd2db6 KS |
451 | case K_GENMASK: |
452 | argc--; | |
453 | (void) getaddr(RTA_GENMASK, *++argv, 0); | |
454 | break; | |
ac62fbdc KS |
455 | case K_GATEWAY: |
456 | argc--; | |
457 | (void) getaddr(RTA_GATEWAY, *++argv, 0); | |
458 | break; | |
459 | case K_DST: | |
460 | argc--; | |
461 | ishost = getaddr(RTA_DST, *++argv, &hp); | |
462 | dest = *argv; | |
463 | break; | |
464 | case K_NETMASK: | |
465 | argc--; | |
466 | (void) getaddr(RTA_NETMASK, *++argv, 0); | |
467 | /* FALLTHROUGH */ | |
468 | case K_NET: | |
469 | forcenet++; | |
470 | break; | |
7cd60aa5 KS |
471 | case K_MTU: |
472 | case K_HOPCOUNT: | |
473 | case K_EXPIRE: | |
474 | case K_RECVPIPE: | |
475 | case K_SENDPIPE: | |
476 | case K_SSTHRESH: | |
477 | case K_RTT: | |
478 | case K_RTTVAR: | |
479 | argc--; | |
480 | set_metric(*++argv, key); | |
481 | break; | |
31bd2db6 KS |
482 | default: |
483 | usage(1+*argv); | |
484 | } | |
485 | } else { | |
486 | if ((rtm_addrs & RTA_DST) == 0) { | |
487 | dest = *argv; | |
488 | ishost = getaddr(RTA_DST, *argv, &hp); | |
489 | } else if ((rtm_addrs & RTA_GATEWAY) == 0) { | |
490 | gateway = *argv; | |
491 | (void) getaddr(RTA_GATEWAY, *argv, &hp); | |
492 | } else { | |
493 | int ret = atoi(*argv); | |
494 | if (ret == 0) { | |
495 | printf("%s,%s", "old usage of trailing 0", | |
496 | "assuming route to if\n"); | |
497 | iflag = 1; | |
498 | continue; | |
499 | } else if (ret > 0 && ret < 10) { | |
500 | printf("old usage of trailing digit, "); | |
501 | printf("assuming route via gateway\n"); | |
502 | iflag = 0; | |
503 | continue; | |
504 | } | |
505 | (void) getaddr(RTA_NETMASK, *argv, 0); | |
506 | } | |
507 | } | |
508 | } | |
b3933da8 MK |
509 | if (forcehost) |
510 | ishost = 1; | |
511 | if (forcenet) | |
512 | ishost = 0; | |
7cd60aa5 | 513 | flags |= RTF_UP; |
6edb1941 | 514 | if (ishost) |
7d5f817b | 515 | flags |= RTF_HOST; |
57cacc90 | 516 | if (iflag == 0) |
7d5f817b | 517 | flags |= RTF_GATEWAY; |
792b0612 MK |
518 | for (attempts = 1; ; attempts++) { |
519 | errno = 0; | |
31bd2db6 | 520 | if (Cflag && (af == AF_INET || af == AF_NS)) { |
7d5f817b KS |
521 | route.rt_flags = flags; |
522 | route.rt_dst = so_dst.sa; | |
523 | route.rt_gateway = so_gate.sa; | |
57cacc90 KS |
524 | if ((ret = ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT, |
525 | (caddr_t)&route)) == 0) | |
526 | break; | |
527 | } else { | |
ac62fbdc | 528 | if ((ret = rtmsg(*cmd, flags)) == 0) |
57cacc90 KS |
529 | break; |
530 | } | |
792b0612 MK |
531 | if (errno != ENETUNREACH && errno != ESRCH) |
532 | break; | |
ac62fbdc | 533 | if (af == AF_INET && hp && hp->h_addr_list[1]) { |
792b0612 | 534 | hp->h_addr_list++; |
7d5f817b | 535 | bcopy(hp->h_addr_list[0], (caddr_t)&so_dst.sin.sin_addr, |
792b0612 MK |
536 | hp->h_length); |
537 | } else | |
538 | break; | |
539 | } | |
ac62fbdc KS |
540 | if (*cmd == 'g') |
541 | exit(0); | |
792b0612 MK |
542 | oerrno = errno; |
543 | printf("%s %s %s: gateway %s", cmd, ishost? "host" : "net", | |
544 | dest, gateway); | |
545 | if (attempts > 1 && ret == 0) | |
546 | printf(" (%s)", | |
547 | inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr)); | |
548 | if (ret == 0) | |
549 | printf("\n"); | |
550 | else { | |
551 | printf(": "); | |
552 | fflush(stdout); | |
553 | errno = oerrno; | |
31bd2db6 | 554 | error(""); |
792b0612 | 555 | } |
31bd2db6 | 556 | exit(0); |
4bec325f BJ |
557 | } |
558 | ||
559 | error(cmd) | |
560 | char *cmd; | |
561 | { | |
a48a48cc | 562 | extern int errno; |
4bec325f | 563 | |
a48a48cc KB |
564 | switch(errno) { |
565 | case ESRCH: | |
ae578a19 | 566 | printf("not in table\n"); |
a48a48cc KB |
567 | break; |
568 | case EBUSY: | |
ae578a19 | 569 | printf("entry in use\n"); |
a48a48cc KB |
570 | break; |
571 | case ENOBUFS: | |
ae578a19 | 572 | printf("routing table overflow\n"); |
a48a48cc KB |
573 | break; |
574 | default: | |
57cacc90 | 575 | printf("ioctl returns %d\n", errno); |
4bec325f | 576 | perror(cmd); |
a48a48cc | 577 | } |
ae578a19 KS |
578 | fflush(stdout); |
579 | errno = 0; | |
4bec325f BJ |
580 | } |
581 | ||
55e026df MK |
582 | char * |
583 | savestr(s) | |
584 | char *s; | |
585 | { | |
586 | char *sav; | |
587 | ||
588 | sav = malloc(strlen(s) + 1); | |
589 | if (sav == NULL) { | |
590 | fprintf("route: out of memory\n"); | |
591 | exit(1); | |
592 | } | |
593 | strcpy(sav, s); | |
594 | return (sav); | |
595 | } | |
596 | ||
31bd2db6 | 597 | inet_makenetandmask(net, sin) |
5c7868a2 | 598 | u_long net; |
31bd2db6 | 599 | register struct sockaddr_in *sin; |
57cacc90 KS |
600 | { |
601 | u_long addr; | |
5c7868a2 | 602 | u_long mask = 0; |
31bd2db6 | 603 | register char *cp; |
57cacc90 | 604 | |
31bd2db6 | 605 | rtm_addrs |= RTA_NETMASK; |
57cacc90 | 606 | if (net == 0) |
5c7868a2 | 607 | mask = addr = 0; |
57cacc90 KS |
608 | else if (net < 128) { |
609 | addr = net << IN_CLASSA_NSHIFT; | |
5c7868a2 | 610 | mask = IN_CLASSA_NET; |
57cacc90 KS |
611 | } else if (net < 65536) { |
612 | addr = net << IN_CLASSB_NSHIFT; | |
5c7868a2 | 613 | mask = IN_CLASSB_NET; |
57cacc90 KS |
614 | } else if (net < 16777216L) { |
615 | addr = net << IN_CLASSC_NSHIFT; | |
5c7868a2 | 616 | mask = IN_CLASSC_NET; |
57cacc90 KS |
617 | } else { |
618 | addr = net; | |
619 | if ((addr & IN_CLASSA_HOST) == 0) | |
5c7868a2 | 620 | mask = IN_CLASSA_NET; |
57cacc90 | 621 | else if ((addr & IN_CLASSB_HOST) == 0) |
5c7868a2 | 622 | mask = IN_CLASSB_NET; |
57cacc90 | 623 | else if ((addr & IN_CLASSC_HOST) == 0) |
5c7868a2 | 624 | mask = IN_CLASSC_NET; |
57cacc90 | 625 | else |
5c7868a2 KS |
626 | mask = -1; |
627 | } | |
31bd2db6 KS |
628 | sin->sin_addr.s_addr = htonl(addr); |
629 | sin = &so_mask.sin; | |
630 | sin->sin_addr.s_addr = htonl(mask); | |
631 | sin->sin_len = 0; | |
632 | sin->sin_family = 0; | |
633 | cp = (char *)(1 + &(sin->sin_addr)); | |
634 | while (*--cp == 0 && cp > (char *)sin) | |
635 | ; | |
636 | sin->sin_len = 1 + cp - (char *)sin; | |
57cacc90 KS |
637 | } |
638 | ||
6edb1941 MK |
639 | /* |
640 | * Interpret an argument as a network address of some kind, | |
641 | * returning 1 if a host address, 0 if a network address. | |
642 | */ | |
31bd2db6 | 643 | getaddr(which, s, hpp) |
4bec325f | 644 | char *s; |
792b0612 | 645 | struct hostent **hpp; |
4bec325f | 646 | { |
ac62fbdc | 647 | register sup su; |
b268b889 | 648 | struct ns_addr ns_addr(); |
eb03b231 | 649 | struct iso_addr *iso_addr(); |
accbc2e3 | 650 | struct hostent *hp; |
379dcc38 | 651 | struct netent *np; |
31bd2db6 | 652 | u_long val; |
accbc2e3 | 653 | |
eb03b231 | 654 | if (af == 0) { |
31bd2db6 | 655 | af = AF_INET; |
eb03b231 KS |
656 | aflen = sizeof(struct sockaddr_in); |
657 | } | |
658 | rtm_addrs |= which; | |
31bd2db6 | 659 | switch (which) { |
eb03b231 KS |
660 | case RTA_DST: su = so_addrs[0]; su->sa.sa_family = af; break; |
661 | case RTA_GATEWAY: su = so_addrs[1]; su->sa.sa_family = af; break; | |
662 | case RTA_NETMASK: su = so_addrs[2]; break; | |
31bd2db6 | 663 | case RTA_GENMASK: su = so_addrs[3]; break; |
ac62fbdc KS |
664 | case RTA_IFP: su = so_addrs[4]; su->sa.sa_family = af; break; |
665 | case RTA_IFA: su = so_addrs[5]; su->sa.sa_family = af; break; | |
31bd2db6 KS |
666 | default: usage("Internal Error"); /*NOTREACHED*/ |
667 | } | |
eb03b231 | 668 | su->sa.sa_len = aflen; |
7d5f817b | 669 | if (strcmp(s, "default") == 0) { |
eb03b231 KS |
670 | switch (which) { |
671 | case RTA_DST: | |
672 | forcenet++; | |
31bd2db6 | 673 | getaddr(RTA_NETMASK, s, 0); |
eb03b231 KS |
674 | break; |
675 | case RTA_NETMASK: | |
676 | case RTA_GENMASK: | |
677 | su->sa.sa_len = 0; | |
678 | } | |
31bd2db6 | 679 | return 0; |
7d5f817b | 680 | } |
31bd2db6 | 681 | if (af == AF_NS) |
b268b889 | 682 | goto do_xns; |
31bd2db6 | 683 | if (af == AF_OSI) |
7d5f817b | 684 | goto do_osi; |
31bd2db6 KS |
685 | if (af == AF_LINK) |
686 | goto do_link; | |
31bd2db6 | 687 | if (hpp == 0) hpp = &hp; |
7d5f817b | 688 | *hpp = 0; |
85e467b1 KS |
689 | if (((val = inet_addr(s)) != -1) && |
690 | (which != RTA_DST || forcenet == 0)) { | |
31bd2db6 KS |
691 | su->sin.sin_addr.s_addr = val; |
692 | if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY) | |
693 | return (1); | |
694 | else { | |
695 | val = ntohl(val); | |
696 | out: if (which == RTA_DST) | |
697 | inet_makenetandmask(val, &su->sin); | |
698 | return (0); | |
a2280e64 | 699 | } |
792b0612 MK |
700 | } |
701 | val = inet_network(s); | |
702 | if (val != -1) { | |
5c7868a2 | 703 | goto out; |
792b0612 | 704 | } |
379dcc38 SL |
705 | np = getnetbyname(s); |
706 | if (np) { | |
5c7868a2 | 707 | val = np->n_net; |
5c7868a2 | 708 | goto out; |
379dcc38 | 709 | } |
78160c55 MK |
710 | hp = gethostbyname(s); |
711 | if (hp) { | |
792b0612 | 712 | *hpp = hp; |
31bd2db6 KS |
713 | su->sin.sin_family = hp->h_addrtype; |
714 | bcopy(hp->h_addr, &su->sin.sin_addr, hp->h_length); | |
57cacc90 | 715 | return (1); |
78160c55 | 716 | } |
379dcc38 SL |
717 | fprintf(stderr, "%s: bad value\n", s); |
718 | exit(1); | |
b268b889 | 719 | do_xns: |
7d5f817b KS |
720 | if (val == 0) |
721 | return(0); | |
31bd2db6 | 722 | if (which == RTA_DST) { |
57cacc90 | 723 | extern short ns_bh[3]; |
31bd2db6 KS |
724 | struct sockaddr_ns *sms = &(so_mask.sns); |
725 | bzero((char *)sms, sizeof(*sms)); | |
57cacc90 KS |
726 | sms->sns_family = 0; |
727 | sms->sns_len = 6; | |
728 | sms->sns_addr.x_net = *(union ns_net *)ns_bh; | |
31bd2db6 | 729 | rtm_addrs |= RTA_NETMASK; |
57cacc90 | 730 | } |
31bd2db6 KS |
731 | su->sns.sns_addr = ns_addr(s); |
732 | return (!ns_nullhost(su->sns.sns_addr)); | |
7d5f817b | 733 | do_osi: |
eb03b231 KS |
734 | su->siso.siso_addr = *iso_addr(s); |
735 | if (which == RTA_NETMASK || which == RTA_GENMASK) { | |
736 | register char *cp = (char *)TSEL(&su->siso); | |
737 | su->siso.siso_nlen = 0; | |
738 | do {--cp ;} while ((cp > (char *)su) && (*cp == 0)); | |
739 | su->siso.siso_len = 1 + cp - (char *)su; | |
740 | } | |
31bd2db6 KS |
741 | return (1); |
742 | do_link: | |
31bd2db6 | 743 | link_addr(s, &su->sdl); |
7d5f817b | 744 | return (1); |
183ef13b | 745 | } |
eac76d14 MK |
746 | |
747 | short ns_nullh[] = {0,0,0}; | |
748 | short ns_bh[] = {-1,-1,-1}; | |
749 | ||
750 | char * | |
751 | ns_print(sns) | |
752 | struct sockaddr_ns *sns; | |
753 | { | |
754 | struct ns_addr work; | |
755 | union { union ns_net net_e; u_long long_e; } net; | |
756 | u_short port; | |
757 | static char mybuf[50], cport[10], chost[25]; | |
758 | char *host = ""; | |
759 | register char *p; register u_char *q; u_char *q_lim; | |
760 | ||
761 | work = sns->sns_addr; | |
762 | port = ntohs(work.x_port); | |
763 | work.x_port = 0; | |
764 | net.net_e = work.x_net; | |
765 | if (ns_nullhost(work) && net.long_e == 0) { | |
766 | if (port ) { | |
9bd38ba8 | 767 | (void)sprintf(mybuf, "*.%xH", port); |
eac76d14 MK |
768 | upHex(mybuf); |
769 | } else | |
9bd38ba8 | 770 | (void)sprintf(mybuf, "*.*"); |
eac76d14 MK |
771 | return (mybuf); |
772 | } | |
773 | ||
774 | if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) { | |
775 | host = "any"; | |
776 | } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) { | |
777 | host = "*"; | |
778 | } else { | |
779 | q = work.x_host.c_host; | |
9bd38ba8 | 780 | (void)sprintf(chost, "%02x%02x%02x%02x%02x%02xH", |
eac76d14 MK |
781 | q[0], q[1], q[2], q[3], q[4], q[5]); |
782 | for (p = chost; *p == '0' && p < chost + 12; p++); | |
783 | host = p; | |
784 | } | |
785 | if (port) | |
9bd38ba8 | 786 | (void)sprintf(cport, ".%xH", htons(port)); |
eac76d14 MK |
787 | else |
788 | *cport = 0; | |
789 | ||
9bd38ba8 | 790 | (void)sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport); |
eac76d14 MK |
791 | upHex(mybuf); |
792 | return(mybuf); | |
793 | } | |
794 | ||
795 | upHex(p0) | |
796 | char *p0; | |
797 | { | |
798 | register char *p = p0; | |
799 | for (; *p; p++) switch (*p) { | |
800 | ||
801 | case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': | |
802 | *p += ('A' - 'a'); | |
803 | } | |
804 | } | |
57cacc90 KS |
805 | |
806 | monitor() | |
807 | { | |
808 | int n; | |
809 | char msg[2048]; | |
9eb5d442 | 810 | verbose = 1; |
57cacc90 KS |
811 | for(;;) { |
812 | n = read(s, msg, 2048); | |
813 | printf("got message of size %d\n", n); | |
31bd2db6 | 814 | print_rtmsg((struct rt_msghdr *)msg); |
57cacc90 KS |
815 | } |
816 | } | |
817 | ||
818 | struct { | |
819 | struct rt_msghdr m_rtm; | |
31bd2db6 | 820 | char m_space[512]; |
57cacc90 KS |
821 | } m_rtmsg; |
822 | ||
31bd2db6 | 823 | rtmsg(cmd, flags) |
57cacc90 KS |
824 | { |
825 | static int seq; | |
85e467b1 | 826 | int rlen; |
57cacc90 | 827 | extern int errno; |
31bd2db6 KS |
828 | register char *cp = m_rtmsg.m_space; |
829 | register int l; | |
57cacc90 | 830 | |
ac62fbdc KS |
831 | #define ROUND(a) (1 + (((a) - 1) | (sizeof(long) - 1))) |
832 | #define NEXTADDR(w, u) { if (rtm_addrs & (w)) {l = (u).sa.sa_len;\ | |
833 | if(verbose)sodump(&(u),"u");if(l == 0) l = sizeof(int); l = ROUND(l);\ | |
834 | bcopy((char *)&(u), cp, l); cp += l;}} | |
835 | ||
57cacc90 KS |
836 | errno = 0; |
837 | bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); | |
838 | if (cmd == 'a') | |
839 | cmd = RTM_ADD; | |
840 | else if (cmd == 'c') | |
841 | cmd = RTM_CHANGE; | |
ac62fbdc KS |
842 | else if (cmd == 'g') |
843 | cmd = RTM_GET; | |
57cacc90 KS |
844 | else |
845 | cmd = RTM_DELETE; | |
ac62fbdc KS |
846 | #define rtm m_rtmsg.m_rtm |
847 | rtm.rtm_type = cmd; | |
848 | rtm.rtm_flags = flags; | |
849 | rtm.rtm_version = RTM_VERSION; | |
850 | rtm.rtm_seq = ++seq; | |
851 | rtm.rtm_addrs = rtm_addrs; | |
852 | rtm.rtm_rmx = rt_metrics; | |
853 | rtm.rtm_inits = rtm_inits; | |
31bd2db6 KS |
854 | |
855 | NEXTADDR(RTA_DST, so_dst); | |
856 | NEXTADDR(RTA_GATEWAY, so_gate); | |
857 | NEXTADDR(RTA_NETMASK, so_mask); | |
858 | NEXTADDR(RTA_GENMASK, so_genmask); | |
ac62fbdc KS |
859 | NEXTADDR(RTA_IFP, so_ifp); |
860 | NEXTADDR(RTA_IFA, so_ifa); | |
861 | rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; | |
31bd2db6 | 862 | if (verbose) |
ac62fbdc | 863 | print_rtmsg(&rtm, l); |
7cd60aa5 KS |
864 | if (debugonly) |
865 | return 0; | |
85e467b1 | 866 | if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { |
57cacc90 | 867 | perror("writing to routing socket"); |
7d5f817b | 868 | return (-1); |
57cacc90 | 869 | } |
ac62fbdc KS |
870 | if (cmd == RTM_GET) { |
871 | do { | |
872 | l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); | |
873 | } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); | |
874 | if (l < 0) | |
875 | perror("reading from routing socket"); | |
876 | else | |
877 | print_getmsg(&rtm, l); | |
878 | } | |
879 | #undef rtm | |
57cacc90 KS |
880 | return (0); |
881 | } | |
882 | ||
883 | char *msgtypes[] = { | |
884 | "", | |
885 | "RTM_ADD: Add Route", | |
886 | "RTM_DELETE: Delete Route", | |
887 | "RTM_CHANGE: Change Metrics or flags", | |
888 | "RTM_GET: Report Metrics", | |
889 | "RTM_LOSING: Kernel Suspects Partitioning", | |
890 | "RTM_REDIRECT: Told to use different route", | |
891 | "RTM_MISS: Lookup failed on this address", | |
892 | "RTM_LOCK: fix specified metrics", | |
893 | "RTM_OLDADD: caused by SIOCADDRT", | |
894 | "RTM_OLDDEL: caused by SIOCDELRT", | |
895 | 0, }; | |
896 | ||
897 | char metricnames[] = | |
7cd60aa5 KS |
898 | "\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu"; |
899 | char routeflags[] = | |
039256d2 | 900 | "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE"; |
57cacc90 KS |
901 | |
902 | #define ROUNDUP(a) ((char *)(1 + (((((int)a)) - 1) | (sizeof(long) - 1)))) | |
903 | ||
ac62fbdc | 904 | print_rtmsg(rtm, msglen) |
57cacc90 KS |
905 | register struct rt_msghdr *rtm; |
906 | { | |
7d5f817b KS |
907 | if (verbose == 0) |
908 | return; | |
a387100b | 909 | if (rtm->rtm_version != RTM_VERSION) { |
5c7868a2 | 910 | printf("routing message version %d not understood\n", |
57cacc90 | 911 | rtm->rtm_version); |
ac62fbdc | 912 | return; |
57cacc90 | 913 | } |
ac62fbdc KS |
914 | printf("%s\npid: %d, len %d, seq %d, errno %d, flags:", |
915 | msgtypes[rtm->rtm_type], rtm->rtm_pid, rtm->rtm_msglen, | |
916 | rtm->rtm_seq, rtm->rtm_errno); | |
917 | bprintf(stdout, rtm->rtm_flags, routeflags); | |
918 | pmsg_common(rtm); | |
919 | } | |
920 | ||
921 | print_getmsg(rtm, msglen) | |
922 | register struct rt_msghdr *rtm; | |
923 | { | |
924 | if (rtm->rtm_version != RTM_VERSION) { | |
925 | printf("routing message version %d not understood\n", | |
926 | rtm->rtm_version); | |
927 | return; | |
928 | } | |
929 | if (rtm->rtm_msglen != msglen) { | |
930 | printf("get length mismatch, in packet %d, returned %d\n", | |
931 | rtm->rtm_msglen, msglen); | |
932 | return; | |
933 | } | |
934 | printf("RTM_GET: errno %d, flags:", rtm->rtm_errno); | |
935 | bprintf(stdout, rtm->rtm_flags, routeflags); | |
936 | printf("\nmetric values:\n\n"); | |
937 | #define metric(f, e) printf("\t%s:\t%d\n", "f", rtm->rtm_rmx.e) | |
938 | metric(RTV_RPIPE, rmx_recvpipe); | |
939 | metric(RTV_SPIPE, rmx_sendpipe); | |
940 | metric(RTV_SSTHRESH, rmx_ssthresh); | |
941 | metric(RTV_RTT, rmx_rtt); | |
942 | metric(RTV_RTTVAR, rmx_rttvar); | |
943 | metric(RTV_HOPCOUNT, rmx_hopcount); | |
944 | metric(RTV_MTU, rmx_mtu); | |
945 | metric(RTV_EXPIRE, rmx_expire); | |
946 | #undef metric | |
947 | pmsg_common(rtm); | |
948 | } | |
949 | ||
950 | pmsg_common(rtm) | |
951 | register struct rt_msghdr *rtm; | |
952 | { | |
953 | char *cp; | |
954 | register struct sockaddr *sa; | |
955 | int i; | |
956 | ||
957 | printf("\nlocks: "); bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); | |
958 | printf(" inits: "); bprintf(stdout, rtm->rtm_inits, metricnames); | |
959 | printf("\nsockaddrs: "); | |
960 | bprintf(stdout, rtm->rtm_addrs, | |
961 | "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR"); | |
962 | putchar('\n'); | |
963 | cp = ((char *)(rtm + 1)); | |
964 | if (rtm->rtm_addrs) | |
965 | for (i = 1; i; i <<= 1) | |
966 | if (i & rtm->rtm_addrs) { | |
967 | sa = (struct sockaddr *)cp; | |
968 | printf(" %s", routename(sa)); | |
969 | cp = ROUNDUP(cp + sa->sa_len); | |
970 | } | |
971 | putchar('\n'); | |
57cacc90 KS |
972 | fflush(stdout); |
973 | } | |
974 | ||
975 | bprintf(fp, b, s) | |
976 | register FILE *fp; | |
977 | register int b; | |
978 | register u_char *s; | |
979 | { | |
980 | register int i; | |
981 | int gotsome = 0; | |
982 | ||
983 | if (b == 0) | |
984 | return; | |
985 | while (i = *s++) { | |
986 | if (b & (1 << (i-1))) { | |
987 | if (gotsome == 0) i = '<'; else i = ','; | |
988 | putc(i, fp); | |
989 | gotsome = 1; | |
990 | for (; (i = *s) > 32; s++) | |
991 | putc(i, fp); | |
992 | } else | |
993 | while (*s > 32) | |
994 | s++; | |
995 | } | |
996 | if (gotsome) | |
997 | putc('>', fp); | |
998 | } | |
31bd2db6 KS |
999 | int |
1000 | keyword(cp) | |
1001 | char *cp; | |
1002 | { | |
1003 | register struct keytab *kt = keywords; | |
1004 | while (kt->kt_cp && strcmp(kt->kt_cp, cp)) | |
1005 | kt++; | |
1006 | return kt->kt_i; | |
1007 | } | |
1008 | ||
1009 | sodump(su, which) | |
ac62fbdc | 1010 | register sup su; |
31bd2db6 KS |
1011 | char *which; |
1012 | { | |
1013 | switch (su->sa.sa_family) { | |
1014 | case AF_LINK: | |
1015 | printf("%s: link %s; ", which, link_ntoa(&su->sdl)); | |
1016 | break; | |
1017 | case AF_ISO: | |
1018 | printf("%s: iso %s; ", which, iso_ntoa(&su->siso.siso_addr)); | |
1019 | break; | |
1020 | case AF_INET: | |
1021 | printf("%s: inet %s; ", which, inet_ntoa(su->sin.sin_addr)); | |
1022 | break; | |
1023 | case AF_NS: | |
ac62fbdc | 1024 | printf("%s: xns %s; ", which, ns_ntoa(su->sns.sns_addr)); |
31bd2db6 KS |
1025 | break; |
1026 | } | |
1027 | fflush(stdout); | |
1028 | } |