ifconfig.c revision 1.157 1 /* $NetBSD: ifconfig.c,v 1.157 2005/03/19 17:32:26 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright (c) 1983, 1993
42 * The Regents of the University of California. All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * SUCH DAMAGE.
67 */
68
69 #include <sys/cdefs.h>
70 #ifndef lint
71 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\
72 The Regents of the University of California. All rights reserved.\n");
73 #endif /* not lint */
74
75 #ifndef lint
76 #if 0
77 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
78 #else
79 __RCSID("$NetBSD: ifconfig.c,v 1.157 2005/03/19 17:32:26 thorpej Exp $");
80 #endif
81 #endif /* not lint */
82
83 #include <sys/param.h>
84 #include <sys/socket.h>
85 #include <sys/ioctl.h>
86
87 #include <net/if.h>
88 #include <net/if_dl.h>
89 #include <net/if_media.h>
90 #include <net/if_ether.h>
91 #include <net80211/ieee80211.h>
92 #include <net80211/ieee80211_ioctl.h>
93 #include <netinet/in.h>
94 #include <netinet/in_var.h>
95 #ifdef INET6
96 #include <netinet6/nd6.h>
97 #endif
98 #include <arpa/inet.h>
99
100 #include <netatalk/at.h>
101
102 #define NSIP
103 #include <netns/ns.h>
104 #include <netns/ns_if.h>
105 #include <netdb.h>
106
107 #define EON
108 #include <netiso/iso.h>
109 #include <netiso/iso_var.h>
110 #include <sys/protosw.h>
111
112 #include <ctype.h>
113 #include <err.h>
114 #include <errno.h>
115 #include <stddef.h>
116 #include <stdio.h>
117 #include <stdlib.h>
118 #include <string.h>
119 #include <unistd.h>
120 #include <ifaddrs.h>
121 #include <util.h>
122
123 #include "extern.h"
124 #include "agr.h"
125 #include "tunnel.h"
126 #include "vlan.h"
127
128 struct ifreq ifr, ridreq;
129 struct ifaliasreq addreq __attribute__((aligned(4)));
130 struct in_aliasreq in_addreq;
131 #ifdef INET6
132 struct in6_ifreq ifr6;
133 struct in6_ifreq in6_ridreq;
134 struct in6_aliasreq in6_addreq;
135 #endif
136 struct iso_ifreq iso_ridreq;
137 struct iso_aliasreq iso_addreq;
138 struct sockaddr_in netmask;
139 struct netrange at_nr; /* AppleTalk net range */
140
141 char name[30];
142 u_short flags;
143 int setaddr, setipdst, doalias;
144 u_long metric, mtu;
145 int clearaddr, s;
146 int newaddr = -1;
147 int conflicting = 0;
148 int nsellength = 1;
149 int af;
150 int aflag, bflag, Cflag, dflag, lflag, mflag, sflag, uflag, vflag, zflag;
151 #ifdef INET6
152 int Lflag;
153 #endif
154 int explicit_prefix = 0;
155
156 struct ifcapreq g_ifcr;
157 int g_ifcr_updated;
158
159 void notealias(const char *, int);
160 void notrailers(const char *, int);
161 void setifaddr(const char *, int);
162 void setifdstaddr(const char *, int);
163 void setifflags(const char *, int);
164 void setifcaps(const char *, int);
165 void setifbroadaddr(const char *, int);
166 void setifipdst(const char *, int);
167 void setifmetric(const char *, int);
168 void setifmtu(const char *, int);
169 void setifnwid(const char *, int);
170 void setifnwkey(const char *, int);
171 void setifbssid(const char *, int);
172 void setifchan(const char *, int);
173 void setifpowersave(const char *, int);
174 void setifpowersavesleep(const char *, int);
175 void setifnetmask(const char *, int);
176 void setifprefixlen(const char *, int);
177 void setnsellength(const char *, int);
178 void setsnpaoffset(const char *, int);
179 void setatrange(const char *, int);
180 void setatphase(const char *, int);
181 #ifdef INET6
182 void setia6flags(const char *, int);
183 void setia6pltime(const char *, int);
184 void setia6vltime(const char *, int);
185 void setia6lifetime(const char *, const char *);
186 void setia6eui64(const char *, int);
187 #endif
188 void checkatrange(struct sockaddr_at *);
189 void setmedia(const char *, int);
190 void setmediamode(const char *, int);
191 void setmediaopt(const char *, int);
192 void unsetmediaopt(const char *, int);
193 void setmediainst(const char *, int);
194 void clone_create(const char *, int);
195 void clone_destroy(const char *, int);
196 void fixnsel(struct sockaddr_iso *);
197 int main(int, char *[]);
198
199 /*
200 * Media stuff. Whenever a media command is first performed, the
201 * currently select media is grabbed for this interface. If `media'
202 * is given, the current media word is modifed. `mediaopt' commands
203 * only modify the set and clear words. They then operate on the
204 * current media word later.
205 */
206 int media_current;
207 int mediaopt_set;
208 int mediaopt_clear;
209
210 int actions; /* Actions performed */
211
212 #define A_MEDIA 0x0001 /* media command */
213 #define A_MEDIAOPTSET 0x0002 /* mediaopt command */
214 #define A_MEDIAOPTCLR 0x0004 /* -mediaopt command */
215 #define A_MEDIAOPT (A_MEDIAOPTSET|A_MEDIAOPTCLR)
216 #define A_MEDIAINST 0x0008 /* instance or inst command */
217 #define A_MEDIAMODE 0x0010 /* mode command */
218
219 #define NEXTARG 0xffffff
220 #define NEXTARG2 0xfffffe
221
222 const struct cmd {
223 const char *c_name;
224 int c_parameter; /* NEXTARG means next argv */
225 int c_action; /* defered action */
226 void (*c_func)(const char *, int);
227 void (*c_func2)(const char *, const char *);
228 } cmds[] = {
229 { "up", IFF_UP, 0, setifflags } ,
230 { "down", -IFF_UP, 0, setifflags },
231 { "trailers", -1, 0, notrailers },
232 { "-trailers", 1, 0, notrailers },
233 { "arp", -IFF_NOARP, 0, setifflags },
234 { "-arp", IFF_NOARP, 0, setifflags },
235 { "debug", IFF_DEBUG, 0, setifflags },
236 { "-debug", -IFF_DEBUG, 0, setifflags },
237 { "alias", IFF_UP, 0, notealias },
238 { "-alias", -IFF_UP, 0, notealias },
239 { "delete", -IFF_UP, 0, notealias },
240 #ifdef notdef
241 #define EN_SWABIPS 0x1000
242 { "swabips", EN_SWABIPS, 0, setifflags },
243 { "-swabips", -EN_SWABIPS, 0, setifflags },
244 #endif
245 { "netmask", NEXTARG, 0, setifnetmask },
246 { "metric", NEXTARG, 0, setifmetric },
247 { "mtu", NEXTARG, 0, setifmtu },
248 { "bssid", NEXTARG, 0, setifbssid },
249 { "-bssid", -1, 0, setifbssid },
250 { "chan", NEXTARG, 0, setifchan },
251 { "-chan", -1, 0, setifchan },
252 { "ssid", NEXTARG, 0, setifnwid },
253 { "nwid", NEXTARG, 0, setifnwid },
254 { "nwkey", NEXTARG, 0, setifnwkey },
255 { "-nwkey", -1, 0, setifnwkey },
256 { "powersave", 1, 0, setifpowersave },
257 { "-powersave", 0, 0, setifpowersave },
258 { "powersavesleep", NEXTARG, 0, setifpowersavesleep },
259 { "broadcast", NEXTARG, 0, setifbroadaddr },
260 { "ipdst", NEXTARG, 0, setifipdst },
261 { "prefixlen", NEXTARG, 0, setifprefixlen},
262 #ifdef INET6
263 { "anycast", IN6_IFF_ANYCAST, 0, setia6flags },
264 { "-anycast", -IN6_IFF_ANYCAST, 0, setia6flags },
265 { "tentative", IN6_IFF_TENTATIVE, 0, setia6flags },
266 { "-tentative", -IN6_IFF_TENTATIVE, 0, setia6flags },
267 { "deprecated", IN6_IFF_DEPRECATED, 0, setia6flags },
268 { "-deprecated", -IN6_IFF_DEPRECATED, 0, setia6flags },
269 { "pltime", NEXTARG, 0, setia6pltime },
270 { "vltime", NEXTARG, 0, setia6vltime },
271 { "eui64", 0, 0, setia6eui64 },
272 #endif /*INET6*/
273 #ifndef INET_ONLY
274 { "range", NEXTARG, 0, setatrange },
275 { "phase", NEXTARG, 0, setatphase },
276 { "snpaoffset", NEXTARG, 0, setsnpaoffset },
277 { "nsellength", NEXTARG, 0, setnsellength },
278 #endif /* INET_ONLY */
279 { "tunnel", NEXTARG2, 0, NULL,
280 settunnel } ,
281 { "deletetunnel", 0, 0, deletetunnel },
282 { "vlan", NEXTARG, 0, setvlan } ,
283 { "vlanif", NEXTARG, 0, setvlanif } ,
284 { "-vlanif", 0, 0, unsetvlanif } ,
285 #if 0
286 /* XXX `create' special-cased below */
287 { "create", 0, 0, clone_create } ,
288 #endif
289 { "destroy", 0, 0, clone_destroy } ,
290 { "link0", IFF_LINK0, 0, setifflags } ,
291 { "-link0", -IFF_LINK0, 0, setifflags } ,
292 { "link1", IFF_LINK1, 0, setifflags } ,
293 { "-link1", -IFF_LINK1, 0, setifflags } ,
294 { "link2", IFF_LINK2, 0, setifflags } ,
295 { "-link2", -IFF_LINK2, 0, setifflags } ,
296 { "media", NEXTARG, A_MEDIA, setmedia },
297 { "mediaopt", NEXTARG, A_MEDIAOPTSET, setmediaopt },
298 { "-mediaopt", NEXTARG, A_MEDIAOPTCLR, unsetmediaopt },
299 { "mode", NEXTARG, A_MEDIAMODE, setmediamode },
300 { "instance", NEXTARG, A_MEDIAINST, setmediainst },
301 { "inst", NEXTARG, A_MEDIAINST, setmediainst },
302 { "ip4csum", IFCAP_CSUM_IPv4,0, setifcaps },
303 { "-ip4csum", -IFCAP_CSUM_IPv4,0, setifcaps },
304 { "tcp4csum", IFCAP_CSUM_TCPv4,0, setifcaps },
305 { "-tcp4csum", -IFCAP_CSUM_TCPv4,0, setifcaps },
306 { "udp4csum", IFCAP_CSUM_UDPv4,0, setifcaps },
307 { "-udp4csum", -IFCAP_CSUM_UDPv4,0, setifcaps },
308 { "tcp6csum", IFCAP_CSUM_TCPv6,0, setifcaps },
309 { "-tcp6csum", -IFCAP_CSUM_TCPv6,0, setifcaps },
310 { "udp6csum", IFCAP_CSUM_UDPv6,0, setifcaps },
311 { "-udp6csum", -IFCAP_CSUM_UDPv6,0, setifcaps },
312 { "tcp4csum-rx",IFCAP_CSUM_TCPv4_Rx,0, setifcaps },
313 { "-tcp4csum-rx",-IFCAP_CSUM_TCPv4_Rx,0, setifcaps },
314 { "udp4csum-rx",IFCAP_CSUM_UDPv4_Rx,0, setifcaps },
315 { "-udp4csum-rx",-IFCAP_CSUM_UDPv4_Rx,0, setifcaps },
316 { "tso4", IFCAP_TSOv4, 0, setifcaps },
317 { "-tso4", -IFCAP_TSOv4, 0, setifcaps },
318 { "agrport", NEXTARG, 0, agraddport } ,
319 { "-agrport", NEXTARG, 0, agrremport } ,
320 { 0, 0, 0, setifaddr },
321 { 0, 0, 0, setifdstaddr },
322 };
323
324 void adjust_nsellength(void);
325 int getinfo(struct ifreq *);
326 int carrier(void);
327 void getsock(int);
328 void printall(const char *);
329 void list_cloners(void);
330 int prefix(void *, int);
331 void status(const struct sockaddr_dl *);
332 void usage(void);
333 const char *get_string(const char *, const char *, u_int8_t *, int *);
334 void print_string(const u_int8_t *, int);
335 char *sec2str(time_t);
336
337 void print_media_word(int, const char *);
338 void process_media_commands(void);
339 void init_current_media(void);
340
341 /*
342 * XNS support liberally adapted from code written at the University of
343 * Maryland principally by James O'Toole and Chris Torek.
344 */
345 void in_alias(struct ifreq *);
346 void in_status(int);
347 void in_getaddr(const char *, int);
348 void in_getprefix(const char *, int);
349 #ifdef INET6
350 void in6_fillscopeid(struct sockaddr_in6 *sin6);
351 void in6_alias(struct in6_ifreq *);
352 void in6_status(int);
353 void in6_getaddr(const char *, int);
354 void in6_getprefix(const char *, int);
355 #endif
356 void at_status(int);
357 void at_getaddr(const char *, int);
358 void xns_status(int);
359 void xns_getaddr(const char *, int);
360 void iso_status(int);
361 void iso_getaddr(const char *, int);
362
363 void ieee80211_statistics(void);
364 void ieee80211_status(void);
365
366 /* Known address families */
367 struct afswtch afs[] = {
368 { "inet", AF_INET, in_status, in_getaddr, in_getprefix,
369 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, &ridreq, &in_addreq },
370 #ifdef INET6
371 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix,
372 SIOCDIFADDR_IN6, SIOCAIFADDR_IN6,
373 /*
374 * Deleting the first address before setting new one is
375 * not prefered way in this protocol.
376 */
377 0,
378 &in6_ridreq, &in6_addreq },
379 #endif
380 #ifndef INET_ONLY /* small version, for boot media */
381 { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL,
382 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, &addreq, &addreq },
383 { "ns", AF_NS, xns_status, xns_getaddr, NULL,
384 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, &ridreq, &addreq },
385 { "iso", AF_ISO, iso_status, iso_getaddr, NULL,
386 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, SIOCGIFADDR_ISO,
387 &iso_ridreq, &iso_addreq },
388 #endif /* INET_ONLY */
389 { 0, 0, 0, 0 }
390 };
391
392 struct afswtch *afp; /*the address family being set or asked about*/
393
394 struct afswtch *lookup_af(const char *);
395
396 int
397 main(int argc, char *argv[])
398 {
399 int ch;
400
401 /* Parse command-line options */
402 aflag = mflag = vflag = zflag = 0;
403 while ((ch = getopt(argc, argv, "AabCdlmsuvz"
404 #ifdef INET6
405 "L"
406 #endif
407 )) != -1) {
408 switch (ch) {
409 case 'A':
410 warnx("-A is deprecated");
411 break;
412
413 case 'a':
414 aflag = 1;
415 break;
416
417 case 'b':
418 bflag = 1;
419 break;
420
421 case 'C':
422 Cflag = 1;
423 break;
424
425 case 'd':
426 dflag = 1;
427 break;
428
429 #ifdef INET6
430 case 'L':
431 Lflag = 1;
432 break;
433 #endif
434
435 case 'l':
436 lflag = 1;
437 break;
438
439 case 'm':
440 mflag = 1;
441 break;
442
443 case 's':
444 sflag = 1;
445 break;
446
447 case 'u':
448 uflag = 1;
449 break;
450
451 case 'v':
452 vflag = 1;
453 break;
454
455 case 'z':
456 zflag = 1;
457 break;
458
459
460 default:
461 usage();
462 /* NOTREACHED */
463 }
464 }
465 argc -= optind;
466 argv += optind;
467
468 /*
469 * -l means "list all interfaces", and is mutally exclusive with
470 * all other flags/commands.
471 *
472 * -C means "list all names of cloners", and it mutually exclusive
473 * with all other flags/commands.
474 *
475 * -a means "print status of all interfaces".
476 */
477 if ((lflag || Cflag) && (aflag || mflag || vflag || argc || zflag))
478 usage();
479 #ifdef INET6
480 if ((lflag || Cflag) && Lflag)
481 usage();
482 #endif
483 if (lflag && Cflag)
484 usage();
485 if (Cflag) {
486 if (argc)
487 usage();
488 list_cloners();
489 exit(0);
490 }
491 if (aflag || lflag) {
492 if (argc > 1)
493 usage();
494 else if (argc == 1) {
495 afp = lookup_af(argv[0]);
496 if (afp == NULL)
497 usage();
498 }
499 if (afp)
500 af = ifr.ifr_addr.sa_family = afp->af_af;
501 else
502 af = ifr.ifr_addr.sa_family = afs[0].af_af;
503 printall(NULL);
504 exit(0);
505 }
506
507 /* Make sure there's an interface name. */
508 if (argc < 1)
509 usage();
510 if (strlcpy(name, argv[0], sizeof(name)) >= sizeof(name))
511 errx(1, "interface name '%s' too long", argv[0]);
512 argc--; argv++;
513
514 /*
515 * NOTE: We must special-case the `create' command right
516 * here as we would otherwise fail in getinfo().
517 */
518 if (argc > 0 && strcmp(argv[0], "create") == 0) {
519 clone_create(argv[0], 0);
520 argc--, argv++;
521 if (argc == 0)
522 exit(0);
523 }
524
525 /* Check for address family. */
526 afp = NULL;
527 if (argc > 0) {
528 afp = lookup_af(argv[0]);
529 if (afp != NULL) {
530 argv++;
531 argc--;
532 }
533 }
534
535 /* Initialize af, just for use in getinfo(). */
536 if (afp == NULL)
537 af = afs->af_af;
538 else
539 af = afp->af_af;
540
541 /* Get information about the interface. */
542 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
543 if (getinfo(&ifr) < 0)
544 exit(1);
545
546 if (sflag) {
547 if (argc != 0)
548 usage();
549 else
550 exit(carrier());
551 }
552
553 /* No more arguments means interface status. */
554 if (argc == 0) {
555 printall(name);
556 exit(0);
557 }
558
559 /* The following operations assume inet family as the default. */
560 if (afp == NULL)
561 afp = afs;
562 af = ifr.ifr_addr.sa_family = afp->af_af;
563
564 #ifdef INET6
565 /* initialization */
566 in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
567 in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
568 #endif
569
570 /* Process commands. */
571 while (argc > 0) {
572 const struct cmd *p;
573
574 for (p = cmds; p->c_name; p++)
575 if (strcmp(argv[0], p->c_name) == 0)
576 break;
577 if (p->c_name == 0 && setaddr) {
578 if ((flags & IFF_POINTOPOINT) == 0) {
579 errx(EXIT_FAILURE,
580 "can't set destination address %s",
581 "on non-point-to-point link");
582 }
583 p++; /* got src, do dst */
584 }
585 if (p->c_func != NULL || p->c_func2 != NULL) {
586 if (p->c_parameter == NEXTARG) {
587 if (argc < 2)
588 errx(EXIT_FAILURE,
589 "'%s' requires argument",
590 p->c_name);
591 (*p->c_func)(argv[1], 0);
592 argc--, argv++;
593 } else if (p->c_parameter == NEXTARG2) {
594 if (argc < 3)
595 errx(EXIT_FAILURE,
596 "'%s' requires 2 arguments",
597 p->c_name);
598 (*p->c_func2)(argv[1], argv[2]);
599 argc -= 2, argv += 2;
600 } else
601 (*p->c_func)(argv[0], p->c_parameter);
602 actions |= p->c_action;
603 }
604 argc--, argv++;
605 }
606
607 /*
608 * See if multiple alias, -alias, or delete commands were
609 * specified. More than one constitutes an invalid command line
610 */
611
612 if (conflicting > 1)
613 errx(EXIT_FAILURE,
614 "Only one use of alias, -alias or delete is valid.");
615
616 /* Process any media commands that may have been issued. */
617 process_media_commands();
618
619 if (af == AF_INET6 && explicit_prefix == 0) {
620 /*
621 * Aggregatable address architecture defines all prefixes
622 * are 64. So, it is convenient to set prefixlen to 64 if
623 * it is not specified.
624 */
625 setifprefixlen("64", 0);
626 /* in6_getprefix("64", MASK) if MASK is available here... */
627 }
628
629 #ifndef INET_ONLY
630 if (af == AF_ISO)
631 adjust_nsellength();
632
633 if (af == AF_APPLETALK)
634 checkatrange((struct sockaddr_at *) &addreq.ifra_addr);
635
636 if (setipdst && af==AF_NS) {
637 struct nsip_req rq;
638 int size = sizeof(rq);
639
640 rq.rq_ns = addreq.ifra_addr;
641 rq.rq_ip = addreq.ifra_dstaddr;
642
643 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
644 warn("encapsulation routing");
645 }
646
647 #endif /* INET_ONLY */
648
649 if (clearaddr) {
650 (void) strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name);
651 if (ioctl(s, afp->af_difaddr, afp->af_ridreq) == -1)
652 err(EXIT_FAILURE, "SIOCDIFADDR");
653 }
654 if (newaddr > 0) {
655 (void) strncpy(afp->af_addreq, name, sizeof ifr.ifr_name);
656 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) == -1)
657 warn("SIOCAIFADDR");
658 }
659
660 if (g_ifcr_updated) {
661 (void) strncpy(g_ifcr.ifcr_name, name,
662 sizeof(g_ifcr.ifcr_name));
663 if (ioctl(s, SIOCSIFCAP, &g_ifcr) == -1)
664 err(EXIT_FAILURE, "SIOCSIFCAP");
665 }
666
667 exit(0);
668 }
669
670 struct afswtch *
671 lookup_af(const char *cp)
672 {
673 struct afswtch *a;
674
675 for (a = afs; a->af_name != NULL; a++)
676 if (strcmp(a->af_name, cp) == 0)
677 return (a);
678 return (NULL);
679 }
680
681 void
682 getsock(int naf)
683 {
684 static int oaf = -1;
685
686 if (oaf == naf)
687 return;
688 if (oaf != -1)
689 close(s);
690 s = socket(naf, SOCK_DGRAM, 0);
691 if (s < 0)
692 oaf = -1;
693 else
694 oaf = naf;
695 }
696
697 int
698 getinfo(struct ifreq *giifr)
699 {
700
701 getsock(af);
702 if (s < 0)
703 err(EXIT_FAILURE, "socket");
704 if (ioctl(s, SIOCGIFFLAGS, giifr) == -1) {
705 warn("SIOCGIFFLAGS %s", giifr->ifr_name);
706 return (-1);
707 }
708 flags = giifr->ifr_flags;
709 if (ioctl(s, SIOCGIFMETRIC, giifr) == -1) {
710 warn("SIOCGIFMETRIC %s", giifr->ifr_name);
711 metric = 0;
712 } else
713 metric = giifr->ifr_metric;
714 if (ioctl(s, SIOCGIFMTU, giifr) == -1)
715 mtu = 0;
716 else
717 mtu = giifr->ifr_mtu;
718
719 memset(&g_ifcr, 0, sizeof(g_ifcr));
720 strcpy(g_ifcr.ifcr_name, giifr->ifr_name);
721 (void) ioctl(s, SIOCGIFCAP, &g_ifcr);
722
723 return (0);
724 }
725
726 void
727 printall(const char *ifname)
728 {
729 struct ifaddrs *ifap, *ifa;
730 struct ifreq paifr;
731 const struct sockaddr_dl *sdl = NULL;
732 int idx;
733 char *p;
734
735 if (getifaddrs(&ifap) != 0)
736 err(EXIT_FAILURE, "getifaddrs");
737 p = NULL;
738 idx = 0;
739 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
740 memset(&paifr, 0, sizeof(paifr));
741 strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name));
742 if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) {
743 memcpy(&paifr.ifr_addr, ifa->ifa_addr,
744 ifa->ifa_addr->sa_len);
745 }
746
747 if (ifname && strcmp(ifname, ifa->ifa_name) != 0)
748 continue;
749 if (ifa->ifa_addr->sa_family == AF_LINK)
750 sdl = (const struct sockaddr_dl *) ifa->ifa_addr;
751 if (p && strcmp(p, ifa->ifa_name) == 0)
752 continue;
753 if (strlcpy(name, ifa->ifa_name, sizeof(name)) >= sizeof(name))
754 continue;
755 p = ifa->ifa_name;
756
757 if (getinfo(&paifr) < 0)
758 continue;
759 if (bflag && (ifa->ifa_flags & IFF_BROADCAST) == 0)
760 continue;
761 if (dflag && (ifa->ifa_flags & IFF_UP) != 0)
762 continue;
763 if (uflag && (ifa->ifa_flags & IFF_UP) == 0)
764 continue;
765
766 if (sflag && carrier())
767 continue;
768 idx++;
769 /*
770 * Are we just listing the interfaces?
771 */
772 if (lflag) {
773 if (idx > 1)
774 printf(" ");
775 fputs(name, stdout);
776 continue;
777 }
778
779 status(sdl);
780 sdl = NULL;
781 }
782 if (lflag)
783 printf("\n");
784 freeifaddrs(ifap);
785 }
786
787 void
788 list_cloners(void)
789 {
790 struct if_clonereq ifcr;
791 char *cp, *buf;
792 int idx;
793
794 memset(&ifcr, 0, sizeof(ifcr));
795
796 getsock(AF_INET);
797
798 if (ioctl(s, SIOCIFGCLONERS, &ifcr) == -1)
799 err(EXIT_FAILURE, "SIOCIFGCLONERS for count");
800
801 buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
802 if (buf == NULL)
803 err(EXIT_FAILURE, "unable to allocate cloner name buffer");
804
805 ifcr.ifcr_count = ifcr.ifcr_total;
806 ifcr.ifcr_buffer = buf;
807
808 if (ioctl(s, SIOCIFGCLONERS, &ifcr) == -1)
809 err(EXIT_FAILURE, "SIOCIFGCLONERS for names");
810
811 /*
812 * In case some disappeared in the mean time, clamp it down.
813 */
814 if (ifcr.ifcr_count > ifcr.ifcr_total)
815 ifcr.ifcr_count = ifcr.ifcr_total;
816
817 for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) {
818 if (idx > 0)
819 printf(" ");
820 printf("%s", cp);
821 }
822
823 printf("\n");
824 free(buf);
825 return;
826 }
827
828 /*ARGSUSED*/
829 void
830 clone_create(const char *addr, int param)
831 {
832
833 /* We're called early... */
834 getsock(AF_INET);
835
836 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
837 if (ioctl(s, SIOCIFCREATE, &ifr) == -1)
838 err(EXIT_FAILURE, "SIOCIFCREATE");
839 }
840
841 /*ARGSUSED*/
842 void
843 clone_destroy(const char *addr, int param)
844 {
845
846 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
847 if (ioctl(s, SIOCIFDESTROY, &ifr) == -1)
848 err(EXIT_FAILURE, "SIOCIFDESTROY");
849 }
850
851 #define RIDADDR 0
852 #define ADDR 1
853 #define MASK 2
854 #define DSTADDR 3
855
856 /*ARGSUSED*/
857 void
858 setifaddr(const char *addr, int param)
859 {
860 struct ifreq *siifr; /* XXX */
861
862 /*
863 * Delay the ioctl to set the interface addr until flags are all set.
864 * The address interpretation may depend on the flags,
865 * and the flags may change when the address is set.
866 */
867 setaddr++;
868 if (newaddr == -1)
869 newaddr = 1;
870 if (doalias == 0 && afp->af_gifaddr != 0) {
871 siifr = (struct ifreq *)afp->af_ridreq;
872 (void) strncpy(siifr->ifr_name, name, sizeof(siifr->ifr_name));
873 siifr->ifr_addr.sa_family = afp->af_af;
874 if (ioctl(s, afp->af_gifaddr, afp->af_ridreq) == 0)
875 clearaddr = 1;
876 else if (errno == EADDRNOTAVAIL)
877 /* No address was assigned yet. */
878 ;
879 else
880 err(EXIT_FAILURE, "SIOCGIFADDR");
881 }
882
883 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
884 }
885
886 void
887 setifnetmask(const char *addr, int d)
888 {
889 (*afp->af_getaddr)(addr, MASK);
890 }
891
892 void
893 setifbroadaddr(const char *addr, int d)
894 {
895 (*afp->af_getaddr)(addr, DSTADDR);
896 }
897
898 void
899 setifipdst(const char *addr, int d)
900 {
901 in_getaddr(addr, DSTADDR);
902 setipdst++;
903 clearaddr = 0;
904 newaddr = 0;
905 }
906
907 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
908 /*ARGSUSED*/
909 void
910 notealias(const char *addr, int param)
911 {
912 if (setaddr && doalias == 0 && param < 0)
913 (void) memcpy(rqtosa(af_ridreq), rqtosa(af_addreq),
914 rqtosa(af_addreq)->sa_len);
915 doalias = param;
916 if (param < 0) {
917 clearaddr = 1;
918 newaddr = 0;
919 conflicting++;
920 } else {
921 clearaddr = 0;
922 conflicting++;
923 }
924 }
925
926 /*ARGSUSED*/
927 void
928 notrailers(const char *vname, int value)
929 {
930 puts("Note: trailers are no longer sent, but always received");
931 }
932
933 /*ARGSUSED*/
934 void
935 setifdstaddr(const char *addr, int param)
936 {
937 (*afp->af_getaddr)(addr, DSTADDR);
938 }
939
940 void
941 setifflags(const char *vname, int value)
942 {
943 struct ifreq ifreq;
944
945 (void) strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
946 if (ioctl(s, SIOCGIFFLAGS, &ifreq) == -1)
947 err(EXIT_FAILURE, "SIOCGIFFLAGS");
948 flags = ifreq.ifr_flags;
949
950 if (value < 0) {
951 value = -value;
952 flags &= ~value;
953 } else
954 flags |= value;
955 ifreq.ifr_flags = flags;
956 if (ioctl(s, SIOCSIFFLAGS, &ifreq) == -1)
957 err(EXIT_FAILURE, "SIOCSIFFLAGS");
958 }
959
960 void
961 setifcaps(const char *vname, int value)
962 {
963
964 if (value < 0) {
965 value = -value;
966 g_ifcr.ifcr_capenable &= ~value;
967 } else
968 g_ifcr.ifcr_capenable |= value;
969
970 g_ifcr_updated = 1;
971 }
972
973 #ifdef INET6
974 void
975 setia6flags(const char *vname, int value)
976 {
977
978 if (value < 0) {
979 value = -value;
980 in6_addreq.ifra_flags &= ~value;
981 } else
982 in6_addreq.ifra_flags |= value;
983 }
984
985 void
986 setia6pltime(const char *val, int d)
987 {
988
989 setia6lifetime("pltime", val);
990 }
991
992 void
993 setia6vltime(const char *val, int d)
994 {
995
996 setia6lifetime("vltime", val);
997 }
998
999 void
1000 setia6lifetime(const char *cmd, const char *val)
1001 {
1002 time_t newval, t;
1003 char *ep;
1004
1005 t = time(NULL);
1006 newval = (time_t)strtoul(val, &ep, 0);
1007 if (val == ep)
1008 errx(EXIT_FAILURE, "invalid %s", cmd);
1009 if (afp->af_af != AF_INET6)
1010 errx(EXIT_FAILURE, "%s not allowed for the AF", cmd);
1011 if (strcmp(cmd, "vltime") == 0) {
1012 in6_addreq.ifra_lifetime.ia6t_expire = t + newval;
1013 in6_addreq.ifra_lifetime.ia6t_vltime = newval;
1014 } else if (strcmp(cmd, "pltime") == 0) {
1015 in6_addreq.ifra_lifetime.ia6t_preferred = t + newval;
1016 in6_addreq.ifra_lifetime.ia6t_pltime = newval;
1017 }
1018 }
1019
1020 void
1021 setia6eui64(const char *cmd, int val)
1022 {
1023 struct ifaddrs *ifap, *ifa;
1024 const struct sockaddr_in6 *sin6 = NULL;
1025 const struct in6_addr *lladdr = NULL;
1026 struct in6_addr *in6;
1027
1028 if (afp->af_af != AF_INET6)
1029 errx(EXIT_FAILURE, "%s not allowed for the AF", cmd);
1030 in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr;
1031 if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0)
1032 errx(EXIT_FAILURE, "interface index is already filled");
1033 if (getifaddrs(&ifap) != 0)
1034 err(EXIT_FAILURE, "getifaddrs");
1035 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1036 if (ifa->ifa_addr->sa_family == AF_INET6 &&
1037 strcmp(ifa->ifa_name, name) == 0) {
1038 sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr;
1039 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1040 lladdr = &sin6->sin6_addr;
1041 break;
1042 }
1043 }
1044 }
1045 if (!lladdr)
1046 errx(EXIT_FAILURE, "could not determine link local address");
1047
1048 memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8);
1049
1050 freeifaddrs(ifap);
1051 }
1052 #endif
1053
1054 void
1055 setifmetric(const char *val, int d)
1056 {
1057 char *ep = NULL;
1058
1059 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1060 ifr.ifr_metric = strtoul(val, &ep, 10);
1061 if (!ep || *ep)
1062 errx(EXIT_FAILURE, "%s: invalid metric", val);
1063 if (ioctl(s, SIOCSIFMETRIC, &ifr) == -1)
1064 warn("SIOCSIFMETRIC");
1065 }
1066
1067 void
1068 setifmtu(const char *val, int d)
1069 {
1070 char *ep = NULL;
1071
1072 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1073 ifr.ifr_mtu = strtoul(val, &ep, 10);
1074 if (!ep || *ep)
1075 errx(EXIT_FAILURE, "%s: invalid mtu", val);
1076 if (ioctl(s, SIOCSIFMTU, &ifr) == -1)
1077 warn("SIOCSIFMTU");
1078 }
1079
1080 const char *
1081 get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
1082 {
1083 int len;
1084 int hexstr;
1085 u_int8_t *p;
1086
1087 len = *lenp;
1088 p = buf;
1089 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x');
1090 if (hexstr)
1091 val += 2;
1092 for (;;) {
1093 if (*val == '\0')
1094 break;
1095 if (sep != NULL && strchr(sep, *val) != NULL) {
1096 val++;
1097 break;
1098 }
1099 if (hexstr) {
1100 if (!isxdigit((u_char)val[0]) ||
1101 !isxdigit((u_char)val[1])) {
1102 warnx("bad hexadecimal digits");
1103 return NULL;
1104 }
1105 }
1106 if (p > buf + len) {
1107 if (hexstr)
1108 warnx("hexadecimal digits too long");
1109 else
1110 warnx("strings too long");
1111 return NULL;
1112 }
1113 if (hexstr) {
1114 #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
1115 *p++ = (tohex((u_char)val[0]) << 4) |
1116 tohex((u_char)val[1]);
1117 #undef tohex
1118 val += 2;
1119 } else
1120 *p++ = *val++;
1121 }
1122 len = p - buf;
1123 if (len < *lenp)
1124 memset(p, 0, *lenp - len);
1125 *lenp = len;
1126 return val;
1127 }
1128
1129 void
1130 print_string(const u_int8_t *buf, int len)
1131 {
1132 int i;
1133 int hasspc;
1134
1135 i = 0;
1136 hasspc = 0;
1137 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') {
1138 for (; i < len; i++) {
1139 if (!isprint(buf[i]))
1140 break;
1141 if (isspace(buf[i]))
1142 hasspc++;
1143 }
1144 }
1145 if (i == len) {
1146 if (hasspc || len == 0)
1147 printf("\"%.*s\"", len, buf);
1148 else
1149 printf("%.*s", len, buf);
1150 } else {
1151 printf("0x");
1152 for (i = 0; i < len; i++)
1153 printf("%02x", buf[i]);
1154 }
1155 }
1156
1157 void
1158 setifnwid(const char *val, int d)
1159 {
1160 struct ieee80211_nwid nwid;
1161 int len;
1162
1163 len = sizeof(nwid.i_nwid);
1164 if (get_string(val, NULL, nwid.i_nwid, &len) == NULL)
1165 return;
1166 nwid.i_len = len;
1167 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1168 ifr.ifr_data = (void *)&nwid;
1169 if (ioctl(s, SIOCS80211NWID, &ifr) == -1)
1170 warn("SIOCS80211NWID");
1171 }
1172
1173 void
1174 setifbssid(const char *val, int d)
1175 {
1176 struct ieee80211_bssid bssid;
1177 struct ether_addr *ea;
1178
1179 if (d != 0) {
1180 /* no BSSID is especially desired */
1181 memset(&bssid.i_bssid, 0, sizeof(bssid.i_bssid));
1182 } else {
1183 ea = ether_aton(val);
1184 if (ea == NULL) {
1185 warnx("malformed BSSID: %s", val);
1186 return;
1187 }
1188 memcpy(&bssid.i_bssid, ea->ether_addr_octet,
1189 sizeof(bssid.i_bssid));
1190 }
1191 (void)strncpy(bssid.i_name, name, sizeof(bssid.i_name));
1192 if (ioctl(s, SIOCS80211BSSID, &bssid) == -1)
1193 warn("SIOCS80211BSSID");
1194 }
1195
1196 void
1197 setifchan(const char *val, int d)
1198 {
1199 struct ieee80211chanreq channel;
1200 int chan;
1201
1202 if (d != 0)
1203 chan = IEEE80211_CHAN_ANY;
1204 else {
1205 chan = atoi(val);
1206 if (chan < 0 || chan > 0xffff) {
1207 warnx("invalid channel: %s", val);
1208 return;
1209 }
1210 }
1211
1212 (void)strncpy(channel.i_name, name, sizeof(channel.i_name));
1213 channel.i_channel = (u_int16_t) chan;
1214 if (ioctl(s, SIOCS80211CHANNEL, &channel) == -1)
1215 warn("SIOCS80211CHANNEL");
1216 }
1217
1218 void
1219 setifnwkey(const char *val, int d)
1220 {
1221 struct ieee80211_nwkey nwkey;
1222 int i;
1223 u_int8_t keybuf[IEEE80211_WEP_NKID][16];
1224
1225 nwkey.i_wepon = IEEE80211_NWKEY_WEP;
1226 nwkey.i_defkid = 1;
1227 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1228 nwkey.i_key[i].i_keylen = sizeof(keybuf[i]);
1229 nwkey.i_key[i].i_keydat = keybuf[i];
1230 }
1231 if (d != 0) {
1232 /* disable WEP encryption */
1233 nwkey.i_wepon = 0;
1234 i = 0;
1235 } else if (strcasecmp("persist", val) == 0) {
1236 /* use all values from persistent memory */
1237 nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST;
1238 nwkey.i_defkid = 0;
1239 for (i = 0; i < IEEE80211_WEP_NKID; i++)
1240 nwkey.i_key[i].i_keylen = -1;
1241 } else if (strncasecmp("persist:", val, 8) == 0) {
1242 val += 8;
1243 /* program keys in persistent memory */
1244 nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST;
1245 goto set_nwkey;
1246 } else {
1247 set_nwkey:
1248 if (isdigit((unsigned char)val[0]) && val[1] == ':') {
1249 /* specifying a full set of four keys */
1250 nwkey.i_defkid = val[0] - '0';
1251 val += 2;
1252 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1253 val = get_string(val, ",", keybuf[i],
1254 &nwkey.i_key[i].i_keylen);
1255 if (val == NULL)
1256 return;
1257 }
1258 if (*val != '\0') {
1259 warnx("SIOCS80211NWKEY: too many keys.");
1260 return;
1261 }
1262 } else {
1263 val = get_string(val, NULL, keybuf[0],
1264 &nwkey.i_key[0].i_keylen);
1265 if (val == NULL)
1266 return;
1267 i = 1;
1268 }
1269 }
1270 for (; i < IEEE80211_WEP_NKID; i++)
1271 nwkey.i_key[i].i_keylen = 0;
1272 (void)strncpy(nwkey.i_name, name, sizeof(nwkey.i_name));
1273 if (ioctl(s, SIOCS80211NWKEY, &nwkey) == -1)
1274 warn("SIOCS80211NWKEY");
1275 }
1276
1277 void
1278 setifpowersave(const char *val, int d)
1279 {
1280 struct ieee80211_power power;
1281
1282 (void)strncpy(power.i_name, name, sizeof(power.i_name));
1283 if (ioctl(s, SIOCG80211POWER, &power) == -1) {
1284 warn("SIOCG80211POWER");
1285 return;
1286 }
1287
1288 power.i_enabled = d;
1289 if (ioctl(s, SIOCS80211POWER, &power) == -1)
1290 warn("SIOCS80211POWER");
1291 }
1292
1293 void
1294 setifpowersavesleep(const char *val, int d)
1295 {
1296 struct ieee80211_power power;
1297
1298 (void)strncpy(power.i_name, name, sizeof(power.i_name));
1299 if (ioctl(s, SIOCG80211POWER, &power) == -1) {
1300 warn("SIOCG80211POWER");
1301 return;
1302 }
1303
1304 power.i_maxsleep = atoi(val);
1305 if (ioctl(s, SIOCS80211POWER, &power) == -1)
1306 warn("SIOCS80211POWER");
1307 }
1308
1309 void
1310 ieee80211_statistics(void)
1311 {
1312 struct ieee80211_stats stats;
1313
1314 memset(&ifr, 0, sizeof(ifr));
1315 ifr.ifr_data = (caddr_t)&stats;
1316 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1317 if (ioctl(s, (zflag) ? SIOCG80211ZSTATS : SIOCG80211STATS,
1318 (caddr_t)&ifr) == -1)
1319 return;
1320 #define RX_PRINT(desc, member) printf("\trx " desc ": %u\n", stats.member)
1321 #define TX_PRINT(desc, member) printf("\ttx " desc ": %u\n", stats.member)
1322
1323 RX_PRINT("too short", is_rx_tooshort);
1324 RX_PRINT("bad version", is_rx_badversion);
1325 RX_PRINT("wrong bss", is_rx_wrongbss);
1326 RX_PRINT("duplicate", is_rx_dup);
1327 RX_PRINT("wrong direction", is_rx_wrongdir);
1328 RX_PRINT("multicast echo", is_rx_mcastecho);
1329 RX_PRINT("STA not associated", is_rx_notassoc);
1330 RX_PRINT("WEP-encrypted but WEP not configured", is_rx_nowep);
1331 RX_PRINT("WEP processing failed", is_rx_wepfail);
1332 #if 0
1333 RX_PRINT("single (M)MSDU, both WEP/non-WEP fragments", is_rx_wepmix);
1334 RX_PRINT("non-consecutive fragments", is_rx_fragorder);
1335 #endif
1336 RX_PRINT("decapsulation failed", is_rx_decap);
1337 RX_PRINT("management-type discarded", is_rx_mgtdiscard);
1338 RX_PRINT("control-type discarded", is_rx_ctl);
1339 RX_PRINT("truncated rate set", is_rx_rstoobig);
1340 RX_PRINT("beacon/prresp element missing", is_rx_elem_missing);
1341 RX_PRINT("beacon/prresp element too big", is_rx_elem_toobig);
1342 RX_PRINT("beacon/prresp element too small", is_rx_elem_toosmall);
1343 RX_PRINT("beacon/prresp element unknown", is_rx_elem_unknown);
1344 RX_PRINT("invalid channel", is_rx_badchan);
1345 RX_PRINT("channel mismatch", is_rx_chanmismatch);
1346 RX_PRINT("failed node allocation", is_rx_nodealloc);
1347 RX_PRINT("SSID mismatch", is_rx_ssidmismatch);
1348 RX_PRINT("unsupported authentication algor.", is_rx_auth_unsupported);
1349 RX_PRINT("STA authentication failure", is_rx_auth_fail);
1350 RX_PRINT("association for wrong bss", is_rx_assoc_bss);
1351 RX_PRINT("association without authenication", is_rx_assoc_notauth);
1352 RX_PRINT("association capability mismatch", is_rx_assoc_capmismatch);
1353 RX_PRINT("association without rate match", is_rx_assoc_norate);
1354 RX_PRINT("deauthentication", is_rx_deauth);
1355 RX_PRINT("disassocation", is_rx_disassoc);
1356 RX_PRINT("unknown subtype", is_rx_badsubtype);
1357 RX_PRINT("failed, mbuf unavailable", is_rx_nombuf);
1358 RX_PRINT("failed, bad ICV", is_rx_decryptcrc);
1359 RX_PRINT("discard mgmt frame in ad-hoc demo mode", is_rx_ahdemo_mgt);
1360 RX_PRINT("bad authentication", is_rx_bad_auth);
1361 TX_PRINT("failed, mbuf unavailable", is_tx_nombuf);
1362 TX_PRINT("failed, no node", is_tx_nonode);
1363 TX_PRINT("unknown mgmt frame", is_tx_unknownmgt);
1364 printf("\tactive scans: %u\n", stats.is_scan_active);
1365 printf("\tpassive scans: %u\n", stats.is_scan_passive);
1366 printf("\tnodes timed-out for inactivity: %u\n",
1367 stats.is_node_timeout);
1368 printf("\tcrypto context memory unavailable: %u\n",
1369 stats.is_crypto_nomem);
1370 }
1371
1372 void
1373 ieee80211_status(void)
1374 {
1375 int i, nwkey_verbose;
1376 struct ieee80211_nwid nwid;
1377 struct ieee80211_nwkey nwkey;
1378 struct ieee80211_power power;
1379 u_int8_t keybuf[IEEE80211_WEP_NKID][16];
1380 struct ieee80211_bssid bssid;
1381 struct ieee80211chanreq channel;
1382 struct ether_addr ea;
1383 static const u_int8_t zero_macaddr[IEEE80211_ADDR_LEN];
1384
1385 memset(&ifr, 0, sizeof(ifr));
1386 ifr.ifr_data = (void *)&nwid;
1387 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1388 if (ioctl(s, SIOCG80211NWID, &ifr) == -1)
1389 return;
1390 if (nwid.i_len > IEEE80211_NWID_LEN) {
1391 warnx("SIOCG80211NWID: wrong length of nwid (%d)", nwid.i_len);
1392 return;
1393 }
1394 printf("\tssid ");
1395 print_string(nwid.i_nwid, nwid.i_len);
1396 memset(&nwkey, 0, sizeof(nwkey));
1397 (void)strncpy(nwkey.i_name, name, sizeof(nwkey.i_name));
1398 /* show nwkey only when WEP is enabled */
1399 if (ioctl(s, SIOCG80211NWKEY, &nwkey) == -1 ||
1400 nwkey.i_wepon == 0) {
1401 printf("\n");
1402 goto skip_wep;
1403 }
1404
1405 printf(" nwkey ");
1406 /* try to retrieve WEP keys */
1407 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1408 nwkey.i_key[i].i_keydat = keybuf[i];
1409 nwkey.i_key[i].i_keylen = sizeof(keybuf[i]);
1410 }
1411 if (ioctl(s, SIOCG80211NWKEY, &nwkey) == -1) {
1412 printf("*****");
1413 } else {
1414 nwkey_verbose = 0;
1415 /* check to see non default key or multiple keys defined */
1416 if (nwkey.i_defkid != 1) {
1417 nwkey_verbose = 1;
1418 } else {
1419 for (i = 1; i < IEEE80211_WEP_NKID; i++) {
1420 if (nwkey.i_key[i].i_keylen != 0) {
1421 nwkey_verbose = 1;
1422 break;
1423 }
1424 }
1425 }
1426 /* check extra ambiguity with keywords */
1427 if (!nwkey_verbose) {
1428 if (nwkey.i_key[0].i_keylen >= 2 &&
1429 isdigit(nwkey.i_key[0].i_keydat[0]) &&
1430 nwkey.i_key[0].i_keydat[1] == ':')
1431 nwkey_verbose = 1;
1432 else if (nwkey.i_key[0].i_keylen >= 7 &&
1433 strncasecmp("persist", nwkey.i_key[0].i_keydat, 7)
1434 == 0)
1435 nwkey_verbose = 1;
1436 }
1437 if (nwkey_verbose)
1438 printf("%d:", nwkey.i_defkid);
1439 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1440 if (i > 0)
1441 printf(",");
1442 if (nwkey.i_key[i].i_keylen < 0)
1443 printf("persist");
1444 else
1445 print_string(nwkey.i_key[i].i_keydat,
1446 nwkey.i_key[i].i_keylen);
1447 if (!nwkey_verbose)
1448 break;
1449 }
1450 }
1451 printf("\n");
1452
1453 skip_wep:
1454 (void)strncpy(power.i_name, name, sizeof(power.i_name));
1455 if (ioctl(s, SIOCG80211POWER, &power) == -1)
1456 goto skip_power;
1457 printf("\tpowersave ");
1458 if (power.i_enabled)
1459 printf("on (%dms sleep)", power.i_maxsleep);
1460 else
1461 printf("off");
1462 printf("\n");
1463
1464 skip_power:
1465 (void)strncpy(bssid.i_name, name, sizeof(bssid.i_name));
1466 if (ioctl(s, SIOCG80211BSSID, &bssid) == -1)
1467 return;
1468 (void)strncpy(channel.i_name, name, sizeof(channel.i_name));
1469 if (ioctl(s, SIOCG80211CHANNEL, &channel) == -1)
1470 return;
1471 if (memcmp(bssid.i_bssid, zero_macaddr, IEEE80211_ADDR_LEN) == 0) {
1472 if (channel.i_channel != (u_int16_t)-1)
1473 printf("\tchan %d\n", channel.i_channel);
1474 } else {
1475 memcpy(ea.ether_addr_octet, bssid.i_bssid,
1476 sizeof(ea.ether_addr_octet));
1477 printf("\tbssid %s", ether_ntoa(&ea));
1478 if (channel.i_channel != IEEE80211_CHAN_ANY)
1479 printf(" chan %d", channel.i_channel);
1480 printf("\n");
1481 }
1482 }
1483
1484 static void
1485 media_error(int type, const char *val, const char *opt)
1486 {
1487 errx(EXIT_FAILURE, "unknown %s media %s: %s",
1488 get_media_type_string(type), opt, val);
1489 }
1490
1491 void
1492 init_current_media(void)
1493 {
1494 struct ifmediareq ifmr;
1495
1496 /*
1497 * If we have not yet done so, grab the currently-selected
1498 * media.
1499 */
1500 if ((actions & (A_MEDIA|A_MEDIAOPT|A_MEDIAMODE)) == 0) {
1501 (void) memset(&ifmr, 0, sizeof(ifmr));
1502 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
1503
1504 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) {
1505 /*
1506 * If we get E2BIG, the kernel is telling us
1507 * that there are more, so we can ignore it.
1508 */
1509 if (errno != E2BIG)
1510 err(EXIT_FAILURE, "SGIOCGIFMEDIA");
1511 }
1512
1513 media_current = ifmr.ifm_current;
1514 }
1515
1516 /* Sanity. */
1517 if (IFM_TYPE(media_current) == 0)
1518 errx(EXIT_FAILURE, "%s: no link type?", name);
1519 }
1520
1521 void
1522 process_media_commands(void)
1523 {
1524
1525 if ((actions & (A_MEDIA|A_MEDIAOPT|A_MEDIAMODE)) == 0) {
1526 /* Nothing to do. */
1527 return;
1528 }
1529
1530 /*
1531 * Media already set up, and commands sanity-checked. Set/clear
1532 * any options, and we're ready to go.
1533 */
1534 media_current |= mediaopt_set;
1535 media_current &= ~mediaopt_clear;
1536
1537 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1538 ifr.ifr_media = media_current;
1539
1540 if (ioctl(s, SIOCSIFMEDIA, &ifr) == -1)
1541 err(EXIT_FAILURE, "SIOCSIFMEDIA");
1542 }
1543
1544 void
1545 setmedia(const char *val, int d)
1546 {
1547 int type, subtype, inst;
1548
1549 init_current_media();
1550
1551 /* Only one media command may be given. */
1552 if (actions & A_MEDIA)
1553 errx(EXIT_FAILURE, "only one `media' command may be issued");
1554
1555 /* Must not come after mode commands */
1556 if (actions & A_MEDIAMODE)
1557 errx(EXIT_FAILURE,
1558 "may not issue `media' after `mode' commands");
1559
1560 /* Must not come after mediaopt commands */
1561 if (actions & A_MEDIAOPT)
1562 errx(EXIT_FAILURE,
1563 "may not issue `media' after `mediaopt' commands");
1564
1565 /*
1566 * No need to check if `instance' has been issued; setmediainst()
1567 * craps out if `media' has not been specified.
1568 */
1569
1570 type = IFM_TYPE(media_current);
1571 inst = IFM_INST(media_current);
1572
1573 /* Look up the subtype. */
1574 subtype = get_media_subtype(type, val);
1575 if (subtype == -1)
1576 media_error(type, val, "subtype");
1577
1578 /* Build the new current media word. */
1579 media_current = IFM_MAKEWORD(type, subtype, 0, inst);
1580
1581 /* Media will be set after other processing is complete. */
1582 }
1583
1584 void
1585 setmediaopt(const char *val, int d)
1586 {
1587 char *invalid;
1588
1589 init_current_media();
1590
1591 /* Can only issue `mediaopt' once. */
1592 if (actions & A_MEDIAOPTSET)
1593 errx(EXIT_FAILURE, "only one `mediaopt' command may be issued");
1594
1595 /* Can't issue `mediaopt' if `instance' has already been issued. */
1596 if (actions & A_MEDIAINST)
1597 errx(EXIT_FAILURE, "may not issue `mediaopt' after `instance'");
1598
1599 mediaopt_set = get_media_options(media_current, val, &invalid);
1600 if (mediaopt_set == -1)
1601 media_error(media_current, invalid, "option");
1602
1603 /* Media will be set after other processing is complete. */
1604 }
1605
1606 void
1607 unsetmediaopt(const char *val, int d)
1608 {
1609 char *invalid;
1610
1611 init_current_media();
1612
1613 /* Can only issue `-mediaopt' once. */
1614 if (actions & A_MEDIAOPTCLR)
1615 errx(EXIT_FAILURE,
1616 "only one `-mediaopt' command may be issued");
1617
1618 /* May not issue `media' and `-mediaopt'. */
1619 if (actions & A_MEDIA)
1620 errx(EXIT_FAILURE,
1621 "may not issue both `media' and `-mediaopt'");
1622
1623 /*
1624 * No need to check for A_MEDIAINST, since the test for A_MEDIA
1625 * implicitly checks for A_MEDIAINST.
1626 */
1627
1628 mediaopt_clear = get_media_options(media_current, val, &invalid);
1629 if (mediaopt_clear == -1)
1630 media_error(media_current, invalid, "option");
1631
1632 /* Media will be set after other processing is complete. */
1633 }
1634
1635 void
1636 setmediainst(const char *val, int d)
1637 {
1638 int type, subtype, options, inst;
1639
1640 init_current_media();
1641
1642 /* Can only issue `instance' once. */
1643 if (actions & A_MEDIAINST)
1644 errx(EXIT_FAILURE, "only one `instance' command may be issued");
1645
1646 /* Must have already specified `media' */
1647 if ((actions & A_MEDIA) == 0)
1648 errx(EXIT_FAILURE, "must specify `media' before `instance'");
1649
1650 type = IFM_TYPE(media_current);
1651 subtype = IFM_SUBTYPE(media_current);
1652 options = IFM_OPTIONS(media_current);
1653
1654 inst = atoi(val);
1655 if (inst < 0 || inst > IFM_INST_MAX)
1656 errx(EXIT_FAILURE, "invalid media instance: %s", val);
1657
1658 media_current = IFM_MAKEWORD(type, subtype, options, inst);
1659
1660 /* Media will be set after other processing is complete. */
1661 }
1662
1663 void
1664 setmediamode(const char *val, int d)
1665 {
1666 int type, subtype, options, inst, mode;
1667
1668 init_current_media();
1669
1670 /* Can only issue `mode' once. */
1671 if (actions & A_MEDIAMODE)
1672 errx(EXIT_FAILURE, "only one `mode' command may be issued");
1673
1674 type = IFM_TYPE(media_current);
1675 subtype = IFM_SUBTYPE(media_current);
1676 options = IFM_OPTIONS(media_current);
1677 inst = IFM_INST(media_current);
1678
1679 mode = get_media_mode(type, val);
1680 if (mode == -1)
1681 media_error(type, val, "mode");
1682
1683 media_current = IFM_MAKEWORD(type, subtype, options, inst) | mode;
1684
1685 /* Media will be set after other processing is complete. */
1686 }
1687
1688 void
1689 print_media_word(int ifmw, const char *opt_sep)
1690 {
1691 const char *str;
1692
1693 printf("%s", get_media_subtype_string(ifmw));
1694
1695 /* Find mode. */
1696 if (IFM_MODE(ifmw) != 0) {
1697 str = get_media_mode_string(ifmw);
1698 if (str != NULL)
1699 printf(" mode %s", str);
1700 }
1701
1702 /* Find options. */
1703 for (; (str = get_media_option_string(&ifmw)) != NULL; opt_sep = ",")
1704 printf("%s%s", opt_sep, str);
1705
1706 if (IFM_INST(ifmw) != 0)
1707 printf(" instance %d", IFM_INST(ifmw));
1708 }
1709
1710 int
1711 carrier(void)
1712 {
1713 struct ifmediareq ifmr;
1714
1715 (void) memset(&ifmr, 0, sizeof(ifmr));
1716 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
1717
1718 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) {
1719 /*
1720 * Interface doesn't support SIOC{G,S}IFMEDIA;
1721 * assume ok.
1722 */
1723 return 0;
1724 }
1725 if ((ifmr.ifm_status & IFM_AVALID) == 0) {
1726 /*
1727 * Interface doesn't report media-valid status.
1728 * assume ok.
1729 */
1730 return 0;
1731 }
1732 /* otherwise, return ok for active, not-ok if not active. */
1733 return !(ifmr.ifm_status & IFM_ACTIVE);
1734 }
1735
1736
1737 #define IFFBITS \
1738 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
1739 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
1740
1741 #define IFCAPBITS \
1742 "\020\1IP4CSUM\2TCP4CSUM\3UDP4CSUM\4TCP6CSUM\5UDP6CSUM\6TCP4CSUM_Rx\7UDP4CSUM_Rx\10TSO4"
1743
1744 const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST;
1745
1746 const struct ifmedia_status_description ifm_status_descriptions[] =
1747 IFM_STATUS_DESCRIPTIONS;
1748
1749 /*
1750 * Print the status of the interface. If an address family was
1751 * specified, show it and it only; otherwise, show them all.
1752 */
1753 void
1754 status(const struct sockaddr_dl *sdl)
1755 {
1756 struct afswtch *p = afp;
1757 struct ifmediareq ifmr;
1758 struct ifdatareq ifdr;
1759 int *media_list, i;
1760 char hbuf[NI_MAXHOST];
1761 char fbuf[BUFSIZ];
1762
1763 (void)snprintb(fbuf, sizeof(fbuf), IFFBITS, flags);
1764 printf("%s: flags=%s", name, &fbuf[2]);
1765 if (metric)
1766 printf(" metric %lu", metric);
1767 if (mtu)
1768 printf(" mtu %lu", mtu);
1769 printf("\n");
1770
1771 if (g_ifcr.ifcr_capabilities) {
1772 (void)snprintb(fbuf, sizeof(fbuf), IFCAPBITS,
1773 g_ifcr.ifcr_capabilities);
1774 printf("\tcapabilities=%s\n", &fbuf[2]);
1775 (void)snprintb(fbuf, sizeof(fbuf), IFCAPBITS,
1776 g_ifcr.ifcr_capenable);
1777 printf("\tenabled=%s\n", &fbuf[2]);
1778 }
1779
1780 ieee80211_status();
1781 vlan_status();
1782 tunnel_status();
1783 agr_status();
1784
1785 if (sdl != NULL &&
1786 getnameinfo((const struct sockaddr *)sdl, sdl->sdl_len,
1787 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0 &&
1788 hbuf[0] != '\0')
1789 printf("\taddress: %s\n", hbuf);
1790
1791 (void) memset(&ifmr, 0, sizeof(ifmr));
1792 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
1793
1794 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) {
1795 /*
1796 * Interface doesn't support SIOC{G,S}IFMEDIA.
1797 */
1798 goto iface_stats;
1799 }
1800
1801 if (ifmr.ifm_count == 0) {
1802 warnx("%s: no media types?", name);
1803 goto iface_stats;
1804 }
1805
1806 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
1807 if (media_list == NULL)
1808 err(EXIT_FAILURE, "malloc");
1809 ifmr.ifm_ulist = media_list;
1810
1811 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1)
1812 err(EXIT_FAILURE, "SIOCGIFMEDIA");
1813
1814 printf("\tmedia: %s ", get_media_type_string(ifmr.ifm_current));
1815 print_media_word(ifmr.ifm_current, " ");
1816 if (ifmr.ifm_active != ifmr.ifm_current) {
1817 printf(" (");
1818 print_media_word(ifmr.ifm_active, " ");
1819 printf(")");
1820 }
1821 printf("\n");
1822
1823 if (ifmr.ifm_status & IFM_STATUS_VALID) {
1824 const struct ifmedia_status_description *ifms;
1825 int bitno, found = 0;
1826
1827 printf("\tstatus: ");
1828 for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) {
1829 for (ifms = ifm_status_descriptions;
1830 ifms->ifms_valid != 0; ifms++) {
1831 if (ifms->ifms_type !=
1832 IFM_TYPE(ifmr.ifm_current) ||
1833 ifms->ifms_valid !=
1834 ifm_status_valid_list[bitno])
1835 continue;
1836 printf("%s%s", found ? ", " : "",
1837 IFM_STATUS_DESC(ifms, ifmr.ifm_status));
1838 found = 1;
1839
1840 /*
1841 * For each valid indicator bit, there's
1842 * only one entry for each media type, so
1843 * terminate the inner loop now.
1844 */
1845 break;
1846 }
1847 }
1848
1849 if (found == 0)
1850 printf("unknown");
1851 printf("\n");
1852 }
1853
1854 if (mflag) {
1855 int type, printed_type;
1856
1857 for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) {
1858 for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) {
1859 if (IFM_TYPE(media_list[i]) != type)
1860 continue;
1861 if (printed_type == 0) {
1862 printf("\tsupported %s media:\n",
1863 get_media_type_string(type));
1864 printed_type = 1;
1865 }
1866 printf("\t\tmedia ");
1867 print_media_word(media_list[i], " mediaopt ");
1868 printf("\n");
1869 }
1870 }
1871 }
1872
1873 free(media_list);
1874
1875 iface_stats:
1876 if (!vflag && !zflag)
1877 goto proto_status;
1878
1879 (void) strncpy(ifdr.ifdr_name, name, sizeof(ifdr.ifdr_name));
1880
1881 if (ioctl(s, zflag ? SIOCZIFDATA:SIOCGIFDATA, &ifdr) == -1) {
1882 err(EXIT_FAILURE, zflag ? "SIOCZIFDATA" : "SIOCGIFDATA");
1883 } else {
1884 struct if_data * const ifi = &ifdr.ifdr_data;
1885 #define PLURAL(n) ((n) == 1 ? "" : "s")
1886 printf("\tinput: %llu packet%s, %llu byte%s",
1887 (unsigned long long) ifi->ifi_ipackets,
1888 PLURAL(ifi->ifi_ipackets),
1889 (unsigned long long) ifi->ifi_ibytes,
1890 PLURAL(ifi->ifi_ibytes));
1891 if (ifi->ifi_imcasts)
1892 printf(", %llu multicast%s",
1893 (unsigned long long) ifi->ifi_imcasts,
1894 PLURAL(ifi->ifi_imcasts));
1895 if (ifi->ifi_ierrors)
1896 printf(", %llu error%s",
1897 (unsigned long long) ifi->ifi_ierrors,
1898 PLURAL(ifi->ifi_ierrors));
1899 if (ifi->ifi_iqdrops)
1900 printf(", %llu queue drop%s",
1901 (unsigned long long) ifi->ifi_iqdrops,
1902 PLURAL(ifi->ifi_iqdrops));
1903 if (ifi->ifi_noproto)
1904 printf(", %llu unknown protocol",
1905 (unsigned long long) ifi->ifi_noproto);
1906 printf("\n\toutput: %llu packet%s, %llu byte%s",
1907 (unsigned long long) ifi->ifi_opackets,
1908 PLURAL(ifi->ifi_opackets),
1909 (unsigned long long) ifi->ifi_obytes,
1910 PLURAL(ifi->ifi_obytes));
1911 if (ifi->ifi_omcasts)
1912 printf(", %llu multicast%s",
1913 (unsigned long long) ifi->ifi_omcasts,
1914 PLURAL(ifi->ifi_omcasts));
1915 if (ifi->ifi_oerrors)
1916 printf(", %llu error%s",
1917 (unsigned long long) ifi->ifi_oerrors,
1918 PLURAL(ifi->ifi_oerrors));
1919 if (ifi->ifi_collisions)
1920 printf(", %llu collision%s",
1921 (unsigned long long) ifi->ifi_collisions,
1922 PLURAL(ifi->ifi_collisions));
1923 printf("\n");
1924 #undef PLURAL
1925 }
1926
1927 ieee80211_statistics();
1928
1929 proto_status:
1930 if ((p = afp) != NULL) {
1931 (*p->af_status)(1);
1932 } else for (p = afs; p->af_name; p++) {
1933 ifr.ifr_addr.sa_family = p->af_af;
1934 (*p->af_status)(0);
1935 }
1936 }
1937
1938 void
1939 in_alias(struct ifreq *creq)
1940 {
1941 struct sockaddr_in *iasin;
1942 int alias;
1943
1944 if (lflag)
1945 return;
1946
1947 alias = 1;
1948
1949 /* Get the non-alias address for this interface. */
1950 getsock(AF_INET);
1951 if (s < 0) {
1952 if (errno == EPROTONOSUPPORT)
1953 return;
1954 err(EXIT_FAILURE, "socket");
1955 }
1956 (void) memset(&ifr, 0, sizeof(ifr));
1957 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1958 if (ioctl(s, SIOCGIFADDR, &ifr) == -1) {
1959 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1960 return;
1961 } else
1962 warn("SIOCGIFADDR");
1963 }
1964 /* If creq and ifr are the same address, this is not an alias. */
1965 if (memcmp(&ifr.ifr_addr, &creq->ifr_addr,
1966 sizeof(creq->ifr_addr)) == 0)
1967 alias = 0;
1968 (void) memset(&in_addreq, 0, sizeof(in_addreq));
1969 (void) strncpy(in_addreq.ifra_name, name, sizeof(in_addreq.ifra_name));
1970 memcpy(&in_addreq.ifra_addr, &creq->ifr_addr,
1971 sizeof(in_addreq.ifra_addr));
1972 if (ioctl(s, SIOCGIFALIAS, &in_addreq) == -1) {
1973 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1974 return;
1975 } else
1976 warn("SIOCGIFALIAS");
1977 }
1978
1979 iasin = &in_addreq.ifra_addr;
1980 printf("\tinet %s%s", alias ? "alias " : "", inet_ntoa(iasin->sin_addr));
1981
1982 if (flags & IFF_POINTOPOINT) {
1983 iasin = &in_addreq.ifra_dstaddr;
1984 printf(" -> %s", inet_ntoa(iasin->sin_addr));
1985 }
1986
1987 iasin = &in_addreq.ifra_mask;
1988 printf(" netmask 0x%x", ntohl(iasin->sin_addr.s_addr));
1989
1990 if (flags & IFF_BROADCAST) {
1991 iasin = &in_addreq.ifra_broadaddr;
1992 printf(" broadcast %s", inet_ntoa(iasin->sin_addr));
1993 }
1994 printf("\n");
1995 }
1996
1997 void
1998 in_status(int force)
1999 {
2000 struct ifaddrs *ifap, *ifa;
2001 struct ifreq isifr;
2002
2003 if (getifaddrs(&ifap) != 0)
2004 err(EXIT_FAILURE, "getifaddrs");
2005 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2006 if (strcmp(name, ifa->ifa_name) != 0)
2007 continue;
2008 if (ifa->ifa_addr->sa_family != AF_INET)
2009 continue;
2010 if (sizeof(isifr.ifr_addr) < ifa->ifa_addr->sa_len)
2011 continue;
2012
2013 memset(&isifr, 0, sizeof(isifr));
2014 strncpy(isifr.ifr_name, ifa->ifa_name, sizeof(isifr.ifr_name));
2015 memcpy(&isifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
2016 in_alias(&isifr);
2017 }
2018 freeifaddrs(ifap);
2019 }
2020
2021 void
2022 setifprefixlen(const char *addr, int d)
2023 {
2024 if (*afp->af_getprefix)
2025 (*afp->af_getprefix)(addr, MASK);
2026 explicit_prefix = 1;
2027 }
2028
2029 #ifdef INET6
2030 void
2031 in6_fillscopeid(struct sockaddr_in6 *sin6)
2032 {
2033 #if defined(__KAME__) && defined(KAME_SCOPEID)
2034 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
2035 sin6->sin6_scope_id =
2036 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
2037 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
2038 }
2039 #endif
2040 }
2041
2042 /* XXX not really an alias */
2043 void
2044 in6_alias(struct in6_ifreq *creq)
2045 {
2046 struct sockaddr_in6 *sin6;
2047 char hbuf[NI_MAXHOST];
2048 u_int32_t scopeid;
2049 const int niflag = NI_NUMERICHOST;
2050
2051 /* Get the non-alias address for this interface. */
2052 getsock(AF_INET6);
2053 if (s < 0) {
2054 if (errno == EPROTONOSUPPORT)
2055 return;
2056 err(EXIT_FAILURE, "socket");
2057 }
2058
2059 sin6 = (struct sockaddr_in6 *)&creq->ifr_addr;
2060
2061 in6_fillscopeid(sin6);
2062 scopeid = sin6->sin6_scope_id;
2063 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
2064 hbuf, sizeof(hbuf), NULL, 0, niflag))
2065 strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
2066 printf("\tinet6 %s", hbuf);
2067
2068 if (flags & IFF_POINTOPOINT) {
2069 (void) memset(&ifr6, 0, sizeof(ifr6));
2070 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
2071 ifr6.ifr_addr = creq->ifr_addr;
2072 if (ioctl(s, SIOCGIFDSTADDR_IN6, &ifr6) == -1) {
2073 if (errno != EADDRNOTAVAIL)
2074 warn("SIOCGIFDSTADDR_IN6");
2075 (void) memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr));
2076 ifr6.ifr_addr.sin6_family = AF_INET6;
2077 ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
2078 }
2079 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
2080 in6_fillscopeid(sin6);
2081 hbuf[0] = '\0';
2082 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
2083 hbuf, sizeof(hbuf), NULL, 0, niflag))
2084 strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
2085 printf(" -> %s", hbuf);
2086 }
2087
2088 (void) memset(&ifr6, 0, sizeof(ifr6));
2089 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
2090 ifr6.ifr_addr = creq->ifr_addr;
2091 if (ioctl(s, SIOCGIFNETMASK_IN6, &ifr6) == -1) {
2092 if (errno != EADDRNOTAVAIL)
2093 warn("SIOCGIFNETMASK_IN6");
2094 } else {
2095 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
2096 printf(" prefixlen %d", prefix(&sin6->sin6_addr,
2097 sizeof(struct in6_addr)));
2098 }
2099
2100 (void) memset(&ifr6, 0, sizeof(ifr6));
2101 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
2102 ifr6.ifr_addr = creq->ifr_addr;
2103 if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == -1) {
2104 if (errno != EADDRNOTAVAIL)
2105 warn("SIOCGIFAFLAG_IN6");
2106 } else {
2107 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
2108 printf(" anycast");
2109 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
2110 printf(" tentative");
2111 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED)
2112 printf(" duplicated");
2113 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED)
2114 printf(" detached");
2115 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
2116 printf(" deprecated");
2117 }
2118
2119 if (scopeid)
2120 printf(" scopeid 0x%x", scopeid);
2121
2122 if (Lflag) {
2123 struct in6_addrlifetime *lifetime;
2124 (void) memset(&ifr6, 0, sizeof(ifr6));
2125 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
2126 ifr6.ifr_addr = creq->ifr_addr;
2127 lifetime = &ifr6.ifr_ifru.ifru_lifetime;
2128 if (ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) == -1) {
2129 if (errno != EADDRNOTAVAIL)
2130 warn("SIOCGIFALIFETIME_IN6");
2131 } else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) {
2132 time_t t = time(NULL);
2133 printf(" pltime ");
2134 if (lifetime->ia6t_preferred) {
2135 printf("%s", lifetime->ia6t_preferred < t
2136 ? "0"
2137 : sec2str(lifetime->ia6t_preferred - t));
2138 } else
2139 printf("infty");
2140
2141 printf(" vltime ");
2142 if (lifetime->ia6t_expire) {
2143 printf("%s", lifetime->ia6t_expire < t
2144 ? "0"
2145 : sec2str(lifetime->ia6t_expire - t));
2146 } else
2147 printf("infty");
2148 }
2149 }
2150
2151 printf("\n");
2152 }
2153
2154 void
2155 in6_status(int force)
2156 {
2157 struct ifaddrs *ifap, *ifa;
2158 struct in6_ifreq isifr;
2159
2160 if (getifaddrs(&ifap) != 0)
2161 err(EXIT_FAILURE, "getifaddrs");
2162 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2163 if (strcmp(name, ifa->ifa_name) != 0)
2164 continue;
2165 if (ifa->ifa_addr->sa_family != AF_INET6)
2166 continue;
2167 if (sizeof(isifr.ifr_addr) < ifa->ifa_addr->sa_len)
2168 continue;
2169
2170 memset(&isifr, 0, sizeof(isifr));
2171 strncpy(isifr.ifr_name, ifa->ifa_name, sizeof(isifr.ifr_name));
2172 memcpy(&isifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
2173 in6_alias(&isifr);
2174 }
2175 freeifaddrs(ifap);
2176 }
2177 #endif /*INET6*/
2178
2179 #ifndef INET_ONLY
2180
2181 void
2182 at_status(int force)
2183 {
2184 struct sockaddr_at *sat, null_sat;
2185 struct netrange *nr;
2186
2187 getsock(AF_APPLETALK);
2188 if (s < 0) {
2189 if (errno == EPROTONOSUPPORT)
2190 return;
2191 err(EXIT_FAILURE, "socket");
2192 }
2193 (void) memset(&ifr, 0, sizeof(ifr));
2194 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2195 if (ioctl(s, SIOCGIFADDR, &ifr) == -1) {
2196 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
2197 if (!force)
2198 return;
2199 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
2200 } else
2201 warn("SIOCGIFADDR");
2202 }
2203 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
2204 sat = (struct sockaddr_at *)&ifr.ifr_addr;
2205
2206 (void) memset(&null_sat, 0, sizeof(null_sat));
2207
2208 nr = (struct netrange *) &sat->sat_zero;
2209 printf("\tatalk %d.%d range %d-%d phase %d",
2210 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
2211 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase);
2212 if (flags & IFF_POINTOPOINT) {
2213 if (ioctl(s, SIOCGIFDSTADDR, &ifr) == -1) {
2214 if (errno == EADDRNOTAVAIL)
2215 (void) memset(&ifr.ifr_addr, 0,
2216 sizeof(ifr.ifr_addr));
2217 else
2218 warn("SIOCGIFDSTADDR");
2219 }
2220 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
2221 sat = (struct sockaddr_at *)&ifr.ifr_dstaddr;
2222 if (!sat)
2223 sat = &null_sat;
2224 printf("--> %d.%d",
2225 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
2226 }
2227 if (flags & IFF_BROADCAST) {
2228 /* note RTAX_BRD overlap with IFF_POINTOPOINT */
2229 sat = (struct sockaddr_at *)&ifr.ifr_broadaddr;
2230 if (sat)
2231 printf(" broadcast %d.%d", ntohs(sat->sat_addr.s_net),
2232 sat->sat_addr.s_node);
2233 }
2234 printf("\n");
2235 }
2236
2237 void
2238 xns_status(int force)
2239 {
2240 struct sockaddr_ns *sns;
2241
2242 getsock(AF_NS);
2243 if (s < 0) {
2244 if (errno == EPROTONOSUPPORT)
2245 return;
2246 err(EXIT_FAILURE, "socket");
2247 }
2248 (void) memset(&ifr, 0, sizeof(ifr));
2249 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2250 if (ioctl(s, SIOCGIFADDR, &ifr) == -1) {
2251 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
2252 if (!force)
2253 return;
2254 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
2255 } else
2256 warn("SIOCGIFADDR");
2257 }
2258 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
2259 sns = (struct sockaddr_ns *)&ifr.ifr_addr;
2260 printf("\tns %s ", ns_ntoa(sns->sns_addr));
2261 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
2262 if (ioctl(s, SIOCGIFDSTADDR, &ifr) == -1) {
2263 if (errno == EADDRNOTAVAIL)
2264 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
2265 else
2266 warn("SIOCGIFDSTADDR");
2267 }
2268 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
2269 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
2270 printf("--> %s ", ns_ntoa(sns->sns_addr));
2271 }
2272 printf("\n");
2273 }
2274
2275 void
2276 iso_status(int force)
2277 {
2278 struct sockaddr_iso *siso;
2279 struct iso_ifreq isoifr;
2280
2281 getsock(AF_ISO);
2282 if (s < 0) {
2283 if (errno == EPROTONOSUPPORT)
2284 return;
2285 err(EXIT_FAILURE, "socket");
2286 }
2287 (void) memset(&isoifr, 0, sizeof(isoifr));
2288 (void) strncpy(isoifr.ifr_name, name, sizeof(isoifr.ifr_name));
2289 if (ioctl(s, SIOCGIFADDR_ISO, &isoifr) == -1) {
2290 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
2291 if (!force)
2292 return;
2293 (void) memset(&isoifr.ifr_Addr, 0,
2294 sizeof(isoifr.ifr_Addr));
2295 } else
2296 warn("SIOCGIFADDR_ISO");
2297 }
2298 (void) strncpy(isoifr.ifr_name, name, sizeof isoifr.ifr_name);
2299 siso = &isoifr.ifr_Addr;
2300 printf("\tiso %s ", iso_ntoa(&siso->siso_addr));
2301 if (ioctl(s, SIOCGIFNETMASK_ISO, &isoifr) == -1) {
2302 if (errno == EADDRNOTAVAIL)
2303 memset(&isoifr.ifr_Addr, 0, sizeof(isoifr.ifr_Addr));
2304 else
2305 warn("SIOCGIFNETMASK_ISO");
2306 } else {
2307 if (siso->siso_len > offsetof(struct sockaddr_iso, siso_addr))
2308 siso->siso_addr.isoa_len = siso->siso_len
2309 - offsetof(struct sockaddr_iso, siso_addr);
2310 printf("\n\t\tnetmask %s ", iso_ntoa(&siso->siso_addr));
2311 }
2312 if (flags & IFF_POINTOPOINT) {
2313 if (ioctl(s, SIOCGIFDSTADDR_ISO, &isoifr) == -1) {
2314 if (errno == EADDRNOTAVAIL)
2315 memset(&isoifr.ifr_Addr, 0,
2316 sizeof(isoifr.ifr_Addr));
2317 else
2318 warn("SIOCGIFDSTADDR_ISO");
2319 }
2320 (void) strncpy(isoifr.ifr_name, name, sizeof (isoifr.ifr_name));
2321 siso = &isoifr.ifr_Addr;
2322 printf("--> %s ", iso_ntoa(&siso->siso_addr));
2323 }
2324 printf("\n");
2325 }
2326
2327 #endif /* INET_ONLY */
2328
2329 #define SIN(x) ((struct sockaddr_in *) &(x))
2330 struct sockaddr_in *sintab[] = {
2331 SIN(ridreq.ifr_addr), SIN(in_addreq.ifra_addr),
2332 SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr)};
2333
2334 void
2335 in_getaddr(const char *str, int which)
2336 {
2337 struct sockaddr_in *gasin = sintab[which];
2338 struct hostent *hp;
2339 struct netent *np;
2340
2341 gasin->sin_len = sizeof(*gasin);
2342 if (which != MASK)
2343 gasin->sin_family = AF_INET;
2344
2345 if (which == ADDR) {
2346 char *p = NULL;
2347 if ((p = strrchr(str, '/')) != NULL) {
2348 *p = '\0';
2349 in_getprefix(p + 1, MASK);
2350 }
2351 }
2352
2353 if (inet_aton(str, &gasin->sin_addr) == 0) {
2354 if ((hp = gethostbyname(str)) != NULL)
2355 (void) memcpy(&gasin->sin_addr, hp->h_addr, hp->h_length);
2356 else if ((np = getnetbyname(str)) != NULL)
2357 gasin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
2358 else
2359 errx(EXIT_FAILURE, "%s: bad value", str);
2360 }
2361 }
2362
2363 void
2364 in_getprefix(const char *plen, int which)
2365 {
2366 struct sockaddr_in *igsin = sintab[which];
2367 u_char *cp;
2368 int len = strtol(plen, (char **)NULL, 10);
2369
2370 if ((len < 0) || (len > 32))
2371 errx(EXIT_FAILURE, "%s: bad value", plen);
2372 igsin->sin_len = sizeof(*igsin);
2373 if (which != MASK)
2374 igsin->sin_family = AF_INET;
2375 if ((len == 0) || (len == 32)) {
2376 memset(&igsin->sin_addr, 0xff, sizeof(struct in_addr));
2377 return;
2378 }
2379 memset((void *)&igsin->sin_addr, 0x00, sizeof(igsin->sin_addr));
2380 for (cp = (u_char *)&igsin->sin_addr; len > 7; len -= 8)
2381 *cp++ = 0xff;
2382 if (len)
2383 *cp = 0xff << (8 - len);
2384 }
2385
2386 #ifdef INET6
2387 #define SIN6(x) ((struct sockaddr_in6 *) &(x))
2388 struct sockaddr_in6 *sin6tab[] = {
2389 SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr),
2390 SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)};
2391
2392 void
2393 in6_getaddr(const char *str, int which)
2394 {
2395 #if defined(__KAME__) && defined(KAME_SCOPEID)
2396 struct sockaddr_in6 *sin6 = sin6tab[which];
2397 struct addrinfo hints, *res;
2398 int error;
2399 char *slash = NULL;
2400
2401 if (which == ADDR) {
2402 if ((slash = strrchr(str, '/')) != NULL)
2403 *slash = '\0';
2404 }
2405
2406 memset(&hints, 0, sizeof(hints));
2407 hints.ai_family = AF_INET6;
2408 hints.ai_socktype = SOCK_DGRAM;
2409 #if 0 /* in_getaddr() allows FQDN */
2410 hints.ai_flags = AI_NUMERICHOST;
2411 #endif
2412 error = getaddrinfo(str, "0", &hints, &res);
2413 if (error && slash) {
2414 /* try again treating the '/' as part of the name */
2415 *slash = '/';
2416 slash = NULL;
2417 error = getaddrinfo(str, "0", &hints, &res);
2418 }
2419 if (error)
2420 errx(EXIT_FAILURE, "%s: %s", str, gai_strerror(error));
2421 if (res->ai_next)
2422 errx(EXIT_FAILURE, "%s: resolved to multiple addresses", str);
2423 if (res->ai_addrlen != sizeof(struct sockaddr_in6))
2424 errx(EXIT_FAILURE, "%s: bad value", str);
2425 memcpy(sin6, res->ai_addr, res->ai_addrlen);
2426 freeaddrinfo(res);
2427 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && sin6->sin6_scope_id) {
2428 *(u_int16_t *)&sin6->sin6_addr.s6_addr[2] =
2429 htons(sin6->sin6_scope_id);
2430 sin6->sin6_scope_id = 0;
2431 }
2432 if (slash) {
2433 in6_getprefix(slash + 1, MASK);
2434 explicit_prefix = 1;
2435 }
2436 #else
2437 struct sockaddr_in6 *gasin = sin6tab[which];
2438
2439 gasin->sin6_len = sizeof(*gasin);
2440 if (which != MASK)
2441 gasin->sin6_family = AF_INET6;
2442
2443 if (which == ADDR) {
2444 char *p = NULL;
2445 if((p = strrchr(str, '/')) != NULL) {
2446 *p = '\0';
2447 in6_getprefix(p + 1, MASK);
2448 explicit_prefix = 1;
2449 }
2450 }
2451
2452 if (inet_pton(AF_INET6, str, &gasin->sin6_addr) != 1)
2453 errx(EXIT_FAILURE, "%s: bad value", str);
2454 #endif
2455 }
2456
2457 void
2458 in6_getprefix(const char *plen, int which)
2459 {
2460 struct sockaddr_in6 *gpsin = sin6tab[which];
2461 u_char *cp;
2462 int len = strtol(plen, (char **)NULL, 10);
2463
2464 if ((len < 0) || (len > 128))
2465 errx(EXIT_FAILURE, "%s: bad value", plen);
2466 gpsin->sin6_len = sizeof(*gpsin);
2467 if (which != MASK)
2468 gpsin->sin6_family = AF_INET6;
2469 if ((len == 0) || (len == 128)) {
2470 memset(&gpsin->sin6_addr, 0xff, sizeof(struct in6_addr));
2471 return;
2472 }
2473 memset((void *)&gpsin->sin6_addr, 0x00, sizeof(gpsin->sin6_addr));
2474 for (cp = (u_char *)&gpsin->sin6_addr; len > 7; len -= 8)
2475 *cp++ = 0xff;
2476 if (len)
2477 *cp = 0xff << (8 - len);
2478 }
2479
2480 int
2481 prefix(void *val, int size)
2482 {
2483 u_char *pname = (u_char *)val;
2484 int byte, bit, plen = 0;
2485
2486 for (byte = 0; byte < size; byte++, plen += 8)
2487 if (pname[byte] != 0xff)
2488 break;
2489 if (byte == size)
2490 return (plen);
2491 for (bit = 7; bit != 0; bit--, plen++)
2492 if (!(pname[byte] & (1 << bit)))
2493 break;
2494 for (; bit != 0; bit--)
2495 if (pname[byte] & (1 << bit))
2496 return(0);
2497 byte++;
2498 for (; byte < size; byte++)
2499 if (pname[byte])
2500 return(0);
2501 return (plen);
2502 }
2503 #endif /*INET6*/
2504
2505 #ifndef INET_ONLY
2506 void
2507 at_getaddr(const char *addr, int which)
2508 {
2509 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr;
2510 u_int net, node;
2511
2512 sat->sat_family = AF_APPLETALK;
2513 sat->sat_len = sizeof(*sat);
2514 if (which == MASK)
2515 errx(EXIT_FAILURE, "AppleTalk does not use netmasks");
2516 if (sscanf(addr, "%u.%u", &net, &node) != 2
2517 || net == 0 || net > 0xffff || node == 0 || node > 0xfe)
2518 errx(EXIT_FAILURE, "%s: illegal address", addr);
2519 sat->sat_addr.s_net = htons(net);
2520 sat->sat_addr.s_node = node;
2521 }
2522
2523 void
2524 setatrange(const char *range, int d)
2525 {
2526 u_short first = 123, last = 123;
2527
2528 if (sscanf(range, "%hu-%hu", &first, &last) != 2
2529 || first == 0 /* || first > 0xffff */
2530 || last == 0 /* || last > 0xffff */ || first > last)
2531 errx(EXIT_FAILURE, "%s: illegal net range: %u-%u", range,
2532 first, last);
2533 at_nr.nr_firstnet = htons(first);
2534 at_nr.nr_lastnet = htons(last);
2535 }
2536
2537 void
2538 setatphase(const char *phase, int d)
2539 {
2540 if (!strcmp(phase, "1"))
2541 at_nr.nr_phase = 1;
2542 else if (!strcmp(phase, "2"))
2543 at_nr.nr_phase = 2;
2544 else
2545 errx(EXIT_FAILURE, "%s: illegal phase", phase);
2546 }
2547
2548 void
2549 checkatrange(struct sockaddr_at *sat)
2550 {
2551 if (at_nr.nr_phase == 0)
2552 at_nr.nr_phase = 2; /* Default phase 2 */
2553 if (at_nr.nr_firstnet == 0)
2554 at_nr.nr_firstnet = /* Default range of one */
2555 at_nr.nr_lastnet = sat->sat_addr.s_net;
2556 printf("\tatalk %d.%d range %d-%d phase %d\n",
2557 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
2558 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase);
2559 if ((u_short) ntohs(at_nr.nr_firstnet) >
2560 (u_short) ntohs(sat->sat_addr.s_net)
2561 || (u_short) ntohs(at_nr.nr_lastnet) <
2562 (u_short) ntohs(sat->sat_addr.s_net))
2563 errx(EXIT_FAILURE, "AppleTalk address is not in range");
2564 *((struct netrange *) &sat->sat_zero) = at_nr;
2565 }
2566
2567 #define SNS(x) ((struct sockaddr_ns *) &(x))
2568 struct sockaddr_ns *snstab[] = {
2569 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr),
2570 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)};
2571
2572 void
2573 xns_getaddr(const char *addr, int which)
2574 {
2575 struct sockaddr_ns *sns = snstab[which];
2576
2577 sns->sns_family = AF_NS;
2578 sns->sns_len = sizeof(*sns);
2579 sns->sns_addr = ns_addr(addr);
2580 if (which == MASK)
2581 puts("Attempt to set XNS netmask will be ineffectual");
2582 }
2583
2584 #define SISO(x) ((struct sockaddr_iso *) &(x))
2585 struct sockaddr_iso *sisotab[] = {
2586 SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr),
2587 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)};
2588
2589 void
2590 iso_getaddr(const char *addr, int which)
2591 {
2592 struct sockaddr_iso *siso = sisotab[which];
2593 siso->siso_addr = *iso_addr(addr);
2594
2595 if (which == MASK) {
2596 siso->siso_len = TSEL(siso) - (char *)(siso);
2597 siso->siso_nlen = 0;
2598 } else {
2599 siso->siso_len = sizeof(*siso);
2600 siso->siso_family = AF_ISO;
2601 }
2602 }
2603
2604 void
2605 setsnpaoffset(const char *val, int d)
2606 {
2607 iso_addreq.ifra_snpaoffset = atoi(val);
2608 }
2609
2610 void
2611 setnsellength(const char *val, int d)
2612 {
2613 nsellength = atoi(val);
2614 if (nsellength < 0)
2615 errx(EXIT_FAILURE, "Negative NSEL length is absurd");
2616 if (afp == 0 || afp->af_af != AF_ISO)
2617 errx(EXIT_FAILURE, "Setting NSEL length valid only for iso");
2618 }
2619
2620 void
2621 fixnsel(struct sockaddr_iso *siso)
2622 {
2623 if (siso->siso_family == 0)
2624 return;
2625 siso->siso_tlen = nsellength;
2626 }
2627
2628 void
2629 adjust_nsellength(void)
2630 {
2631 fixnsel(sisotab[RIDADDR]);
2632 fixnsel(sisotab[ADDR]);
2633 fixnsel(sisotab[DSTADDR]);
2634 }
2635
2636 #endif /* INET_ONLY */
2637
2638 void
2639 usage(void)
2640 {
2641 const char *progname = getprogname();
2642
2643 fprintf(stderr,
2644 "usage: %s [-m] [-v] [-z] "
2645 #ifdef INET6
2646 "[-L] "
2647 #endif
2648 "interface\n"
2649 "\t[ af [ address [ dest_addr ] ] [ netmask mask ] [ prefixlen n ]\n"
2650 "\t\t[ alias | -alias ] ]\n"
2651 "\t[ up ] [ down ] [ metric n ] [ mtu n ]\n"
2652 "\t[ nwid network_id ] [ nwkey network_key | -nwkey ]\n"
2653 "\t[ powersave | -powersave ] [ powersavesleep duration ]\n"
2654 "\t[ [ af ] tunnel src_addr dest_addr ] [ deletetunnel ]\n"
2655 "\t[ arp | -arp ]\n"
2656 "\t[ media type ] [ mediaopt opts ] [ -mediaopt opts ] "
2657 "[ instance minst ]\n"
2658 "\t[ vlan n vlanif i ]\n"
2659 "\t[ agrport i ] [ -agrport i ]\n"
2660 "\t[ anycast | -anycast ] [ deprecated | -deprecated ]\n"
2661 "\t[ tentative | -tentative ] [ pltime n ] [ vltime n ] [ eui64 ]\n"
2662 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n"
2663 " %s -a [-b] [-m] [-d] [-u] [-v] [-z] [ af ]\n"
2664 " %s -l [-b] [-d] [-u] [-s]\n"
2665 " %s -C\n"
2666 " %s interface create\n"
2667 " %s interface destroy\n",
2668 progname, progname, progname, progname, progname, progname);
2669 exit(1);
2670 }
2671
2672 #ifdef INET6
2673 char *
2674 sec2str(total)
2675 time_t total;
2676 {
2677 static char result[256];
2678 int days, hours, mins, secs;
2679 int first = 1;
2680 char *p = result;
2681 char *end = &result[sizeof(result)];
2682 int n;
2683
2684 if (0) { /*XXX*/
2685 days = total / 3600 / 24;
2686 hours = (total / 3600) % 24;
2687 mins = (total / 60) % 60;
2688 secs = total % 60;
2689
2690 if (days) {
2691 first = 0;
2692 n = snprintf(p, end - p, "%dd", days);
2693 if (n < 0 || n >= end - p)
2694 return(result);
2695 p += n;
2696 }
2697 if (!first || hours) {
2698 first = 0;
2699 n = snprintf(p, end - p, "%dh", hours);
2700 if (n < 0 || n >= end - p)
2701 return(result);
2702 p += n;
2703 }
2704 if (!first || mins) {
2705 first = 0;
2706 n = snprintf(p, end - p, "%dm", mins);
2707 if (n < 0 || n >= end - p)
2708 return(result);
2709 p += n;
2710 }
2711 snprintf(p, end - p, "%ds", secs);
2712 } else
2713 snprintf(p, end - p, "%lu", (u_long)total);
2714
2715 return(result);
2716 }
2717 #endif
2718