Sat Aug 25 07:06:48 2018 UTC ()
Pull up following revision(s) (requested by roy in ticket #976):

	sbin/route/route.c: revision 1.160

Resolve every route(4) message type before printing anything more about it
other than the type and length.

This solves the issue where RTM_ONEWADDR is received and it tries to
parse route information from it.


(martin)
diff -r1.155.4.3 -r1.155.4.4 src/sbin/route/route.c

cvs diff -r1.155.4.3 -r1.155.4.4 src/sbin/route/route.c (switch to unified diff)

--- src/sbin/route/route.c 2018/04/09 13:34:11 1.155.4.3
+++ src/sbin/route/route.c 2018/08/25 07:06:48 1.155.4.4
@@ -1,1813 +1,1816 @@ @@ -1,1813 +1,1816 @@
1/* $NetBSD: route.c,v 1.155.4.3 2018/04/09 13:34:11 bouyer Exp $ */ 1/* $NetBSD: route.c,v 1.155.4.4 2018/08/25 07:06:48 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1983, 1989, 1991, 1993 4 * Copyright (c) 1983, 1989, 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors 15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software 16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission. 17 * without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#ifndef lint 33#ifndef lint
34__COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1991, 1993\ 34__COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1991, 1993\
35 The Regents of the University of California. All rights reserved."); 35 The Regents of the University of California. All rights reserved.");
36#endif /* not lint */ 36#endif /* not lint */
37 37
38#ifndef lint 38#ifndef lint
39#if 0 39#if 0
40static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95"; 40static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95";
41#else 41#else
42__RCSID("$NetBSD: route.c,v 1.155.4.3 2018/04/09 13:34:11 bouyer Exp $"); 42__RCSID("$NetBSD: route.c,v 1.155.4.4 2018/08/25 07:06:48 martin Exp $");
43#endif 43#endif
44#endif /* not lint */ 44#endif /* not lint */
45 45
46#include <sys/param.h> 46#include <sys/param.h>
47#include <sys/file.h> 47#include <sys/file.h>
48#include <sys/socket.h> 48#include <sys/socket.h>
49#include <sys/ioctl.h> 49#include <sys/ioctl.h>
50#include <sys/sysctl.h> 50#include <sys/sysctl.h>
51 51
52#include <net/if.h> 52#include <net/if.h>
53#include <net/route.h> 53#include <net/route.h>
54#include <net/if_dl.h> 54#include <net/if_dl.h>
55#include <net80211/ieee80211_netbsd.h> 55#include <net80211/ieee80211_netbsd.h>
56#include <netinet/in.h> 56#include <netinet/in.h>
57#include <netatalk/at.h> 57#include <netatalk/at.h>
58#include <netmpls/mpls.h> 58#include <netmpls/mpls.h>
59#include <arpa/inet.h> 59#include <arpa/inet.h>
60#include <netdb.h> 60#include <netdb.h>
61 61
62#include <errno.h> 62#include <errno.h>
63#include <unistd.h> 63#include <unistd.h>
64#include <stdio.h> 64#include <stdio.h>
65#include <ctype.h> 65#include <ctype.h>
66#include <stdlib.h> 66#include <stdlib.h>
67#include <string.h> 67#include <string.h>
68#include <time.h> 68#include <time.h>
69#include <paths.h> 69#include <paths.h>
70#include <err.h> 70#include <err.h>
71 71
72#include "keywords.h" 72#include "keywords.h"
73#include "extern.h" 73#include "extern.h"
74#include "prog_ops.h" 74#include "prog_ops.h"
75#include "rtutil.h" 75#include "rtutil.h"
76 76
77union sockunion { 77union sockunion {
78 struct sockaddr sa; 78 struct sockaddr sa;
79 struct sockaddr_in sin; 79 struct sockaddr_in sin;
80#ifdef INET6 80#ifdef INET6
81 struct sockaddr_in6 sin6; 81 struct sockaddr_in6 sin6;
82#endif 82#endif
83 struct sockaddr_at sat; 83 struct sockaddr_at sat;
84 struct sockaddr_dl sdl; 84 struct sockaddr_dl sdl;
85#ifndef SMALL 85#ifndef SMALL
86 struct sockaddr_mpls smpls; 86 struct sockaddr_mpls smpls;
87#endif /* SMALL */ 87#endif /* SMALL */
88 struct sockaddr_storage sstorage; 88 struct sockaddr_storage sstorage;
89}; 89};
90 90
91typedef union sockunion *sup; 91typedef union sockunion *sup;
92 92
93struct sou { 93struct sou {
94 union sockunion *so_dst, *so_gate, *so_mask, *so_genmask, *so_ifa, 94 union sockunion *so_dst, *so_gate, *so_mask, *so_genmask, *so_ifa,
95 *so_ifp, *so_mpls; 95 *so_ifp, *so_mpls;
96}; 96};
97 97
98static const char *route_strerror(int); 98static const char *route_strerror(int);
99static void set_metric(const char *, int); 99static void set_metric(const char *, int);
100static int newroute(int, char *const *); 100static int newroute(int, char *const *);
101static void inet_makenetandmask(u_int32_t, struct sockaddr_in *, struct sou *); 101static void inet_makenetandmask(u_int32_t, struct sockaddr_in *, struct sou *);
102#ifdef INET6 102#ifdef INET6
103static int inet6_makenetandmask(const struct sockaddr_in6 *, struct sou *); 103static int inet6_makenetandmask(const struct sockaddr_in6 *, struct sou *);
104#endif 104#endif
105static int getaddr(int, const char *, struct hostent **, struct sou *); 105static int getaddr(int, const char *, struct hostent **, struct sou *);
106static int flushroutes(int, char *const [], int); 106static int flushroutes(int, char *const [], int);
107static char *netmask_string(const struct sockaddr *, int, int); 107static char *netmask_string(const struct sockaddr *, int, int);
108static int prefixlen(const char *, struct sou *); 108static int prefixlen(const char *, struct sou *);
109#ifndef SMALL 109#ifndef SMALL
110static void interfaces(void); 110static void interfaces(void);
111static void monitor(int, char * const *); 111static void monitor(int, char * const *);
112static int print_getmsg(struct rt_msghdr *, int, struct sou *); 112static int print_getmsg(struct rt_msghdr *, int, struct sou *);
113static const char *linkstate(struct if_msghdr *); 113static const char *linkstate(struct if_msghdr *);
114static sup readtag(sup, const char *); 114static sup readtag(sup, const char *);
115static void addtag(sup, const char *, int); 115static void addtag(sup, const char *, int);
116#endif /* SMALL */ 116#endif /* SMALL */
117static int rtmsg(int, int, struct sou *); 117static int rtmsg(int, int, struct sou *);
118static void mask_addr(struct sou *); 118static void mask_addr(struct sou *);
119static void print_rtmsg(struct rt_msghdr *, int); 119static void print_rtmsg(struct rt_msghdr *, int);
120static void pmsg_common(struct rt_msghdr *); 120static void pmsg_common(struct rt_msghdr *);
121static void pmsg_addrs(const char *, int); 121static void pmsg_addrs(const char *, int);
122static void bprintf(FILE *, int, const char *); 122static void bprintf(FILE *, int, const char *);
123static void sodump(sup, const char *); 123static void sodump(sup, const char *);
124static void sockaddr(const char *, struct sockaddr *); 124static void sockaddr(const char *, struct sockaddr *);
125 125
126int pid, rtm_addrs; 126int pid, rtm_addrs;
127int sock; 127int sock;
128int forcehost, forcenet, doflush, af; 128int forcehost, forcenet, doflush, af;
129int iflag, Lflag, nflag, qflag, tflag, Sflag, Tflag; 129int iflag, Lflag, nflag, qflag, tflag, Sflag, Tflag;
130int verbose, aflen = sizeof(struct sockaddr_in), rtag; 130int verbose, aflen = sizeof(struct sockaddr_in), rtag;
131int locking, lockrest, debugonly, shortoutput; 131int locking, lockrest, debugonly, shortoutput;
132struct rt_metrics rt_metrics; 132struct rt_metrics rt_metrics;
133int rtm_inits; 133int rtm_inits;
134short ns_nullh[] = {0,0,0}; 134short ns_nullh[] = {0,0,0};
135short ns_bh[] = {-1,-1,-1}; 135short ns_bh[] = {-1,-1,-1};
136 136
137static const char opts[] = "dfLnqSsTtv"; 137static const char opts[] = "dfLnqSsTtv";
138 138
139void 139void
140usage(const char *cp) 140usage(const char *cp)
141{ 141{
142 142
143 if (cp) 143 if (cp)
144 warnx("botched keyword: %s", cp); 144 warnx("botched keyword: %s", cp);
145 (void)fprintf(stderr, 145 (void)fprintf(stderr,
146 "Usage: %s [-%s] cmd [[-<qualifers>] args]\n", getprogname(), opts); 146 "Usage: %s [-%s] cmd [[-<qualifers>] args]\n", getprogname(), opts);
147 exit(1); 147 exit(1);
148 /* NOTREACHED */ 148 /* NOTREACHED */
149} 149}
150 150
151#define PRIETHER "02x:%02x:%02x:%02x:%02x:%02x" 151#define PRIETHER "02x:%02x:%02x:%02x:%02x:%02x"
152#define PRIETHER_ARGS(__enaddr) (__enaddr)[0], (__enaddr)[1], (__enaddr)[2], \ 152#define PRIETHER_ARGS(__enaddr) (__enaddr)[0], (__enaddr)[1], (__enaddr)[2], \
153 (__enaddr)[3], (__enaddr)[4], (__enaddr)[5] 153 (__enaddr)[3], (__enaddr)[4], (__enaddr)[5]
154 154
155int 155int
156main(int argc, char * const *argv) 156main(int argc, char * const *argv)
157{ 157{
158 int ch; 158 int ch;
159 159
160 if (argc < 2) 160 if (argc < 2)
161 usage(NULL); 161 usage(NULL);
162 162
163 while ((ch = getopt(argc, argv, opts)) != -1) 163 while ((ch = getopt(argc, argv, opts)) != -1)
164 switch (ch) { 164 switch (ch) {
165 case 'd': 165 case 'd':
166 debugonly = 1; 166 debugonly = 1;
167 break; 167 break;
168 case 'f': 168 case 'f':
169 doflush = 1; 169 doflush = 1;
170 break; 170 break;
171 case 'L': 171 case 'L':
172 Lflag = RT_LFLAG; 172 Lflag = RT_LFLAG;
173 break; 173 break;
174 case 'n': 174 case 'n':
175 nflag = RT_NFLAG; 175 nflag = RT_NFLAG;
176 break; 176 break;
177 case 'q': 177 case 'q':
178 qflag = 1; 178 qflag = 1;
179 break; 179 break;
180 case 'S': 180 case 'S':
181 Sflag = 1; 181 Sflag = 1;
182 break; 182 break;
183 case 's': 183 case 's':
184 shortoutput = 1; 184 shortoutput = 1;
185 break; 185 break;
186 case 'T': 186 case 'T':
187 Tflag = RT_TFLAG; 187 Tflag = RT_TFLAG;
188 break; 188 break;
189 case 't': 189 case 't':
190 tflag = 1; 190 tflag = 1;
191 break; 191 break;
192 case 'v': 192 case 'v':
193 verbose = RT_VFLAG; 193 verbose = RT_VFLAG;
194 break; 194 break;
195 case '?': 195 case '?':
196 default: 196 default:
197 usage(NULL); 197 usage(NULL);
198 /*NOTREACHED*/ 198 /*NOTREACHED*/
199 } 199 }
200 argc -= optind; 200 argc -= optind;
201 argv += optind; 201 argv += optind;
202 202
203 if (prog_init && prog_init() == -1) 203 if (prog_init && prog_init() == -1)
204 err(1, "init failed"); 204 err(1, "init failed");
205 205
206 pid = prog_getpid(); 206 pid = prog_getpid();
207 if (tflag) 207 if (tflag)
208 sock = prog_open("/dev/null", O_WRONLY, 0); 208 sock = prog_open("/dev/null", O_WRONLY, 0);
209 else 209 else
210 sock = prog_socket(PF_ROUTE, SOCK_RAW, 0); 210 sock = prog_socket(PF_ROUTE, SOCK_RAW, 0);
211 if (sock < 0) 211 if (sock < 0)
212 err(EXIT_FAILURE, "socket"); 212 err(EXIT_FAILURE, "socket");
213 213
214 if (*argv == NULL) { 214 if (*argv == NULL) {
215 if (doflush) 215 if (doflush)
216 ch = K_FLUSH; 216 ch = K_FLUSH;
217 else 217 else
218 goto no_cmd; 218 goto no_cmd;
219 } else 219 } else
220 ch = keyword(*argv); 220 ch = keyword(*argv);
221 221
222 switch (ch) { 222 switch (ch) {
223#ifndef SMALL 223#ifndef SMALL
224 case K_GET: 224 case K_GET:
225#endif /* SMALL */ 225#endif /* SMALL */
226 case K_CHANGE: 226 case K_CHANGE:
227 case K_ADD: 227 case K_ADD:
228 case K_DELETE: 228 case K_DELETE:
229 if (doflush) 229 if (doflush)
230 (void)flushroutes(1, argv, 0); 230 (void)flushroutes(1, argv, 0);
231 return newroute(argc, argv); 231 return newroute(argc, argv);
232 232
233 case K_SHOW: 233 case K_SHOW:
234 show(argc, argv, Lflag|nflag|Tflag|verbose); 234 show(argc, argv, Lflag|nflag|Tflag|verbose);
235 return 0; 235 return 0;
236 236
237#ifndef SMALL 237#ifndef SMALL
238 case K_MONITOR: 238 case K_MONITOR:
239 monitor(argc, argv); 239 monitor(argc, argv);
240 return 0; 240 return 0;
241 241
242#endif /* SMALL */ 242#endif /* SMALL */
243 case K_FLUSH: 243 case K_FLUSH:
244 return flushroutes(argc, argv, 0); 244 return flushroutes(argc, argv, 0);
245 245
246 case K_FLUSHALL: 246 case K_FLUSHALL:
247 return flushroutes(argc, argv, 1); 247 return flushroutes(argc, argv, 1);
248 no_cmd: 248 no_cmd:
249 default: 249 default:
250 usage(*argv); 250 usage(*argv);
251 /*NOTREACHED*/ 251 /*NOTREACHED*/
252 } 252 }
253} 253}
254 254
255static char * 255static char *
256netmask_string(const struct sockaddr *mask, int len, int family) 256netmask_string(const struct sockaddr *mask, int len, int family)
257{ 257{
258 static char smask[INET6_ADDRSTRLEN]; 258 static char smask[INET6_ADDRSTRLEN];
259 struct sockaddr_in nsin; 259 struct sockaddr_in nsin;
260 struct sockaddr_in6 nsin6; 260 struct sockaddr_in6 nsin6;
261 261
262 if (len >= 0) 262 if (len >= 0)
263 snprintf(smask, sizeof(smask), "%d", len); 263 snprintf(smask, sizeof(smask), "%d", len);
264 else { 264 else {
265 switch (family) { 265 switch (family) {
266 case AF_INET: 266 case AF_INET:
267 memset(&nsin, 0, sizeof(nsin)); 267 memset(&nsin, 0, sizeof(nsin));
268 memcpy(&nsin, mask, mask->sa_len); 268 memcpy(&nsin, mask, mask->sa_len);
269 snprintf(smask, sizeof(smask), "%s", 269 snprintf(smask, sizeof(smask), "%s",
270 inet_ntoa(nsin.sin_addr)); 270 inet_ntoa(nsin.sin_addr));
271 break; 271 break;
272 case AF_INET6: 272 case AF_INET6:
273 memset(&nsin6, 0, sizeof(nsin6)); 273 memset(&nsin6, 0, sizeof(nsin6));
274 memcpy(&nsin6, mask, mask->sa_len); 274 memcpy(&nsin6, mask, mask->sa_len);
275 inet_ntop(family, &nsin6.sin6_addr, smask, 275 inet_ntop(family, &nsin6.sin6_addr, smask,
276 sizeof(smask)); 276 sizeof(smask));
277 break; 277 break;
278 default: 278 default:
279 snprintf(smask, sizeof(smask), "%s", any_ntoa(mask)); 279 snprintf(smask, sizeof(smask), "%s", any_ntoa(mask));
280 } 280 }
281 } 281 }
282 282
283 return smask; 283 return smask;
284} 284}
285/* 285/*
286 * Purge all entries in the routing tables not 286 * Purge all entries in the routing tables not
287 * associated with network interfaces. 287 * associated with network interfaces.
288 */ 288 */
289static int 289static int
290flushroutes(int argc, char * const argv[], int doall) 290flushroutes(int argc, char * const argv[], int doall)
291{ 291{
292 struct sockaddr *sa; 292 struct sockaddr *sa;
293 size_t needed; 293 size_t needed;
294 int flags, mib[6], rlen, seqno; 294 int flags, mib[6], rlen, seqno;
295 char *buf, *next, *lim; 295 char *buf, *next, *lim;
296 const char *afname; 296 const char *afname;
297 struct rt_msghdr *rtm; 297 struct rt_msghdr *rtm;
298 298
299 flags = 0; 299 flags = 0;
300 af = AF_UNSPEC; 300 af = AF_UNSPEC;
301 /* Don't want to read back our messages */ 301 /* Don't want to read back our messages */
302 prog_shutdown(sock, SHUT_RD); 302 prog_shutdown(sock, SHUT_RD);
303 parse_show_opts(argc, argv, &af, &flags, &afname, false); 303 parse_show_opts(argc, argv, &af, &flags, &afname, false);
304 mib[0] = CTL_NET; 304 mib[0] = CTL_NET;
305 mib[1] = PF_ROUTE; 305 mib[1] = PF_ROUTE;
306 mib[2] = 0; /* protocol */ 306 mib[2] = 0; /* protocol */
307 mib[3] = 0; /* wildcard address family */ 307 mib[3] = 0; /* wildcard address family */
308 mib[4] = NET_RT_DUMP; 308 mib[4] = NET_RT_DUMP;
309 mib[5] = 0; /* no flags */ 309 mib[5] = 0; /* no flags */
310 if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 310 if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
311 err(EXIT_FAILURE, "route-sysctl-estimate"); 311 err(EXIT_FAILURE, "route-sysctl-estimate");
312 buf = lim = NULL; 312 buf = lim = NULL;
313 if (needed) { 313 if (needed) {
314 if ((buf = malloc(needed)) == NULL) 314 if ((buf = malloc(needed)) == NULL)
315 err(EXIT_FAILURE, "malloc"); 315 err(EXIT_FAILURE, "malloc");
316 if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 316 if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
317 err(EXIT_FAILURE, "actual retrieval of routing table"); 317 err(EXIT_FAILURE, "actual retrieval of routing table");
318 lim = buf + needed; 318 lim = buf + needed;
319 } 319 }
320 if (verbose) { 320 if (verbose) {
321 (void)printf("Examining routing table from sysctl\n"); 321 (void)printf("Examining routing table from sysctl\n");
322 if (af != AF_UNSPEC) 322 if (af != AF_UNSPEC)
323 printf("(address family %s)\n", afname); 323 printf("(address family %s)\n", afname);
324 } 324 }
325 if (needed == 0) 325 if (needed == 0)
326 return 0; 326 return 0;
327 seqno = 0; /* ??? */ 327 seqno = 0; /* ??? */
328 for (next = buf; next < lim; next += rtm->rtm_msglen) { 328 for (next = buf; next < lim; next += rtm->rtm_msglen) {
329 rtm = (struct rt_msghdr *)next; 329 rtm = (struct rt_msghdr *)next;
330 sa = (struct sockaddr *)(rtm + 1); 330 sa = (struct sockaddr *)(rtm + 1);
331 if (verbose) 331 if (verbose)
332 print_rtmsg(rtm, rtm->rtm_msglen); 332 print_rtmsg(rtm, rtm->rtm_msglen);
333 if ((rtm->rtm_flags & flags) != flags) 333 if ((rtm->rtm_flags & flags) != flags)
334 continue; 334 continue;
335 if (!(rtm->rtm_flags & (RTF_GATEWAY | RTF_STATIC)) && !doall) 335 if (!(rtm->rtm_flags & (RTF_GATEWAY | RTF_STATIC)) && !doall)
336 continue; 336 continue;
337 if (af != AF_UNSPEC && sa->sa_family != af) 337 if (af != AF_UNSPEC && sa->sa_family != af)
338 continue; 338 continue;
339 if (debugonly) 339 if (debugonly)
340 continue; 340 continue;
341 rtm->rtm_type = RTM_DELETE; 341 rtm->rtm_type = RTM_DELETE;
342 rtm->rtm_seq = seqno; 342 rtm->rtm_seq = seqno;
343 do { 343 do {
344 rlen = prog_write(sock, next, rtm->rtm_msglen); 344 rlen = prog_write(sock, next, rtm->rtm_msglen);
345 } while (rlen == -1 && errno == ENOBUFS); 345 } while (rlen == -1 && errno == ENOBUFS);
346 if (rlen == -1) { 346 if (rlen == -1) {
347 warnx("writing to routing socket: %s", 347 warnx("writing to routing socket: %s",
348 route_strerror(errno)); 348 route_strerror(errno));
349 return 1; 349 return 1;
350 } 350 }
351 if (rlen < (int)rtm->rtm_msglen) { 351 if (rlen < (int)rtm->rtm_msglen) {
352 warnx("write to routing socket, got %d for rlen", rlen); 352 warnx("write to routing socket, got %d for rlen", rlen);
353 return 1; 353 return 1;
354 } 354 }
355 seqno++; 355 seqno++;
356 if (qflag) 356 if (qflag)
357 continue; 357 continue;
358 if (verbose) 358 if (verbose)
359 print_rtmsg(rtm, rlen); 359 print_rtmsg(rtm, rlen);
360 else { 360 else {
361 (void)printf("%-20.20s ", netname(sa, NULL, nflag)); 361 (void)printf("%-20.20s ", netname(sa, NULL, nflag));
362 sa = (struct sockaddr *)(RT_ROUNDUP(sa->sa_len) + 362 sa = (struct sockaddr *)(RT_ROUNDUP(sa->sa_len) +
363 (char *)sa); 363 (char *)sa);
364 (void)printf("%-20.20s ", routename(sa, nflag)); 364 (void)printf("%-20.20s ", routename(sa, nflag));
365 (void)printf("done\n"); 365 (void)printf("done\n");
366 } 366 }
367 } 367 }
368 free(buf); 368 free(buf);
369 return 0; 369 return 0;
370} 370}
371 371
372static const char * 372static const char *
373route_strerror(int error) 373route_strerror(int error)
374{ 374{
375 375
376 switch (error) { 376 switch (error) {
377 case ESRCH: 377 case ESRCH:
378 return "not in table"; 378 return "not in table";
379 case EBUSY: 379 case EBUSY:
380 return "entry in use"; 380 return "entry in use";
381 case ENOBUFS: 381 case ENOBUFS:
382 return "routing table overflow"; 382 return "routing table overflow";
383 default: 383 default:
384 return strerror(error); 384 return strerror(error);
385 } 385 }
386} 386}
387 387
388static void 388static void
389set_metric(const char *value, int key) 389set_metric(const char *value, int key)
390{ 390{
391 int flag = 0; 391 int flag = 0;
392 uint64_t noval, *valp = &noval; 392 uint64_t noval, *valp = &noval;
393 393
394 switch (key) { 394 switch (key) {
395#define caseof(x, y, z) \ 395#define caseof(x, y, z) \
396 case x: valp = (uint64_t *)&rt_metrics.z; flag = y; break 396 case x: valp = (uint64_t *)&rt_metrics.z; flag = y; break
397 caseof(K_MTU, RTV_MTU, rmx_mtu); 397 caseof(K_MTU, RTV_MTU, rmx_mtu);
398 caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount); 398 caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount);
399 caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire); 399 caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire);
400 caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe); 400 caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe);
401 caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe); 401 caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe);
402 caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh); 402 caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh);
403 caseof(K_RTT, RTV_RTT, rmx_rtt); 403 caseof(K_RTT, RTV_RTT, rmx_rtt);
404 caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar); 404 caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar);
405 } 405 }
406 rtm_inits |= flag; 406 rtm_inits |= flag;
407 if (lockrest || locking) 407 if (lockrest || locking)
408 rt_metrics.rmx_locks |= flag; 408 rt_metrics.rmx_locks |= flag;
409 if (locking) 409 if (locking)
410 locking = 0; 410 locking = 0;
411 *valp = strtoul(value, NULL, 0); 411 *valp = strtoul(value, NULL, 0);
412} 412}
413 413
414static int 414static int
415newroute(int argc, char *const *argv) 415newroute(int argc, char *const *argv)
416{ 416{
417 const char *cmd, *dest = "", *gateway = ""; 417 const char *cmd, *dest = "", *gateway = "";
418 int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC; 418 int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC;
419 int key; 419 int key;
420 struct hostent *hp = 0; 420 struct hostent *hp = 0;
421 struct sou sou, *soup = &sou; 421 struct sou sou, *soup = &sou;
422 422
423 sou.so_dst = calloc(1, sizeof(union sockunion)); 423 sou.so_dst = calloc(1, sizeof(union sockunion));
424 sou.so_gate = calloc(1, sizeof(union sockunion)); 424 sou.so_gate = calloc(1, sizeof(union sockunion));
425 sou.so_mask = calloc(1, sizeof(union sockunion)); 425 sou.so_mask = calloc(1, sizeof(union sockunion));
426 sou.so_genmask = calloc(1, sizeof(union sockunion)); 426 sou.so_genmask = calloc(1, sizeof(union sockunion));
427 sou.so_ifa = calloc(1, sizeof(union sockunion)); 427 sou.so_ifa = calloc(1, sizeof(union sockunion));
428 sou.so_ifp = calloc(1, sizeof(union sockunion)); 428 sou.so_ifp = calloc(1, sizeof(union sockunion));
429 sou.so_mpls = calloc(1, sizeof(union sockunion)); 429 sou.so_mpls = calloc(1, sizeof(union sockunion));
430 430
431 if (sou.so_dst == NULL || sou.so_gate == NULL || sou.so_mask == NULL || 431 if (sou.so_dst == NULL || sou.so_gate == NULL || sou.so_mask == NULL ||
432 sou.so_genmask == NULL || sou.so_ifa == NULL || sou.so_ifp == NULL || 432 sou.so_genmask == NULL || sou.so_ifa == NULL || sou.so_ifp == NULL ||
433 sou.so_mpls == NULL) 433 sou.so_mpls == NULL)
434 errx(EXIT_FAILURE, "Cannot allocate memory"); 434 errx(EXIT_FAILURE, "Cannot allocate memory");
435 435
436 cmd = argv[0]; 436 cmd = argv[0];
437 af = AF_UNSPEC; 437 af = AF_UNSPEC;
438 if (*cmd != 'g') { 438 if (*cmd != 'g') {
439 /* Don't want to read back our messages */ 439 /* Don't want to read back our messages */
440 prog_shutdown(sock, SHUT_RD); 440 prog_shutdown(sock, SHUT_RD);
441 } 441 }
442 while (--argc > 0) { 442 while (--argc > 0) {
443 if (**(++argv)== '-') { 443 if (**(++argv)== '-') {
444 switch (key = keyword(1 + *argv)) { 444 switch (key = keyword(1 + *argv)) {
445 445
446 case K_SA: 446 case K_SA:
447 af = PF_ROUTE; 447 af = PF_ROUTE;
448 aflen = sizeof(union sockunion); 448 aflen = sizeof(union sockunion);
449 break; 449 break;
450 450
451#ifndef SMALL 451#ifndef SMALL
452 case K_ATALK: 452 case K_ATALK:
453 af = AF_APPLETALK; 453 af = AF_APPLETALK;
454 aflen = sizeof(struct sockaddr_at); 454 aflen = sizeof(struct sockaddr_at);
455 break; 455 break;
456#endif 456#endif
457 457
458 case K_INET: 458 case K_INET:
459 af = AF_INET; 459 af = AF_INET;
460 aflen = sizeof(struct sockaddr_in); 460 aflen = sizeof(struct sockaddr_in);
461 break; 461 break;
462 462
463#ifdef INET6 463#ifdef INET6
464 case K_INET6: 464 case K_INET6:
465 af = AF_INET6; 465 af = AF_INET6;
466 aflen = sizeof(struct sockaddr_in6); 466 aflen = sizeof(struct sockaddr_in6);
467 break; 467 break;
468#endif 468#endif
469 469
470 case K_LINK: 470 case K_LINK:
471 af = AF_LINK; 471 af = AF_LINK;
472 aflen = sizeof(struct sockaddr_dl); 472 aflen = sizeof(struct sockaddr_dl);
473 break; 473 break;
474 474
475#ifndef SMALL 475#ifndef SMALL
476 case K_MPLS: 476 case K_MPLS:
477 af = AF_MPLS; 477 af = AF_MPLS;
478 aflen = sizeof(struct sockaddr_mpls); 478 aflen = sizeof(struct sockaddr_mpls);
479 break; 479 break;
480 case K_TAG: 480 case K_TAG:
481 if (!--argc) 481 if (!--argc)
482 usage(1+*argv); 482 usage(1+*argv);
483 af = AF_MPLS; 483 af = AF_MPLS;
484 aflen = sizeof(struct sockaddr_mpls); 484 aflen = sizeof(struct sockaddr_mpls);
485 (void)getaddr(RTA_TAG, *++argv, 0, soup); 485 (void)getaddr(RTA_TAG, *++argv, 0, soup);
486 break; 486 break;
487#endif /* SMALL */ 487#endif /* SMALL */
488 488
489 case K_IFACE: 489 case K_IFACE:
490 case K_INTERFACE: 490 case K_INTERFACE:
491 iflag++; 491 iflag++;
492 break; 492 break;
493 case K_NOSTATIC: 493 case K_NOSTATIC:
494 flags &= ~RTF_STATIC; 494 flags &= ~RTF_STATIC;
495 break; 495 break;
496 case K_LOCK: 496 case K_LOCK:
497 locking = 1; 497 locking = 1;
498 break; 498 break;
499 case K_LOCKREST: 499 case K_LOCKREST:
500 lockrest = 1; 500 lockrest = 1;
501 break; 501 break;
502 case K_HOST: 502 case K_HOST:
503 forcehost++; 503 forcehost++;
504 break; 504 break;
505 case K_REJECT: 505 case K_REJECT:
506 flags |= RTF_REJECT; 506 flags |= RTF_REJECT;
507 break; 507 break;
508 case K_NOREJECT: 508 case K_NOREJECT:
509 flags &= ~RTF_REJECT; 509 flags &= ~RTF_REJECT;
510 break; 510 break;
511 case K_BLACKHOLE: 511 case K_BLACKHOLE:
512 flags |= RTF_BLACKHOLE; 512 flags |= RTF_BLACKHOLE;
513 break; 513 break;
514 case K_NOBLACKHOLE: 514 case K_NOBLACKHOLE:
515 flags &= ~RTF_BLACKHOLE; 515 flags &= ~RTF_BLACKHOLE;
516 break; 516 break;
517 case K_PROTO1: 517 case K_PROTO1:
518 flags |= RTF_PROTO1; 518 flags |= RTF_PROTO1;
519 break; 519 break;
520 case K_PROTO2: 520 case K_PROTO2:
521 flags |= RTF_PROTO2; 521 flags |= RTF_PROTO2;
522 break; 522 break;
523 case K_PROXY: 523 case K_PROXY:
524 flags |= RTF_ANNOUNCE; 524 flags |= RTF_ANNOUNCE;
525 break; 525 break;
526 case K_CONNECTED: 526 case K_CONNECTED:
527 flags |= RTF_CONNECTED; 527 flags |= RTF_CONNECTED;
528 break; 528 break;
529 case K_NOCONNECTED: 529 case K_NOCONNECTED:
530 flags &= ~RTF_CONNECTED; 530 flags &= ~RTF_CONNECTED;
531 break; 531 break;
532 case K_STATIC: 532 case K_STATIC:
533 flags |= RTF_STATIC; 533 flags |= RTF_STATIC;
534 break; 534 break;
535 case K_IFA: 535 case K_IFA:
536 if (!--argc) 536 if (!--argc)
537 usage(1+*argv); 537 usage(1+*argv);
538 (void)getaddr(RTA_IFA, *++argv, 0, soup); 538 (void)getaddr(RTA_IFA, *++argv, 0, soup);
539 break; 539 break;
540 case K_IFP: 540 case K_IFP:
541 if (!--argc) 541 if (!--argc)
542 usage(1+*argv); 542 usage(1+*argv);
543 (void)getaddr(RTA_IFP, *++argv, 0, soup); 543 (void)getaddr(RTA_IFP, *++argv, 0, soup);
544 break; 544 break;
545 case K_GENMASK: 545 case K_GENMASK:
546 if (!--argc) 546 if (!--argc)
547 usage(1+*argv); 547 usage(1+*argv);
548 (void)getaddr(RTA_GENMASK, *++argv, 0, soup); 548 (void)getaddr(RTA_GENMASK, *++argv, 0, soup);
549 break; 549 break;
550 case K_GATEWAY: 550 case K_GATEWAY:
551 if (!--argc) 551 if (!--argc)
552 usage(1+*argv); 552 usage(1+*argv);
553 (void)getaddr(RTA_GATEWAY, *++argv, 0, soup); 553 (void)getaddr(RTA_GATEWAY, *++argv, 0, soup);
554 break; 554 break;
555 case K_DST: 555 case K_DST:
556 if (!--argc) 556 if (!--argc)
557 usage(1+*argv); 557 usage(1+*argv);
558 ishost = getaddr(RTA_DST, *++argv, &hp, soup); 558 ishost = getaddr(RTA_DST, *++argv, &hp, soup);
559 dest = *argv; 559 dest = *argv;
560 break; 560 break;
561 case K_NETMASK: 561 case K_NETMASK:
562 if (!--argc) 562 if (!--argc)
563 usage(1+*argv); 563 usage(1+*argv);
564 (void)getaddr(RTA_NETMASK, *++argv, 0, soup); 564 (void)getaddr(RTA_NETMASK, *++argv, 0, soup);
565 /* FALLTHROUGH */ 565 /* FALLTHROUGH */
566 case K_NET: 566 case K_NET:
567 forcenet++; 567 forcenet++;
568 break; 568 break;
569 case K_PREFIXLEN: 569 case K_PREFIXLEN:
570 if (!--argc) 570 if (!--argc)
571 usage(1+*argv); 571 usage(1+*argv);
572 ishost = prefixlen(*++argv, soup); 572 ishost = prefixlen(*++argv, soup);
573 break; 573 break;
574 case K_MTU: 574 case K_MTU:
575 case K_HOPCOUNT: 575 case K_HOPCOUNT:
576 case K_EXPIRE: 576 case K_EXPIRE:
577 case K_RECVPIPE: 577 case K_RECVPIPE:
578 case K_SENDPIPE: 578 case K_SENDPIPE:
579 case K_SSTHRESH: 579 case K_SSTHRESH:
580 case K_RTT: 580 case K_RTT:
581 case K_RTTVAR: 581 case K_RTTVAR:
582 if (!--argc) 582 if (!--argc)
583 usage(1+*argv); 583 usage(1+*argv);
584 set_metric(*++argv, key); 584 set_metric(*++argv, key);
585 break; 585 break;
586 default: 586 default:
587 usage(1+*argv); 587 usage(1+*argv);
588 } 588 }
589 } else { 589 } else {
590 if ((rtm_addrs & RTA_DST) == 0) { 590 if ((rtm_addrs & RTA_DST) == 0) {
591 dest = *argv; 591 dest = *argv;
592 ishost = getaddr(RTA_DST, *argv, &hp, soup); 592 ishost = getaddr(RTA_DST, *argv, &hp, soup);
593 } else if ((rtm_addrs & RTA_GATEWAY) == 0) { 593 } else if ((rtm_addrs & RTA_GATEWAY) == 0) {
594 gateway = *argv; 594 gateway = *argv;
595 (void)getaddr(RTA_GATEWAY, *argv, &hp, soup); 595 (void)getaddr(RTA_GATEWAY, *argv, &hp, soup);
596 } else { 596 } else {
597 ret = atoi(*argv); 597 ret = atoi(*argv);
598 598
599 if (ret == 0) { 599 if (ret == 0) {
600 if (strcmp(*argv, "0") == 0) { 600 if (strcmp(*argv, "0") == 0) {
601 if (!qflag) { 601 if (!qflag) {
602 warnx("%s, %s", 602 warnx("%s, %s",
603 "old usage of trailing 0", 603 "old usage of trailing 0",
604 "assuming route to if"); 604 "assuming route to if");
605 } 605 }
606 } else 606 } else
607 usage(NULL); 607 usage(NULL);
608 iflag = 1; 608 iflag = 1;
609 continue; 609 continue;
610 } else if (ret > 0 && ret < 10) { 610 } else if (ret > 0 && ret < 10) {
611 if (!qflag) { 611 if (!qflag) {
612 warnx("%s, %s", 612 warnx("%s, %s",
613 "old usage of trailing digit", 613 "old usage of trailing digit",
614 "assuming route via gateway"); 614 "assuming route via gateway");
615 } 615 }
616 iflag = 0; 616 iflag = 0;
617 continue; 617 continue;
618 } 618 }
619 (void)getaddr(RTA_NETMASK, *argv, 0, soup); 619 (void)getaddr(RTA_NETMASK, *argv, 0, soup);
620 } 620 }
621 } 621 }
622 } 622 }
623 if ((rtm_addrs & RTA_DST) == 0) 623 if ((rtm_addrs & RTA_DST) == 0)
624 errx(EXIT_FAILURE, "missing destination specification"); 624 errx(EXIT_FAILURE, "missing destination specification");
625 if (*cmd == 'a' && (rtm_addrs & RTA_GATEWAY) == 0) 625 if (*cmd == 'a' && (rtm_addrs & RTA_GATEWAY) == 0)
626 errx(EXIT_FAILURE, "missing gateway specification"); 626 errx(EXIT_FAILURE, "missing gateway specification");
627 if (forcehost && forcenet) 627 if (forcehost && forcenet)
628 errx(EXIT_FAILURE, "-host and -net conflict"); 628 errx(EXIT_FAILURE, "-host and -net conflict");
629 else if (forcehost) 629 else if (forcehost)
630 ishost = 1; 630 ishost = 1;
631 else if (forcenet) 631 else if (forcenet)
632 ishost = 0; 632 ishost = 0;
633 flags |= RTF_UP; 633 flags |= RTF_UP;
634 if (ishost) 634 if (ishost)
635 flags |= RTF_HOST; 635 flags |= RTF_HOST;
636 if (iflag == 0) 636 if (iflag == 0)
637 flags |= RTF_GATEWAY; 637 flags |= RTF_GATEWAY;
638 for (attempts = 1; ; attempts++) { 638 for (attempts = 1; ; attempts++) {
639 errno = 0; 639 errno = 0;
640 if ((ret = rtmsg(*cmd, flags, soup)) == 0) 640 if ((ret = rtmsg(*cmd, flags, soup)) == 0)
641 break; 641 break;
642 if (errno != ENETUNREACH && errno != ESRCH) 642 if (errno != ENETUNREACH && errno != ESRCH)
643 break; 643 break;
644 if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) { 644 if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) {
645 hp->h_addr_list++; 645 hp->h_addr_list++;
646 memmove(&soup->so_gate->sin.sin_addr, hp->h_addr_list[0], 646 memmove(&soup->so_gate->sin.sin_addr, hp->h_addr_list[0],
647 hp->h_length); 647 hp->h_length);
648 } else 648 } else
649 break; 649 break;
650 } 650 }
651 if (*cmd == 'g' || qflag) 651 if (*cmd == 'g' || qflag)
652 goto out; 652 goto out;
653 653
654 oerrno = errno; 654 oerrno = errno;
655 (void)printf("%s %s %s", cmd, ishost? "host" : "net", dest); 655 (void)printf("%s %s %s", cmd, ishost? "host" : "net", dest);
656 if (*gateway) { 656 if (*gateway) {
657 (void)printf(": gateway %s", gateway); 657 (void)printf(": gateway %s", gateway);
658 if (attempts > 1 && ret == 0 && af == AF_INET) 658 if (attempts > 1 && ret == 0 && af == AF_INET)
659 (void)printf(" (%s)", 659 (void)printf(" (%s)",
660 inet_ntoa(soup->so_gate->sin.sin_addr)); 660 inet_ntoa(soup->so_gate->sin.sin_addr));
661 } 661 }
662 if (ret == 0) 662 if (ret == 0)
663 (void)printf("\n"); 663 (void)printf("\n");
664 else 664 else
665 (void)printf(": %s\n", route_strerror(oerrno)); 665 (void)printf(": %s\n", route_strerror(oerrno));
666out: 666out:
667 free(sou.so_dst); 667 free(sou.so_dst);
668 free(sou.so_gate); 668 free(sou.so_gate);
669 free(sou.so_mask); 669 free(sou.so_mask);
670 free(sou.so_genmask); 670 free(sou.so_genmask);
671 free(sou.so_ifa); 671 free(sou.so_ifa);
672 free(sou.so_ifp); 672 free(sou.so_ifp);
673 free(sou.so_mpls); 673 free(sou.so_mpls);
674 674
675 return ret != 0; 675 return ret != 0;
676} 676}
677 677
678static void 678static void
679inet_makenetandmask(const u_int32_t net, struct sockaddr_in * const isin, 679inet_makenetandmask(const u_int32_t net, struct sockaddr_in * const isin,
680 struct sou *soup) 680 struct sou *soup)
681{ 681{
682 struct sockaddr_in *sin; 682 struct sockaddr_in *sin;
683 u_int32_t addr, mask = 0; 683 u_int32_t addr, mask = 0;
684 char *cp; 684 char *cp;
685 685
686 rtm_addrs |= RTA_NETMASK; 686 rtm_addrs |= RTA_NETMASK;
687 if (net == 0) 687 if (net == 0)
688 mask = addr = 0; 688 mask = addr = 0;
689 else if (net < 128) { 689 else if (net < 128) {
690 addr = net << IN_CLASSA_NSHIFT; 690 addr = net << IN_CLASSA_NSHIFT;
691 mask = IN_CLASSA_NET; 691 mask = IN_CLASSA_NET;
692 } else if (net < 192) { 692 } else if (net < 192) {
693 addr = net << IN_CLASSA_NSHIFT; 693 addr = net << IN_CLASSA_NSHIFT;
694 mask = IN_CLASSB_NET; 694 mask = IN_CLASSB_NET;
695 } else if (net < 224) { 695 } else if (net < 224) {
696 addr = net << IN_CLASSA_NSHIFT; 696 addr = net << IN_CLASSA_NSHIFT;
697 mask = IN_CLASSC_NET; 697 mask = IN_CLASSC_NET;
698 } else if (net < 256) { 698 } else if (net < 256) {
699 addr = net << IN_CLASSA_NSHIFT; 699 addr = net << IN_CLASSA_NSHIFT;
700 mask = IN_CLASSD_NET; 700 mask = IN_CLASSD_NET;
701 } else if (net < 49152) { /* 192 * 256 */ 701 } else if (net < 49152) { /* 192 * 256 */
702 addr = net << IN_CLASSB_NSHIFT; 702 addr = net << IN_CLASSB_NSHIFT;
703 mask = IN_CLASSB_NET; 703 mask = IN_CLASSB_NET;
704 } else if (net < 57344) { /* 224 * 256 */ 704 } else if (net < 57344) { /* 224 * 256 */
705 addr = net << IN_CLASSB_NSHIFT; 705 addr = net << IN_CLASSB_NSHIFT;
706 mask = IN_CLASSC_NET; 706 mask = IN_CLASSC_NET;
707 } else if (net < 65536) { 707 } else if (net < 65536) {
708 addr = net << IN_CLASSB_NSHIFT; 708 addr = net << IN_CLASSB_NSHIFT;
709 mask = IN_CLASSB_NET; 709 mask = IN_CLASSB_NET;
710 } else if (net < 14680064L) { /* 224 * 65536 */ 710 } else if (net < 14680064L) { /* 224 * 65536 */
711 addr = net << IN_CLASSC_NSHIFT; 711 addr = net << IN_CLASSC_NSHIFT;
712 mask = IN_CLASSC_NET; 712 mask = IN_CLASSC_NET;
713 } else if (net < 16777216L) {  713 } else if (net < 16777216L) {
714 addr = net << IN_CLASSC_NSHIFT; 714 addr = net << IN_CLASSC_NSHIFT;
715 mask = IN_CLASSD_NET; 715 mask = IN_CLASSD_NET;
716 } else { 716 } else {
717 addr = net; 717 addr = net;
718 if ((addr & IN_CLASSA_HOST) == 0) 718 if ((addr & IN_CLASSA_HOST) == 0)
719 mask = IN_CLASSA_NET; 719 mask = IN_CLASSA_NET;
720 else if ((addr & IN_CLASSB_HOST) == 0) 720 else if ((addr & IN_CLASSB_HOST) == 0)
721 mask = IN_CLASSB_NET; 721 mask = IN_CLASSB_NET;
722 else if ((addr & IN_CLASSC_HOST) == 0) 722 else if ((addr & IN_CLASSC_HOST) == 0)
723 mask = IN_CLASSC_NET; 723 mask = IN_CLASSC_NET;
724 else 724 else
725 mask = -1; 725 mask = -1;
726 } 726 }
727 isin->sin_addr.s_addr = htonl(addr); 727 isin->sin_addr.s_addr = htonl(addr);
728 sin = &soup->so_mask->sin; 728 sin = &soup->so_mask->sin;
729 sin->sin_addr.s_addr = htonl(mask); 729 sin->sin_addr.s_addr = htonl(mask);
730 sin->sin_len = 0; 730 sin->sin_len = 0;
731 sin->sin_family = 0; 731 sin->sin_family = 0;
732 cp = (char *)(&sin->sin_addr + 1); 732 cp = (char *)(&sin->sin_addr + 1);
733 while (*--cp == 0 && cp > (char *)sin) 733 while (*--cp == 0 && cp > (char *)sin)
734 ; 734 ;
735 sin->sin_len = 1 + cp - (char *)sin; 735 sin->sin_len = 1 + cp - (char *)sin;
736 sin->sin_family = AF_INET; 736 sin->sin_family = AF_INET;
737} 737}
738 738
739#ifdef INET6 739#ifdef INET6
740/* 740/*
741 * XXX the function may need more improvement... 741 * XXX the function may need more improvement...
742 */ 742 */
743static int 743static int
744inet6_makenetandmask(const struct sockaddr_in6 * const sin6, struct sou *soup) 744inet6_makenetandmask(const struct sockaddr_in6 * const sin6, struct sou *soup)
745{ 745{
746 const char *plen; 746 const char *plen;
747 struct in6_addr in6; 747 struct in6_addr in6;
748 748
749 plen = NULL; 749 plen = NULL;
750 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 750 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
751 sin6->sin6_scope_id == 0) { 751 sin6->sin6_scope_id == 0) {
752 plen = "0"; 752 plen = "0";
753 } else if ((sin6->sin6_addr.s6_addr[0] & 0xe0) == 0x20) { 753 } else if ((sin6->sin6_addr.s6_addr[0] & 0xe0) == 0x20) {
754 /* aggregatable global unicast - RFC2374 */ 754 /* aggregatable global unicast - RFC2374 */
755 memset(&in6, 0, sizeof(in6)); 755 memset(&in6, 0, sizeof(in6));
756 if (!memcmp(&sin6->sin6_addr.s6_addr[8], &in6.s6_addr[8], 8)) 756 if (!memcmp(&sin6->sin6_addr.s6_addr[8], &in6.s6_addr[8], 8))
757 plen = "64"; 757 plen = "64";
758 } 758 }
759 759
760 if (!plen || strcmp(plen, "128") == 0) 760 if (!plen || strcmp(plen, "128") == 0)
761 return 1; 761 return 1;
762 else { 762 else {
763 rtm_addrs |= RTA_NETMASK; 763 rtm_addrs |= RTA_NETMASK;
764 (void)prefixlen(plen, soup); 764 (void)prefixlen(plen, soup);
765 return 0; 765 return 0;
766 } 766 }
767} 767}
768#endif 768#endif
769 769
770/* 770/*
771 * Interpret an argument as a network address of some kind, 771 * Interpret an argument as a network address of some kind,
772 * returning 1 if a host address, 0 if a network address. 772 * returning 1 if a host address, 0 if a network address.
773 */ 773 */
774static int 774static int
775getaddr(int which, const char *s, struct hostent **hpp, struct sou *soup) 775getaddr(int which, const char *s, struct hostent **hpp, struct sou *soup)
776{ 776{
777 sup su; 777 sup su;
778 struct hostent *hp; 778 struct hostent *hp;
779 struct netent *np; 779 struct netent *np;
780 u_int32_t val; 780 u_int32_t val;
781 char *t; 781 char *t;
782 int afamily; /* local copy of af so we can change it */ 782 int afamily; /* local copy of af so we can change it */
783 783
784 if (af == AF_UNSPEC) { 784 if (af == AF_UNSPEC) {
785 af = AF_INET; 785 af = AF_INET;
786 aflen = sizeof(struct sockaddr_in); 786 aflen = sizeof(struct sockaddr_in);
787 } 787 }
788 afamily = af; 788 afamily = af;
789 rtm_addrs |= which; 789 rtm_addrs |= which;
790 switch (which) { 790 switch (which) {
791 case RTA_DST: 791 case RTA_DST:
792 su = soup->so_dst; 792 su = soup->so_dst;
793 break; 793 break;
794 case RTA_GATEWAY: 794 case RTA_GATEWAY:
795 su = soup->so_gate; 795 su = soup->so_gate;
796 break; 796 break;
797 case RTA_NETMASK: 797 case RTA_NETMASK:
798 su = soup->so_mask; 798 su = soup->so_mask;
799 break; 799 break;
800 case RTA_GENMASK: 800 case RTA_GENMASK:
801 su = soup->so_genmask; 801 su = soup->so_genmask;
802 break; 802 break;
803 case RTA_IFP: 803 case RTA_IFP:
804 su = soup->so_ifp; 804 su = soup->so_ifp;
805 afamily = AF_LINK; 805 afamily = AF_LINK;
806 break; 806 break;
807 case RTA_IFA: 807 case RTA_IFA:
808 su = soup->so_ifa; 808 su = soup->so_ifa;
809 su->sa.sa_family = af; 809 su->sa.sa_family = af;
810 break; 810 break;
811#ifndef SMALL 811#ifndef SMALL
812 case RTA_TAG: 812 case RTA_TAG:
813 su = soup->so_mpls; 813 su = soup->so_mpls;
814 afamily = AF_MPLS; 814 afamily = AF_MPLS;
815 break; 815 break;
816#endif 816#endif
817 default: 817 default:
818 su = NULL; 818 su = NULL;
819 usage("Internal Error"); 819 usage("Internal Error");
820 /*NOTREACHED*/ 820 /*NOTREACHED*/
821 } 821 }
822 su->sa.sa_len = aflen; 822 su->sa.sa_len = aflen;
823 su->sa.sa_family = afamily; /* cases that don't want it have left already */ 823 su->sa.sa_family = afamily; /* cases that don't want it have left already */
824 if (strcmp(s, "default") == 0) { 824 if (strcmp(s, "default") == 0) {
825 switch (which) { 825 switch (which) {
826 case RTA_DST: 826 case RTA_DST:
827 forcenet++; 827 forcenet++;
828 (void)getaddr(RTA_NETMASK, s, 0, soup); 828 (void)getaddr(RTA_NETMASK, s, 0, soup);
829 break; 829 break;
830 case RTA_NETMASK: 830 case RTA_NETMASK:
831 case RTA_GENMASK: 831 case RTA_GENMASK:
832 su->sa.sa_len = 0; 832 su->sa.sa_len = 0;
833 } 833 }
834 return 0; 834 return 0;
835 } 835 }
836 switch (afamily) { 836 switch (afamily) {
837#ifdef INET6 837#ifdef INET6
838 case AF_INET6: 838 case AF_INET6:
839 { 839 {
840 struct addrinfo hints, *res; 840 struct addrinfo hints, *res;
841 char *slash = 0; 841 char *slash = 0;
842 842
843 if (which == RTA_DST && (slash = (strrchr(s, '/'))) != 0) 843 if (which == RTA_DST && (slash = (strrchr(s, '/'))) != 0)
844 *slash = '\0'; 844 *slash = '\0';
845 memset(&hints, 0, sizeof(hints)); 845 memset(&hints, 0, sizeof(hints));
846 hints.ai_family = afamily; /*AF_INET6*/ 846 hints.ai_family = afamily; /*AF_INET6*/
847 hints.ai_flags = AI_NUMERICHOST; 847 hints.ai_flags = AI_NUMERICHOST;
848 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 848 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
849 if (getaddrinfo(s, "0", &hints, &res) != 0) { 849 if (getaddrinfo(s, "0", &hints, &res) != 0) {
850 hints.ai_flags = 0; 850 hints.ai_flags = 0;
851 if (slash) { 851 if (slash) {
852 *slash = '/'; 852 *slash = '/';
853 slash = 0; 853 slash = 0;
854 } 854 }
855 if (getaddrinfo(s, "0", &hints, &res) != 0) 855 if (getaddrinfo(s, "0", &hints, &res) != 0)
856 errx(EXIT_FAILURE, "%s: bad value", s); 856 errx(EXIT_FAILURE, "%s: bad value", s);
857 } 857 }
858 if (slash) 858 if (slash)
859 *slash = '/'; 859 *slash = '/';
860 if (sizeof(su->sin6) != res->ai_addrlen) 860 if (sizeof(su->sin6) != res->ai_addrlen)
861 errx(EXIT_FAILURE, "%s: bad value", s); 861 errx(EXIT_FAILURE, "%s: bad value", s);
862 if (res->ai_next) { 862 if (res->ai_next) {
863 errx(EXIT_FAILURE, 863 errx(EXIT_FAILURE,
864 "%s: address resolved to multiple values", s); 864 "%s: address resolved to multiple values", s);
865 } 865 }
866 memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6)); 866 memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6));
867 freeaddrinfo(res); 867 freeaddrinfo(res);
868 inet6_putscopeid(&su->sin6, INET6_IS_ADDR_LINKLOCAL| 868 inet6_putscopeid(&su->sin6, INET6_IS_ADDR_LINKLOCAL|
869 INET6_IS_ADDR_MC_LINKLOCAL); 869 INET6_IS_ADDR_MC_LINKLOCAL);
870 if (hints.ai_flags == AI_NUMERICHOST) { 870 if (hints.ai_flags == AI_NUMERICHOST) {
871 if (slash) 871 if (slash)
872 return prefixlen(slash + 1, soup); 872 return prefixlen(slash + 1, soup);
873 if (which == RTA_DST) 873 if (which == RTA_DST)
874 return inet6_makenetandmask(&su->sin6, soup); 874 return inet6_makenetandmask(&su->sin6, soup);
875 return 0; 875 return 0;
876 } else 876 } else
877 return 1; 877 return 1;
878 } 878 }
879#endif 879#endif
880 880
881 case PF_ROUTE: 881 case PF_ROUTE:
882 su->sa.sa_len = sizeof(*su); 882 su->sa.sa_len = sizeof(*su);
883 sockaddr(s, &su->sa); 883 sockaddr(s, &su->sa);
884 return 1; 884 return 1;
885 885
886#ifndef SMALL 886#ifndef SMALL
887 case AF_APPLETALK: 887 case AF_APPLETALK:
888 t = strchr (s, '.'); 888 t = strchr (s, '.');
889 if (!t) { 889 if (!t) {
890badataddr: 890badataddr:
891 errx(EXIT_FAILURE, "bad address: %s", s); 891 errx(EXIT_FAILURE, "bad address: %s", s);
892 } 892 }
893 val = atoi (s); 893 val = atoi (s);
894 if (val > 65535) 894 if (val > 65535)
895 goto badataddr; 895 goto badataddr;
896 su->sat.sat_addr.s_net = val; 896 su->sat.sat_addr.s_net = val;
897 val = atoi (t); 897 val = atoi (t);
898 if (val > 256) 898 if (val > 256)
899 goto badataddr; 899 goto badataddr;
900 su->sat.sat_addr.s_node = val; 900 su->sat.sat_addr.s_node = val;
901 rtm_addrs |= RTA_NETMASK; 901 rtm_addrs |= RTA_NETMASK;
902 return(forcehost || su->sat.sat_addr.s_node != 0); 902 return(forcehost || su->sat.sat_addr.s_node != 0);
903 case AF_MPLS: 903 case AF_MPLS:
904 if (which == RTA_DST) 904 if (which == RTA_DST)
905 soup->so_dst = readtag(su, s); 905 soup->so_dst = readtag(su, s);
906 else if (which == RTA_TAG) 906 else if (which == RTA_TAG)
907 soup->so_mpls = readtag(su, s); 907 soup->so_mpls = readtag(su, s);
908 else 908 else
909 errx(EXIT_FAILURE, "MPLS can be used only as " 909 errx(EXIT_FAILURE, "MPLS can be used only as "
910 "DST or TAG"); 910 "DST or TAG");
911 return 1; 911 return 1;
912#endif 912#endif
913 913
914 case AF_LINK: 914 case AF_LINK:
915 link_addr(s, &su->sdl); 915 link_addr(s, &su->sdl);
916 return 1; 916 return 1;
917 917
918 case AF_INET: 918 case AF_INET:
919 default: 919 default:
920 break; 920 break;
921 } 921 }
922 922
923 if (hpp == NULL) 923 if (hpp == NULL)
924 hpp = &hp; 924 hpp = &hp;
925 *hpp = NULL; 925 *hpp = NULL;
926 926
927 if ((t = strchr(s, '/')) != NULL && which == RTA_DST) { 927 if ((t = strchr(s, '/')) != NULL && which == RTA_DST) {
928 *t = '\0'; 928 *t = '\0';
929 if (forcenet == 0) { 929 if (forcenet == 0) {
930 if ((val = inet_addr(s)) != INADDR_NONE) { 930 if ((val = inet_addr(s)) != INADDR_NONE) {
931 inet_makenetandmask(htonl(val), &su->sin, soup); 931 inet_makenetandmask(htonl(val), &su->sin, soup);
932 return prefixlen(&t[1], soup); 932 return prefixlen(&t[1], soup);
933 } 933 }
934 } else { 934 } else {
935 if ((val = inet_network(s)) != INADDR_NONE) { 935 if ((val = inet_network(s)) != INADDR_NONE) {
936 inet_makenetandmask(val, &su->sin, soup); 936 inet_makenetandmask(val, &su->sin, soup);
937 return prefixlen(&t[1], soup); 937 return prefixlen(&t[1], soup);
938 } 938 }
939 } 939 }
940 *t = '/'; 940 *t = '/';
941 } 941 }
942 if (inet_aton(s, &su->sin.sin_addr) && 942 if (inet_aton(s, &su->sin.sin_addr) &&
943 (which != RTA_DST || forcenet == 0)) { 943 (which != RTA_DST || forcenet == 0)) {
944 val = su->sin.sin_addr.s_addr; 944 val = su->sin.sin_addr.s_addr;
945 if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY) 945 if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY)
946 return 1; 946 return 1;
947 else { 947 else {
948 val = ntohl(val); 948 val = ntohl(val);
949 goto netdone; 949 goto netdone;
950 } 950 }
951 } 951 }
952 if ((val = inet_network(s)) != INADDR_NONE || 952 if ((val = inet_network(s)) != INADDR_NONE ||
953 ((np = getnetbyname(s)) != NULL && (val = np->n_net) != 0)) { 953 ((np = getnetbyname(s)) != NULL && (val = np->n_net) != 0)) {
954netdone: 954netdone:
955 if (which == RTA_DST) 955 if (which == RTA_DST)
956 inet_makenetandmask(val, &su->sin, soup); 956 inet_makenetandmask(val, &su->sin, soup);
957 return 0; 957 return 0;
958 } 958 }
959 hp = gethostbyname(s); 959 hp = gethostbyname(s);
960 if (hp) { 960 if (hp) {
961 *hpp = hp; 961 *hpp = hp;
962 su->sin.sin_family = hp->h_addrtype; 962 su->sin.sin_family = hp->h_addrtype;
963 memmove(&su->sin.sin_addr, hp->h_addr, hp->h_length); 963 memmove(&su->sin.sin_addr, hp->h_addr, hp->h_length);
964 return 1; 964 return 1;
965 } 965 }
966 errx(EXIT_FAILURE, "%s: bad value", s); 966 errx(EXIT_FAILURE, "%s: bad value", s);
967 /*NOTREACHED*/ 967 /*NOTREACHED*/
968} 968}
969 969
970#ifndef SMALL 970#ifndef SMALL
971static sup 971static sup
972readtag(sup su, const char *s) 972readtag(sup su, const char *s)
973{ 973{
974 char *p, *n, *norig; 974 char *p, *n, *norig;
975 int mplssize = 0; 975 int mplssize = 0;
976 sup retsu = su; 976 sup retsu = su;
977 977
978 n = strdup(s); 978 n = strdup(s);
979 if (n == NULL) 979 if (n == NULL)
980 errx(EXIT_FAILURE, "%s: Cannot allocate memory", s); 980 errx(EXIT_FAILURE, "%s: Cannot allocate memory", s);
981 norig = n; 981 norig = n;
982 for (uint i = 0; i < strlen(n); i++) 982 for (uint i = 0; i < strlen(n); i++)
983 if(n[i] == ',') 983 if(n[i] == ',')
984 mplssize++; 984 mplssize++;
985 985
986#define MPLS_NEW_SIZE (sizeof(struct sockaddr_mpls) + \ 986#define MPLS_NEW_SIZE (sizeof(struct sockaddr_mpls) + \
987 mplssize * sizeof(union mpls_shim)) 987 mplssize * sizeof(union mpls_shim))
988 988
989 if (mplssize != 0 && sizeof(union sockunion) < MPLS_NEW_SIZE) { 989 if (mplssize != 0 && sizeof(union sockunion) < MPLS_NEW_SIZE) {
990 free(su); 990 free(su);
991 retsu = malloc(MPLS_NEW_SIZE); 991 retsu = malloc(MPLS_NEW_SIZE);
992 retsu->smpls.smpls_family = AF_MPLS; 992 retsu->smpls.smpls_family = AF_MPLS;
993 } 993 }
994 retsu->smpls.smpls_len = MPLS_NEW_SIZE; 994 retsu->smpls.smpls_len = MPLS_NEW_SIZE;
995 mplssize = 0; 995 mplssize = 0;
996 while ((p = strchr(n, ',')) != NULL) { 996 while ((p = strchr(n, ',')) != NULL) {
997 p[0] = '\0'; 997 p[0] = '\0';
998 addtag(retsu, n, mplssize); 998 addtag(retsu, n, mplssize);
999 n = p + 1; 999 n = p + 1;
1000 mplssize++; 1000 mplssize++;
1001 } 1001 }
1002 addtag(retsu, n, mplssize); 1002 addtag(retsu, n, mplssize);
1003 1003
1004 free(norig); 1004 free(norig);
1005 return retsu; 1005 return retsu;
1006} 1006}
1007 1007
1008static void 1008static void
1009addtag(sup su, const char *s, int where) 1009addtag(sup su, const char *s, int where)
1010{ 1010{
1011 union mpls_shim *ms = &su->smpls.smpls_addr; 1011 union mpls_shim *ms = &su->smpls.smpls_addr;
1012 1012
1013 if (atoi(s) < 0 || atoi(s) >= (1 << 20)) 1013 if (atoi(s) < 0 || atoi(s) >= (1 << 20))
1014 errx(EXIT_FAILURE, "%s: Bad tag", s); 1014 errx(EXIT_FAILURE, "%s: Bad tag", s);
1015 ms[where].s_addr = 0; 1015 ms[where].s_addr = 0;
1016 ms[where].shim.label = atoi(s); 1016 ms[where].shim.label = atoi(s);
1017 ms[where].s_addr = htonl(ms[where].s_addr); 1017 ms[where].s_addr = htonl(ms[where].s_addr);
1018} 1018}
1019#endif /* SMALL */ 1019#endif /* SMALL */
1020 1020
1021int 1021int
1022prefixlen(const char *s, struct sou *soup) 1022prefixlen(const char *s, struct sou *soup)
1023{ 1023{
1024 int max, len = atoi(s); 1024 int max, len = atoi(s);
1025#ifdef INET6 1025#ifdef INET6
1026 int q, r; 1026 int q, r;
1027#endif 1027#endif
1028 1028
1029 switch (af) { 1029 switch (af) {
1030 case AF_INET: 1030 case AF_INET:
1031 max = sizeof(struct in_addr) * 8; 1031 max = sizeof(struct in_addr) * 8;
1032 break; 1032 break;
1033#ifdef INET6 1033#ifdef INET6
1034 case AF_INET6: 1034 case AF_INET6:
1035 max = sizeof(struct in6_addr) * 8; 1035 max = sizeof(struct in6_addr) * 8;
1036 break; 1036 break;
1037#endif 1037#endif
1038 default: 1038 default:
1039 errx(EXIT_FAILURE, "prefixlen is not supported with af %d", af); 1039 errx(EXIT_FAILURE, "prefixlen is not supported with af %d", af);
1040 /*NOTREACHED*/ 1040 /*NOTREACHED*/
1041 } 1041 }
1042 1042
1043 rtm_addrs |= RTA_NETMASK;  1043 rtm_addrs |= RTA_NETMASK;
1044 if (len < -1 || len > max) 1044 if (len < -1 || len > max)
1045 errx(EXIT_FAILURE, "%s: bad value", s); 1045 errx(EXIT_FAILURE, "%s: bad value", s);
1046  1046
1047#ifdef INET6 1047#ifdef INET6
1048 q = len >> 3; 1048 q = len >> 3;
1049 r = len & 7; 1049 r = len & 7;
1050#endif 1050#endif
1051 switch (af) { 1051 switch (af) {
1052 case AF_INET: 1052 case AF_INET:
1053 memset(soup->so_mask, 0, sizeof(*soup->so_mask)); 1053 memset(soup->so_mask, 0, sizeof(*soup->so_mask));
1054 soup->so_mask->sin.sin_family = AF_INET; 1054 soup->so_mask->sin.sin_family = AF_INET;
1055 soup->so_mask->sin.sin_len = sizeof(struct sockaddr_in); 1055 soup->so_mask->sin.sin_len = sizeof(struct sockaddr_in);
1056 soup->so_mask->sin.sin_addr.s_addr = (len == 0 ? 0 1056 soup->so_mask->sin.sin_addr.s_addr = (len == 0 ? 0
1057 : htonl(0xffffffff << (32 - len))); 1057 : htonl(0xffffffff << (32 - len)));
1058 break; 1058 break;
1059#ifdef INET6 1059#ifdef INET6
1060 case AF_INET6: 1060 case AF_INET6:
1061 soup->so_mask->sin6.sin6_family = AF_INET6; 1061 soup->so_mask->sin6.sin6_family = AF_INET6;
1062 soup->so_mask->sin6.sin6_len = sizeof(struct sockaddr_in6); 1062 soup->so_mask->sin6.sin6_len = sizeof(struct sockaddr_in6);
1063 memset(&soup->so_mask->sin6.sin6_addr, 0, 1063 memset(&soup->so_mask->sin6.sin6_addr, 0,
1064 sizeof(soup->so_mask->sin6.sin6_addr)); 1064 sizeof(soup->so_mask->sin6.sin6_addr));
1065 if (q > 0) 1065 if (q > 0)
1066 memset(&soup->so_mask->sin6.sin6_addr, 0xff, q); 1066 memset(&soup->so_mask->sin6.sin6_addr, 0xff, q);
1067 if (r > 0) 1067 if (r > 0)
1068 *((u_char *)&soup->so_mask->sin6.sin6_addr + q) = 1068 *((u_char *)&soup->so_mask->sin6.sin6_addr + q) =
1069 (0xff00 >> r) & 0xff; 1069 (0xff00 >> r) & 0xff;
1070 break; 1070 break;
1071#endif 1071#endif
1072 } 1072 }
1073 return len == max; 1073 return len == max;
1074} 1074}
1075 1075
1076#ifndef SMALL 1076#ifndef SMALL
1077static void 1077static void
1078interfaces(void) 1078interfaces(void)
1079{ 1079{
1080 size_t needed; 1080 size_t needed;
1081 int mib[6]; 1081 int mib[6];
1082 char *buf, *lim, *next; 1082 char *buf, *lim, *next;
1083 struct rt_msghdr *rtm; 1083 struct rt_msghdr *rtm;
1084 1084
1085 mib[0] = CTL_NET; 1085 mib[0] = CTL_NET;
1086 mib[1] = PF_ROUTE; 1086 mib[1] = PF_ROUTE;
1087 mib[2] = 0; /* protocol */ 1087 mib[2] = 0; /* protocol */
1088 mib[3] = 0; /* wildcard address family */ 1088 mib[3] = 0; /* wildcard address family */
1089 mib[4] = NET_RT_IFLIST; 1089 mib[4] = NET_RT_IFLIST;
1090 mib[5] = 0; /* no flags */ 1090 mib[5] = 0; /* no flags */
1091 if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 1091 if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
1092 err(EXIT_FAILURE, "route-sysctl-estimate"); 1092 err(EXIT_FAILURE, "route-sysctl-estimate");
1093 if (needed) { 1093 if (needed) {
1094 if ((buf = malloc(needed)) == NULL) 1094 if ((buf = malloc(needed)) == NULL)
1095 err(EXIT_FAILURE, "malloc"); 1095 err(EXIT_FAILURE, "malloc");
1096 if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 1096 if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
1097 err(EXIT_FAILURE, 1097 err(EXIT_FAILURE,
1098 "actual retrieval of interface table"); 1098 "actual retrieval of interface table");
1099 } 1099 }
1100 lim = buf + needed; 1100 lim = buf + needed;
1101 for (next = buf; next < lim; next += rtm->rtm_msglen) { 1101 for (next = buf; next < lim; next += rtm->rtm_msglen) {
1102 rtm = (struct rt_msghdr *)next; 1102 rtm = (struct rt_msghdr *)next;
1103 print_rtmsg(rtm, rtm->rtm_msglen); 1103 print_rtmsg(rtm, rtm->rtm_msglen);
1104 } 1104 }
1105 free(buf); 1105 free(buf);
1106 } 1106 }
1107} 1107}
1108 1108
1109static void 1109static void
1110monitor(int argc, char * const *argv) 1110monitor(int argc, char * const *argv)
1111{ 1111{
1112 int i, n; 1112 int i, n;
1113 union { 1113 union {
1114 char msg[2048]; 1114 char msg[2048];
1115 struct rt_msghdr hdr; 1115 struct rt_msghdr hdr;
1116 } u; 1116 } u;
1117 int count = 0; 1117 int count = 0;
1118 1118
1119 /* usage: route monitor [-c <count>] */ 1119 /* usage: route monitor [-c <count>] */
1120 1120
1121 /* eat "monitor" */ 1121 /* eat "monitor" */
1122 argc -= 1; 1122 argc -= 1;
1123 argv += 1; 1123 argv += 1;
1124 1124
1125 /* parse [-c <count>] */ 1125 /* parse [-c <count>] */
1126 if (argc > 0) { 1126 if (argc > 0) {
1127 if (argc != 2) 1127 if (argc != 2)
1128 usage(argv[0]); 1128 usage(argv[0]);
1129 if (strcmp(argv[0], "-c") != 0) 1129 if (strcmp(argv[0], "-c") != 0)
1130 usage(argv[0]); 1130 usage(argv[0]);
1131 1131
1132 count = atoi(argv[1]); 1132 count = atoi(argv[1]);
1133 } 1133 }
1134 1134
1135 verbose = 1; 1135 verbose = 1;
1136 if (debugonly) { 1136 if (debugonly) {
1137 interfaces(); 1137 interfaces();
1138 exit(0); 1138 exit(0);
1139 } 1139 }
1140 for(i = 0; count == 0 || i < count; i++) { 1140 for(i = 0; count == 0 || i < count; i++) {
1141 time_t now; 1141 time_t now;
1142 n = prog_read(sock, &u, sizeof(u)); 1142 n = prog_read(sock, &u, sizeof(u));
1143 if (n == -1) { 1143 if (n == -1) {
1144 warn("read"); 1144 warn("read");
1145 continue; 1145 continue;
1146 } 1146 }
1147 now = time(NULL); 1147 now = time(NULL);
1148 (void)printf("got message of size %d on %s", n, ctime(&now)); 1148 (void)printf("got message of size %d on %s", n, ctime(&now));
1149 print_rtmsg(&u.hdr, n); 1149 print_rtmsg(&u.hdr, n);
1150 } 1150 }
1151} 1151}
1152 1152
1153#endif /* SMALL */ 1153#endif /* SMALL */
1154 1154
1155 1155
1156struct { 1156struct {
1157 struct rt_msghdr m_rtm; 1157 struct rt_msghdr m_rtm;
1158 char m_space[512]; 1158 char m_space[512];
1159} m_rtmsg; 1159} m_rtmsg;
1160 1160
1161static int 1161static int
1162rtmsg(int cmd, int flags, struct sou *soup) 1162rtmsg(int cmd, int flags, struct sou *soup)
1163{ 1163{
1164 static int seq; 1164 static int seq;
1165 int rlen; 1165 int rlen;
1166 char *cp = m_rtmsg.m_space; 1166 char *cp = m_rtmsg.m_space;
1167 int l; 1167 int l;
1168 1168
1169#define NEXTADDR(w, u) \ 1169#define NEXTADDR(w, u) \
1170 if (rtm_addrs & (w)) {\ 1170 if (rtm_addrs & (w)) {\
1171 l = RT_ROUNDUP(u->sa.sa_len); memmove(cp, u, l); cp += l;\ 1171 l = RT_ROUNDUP(u->sa.sa_len); memmove(cp, u, l); cp += l;\
1172 if (verbose && ! shortoutput) sodump(u,#u);\ 1172 if (verbose && ! shortoutput) sodump(u,#u);\
1173 } 1173 }
1174 1174
1175 errno = 0; 1175 errno = 0;
1176 memset(&m_rtmsg, 0, sizeof(m_rtmsg)); 1176 memset(&m_rtmsg, 0, sizeof(m_rtmsg));
1177 if (cmd == 'a') 1177 if (cmd == 'a')
1178 cmd = RTM_ADD; 1178 cmd = RTM_ADD;
1179 else if (cmd == 'c') 1179 else if (cmd == 'c')
1180 cmd = RTM_CHANGE; 1180 cmd = RTM_CHANGE;
1181 else if (cmd == 'g') { 1181 else if (cmd == 'g') {
1182#ifdef SMALL 1182#ifdef SMALL
1183 return -1; 1183 return -1;
1184#else /* SMALL */ 1184#else /* SMALL */
1185 cmd = RTM_GET; 1185 cmd = RTM_GET;
1186 if (soup->so_ifp->sa.sa_family == AF_UNSPEC) { 1186 if (soup->so_ifp->sa.sa_family == AF_UNSPEC) {
1187 soup->so_ifp->sa.sa_family = AF_LINK; 1187 soup->so_ifp->sa.sa_family = AF_LINK;
1188 soup->so_ifp->sa.sa_len = sizeof(struct sockaddr_dl); 1188 soup->so_ifp->sa.sa_len = sizeof(struct sockaddr_dl);
1189 rtm_addrs |= RTA_IFP; 1189 rtm_addrs |= RTA_IFP;
1190 } 1190 }
1191#endif /* SMALL */ 1191#endif /* SMALL */
1192 } else 1192 } else
1193 cmd = RTM_DELETE; 1193 cmd = RTM_DELETE;
1194#define rtm m_rtmsg.m_rtm 1194#define rtm m_rtmsg.m_rtm
1195 rtm.rtm_type = cmd; 1195 rtm.rtm_type = cmd;
1196 rtm.rtm_flags = flags; 1196 rtm.rtm_flags = flags;
1197 rtm.rtm_version = RTM_VERSION; 1197 rtm.rtm_version = RTM_VERSION;
1198 rtm.rtm_seq = ++seq; 1198 rtm.rtm_seq = ++seq;
1199 rtm.rtm_addrs = rtm_addrs; 1199 rtm.rtm_addrs = rtm_addrs;
1200 rtm.rtm_rmx = rt_metrics; 1200 rtm.rtm_rmx = rt_metrics;
1201 rtm.rtm_inits = rtm_inits; 1201 rtm.rtm_inits = rtm_inits;
1202 1202
1203 if (rtm_addrs & RTA_NETMASK) 1203 if (rtm_addrs & RTA_NETMASK)
1204 mask_addr(soup); 1204 mask_addr(soup);
1205 NEXTADDR(RTA_DST, soup->so_dst); 1205 NEXTADDR(RTA_DST, soup->so_dst);
1206 NEXTADDR(RTA_GATEWAY, soup->so_gate); 1206 NEXTADDR(RTA_GATEWAY, soup->so_gate);
1207 NEXTADDR(RTA_NETMASK, soup->so_mask); 1207 NEXTADDR(RTA_NETMASK, soup->so_mask);
1208 NEXTADDR(RTA_GENMASK, soup->so_genmask); 1208 NEXTADDR(RTA_GENMASK, soup->so_genmask);
1209 NEXTADDR(RTA_IFP, soup->so_ifp); 1209 NEXTADDR(RTA_IFP, soup->so_ifp);
1210 NEXTADDR(RTA_IFA, soup->so_ifa); 1210 NEXTADDR(RTA_IFA, soup->so_ifa);
1211#ifndef SMALL 1211#ifndef SMALL
1212 NEXTADDR(RTA_TAG, soup->so_mpls); 1212 NEXTADDR(RTA_TAG, soup->so_mpls);
1213#endif 1213#endif
1214 rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; 1214 rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
1215 if (verbose && ! shortoutput) { 1215 if (verbose && ! shortoutput) {
1216 if (rtm_addrs) 1216 if (rtm_addrs)
1217 putchar('\n'); 1217 putchar('\n');
1218 print_rtmsg(&rtm, l); 1218 print_rtmsg(&rtm, l);
1219 } 1219 }
1220 if (debugonly) 1220 if (debugonly)
1221 return 0; 1221 return 0;
1222 do { 1222 do {
1223 rlen = prog_write(sock, (char *)&m_rtmsg, l); 1223 rlen = prog_write(sock, (char *)&m_rtmsg, l);
1224 } while (rlen == -1 && errno == ENOBUFS); 1224 } while (rlen == -1 && errno == ENOBUFS);
1225 if (rlen == -1) { 1225 if (rlen == -1) {
1226 warnx("writing to routing socket: %s", route_strerror(errno)); 1226 warnx("writing to routing socket: %s", route_strerror(errno));
1227 return -1; 1227 return -1;
1228 } 1228 }
1229 if (rlen < l) { 1229 if (rlen < l) {
1230 warnx("write to routing socket, got %d for rlen", rlen); 1230 warnx("write to routing socket, got %d for rlen", rlen);
1231 return 1; 1231 return 1;
1232 } 1232 }
1233#ifndef SMALL 1233#ifndef SMALL
1234 if (cmd == RTM_GET) { 1234 if (cmd == RTM_GET) {
1235 do { 1235 do {
1236 l = prog_read(sock, 1236 l = prog_read(sock,
1237 (char *)&m_rtmsg, sizeof(m_rtmsg)); 1237 (char *)&m_rtmsg, sizeof(m_rtmsg));
1238 } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); 1238 } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
1239 if (l < 0) 1239 if (l < 0)
1240 err(EXIT_FAILURE, "read from routing socket"); 1240 err(EXIT_FAILURE, "read from routing socket");
1241 else 1241 else
1242 return print_getmsg(&rtm, l, soup); 1242 return print_getmsg(&rtm, l, soup);
1243 } 1243 }
1244#endif /* SMALL */ 1244#endif /* SMALL */
1245#undef rtm 1245#undef rtm
1246 return 0; 1246 return 0;
1247} 1247}
1248 1248
1249static void 1249static void
1250mask_addr(struct sou *soup) 1250mask_addr(struct sou *soup)
1251{ 1251{
1252 int olen = soup->so_mask->sa.sa_len; 1252 int olen = soup->so_mask->sa.sa_len;
1253 char *cp1 = olen + (char *)soup->so_mask, *cp2; 1253 char *cp1 = olen + (char *)soup->so_mask, *cp2;
1254 1254
1255 for (soup->so_mask->sa.sa_len = 0; cp1 > (char *)soup->so_mask; ) 1255 for (soup->so_mask->sa.sa_len = 0; cp1 > (char *)soup->so_mask; )
1256 if (*--cp1 != 0) { 1256 if (*--cp1 != 0) {
1257 soup->so_mask->sa.sa_len = 1 + cp1 - (char *)soup->so_mask; 1257 soup->so_mask->sa.sa_len = 1 + cp1 - (char *)soup->so_mask;
1258 break; 1258 break;
1259 } 1259 }
1260 if ((rtm_addrs & RTA_DST) == 0) 1260 if ((rtm_addrs & RTA_DST) == 0)
1261 return; 1261 return;
1262 switch (soup->so_dst->sa.sa_family) { 1262 switch (soup->so_dst->sa.sa_family) {
1263 case AF_INET: 1263 case AF_INET:
1264#ifdef INET6 1264#ifdef INET6
1265 case AF_INET6: 1265 case AF_INET6:
1266#endif 1266#endif
1267#ifndef SMALL 1267#ifndef SMALL
1268 case AF_APPLETALK: 1268 case AF_APPLETALK:
1269#endif /* SMALL */ 1269#endif /* SMALL */
1270 case 0: 1270 case 0:
1271 return; 1271 return;
1272 } 1272 }
1273 cp1 = soup->so_mask->sa.sa_len + 1 + (char *)soup->so_dst; 1273 cp1 = soup->so_mask->sa.sa_len + 1 + (char *)soup->so_dst;
1274 cp2 = soup->so_dst->sa.sa_len + 1 + (char *)soup->so_dst; 1274 cp2 = soup->so_dst->sa.sa_len + 1 + (char *)soup->so_dst;
1275 while (cp2 > cp1) 1275 while (cp2 > cp1)
1276 *--cp2 = 0; 1276 *--cp2 = 0;
1277 cp2 = soup->so_mask->sa.sa_len + 1 + (char *)soup->so_mask; 1277 cp2 = soup->so_mask->sa.sa_len + 1 + (char *)soup->so_mask;
1278 while (cp1 > soup->so_dst->sa.sa_data) 1278 while (cp1 > soup->so_dst->sa.sa_data)
1279 *--cp1 &= *--cp2; 1279 *--cp1 &= *--cp2;
1280} 1280}
1281 1281
1282const char * const msgtypes[] = { 1282const char * const msgtypes[] = {
1283 [RTM_ADD] = "RTM_ADD: Add Route", 1283 [RTM_ADD] = "RTM_ADD: Add Route",
1284 [RTM_DELETE] = "RTM_DELETE: Delete Route", 1284 [RTM_DELETE] = "RTM_DELETE: Delete Route",
1285 [RTM_CHANGE] = "RTM_CHANGE: Change Metrics, Flags or Gateway", 1285 [RTM_CHANGE] = "RTM_CHANGE: Change Metrics, Flags or Gateway",
1286 [RTM_GET] = "RTM_GET: Report Metrics", 1286 [RTM_GET] = "RTM_GET: Report Metrics",
1287 [RTM_LOSING] = "RTM_LOSING: Kernel Suspects Partitioning", 1287 [RTM_LOSING] = "RTM_LOSING: Kernel Suspects Partitioning",
1288 [RTM_REDIRECT] = "RTM_REDIRECT: Told to use different route", 1288 [RTM_REDIRECT] = "RTM_REDIRECT: Told to use different route",
1289 [RTM_MISS] = "RTM_MISS: Lookup failed on this address", 1289 [RTM_MISS] = "RTM_MISS: Lookup failed on this address",
1290 [RTM_LOCK] = "RTM_LOCK: fix specified metrics", 1290 [RTM_LOCK] = "RTM_LOCK: fix specified metrics",
1291 [RTM_OLDADD] = "RTM_OLDADD: caused by SIOCADDRT", 1291 [RTM_OLDADD] = "RTM_OLDADD: caused by SIOCADDRT",
1292 [RTM_OLDDEL] = "RTM_OLDDEL: caused by SIOCDELRT", 1292 [RTM_OLDDEL] = "RTM_OLDDEL: caused by SIOCDELRT",
1293 [RTM_NEWADDR] = "RTM_NEWADDR: address being added to iface", 1293 [RTM_NEWADDR] = "RTM_NEWADDR: address being added to iface",
1294 [RTM_DELADDR] = "RTM_DELADDR: address being removed from iface", 1294 [RTM_DELADDR] = "RTM_DELADDR: address being removed from iface",
1295 [RTM_OOIFINFO] = "RTM_OOIFINFO: iface status change (pre-1.5)", 1295 [RTM_OOIFINFO] = "RTM_OOIFINFO: iface status change (pre-1.5)",
1296 [RTM_OIFINFO] = "RTM_OIFINFO: iface status change (pre-64bit time)", 1296 [RTM_OIFINFO] = "RTM_OIFINFO: iface status change (pre-64bit time)",
1297 [RTM_IFANNOUNCE] = "RTM_IFANNOUNCE: iface arrival/departure", 1297 [RTM_IFANNOUNCE] = "RTM_IFANNOUNCE: iface arrival/departure",
1298 [RTM_IEEE80211] = "RTM_IEEE80211: IEEE80211 wireless event", 1298 [RTM_IEEE80211] = "RTM_IEEE80211: IEEE80211 wireless event",
1299 [RTM_IFINFO] = "RTM_IFINFO: iface status change", 1299 [RTM_IFINFO] = "RTM_IFINFO: iface status change",
1300 [RTM_CHGADDR] = "RTM_CHGADDR: address being changed on iface", 1300 [RTM_CHGADDR] = "RTM_CHGADDR: address being changed on iface",
1301}; 1301};
1302 1302
1303const char metricnames[] = 1303const char metricnames[] =
1304"\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu"; 1304"\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu";
1305const char routeflags[] = 1305const char routeflags[] =
1306"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CONNECTED\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016CLONED\017PROTO2\020PROTO1\023LOCAL\024BROADCAST"; 1306"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CONNECTED\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016CLONED\017PROTO2\020PROTO1\023LOCAL\024BROADCAST";
1307const char ifnetflags[] = 1307const char ifnetflags[] =
1308"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP\011PROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST"; 1308"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP\011PROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST";
1309const char addrnames[] = 1309const char addrnames[] =
1310"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011TAG"; 1310"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011TAG";
1311 1311
1312 1312
1313#ifndef SMALL 1313#ifndef SMALL
1314static const char * 1314static const char *
1315linkstate(struct if_msghdr *ifm) 1315linkstate(struct if_msghdr *ifm)
1316{ 1316{
1317 static char buf[64]; 1317 static char buf[64];
1318 1318
1319 switch (ifm->ifm_data.ifi_link_state) { 1319 switch (ifm->ifm_data.ifi_link_state) {
1320 case LINK_STATE_UNKNOWN: 1320 case LINK_STATE_UNKNOWN:
1321 return "carrier: unknown"; 1321 return "carrier: unknown";
1322 case LINK_STATE_DOWN: 1322 case LINK_STATE_DOWN:
1323 return "carrier: no carrier"; 1323 return "carrier: no carrier";
1324 case LINK_STATE_UP: 1324 case LINK_STATE_UP:
1325 return "carrier: active"; 1325 return "carrier: active";
1326 default: 1326 default:
1327 (void)snprintf(buf, sizeof(buf), "carrier: 0x%x", 1327 (void)snprintf(buf, sizeof(buf), "carrier: 0x%x",
1328 ifm->ifm_data.ifi_link_state); 1328 ifm->ifm_data.ifi_link_state);
1329 return buf; 1329 return buf;
1330 } 1330 }
1331} 1331}
1332#endif /* SMALL */ 1332#endif /* SMALL */
1333 1333
1334static void 1334static void
1335print_rtmsg(struct rt_msghdr *rtm, int msglen) 1335print_rtmsg(struct rt_msghdr *rtm, int msglen)
1336{ 1336{
1337 struct if_msghdr *ifm; 1337 struct if_msghdr *ifm;
1338 struct ifa_msghdr *ifam; 1338 struct ifa_msghdr *ifam;
1339 struct if_announcemsghdr *ifan; 1339 struct if_announcemsghdr *ifan;
1340 union { 1340 union {
1341 struct ieee80211_join_event join; 1341 struct ieee80211_join_event join;
1342 struct ieee80211_leave_event leave; 1342 struct ieee80211_leave_event leave;
1343 struct ieee80211_replay_event replay; 1343 struct ieee80211_replay_event replay;
1344 struct ieee80211_michael_event michael; 1344 struct ieee80211_michael_event michael;
1345 } ev; 1345 } ev;
1346 size_t evlen = 0; 1346 size_t evlen = 0;
1347 1347
1348 if (verbose == 0) 1348 if (verbose == 0)
1349 return; 1349 return;
1350 if (rtm->rtm_version != RTM_VERSION) { 1350 if (rtm->rtm_version != RTM_VERSION) {
1351 (void)printf("routing message version %d not understood\n", 1351 (void)printf("routing message version %d not understood\n",
1352 rtm->rtm_version); 1352 rtm->rtm_version);
1353 return; 1353 return;
1354 } 1354 }
1355 if (msgtypes[rtm->rtm_type]) 1355 if (msgtypes[rtm->rtm_type])
1356 (void)printf("%s: ", msgtypes[rtm->rtm_type]); 1356 (void)printf("%s: ", msgtypes[rtm->rtm_type]);
1357 else 1357 else
1358 (void)printf("#%d: ", rtm->rtm_type); 1358 (void)printf("#%d: ", rtm->rtm_type);
1359 (void)printf("len %d, ", rtm->rtm_msglen); 1359 (void)printf("len %d, ", rtm->rtm_msglen);
1360 switch (rtm->rtm_type) { 1360 switch (rtm->rtm_type) {
1361 case RTM_IFINFO: 1361 case RTM_IFINFO:
1362 ifm = (struct if_msghdr *)rtm; 1362 ifm = (struct if_msghdr *)rtm;
1363 (void)printf("if# %d, %s, flags: ", ifm->ifm_index, 1363 (void)printf("if# %d, %s, flags: ", ifm->ifm_index,
1364#ifdef SMALL 1364#ifdef SMALL
1365 "" 1365 ""
1366#else 1366#else
1367 linkstate(ifm) 1367 linkstate(ifm)
1368#endif /* SMALL */ 1368#endif /* SMALL */
1369 ); 1369 );
1370 bprintf(stdout, ifm->ifm_flags, ifnetflags); 1370 bprintf(stdout, ifm->ifm_flags, ifnetflags);
1371 pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs); 1371 pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs);
1372 break; 1372 break;
1373 case RTM_NEWADDR: 1373 case RTM_NEWADDR:
1374 case RTM_DELADDR: 1374 case RTM_DELADDR:
1375 case RTM_CHGADDR: 1375 case RTM_CHGADDR:
1376 ifam = (struct ifa_msghdr *)rtm; 1376 ifam = (struct ifa_msghdr *)rtm;
1377 (void)printf("pid %d, metric %d, flags: ", 1377 (void)printf("pid %d, metric %d, flags: ",
1378 ifam->ifam_pid, ifam->ifam_metric); 1378 ifam->ifam_pid, ifam->ifam_metric);
1379 bprintf(stdout, ifam->ifam_flags, routeflags); 1379 bprintf(stdout, ifam->ifam_flags, routeflags);
1380 pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs); 1380 pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs);
1381 break; 1381 break;
1382 case RTM_IEEE80211: 1382 case RTM_IEEE80211:
1383 ifan = (struct if_announcemsghdr *)rtm; 1383 ifan = (struct if_announcemsghdr *)rtm;
1384 (void)printf("if# %d, what: ", ifan->ifan_index); 1384 (void)printf("if# %d, what: ", ifan->ifan_index);
1385 switch (ifan->ifan_what) { 1385 switch (ifan->ifan_what) {
1386 case RTM_IEEE80211_ASSOC: 1386 case RTM_IEEE80211_ASSOC:
1387 printf("associate"); 1387 printf("associate");
1388 break; 1388 break;
1389 case RTM_IEEE80211_REASSOC: 1389 case RTM_IEEE80211_REASSOC:
1390 printf("re-associate"); 1390 printf("re-associate");
1391 break; 1391 break;
1392 case RTM_IEEE80211_DISASSOC: 1392 case RTM_IEEE80211_DISASSOC:
1393 printf("disassociate"); 1393 printf("disassociate");
1394 break; 1394 break;
1395 case RTM_IEEE80211_SCAN: 1395 case RTM_IEEE80211_SCAN:
1396 printf("scan complete"); 1396 printf("scan complete");
1397 break; 1397 break;
1398 case RTM_IEEE80211_JOIN: 1398 case RTM_IEEE80211_JOIN:
1399 evlen = sizeof(ev.join); 1399 evlen = sizeof(ev.join);
1400 printf("join"); 1400 printf("join");
1401 break; 1401 break;
1402 case RTM_IEEE80211_LEAVE: 1402 case RTM_IEEE80211_LEAVE:
1403 evlen = sizeof(ev.leave); 1403 evlen = sizeof(ev.leave);
1404 printf("leave"); 1404 printf("leave");
1405 break; 1405 break;
1406 case RTM_IEEE80211_MICHAEL: 1406 case RTM_IEEE80211_MICHAEL:
1407 evlen = sizeof(ev.michael); 1407 evlen = sizeof(ev.michael);
1408 printf("michael"); 1408 printf("michael");
1409 break; 1409 break;
1410 case RTM_IEEE80211_REPLAY: 1410 case RTM_IEEE80211_REPLAY:
1411 evlen = sizeof(ev.replay); 1411 evlen = sizeof(ev.replay);
1412 printf("replay"); 1412 printf("replay");
1413 break; 1413 break;
1414 default: 1414 default:
1415 evlen = 0; 1415 evlen = 0;
1416 printf("#%d", ifan->ifan_what); 1416 printf("#%d", ifan->ifan_what);
1417 break; 1417 break;
1418 } 1418 }
1419 if (sizeof(*ifan) + evlen > ifan->ifan_msglen) { 1419 if (sizeof(*ifan) + evlen > ifan->ifan_msglen) {
1420 printf(" (truncated)\n"); 1420 printf(" (truncated)\n");
1421 break; 1421 break;
1422 } 1422 }
1423 (void)memcpy(&ev, (ifan + 1), evlen); 1423 (void)memcpy(&ev, (ifan + 1), evlen);
1424 switch (ifan->ifan_what) { 1424 switch (ifan->ifan_what) {
1425 case RTM_IEEE80211_JOIN: 1425 case RTM_IEEE80211_JOIN:
1426 case RTM_IEEE80211_LEAVE: 1426 case RTM_IEEE80211_LEAVE:
1427 printf(" mac %" PRIETHER, 1427 printf(" mac %" PRIETHER,
1428 PRIETHER_ARGS(ev.join.iev_addr)); 1428 PRIETHER_ARGS(ev.join.iev_addr));
1429 break; 1429 break;
1430 case RTM_IEEE80211_REPLAY: 1430 case RTM_IEEE80211_REPLAY:
1431 case RTM_IEEE80211_MICHAEL: 1431 case RTM_IEEE80211_MICHAEL:
1432 printf(" src %" PRIETHER " dst %" PRIETHER 1432 printf(" src %" PRIETHER " dst %" PRIETHER
1433 " cipher %" PRIu8 " keyix %" PRIu8, 1433 " cipher %" PRIu8 " keyix %" PRIu8,
1434 PRIETHER_ARGS(ev.replay.iev_src), 1434 PRIETHER_ARGS(ev.replay.iev_src),
1435 PRIETHER_ARGS(ev.replay.iev_dst), 1435 PRIETHER_ARGS(ev.replay.iev_dst),
1436 ev.replay.iev_cipher, 1436 ev.replay.iev_cipher,
1437 ev.replay.iev_keyix); 1437 ev.replay.iev_keyix);
1438 if (ifan->ifan_what == RTM_IEEE80211_REPLAY) { 1438 if (ifan->ifan_what == RTM_IEEE80211_REPLAY) {
1439 printf(" key rsc %#" PRIx64 1439 printf(" key rsc %#" PRIx64
1440 " frame rsc %#" PRIx64, 1440 " frame rsc %#" PRIx64,
1441 ev.replay.iev_keyrsc, ev.replay.iev_rsc); 1441 ev.replay.iev_keyrsc, ev.replay.iev_rsc);
1442 } 1442 }
1443 break; 1443 break;
1444 default: 1444 default:
1445 break; 1445 break;
1446 } 1446 }
1447 printf("\n"); 1447 printf("\n");
1448 break; 1448 break;
1449 case RTM_IFANNOUNCE: 1449 case RTM_IFANNOUNCE:
1450 ifan = (struct if_announcemsghdr *)rtm; 1450 ifan = (struct if_announcemsghdr *)rtm;
1451 (void)printf("if# %d, what: ", ifan->ifan_index); 1451 (void)printf("if# %d, what: ", ifan->ifan_index);
1452 switch (ifan->ifan_what) { 1452 switch (ifan->ifan_what) {
1453 case IFAN_ARRIVAL: 1453 case IFAN_ARRIVAL:
1454 printf("arrival"); 1454 printf("arrival");
1455 break; 1455 break;
1456 case IFAN_DEPARTURE: 1456 case IFAN_DEPARTURE:
1457 printf("departure"); 1457 printf("departure");
1458 break; 1458 break;
1459 default: 1459 default:
1460 printf("#%d", ifan->ifan_what); 1460 printf("#%d", ifan->ifan_what);
1461 break; 1461 break;
1462 } 1462 }
1463 printf("\n"); 1463 printf("\n");
1464 break; 1464 break;
1465 default: 1465 case RTM_ADD:
 1466 case RTM_DELETE:
 1467 case RTM_GET:
1466 (void)printf("pid %d, seq %d, errno %d, flags: ", 1468 (void)printf("pid %d, seq %d, errno %d, flags: ",
1467 rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno); 1469 rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
1468 bprintf(stdout, rtm->rtm_flags, routeflags); 1470 bprintf(stdout, rtm->rtm_flags, routeflags);
1469 pmsg_common(rtm); 1471 pmsg_common(rtm);
 1472 break;
1470 } 1473 }
1471} 1474}
1472 1475
1473#ifndef SMALL 1476#ifndef SMALL
1474static int 1477static int
1475print_getmsg(struct rt_msghdr *rtm, int msglen, struct sou *soup) 1478print_getmsg(struct rt_msghdr *rtm, int msglen, struct sou *soup)
1476{ 1479{
1477 struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *ifa = NULL, *mpls = NULL; 1480 struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *ifa = NULL, *mpls = NULL;
1478 struct sockaddr_dl *ifp = NULL; 1481 struct sockaddr_dl *ifp = NULL;
1479 struct sockaddr *sa; 1482 struct sockaddr *sa;
1480 char *cp; 1483 char *cp;
1481 int i; 1484 int i;
1482 1485
1483 if (! shortoutput) { 1486 if (! shortoutput) {
1484 (void)printf(" route to: %s\n", 1487 (void)printf(" route to: %s\n",
1485 routename(&soup->so_dst->sa, nflag)); 1488 routename(&soup->so_dst->sa, nflag));
1486 } 1489 }
1487 if (rtm->rtm_version != RTM_VERSION) { 1490 if (rtm->rtm_version != RTM_VERSION) {
1488 warnx("routing message version %d not understood", 1491 warnx("routing message version %d not understood",
1489 rtm->rtm_version); 1492 rtm->rtm_version);
1490 return 1; 1493 return 1;
1491 } 1494 }
1492 if (rtm->rtm_msglen > msglen) { 1495 if (rtm->rtm_msglen > msglen) {
1493 warnx("message length mismatch, in packet %d, returned %d", 1496 warnx("message length mismatch, in packet %d, returned %d",
1494 rtm->rtm_msglen, msglen); 1497 rtm->rtm_msglen, msglen);
1495 } 1498 }
1496 if (rtm->rtm_errno) { 1499 if (rtm->rtm_errno) {
1497 warnx("RTM_GET: %s (errno %d)", 1500 warnx("RTM_GET: %s (errno %d)",
1498 strerror(rtm->rtm_errno), rtm->rtm_errno); 1501 strerror(rtm->rtm_errno), rtm->rtm_errno);
1499 return 1; 1502 return 1;
1500 } 1503 }
1501 cp = ((char *)(rtm + 1)); 1504 cp = ((char *)(rtm + 1));
1502 if (rtm->rtm_addrs) 1505 if (rtm->rtm_addrs)
1503 for (i = 1; i; i <<= 1) 1506 for (i = 1; i; i <<= 1)
1504 if (i & rtm->rtm_addrs) { 1507 if (i & rtm->rtm_addrs) {
1505 sa = (struct sockaddr *)cp; 1508 sa = (struct sockaddr *)cp;
1506 switch (i) { 1509 switch (i) {
1507 case RTA_DST: 1510 case RTA_DST:
1508 dst = sa; 1511 dst = sa;
1509 break; 1512 break;
1510 case RTA_GATEWAY: 1513 case RTA_GATEWAY:
1511 gate = sa; 1514 gate = sa;
1512 break; 1515 break;
1513 case RTA_NETMASK: 1516 case RTA_NETMASK:
1514 mask = sa; 1517 mask = sa;
1515 break; 1518 break;
1516 case RTA_IFP: 1519 case RTA_IFP:
1517 if (sa->sa_family == AF_LINK && 1520 if (sa->sa_family == AF_LINK &&
1518 ((struct sockaddr_dl *)sa)->sdl_nlen) 1521 ((struct sockaddr_dl *)sa)->sdl_nlen)
1519 ifp = (struct sockaddr_dl *)sa; 1522 ifp = (struct sockaddr_dl *)sa;
1520 break; 1523 break;
1521 case RTA_IFA: 1524 case RTA_IFA:
1522 ifa = sa; 1525 ifa = sa;
1523 break; 1526 break;
1524 case RTA_TAG: 1527 case RTA_TAG:
1525 mpls = sa; 1528 mpls = sa;
1526 break; 1529 break;
1527 } 1530 }
1528 RT_ADVANCE(cp, sa); 1531 RT_ADVANCE(cp, sa);
1529 } 1532 }
1530 if (dst && mask) 1533 if (dst && mask)
1531 mask->sa_family = dst->sa_family; /* XXX */ 1534 mask->sa_family = dst->sa_family; /* XXX */
1532 if (dst && ! shortoutput) 1535 if (dst && ! shortoutput)
1533 (void)printf("destination: %s\n", 1536 (void)printf("destination: %s\n",
1534 routename(dst, nflag)); 1537 routename(dst, nflag));
1535 if (mask && ! shortoutput) { 1538 if (mask && ! shortoutput) {
1536 int savenflag = nflag; 1539 int savenflag = nflag;
1537 1540
1538 nflag = RT_NFLAG; 1541 nflag = RT_NFLAG;
1539 (void)printf(" mask: %s\n", 1542 (void)printf(" mask: %s\n",
1540 routename(mask, nflag)); 1543 routename(mask, nflag));
1541 nflag = savenflag; 1544 nflag = savenflag;
1542 } 1545 }
1543 if (gate && rtm->rtm_flags & RTF_GATEWAY) { 1546 if (gate && rtm->rtm_flags & RTF_GATEWAY) {
1544 const char *name; 1547 const char *name;
1545 1548
1546 name = routename(gate, nflag); 1549 name = routename(gate, nflag);
1547 if (shortoutput) { 1550 if (shortoutput) {
1548 if (*name == '\0') 1551 if (*name == '\0')
1549 return 1; 1552 return 1;
1550 (void)printf("%s\n", name); 1553 (void)printf("%s\n", name);
1551 } else 1554 } else
1552 (void)printf(" gateway: %s\n", name); 1555 (void)printf(" gateway: %s\n", name);
1553 } 1556 }
1554 if (mpls) { 1557 if (mpls) {
1555 const char *name; 1558 const char *name;
1556 name = routename(mpls, nflag); 1559 name = routename(mpls, nflag);
1557 if(shortoutput) { 1560 if(shortoutput) {
1558 if (*name == '\0') 1561 if (*name == '\0')
1559 return 1; 1562 return 1;
1560 printf("%s\n", name); 1563 printf("%s\n", name);
1561 } else 1564 } else
1562 printf(" Tag: %s\n", name); 1565 printf(" Tag: %s\n", name);
1563 } 1566 }
1564  1567
1565 if (ifa && ! shortoutput) 1568 if (ifa && ! shortoutput)
1566 (void)printf(" local addr: %s\n", 1569 (void)printf(" local addr: %s\n",
1567 routename(ifa, nflag)); 1570 routename(ifa, nflag));
1568 if (ifp && ! shortoutput) 1571 if (ifp && ! shortoutput)
1569 (void)printf(" interface: %.*s\n", 1572 (void)printf(" interface: %.*s\n",
1570 ifp->sdl_nlen, ifp->sdl_data); 1573 ifp->sdl_nlen, ifp->sdl_data);
1571 if (! shortoutput) { 1574 if (! shortoutput) {
1572 (void)printf(" flags: "); 1575 (void)printf(" flags: ");
1573 bprintf(stdout, rtm->rtm_flags, routeflags); 1576 bprintf(stdout, rtm->rtm_flags, routeflags);
1574 } 1577 }
1575 1578
1576#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ') 1579#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ')
1577#define msec(u) (((u) + 500) / 1000) /* usec to msec */ 1580#define msec(u) (((u) + 500) / 1000) /* usec to msec */
1578 1581
1579 if (! shortoutput) { 1582 if (! shortoutput) {
1580 (void)printf("\n%s\n", "\ 1583 (void)printf("\n%s\n", "\
1581 recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire"); 1584 recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire");
1582 printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE)); 1585 printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE));
1583 printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE)); 1586 printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE));
1584 printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH)); 1587 printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH));
1585 printf("%8"PRId64"%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT)); 1588 printf("%8"PRId64"%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT));
1586 printf("%8"PRId64"%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR)); 1589 printf("%8"PRId64"%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR));
1587 printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT)); 1590 printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT));
1588 printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU)); 1591 printf("%8"PRId64"%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU));
1589 if (rtm->rtm_rmx.rmx_expire) 1592 if (rtm->rtm_rmx.rmx_expire)
1590 rtm->rtm_rmx.rmx_expire -= time(0); 1593 rtm->rtm_rmx.rmx_expire -= time(0);
1591 printf("%8"PRId64"%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE)); 1594 printf("%8"PRId64"%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
1592 } 1595 }
1593#undef lock 1596#undef lock
1594#undef msec 1597#undef msec
1595#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD) 1598#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD)
1596 1599
1597 if (shortoutput) 1600 if (shortoutput)
1598 return (rtm->rtm_addrs & RTF_GATEWAY) == 0; 1601 return (rtm->rtm_addrs & RTF_GATEWAY) == 0;
1599 else if (verbose) 1602 else if (verbose)
1600 pmsg_common(rtm); 1603 pmsg_common(rtm);
1601 else if (rtm->rtm_addrs &~ RTA_IGN) { 1604 else if (rtm->rtm_addrs &~ RTA_IGN) {
1602 (void)printf("sockaddrs: "); 1605 (void)printf("sockaddrs: ");
1603 bprintf(stdout, rtm->rtm_addrs, addrnames); 1606 bprintf(stdout, rtm->rtm_addrs, addrnames);
1604 putchar('\n'); 1607 putchar('\n');
1605 } 1608 }
1606 return 0; 1609 return 0;
1607#undef RTA_IGN 1610#undef RTA_IGN
1608} 1611}
1609#endif /* SMALL */ 1612#endif /* SMALL */
1610 1613
1611void 1614void
1612pmsg_common(struct rt_msghdr *rtm) 1615pmsg_common(struct rt_msghdr *rtm)
1613{ 1616{
1614 (void)printf("\nlocks: "); 1617 (void)printf("\nlocks: ");
1615 bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); 1618 bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
1616 (void)printf(" inits: "); 1619 (void)printf(" inits: ");
1617 bprintf(stdout, rtm->rtm_inits, metricnames); 1620 bprintf(stdout, rtm->rtm_inits, metricnames);
1618 pmsg_addrs((char *)(rtm + 1), rtm->rtm_addrs); 1621 pmsg_addrs((char *)(rtm + 1), rtm->rtm_addrs);
1619} 1622}
1620 1623
1621static void 1624static void
1622extract_addrs(const char *cp, int addrs, const struct sockaddr *sa[], int *nmfp) 1625extract_addrs(const char *cp, int addrs, const struct sockaddr *sa[], int *nmfp)
1623{ 1626{
1624 int i, nmf = -1; 1627 int i, nmf = -1;
1625 1628
1626 for (i = 0; i < RTAX_MAX; i++) { 1629 for (i = 0; i < RTAX_MAX; i++) {
1627 if ((1 << i) & addrs) { 1630 if ((1 << i) & addrs) {
1628 sa[i] = (const struct sockaddr *)cp; 1631 sa[i] = (const struct sockaddr *)cp;
1629 if ((i == RTAX_DST || i == RTAX_IFA) && 1632 if ((i == RTAX_DST || i == RTAX_IFA) &&
1630 nmf == -1) 1633 nmf == -1)
1631 nmf = sa[i]->sa_family; 1634 nmf = sa[i]->sa_family;
1632 RT_ADVANCE(cp, sa[i]); 1635 RT_ADVANCE(cp, sa[i]);
1633 } else 1636 } else
1634 sa[i] = NULL; 1637 sa[i] = NULL;
1635 } 1638 }
1636 1639
1637 if (nmfp != NULL) 1640 if (nmfp != NULL)
1638 *nmfp = nmf; 1641 *nmfp = nmf;
1639} 1642}
1640 1643
1641static void 1644static void
1642pmsg_addrs(const char *cp, int addrs) 1645pmsg_addrs(const char *cp, int addrs)
1643{ 1646{
1644 const struct sockaddr *sa[RTAX_MAX]; 1647 const struct sockaddr *sa[RTAX_MAX];
1645 int i, nmf; 1648 int i, nmf;
1646 1649
1647 if (addrs != 0) { 1650 if (addrs != 0) {
1648 (void)printf("\nsockaddrs: "); 1651 (void)printf("\nsockaddrs: ");
1649 bprintf(stdout, addrs, addrnames); 1652 bprintf(stdout, addrs, addrnames);
1650 (void)putchar('\n'); 1653 (void)putchar('\n');
1651 extract_addrs(cp, addrs, sa, &nmf); 1654 extract_addrs(cp, addrs, sa, &nmf);
1652 for (i = 0; i < RTAX_MAX; i++) { 1655 for (i = 0; i < RTAX_MAX; i++) {
1653 if (sa[i] == NULL) 1656 if (sa[i] == NULL)
1654 continue; 1657 continue;
1655 1658
1656 if (i == RTAX_NETMASK && sa[i]->sa_len) 1659 if (i == RTAX_NETMASK && sa[i]->sa_len)
1657 (void)printf(" %s", 1660 (void)printf(" %s",
1658 netmask_string(sa[i], -1, nmf)); 1661 netmask_string(sa[i], -1, nmf));
1659 else 1662 else
1660 (void)printf(" %s", 1663 (void)printf(" %s",
1661 routename(sa[i], nflag)); 1664 routename(sa[i], nflag));
1662 } 1665 }
1663 } 1666 }
1664 (void)putchar('\n'); 1667 (void)putchar('\n');
1665 (void)fflush(stdout); 1668 (void)fflush(stdout);
1666} 1669}
1667 1670
1668static void 1671static void
1669bprintf(FILE *fp, int b, const char *f) 1672bprintf(FILE *fp, int b, const char *f)
1670{ 1673{
1671 int i; 1674 int i;
1672 int gotsome = 0; 1675 int gotsome = 0;
1673 const uint8_t *s = (const uint8_t *)f; 1676 const uint8_t *s = (const uint8_t *)f;
1674 1677
1675 if (b == 0) { 1678 if (b == 0) {
1676 fputs("none", fp); 1679 fputs("none", fp);
1677 return; 1680 return;
1678 } 1681 }
1679 while ((i = *s++) != 0) { 1682 while ((i = *s++) != 0) {
1680 if (b & (1 << (i-1))) { 1683 if (b & (1 << (i-1))) {
1681 if (gotsome == 0) 1684 if (gotsome == 0)
1682 i = '<'; 1685 i = '<';
1683 else 1686 else
1684 i = ','; 1687 i = ',';
1685 (void)putc(i, fp); 1688 (void)putc(i, fp);
1686 gotsome = 1; 1689 gotsome = 1;
1687 for (; (i = *s) > 32; s++) 1690 for (; (i = *s) > 32; s++)
1688 (void)putc(i, fp); 1691 (void)putc(i, fp);
1689 } else 1692 } else
1690 while (*s > 32) 1693 while (*s > 32)
1691 s++; 1694 s++;
1692 } 1695 }
1693 if (gotsome) 1696 if (gotsome)
1694 (void)putc('>', fp); 1697 (void)putc('>', fp);
1695} 1698}
1696 1699
1697int 1700int
1698keyword(const char *cp) 1701keyword(const char *cp)
1699{ 1702{
1700 struct keytab *kt = keywords; 1703 struct keytab *kt = keywords;
1701 1704
1702 while (kt->kt_cp && strcmp(kt->kt_cp, cp)) 1705 while (kt->kt_cp && strcmp(kt->kt_cp, cp))
1703 kt++; 1706 kt++;
1704 return kt->kt_i; 1707 return kt->kt_i;
1705} 1708}
1706 1709
1707static void 1710static void
1708sodump(sup su, const char *which) 1711sodump(sup su, const char *which)
1709{ 1712{
1710#ifdef INET6 1713#ifdef INET6
1711 char ntop_buf[NI_MAXHOST]; 1714 char ntop_buf[NI_MAXHOST];
1712#endif 1715#endif
1713 1716
1714 switch (su->sa.sa_family) { 1717 switch (su->sa.sa_family) {
1715 case AF_INET: 1718 case AF_INET:
1716 (void)printf("%s: inet %s; ", 1719 (void)printf("%s: inet %s; ",
1717 which, inet_ntoa(su->sin.sin_addr)); 1720 which, inet_ntoa(su->sin.sin_addr));
1718 break; 1721 break;
1719#ifndef SMALL 1722#ifndef SMALL
1720 case AF_APPLETALK: 1723 case AF_APPLETALK:
1721 (void)printf("%s: atalk %d.%d; ", 1724 (void)printf("%s: atalk %d.%d; ",
1722 which, su->sat.sat_addr.s_net, su->sat.sat_addr.s_node); 1725 which, su->sat.sat_addr.s_net, su->sat.sat_addr.s_node);
1723 break; 1726 break;
1724#endif 1727#endif
1725 case AF_LINK: 1728 case AF_LINK:
1726 (void)printf("%s: link %s; ", 1729 (void)printf("%s: link %s; ",
1727 which, link_ntoa(&su->sdl)); 1730 which, link_ntoa(&su->sdl));
1728 break; 1731 break;
1729#ifdef INET6 1732#ifdef INET6
1730 case AF_INET6: 1733 case AF_INET6:
1731 (void)printf("%s: inet6 %s; ", 1734 (void)printf("%s: inet6 %s; ",
1732 which, inet_ntop(AF_INET6, &su->sin6.sin6_addr, 1735 which, inet_ntop(AF_INET6, &su->sin6.sin6_addr,
1733 ntop_buf, sizeof(ntop_buf))); 1736 ntop_buf, sizeof(ntop_buf)));
1734 break; 1737 break;
1735#endif 1738#endif
1736#ifndef SMALL 1739#ifndef SMALL
1737 case AF_MPLS: 1740 case AF_MPLS:
1738 { 1741 {
1739 union mpls_shim ms; 1742 union mpls_shim ms;
1740 const union mpls_shim *pms; 1743 const union mpls_shim *pms;
1741 int psize = sizeof(struct sockaddr_mpls); 1744 int psize = sizeof(struct sockaddr_mpls);
1742 1745
1743 ms.s_addr = ntohl(su->smpls.smpls_addr.s_addr); 1746 ms.s_addr = ntohl(su->smpls.smpls_addr.s_addr);
1744 printf("%s: mpls %u; ", 1747 printf("%s: mpls %u; ",
1745 which, ms.shim.label); 1748 which, ms.shim.label);
1746 1749
1747 pms = &su->smpls.smpls_addr; 1750 pms = &su->smpls.smpls_addr;
1748 while(psize < su->smpls.smpls_len) { 1751 while(psize < su->smpls.smpls_len) {
1749 pms++; 1752 pms++;
1750 ms.s_addr = ntohl(pms->s_addr); 1753 ms.s_addr = ntohl(pms->s_addr);
1751 printf("%u; ", ms.shim.label); 1754 printf("%u; ", ms.shim.label);
1752 psize += sizeof(ms); 1755 psize += sizeof(ms);
1753 } 1756 }
1754 break; 1757 break;
1755 } 1758 }
1756#endif /* SMALL */ 1759#endif /* SMALL */
1757 default: 1760 default:
1758 (void)printf("%s: (%d) %s; ", 1761 (void)printf("%s: (%d) %s; ",
1759 which, su->sa.sa_family, any_ntoa(&su->sa)); 1762 which, su->sa.sa_family, any_ntoa(&su->sa));
1760 } 1763 }
1761 (void)fflush(stdout); 1764 (void)fflush(stdout);
1762} 1765}
1763 1766
1764/* States*/ 1767/* States*/
1765#define VIRGIN 0 1768#define VIRGIN 0
1766#define GOTONE 1 1769#define GOTONE 1
1767#define GOTTWO 2 1770#define GOTTWO 2
1768/* Inputs */ 1771/* Inputs */
1769#define DIGIT (4*0) 1772#define DIGIT (4*0)
1770#define END (4*1) 1773#define END (4*1)
1771#define DELIM (4*2) 1774#define DELIM (4*2)
1772 1775
1773static void 1776static void
1774sockaddr(const char *addr, struct sockaddr *sa) 1777sockaddr(const char *addr, struct sockaddr *sa)
1775{ 1778{
1776 char *cp = (char *)sa; 1779 char *cp = (char *)sa;
1777 int size = sa->sa_len; 1780 int size = sa->sa_len;
1778 char *cplim = cp + size; 1781 char *cplim = cp + size;
1779 int byte = 0, state = VIRGIN, new = 0; 1782 int byte = 0, state = VIRGIN, new = 0;
1780 1783
1781 (void)memset(cp, 0, size); 1784 (void)memset(cp, 0, size);
1782 cp++; 1785 cp++;
1783 do { 1786 do {
1784 if ((*addr >= '0') && (*addr <= '9')) { 1787 if ((*addr >= '0') && (*addr <= '9')) {
1785 new = *addr - '0'; 1788 new = *addr - '0';
1786 } else if ((*addr >= 'a') && (*addr <= 'f')) { 1789 } else if ((*addr >= 'a') && (*addr <= 'f')) {
1787 new = *addr - 'a' + 10; 1790 new = *addr - 'a' + 10;
1788 } else if ((*addr >= 'A') && (*addr <= 'F')) { 1791 } else if ((*addr >= 'A') && (*addr <= 'F')) {
1789 new = *addr - 'A' + 10; 1792 new = *addr - 'A' + 10;
1790 } else if (*addr == 0) 1793 } else if (*addr == 0)
1791 state |= END; 1794 state |= END;
1792 else 1795 else
1793 state |= DELIM; 1796 state |= DELIM;
1794 addr++; 1797 addr++;
1795 switch (state /* | INPUT */) { 1798 switch (state /* | INPUT */) {
1796 case GOTTWO | DIGIT: 1799 case GOTTWO | DIGIT:
1797 *cp++ = byte; /*FALLTHROUGH*/ 1800 *cp++ = byte; /*FALLTHROUGH*/
1798 case VIRGIN | DIGIT: 1801 case VIRGIN | DIGIT:
1799 state = GOTONE; byte = new; continue; 1802 state = GOTONE; byte = new; continue;
1800 case GOTONE | DIGIT: 1803 case GOTONE | DIGIT:
1801 state = GOTTWO; byte = new + (byte << 4); continue; 1804 state = GOTTWO; byte = new + (byte << 4); continue;
1802 default: /* | DELIM */ 1805 default: /* | DELIM */
1803 state = VIRGIN; *cp++ = byte; byte = 0; continue; 1806 state = VIRGIN; *cp++ = byte; byte = 0; continue;
1804 case GOTONE | END: 1807 case GOTONE | END:
1805 case GOTTWO | END: 1808 case GOTTWO | END:
1806 *cp++ = byte; /* FALLTHROUGH */ 1809 *cp++ = byte; /* FALLTHROUGH */
1807 case VIRGIN | END: 1810 case VIRGIN | END:
1808 break; 1811 break;
1809 } 1812 }
1810 break; 1813 break;
1811 } while (cp < cplim); 1814 } while (cp < cplim);
1812 sa->sa_len = cp - (char *)sa; 1815 sa->sa_len = cp - (char *)sa;
1813} 1816}