Bug Summary

File:src/sbin/ifconfig/ifconfig.c
Warning:line 1945, column 3
Value stored to 'i' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ifconfig.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/ifconfig/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/ifconfig/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/sbin/ifconfig/ifconfig.c
1/* $OpenBSD: ifconfig.c,v 1.470 2023/11/23 03:38:34 dlg Exp $ */
2/* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */
3
4/*
5 * Copyright (c) 1983, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*-
34 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
35 * All rights reserved.
36 *
37 * This code is derived from software contributed to The NetBSD Foundation
38 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
39 * NASA Ames Research Center.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
61 */
62
63#include <sys/socket.h>
64#include <sys/ioctl.h>
65#include <sys/time.h>
66
67#include <net/if.h>
68#include <net/if_dl.h>
69#include <net/if_media.h>
70#include <net/if_types.h>
71#include <netinet/in.h>
72#include <netinet/in_var.h>
73#include <netinet6/in6_var.h>
74#include <netinet6/nd6.h>
75#include <arpa/inet.h>
76#include <netinet/ip_ipsp.h>
77#include <netinet/if_ether.h>
78#include <net80211/ieee80211.h>
79#include <net80211/ieee80211_ioctl.h>
80#include <net/pfvar.h>
81#include <net/if_pfsync.h>
82#include <net/if_pflow.h>
83#include <net/if_pppoe.h>
84#include <net/if_trunk.h>
85#include <net/if_wg.h>
86#include <net/trunklacp.h>
87#include <net/if_sppp.h>
88#include <net/ppp_defs.h>
89
90#include <netinet/ip_carp.h>
91
92#include <netdb.h>
93
94#include <net/if_vlan_var.h>
95
96#include <netmpls/mpls.h>
97
98#include <ctype.h>
99#include <err.h>
100#include <errno(*__errno()).h>
101#include <stdio.h>
102#include <stdint.h>
103#include <stdlib.h>
104#include <stddef.h>
105#include <string.h>
106#include <unistd.h>
107#include <limits.h>
108#include <resolv.h>
109#include <util.h>
110#include <ifaddrs.h>
111
112#ifndef SMALL
113#include <dev/usb/mbim.h>
114#include <dev/usb/if_umb.h>
115#endif /* SMALL */
116
117#include "ifconfig.h"
118
119#ifndef nitems
120#define nitems(_a)(sizeof((_a)) / sizeof((_a)[0])) (sizeof((_a)) / sizeof((_a)[0]))
121#endif
122
123#define MINIMUM(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b))
124#define MAXIMUM(a, b)(((a) > (b)) ? (a) : (b)) (((a) > (b)) ? (a) : (b))
125
126#define HWFEATURESBITS"\024\1CSUM_IPv4\2CSUM_TCPv4\3CSUM_UDPv4" "\5VLAN_MTU\6VLAN_HWTAGGING\10CSUM_TCPv6"
"\11CSUM_UDPv6\15TSOv4\16TSOv6\17LRO\20WOL"
\
127 "\024\1CSUM_IPv4\2CSUM_TCPv4\3CSUM_UDPv4" \
128 "\5VLAN_MTU\6VLAN_HWTAGGING\10CSUM_TCPv6" \
129 "\11CSUM_UDPv6\15TSOv4\16TSOv6\17LRO\20WOL"
130
131struct ifencap {
132 unsigned int ife_flags;
133#define IFE_VNETID_MASK0xf 0xf
134#define IFE_VNETID_NOPE0x0 0x0
135#define IFE_VNETID_NONE0x1 0x1
136#define IFE_VNETID_ANY0x2 0x2
137#define IFE_VNETID_SET0x3 0x3
138 int64_t ife_vnetid;
139#define IFE_VNETFLOWID0x10 0x10
140
141#define IFE_PARENT_MASK0xf00 0xf00
142#define IFE_PARENT_NOPE0x000 0x000
143#define IFE_PARENT_NONE0x100 0x100
144#define IFE_PARENT_SET0x200 0x200
145 char ife_parent[IFNAMSIZ16];
146
147#define IFE_TXHPRIO_SET0x1000 0x1000
148 int ife_txhprio;
149#define IFE_RXHPRIO_SET0x2000 0x2000
150 int ife_rxhprio;
151};
152
153struct ifreq ifr, ridreq;
154struct in_aliasreq in_addreq;
155struct in6_ifreq ifr6;
156struct in6_ifreq in6_ridreq;
157struct in6_aliasreq in6_addreq;
158struct sockaddr_in netmask;
159
160#ifndef SMALL
161int rdomainid;
162#endif /* SMALL */
163
164char ifname[IFNAMSIZ16];
165int flags, xflags, setaddr, setipdst, doalias;
166u_long metric, mtu;
167int llprio;
168int clearaddr, sock;
169int newaddr = 0;
170int af = AF_INET2;
171int explicit_prefix = 0;
172int Lflag = 1;
173int show_join = 0;
174
175int showmediaflag;
176int showcapsflag;
177int shownet80211chans;
178int shownet80211nodes;
179int showclasses;
180int showtransceiver;
181
182struct ifencap;
183
184struct ieee80211_join join;
185
186const char *lacpmodeactive = "active";
187const char *lacpmodepassive = "passive";
188const char *lacptimeoutfast = "fast";
189const char *lacptimeoutslow = "slow";
190
191void notealias(const char *, int);
192void setifaddr(const char *, int);
193void setiflladdr(const char *, int);
194void setifdstaddr(const char *, int);
195void setifflags(const char *, int);
196void setifxflags(const char *, int);
197void addaf(const char *, int);
198void removeaf(const char *, int);
199void setifbroadaddr(const char *, int);
200void setifmtu(const char *, int);
201void setifllprio(const char *, int);
202void setifnwid(const char *, int);
203void setifjoin(const char *, int);
204void delifjoin(const char *, int);
205void delifjoinlist(const char *, int);
206void showjoin(const char *, int);
207void setifbssid(const char *, int);
208void setifnwkey(const char *, int);
209void setifwpa(const char *, int);
210void setifwpaprotos(const char *, int);
211void setifwpaakms(const char *, int);
212void setifwpaciphers(const char *, int);
213void setifwpagroupcipher(const char *, int);
214void setifwpakey(const char *, int);
215void setifchan(const char *, int);
216void setifscan(const char *, int);
217void setifnwflag(const char *, int);
218void unsetifnwflag(const char *, int);
219void setifnetmask(const char *, int);
220void setifprefixlen(const char *, int);
221void setvnetid(const char *, int);
222void delvnetid(const char *, int);
223void getvnetid(struct ifencap *);
224void setifparent(const char *, int);
225void delifparent(const char *, int);
226void getifparent(struct ifencap *);
227void getencap(void);
228void setia6flags(const char *, int);
229void setia6pltime(const char *, int);
230void setia6vltime(const char *, int);
231void setia6lifetime(const char *, const char *);
232void setia6eui64(const char *, int);
233void setmedia(const char *, int);
234void setmediaopt(const char *, int);
235void setmediamode(const char *, int);
236void unsetmediamode(const char *, int);
237void clone_create(const char *, int);
238void clone_destroy(const char *, int);
239void unsetmediaopt(const char *, int);
240void setmediainst(const char *, int);
241int prefix(void *val, int);
242void getifgroups(void);
243void setifgroup(const char *, int);
244void unsetifgroup(const char *, int);
245void setgroupattribs(char *, int, char *[]);
246int printgroup(char *, int);
247void setautoconf(const char *, int);
248void settemporary(const char *, int);
249void settrunkport(const char *, int);
250void unsettrunkport(const char *, int);
251void settrunkproto(const char *, int);
252void settrunklacpmode(const char *, int);
253void settrunklacptimeout(const char *, int);
254void trunk_status(void);
255void list_cloners(void);
256
257#ifndef SMALL
258void setifrtlabel(const char *, int);
259void setrdomain(const char *, int);
260void unsetrdomain(const char *, int);
261void setkeepalive(const char *, const char *);
262void unsetkeepalive(const char *, int);
263void carp_status(void);
264void setcarp_advbase(const char *,int);
265void setcarp_advskew(const char *, int);
266void setcarppeer(const char *, int);
267void unsetcarppeer(const char *, int);
268void setcarp_passwd(const char *, int);
269void setcarp_vhid(const char *, int);
270void setcarp_state(const char *, int);
271void setcarpdev(const char *, int);
272void setcarp_nodes(const char *, int);
273void setcarp_balancing(const char *, int);
274void setpfsync_syncdev(const char *, int);
275void setpfsync_maxupd(const char *, int);
276void unsetpfsync_syncdev(const char *, int);
277void setpfsync_syncpeer(const char *, int);
278void unsetpfsync_syncpeer(const char *, int);
279void setpfsync_defer(const char *, int);
280void pfsync_status(void);
281void setvnetflowid(const char *, int);
282void delvnetflowid(const char *, int);
283void getvnetflowid(struct ifencap *);
284void gettxprio(struct ifencap *);
285void settxprio(const char *, int);
286void getrxprio(struct ifencap *);
287void setrxprio(const char *, int);
288void setmplslabel(const char *, int);
289void unsetmplslabel(const char *, int);
290void setpwe3cw(const char *, int);
291void unsetpwe3cw(const char *, int);
292void setpwe3fat(const char *, int);
293void unsetpwe3fat(const char *, int);
294void setpwe3neighbor(const char *, const char *);
295void unsetpwe3neighbor(const char *, int);
296void mpls_status(void);
297void settunnel(const char *, const char *);
298void settunneladdr(const char *, int);
299void deletetunnel(const char *, int);
300void settunnelinst(const char *, int);
301void unsettunnelinst(const char *, int);
302void settunnelttl(const char *, int);
303void settunneldf(const char *, int);
304void settunnelnodf(const char *, int);
305void settunnelecn(const char *, int);
306void settunnelnoecn(const char *, int);
307void setpppoe_dev(const char *,int);
308void setpppoe_svc(const char *,int);
309void setpppoe_ac(const char *,int);
310void pppoe_status(void);
311void setspppproto(const char *, int);
312void setspppname(const char *, int);
313void setspppkey(const char *, int);
314void setsppppeerproto(const char *, int);
315void setsppppeername(const char *, int);
316void setsppppeerkey(const char *, int);
317void setsppppeerflag(const char *, int);
318void unsetsppppeerflag(const char *, int);
319void sppp_status(void);
320void sppp_printproto(const char *, struct sauthreq *);
321void setifpriority(const char *, int);
322void setifpowersave(const char *, int);
323void setifmetric(const char *, int);
324void pflow_status(void);
325void pflow_addr(const char*, struct sockaddr_storage *);
326void setpflow_sender(const char *, int);
327void unsetpflow_sender(const char *, int);
328void setpflow_receiver(const char *, int);
329void unsetpflow_receiver(const char *, int);
330void setpflowproto(const char *, int);
331void setifipdst(const char *, int);
332void setifdesc(const char *, int);
333void unsetifdesc(const char *, int);
334void printifhwfeatures(const char *, int);
335void setpair(const char *, int);
336void unsetpair(const char *, int);
337void umb_status(void);
338void umb_printclasses(char *, int);
339int umb_parse_classes(const char *);
340void umb_setpin(const char *, int);
341void umb_chgpin(const char *, const char *);
342void umb_puk(const char *, const char *);
343void umb_pinop(int, int, const char *, const char *);
344void umb_apn(const char *, int);
345void umb_setclass(const char *, int);
346void umb_roaming(const char *, int);
347void utf16_to_char(uint16_t *, int, char *, size_t);
348int char_to_utf16(const char *, uint16_t *, size_t);
349void transceiver(const char *, int);
350void transceiverdump(const char *, int);
351
352/* WG */
353void setwgpeer(const char *, int);
354void setwgpeerdesc(const char *, int);
355void setwgpeerep(const char *, const char *);
356void setwgpeeraip(const char *, int);
357void setwgpeerpsk(const char *, int);
358void setwgpeerpka(const char *, int);
359void setwgport(const char *, int);
360void setwgkey(const char *, int);
361void setwgrtable(const char *, int);
362
363void unsetwgpeer(const char *, int);
364void unsetwgpeerdesc(const char *, int);
365void unsetwgpeerpsk(const char *, int);
366void unsetwgpeerall(const char *, int);
367
368void wg_status(int);
369#else
370void setignore(const char *, int);
371#endif
372
373struct if_clonereq *get_cloners(void);
374int findmac(const char *);
375
376/*
377 * Media stuff. Whenever a media command is first performed, the
378 * currently select media is grabbed for this interface. If `media'
379 * is given, the current media word is modified. `mediaopt' commands
380 * only modify the set and clear words. They then operate on the
381 * current media word later.
382 */
383uint64_t media_current;
384uint64_t mediaopt_set;
385uint64_t mediaopt_clear;
386
387int actions; /* Actions performed */
388
389#define A_MEDIA0x0001 0x0001 /* media command */
390#define A_MEDIAOPTSET0x0002 0x0002 /* mediaopt command */
391#define A_MEDIAOPTCLR0x0004 0x0004 /* -mediaopt command */
392#define A_MEDIAOPT(0x0002|0x0004) (A_MEDIAOPTSET0x0002|A_MEDIAOPTCLR0x0004)
393#define A_MEDIAINST0x0008 0x0008 /* instance or inst command */
394#define A_MEDIAMODE0x0010 0x0010 /* mode command */
395#define A_JOIN0x0020 0x0020 /* join */
396#define A_WIREGUARD0x0040 0x0040 /* any WireGuard command */
397#define A_SILENT0x8000000 0x8000000 /* doing operation, do not print */
398
399#define NEXTARG00xffffff 0xffffff
400#define NEXTARG0xfffffe 0xfffffe
401#define NEXTARG20xfffffd 0xfffffd
402
403const struct cmd {
404 char *c_name;
405 int c_parameter; /* NEXTARG means next argv */
406 int c_action; /* defered action */
407 void (*c_func)(const char *, int);
408 void (*c_func2)(const char *, const char *);
409} cmds[] = {
410 { "up", IFF_UP0x1, 0, setifflags } ,
411 { "down", -IFF_UP0x1, 0, setifflags },
412 { "arp", -IFF_NOARP0x80, 0, setifflags },
413 { "-arp", IFF_NOARP0x80, 0, setifflags },
414 { "debug", IFF_DEBUG0x4, 0, setifflags },
415 { "-debug", -IFF_DEBUG0x4, 0, setifflags },
416 { "alias", IFF_UP0x1, 0, notealias },
417 { "-alias", -IFF_UP0x1, 0, notealias },
418 { "delete", -IFF_UP0x1, 0, notealias },
419 { "netmask", NEXTARG0xfffffe, 0, setifnetmask },
420 { "mtu", NEXTARG0xfffffe, 0, setifmtu },
421 { "nwid", NEXTARG0xfffffe, 0, setifnwid },
422 { "-nwid", -1, 0, setifnwid },
423 { "join", NEXTARG0xfffffe, 0, setifjoin },
424 { "-join", NEXTARG0xfffffe, 0, delifjoin },
425 { "joinlist", NEXTARG00xffffff, 0, showjoin },
426 { "-joinlist", -1, 0, delifjoinlist },
427 { "bssid", NEXTARG0xfffffe, 0, setifbssid },
428 { "-bssid", -1, 0, setifbssid },
429 { "nwkey", NEXTARG0xfffffe, 0, setifnwkey },
430 { "-nwkey", -1, 0, setifnwkey },
431 { "wpa", 1, 0, setifwpa },
432 { "-wpa", 0, 0, setifwpa },
433 { "wpaakms", NEXTARG0xfffffe, 0, setifwpaakms },
434 { "wpaciphers", NEXTARG0xfffffe, 0, setifwpaciphers },
435 { "wpagroupcipher", NEXTARG0xfffffe, 0, setifwpagroupcipher },
436 { "wpaprotos", NEXTARG0xfffffe, 0, setifwpaprotos },
437 { "wpakey", NEXTARG0xfffffe, 0, setifwpakey },
438 { "-wpakey", -1, 0, setifwpakey },
439 { "chan", NEXTARG00xffffff, 0, setifchan },
440 { "-chan", -1, 0, setifchan },
441 { "scan", NEXTARG00xffffff, 0, setifscan },
442 { "broadcast", NEXTARG0xfffffe, 0, setifbroadaddr },
443 { "prefixlen", NEXTARG0xfffffe, 0, setifprefixlen},
444 { "vnetid", NEXTARG0xfffffe, 0, setvnetid },
445 { "-vnetid", 0, 0, delvnetid },
446 { "parent", NEXTARG0xfffffe, 0, setifparent },
447 { "-parent", 1, 0, delifparent },
448 { "vlan", NEXTARG0xfffffe, 0, setvnetid },
449 { "-vlan", 0, 0, delvnetid },
450 { "vlandev", NEXTARG0xfffffe, 0, setifparent },
451 { "-vlandev", 1, 0, delifparent },
452 { "group", NEXTARG0xfffffe, 0, setifgroup },
453 { "-group", NEXTARG0xfffffe, 0, unsetifgroup },
454 { "autoconf", 1, 0, setautoconf },
455 { "-autoconf", -1, 0, setautoconf },
456 { "trunkport", NEXTARG0xfffffe, 0, settrunkport },
457 { "-trunkport", NEXTARG0xfffffe, 0, unsettrunkport },
458 { "trunkproto", NEXTARG0xfffffe, 0, settrunkproto },
459 { "lacpmode", NEXTARG0xfffffe, 0, settrunklacpmode },
460 { "lacptimeout", NEXTARG0xfffffe, 0, settrunklacptimeout },
461 { "anycast", IN6_IFF_ANYCAST0x01, 0, setia6flags },
462 { "-anycast", -IN6_IFF_ANYCAST0x01, 0, setia6flags },
463 { "tentative", IN6_IFF_TENTATIVE0x02, 0, setia6flags },
464 { "-tentative", -IN6_IFF_TENTATIVE0x02, 0, setia6flags },
465 { "pltime", NEXTARG0xfffffe, 0, setia6pltime },
466 { "vltime", NEXTARG0xfffffe, 0, setia6vltime },
467 { "eui64", 0, 0, setia6eui64 },
468 { "temporary", 1, 0, settemporary },
469 { "-temporary", -1, 0, settemporary },
470 { "soii", -IFXF_INET6_NOSOII0x40, 0, setifxflags },
471 { "-soii", IFXF_INET6_NOSOII0x40, 0, setifxflags },
472 { "monitor", IFXF_MONITOR0x100, 0, setifxflags },
473 { "-monitor", -IFXF_MONITOR0x100, 0, setifxflags },
474 { "tcplro", IFXF_LRO0x200, 0, setifxflags },
475 { "-tcplro", -IFXF_LRO0x200, 0, setifxflags },
476#ifndef SMALL
477 { "hwfeatures", NEXTARG00xffffff, 0, printifhwfeatures },
478 { "metric", NEXTARG0xfffffe, 0, setifmetric },
479 { "powersave", NEXTARG00xffffff, 0, setifpowersave },
480 { "-powersave", -1, 0, setifpowersave },
481 { "priority", NEXTARG0xfffffe, 0, setifpriority },
482 { "rtlabel", NEXTARG0xfffffe, 0, setifrtlabel },
483 { "-rtlabel", -1, 0, setifrtlabel },
484 { "rdomain", NEXTARG0xfffffe, 0, setrdomain },
485 { "-rdomain", 0, 0, unsetrdomain },
486 { "staticarp", IFF_STATICARP0x20, 0, setifflags },
487 { "-staticarp", -IFF_STATICARP0x20, 0, setifflags },
488 { "mpls", IFXF_MPLS0x8, 0, setifxflags },
489 { "-mpls", -IFXF_MPLS0x8, 0, setifxflags },
490 { "mplslabel", NEXTARG0xfffffe, 0, setmplslabel },
491 { "-mplslabel", 0, 0, unsetmplslabel },
492 { "pwecw", 0, 0, setpwe3cw },
493 { "-pwecw", 0, 0, unsetpwe3cw },
494 { "pwefat", 0, 0, setpwe3fat },
495 { "-pwefat", 0, 0, unsetpwe3fat },
496 { "pweneighbor", NEXTARG20xfffffd, 0, NULL((void *)0), setpwe3neighbor },
497 { "-pweneighbor", 0, 0, unsetpwe3neighbor },
498 { "advbase", NEXTARG0xfffffe, 0, setcarp_advbase },
499 { "advskew", NEXTARG0xfffffe, 0, setcarp_advskew },
500 { "carppeer", NEXTARG0xfffffe, 0, setcarppeer },
501 { "-carppeer", 1, 0, unsetcarppeer },
502 { "pass", NEXTARG0xfffffe, 0, setcarp_passwd },
503 { "vhid", NEXTARG0xfffffe, 0, setcarp_vhid },
504 { "state", NEXTARG0xfffffe, 0, setcarp_state },
505 { "carpdev", NEXTARG0xfffffe, 0, setcarpdev },
506 { "carpnodes", NEXTARG0xfffffe, 0, setcarp_nodes },
507 { "balancing", NEXTARG0xfffffe, 0, setcarp_balancing },
508 { "syncdev", NEXTARG0xfffffe, 0, setpfsync_syncdev },
509 { "-syncdev", 1, 0, unsetpfsync_syncdev },
510 { "syncif", NEXTARG0xfffffe, 0, setpfsync_syncdev },
511 { "-syncif", 1, 0, unsetpfsync_syncdev },
512 { "syncpeer", NEXTARG0xfffffe, 0, setpfsync_syncpeer },
513 { "-syncpeer", 1, 0, unsetpfsync_syncpeer },
514 { "maxupd", NEXTARG0xfffffe, 0, setpfsync_maxupd },
515 { "defer", 1, 0, setpfsync_defer },
516 { "-defer", 0, 0, setpfsync_defer },
517 { "tunnel", NEXTARG20xfffffd, 0, NULL((void *)0), settunnel },
518 { "tunneladdr", NEXTARG0xfffffe, 0, settunneladdr },
519 { "-tunnel", 0, 0, deletetunnel },
520 { "tunneldomain", NEXTARG0xfffffe, 0, settunnelinst },
521 { "-tunneldomain", 0, 0, unsettunnelinst },
522 { "tunnelttl", NEXTARG0xfffffe, 0, settunnelttl },
523 { "tunneldf", 0, 0, settunneldf },
524 { "-tunneldf", 0, 0, settunnelnodf },
525 { "tunnelecn", 0, 0, settunnelecn },
526 { "-tunnelecn", 0, 0, settunnelnoecn },
527 { "vnetflowid", 0, 0, setvnetflowid },
528 { "-vnetflowid", 0, 0, delvnetflowid },
529 { "txprio", NEXTARG0xfffffe, 0, settxprio },
530 { "rxprio", NEXTARG0xfffffe, 0, setrxprio },
531 { "pppoedev", NEXTARG0xfffffe, 0, setpppoe_dev },
532 { "pppoesvc", NEXTARG0xfffffe, 0, setpppoe_svc },
533 { "-pppoesvc", 1, 0, setpppoe_svc },
534 { "pppoeac", NEXTARG0xfffffe, 0, setpppoe_ac },
535 { "-pppoeac", 1, 0, setpppoe_ac },
536 { "authproto", NEXTARG0xfffffe, 0, setspppproto },
537 { "authname", NEXTARG0xfffffe, 0, setspppname },
538 { "authkey", NEXTARG0xfffffe, 0, setspppkey },
539 { "peerproto", NEXTARG0xfffffe, 0, setsppppeerproto },
540 { "peername", NEXTARG0xfffffe, 0, setsppppeername },
541 { "peerkey", NEXTARG0xfffffe, 0, setsppppeerkey },
542 { "peerflag", NEXTARG0xfffffe, 0, setsppppeerflag },
543 { "-peerflag", NEXTARG0xfffffe, 0, unsetsppppeerflag },
544 { "nwflag", NEXTARG0xfffffe, 0, setifnwflag },
545 { "-nwflag", NEXTARG0xfffffe, 0, unsetifnwflag },
546 { "flowsrc", NEXTARG0xfffffe, 0, setpflow_sender },
547 { "-flowsrc", 1, 0, unsetpflow_sender },
548 { "flowdst", NEXTARG0xfffffe, 0, setpflow_receiver },
549 { "-flowdst", 1, 0, unsetpflow_receiver },
550 { "pflowproto", NEXTARG0xfffffe, 0, setpflowproto },
551 { "-inet", AF_INET2, 0, removeaf },
552 { "-inet6", AF_INET624, 0, removeaf },
553 { "keepalive", NEXTARG20xfffffd, 0, NULL((void *)0), setkeepalive },
554 { "-keepalive", 1, 0, unsetkeepalive },
555 { "add", NEXTARG0xfffffe, 0, bridge_add },
556 { "del", NEXTARG0xfffffe, 0, bridge_delete },
557 { "addspan", NEXTARG0xfffffe, 0, bridge_addspan },
558 { "delspan", NEXTARG0xfffffe, 0, bridge_delspan },
559 { "discover", NEXTARG0xfffffe, 0, setdiscover },
560 { "-discover", NEXTARG0xfffffe, 0, unsetdiscover },
561 { "blocknonip", NEXTARG0xfffffe, 0, setblocknonip },
562 { "-blocknonip",NEXTARG0xfffffe, 0, unsetblocknonip },
563 { "learn", NEXTARG0xfffffe, 0, setlearn },
564 { "-learn", NEXTARG0xfffffe, 0, unsetlearn },
565 { "stp", NEXTARG0xfffffe, 0, setstp },
566 { "-stp", NEXTARG0xfffffe, 0, unsetstp },
567 { "edge", NEXTARG0xfffffe, 0, setedge },
568 { "-edge", NEXTARG0xfffffe, 0, unsetedge },
569 { "autoedge", NEXTARG0xfffffe, 0, setautoedge },
570 { "-autoedge", NEXTARG0xfffffe, 0, unsetautoedge },
571 { "protected", NEXTARG20xfffffd, 0, NULL((void *)0), bridge_protect },
572 { "-protected", NEXTARG0xfffffe, 0, bridge_unprotect },
573 { "ptp", NEXTARG0xfffffe, 0, setptp },
574 { "-ptp", NEXTARG0xfffffe, 0, unsetptp },
575 { "autoptp", NEXTARG0xfffffe, 0, setautoptp },
576 { "-autoptp", NEXTARG0xfffffe, 0, unsetautoptp },
577 { "flush", 0, 0, bridge_flush },
578 { "flushall", 0, 0, bridge_flushall },
579 { "static", NEXTARG20xfffffd, 0, NULL((void *)0), bridge_addaddr },
580 { "endpoint", NEXTARG20xfffffd, 0, NULL((void *)0), bridge_addendpoint },
581 { "deladdr", NEXTARG0xfffffe, 0, bridge_deladdr },
582 { "maxaddr", NEXTARG0xfffffe, 0, bridge_maxaddr },
583 { "addr", 0, 0, bridge_addrs },
584 { "hellotime", NEXTARG0xfffffe, 0, bridge_hellotime },
585 { "fwddelay", NEXTARG0xfffffe, 0, bridge_fwddelay },
586 { "maxage", NEXTARG0xfffffe, 0, bridge_maxage },
587 { "proto", NEXTARG0xfffffe, 0, bridge_proto },
588 { "ifpriority", NEXTARG20xfffffd, 0, NULL((void *)0), bridge_ifprio },
589 { "ifcost", NEXTARG20xfffffd, 0, NULL((void *)0), bridge_ifcost },
590 { "-ifcost", NEXTARG0xfffffe, 0, bridge_noifcost },
591 { "timeout", NEXTARG0xfffffe, 0, bridge_timeout },
592 { "holdcnt", NEXTARG0xfffffe, 0, bridge_holdcnt },
593 { "spanpriority", NEXTARG0xfffffe, 0, bridge_priority },
594 { "ipdst", NEXTARG0xfffffe, 0, setifipdst },
595#if 0
596 /* XXX `rule` special-cased below */
597 { "rule", 0, 0, bridge_rule },
598#endif
599 { "rules", NEXTARG0xfffffe, 0, bridge_rules },
600 { "rulefile", NEXTARG0xfffffe, 0, bridge_rulefile },
601 { "flushrule", NEXTARG0xfffffe, 0, bridge_flushrule },
602 { "description", NEXTARG0xfffffe, 0, setifdesc },
603 { "descr", NEXTARG0xfffffe, 0, setifdesc },
604 { "-description", 1, 0, unsetifdesc },
605 { "-descr", 1, 0, unsetifdesc },
606 { "wol", IFXF_WOL0x10, 0, setifxflags },
607 { "-wol", -IFXF_WOL0x10, 0, setifxflags },
608 { "pin", NEXTARG0xfffffe, 0, umb_setpin },
609 { "chgpin", NEXTARG20xfffffd, 0, NULL((void *)0), umb_chgpin },
610 { "puk", NEXTARG20xfffffd, 0, NULL((void *)0), umb_puk },
611 { "apn", NEXTARG0xfffffe, 0, umb_apn },
612 { "-apn", -1, 0, umb_apn },
613 { "class", NEXTARG00xffffff, 0, umb_setclass },
614 { "-class", -1, 0, umb_setclass },
615 { "roaming", 1, 0, umb_roaming },
616 { "-roaming", 0, 0, umb_roaming },
617 { "patch", NEXTARG0xfffffe, 0, setpair },
618 { "-patch", 1, 0, unsetpair },
619 { "addlocal", NEXTARG0xfffffe, 0, addlocal },
620 { "transceiver", NEXTARG00xffffff, 0, transceiver },
621 { "sff", NEXTARG00xffffff, 0, transceiver },
622 { "sffdump", 0, 0, transceiverdump },
623
624 { "wgpeer", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeer},
625 { "wgdescription", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeerdesc},
626 { "wgdescr", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeerdesc},
627 { "wgendpoint", NEXTARG20xfffffd, A_WIREGUARD0x0040, NULL((void *)0), setwgpeerep},
628 { "wgaip", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeeraip},
629 { "wgpsk", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeerpsk},
630 { "wgpka", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeerpka},
631 { "wgport", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgport},
632 { "wgkey", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgkey},
633 { "wgrtable", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgrtable},
634 { "-wgpeer", NEXTARG0xfffffe, A_WIREGUARD0x0040, unsetwgpeer},
635 { "-wgpsk", 0, A_WIREGUARD0x0040, unsetwgpeerpsk},
636 { "-wgdescription", 0, A_WIREGUARD0x0040, unsetwgpeerdesc},
637 { "-wgdescr", 0, A_WIREGUARD0x0040, unsetwgpeerdesc},
638 { "-wgpeerall", 0, A_WIREGUARD0x0040, unsetwgpeerall},
639
640#else /* SMALL */
641 { "powersave", NEXTARG00xffffff, 0, setignore },
642 { "priority", NEXTARG0xfffffe, 0, setignore },
643 { "rtlabel", NEXTARG0xfffffe, 0, setignore },
644 { "mpls", IFXF_MPLS0x8, 0, setignore },
645 { "nwflag", NEXTARG0xfffffe, 0, setignore },
646 { "rdomain", NEXTARG0xfffffe, 0, setignore },
647 { "-inet", AF_INET2, 0, removeaf },
648 { "-inet6", AF_INET624, 0, removeaf },
649 { "description", NEXTARG0xfffffe, 0, setignore },
650 { "descr", NEXTARG0xfffffe, 0, setignore },
651 { "wol", IFXF_WOL0x10, 0, setignore },
652 { "-wol", -IFXF_WOL0x10, 0, setignore },
653#endif /* SMALL */
654#if 0
655 /* XXX `create' special-cased below */
656 { "create", 0, 0, clone_create } ,
657#endif
658 { "destroy", 0, 0, clone_destroy } ,
659 { "link0", IFF_LINK00x1000, 0, setifflags } ,
660 { "-link0", -IFF_LINK00x1000, 0, setifflags } ,
661 { "link1", IFF_LINK10x2000, 0, setifflags } ,
662 { "-link1", -IFF_LINK10x2000, 0, setifflags } ,
663 { "link2", IFF_LINK20x4000, 0, setifflags } ,
664 { "-link2", -IFF_LINK20x4000, 0, setifflags } ,
665 { "media", NEXTARG00xffffff, A_MEDIA0x0001, setmedia },
666 { "mediaopt", NEXTARG0xfffffe, A_MEDIAOPTSET0x0002, setmediaopt },
667 { "-mediaopt", NEXTARG0xfffffe, A_MEDIAOPTCLR0x0004, unsetmediaopt },
668 { "mode", NEXTARG0xfffffe, A_MEDIAMODE0x0010, setmediamode },
669 { "-mode", 0, A_MEDIAMODE0x0010, unsetmediamode },
670 { "instance", NEXTARG0xfffffe, A_MEDIAINST0x0008, setmediainst },
671 { "inst", NEXTARG0xfffffe, A_MEDIAINST0x0008, setmediainst },
672 { "lladdr", NEXTARG0xfffffe, 0, setiflladdr },
673 { "llprio", NEXTARG0xfffffe, 0, setifllprio },
674 { NULL((void *)0), /*src*/ 0, 0, setifaddr },
675 { NULL((void *)0), /*dst*/ 0, 0, setifdstaddr },
676 { NULL((void *)0), /*illegal*/0, 0, NULL((void *)0) },
677};
678
679#define IFFBITS"\024\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6STATICARP"
"\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX"
"\15LINK0\16LINK1\17LINK2\20MULTICAST" "\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII"
"\30AUTOCONF4" "\31MONITOR" "\32LRO"
\
680 "\024\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6STATICARP" \
681 "\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX" \
682 "\15LINK0\16LINK1\17LINK2\20MULTICAST" \
683 "\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII" \
684 "\30AUTOCONF4" "\31MONITOR" "\32LRO"
685
686int getinfo(struct ifreq *, int);
687void getsock(int);
688void printgroupattribs(char *);
689void printif(char *, int);
690void printb_status(unsigned short, unsigned char *);
691const char *get_linkstate(int, int);
692void status(int, struct sockaddr_dl *, int, int);
693__dead__attribute__((__noreturn__)) void usage(void);
694const char *get_string(const char *, const char *, u_int8_t *, int *);
695int len_string(const u_int8_t *, int);
696int print_string(const u_int8_t *, int);
697char *sec2str(time_t);
698
699const char *get_media_type_string(uint64_t);
700const char *get_media_subtype_string(uint64_t);
701uint64_t get_media_mode(uint64_t, const char *);
702uint64_t get_media_subtype(uint64_t, const char *);
703uint64_t get_media_options(uint64_t, const char *);
704uint64_t lookup_media_word(const struct ifmedia_description *, uint64_t,
705 const char *);
706void print_media_word(uint64_t, int, int);
707void process_media_commands(void);
708void init_current_media(void);
709
710void process_join_commands(void);
711
712void process_wg_commands(void);
713
714unsigned long get_ts_map(int, int, int);
715
716void in_status(int);
717void in_getaddr(const char *, int);
718void in_getprefix(const char *, int);
719void in6_fillscopeid(struct sockaddr_in6 *);
720void in6_alias(struct in6_ifreq *);
721void in6_status(int);
722void in6_getaddr(const char *, int);
723void in6_getprefix(const char *, int);
724void ieee80211_status(void);
725void join_status(void);
726void ieee80211_listchans(void);
727void ieee80211_listnodes(void);
728void ieee80211_printnode(struct ieee80211_nodereq *);
729u_int getwpacipher(const char *);
730void print_cipherset(u_int32_t);
731
732void spppauthinfo(struct sauthreq *, int);
733void spppdnsinfo(struct sdnsreq *);
734
735/* Known address families */
736const struct afswtch {
737 char *af_name;
738 short af_af;
739 void (*af_status)(int);
740 void (*af_getaddr)(const char *, int);
741 void (*af_getprefix)(const char *, int);
742 u_long af_difaddr;
743 u_long af_aifaddr;
744 caddr_t af_ridreq;
745 caddr_t af_addreq;
746} afs[] = {
747#define C(x)((caddr_t) &x) ((caddr_t) &x)
748 { "inet", AF_INET2, in_status, in_getaddr, in_getprefix,
749 SIOCDIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((25)))
, SIOCAIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifaliasreq) &
0x1fff) << 16) | ((('i')) << 8) | ((26)))
, C(ridreq)((caddr_t) &ridreq), C(in_addreq)((caddr_t) &in_addreq) },
750 { "inet6", AF_INET624, in6_status, in6_getaddr, in6_getprefix,
751 SIOCDIFADDR_IN6((unsigned long)0x80000000 | ((sizeof(struct in6_ifreq) &
0x1fff) << 16) | ((('i')) << 8) | ((25)))
, SIOCAIFADDR_IN6((unsigned long)0x80000000 | ((sizeof(struct in6_aliasreq) &
0x1fff) << 16) | ((('i')) << 8) | ((26)))
, C(in6_ridreq)((caddr_t) &in6_ridreq), C(in6_addreq)((caddr_t) &in6_addreq) },
752 { 0, 0, 0, 0 }
753};
754
755const struct afswtch *afp; /*the address family being set or asked about*/
756
757char joinname[IEEE80211_NWID_LEN32];
758size_t joinlen;
759char nwidname[IEEE80211_NWID_LEN32];
760size_t nwidlen;
761
762int ifaliases = 0;
763int aflag = 0;
764
765int
766main(int argc, char *argv[])
767{
768 const struct afswtch *rafp = NULL((void *)0);
769 int create = 0;
770 int Cflag = 0;
771 int gflag = 0;
772 int found_rulefile = 0;
773 int i;
774
775 /* If no args at all, print all interfaces. */
776 if (argc < 2) {
777 /* no filesystem visibility */
778 if (unveil("/", "") == -1)
779 err(1, "unveil /");
780 if (unveil(NULL((void *)0), NULL((void *)0)) == -1)
781 err(1, "unveil");
782 aflag = 1;
783 printif(NULL((void *)0), 0);
784 return (0);
785 }
786 argc--, argv++;
787 if (*argv[0] == '-') {
788 int nomore = 0;
789
790 for (i = 1; argv[0][i]; i++) {
791 switch (argv[0][i]) {
792 case 'a':
793 aflag = 1;
794 nomore = 1;
795 break;
796 case 'A':
797 aflag = 1;
798 ifaliases = 1;
799 nomore = 1;
800 break;
801 case 'g':
802 gflag = 1;
803 break;
804 case 'C':
805 Cflag = 1;
806 nomore = 1;
807 break;
808 case 'M':
809 if (argv[1] == NULL((void *)0))
810 usage();
811 exit(findmac(argv[1]));
812 break;
813 default:
814 usage();
815 break;
816 }
817 }
818 if (nomore == 0) {
819 argc--, argv++;
820 if (argc < 1)
821 usage();
822 if (strlcpy(ifname, *argv, sizeof(ifname)) >= IFNAMSIZ16)
823 errx(1, "interface name '%s' too long", *argv);
824 }
825 } else if (strlcpy(ifname, *argv, sizeof(ifname)) >= IFNAMSIZ16)
826 errx(1, "interface name '%s' too long", *argv);
827 argc--, argv++;
828
829 for (i = 0; i < argc; i++) {
830 if (strcmp(argv[i], "rulefile") == 0) {
831 found_rulefile = 1;
832 break;
833 }
834 }
835
836 if (!found_rulefile) {
837 if (unveil(_PATH_RESCONF"/etc/resolv.conf", "r") == -1)
838 err(1, "unveil %s", _PATH_RESCONF"/etc/resolv.conf");
839 if (unveil(_PATH_HOSTS"/etc/hosts", "r") == -1)
840 err(1, "unveil %s", _PATH_HOSTS"/etc/hosts");
841 if (unveil(_PATH_SERVICES"/etc/services", "r") == -1)
842 err(1, "unveil %s", _PATH_SERVICES"/etc/services");
843 if (unveil(NULL((void *)0), NULL((void *)0)) == -1)
844 err(1, "unveil");
845 }
846
847 if (argc > 0) {
848 for (afp = rafp = afs; rafp->af_name; rafp++)
849 if (strcmp(rafp->af_name, *argv) == 0) {
850 afp = rafp;
851 argc--;
852 argv++;
853 break;
854 }
855 rafp = afp;
856 af = ifr.ifr_addrifr_ifru.ifru_addr.sa_family = rafp->af_af;
857 }
858 if (Cflag) {
859 if (argc > 0 || aflag)
860 usage();
861 list_cloners();
862 return (0);
863 }
864 if (gflag) {
865 if (argc == 0)
866 printgroupattribs(ifname);
867 else
868 setgroupattribs(ifname, argc, argv);
869 return (0);
870 }
871 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
872
873 /* initialization */
874 in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME0xffffffff;
875 in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME0xffffffff;
876
877 /*
878 * NOTE: We must special-case the `create' command right
879 * here as we would otherwise fail in getinfo().
880 */
881 if (argc > 0 && strcmp(argv[0], "create") == 0) {
882 clone_create(argv[0], 0);
883 argc--, argv++;
884 if (argc == 0)
885 return (0);
886 }
887 if (aflag == 0) {
888 create = (argc > 0) && strcmp(argv[0], "destroy") != 0;
889 (void)getinfo(&ifr, create);
890 }
891
892 if (argc != 0 && af == AF_INET624)
893 addaf(ifname, AF_INET624);
894
895 while (argc > 0) {
896 const struct cmd *p;
897
898 for (p = cmds; p->c_name; p++)
899 if (strcmp(*argv, p->c_name) == 0)
900 break;
901#ifndef SMALL
902 if (strcmp(*argv, "rule") == 0) {
903 argc--, argv++;
904 return bridge_rule(argc, argv, -1);
905 }
906#endif
907 if (p->c_name == 0 && setaddr)
908 for (i = setaddr; i > 0; i--) {
909 p++;
910 if (p->c_func == NULL((void *)0))
911 errx(1, "%s: bad value", *argv);
912 }
913 if (p->c_func || p->c_func2) {
914 if (p->c_parameter == NEXTARG00xffffff) {
915 const struct cmd *p0;
916 int noarg = 1;
917
918 if (argv[1]) {
919 for (p0 = cmds; p0->c_name; p0++)
920 if (strcmp(argv[1],
921 p0->c_name) == 0) {
922 noarg = 0;
923 break;
924 }
925 } else
926 noarg = 0;
927
928 if (noarg == 0)
929 (*p->c_func)(NULL((void *)0), 0);
930 else
931 goto nextarg;
932 } else if (p->c_parameter == NEXTARG0xfffffe) {
933nextarg:
934 if (argv[1] == NULL((void *)0))
935 errx(1, "'%s' requires argument",
936 p->c_name);
937 (*p->c_func)(argv[1], 0);
938 argc--, argv++;
939 actions = actions | A_SILENT0x8000000 | p->c_action;
940 } else if (p->c_parameter == NEXTARG20xfffffd) {
941 if ((argv[1] == NULL((void *)0)) ||
942 (argv[2] == NULL((void *)0)))
943 errx(1, "'%s' requires 2 arguments",
944 p->c_name);
945 (*p->c_func2)(argv[1], argv[2]);
946 argc -= 2;
947 argv += 2;
948 actions = actions | A_SILENT0x8000000 | p->c_action;
949 } else {
950 (*p->c_func)(*argv, p->c_parameter);
951 actions = actions | A_SILENT0x8000000 | p->c_action;
952 }
953 }
954 argc--, argv++;
955 }
956
957 if (argc == 0 && actions == 0) {
958 printif(ifr.ifr_name, aflag ? ifaliases : 1);
959 return (0);
960 }
961
962#ifndef SMALL
963 process_wg_commands();
964#endif
965
966 process_join_commands();
967
968 /* Process any media commands that may have been issued. */
969 process_media_commands();
970
971 if (af == AF_INET624 && explicit_prefix == 0) {
972 /*
973 * Aggregatable address architecture defines all prefixes
974 * are 64. So, it is convenient to set prefixlen to 64 if
975 * it is not specified. If we are setting a destination
976 * address on a point-to-point interface, 128 is required.
977 */
978 if (setipdst && (flags & IFF_POINTOPOINT0x10))
979 setifprefixlen("128", 0);
980 else
981 setifprefixlen("64", 0);
982 /* in6_getprefix("64", MASK) if MASK is available here... */
983 }
984
985 if (clearaddr) {
986 (void) strlcpy(rafp->af_ridreq, ifname, sizeof(ifr.ifr_name));
987 if (ioctl(sock, rafp->af_difaddr, rafp->af_ridreq) == -1) {
988 if (errno(*__errno()) == EADDRNOTAVAIL49 && (doalias >= 0)) {
989 /* means no previous address for interface */
990 } else
991 err(1, "SIOCDIFADDR");
992 }
993 }
994 if (newaddr) {
995 (void) strlcpy(rafp->af_addreq, ifname, sizeof(ifr.ifr_name));
996 if (ioctl(sock, rafp->af_aifaddr, rafp->af_addreq) == -1)
997 err(1, "SIOCAIFADDR");
998 }
999 return (0);
1000}
1001
1002void
1003getsock(int naf)
1004{
1005 static int oaf = -1;
1006
1007 if (oaf == naf)
1008 return;
1009 if (oaf != -1)
1010 close(sock);
1011 sock = socket(naf, SOCK_DGRAM2, 0);
1012 if (sock == -1)
1013 oaf = -1;
1014 else
1015 oaf = naf;
1016}
1017
1018int
1019getinfo(struct ifreq *ifr, int create)
1020{
1021
1022 getsock(af);
1023 if (sock == -1)
1024 err(1, "socket");
1025 if (!isdigit((unsigned char)ifname[strlen(ifname) - 1]))
1026 return (-1); /* ignore groups here */
1027 if (ioctl(sock, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((17)))
, (caddr_t)ifr) == -1) {
1028 int oerrno = errno(*__errno());
1029
1030 if (!create)
1031 return (-1);
1032 if (ioctl(sock, SIOCIFCREATE((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((122)))
, (caddr_t)ifr) == -1) {
1033 errno(*__errno()) = oerrno;
1034 return (-1);
1035 }
1036 if (ioctl(sock, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((17)))
, (caddr_t)ifr) == -1)
1037 return (-1);
1038 }
1039 flags = ifr->ifr_flagsifr_ifru.ifru_flags & 0xffff;
1040 if (ioctl(sock, SIOCGIFXFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((158)))
, (caddr_t)ifr) == -1)
1041 ifr->ifr_flagsifr_ifru.ifru_flags = 0;
1042 xflags = ifr->ifr_flagsifr_ifru.ifru_flags;
1043 if (ioctl(sock, SIOCGIFMETRIC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((23)))
, (caddr_t)ifr) == -1)
1044 metric = 0;
1045 else
1046 metric = ifr->ifr_metricifr_ifru.ifru_metric;
1047 if (ioctl(sock, SIOCGIFMTU(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((126)))
, (caddr_t)ifr) == -1)
1048 mtu = 0;
1049 else
1050 mtu = ifr->ifr_mtuifr_ifru.ifru_metric;
1051#ifndef SMALL
1052 if (ioctl(sock, SIOCGIFRDOMAIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((160)))
, (caddr_t)ifr) == -1)
1053 rdomainid = 0;
1054 else
1055 rdomainid = ifr->ifr_rdomainidifr_ifru.ifru_metric;
1056#endif
1057 if (ioctl(sock, SIOCGIFLLPRIO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((182)))
, (caddr_t)ifr) == -1)
1058 llprio = 0;
1059 else
1060 llprio = ifr->ifr_llprioifr_ifru.ifru_metric;
1061
1062 return (0);
1063}
1064
1065int
1066printgroup(char *groupname, int ifaliases)
1067{
1068 struct ifgroupreq ifgr;
1069 struct ifg_req *ifg;
1070 int len, cnt = 0;
1071
1072 getsock(AF_INET2);
1073 bzero(&ifgr, sizeof(ifgr));
1074 strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name));
1075 if (ioctl(sock, SIOCGIFGMEMB(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((138)))
, (caddr_t)&ifgr) == -1) {
1076 if (errno(*__errno()) == EINVAL22 || errno(*__errno()) == ENOTTY25 ||
1077 errno(*__errno()) == ENOENT2)
1078 return (-1);
1079 else
1080 err(1, "%s: SIOCGIFGMEMB", ifgr.ifgr_name);
1081 }
1082
1083 len = ifgr.ifgr_len;
1084 if ((ifgr.ifgr_groupsifgr_ifgru.ifgru_groups = calloc(1, len)) == NULL((void *)0))
1085 err(1, "printgroup");
1086 if (ioctl(sock, SIOCGIFGMEMB(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((138)))
, (caddr_t)&ifgr) == -1)
1087 err(1, "%s: SIOCGIFGMEMB", ifgr.ifgr_name);
1088
1089 for (ifg = ifgr.ifgr_groupsifgr_ifgru.ifgru_groups; ifg && len >= sizeof(struct ifg_req);
1090 ifg++) {
1091 len -= sizeof(struct ifg_req);
1092 printif(ifg->ifgrq_memberifgrq_ifgrqu.ifgrqu_member, ifaliases);
1093 cnt++;
1094 }
1095 free(ifgr.ifgr_groupsifgr_ifgru.ifgru_groups);
1096
1097 return (cnt);
1098}
1099
1100void
1101printgroupattribs(char *groupname)
1102{
1103 struct ifgroupreq ifgr;
1104
1105 getsock(AF_INET2);
1106 bzero(&ifgr, sizeof(ifgr));
1107 strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name));
1108 if (ioctl(sock, SIOCGIFGATTR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((139)))
, (caddr_t)&ifgr) == -1)
1109 err(1, "%s: SIOCGIFGATTR", ifgr.ifgr_name);
1110
1111 printf("%s:", groupname);
1112 printf(" carp demote count %d", ifgr.ifgr_attribifgr_ifgru.ifgru_attrib.ifg_carp_demoted);
1113 printf("\n");
1114}
1115
1116void
1117setgroupattribs(char *groupname, int argc, char *argv[])
1118{
1119 const char *errstr;
1120 char *p = argv[0];
1121 int neg = 1;
1122
1123 struct ifgroupreq ifgr;
1124
1125 getsock(AF_INET2);
1126 bzero(&ifgr, sizeof(ifgr));
1127 strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name));
1128
1129 if (argc > 1) {
1130 neg = strtonum(argv[1], 0, 128, &errstr);
1131 if (errstr)
1132 errx(1, "%s: invalid carp demotion: %s", ifgr.ifgr_name,
1133 errstr);
1134 }
1135
1136 if (p[0] == '-') {
1137 neg = neg * -1;
1138 p++;
1139 }
1140 if (!strcmp(p, "carpdemote"))
1141 ifgr.ifgr_attribifgr_ifgru.ifgru_attrib.ifg_carp_demoted = neg;
1142 else
1143 usage();
1144
1145 if (ioctl(sock, SIOCSIFGATTR((unsigned long)0x80000000 | ((sizeof(struct ifgroupreq) &
0x1fff) << 16) | ((('i')) << 8) | ((140)))
, (caddr_t)&ifgr) == -1)
1146 err(1, "%s: SIOCSIFGATTR", ifgr.ifgr_name);
1147}
1148
1149void
1150printif(char *name, int ifaliases)
1151{
1152 struct ifaddrs *ifap, *ifa;
1153 struct if_data *ifdata;
1154 const char *namep;
1155 char *oname = NULL((void *)0);
1156 struct ifreq *ifrp;
1157 int count = 0, noinet = 1;
1158 size_t nlen = 0;
1159
1160 if (aflag)
1161 name = NULL((void *)0);
1162 if (name) {
1163 if ((oname = strdup(name)) == NULL((void *)0))
1164 err(1, "strdup");
1165 nlen = strlen(oname);
1166 /* is it a group? */
1167 if (nlen && !isdigit((unsigned char)oname[nlen - 1]))
1168 if (printgroup(oname, ifaliases) != -1) {
1169 free(oname);
1170 return;
1171 }
1172 }
1173
1174 if (getifaddrs(&ifap) != 0)
1175 err(1, "getifaddrs");
1176
1177 namep = NULL((void *)0);
1178 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1179 if (oname) {
1180 if (nlen && isdigit((unsigned char)oname[nlen - 1])) {
1181 /* must have exact match */
1182 if (strcmp(oname, ifa->ifa_name) != 0)
1183 continue;
1184 } else {
1185 /* partial match OK if it ends w/ digit */
1186 if (strncmp(oname, ifa->ifa_name, nlen) != 0 ||
1187 !isdigit((unsigned char)ifa->ifa_name[nlen]))
1188 continue;
1189 }
1190 }
1191 /* quickhack: sizeof(ifr) < sizeof(ifr6) */
1192 if (ifa->ifa_addr != NULL((void *)0) &&
1193 ifa->ifa_addr->sa_family == AF_INET624) {
1194 memset(&ifr6, 0, sizeof(ifr6));
1195 memcpy(&ifr6.ifr_addrifr_ifru.ifru_addr, ifa->ifa_addr,
1196 MINIMUM(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len)(((sizeof(ifr6.ifr_ifru.ifru_addr)) < (ifa->ifa_addr->
sa_len)) ? (sizeof(ifr6.ifr_ifru.ifru_addr)) : (ifa->ifa_addr
->sa_len))
);
1197 ifrp = (struct ifreq *)&ifr6;
1198 } else if (ifa->ifa_addr != NULL((void *)0)) {
1199 memset(&ifr, 0, sizeof(ifr));
1200 memcpy(&ifr.ifr_addrifr_ifru.ifru_addr, ifa->ifa_addr,
1201 MINIMUM(sizeof(ifr.ifr_addr), ifa->ifa_addr->sa_len)(((sizeof(ifr.ifr_ifru.ifru_addr)) < (ifa->ifa_addr->
sa_len)) ? (sizeof(ifr.ifr_ifru.ifru_addr)) : (ifa->ifa_addr
->sa_len))
);
1202 ifrp = &ifr;
1203 }
1204 strlcpy(ifname, ifa->ifa_name, sizeof(ifname));
1205 strlcpy(ifrp->ifr_name, ifa->ifa_name, sizeof(ifrp->ifr_name));
1206
1207 if (ifa->ifa_addr != NULL((void *)0) &&
1208 ifa->ifa_addr->sa_family == AF_LINK18) {
1209 namep = ifa->ifa_name;
1210 if (getinfo(ifrp, 0) < 0)
1211 continue;
1212 ifdata = ifa->ifa_data;
1213 status(1, (struct sockaddr_dl *)ifa->ifa_addr,
1214 ifdata->ifi_link_state, ifaliases);
1215 count++;
1216 noinet = 1;
1217 continue;
1218 }
1219
1220 if (!namep || !strcmp(namep, ifa->ifa_name)) {
1221 const struct afswtch *p;
1222
1223 if (ifa->ifa_addr == NULL((void *)0) ||
1224 (ifa->ifa_addr->sa_family == AF_INET2 &&
1225 ifaliases == 0 && noinet == 0))
1226 continue;
1227 if ((p = afp) != NULL((void *)0)) {
1228 if (ifa->ifa_addr->sa_family == p->af_af)
1229 p->af_status(1);
1230 } else {
1231 for (p = afs; p->af_name; p++) {
1232 if (ifa->ifa_addr->sa_family ==
1233 p->af_af)
1234 p->af_status(0);
1235 }
1236 }
1237 count++;
1238 if (ifa->ifa_addr->sa_family == AF_INET2)
1239 noinet = 0;
1240 continue;
1241 }
1242 }
1243 freeifaddrs(ifap);
1244 free(oname);
1245 if (count == 0) {
1246 fprintf(stderr(&__sF[2]), "%s: no such interface\n", ifname);
1247 exit(1);
1248 }
1249}
1250
1251void
1252clone_create(const char *addr, int param)
1253{
1254
1255 /* We're called early... */
1256 getsock(AF_INET2);
1257
1258 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1259 if (ioctl(sock, SIOCIFCREATE((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((122)))
, &ifr) == -1)
1260 err(1, "%s: SIOCIFCREATE", ifr.ifr_name);
1261}
1262
1263void
1264clone_destroy(const char *addr, int param)
1265{
1266
1267 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1268 if (ioctl(sock, SIOCIFDESTROY((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((121)))
, &ifr) == -1)
1269 err(1, "%s: SIOCIFDESTROY", ifr.ifr_name);
1270}
1271
1272struct if_clonereq *
1273get_cloners(void)
1274{
1275 static struct if_clonereq ifcr;
1276
1277 memset(&ifcr, 0, sizeof(ifcr));
1278
1279 getsock(AF_INET2);
1280
1281 if (ioctl(sock, SIOCIFGCLONERS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct if_clonereq) & 0x1fff) << 16) | ((('i')) <<
8) | ((120)))
, &ifcr) == -1)
1282 err(1, "SIOCIFGCLONERS for count");
1283
1284 if ((ifcr.ifcr_buffer = calloc(ifcr.ifcr_total, IFNAMSIZ16)) == NULL((void *)0))
1285 err(1, "unable to allocate cloner name buffer");
1286 ifcr.ifcr_count = ifcr.ifcr_total;
1287
1288 if (ioctl(sock, SIOCIFGCLONERS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct if_clonereq) & 0x1fff) << 16) | ((('i')) <<
8) | ((120)))
, &ifcr) == -1)
1289 err(1, "SIOCIFGCLONERS for names");
1290
1291 /*
1292 * In case some disappeared in the mean time, clamp it down.
1293 */
1294 if (ifcr.ifcr_count > ifcr.ifcr_total)
1295 ifcr.ifcr_count = ifcr.ifcr_total;
1296
1297 return &ifcr;
1298}
1299
1300void
1301list_cloners(void)
1302{
1303 struct if_clonereq *ifcr;
1304 char *cp, *buf;
1305 int idx;
1306
1307 ifcr = get_cloners();
1308 buf = ifcr->ifcr_buffer;
1309
1310 qsort(buf, ifcr->ifcr_count, IFNAMSIZ16,
1311 (int(*)(const void *, const void *))strcmp);
1312
1313 for (cp = buf, idx = 0; idx < ifcr->ifcr_count; idx++, cp += IFNAMSIZ16) {
1314 if (idx > 0)
1315 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
1316 printf("%s", cp);
1317 }
1318
1319 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1320 free(ifcr->ifcr_buffer);
1321}
1322
1323#define RIDADDR0 0
1324#define ADDR1 1
1325#define MASK2 2
1326#define DSTADDR3 3
1327
1328void
1329setifaddr(const char *addr, int param)
1330{
1331 /*
1332 * Delay the ioctl to set the interface addr until flags are all set.
1333 * The address interpretation may depend on the flags,
1334 * and the flags may change when the address is set.
1335 */
1336 setaddr++;
1337 if (doalias >= 0)
1338 newaddr = 1;
1339 if (doalias == 0)
1340 clearaddr = 1;
1341 afp->af_getaddr(addr, (doalias >= 0 ? ADDR1 : RIDADDR0));
1342}
1343
1344#ifndef SMALL
1345void
1346setifrtlabel(const char *label, int d)
1347{
1348 if (d != 0)
1349 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)(const char *)"";
1350 else
1351 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)label;
1352 if (ioctl(sock, SIOCSIFRTLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((130)))
, &ifr) == -1)
1353 warn("SIOCSIFRTLABEL");
1354}
1355#endif
1356
1357void
1358setifnetmask(const char *addr, int ignored)
1359{
1360 afp->af_getaddr(addr, MASK2);
1361 explicit_prefix = 1;
1362}
1363
1364void
1365setifbroadaddr(const char *addr, int ignored)
1366{
1367 afp->af_getaddr(addr, DSTADDR3);
1368}
1369
1370#ifndef SMALL
1371void
1372setifdesc(const char *val, int ignored)
1373{
1374 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)val;
1375 if (ioctl(sock, SIOCSIFDESCR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((128)))
, &ifr) == -1)
1376 warn("SIOCSIFDESCR");
1377}
1378
1379void
1380unsetifdesc(const char *noval, int ignored)
1381{
1382 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)(const char *)"";
1383 if (ioctl(sock, SIOCSIFDESCR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((128)))
, &ifr) == -1)
1384 warn("SIOCSIFDESCR");
1385}
1386
1387void
1388setifipdst(const char *addr, int ignored)
1389{
1390 in_getaddr(addr, DSTADDR3);
1391 setipdst++;
1392 clearaddr = 0;
1393 newaddr = 0;
1394}
1395#endif
1396
1397#define rqtosa(x)(&(((struct ifreq *)(afp->x))->ifr_ifru.ifru_addr)) (&(((struct ifreq *)(afp->x))->ifr_addrifr_ifru.ifru_addr))
1398void
1399notealias(const char *addr, int param)
1400{
1401 if (setaddr && doalias == 0 && param < 0)
1402 memcpy(rqtosa(af_ridreq)(&(((struct ifreq *)(afp->af_ridreq))->ifr_ifru.ifru_addr
))
, rqtosa(af_addreq)(&(((struct ifreq *)(afp->af_addreq))->ifr_ifru.ifru_addr
))
,
1403 rqtosa(af_addreq)(&(((struct ifreq *)(afp->af_addreq))->ifr_ifru.ifru_addr
))
->sa_len);
1404 doalias = param;
1405 if (param < 0) {
1406 clearaddr = 1;
1407 newaddr = 0;
1408 } else
1409 clearaddr = 0;
1410}
1411
1412void
1413setifdstaddr(const char *addr, int param)
1414{
1415 setaddr++;
1416 setipdst++;
1417 afp->af_getaddr(addr, DSTADDR3);
1418}
1419
1420/*
1421 * Note: doing an SIOCGIFFLAGS scribbles on the union portion
1422 * of the ifreq structure, which may confuse other parts of ifconfig.
1423 * Make a private copy so we can avoid that.
1424 */
1425void
1426setifflags(const char *vname, int value)
1427{
1428 struct ifreq my_ifr;
1429
1430 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq));
1431
1432 if (ioctl(sock, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((17)))
, (caddr_t)&my_ifr) == -1)
1433 err(1, "%s: SIOCGIFFLAGS", my_ifr.ifr_name);
1434 (void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name));
1435 flags = my_ifr.ifr_flagsifr_ifru.ifru_flags;
1436
1437 if (value < 0) {
1438 value = -value;
1439 flags &= ~value;
1440 } else
1441 flags |= value;
1442 my_ifr.ifr_flagsifr_ifru.ifru_flags = flags;
1443 if (ioctl(sock, SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
, (caddr_t)&my_ifr) == -1)
1444 err(1, "%s: SIOCSIFFLAGS", my_ifr.ifr_name);
1445}
1446
1447void
1448setifxflags(const char *vname, int value)
1449{
1450 struct ifreq my_ifr;
1451
1452 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq));
1453
1454 if (ioctl(sock, SIOCGIFXFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((158)))
, (caddr_t)&my_ifr) == -1)
1455 warn("%s: SIOCGIFXFLAGS", my_ifr.ifr_name);
1456 (void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name));
1457 xflags = my_ifr.ifr_flagsifr_ifru.ifru_flags;
1458
1459 if (value < 0) {
1460 value = -value;
1461 xflags &= ~value;
1462 } else
1463 xflags |= value;
1464 my_ifr.ifr_flagsifr_ifru.ifru_flags = xflags;
1465 if (ioctl(sock, SIOCSIFXFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((157)))
, (caddr_t)&my_ifr) == -1)
1466 warn("%s: SIOCSIFXFLAGS", my_ifr.ifr_name);
1467}
1468
1469void
1470addaf(const char *vname, int value)
1471{
1472 struct if_afreq ifar;
1473
1474 strlcpy(ifar.ifar_name, ifname, sizeof(ifar.ifar_name));
1475 ifar.ifar_af = value;
1476 if (ioctl(sock, SIOCIFAFATTACH((unsigned long)0x80000000 | ((sizeof(struct if_afreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((171)))
, (caddr_t)&ifar) == -1)
1477 warn("%s: SIOCIFAFATTACH", ifar.ifar_name);
1478}
1479
1480void
1481removeaf(const char *vname, int value)
1482{
1483 struct if_afreq ifar;
1484
1485 strlcpy(ifar.ifar_name, ifname, sizeof(ifar.ifar_name));
1486 ifar.ifar_af = value;
1487 if (ioctl(sock, SIOCIFAFDETACH((unsigned long)0x80000000 | ((sizeof(struct if_afreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((172)))
, (caddr_t)&ifar) == -1)
1488 warn("%s: SIOCIFAFDETACH", ifar.ifar_name);
1489}
1490
1491void
1492setia6flags(const char *vname, int value)
1493{
1494
1495 if (value < 0) {
1496 value = -value;
1497 in6_addreq.ifra_flags &= ~value;
1498 } else
1499 in6_addreq.ifra_flags |= value;
1500}
1501
1502void
1503setia6pltime(const char *val, int d)
1504{
1505
1506 setia6lifetime("pltime", val);
1507}
1508
1509void
1510setia6vltime(const char *val, int d)
1511{
1512
1513 setia6lifetime("vltime", val);
1514}
1515
1516void
1517setia6lifetime(const char *cmd, const char *val)
1518{
1519 const char *errmsg = NULL((void *)0);
1520 time_t newval, t;
1521
1522 newval = strtonum(val, 0, 1000000, &errmsg);
1523 if (errmsg)
1524 errx(1, "invalid %s %s: %s", cmd, val, errmsg);
1525
1526 t = time(NULL((void *)0));
1527
1528 if (afp->af_af != AF_INET624)
1529 errx(1, "%s not allowed for this address family", cmd);
1530 if (strcmp(cmd, "vltime") == 0) {
1531 in6_addreq.ifra_lifetime.ia6t_expire = t + newval;
1532 in6_addreq.ifra_lifetime.ia6t_vltime = newval;
1533 } else if (strcmp(cmd, "pltime") == 0) {
1534 in6_addreq.ifra_lifetime.ia6t_preferred = t + newval;
1535 in6_addreq.ifra_lifetime.ia6t_pltime = newval;
1536 }
1537}
1538
1539void
1540setia6eui64(const char *cmd, int val)
1541{
1542 struct ifaddrs *ifap, *ifa;
1543 const struct sockaddr_in6 *sin6 = NULL((void *)0);
1544 const struct in6_addr *lladdr = NULL((void *)0);
1545 struct in6_addr *in6;
1546
1547 if (afp->af_af != AF_INET624)
1548 errx(1, "%s not allowed for this address family", cmd);
1549
1550 addaf(ifname, AF_INET624);
1551
1552 in6 = (struct in6_addr *)&in6_addreq.ifra_addrifra_ifrau.ifrau_addr.sin6_addr;
1553 if (memcmp(&in6addr_any.s6_addr__u6_addr.__u6_addr8[8], &in6->s6_addr__u6_addr.__u6_addr8[8], 8) != 0)
1554 errx(1, "interface index is already filled");
1555 if (getifaddrs(&ifap) != 0)
1556 err(1, "getifaddrs");
1557 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1558 if (ifa->ifa_addr->sa_family == AF_INET624 &&
1559 strcmp(ifa->ifa_name, ifname) == 0) {
1560 sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr;
1561 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))
) {
1562 lladdr = &sin6->sin6_addr;
1563 break;
1564 }
1565 }
1566 }
1567 if (!lladdr)
1568 errx(1, "could not determine link local address");
1569
1570 memcpy(&in6->s6_addr__u6_addr.__u6_addr8[8], &lladdr->s6_addr__u6_addr.__u6_addr8[8], 8);
1571
1572 freeifaddrs(ifap);
1573}
1574
1575void
1576setautoconf(const char *cmd, int val)
1577{
1578 switch (afp->af_af) {
1579 case AF_INET2:
1580 setifxflags("inet", val * IFXF_AUTOCONF40x80);
1581 break;
1582 case AF_INET624:
1583 if (val > 0)
1584 setifxflags("inet6", (IFXF_AUTOCONF60x20 |
1585 IFXF_AUTOCONF6TEMP0x4));
1586 else
1587 setifxflags("inet6", -IFXF_AUTOCONF60x20);
1588 break;
1589 default:
1590 errx(1, "autoconf not allowed for this address family");
1591 }
1592}
1593
1594void
1595settemporary(const char *cmd, int val)
1596{
1597 switch (afp->af_af) {
1598 case AF_INET624:
1599 setifxflags("inet6", val * IFXF_AUTOCONF6TEMP0x4);
1600 break;
1601 default:
1602 errx(1, "temporary not allowed for this address family");
1603 }
1604}
1605
1606#ifndef SMALL
1607void
1608setifmetric(const char *val, int ignored)
1609{
1610 const char *errmsg = NULL((void *)0);
1611
1612 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1613
1614 ifr.ifr_metricifr_ifru.ifru_metric = strtonum(val, 0, INT_MAX0x7fffffff, &errmsg);
1615 if (errmsg)
1616 errx(1, "metric %s: %s", val, errmsg);
1617 if (ioctl(sock, SIOCSIFMETRIC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((24)))
, (caddr_t)&ifr) == -1)
1618 warn("SIOCSIFMETRIC");
1619}
1620#endif
1621
1622void
1623setifmtu(const char *val, int d)
1624{
1625 const char *errmsg = NULL((void *)0);
1626
1627 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1628
1629 ifr.ifr_mtuifr_ifru.ifru_metric = strtonum(val, 0, INT_MAX0x7fffffff, &errmsg);
1630 if (errmsg)
1631 errx(1, "mtu %s: %s", val, errmsg);
1632 if (ioctl(sock, SIOCSIFMTU((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((127)))
, (caddr_t)&ifr) == -1)
1633 warn("SIOCSIFMTU");
1634}
1635
1636void
1637setifllprio(const char *val, int d)
1638{
1639 const char *errmsg = NULL((void *)0);
1640
1641 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1642
1643 ifr.ifr_llprioifr_ifru.ifru_metric = strtonum(val, 0, UCHAR_MAX0xff, &errmsg);
1644 if (errmsg)
1645 errx(1, "llprio %s: %s", val, errmsg);
1646 if (ioctl(sock, SIOCSIFLLPRIO((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((181)))
, (caddr_t)&ifr) == -1)
1647 warn("SIOCSIFLLPRIO");
1648}
1649
1650void
1651setifgroup(const char *group_name, int dummy)
1652{
1653 struct ifgroupreq ifgr;
1654 size_t namelen;
1655
1656 memset(&ifgr, 0, sizeof(ifgr));
1657 strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ16);
1658
1659 namelen = strlen(group_name);
1660 if (namelen == 0)
1661 errx(1, "setifgroup: group name empty");
1662 if (namelen >= IFNAMSIZ16)
1663 errx(1, "setifgroup: group name too long");
1664 if (isdigit((unsigned char)group_name[namelen - 1]))
1665 errx(1, "setifgroup: group names may not end in a digit");
1666
1667 strlcpy(ifgr.ifgr_groupifgr_ifgru.ifgru_group, group_name, IFNAMSIZ16);
1668 if (ioctl(sock, SIOCAIFGROUP((unsigned long)0x80000000 | ((sizeof(struct ifgroupreq) &
0x1fff) << 16) | ((('i')) << 8) | ((135)))
, (caddr_t)&ifgr) == -1) {
1669 if (errno(*__errno()) != EEXIST17)
1670 err(1,"%s: SIOCAIFGROUP", group_name);
1671 }
1672}
1673
1674void
1675unsetifgroup(const char *group_name, int dummy)
1676{
1677 struct ifgroupreq ifgr;
1678
1679 memset(&ifgr, 0, sizeof(ifgr));
1680 strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ16);
1681
1682 if (strlcpy(ifgr.ifgr_groupifgr_ifgru.ifgru_group, group_name, IFNAMSIZ16) >= IFNAMSIZ16)
1683 errx(1, "unsetifgroup: group name too long");
1684 if (ioctl(sock, SIOCDIFGROUP((unsigned long)0x80000000 | ((sizeof(struct ifgroupreq) &
0x1fff) << 16) | ((('i')) << 8) | ((137)))
, (caddr_t)&ifgr) == -1)
1685 err(1, "%s: SIOCDIFGROUP", group_name);
1686}
1687
1688const char *
1689get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
1690{
1691 int len = *lenp, hexstr;
1692 u_int8_t *p = buf;
1693
1694 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x');
1695 if (hexstr)
1696 val += 2;
1697 for (;;) {
1698 if (*val == '\0')
1699 break;
1700 if (sep != NULL((void *)0) && strchr(sep, *val) != NULL((void *)0)) {
1701 val++;
1702 break;
1703 }
1704 if (hexstr) {
1705 if (!isxdigit((u_char)val[0]) ||
1706 !isxdigit((u_char)val[1])) {
1707 warnx("bad hexadecimal digits");
1708 return NULL((void *)0);
1709 }
1710 }
1711 if (p > buf + len) {
1712 if (hexstr)
1713 warnx("hexadecimal digits too long");
1714 else
1715 warnx("strings too long");
1716 return NULL((void *)0);
1717 }
1718 if (hexstr) {
1719#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
1720 *p++ = (tohex((u_char)val[0]) << 4) |
1721 tohex((u_char)val[1]);
1722#undef tohex
1723 val += 2;
1724 } else {
1725 if (*val == '\\' &&
1726 sep != NULL((void *)0) && strchr(sep, *(val + 1)) != NULL((void *)0))
1727 val++;
1728 *p++ = *val++;
1729 }
1730 }
1731 len = p - buf;
1732 if (len < *lenp)
1733 memset(p, 0, *lenp - len);
1734 *lenp = len;
1735 return val;
1736}
1737
1738int
1739len_string(const u_int8_t *buf, int len)
1740{
1741 int i = 0, hasspc = 0;
1742
1743 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') {
1744 for (; i < len; i++) {
1745 /* Only print 7-bit ASCII keys */
1746 if (buf[i] & 0x80 || !isprint(buf[i]))
1747 break;
1748 if (isspace(buf[i]))
1749 hasspc++;
1750 }
1751 }
1752 if (i == len) {
1753 if (hasspc || len == 0)
1754 return len + 2;
1755 else
1756 return len;
1757 } else
1758 return (len * 2) + 2;
1759}
1760
1761int
1762print_string(const u_int8_t *buf, int len)
1763{
1764 int i = 0, hasspc = 0;
1765
1766 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') {
1767 for (; i < len; i++) {
1768 /* Only print 7-bit ASCII keys */
1769 if (buf[i] & 0x80 || !isprint(buf[i]))
1770 break;
1771 if (isspace(buf[i]))
1772 hasspc++;
1773 }
1774 }
1775 if (i == len) {
1776 if (hasspc || len == 0) {
1777 printf("\"%.*s\"", len, buf);
1778 return len + 2;
1779 } else {
1780 printf("%.*s", len, buf);
1781 return len;
1782 }
1783 } else {
1784 printf("0x");
1785 for (i = 0; i < len; i++)
1786 printf("%02x", buf[i]);
1787 return (len * 2) + 2;
1788 }
1789}
1790
1791void
1792setifnwid(const char *val, int d)
1793{
1794 struct ieee80211_nwid nwid;
1795 int len;
1796
1797 if (joinlen != 0) {
1798 errx(1, "nwid and join may not be used at the same time");
1799 }
1800
1801 if (nwidlen != 0) {
1802 errx(1, "nwid may not be specified twice");
1803 }
1804
1805 if (d != 0) {
1806 /* no network id is especially desired */
1807 memset(&nwid, 0, sizeof(nwid));
1808 len = 0;
1809 } else {
1810 len = sizeof(nwid.i_nwid);
1811 if (get_string(val, NULL((void *)0), nwid.i_nwid, &len) == NULL((void *)0))
1812 return;
1813 }
1814 nwidlen = nwid.i_len = len;
1815 (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1816 memcpy(nwidname, nwid.i_nwid, len);
1817 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&nwid;
1818 if (ioctl(sock, SIOCS80211NWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((230)))
, (caddr_t)&ifr) == -1)
1819 warn("SIOCS80211NWID");
1820}
1821
1822
1823void
1824process_join_commands(void)
1825{
1826 if (!(actions & A_JOIN0x0020))
1827 return;
1828
1829 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&join;
1830 if (ioctl(sock, SIOCS80211JOIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((255)))
, (caddr_t)&ifr) == -1)
1831 err(1, "%s: SIOCS80211JOIN", ifr.ifr_name);
1832}
1833
1834void
1835setifjoin(const char *val, int d)
1836{
1837 int len;
1838
1839 if (nwidlen != 0) {
1840 errx(1, "nwid and join may not be used at the same time");
1841 }
1842
1843 if (joinlen != 0) {
1844 errx(1, "join may not be specified twice");
1845 }
1846
1847 if (d != 0) {
1848 /* no network id is especially desired */
1849 memset(&join, 0, sizeof(join));
1850 len = 0;
1851 } else {
1852 len = sizeof(join.i_nwid);
1853 if (get_string(val, NULL((void *)0), join.i_nwid, &len) == NULL((void *)0))
1854 return;
1855 if (len == 0)
1856 join.i_flags |= IEEE80211_JOIN_ANY0x80;
1857 }
1858 joinlen = join.i_len = len;
1859 (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1860 memcpy(joinname, join.i_nwid, len);
1861
1862 actions |= A_JOIN0x0020;
1863}
1864
1865void
1866delifjoin(const char *val, int d)
1867{
1868 struct ieee80211_join join;
1869 int len;
1870
1871 memset(&join, 0, sizeof(join));
1872 len = 0;
1873 join.i_flags |= IEEE80211_JOIN_DEL0x04;
1874
1875 if (d == -1) {
1876 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&join;
1877 if (ioctl(sock, SIOCS80211JOIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((255)))
, (caddr_t)&ifr) == -1)
1878 err(1, "%s: SIOCS80211JOIN", ifr.ifr_name);
1879 }
1880
1881 len = sizeof(join.i_nwid);
1882 if (get_string(val, NULL((void *)0), join.i_nwid, &len) == NULL((void *)0))
1883 return;
1884 join.i_len = len;
1885 if (len == 0)
1886 join.i_flags |= IEEE80211_JOIN_ANY0x80;
1887 (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1888 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&join;
1889 if (ioctl(sock, SIOCS80211JOIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((255)))
, (caddr_t)&ifr) == -1)
1890 err(1, "%s: SIOCS80211JOIN", ifr.ifr_name);
1891}
1892
1893void
1894delifjoinlist(const char *val, int d)
1895{
1896 struct ieee80211_join join;
1897
1898 memset(&join, 0, sizeof(join));
1899 join.i_flags |= (IEEE80211_JOIN_DEL0x04 | IEEE80211_JOIN_DEL_ALL0x100);
1900
1901 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&join;
1902 if (ioctl(sock, SIOCS80211JOIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((255)))
, (caddr_t)&ifr) == -1)
1903 err(1, "%s: SIOCS80211JOIN", ifr.ifr_name);
1904}
1905
1906void
1907setifbssid(const char *val, int d)
1908{
1909
1910 struct ieee80211_bssid bssid;
1911 struct ether_addr *ea;
1912
1913 if (d != 0) {
1914 /* no BSSID is especially desired */
1915 memset(&bssid.i_bssid, 0, sizeof(bssid.i_bssid));
1916 } else {
1917 ea = ether_aton((char*)val);
1918 if (ea == NULL((void *)0)) {
1919 warnx("malformed BSSID: %s", val);
1920 return;
1921 }
1922 memcpy(&bssid.i_bssid, ea->ether_addr_octet,
1923 sizeof(bssid.i_bssid));
1924 }
1925 strlcpy(bssid.i_name, ifname, sizeof(bssid.i_name));
1926 if (ioctl(sock, SIOCS80211BSSID((unsigned long)0x80000000 | ((sizeof(struct ieee80211_bssid)
& 0x1fff) << 16) | ((('i')) << 8) | ((240)))
, &bssid) == -1)
1927 warn("%s: SIOCS80211BSSID", bssid.i_name);
1928}
1929
1930void
1931setifnwkey(const char *val, int d)
1932{
1933 int i, len;
1934 struct ieee80211_nwkey nwkey;
1935 u_int8_t keybuf[IEEE80211_WEP_NKID4][16];
1936
1937 bzero(&nwkey, sizeof(nwkey));
1938 bzero(&keybuf, sizeof(keybuf));
1939
1940 nwkey.i_wepon = IEEE80211_NWKEY_WEP1;
1941 nwkey.i_defkid = 1;
1942 if (d == -1) {
1943 /* disable WEP encryption */
1944 nwkey.i_wepon = IEEE80211_NWKEY_OPEN0;
1945 i = 0;
Value stored to 'i' is never read
1946 } else if (strcasecmp("persist", val) == 0) {
1947 /* use all values from persistent memory */
1948 nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST0x100;
1949 nwkey.i_defkid = 0;
1950 for (i = 0; i < IEEE80211_WEP_NKID4; i++)
1951 nwkey.i_key[i].i_keylen = -1;
1952 } else if (strncasecmp("persist:", val, 8) == 0) {
1953 val += 8;
1954 /* program keys in persistent memory */
1955 nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST0x100;
1956 goto set_nwkey;
1957 } else {
1958 set_nwkey:
1959 if (isdigit((unsigned char)val[0]) && val[1] == ':') {
1960 /* specifying a full set of four keys */
1961 nwkey.i_defkid = val[0] - '0';
1962 val += 2;
1963 for (i = 0; i < IEEE80211_WEP_NKID4; i++) {
1964 len = sizeof(keybuf[i]);
1965 val = get_string(val, ",", keybuf[i], &len);
1966 if (val == NULL((void *)0))
1967 return;
1968 nwkey.i_key[i].i_keylen = len;
1969 nwkey.i_key[i].i_keydat = keybuf[i];
1970 }
1971 if (*val != '\0') {
1972 warnx("SIOCS80211NWKEY: too many keys.");
1973 return;
1974 }
1975 } else {
1976 /*
1977 * length of each key must be either a 5
1978 * character ASCII string or 10 hex digits for
1979 * 40 bit encryption, or 13 character ASCII
1980 * string or 26 hex digits for 128 bit
1981 * encryption.
1982 */
1983 int j;
1984 char *tmp = NULL((void *)0);
1985 size_t vlen = strlen(val);
1986 switch(vlen) {
1987 case 10:
1988 case 26:
1989 /* 0x must be missing for these lengths */
1990 j = asprintf(&tmp, "0x%s", val);
1991 if (j == -1) {
1992 warnx("malloc failed");
1993 return;
1994 }
1995 val = tmp;
1996 break;
1997 case 12:
1998 case 28:
1999 case 5:
2000 case 13:
2001 /* 0xkey or string case - all is ok */
2002 break;
2003 default:
2004 warnx("Invalid WEP key length");
2005 return;
2006 }
2007 len = sizeof(keybuf[0]);
2008 val = get_string(val, NULL((void *)0), keybuf[0], &len);
2009 free(tmp);
2010 if (val == NULL((void *)0))
2011 return;
2012 nwkey.i_key[0].i_keylen = len;
2013 nwkey.i_key[0].i_keydat = keybuf[0];
2014 i = 1;
2015 }
2016 }
2017 (void)strlcpy(nwkey.i_name, ifname, sizeof(nwkey.i_name));
2018
2019 if (actions & A_JOIN0x0020) {
2020 memcpy(&join.i_nwkey, &nwkey, sizeof(join.i_nwkey));
2021 join.i_flags |= IEEE80211_JOIN_NWKEY0x08;
2022 return;
2023 }
2024
2025 if (ioctl(sock, SIOCS80211NWKEY((unsigned long)0x80000000 | ((sizeof(struct ieee80211_nwkey)
& 0x1fff) << 16) | ((('i')) << 8) | ((232)))
, (caddr_t)&nwkey) == -1)
2026 err(1, "%s: SIOCS80211NWKEY", nwkey.i_name);
2027}
2028
2029void
2030setifwpa(const char *val, int d)
2031{
2032 struct ieee80211_wpaparams wpa;
2033
2034 memset(&wpa, 0, sizeof(wpa));
2035 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name));
2036 /* Don't read current values. The kernel will set defaults. */
2037 wpa.i_enabled = d;
2038
2039 if (actions & A_JOIN0x0020) {
2040 join.i_wpaparams.i_enabled = d;
2041 join.i_flags |= IEEE80211_JOIN_WPA0x10;
2042 return;
2043 }
2044
2045 if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams
) & 0x1fff) << 16) | ((('i')) << 8) | ((247))
)
, (caddr_t)&wpa) == -1)
2046 err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name);
2047}
2048
2049void
2050setifwpaprotos(const char *val, int d)
2051{
2052 struct ieee80211_wpaparams wpa;
2053 char *optlist, *str;
2054 u_int rval = 0;
2055
2056 if ((optlist = strdup(val)) == NULL((void *)0))
2057 err(1, "strdup");
2058 str = strtok(optlist, ",");
2059 while (str != NULL((void *)0)) {
2060 if (strcasecmp(str, "wpa1") == 0)
2061 rval |= IEEE80211_WPA_PROTO_WPA10x01;
2062 else if (strcasecmp(str, "wpa2") == 0)
2063 rval |= IEEE80211_WPA_PROTO_WPA20x02;
2064 else
2065 errx(1, "wpaprotos: unknown protocol: %s", str);
2066 str = strtok(NULL((void *)0), ",");
2067 }
2068 free(optlist);
2069
2070 if (actions & A_JOIN0x0020) {
2071 join.i_wpaparams.i_protos = rval;
2072 join.i_flags |= IEEE80211_JOIN_WPA0x10;
2073 return;
2074 }
2075
2076 memset(&wpa, 0, sizeof(wpa));
2077 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name));
2078 if (ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_wpaparams) & 0x1fff) << 16) | (((
'i')) << 8) | ((248)))
, (caddr_t)&wpa) == -1)
2079 err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name);
2080 wpa.i_protos = rval;
2081 /* Let the kernel set up the appropriate default ciphers. */
2082 wpa.i_ciphers = 0;
2083 wpa.i_groupcipher = 0;
2084
2085 if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams
) & 0x1fff) << 16) | ((('i')) << 8) | ((247))
)
, (caddr_t)&wpa) == -1)
2086 err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name);
2087}
2088
2089void
2090setifwpaakms(const char *val, int d)
2091{
2092 struct ieee80211_wpaparams wpa;
2093 char *optlist, *str;
2094 u_int rval = 0;
2095
2096 if ((optlist = strdup(val)) == NULL((void *)0))
2097 err(1, "strdup");
2098 str = strtok(optlist, ",");
2099 while (str != NULL((void *)0)) {
2100 if (strcasecmp(str, "psk") == 0)
2101 rval |= IEEE80211_WPA_AKM_PSK0x01;
2102 else if (strcasecmp(str, "802.1x") == 0)
2103 rval |= IEEE80211_WPA_AKM_8021X0x02;
2104 else
2105 errx(1, "wpaakms: unknown akm: %s", str);
2106 str = strtok(NULL((void *)0), ",");
2107 }
2108 free(optlist);
2109
2110 if (actions & A_JOIN0x0020) {
2111 join.i_wpaparams.i_akms = rval;
2112 join.i_wpaparams.i_enabled =
2113 ((rval & IEEE80211_WPA_AKM_8021X0x02) != 0);
2114 join.i_flags |= IEEE80211_JOIN_WPA0x10;
2115 return;
2116 }
2117
2118 memset(&wpa, 0, sizeof(wpa));
2119 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name));
2120 if (ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_wpaparams) & 0x1fff) << 16) | (((
'i')) << 8) | ((248)))
, (caddr_t)&wpa) == -1)
2121 err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name);
2122 wpa.i_akms = rval;
2123 /* Enable WPA for 802.1x here. PSK case is handled in setifwpakey(). */
2124 wpa.i_enabled = ((rval & IEEE80211_WPA_AKM_8021X0x02) != 0);
2125
2126 if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams
) & 0x1fff) << 16) | ((('i')) << 8) | ((247))
)
, (caddr_t)&wpa) == -1)
2127 err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name);
2128}
2129
2130static const struct {
2131 const char *name;
2132 u_int cipher;
2133} ciphers[] = {
2134 { "usegroup", IEEE80211_WPA_CIPHER_USEGROUP0x01 },
2135 { "wep40", IEEE80211_WPA_CIPHER_WEP400x02 },
2136 { "tkip", IEEE80211_WPA_CIPHER_TKIP0x04 },
2137 { "ccmp", IEEE80211_WPA_CIPHER_CCMP0x08 },
2138 { "wep104", IEEE80211_WPA_CIPHER_WEP1040x10 }
2139};
2140
2141u_int
2142getwpacipher(const char *name)
2143{
2144 int i;
2145
2146 for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); i++)
2147 if (strcasecmp(name, ciphers[i].name) == 0)
2148 return ciphers[i].cipher;
2149 return IEEE80211_WPA_CIPHER_NONE0x00;
2150}
2151
2152void
2153setifwpaciphers(const char *val, int d)
2154{
2155 struct ieee80211_wpaparams wpa;
2156 char *optlist, *str;
2157 u_int rval = 0;
2158
2159 if ((optlist = strdup(val)) == NULL((void *)0))
2160 err(1, "strdup");
2161 str = strtok(optlist, ",");
2162 while (str != NULL((void *)0)) {
2163 u_int cipher = getwpacipher(str);
2164 if (cipher == IEEE80211_WPA_CIPHER_NONE0x00)
2165 errx(1, "wpaciphers: unknown cipher: %s", str);
2166
2167 rval |= cipher;
2168 str = strtok(NULL((void *)0), ",");
2169 }
2170 free(optlist);
2171
2172 if (actions & A_JOIN0x0020) {
2173 join.i_wpaparams.i_ciphers = rval;
2174 join.i_flags |= IEEE80211_JOIN_WPA0x10;
2175 return;
2176 }
2177
2178 memset(&wpa, 0, sizeof(wpa));
2179 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name));
2180 if (ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_wpaparams) & 0x1fff) << 16) | (((
'i')) << 8) | ((248)))
, (caddr_t)&wpa) == -1)
2181 err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name);
2182 wpa.i_ciphers = rval;
2183
2184 if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams
) & 0x1fff) << 16) | ((('i')) << 8) | ((247))
)
, (caddr_t)&wpa) == -1)
2185 err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name);
2186}
2187
2188void
2189setifwpagroupcipher(const char *val, int d)
2190{
2191 struct ieee80211_wpaparams wpa;
2192 u_int cipher;
2193
2194 cipher = getwpacipher(val);
2195 if (cipher == IEEE80211_WPA_CIPHER_NONE0x00)
2196 errx(1, "wpagroupcipher: unknown cipher: %s", val);
2197
2198 memset(&wpa, 0, sizeof(wpa));
2199 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name));
2200 if (ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_wpaparams) & 0x1fff) << 16) | (((
'i')) << 8) | ((248)))
, (caddr_t)&wpa) == -1)
2201 err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name);
2202 wpa.i_groupcipher = cipher;
2203
2204 if (actions & A_JOIN0x0020) {
2205 join.i_wpaparams.i_groupcipher = cipher;
2206 join.i_flags |= IEEE80211_JOIN_WPA0x10;
2207 return;
2208 }
2209
2210 if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams
) & 0x1fff) << 16) | ((('i')) << 8) | ((247))
)
, (caddr_t)&wpa) == -1)
2211 err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name);
2212}
2213
2214void
2215setifwpakey(const char *val, int d)
2216{
2217 struct ieee80211_wpaparams wpa;
2218 struct ieee80211_wpapsk psk;
2219 struct ieee80211_nwid nwid;
2220 int passlen;
2221
2222 memset(&psk, 0, sizeof(psk));
2223 if (d != -1) {
2224 memset(&ifr, 0, sizeof(ifr));
2225 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&nwid;
2226 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2227
2228 /* Use the value specified in 'join' or 'nwid' */
2229 if (joinlen != 0) {
2230 memcpy(nwid.i_nwid, joinname, joinlen);
2231 nwid.i_len = joinlen;
2232 } else if (nwidlen != 0) {
2233 memcpy(nwid.i_nwid, nwidname, nwidlen);
2234 nwid.i_len = nwidlen;
2235 } else {
2236 warnx("no nwid or join command, guessing nwid to use");
2237
2238 if (ioctl(sock, SIOCG80211NWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((231)))
, (caddr_t)&ifr) == -1)
2239 err(1, "%s: SIOCG80211NWID", ifr.ifr_name);
2240 }
2241
2242 passlen = strlen(val);
2243 if (passlen == 2 + 2 * sizeof(psk.i_psk) &&
2244 val[0] == '0' && val[1] == 'x') {
2245 /* Parse a WPA hex key (must be full-length) */
2246 passlen = sizeof(psk.i_psk);
2247 val = get_string(val, NULL((void *)0), psk.i_psk, &passlen);
2248 if (val == NULL((void *)0) || passlen != sizeof(psk.i_psk))
2249 errx(1, "wpakey: invalid pre-shared key");
2250 } else {
2251 /* Parse a WPA passphrase */
2252 if (passlen < 8 || passlen > 63)
2253 errx(1, "wpakey: passphrase must be between "
2254 "8 and 63 characters");
2255 if (nwid.i_len == 0)
2256 errx(1, "wpakey: nwid not set");
2257 if (pkcs5_pbkdf2(val, passlen, nwid.i_nwid, nwid.i_len,
2258 psk.i_psk, sizeof(psk.i_psk), 4096) != 0)
2259 errx(1, "wpakey: passphrase hashing failed");
2260 }
2261 psk.i_enabled = 1;
2262 } else
2263 psk.i_enabled = 0;
2264
2265 (void)strlcpy(psk.i_name, ifname, sizeof(psk.i_name));
2266
2267 if (actions & A_JOIN0x0020) {
2268 memcpy(&join.i_wpapsk, &psk, sizeof(join.i_wpapsk));
2269 join.i_flags |= IEEE80211_JOIN_WPAPSK0x20;
2270 if (!join.i_wpaparams.i_enabled)
2271 setifwpa(NULL((void *)0), join.i_wpapsk.i_enabled);
2272 return;
2273 }
2274
2275 if (ioctl(sock, SIOCS80211WPAPSK((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpapsk
) & 0x1fff) << 16) | ((('i')) << 8) | ((245))
)
, (caddr_t)&psk) == -1)
2276 err(1, "%s: SIOCS80211WPAPSK", psk.i_name);
2277
2278 /* And ... automatically enable or disable WPA */
2279 memset(&wpa, 0, sizeof(wpa));
2280 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name));
2281 if (ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_wpaparams) & 0x1fff) << 16) | (((
'i')) << 8) | ((248)))
, (caddr_t)&wpa) == -1)
2282 err(1, "%s: SIOCG80211WPAPARMS", psk.i_name);
2283 wpa.i_enabled = psk.i_enabled;
2284 if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams
) & 0x1fff) << 16) | ((('i')) << 8) | ((247))
)
, (caddr_t)&wpa) == -1)
2285 err(1, "%s: SIOCS80211WPAPARMS", psk.i_name);
2286}
2287
2288void
2289setifchan(const char *val, int d)
2290{
2291 struct ieee80211chanreq channel;
2292 const char *errstr;
2293 int chan;
2294
2295 if (val == NULL((void *)0)) {
2296 if (shownet80211chans || shownet80211nodes)
2297 usage();
2298 shownet80211chans = 1;
2299 return;
2300 }
2301 if (d != 0)
2302 chan = IEEE80211_CHAN_ANY0xffff;
2303 else {
2304 chan = strtonum(val, 1, 256, &errstr);
2305 if (errstr) {
2306 warnx("invalid channel %s: %s", val, errstr);
2307 return;
2308 }
2309 }
2310
2311 strlcpy(channel.i_name, ifname, sizeof(channel.i_name));
2312 channel.i_channel = (u_int16_t)chan;
2313 if (ioctl(sock, SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq
) & 0x1fff) << 16) | ((('i')) << 8) | ((238))
)
, (caddr_t)&channel) == -1)
2314 warn("%s: SIOCS80211CHANNEL", channel.i_name);
2315}
2316
2317void
2318setifscan(const char *val, int d)
2319{
2320 if (shownet80211chans || shownet80211nodes)
2321 usage();
2322 shownet80211nodes = 1;
2323}
2324
2325#ifndef SMALL
2326
2327void
2328setifnwflag(const char *val, int d)
2329{
2330 static const struct ieee80211_flags nwflags[] = IEEE80211_FLAGS{ { "hidenwid", 0x00000001 }, { "nobridge", 0x00000002 }, { "stayauth"
, 0x00000004 }, { "nomimo", 0x00000008 } }
;
2331 u_int i, flag = 0;
2332
2333 for (i = 0; i < (sizeof(nwflags) / sizeof(nwflags[0])); i++) {
2334 if (strcmp(val, nwflags[i].f_name) == 0) {
2335 flag = nwflags[i].f_flag;
2336 break;
2337 }
2338 }
2339 if (flag == 0)
2340 errx(1, "Invalid nwflag: %s", val);
2341
2342 if (ioctl(sock, SIOCG80211FLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((216)))
, (caddr_t)&ifr) != 0)
2343 err(1, "%s: SIOCG80211FLAGS", ifr.ifr_name);
2344
2345 if (d)
2346 ifr.ifr_flagsifr_ifru.ifru_flags &= ~flag;
2347 else
2348 ifr.ifr_flagsifr_ifru.ifru_flags |= flag;
2349
2350 if (ioctl(sock, SIOCS80211FLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((217)))
, (caddr_t)&ifr) != 0)
2351 err(1, "%s: SIOCS80211FLAGS", ifr.ifr_name);
2352}
2353
2354void
2355unsetifnwflag(const char *val, int d)
2356{
2357 setifnwflag(val, 1);
2358}
2359
2360void
2361setifpowersave(const char *val, int d)
2362{
2363 struct ieee80211_power power;
2364 const char *errmsg = NULL((void *)0);
2365
2366 (void)strlcpy(power.i_name, ifname, sizeof(power.i_name));
2367 if (ioctl(sock, SIOCG80211POWER(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_power) & 0x1fff) << 16) | ((('i')
) << 8) | ((235)))
, (caddr_t)&power) == -1) {
2368 warn("%s: SIOCG80211POWER", power.i_name);
2369 return;
2370 }
2371
2372 if (d != -1 && val != NULL((void *)0)) {
2373 power.i_maxsleep = strtonum(val, 0, INT_MAX0x7fffffff, &errmsg);
2374 if (errmsg)
2375 errx(1, "powersave %s: %s", val, errmsg);
2376 }
2377
2378 power.i_enabled = d == -1 ? 0 : 1;
2379 if (ioctl(sock, SIOCS80211POWER((unsigned long)0x80000000 | ((sizeof(struct ieee80211_power)
& 0x1fff) << 16) | ((('i')) << 8) | ((234)))
, (caddr_t)&power) == -1)
2380 warn("%s: SIOCS80211POWER", power.i_name);
2381}
2382#endif
2383
2384void
2385print_cipherset(u_int32_t cipherset)
2386{
2387 const char *sep = "";
2388 int i;
2389
2390 if (cipherset == IEEE80211_WPA_CIPHER_NONE0x00) {
2391 printf("none");
2392 return;
2393 }
2394 for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); i++) {
2395 if (cipherset & ciphers[i].cipher) {
2396 printf("%s%s", sep, ciphers[i].name);
2397 sep = ",";
2398 }
2399 }
2400}
2401
2402static void
2403print_assoc_failures(uint32_t assoc_fail)
2404{
2405 /* Filter out the most obvious failure cases. */
2406 assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_ESSID0x10;
2407 if (assoc_fail & IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY0x04)
2408 assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_WPA_PROTO0x40;
2409 assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY0x04;
2410
2411 if (assoc_fail == 0)
2412 return;
2413
2414 printb_status(assoc_fail, IEEE80211_NODEREQ_ASSOCFAIL_BITS"\20\1!CHAN\2!IBSS\3!PRIVACY\4!BASICRATE\5!ESSID\6!BSSID\7!WPAPROTO"
"\10!WPAKEY"
);
2415}
2416
2417void
2418ieee80211_status(void)
2419{
2420 int len, inwid, ijoin, inwkey, ipsk, ichan, ipwr;
2421 int ibssid, iwpa, assocfail = 0;
2422 struct ieee80211_nwid nwid;
2423 struct ieee80211_join join;
2424 struct ieee80211_nwkey nwkey;
2425 struct ieee80211_wpapsk psk;
2426 struct ieee80211_power power;
2427 struct ieee80211chanreq channel;
2428 struct ieee80211_bssid bssid;
2429 struct ieee80211_wpaparams wpa;
2430 struct ieee80211_nodereq nr;
2431 u_int8_t zero_bssid[IEEE80211_ADDR_LEN6];
2432 struct ether_addr ea;
2433
2434 /* get current status via ioctls */
2435 memset(&ifr, 0, sizeof(ifr));
2436 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&nwid;
2437 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2438 inwid = ioctl(sock, SIOCG80211NWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((231)))
, (caddr_t)&ifr);
2439
2440 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&join;
2441 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2442 ijoin = ioctl(sock, SIOCG80211JOIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((0)))
, (caddr_t)&ifr);
2443
2444 memset(&nwkey, 0, sizeof(nwkey));
2445 strlcpy(nwkey.i_name, ifname, sizeof(nwkey.i_name));
2446 inwkey = ioctl(sock, SIOCG80211NWKEY(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_nwkey) & 0x1fff) << 16) | ((('i')
) << 8) | ((233)))
, (caddr_t)&nwkey);
2447
2448 memset(&psk, 0, sizeof(psk));
2449 strlcpy(psk.i_name, ifname, sizeof(psk.i_name));
2450 ipsk = ioctl(sock, SIOCG80211WPAPSK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_wpapsk) & 0x1fff) << 16) | ((('i'
)) << 8) | ((246)))
, (caddr_t)&psk);
2451
2452 memset(&power, 0, sizeof(power));
2453 strlcpy(power.i_name, ifname, sizeof(power.i_name));
2454 ipwr = ioctl(sock, SIOCG80211POWER(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_power) & 0x1fff) << 16) | ((('i')
) << 8) | ((235)))
, &power);
2455
2456 memset(&channel, 0, sizeof(channel));
2457 strlcpy(channel.i_name, ifname, sizeof(channel.i_name));
2458 ichan = ioctl(sock, SIOCG80211CHANNEL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211chanreq) & 0x1fff) << 16) | ((('i'
)) << 8) | ((239)))
, (caddr_t)&channel);
2459
2460 memset(&bssid, 0, sizeof(bssid));
2461 strlcpy(bssid.i_name, ifname, sizeof(bssid.i_name));
2462 ibssid = ioctl(sock, SIOCG80211BSSID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_bssid) & 0x1fff) << 16) | ((('i')
) << 8) | ((241)))
, &bssid);
2463
2464 memset(&wpa, 0, sizeof(wpa));
2465 strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name));
2466 iwpa = ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_wpaparams) & 0x1fff) << 16) | (((
'i')) << 8) | ((248)))
, &wpa);
2467
2468 /* check if any ieee80211 option is active */
2469 if (inwid == 0 || ijoin == 0 || inwkey == 0 || ipsk == 0 ||
2470 ipwr == 0 || ichan == 0 || ibssid == 0 || iwpa == 0)
2471 fputs("\tieee80211:", stdout(&__sF[1]));
2472 else
2473 return;
2474
2475 if (inwid == 0) {
2476 /* nwid.i_nwid is not NUL terminated. */
2477 len = nwid.i_len;
2478 if (len > IEEE80211_NWID_LEN32)
2479 len = IEEE80211_NWID_LEN32;
2480 if (ijoin == 0 && join.i_flags & IEEE80211_JOIN_FOUND0x02)
2481 fputs(" join ", stdout(&__sF[1]));
2482 else
2483 fputs(" nwid ", stdout(&__sF[1]));
2484 print_string(nwid.i_nwid, len);
2485 }
2486
2487 if (ichan == 0 && channel.i_channel != 0 &&
2488 channel.i_channel != IEEE80211_CHAN_ANY0xffff)
2489 printf(" chan %u", channel.i_channel);
2490
2491 memset(&zero_bssid, 0, sizeof(zero_bssid));
2492 if (ibssid == 0 &&
2493 memcmp(bssid.i_bssid, zero_bssid, IEEE80211_ADDR_LEN6) != 0) {
2494 memcpy(&ea.ether_addr_octet, bssid.i_bssid,
2495 sizeof(ea.ether_addr_octet));
2496 printf(" bssid %s", ether_ntoa(&ea));
2497
2498 bzero(&nr, sizeof(nr));
2499 bcopy(bssid.i_bssid, &nr.nr_macaddr, sizeof(nr.nr_macaddr));
2500 strlcpy(nr.nr_ifname, ifname, sizeof(nr.nr_ifname));
2501 if (ioctl(sock, SIOCG80211NODE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_nodereq) & 0x1fff) << 16) | ((('i'
)) << 8) | ((211)))
, &nr) == 0) {
2502 if (nr.nr_max_rssi)
2503 printf(" %u%%", IEEE80211_NODEREQ_RSSI(&nr)((u_int)(((float)(&nr)->nr_rssi / (&nr)->nr_max_rssi
) * 100))
);
2504 else
2505 printf(" %ddBm", nr.nr_rssi);
2506 assocfail = nr.nr_assoc_fail;
2507 }
2508 }
2509
2510 if (inwkey == 0 && nwkey.i_wepon > IEEE80211_NWKEY_OPEN0)
2511 fputs(" nwkey", stdout(&__sF[1]));
2512
2513 if (ipsk == 0 && psk.i_enabled)
2514 fputs(" wpakey", stdout(&__sF[1]));
2515 if (iwpa == 0 && wpa.i_enabled) {
2516 const char *sep;
2517
2518 fputs(" wpaprotos ", stdout(&__sF[1])); sep = "";
2519 if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA10x01) {
2520 fputs("wpa1", stdout(&__sF[1]));
2521 sep = ",";
2522 }
2523 if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA20x02)
2524 printf("%swpa2", sep);
2525
2526 fputs(" wpaakms ", stdout(&__sF[1])); sep = "";
2527 if (wpa.i_akms & IEEE80211_WPA_AKM_PSK0x01) {
2528 fputs("psk", stdout(&__sF[1]));
2529 sep = ",";
2530 }
2531 if (wpa.i_akms & IEEE80211_WPA_AKM_8021X0x02)
2532 printf("%s802.1x", sep);
2533
2534 fputs(" wpaciphers ", stdout(&__sF[1]));
2535 print_cipherset(wpa.i_ciphers);
2536
2537 fputs(" wpagroupcipher ", stdout(&__sF[1]));
2538 print_cipherset(wpa.i_groupcipher);
2539 }
2540
2541 if (ipwr == 0 && power.i_enabled)
2542 printf(" powersave on (%dms sleep)", power.i_maxsleep);
2543
2544 if (ioctl(sock, SIOCG80211FLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((216)))
, (caddr_t)&ifr) == 0 &&
2545 ifr.ifr_flagsifr_ifru.ifru_flags) {
2546 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
2547 printb_status(ifr.ifr_flagsifr_ifru.ifru_flags, IEEE80211_F_USERBITS"\20\01HIDENWID\02NOBRIDGE\03STAYAUTH\04NOMIMO");
2548 }
2549
2550 if (assocfail) {
2551 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
2552 print_assoc_failures(assocfail);
2553 }
2554 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
2555 if (show_join)
2556 join_status();
2557 if (shownet80211chans)
2558 ieee80211_listchans();
2559 else if (shownet80211nodes)
2560 ieee80211_listnodes();
2561}
2562
2563void
2564showjoin(const char *cmd, int val)
2565{
2566 show_join = 1;
2567 return;
2568}
2569
2570void
2571join_status(void)
2572{
2573 struct ieee80211_joinreq_all ja;
2574 struct ieee80211_join *jn = NULL((void *)0);
2575 struct ieee80211_wpaparams *wpa;
2576 int jsz = 100;
2577 int ojsz;
2578 int i;
2579 int r;
2580 int maxlen, len;
2581
2582 bzero(&ja, sizeof(ja));
2583 jn = recallocarray(NULL((void *)0), 0, jsz, sizeof(*jn));
2584 if (jn == NULL((void *)0))
2585 err(1, "recallocarray");
2586 ojsz = jsz;
2587 while (1) {
2588 ja.ja_node = jn;
2589 ja.ja_size = jsz * sizeof(*jn);
2590 strlcpy(ja.ja_ifname, ifname, sizeof(ja.ja_ifname));
2591
2592 if ((r = ioctl(sock, SIOCG80211JOINALL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_joinreq_all) & 0x1fff) << 16) | (
(('i')) << 8) | ((218)))
, &ja)) != 0) {
2593 if (errno(*__errno()) == E2BIG7) {
2594 jsz += 100;
2595 jn = recallocarray(jn, ojsz, jsz, sizeof(*jn));
2596 if (jn == NULL((void *)0))
2597 err(1, "recallocarray");
2598 ojsz = jsz;
2599 continue;
2600 } else if (errno(*__errno()) != ENOENT2)
2601 warn("%s: SIOCG80211JOINALL", ja.ja_ifname);
2602 return;
2603 }
2604 break;
2605 }
2606
2607 if (!ja.ja_nodes)
2608 return;
2609
2610 maxlen = 0;
2611 for (i = 0; i < ja.ja_nodes; i++) {
2612 len = len_string(jn[i].i_nwid, jn[i].i_len);
2613 if (len > maxlen)
2614 maxlen = len;
2615 }
2616
2617 for (i = 0; i < ja.ja_nodes; i++) {
2618 printf("\t ");
2619 if (jn[i].i_len > IEEE80211_NWID_LEN32)
2620 jn[i].i_len = IEEE80211_NWID_LEN32;
2621 len = print_string(jn[i].i_nwid, jn[i].i_len);
2622 printf("%-*s", maxlen - len, "");
2623 if (jn[i].i_flags) {
2624 const char *sep;
2625 printf(" ");
2626
2627 if (jn[i].i_flags & IEEE80211_JOIN_NWKEY0x08)
2628 printf("nwkey");
2629
2630 if (jn[i].i_flags & IEEE80211_JOIN_WPA0x10) {
2631 wpa = &jn[i].i_wpaparams;
2632
2633 printf("wpaprotos "); sep = "";
2634 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA10x01) {
2635 printf("wpa1");
2636 sep = ",";
2637 }
2638 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA20x02)
2639 printf("%swpa2", sep);
2640
2641 printf(" wpaakms "); sep = "";
2642 if (wpa->i_akms & IEEE80211_WPA_AKM_PSK0x01) {
2643 printf("psk");
2644 sep = ",";
2645 }
2646 if (wpa->i_akms & IEEE80211_WPA_AKM_8021X0x02)
2647 printf("%s802.1x", sep);
2648
2649 printf(" wpaciphers ");
2650 print_cipherset(wpa->i_ciphers);
2651
2652 printf(" wpagroupcipher ");
2653 print_cipherset(wpa->i_groupcipher);
2654 }
2655 }
2656 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
2657 }
2658}
2659
2660void
2661ieee80211_listchans(void)
2662{
2663 static struct ieee80211_chaninfo chans[256];
2664 struct ieee80211_chanreq_all ca;
2665 int i;
2666
2667 bzero(&ca, sizeof(ca));
2668 bzero(chans, sizeof(chans));
2669 ca.i_chans = chans;
2670 strlcpy(ca.i_name, ifname, sizeof(ca.i_name));
2671
2672 if (ioctl(sock, SIOCG80211ALLCHANS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_chanreq_all) & 0x1fff) << 16) | (
(('i')) << 8) | ((215)))
, &ca) != 0) {
2673 warn("%s: SIOCG80211ALLCHANS", ca.i_name);
2674 return;
2675 }
2676 printf("\t\t%4s %-8s %s\n", "chan", "freq", "properties");
2677 for (i = 1; i < nitems(chans)(sizeof((chans)) / sizeof((chans)[0])); i++) {
2678 if (chans[i].ic_freq == 0)
2679 continue;
2680 printf("\t\t%4d %4d MHz ", i, chans[i].ic_freq);
2681 if (chans[i].ic_flags & IEEE80211_CHANINFO_PASSIVE0x0200)
2682 printf("passive scan");
2683 else
2684 putchar('-')(!__isthreaded ? __sputc('-', (&__sF[1])) : (putc)('-', (
&__sF[1])))
;
2685 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
2686 }
2687}
2688
2689/*
2690 * Returns an integer less than, equal to, or greater than zero if nr1's
2691 * RSSI is respectively greater than, equal to, or less than nr2's RSSI.
2692 */
2693static int
2694rssicmp(const void *nr1, const void *nr2)
2695{
2696 const struct ieee80211_nodereq *x = nr1, *y = nr2;
2697 return y->nr_rssi < x->nr_rssi ? -1 : y->nr_rssi > x->nr_rssi;
2698}
2699
2700void
2701ieee80211_listnodes(void)
2702{
2703 struct ieee80211_nodereq_all na;
2704 struct ieee80211_nodereq nr[512];
2705 struct ifreq ifr;
2706 int i;
2707
2708 if ((flags & IFF_UP0x1) == 0) {
2709 printf("\t\tcannot scan, interface is down\n");
2710 return;
2711 }
2712
2713 bzero(&ifr, sizeof(ifr));
2714 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2715
2716 if (ioctl(sock, SIOCS80211SCAN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((210)))
, (caddr_t)&ifr) != 0) {
2717 if (errno(*__errno()) == EPERM1)
2718 printf("\t\tno permission to scan\n");
2719 return;
2720 }
2721
2722 bzero(&na, sizeof(na));
2723 bzero(&nr, sizeof(nr));
2724 na.na_node = nr;
2725 na.na_size = sizeof(nr);
2726 strlcpy(na.na_ifname, ifname, sizeof(na.na_ifname));
2727
2728 if (ioctl(sock, SIOCG80211ALLNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_nodereq_all) & 0x1fff) << 16) | (
(('i')) << 8) | ((214)))
, &na) != 0) {
2729 warn("%s: SIOCG80211ALLNODES", na.na_ifname);
2730 return;
2731 }
2732
2733 if (!na.na_nodes)
2734 printf("\t\tnone\n");
2735 else
2736 qsort(nr, na.na_nodes, sizeof(*nr), rssicmp);
2737
2738 for (i = 0; i < na.na_nodes; i++) {
2739 printf("\t\t");
2740 ieee80211_printnode(&nr[i]);
2741 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
2742 }
2743}
2744
2745void
2746ieee80211_printnode(struct ieee80211_nodereq *nr)
2747{
2748 int len, i;
2749
2750 if (nr->nr_flags & IEEE80211_NODEREQ_AP0x01 ||
2751 nr->nr_capinfo & IEEE80211_CAPINFO_IBSS0x0002) {
2752 len = nr->nr_nwid_len;
2753 if (len > IEEE80211_NWID_LEN32)
2754 len = IEEE80211_NWID_LEN32;
2755 printf("nwid ");
2756 print_string(nr->nr_nwid, len);
2757 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
2758
2759 printf("chan %u ", nr->nr_channel);
2760
2761 printf("bssid %s ",
2762 ether_ntoa((struct ether_addr*)nr->nr_bssid));
2763 }
2764
2765 if ((nr->nr_flags & IEEE80211_NODEREQ_AP0x01) == 0)
2766 printf("lladdr %s ",
2767 ether_ntoa((struct ether_addr*)nr->nr_macaddr));
2768
2769 if (nr->nr_max_rssi)
2770 printf("%u%% ", IEEE80211_NODEREQ_RSSI(nr)((u_int)(((float)(nr)->nr_rssi / (nr)->nr_max_rssi) * 100
))
);
2771 else
2772 printf("%ddBm ", nr->nr_rssi);
2773
2774 if (nr->nr_pwrsave)
2775 printf("powersave ");
2776 /*
2777 * Print our current Tx rate for associated nodes.
2778 * Print the fastest supported rate for APs.
2779 */
2780 if ((nr->nr_flags & (IEEE80211_NODEREQ_AP0x01)) == 0) {
2781 if (nr->nr_flags & IEEE80211_NODEREQ_VHT0x10) {
2782 printf("VHT-MCS%d/%dSS", nr->nr_txmcs, nr->nr_vht_ss);
2783 } else if (nr->nr_flags & IEEE80211_NODEREQ_HT0x08) {
2784 printf("HT-MCS%d ", nr->nr_txmcs);
2785 } else if (nr->nr_nrates) {
2786 printf("%uM ",
2787 (nr->nr_rates[nr->nr_txrate] & IEEE80211_RATE_VAL0x7f)
2788 / 2);
2789 }
2790 } else if (nr->nr_max_rxrate) {
2791 printf("%uM HT ", nr->nr_max_rxrate);
2792 } else if (nr->nr_rxmcs[0] != 0) {
2793 for (i = IEEE80211_HT_NUM_MCS77 - 1; i >= 0; i--) {
2794 if (nr->nr_rxmcs[i / 8] & (1 << (i / 10)))
2795 break;
2796 }
2797 printf("HT-MCS%d ", i);
2798 } else if (nr->nr_nrates) {
2799 printf("%uM ",
2800 (nr->nr_rates[nr->nr_nrates - 1] & IEEE80211_RATE_VAL0x7f) / 2);
2801 }
2802 /* ESS is the default, skip it */
2803 nr->nr_capinfo &= ~IEEE80211_CAPINFO_ESS0x0001;
2804 if (nr->nr_capinfo) {
2805 printb_status(nr->nr_capinfo, IEEE80211_CAPINFO_BITS"\10\01ESS\02IBSS\03CF_POLLABLE\04CF_POLLREQ" "\05PRIVACY\06SHORT_PREAMBLE\07PBCC\10CHNL_AGILITY"
"\11SPECTRUM_MGMT\12QOS\13SHORT_SLOTTIME\14APSD" "\15RADIO_MEASUREMENT\16DSSSOFDM\17DELAYED_B_ACK\20IMMEDIATE_B_ACK"
);
2806 if (nr->nr_capinfo & IEEE80211_CAPINFO_PRIVACY0x0010) {
2807 if (nr->nr_rsnprotos) {
2808 if (nr->nr_rsnprotos & IEEE80211_WPA_PROTO_WPA20x02)
2809 fputs(",wpa2", stdout(&__sF[1]));
2810 if (nr->nr_rsnprotos & IEEE80211_WPA_PROTO_WPA10x01)
2811 fputs(",wpa1", stdout(&__sF[1]));
2812 } else
2813 fputs(",wep", stdout(&__sF[1]));
2814
2815 if (nr->nr_rsnakms & IEEE80211_WPA_AKM_8021X0x02 ||
2816 nr->nr_rsnakms & IEEE80211_WPA_AKM_SHA256_8021X0x08)
2817 fputs(",802.1x", stdout(&__sF[1]));
2818 }
2819 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
2820 }
2821
2822 if ((nr->nr_flags & IEEE80211_NODEREQ_AP0x01) == 0)
2823 printb_status(IEEE80211_NODEREQ_STATE(nr->nr_state)(1 << nr->nr_state),
2824 IEEE80211_NODEREQ_STATE_BITS"\20\01CACHE\02BSS\03AUTH\04ASSOC\05COLLECT");
2825 else if (nr->nr_assoc_fail)
2826 print_assoc_failures(nr->nr_assoc_fail);
2827}
2828
2829void
2830init_current_media(void)
2831{
2832 struct ifmediareq ifmr;
2833
2834 /*
2835 * If we have not yet done so, grab the currently-selected
2836 * media.
2837 */
2838 if ((actions & (A_MEDIA0x0001|A_MEDIAOPT(0x0002|0x0004)|A_MEDIAMODE0x0010)) == 0) {
2839 (void) memset(&ifmr, 0, sizeof(ifmr));
2840 (void) strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
2841
2842 if (ioctl(sock, SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
, (caddr_t)&ifmr) == -1) {
2843 /*
2844 * If we get E2BIG, the kernel is telling us
2845 * that there are more, so we can ignore it.
2846 */
2847 if (errno(*__errno()) != E2BIG7)
2848 err(1, "%s: SIOCGIFMEDIA", ifmr.ifm_name);
2849 }
2850
2851 media_current = ifmr.ifm_current;
2852 }
2853
2854 /* Sanity. */
2855 if (IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL) == 0)
2856 errx(1, "%s: no link type?", ifname);
2857}
2858
2859void
2860process_media_commands(void)
2861{
2862
2863 if ((actions & (A_MEDIA0x0001|A_MEDIAOPT(0x0002|0x0004)|A_MEDIAMODE0x0010)) == 0) {
2864 /* Nothing to do. */
2865 return;
2866 }
2867
2868 /*
2869 * Media already set up, and commands sanity-checked. Set/clear
2870 * any options, and we're ready to go.
2871 */
2872 media_current |= mediaopt_set;
2873 media_current &= ~mediaopt_clear;
2874
2875 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2876 ifr.ifr_mediaifr_ifru.ifru_media = media_current;
2877
2878 if (ioctl(sock, SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
, (caddr_t)&ifr) == -1)
2879 err(1, "%s: SIOCSIFMEDIA", ifr.ifr_name);
2880}
2881
2882void
2883setmedia(const char *val, int d)
2884{
2885 uint64_t type, subtype, inst;
2886
2887 if (val == NULL((void *)0)) {
2888 if (showmediaflag)
2889 usage();
2890 showmediaflag = 1;
2891 return;
2892 }
2893
2894 init_current_media();
2895
2896 /* Only one media command may be given. */
2897 if (actions & A_MEDIA0x0001)
2898 errx(1, "only one `media' command may be issued");
2899
2900 /* Must not come after mode commands */
2901 if (actions & A_MEDIAMODE0x0010)
2902 errx(1, "may not issue `media' after `mode' commands");
2903
2904 /* Must not come after mediaopt commands */
2905 if (actions & A_MEDIAOPT(0x0002|0x0004))
2906 errx(1, "may not issue `media' after `mediaopt' commands");
2907
2908 /*
2909 * No need to check if `instance' has been issued; setmediainst()
2910 * craps out if `media' has not been specified.
2911 */
2912
2913 type = IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL);
2914 inst = IFM_INST(media_current)(((media_current) & 0xff00000000000000ULL) >> 56);
2915
2916 /* Look up the subtype. */
2917 subtype = get_media_subtype(type, val);
2918
2919 /* Build the new current media word. */
2920 media_current = IFM_MAKEWORD(type, subtype, 0, inst)((type) | (subtype) | (0) | ((uint64_t)(inst) << 56));
2921
2922 /* Media will be set after other processing is complete. */
2923}
2924
2925void
2926setmediamode(const char *val, int d)
2927{
2928 uint64_t type, subtype, options, inst, mode;
2929
2930 init_current_media();
2931
2932 /* Can only issue `mode' once. */
2933 if (actions & A_MEDIAMODE0x0010)
2934 errx(1, "only one `mode' command may be issued");
2935
2936 type = IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL);
2937 subtype = IFM_SUBTYPE(media_current)((media_current) & 0x00000000000000ffULL);
2938 options = IFM_OPTIONS(media_current)((media_current) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL
))
;
2939 inst = IFM_INST(media_current)(((media_current) & 0xff00000000000000ULL) >> 56);
2940
2941 if ((mode = get_media_mode(type, val)) == -1)
2942 errx(1, "invalid media mode: %s", val);
2943 media_current = IFM_MAKEWORD(type, subtype, options, inst)((type) | (subtype) | (options) | ((uint64_t)(inst) << 56
))
| mode;
2944 /* Media will be set after other processing is complete. */
2945}
2946
2947void
2948unsetmediamode(const char *val, int d)
2949{
2950 uint64_t type, subtype, options, inst;
2951
2952 init_current_media();
2953
2954 /* Can only issue `mode' once. */
2955 if (actions & A_MEDIAMODE0x0010)
2956 errx(1, "only one `mode' command may be issued");
2957
2958 type = IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL);
2959 subtype = IFM_SUBTYPE(media_current)((media_current) & 0x00000000000000ffULL);
2960 options = IFM_OPTIONS(media_current)((media_current) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL
))
;
2961 inst = IFM_INST(media_current)(((media_current) & 0xff00000000000000ULL) >> 56);
2962
2963 media_current = IFM_MAKEWORD(type, subtype, options, inst)((type) | (subtype) | (options) | ((uint64_t)(inst) << 56
))
|
2964 (IFM_AUTO0ULL << IFM_MSHIFT32);
2965 /* Media will be set after other processing is complete. */
2966}
2967
2968void
2969setmediaopt(const char *val, int d)
2970{
2971
2972 init_current_media();
2973
2974 /* Can only issue `mediaopt' once. */
2975 if (actions & A_MEDIAOPTSET0x0002)
2976 errx(1, "only one `mediaopt' command may be issued");
2977
2978 /* Can't issue `mediaopt' if `instance' has already been issued. */
2979 if (actions & A_MEDIAINST0x0008)
2980 errx(1, "may not issue `mediaopt' after `instance'");
2981
2982 mediaopt_set = get_media_options(IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL), val);
2983
2984 /* Media will be set after other processing is complete. */
2985}
2986
2987void
2988unsetmediaopt(const char *val, int d)
2989{
2990
2991 init_current_media();
2992
2993 /* Can only issue `-mediaopt' once. */
2994 if (actions & A_MEDIAOPTCLR0x0004)
2995 errx(1, "only one `-mediaopt' command may be issued");
2996
2997 /* May not issue `media' and `-mediaopt'. */
2998 if (actions & A_MEDIA0x0001)
2999 errx(1, "may not issue both `media' and `-mediaopt'");
3000
3001 /*
3002 * No need to check for A_MEDIAINST, since the test for A_MEDIA
3003 * implicitly checks for A_MEDIAINST.
3004 */
3005
3006 mediaopt_clear = get_media_options(IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL), val);
3007
3008 /* Media will be set after other processing is complete. */
3009}
3010
3011void
3012setmediainst(const char *val, int d)
3013{
3014 uint64_t type, subtype, options, inst;
3015 const char *errmsg = NULL((void *)0);
3016
3017 init_current_media();
3018
3019 /* Can only issue `instance' once. */
3020 if (actions & A_MEDIAINST0x0008)
3021 errx(1, "only one `instance' command may be issued");
3022
3023 /* Must have already specified `media' */
3024 if ((actions & A_MEDIA0x0001) == 0)
3025 errx(1, "must specify `media' before `instance'");
3026
3027 type = IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL);
3028 subtype = IFM_SUBTYPE(media_current)((media_current) & 0x00000000000000ffULL);
3029 options = IFM_OPTIONS(media_current)((media_current) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL
))
;
3030
3031 inst = strtonum(val, 0, IFM_INST_MAX(((0xff00000000000000ULL) & 0xff00000000000000ULL) >>
56)
, &errmsg);
3032 if (errmsg)
3033 errx(1, "media instance %s: %s", val, errmsg);
3034
3035 media_current = IFM_MAKEWORD(type, subtype, options, inst)((type) | (subtype) | (options) | ((uint64_t)(inst) << 56
))
;
3036
3037 /* Media will be set after other processing is complete. */
3038}
3039
3040
3041const struct ifmedia_description ifm_type_descriptions[] =
3042 IFM_TYPE_DESCRIPTIONS{ { 0x0000000000000100ULL, "Ethernet" }, { 0x0000000000000100ULL
, "ether" }, { 0x0000000000000300ULL, "FDDI" }, { 0x0000000000000400ULL
, "IEEE802.11" }, { 0x0000000000000500ULL, "TDM" }, { 0x0000000000000600ULL
, "CARP" }, { 0, ((void *)0) }, }
;
3043
3044const struct ifmedia_description ifm_subtype_descriptions[] =
3045 IFM_SUBTYPE_DESCRIPTIONS{ { 0ULL, "autoselect" }, { 0ULL, "auto" }, { 1ULL, "manual" }
, { 2ULL, "none" }, { 0x0000000000000100ULL|3, "10baseT" }, {
0x0000000000000100ULL|3, "10baseT/UTP" }, { 0x0000000000000100ULL
|3, "UTP" }, { 0x0000000000000100ULL|3, "10UTP" }, { 0x0000000000000100ULL
|4, "10base2" }, { 0x0000000000000100ULL|4, "10base2/BNC" }, {
0x0000000000000100ULL|4, "BNC" }, { 0x0000000000000100ULL|4,
"10BNC" }, { 0x0000000000000100ULL|5, "10base5" }, { 0x0000000000000100ULL
|5, "10base5/AUI" }, { 0x0000000000000100ULL|5, "AUI" }, { 0x0000000000000100ULL
|5, "10AUI" }, { 0x0000000000000100ULL|6, "100baseTX" }, { 0x0000000000000100ULL
|6, "100TX" }, { 0x0000000000000100ULL|7, "100baseFX" }, { 0x0000000000000100ULL
|7, "100FX" }, { 0x0000000000000100ULL|8, "100baseT4" }, { 0x0000000000000100ULL
|8, "100T4" }, { 0x0000000000000100ULL|9, "100baseVG" }, { 0x0000000000000100ULL
|9, "100VG" }, { 0x0000000000000100ULL|10, "100baseT2" }, { 0x0000000000000100ULL
|10, "100T2" }, { 0x0000000000000100ULL|11, "1000baseSX" }, {
0x0000000000000100ULL|11, "1000SX" }, { 0x0000000000000100ULL
|12, "10baseSTP" }, { 0x0000000000000100ULL|12, "STP" }, { 0x0000000000000100ULL
|12, "10STP" }, { 0x0000000000000100ULL|13, "10baseFL" }, { 0x0000000000000100ULL
|13, "FL" }, { 0x0000000000000100ULL|13, "10FL" }, { 0x0000000000000100ULL
|14, "1000baseLX" }, { 0x0000000000000100ULL|14, "1000LX" }, {
0x0000000000000100ULL|15, "1000baseCX" }, { 0x0000000000000100ULL
|15, "1000CX" }, { 0x0000000000000100ULL|16, "1000baseT" }, {
0x0000000000000100ULL|16, "1000T" }, { 0x0000000000000100ULL
|16, "1000baseTX" }, { 0x0000000000000100ULL|16, "1000TX" }, {
0x0000000000000100ULL|17, "HomePNA1" }, { 0x0000000000000100ULL
|17, "HPNA1" }, { 0x0000000000000100ULL|18, "10GbaseLR" }, { 0x0000000000000100ULL
|18, "10GLR" }, { 0x0000000000000100ULL|18, "10GBASE-LR" }, {
0x0000000000000100ULL|19, "10GbaseSR" }, { 0x0000000000000100ULL
|19, "10GSR" }, { 0x0000000000000100ULL|19, "10GBASE-SR" }, {
0x0000000000000100ULL|20, "10GbaseCX4" }, { 0x0000000000000100ULL
|20, "10GCX4" }, { 0x0000000000000100ULL|20, "10GBASE-CX4" },
{ 0x0000000000000100ULL|21, "2500baseSX" }, { 0x0000000000000100ULL
|21, "2500SX" }, { 0x0000000000000100ULL|22, "10GbaseT" }, { 0x0000000000000100ULL
|22, "10GT" }, { 0x0000000000000100ULL|22, "10GBASE-T" }, { 0x0000000000000100ULL
|23, "10GSFP+Cu" }, { 0x0000000000000100ULL|23, "10GCu" }, { 0x0000000000000100ULL
|24, "10GbaseLRM" }, { 0x0000000000000100ULL|24, "10GBASE-LRM"
}, { 0x0000000000000100ULL|25, "40GbaseCR4" }, { 0x0000000000000100ULL
|25, "40GBASE-CR4" }, { 0x0000000000000100ULL|26, "40GbaseSR4"
}, { 0x0000000000000100ULL|26, "40GBASE-SR4" }, { 0x0000000000000100ULL
|27, "40GbaseLR4" }, { 0x0000000000000100ULL|27, "40GBASE-LR4"
}, { 0x0000000000000100ULL|28, "1000base-KX" }, { 0x0000000000000100ULL
|28, "1000BASE-KX" }, { 0x0000000000000100ULL|29, "10GbaseKX4"
}, { 0x0000000000000100ULL|29, "10GBASE-KX4" }, { 0x0000000000000100ULL
|30, "10GbaseKR" }, { 0x0000000000000100ULL|30, "10GBASE-KR" }
, { 0x0000000000000100ULL|31, "10GbaseCR1" }, { 0x0000000000000100ULL
|31, "10GBASE-CR1" }, { 0x0000000000000100ULL|54, "10G-AOC" }
, { 0x0000000000000100ULL|32, "20GbaseKR2" }, { 0x0000000000000100ULL
|32, "20GBASE-KR2" }, { 0x0000000000000100ULL|33, "2500baseKX"
}, { 0x0000000000000100ULL|33, "2500BASE-KX" }, { 0x0000000000000100ULL
|34, "2500baseT" }, { 0x0000000000000100ULL|34, "2500BASE-T" }
, { 0x0000000000000100ULL|35, "5000baseT" }, { 0x0000000000000100ULL
|35, "5000BASE-T" }, { 0x0000000000000100ULL|36, "1000base-SGMII"
}, { 0x0000000000000100ULL|36, "1000BASE-SGMII" }, { 0x0000000000000100ULL
|37, "10GbaseSFI" }, { 0x0000000000000100ULL|37, "10GBASE-SFI"
}, { 0x0000000000000100ULL|38, "40GbaseXLPPI" }, { 0x0000000000000100ULL
|38, "40GBASE-XLPPI" }, { 0x0000000000000100ULL|39, "1000baseCX-SGMII"
}, { 0x0000000000000100ULL|39, "1000BASE-CX-SGMII" }, { 0x0000000000000100ULL
|40, "40GbaseKR4" }, { 0x0000000000000100ULL|40, "40GBASE-KR4"
}, { 0x0000000000000100ULL|56, "40G-AOC" }, { 0x0000000000000100ULL
|41, "10GbaseER" }, { 0x0000000000000100ULL|41, "10GBASE-ER" }
, { 0x0000000000000100ULL|42, "100GbaseCR4" }, { 0x0000000000000100ULL
|42, "100GBASE-CR4" }, { 0x0000000000000100ULL|43, "100GbaseSR4"
}, { 0x0000000000000100ULL|43, "100GBASE-SR4" }, { 0x0000000000000100ULL
|44, "100GbaseKR4" }, { 0x0000000000000100ULL|44, "100GBASE-KR4"
}, { 0x0000000000000100ULL|45, "100GbaseLR4" }, { 0x0000000000000100ULL
|45, "100GBASE-LR4" }, { 0x0000000000000100ULL|57, "100G-AOC"
}, { 0x0000000000000100ULL|46, "56GbaseR4" }, { 0x0000000000000100ULL
|46, "56GBASE-R4" }, { 0x0000000000000100ULL|47, "25GbaseCR" }
, { 0x0000000000000100ULL|47, "25GBASE-CR" }, { 0x0000000000000100ULL
|48, "25GbaseKR" }, { 0x0000000000000100ULL|48, "25GBASE-KR" }
, { 0x0000000000000100ULL|49, "25GbaseSR" }, { 0x0000000000000100ULL
|49, "25GBASE-SR" }, { 0x0000000000000100ULL|52, "25GbaseLR" }
, { 0x0000000000000100ULL|52, "25GBASE-LR" }, { 0x0000000000000100ULL
|53, "25GbaseER" }, { 0x0000000000000100ULL|53, "25GBASE-ER" }
, { 0x0000000000000100ULL|55, "25G-AOC" }, { 0x0000000000000100ULL
|50, "50GbaseCR2" }, { 0x0000000000000100ULL|50, "50GBASE-CR2"
}, { 0x0000000000000100ULL|51, "50GbaseKR2" }, { 0x0000000000000100ULL
|51, "50GBASE-KR2" }, { 0x0000000000000300ULL|3, "Single-mode"
}, { 0x0000000000000300ULL|3, "SMF" }, { 0x0000000000000300ULL
|4, "Multi-mode" }, { 0x0000000000000300ULL|4, "MMF" }, { 0x0000000000000300ULL
|5, "UTP" }, { 0x0000000000000300ULL|5, "CDDI" }, { 0x0000000000000400ULL
|3, "FH1" }, { 0x0000000000000400ULL|4, "FH2" }, { 0x0000000000000400ULL
|5, "DS2" }, { 0x0000000000000400ULL|6, "DS5" }, { 0x0000000000000400ULL
|7, "DS11" }, { 0x0000000000000400ULL|8, "DS1" }, { 0x0000000000000400ULL
|9, "DS22" }, { 0x0000000000000400ULL|10, "OFDM6" }, { 0x0000000000000400ULL
|11, "OFDM9" }, { 0x0000000000000400ULL|12, "OFDM12" }, { 0x0000000000000400ULL
|13, "OFDM18" }, { 0x0000000000000400ULL|14, "OFDM24" }, { 0x0000000000000400ULL
|15, "OFDM36" }, { 0x0000000000000400ULL|16, "OFDM48" }, { 0x0000000000000400ULL
|17, "OFDM54" }, { 0x0000000000000400ULL|18, "OFDM72" }, { 0x0000000000000400ULL
|19, "HT-MCS0" }, { 0x0000000000000400ULL|20, "HT-MCS1" }, { 0x0000000000000400ULL
|21, "HT-MCS2" }, { 0x0000000000000400ULL|22, "HT-MCS3" }, { 0x0000000000000400ULL
|23, "HT-MCS4" }, { 0x0000000000000400ULL|24, "HT-MCS5" }, { 0x0000000000000400ULL
|25, "HT-MCS6" }, { 0x0000000000000400ULL|26, "HT-MCS7" }, { 0x0000000000000400ULL
|27, "HT-MCS8" }, { 0x0000000000000400ULL|28, "HT-MCS9" }, { 0x0000000000000400ULL
|29, "HT-MCS10" }, { 0x0000000000000400ULL|30, "HT-MCS11" }, {
0x0000000000000400ULL|31, "HT-MCS12" }, { 0x0000000000000400ULL
|32, "HT-MCS13" }, { 0x0000000000000400ULL|33, "HT-MCS14" }, {
0x0000000000000400ULL|34, "HT-MCS15" }, { 0x0000000000000400ULL
|35, "HT-MCS16" }, { 0x0000000000000400ULL|36, "HT-MCS17" }, {
0x0000000000000400ULL|37, "HT-MCS18" }, { 0x0000000000000400ULL
|38, "HT-MCS19" }, { 0x0000000000000400ULL|39, "HT-MCS20" }, {
0x0000000000000400ULL|40, "HT-MCS21" }, { 0x0000000000000400ULL
|41, "HT-MCS22" }, { 0x0000000000000400ULL|42, "HT-MCS23" }, {
0x0000000000000400ULL|43, "HT-MCS24" }, { 0x0000000000000400ULL
|44, "HT-MCS25" }, { 0x0000000000000400ULL|45, "HT-MCS26" }, {
0x0000000000000400ULL|46, "HT-MCS27" }, { 0x0000000000000400ULL
|47, "HT-MCS28" }, { 0x0000000000000400ULL|48, "HT-MCS29" }, {
0x0000000000000400ULL|49, "HT-MCS30" }, { 0x0000000000000400ULL
|50, "HT-MCS31" }, { 0x0000000000000400ULL|51, "HT-MCS32" }, {
0x0000000000000400ULL|52, "HT-MCS33" }, { 0x0000000000000400ULL
|53, "HT-MCS34" }, { 0x0000000000000400ULL|54, "HT-MCS35" }, {
0x0000000000000400ULL|55, "HT-MCS36" }, { 0x0000000000000400ULL
|56, "HT-MCS37" }, { 0x0000000000000400ULL|57, "HT-MCS38" }, {
0x0000000000000400ULL|58, "HT-MCS39" }, { 0x0000000000000400ULL
|59, "HT-MCS40" }, { 0x0000000000000400ULL|60, "HT-MCS41" }, {
0x0000000000000400ULL|61, "HT-MCS42" }, { 0x0000000000000400ULL
|62, "HT-MCS43" }, { 0x0000000000000400ULL|63, "HT-MCS44" }, {
0x0000000000000400ULL|64, "HT-MCS45" }, { 0x0000000000000400ULL
|65, "HT-MCS46" }, { 0x0000000000000400ULL|66, "HT-MCS47" }, {
0x0000000000000400ULL|67, "HT-MCS48" }, { 0x0000000000000400ULL
|68, "HT-MCS49" }, { 0x0000000000000400ULL|69, "HT-MCS50" }, {
0x0000000000000400ULL|70, "HT-MCS51" }, { 0x0000000000000400ULL
|71, "HT-MCS52" }, { 0x0000000000000400ULL|72, "HT-MCS53" }, {
0x0000000000000400ULL|73, "HT-MCS54" }, { 0x0000000000000400ULL
|74, "HT-MCS55" }, { 0x0000000000000400ULL|75, "HT-MCS56" }, {
0x0000000000000400ULL|76, "HT-MCS57" }, { 0x0000000000000400ULL
|77, "HT-MCS58" }, { 0x0000000000000400ULL|78, "HT-MCS59" }, {
0x0000000000000400ULL|79, "HT-MCS60" }, { 0x0000000000000400ULL
|80, "HT-MCS61" }, { 0x0000000000000400ULL|81, "HT-MCS62" }, {
0x0000000000000400ULL|82, "HT-MCS63" }, { 0x0000000000000400ULL
|83, "HT-MCS64" }, { 0x0000000000000400ULL|84, "HT-MCS65" }, {
0x0000000000000400ULL|85, "HT-MCS66" }, { 0x0000000000000400ULL
|86, "HT-MCS67" }, { 0x0000000000000400ULL|87, "HT-MCS68" }, {
0x0000000000000400ULL|88, "HT-MCS69" }, { 0x0000000000000400ULL
|89, "HT-MCS70" }, { 0x0000000000000400ULL|90, "HT-MCS71" }, {
0x0000000000000400ULL|91, "HT-MCS72" }, { 0x0000000000000400ULL
|92, "HT-MCS73" }, { 0x0000000000000400ULL|93, "HT-MCS74" }, {
0x0000000000000400ULL|94, "HT-MCS75" }, { 0x0000000000000400ULL
|95, "HT-MCS76" }, { 0x0000000000000400ULL|96, "VHT-MCS0" }, {
0x0000000000000400ULL|97, "VHT-MCS1" }, { 0x0000000000000400ULL
|98, "VHT-MCS2" }, { 0x0000000000000400ULL|99, "VHT-MCS3" }, {
0x0000000000000400ULL|100, "VHT-MCS4" }, { 0x0000000000000400ULL
|101, "VHT-MCS5" }, { 0x0000000000000400ULL|102, "VHT-MCS6" }
, { 0x0000000000000400ULL|103, "VHT-MCS7" }, { 0x0000000000000400ULL
|104, "VHT-MCS8" }, { 0x0000000000000400ULL|105, "VHT-MCS9" }
, { 0x0000000000000500ULL|3, "t1" }, { 0x0000000000000500ULL|
4, "t1-ami" }, { 0x0000000000000500ULL|5, "e1" }, { 0x0000000000000500ULL
|6, "e1-g.704" }, { 0x0000000000000500ULL|7, "e1-ami" }, { 0x0000000000000500ULL
|8, "e1-ami-g.704" }, { 0x0000000000000500ULL|9, "t3" }, { 0x0000000000000500ULL
|10, "t3-m13" }, { 0x0000000000000500ULL|11, "e3" }, { 0x0000000000000500ULL
|12, "e3-g.751" }, { 0x0000000000000500ULL|13, "e3-g.832" }, {
0x0000000000000500ULL|14, "e1-g.704-crc4" }, { 0, ((void *)0
) }, }
;
3046
3047const struct ifmedia_description ifm_mode_descriptions[] =
3048 IFM_MODE_DESCRIPTIONS{ { 0ULL, "autoselect" }, { 0ULL, "auto" }, { 0x0000000000000400ULL
|0x0000000100000000ULL, "11a" }, { 0x0000000000000400ULL|0x0000000200000000ULL
, "11b" }, { 0x0000000000000400ULL|0x0000000300000000ULL, "11g"
}, { 0x0000000000000400ULL|0x0000000400000000ULL, "fh" }, { 0x0000000000000400ULL
|0x0000000800000000ULL, "11n" }, { 0x0000000000000400ULL|0x0000001000000000ULL
, "11ac" }, { 0x0000000000000500ULL|0x0000000100000000ULL, "master"
}, { 0, ((void *)0) }, }
;
3049
3050const struct ifmedia_description ifm_option_descriptions[] =
3051 IFM_OPTION_DESCRIPTIONS{ { 0x0000010000000000ULL, "full-duplex" }, { 0x0000010000000000ULL
, "fdx" }, { 0x0000020000000000ULL, "half-duplex" }, { 0x0000020000000000ULL
, "hdx" }, { 0x0000100000000000ULL, "flag0" }, { 0x0000200000000000ULL
, "flag1" }, { 0x0000400000000000ULL, "flag2" }, { 0x0000800000000000ULL
, "loopback" }, { 0x0000800000000000ULL, "hw-loopback"}, { 0x0000800000000000ULL
, "loop" }, { 0x0000000000000100ULL|0x0000000000010000ULL, "master"
}, { 0x0000000000000100ULL|0x0000000000020000ULL, "rxpause" }
, { 0x0000000000000100ULL|0x0000000000040000ULL, "txpause" },
{ 0x0000000000000300ULL|0x00000100, "dual-attach" }, { 0x0000000000000300ULL
|0x00000100, "das" }, { 0x0000000000000400ULL|0x0000000000010000ULL
, "adhoc" }, { 0x0000000000000400ULL|0x0000000000020000ULL, "hostap"
}, { 0x0000000000000400ULL|0x0000000000040000ULL, "ibss" }, {
0x0000000000000400ULL|0x0000000000080000ULL, "ibss-master" }
, { 0x0000000000000400ULL|0x0000000000100000ULL, "monitor" },
{ 0x0000000000000500ULL|0x0100, "hdlc-crc16" }, { 0x0000000000000500ULL
|0x0200, "ppp" }, { 0x0000000000000500ULL|0x0400, "framerelay-ansi"
}, { 0x0000000000000500ULL|0x0800, "framerelay-cisco" }, { 0x0000000000000500ULL
|0x0400, "framerelay-itu" }, { 0, ((void *)0) }, }
;
3052
3053const char *
3054get_media_type_string(uint64_t mword)
3055{
3056 const struct ifmedia_description *desc;
3057
3058 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL((void *)0);
3059 desc++) {
3060 if (IFM_TYPE(mword)((mword) & 0x000000000000ff00ULL) == desc->ifmt_word)
3061 return (desc->ifmt_string);
3062 }
3063 return ("<unknown type>");
3064}
3065
3066const char *
3067get_media_subtype_string(uint64_t mword)
3068{
3069 const struct ifmedia_description *desc;
3070
3071 for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL((void *)0);
3072 desc++) {
3073 if (IFM_TYPE_MATCH(desc->ifmt_word, mword)((((desc->ifmt_word)) & 0x000000000000ff00ULL) == 0 ||
(((desc->ifmt_word)) & 0x000000000000ff00ULL) == (((mword
)) & 0x000000000000ff00ULL))
&&
3074 IFM_SUBTYPE(desc->ifmt_word)((desc->ifmt_word) & 0x00000000000000ffULL) == IFM_SUBTYPE(mword)((mword) & 0x00000000000000ffULL))
3075 return (desc->ifmt_string);
3076 }
3077 return ("<unknown subtype>");
3078}
3079
3080uint64_t
3081get_media_subtype(uint64_t type, const char *val)
3082{
3083 uint64_t rval;
3084
3085 rval = lookup_media_word(ifm_subtype_descriptions, type, val);
3086 if (rval == -1)
3087 errx(1, "unknown %s media subtype: %s",
3088 get_media_type_string(type), val);
3089
3090 return (rval);
3091}
3092
3093uint64_t
3094get_media_mode(uint64_t type, const char *val)
3095{
3096 uint64_t rval;
3097
3098 rval = lookup_media_word(ifm_mode_descriptions, type, val);
3099 if (rval == -1)
3100 errx(1, "unknown %s media mode: %s",
3101 get_media_type_string(type), val);
3102 return (rval);
3103}
3104
3105uint64_t
3106get_media_options(uint64_t type, const char *val)
3107{
3108 char *optlist, *str;
3109 uint64_t option, rval = 0;
3110
3111 /* We muck with the string, so copy it. */
3112 optlist = strdup(val);
3113 if (optlist == NULL((void *)0))
3114 err(1, "strdup");
3115 str = optlist;
3116
3117 /*
3118 * Look up the options in the user-provided comma-separated list.
3119 */
3120 for (; (str = strtok(str, ",")) != NULL((void *)0); str = NULL((void *)0)) {
3121 option = lookup_media_word(ifm_option_descriptions, type, str);
3122 if (option == -1)
3123 errx(1, "unknown %s media option: %s",
3124 get_media_type_string(type), str);
3125 rval |= IFM_OPTIONS(option)((option) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL)
)
;
3126 }
3127
3128 free(optlist);
3129 return (rval);
3130}
3131
3132uint64_t
3133lookup_media_word(const struct ifmedia_description *desc, uint64_t type,
3134 const char *val)
3135{
3136
3137 for (; desc->ifmt_string != NULL((void *)0); desc++) {
3138 if (IFM_TYPE_MATCH(desc->ifmt_word, type)((((desc->ifmt_word)) & 0x000000000000ff00ULL) == 0 ||
(((desc->ifmt_word)) & 0x000000000000ff00ULL) == (((type
)) & 0x000000000000ff00ULL))
&&
3139 strcasecmp(desc->ifmt_string, val) == 0)
3140 return (desc->ifmt_word);
3141 }
3142 return (-1);
3143}
3144
3145void
3146print_media_word(uint64_t ifmw, int print_type, int as_syntax)
3147{
3148 const struct ifmedia_description *desc;
3149 uint64_t seen_option = 0;
3150
3151 if (print_type)
3152 printf("%s ", get_media_type_string(ifmw));
3153 printf("%s%s", as_syntax ? "media " : "",
3154 get_media_subtype_string(ifmw));
3155
3156 /* Find mode. */
3157 if (IFM_MODE(ifmw)((ifmw) & 0x000000ff00000000ULL) != 0) {
3158 for (desc = ifm_mode_descriptions; desc->ifmt_string != NULL((void *)0);
3159 desc++) {
3160 if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw)((((desc->ifmt_word)) & 0x000000000000ff00ULL) == 0 ||
(((desc->ifmt_word)) & 0x000000000000ff00ULL) == (((ifmw
)) & 0x000000000000ff00ULL))
&&
3161 IFM_MODE(ifmw)((ifmw) & 0x000000ff00000000ULL) == IFM_MODE(desc->ifmt_word)((desc->ifmt_word) & 0x000000ff00000000ULL)) {
3162 printf(" mode %s", desc->ifmt_string);
3163 break;
3164 }
3165 }
3166 }
3167
3168 /* Find options. */
3169 for (desc = ifm_option_descriptions; desc->ifmt_string != NULL((void *)0);
3170 desc++) {
3171 if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw)((((desc->ifmt_word)) & 0x000000000000ff00ULL) == 0 ||
(((desc->ifmt_word)) & 0x000000000000ff00ULL) == (((ifmw
)) & 0x000000000000ff00ULL))
&&
3172 (IFM_OPTIONS(ifmw)((ifmw) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL)) & IFM_OPTIONS(desc->ifmt_word)((desc->ifmt_word) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL
))
) != 0 &&
3173 (seen_option & IFM_OPTIONS(desc->ifmt_word)((desc->ifmt_word) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL
))
) == 0) {
3174 if (seen_option == 0)
3175 printf(" %s", as_syntax ? "mediaopt " : "");
3176 printf("%s%s", seen_option ? "," : "",
3177 desc->ifmt_string);
3178 seen_option |= IFM_OPTIONS(desc->ifmt_word)((desc->ifmt_word) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL
))
;
3179 }
3180 }
3181 if (IFM_INST(ifmw)(((ifmw) & 0xff00000000000000ULL) >> 56) != 0)
3182 printf(" instance %lld", IFM_INST(ifmw)(((ifmw) & 0xff00000000000000ULL) >> 56));
3183}
3184
3185static void
3186print_tunnel(const struct if_laddrreq *req)
3187{
3188 char psrcaddr[NI_MAXHOST256];
3189 char psrcport[NI_MAXSERV32];
3190 char pdstaddr[NI_MAXHOST256];
3191 char pdstport[NI_MAXSERV32];
3192 const char *ver = "";
3193 const int niflag = NI_NUMERICHOST1 | NI_NUMERICSERV2 | NI_DGRAM16;
3194
3195 if (req == NULL((void *)0)) {
3196 printf("(unset)");
3197 return;
3198 }
3199
3200 psrcaddr[0] = pdstaddr[0] = '\0';
3201
3202 if (getnameinfo((struct sockaddr *)&req->addr, req->addr.ss_len,
3203 psrcaddr, sizeof(psrcaddr), psrcport, sizeof(psrcport),
3204 niflag) != 0)
3205 strlcpy(psrcaddr, "<error>", sizeof(psrcaddr));
3206 if (req->addr.ss_family == AF_INET624)
3207 ver = "6";
3208
3209 printf("inet%s %s", ver, psrcaddr);
3210 if (strcmp(psrcport, "0") != 0)
3211 printf(":%s", psrcport);
3212
3213 if (req->dstaddr.ss_family != AF_UNSPEC0) {
3214 in_port_t dstport = 0;
3215 const struct sockaddr_in *sin;
3216 const struct sockaddr_in6 *sin6;
3217
3218 if (getnameinfo((struct sockaddr *)&req->dstaddr,
3219 req->dstaddr.ss_len, pdstaddr, sizeof(pdstaddr),
3220 pdstport, sizeof(pdstport), niflag) != 0)
3221 strlcpy(pdstaddr, "<error>", sizeof(pdstaddr));
3222
3223 printf(" --> %s", pdstaddr);
3224 if (strcmp(pdstport, "0") != 0)
3225 printf(":%s", pdstport);
3226 }
3227}
3228
3229static void
3230phys_status(int force)
3231{
3232 struct if_laddrreq req;
3233 struct if_laddrreq *r = &req;
3234
3235 memset(&req, 0, sizeof(req));
3236 (void) strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name));
3237 if (ioctl(sock, SIOCGLIFPHYADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct if_laddrreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((75)))
, (caddr_t)&req) == -1) {
3238 if (errno(*__errno()) != EADDRNOTAVAIL49)
3239 return;
3240
3241 r = NULL((void *)0);
3242 }
3243
3244 printf("\ttunnel: ");
3245 print_tunnel(r);
3246
3247 if (ioctl(sock, SIOCGLIFPHYTTL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((169)))
, (caddr_t)&ifr) == 0) {
3248 if (ifr.ifr_ttlifr_ifru.ifru_metric == -1)
3249 printf(" ttl copy");
3250 else if (ifr.ifr_ttlifr_ifru.ifru_metric > 0)
3251 printf(" ttl %d", ifr.ifr_ttlifr_ifru.ifru_metric);
3252 }
3253
3254 if (ioctl(sock, SIOCGLIFPHYDF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((194)))
, (caddr_t)&ifr) == 0)
3255 printf(" %s", ifr.ifr_dfifr_ifru.ifru_metric ? "df" : "nodf");
3256
3257#ifndef SMALL
3258 if (ioctl(sock, SIOCGLIFPHYECN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((200)))
, (caddr_t)&ifr) == 0)
3259 printf(" %s", ifr.ifr_metricifr_ifru.ifru_metric ? "ecn" : "noecn");
3260
3261 if (ioctl(sock, SIOCGLIFPHYRTABLE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((162)))
, (caddr_t)&ifr) == 0 &&
3262 (rdomainid != 0 || ifr.ifr_rdomainidifr_ifru.ifru_metric != 0))
3263 printf(" rdomain %d", ifr.ifr_rdomainidifr_ifru.ifru_metric);
3264#endif
3265 printf("\n");
3266}
3267
3268#ifndef SMALL
3269const uint64_t ifm_status_valid_list[] = IFM_STATUS_VALID_LIST{ 0x0000000000000001ULL, 0 };
3270
3271const struct ifmedia_status_description ifm_status_descriptions[] =
3272 IFM_STATUS_DESCRIPTIONS{ { 0x0000000000000100ULL, 0x0000000000000001ULL, 0x0000000000000002ULL
, { "no carrier", "active" } }, { 0x0000000000000300ULL, 0x0000000000000001ULL
, 0x0000000000000002ULL, { "no ring", "inserted" } }, { 0x0000000000000400ULL
, 0x0000000000000001ULL, 0x0000000000000002ULL, { "no network"
, "active" } }, { 0x0000000000000500ULL, 0x0000000000000001ULL
, 0x0000000000000002ULL, { "no carrier", "active" } }, { 0x0000000000000600ULL
, 0x0000000000000001ULL, 0x0000000000000002ULL, { "backup", "master"
} }, { 0, 0, 0, { ((void *)0), ((void *)0) } } }
;
3273#endif
3274
3275const struct if_status_description if_status_descriptions[] =
3276 LINK_STATE_DESCRIPTIONS{ { 0x06, 2, "no carrier" }, { 0x47, 2, "no network" }, { 0x17
, 2, "no carrier" }, { 0xf7, 2, "backup" }, { 0xf7, 4, "master"
}, { 0xf7, 5, "master" }, { 0xf7, 6, "master" }, { 0, 4, "active"
}, { 0, 5, "active" }, { 0, 6, "active" }, { 0, 0, "unknown"
}, { 0, 1, "invalid" }, { 0, 2, "down" }, { 0, 3, "keepalive down"
}, { 0, 0, ((void *)0) } }
;
3277
3278const char *
3279get_linkstate(int mt, int link_state)
3280{
3281 const struct if_status_description *p;
3282 static char buf[8];
3283
3284 for (p = if_status_descriptions; p->ifs_string != NULL((void *)0); p++) {
3285 if (LINK_STATE_DESC_MATCH(p, mt, link_state)(((p)->ifs_type == (mt) || (p)->ifs_type == 0) &&
(p)->ifs_state == (link_state))
)
3286 return (p->ifs_string);
3287 }
3288 snprintf(buf, sizeof(buf), "[#%d]", link_state);
3289 return buf;
3290}
3291
3292/*
3293 * Print the status of the interface. If an address family was
3294 * specified, show it and it only; otherwise, show them all.
3295 */
3296void
3297status(int link, struct sockaddr_dl *sdl, int ls, int ifaliases)
3298{
3299 const struct afswtch *p = afp;
3300 struct ifmediareq ifmr;
3301#ifndef SMALL
3302 struct ifreq ifrdesc;
3303 struct ifkalivereq ikardesc;
3304 char ifdescr[IFDESCRSIZE64];
3305 char pifname[IF_NAMESIZE16];
3306#endif
3307 uint64_t *media_list;
3308 int i;
3309 char sep;
3310
3311
3312 printf("%s: ", ifname);
3313 printb("flags", flags | (xflags << 16), IFFBITS"\024\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6STATICARP"
"\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX"
"\15LINK0\16LINK1\17LINK2\20MULTICAST" "\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII"
"\30AUTOCONF4" "\31MONITOR" "\32LRO"
);
3314#ifndef SMALL
3315 if (rdomainid)
3316 printf(" rdomain %d", rdomainid);
3317#endif
3318 if (metric)
3319 printf(" metric %lu", metric);
3320 if (mtu)
3321 printf(" mtu %lu", mtu);
3322 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
3323#ifndef SMALL
3324 if (showcapsflag)
3325 printifhwfeatures(NULL((void *)0), 1);
3326#endif
3327 if (sdl != NULL((void *)0) && sdl->sdl_alen &&
3328 (sdl->sdl_type == IFT_ETHER0x06 || sdl->sdl_type == IFT_CARP0xf7))
3329 (void)printf("\tlladdr %s\n", ether_ntoa(
3330 (struct ether_addr *)LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen))));
3331
3332 sep = '\t';
3333#ifndef SMALL
3334 (void) memset(&ifrdesc, 0, sizeof(ifrdesc));
3335 (void) strlcpy(ifrdesc.ifr_name, ifname, sizeof(ifrdesc.ifr_name));
3336 ifrdesc.ifr_dataifr_ifru.ifru_data = (caddr_t)&ifdescr;
3337 if (ioctl(sock, SIOCGIFDESCR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((129)))
, &ifrdesc) == 0 &&
3338 strlen(ifrdesc.ifr_dataifr_ifru.ifru_data))
3339 printf("\tdescription: %s\n", ifrdesc.ifr_dataifr_ifru.ifru_data);
3340
3341 if (sdl != NULL((void *)0)) {
3342 printf("%cindex %u", sep, sdl->sdl_index);
3343 sep = ' ';
3344 }
3345 if (!is_bridge() && ioctl(sock, SIOCGIFPRIORITY(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((156)))
, &ifrdesc) == 0) {
3346 printf("%cpriority %d", sep, ifrdesc.ifr_metricifr_ifru.ifru_metric);
3347 sep = ' ';
3348 }
3349#endif
3350 printf("%cllprio %d\n", sep, llprio);
3351
3352#ifndef SMALL
3353 (void) memset(&ikardesc, 0, sizeof(ikardesc));
3354 (void) strlcpy(ikardesc.ikar_name, ifname, sizeof(ikardesc.ikar_name));
3355 if (ioctl(sock, SIOCGETKALIVE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifkalivereq) & 0x1fff) << 16) | ((('i')) <<
8) | ((164)))
, &ikardesc) == 0 &&
3356 (ikardesc.ikar_timeo != 0 || ikardesc.ikar_cnt != 0))
3357 printf("\tkeepalive: timeout %d count %d\n",
3358 ikardesc.ikar_timeo, ikardesc.ikar_cnt);
3359 if (ioctl(sock, SIOCGIFPAIR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((177)))
, &ifrdesc) == 0 && ifrdesc.ifr_indexifr_ifru.ifru_index != 0 &&
3360 if_indextoname(ifrdesc.ifr_indexifr_ifru.ifru_index, pifname) != NULL((void *)0))
3361 printf("\tpatch: %s\n", pifname);
3362#endif
3363 getencap();
3364#ifndef SMALL
3365 carp_status();
3366 pfsync_status();
3367 pppoe_status();
3368 sppp_status();
3369 mpls_status();
3370 pflow_status();
3371 umb_status();
3372 wg_status(ifaliases);
3373#endif
3374 trunk_status();
3375 getifgroups();
3376
3377 (void) memset(&ifmr, 0, sizeof(ifmr));
3378 (void) strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
3379
3380 if (ioctl(sock, SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
, (caddr_t)&ifmr) == -1) {
3381 /*
3382 * Interface doesn't support SIOC{G,S}IFMEDIA.
3383 */
3384 if (ls != LINK_STATE_UNKNOWN0)
3385 printf("\tstatus: %s\n",
3386 get_linkstate(sdl->sdl_type, ls));
3387 goto proto_status;
3388 }
3389
3390 if (ifmr.ifm_count == 0) {
3391 warnx("%s: no media types?", ifname);
3392 goto proto_status;
3393 }
3394
3395 media_list = calloc(ifmr.ifm_count, sizeof(*media_list));
3396 if (media_list == NULL((void *)0))
3397 err(1, "calloc");
3398 ifmr.ifm_ulist = media_list;
3399
3400 if (ioctl(sock, SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
, (caddr_t)&ifmr) == -1)
3401 err(1, "%s: SIOCGIFMEDIA", ifmr.ifm_name);
3402
3403 printf("\tmedia: ");
3404 print_media_word(ifmr.ifm_current, 1, 0);
3405 if (ifmr.ifm_active != ifmr.ifm_current) {
3406 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
3407 putchar('(')(!__isthreaded ? __sputc('(', (&__sF[1])) : (putc)('(', (
&__sF[1])))
;
3408 print_media_word(ifmr.ifm_active, 0, 0);
3409 putchar(')')(!__isthreaded ? __sputc(')', (&__sF[1])) : (putc)(')', (
&__sF[1])))
;
3410 }
3411 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
3412
3413#ifdef SMALL
3414 printf("\tstatus: %s\n", get_linkstate(sdl->sdl_type, ls));
3415#else
3416 if (ifmr.ifm_status & IFM_AVALID0x0000000000000001ULL) {
3417 const struct ifmedia_status_description *ifms;
3418 int bitno, found = 0;
3419
3420 printf("\tstatus: ");
3421 for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) {
3422 for (ifms = ifm_status_descriptions;
3423 ifms->ifms_valid != 0; ifms++) {
3424 if (ifms->ifms_type !=
3425 IFM_TYPE(ifmr.ifm_current)((ifmr.ifm_current) & 0x000000000000ff00ULL) ||
3426 ifms->ifms_valid !=
3427 ifm_status_valid_list[bitno])
3428 continue;
3429 printf("%s%s", found ? ", " : "",
3430 IFM_STATUS_DESC(ifms, ifmr.ifm_status)(ifms)->ifms_string[((ifms)->ifms_bit & (ifmr.ifm_status
)) ? 1 : 0]
);
3431 found = 1;
3432
3433 /*
3434 * For each valid indicator bit, there's
3435 * only one entry for each media type, so
3436 * terminate the inner loop now.
3437 */
3438 break;
3439 }
3440 }
3441
3442 if (found == 0)
3443 printf("unknown");
3444 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
3445 }
3446
3447 if (showtransceiver) {
3448 if (if_sff_info(0) == -1)
3449 if (!aflag && errno(*__errno()) != EPERM1 && errno(*__errno()) != ENOTTY25)
3450 warn("%s transceiver", ifname);
3451 }
3452#endif
3453 ieee80211_status();
3454
3455 if (showmediaflag) {
3456 uint64_t type;
3457 int printed_type = 0;
3458
3459 for (type = IFM_NMIN0x0000000000000100ULL; type <= IFM_NMAX0x000000000000ff00ULL; type += IFM_NMIN0x0000000000000100ULL) {
3460 for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) {
3461 if (IFM_TYPE(media_list[i])((media_list[i]) & 0x000000000000ff00ULL) == type) {
3462
3463 /*
3464 * Don't advertise media with fixed
3465 * data rates for wireless interfaces.
3466 * Normal people don't need these.
3467 */
3468 if (type == IFM_IEEE802110x0000000000000400ULL &&
3469 (media_list[i] & IFM_TMASK0x00000000000000ffULL) !=
3470 IFM_AUTO0ULL)
3471 continue;
3472
3473 if (printed_type == 0) {
3474 printf("\tsupported media:\n");
3475 printed_type = 1;
3476 }
3477 printf("\t\t");
3478 print_media_word(media_list[i], 0, 1);
3479 printf("\n");
3480 }
3481 }
3482 }
3483 }
3484
3485 free(media_list);
3486
3487 proto_status:
3488 if (link == 0) {
3489 if ((p = afp) != NULL((void *)0)) {
3490 p->af_status(1);
3491 } else for (p = afs; p->af_name; p++) {
3492 ifr.ifr_addrifr_ifru.ifru_addr.sa_family = p->af_af;
3493 p->af_status(0);
3494 }
3495 }
3496
3497 phys_status(0);
3498#ifndef SMALL
3499 bridge_status();
3500#endif
3501}
3502
3503void
3504in_status(int force)
3505{
3506 struct sockaddr_in *sin, sin2;
3507
3508 getsock(AF_INET2);
3509 if (sock == -1) {
3510 if (errno(*__errno()) == EPROTONOSUPPORT43)
3511 return;
3512 err(1, "socket");
3513 }
3514 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3515 sin = (struct sockaddr_in *)&ifr.ifr_addrifr_ifru.ifru_addr;
3516
3517 /*
3518 * We keep the interface address and reset it before each
3519 * ioctl() so we can get ifaliases information (as opposed
3520 * to the primary interface netmask/dstaddr/broadaddr, if
3521 * the ifr_addr field is zero).
3522 */
3523 memcpy(&sin2, &ifr.ifr_addrifr_ifru.ifru_addr, sizeof(sin2));
3524
3525 printf("\tinet %s", inet_ntoa(sin->sin_addr));
3526 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3527 if (ioctl(sock, SIOCGIFNETMASK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((37)))
, (caddr_t)&ifr) == -1) {
3528 if (errno(*__errno()) != EADDRNOTAVAIL49)
3529 warn("SIOCGIFNETMASK");
3530 memset(&ifr.ifr_addrifr_ifru.ifru_addr, 0, sizeof(ifr.ifr_addrifr_ifru.ifru_addr));
3531 } else
3532 netmask.sin_addr =
3533 ((struct sockaddr_in *)&ifr.ifr_addrifr_ifru.ifru_addr)->sin_addr;
3534 if (flags & IFF_POINTOPOINT0x10) {
3535 memcpy(&ifr.ifr_addrifr_ifru.ifru_addr, &sin2, sizeof(sin2));
3536 if (ioctl(sock, SIOCGIFDSTADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((34)))
, (caddr_t)&ifr) == -1) {
3537 if (errno(*__errno()) == EADDRNOTAVAIL49)
3538 memset(&ifr.ifr_addrifr_ifru.ifru_addr, 0, sizeof(ifr.ifr_addrifr_ifru.ifru_addr));
3539 else
3540 warn("SIOCGIFDSTADDR");
3541 }
3542 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3543 sin = (struct sockaddr_in *)&ifr.ifr_dstaddrifr_ifru.ifru_dstaddr;
3544 printf(" --> %s", inet_ntoa(sin->sin_addr));
3545 }
3546 printf(" netmask 0x%x", ntohl(netmask.sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(netmask.sin_addr.s_addr) ? (
__uint32_t)(((__uint32_t)(netmask.sin_addr.s_addr) & 0xff
) << 24 | ((__uint32_t)(netmask.sin_addr.s_addr) & 0xff00
) << 8 | ((__uint32_t)(netmask.sin_addr.s_addr) & 0xff0000
) >> 8 | ((__uint32_t)(netmask.sin_addr.s_addr) & 0xff000000
) >> 24) : __swap32md(netmask.sin_addr.s_addr))
);
3547 if (flags & IFF_BROADCAST0x2) {
3548 memcpy(&ifr.ifr_addrifr_ifru.ifru_addr, &sin2, sizeof(sin2));
3549 if (ioctl(sock, SIOCGIFBRDADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((35)))
, (caddr_t)&ifr) == -1) {
3550 if (errno(*__errno()) == EADDRNOTAVAIL49)
3551 memset(&ifr.ifr_addrifr_ifru.ifru_addr, 0, sizeof(ifr.ifr_addrifr_ifru.ifru_addr));
3552 else
3553 warn("SIOCGIFBRDADDR");
3554 }
3555 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3556 sin = (struct sockaddr_in *)&ifr.ifr_addrifr_ifru.ifru_addr;
3557 if (sin->sin_addr.s_addr != 0)
3558 printf(" broadcast %s", inet_ntoa(sin->sin_addr));
3559 }
3560 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
3561}
3562
3563void
3564setifprefixlen(const char *addr, int d)
3565{
3566 if (afp->af_getprefix)
3567 afp->af_getprefix(addr, MASK2);
3568 explicit_prefix = 1;
3569}
3570
3571void
3572in6_fillscopeid(struct sockaddr_in6 *sin6)
3573{
3574#ifdef __KAME__
3575 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))
&&
3576 sin6->sin6_scope_id == 0) {
3577 sin6->sin6_scope_id =
3578 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2])(__uint16_t)(__builtin_constant_p(*(u_int16_t *)&sin6->
sin6_addr.__u6_addr.__u6_addr8[2]) ? (__uint16_t)(((__uint16_t
)(*(u_int16_t *)&sin6->sin6_addr.__u6_addr.__u6_addr8[
2]) & 0xffU) << 8 | ((__uint16_t)(*(u_int16_t *)&
sin6->sin6_addr.__u6_addr.__u6_addr8[2]) & 0xff00U) >>
8) : __swap16md(*(u_int16_t *)&sin6->sin6_addr.__u6_addr
.__u6_addr8[2]))
;
3579 sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[2] = sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[3] = 0;
3580 }
3581#endif /* __KAME__ */
3582}
3583
3584/* XXX not really an alias */
3585void
3586in6_alias(struct in6_ifreq *creq)
3587{
3588 struct sockaddr_in6 *sin6;
3589 struct in6_ifreq ifr6; /* shadows file static variable */
3590 u_int32_t scopeid;
3591 char hbuf[NI_MAXHOST256];
3592 const int niflag = NI_NUMERICHOST1;
3593
3594 /* Get the non-alias address for this interface. */
3595 getsock(AF_INET624);
3596 if (sock == -1) {
3597 if (errno(*__errno()) == EPROTONOSUPPORT43)
3598 return;
3599 err(1, "socket");
3600 }
3601
3602 sin6 = (struct sockaddr_in6 *)&creq->ifr_addrifr_ifru.ifru_addr;
3603
3604 in6_fillscopeid(sin6);
3605 scopeid = sin6->sin6_scope_id;
3606 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
3607 hbuf, sizeof(hbuf), NULL((void *)0), 0, niflag) != 0)
3608 strlcpy(hbuf, "", sizeof hbuf);
3609 printf("\tinet6 %s", hbuf);
3610
3611 if (flags & IFF_POINTOPOINT0x10) {
3612 (void) memset(&ifr6, 0, sizeof(ifr6));
3613 (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name));
3614 ifr6.ifr_addrifr_ifru.ifru_addr = creq->ifr_addrifr_ifru.ifru_addr;
3615 if (ioctl(sock, SIOCGIFDSTADDR_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct in6_ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((34)))
, (caddr_t)&ifr6) == -1) {
3616 if (errno(*__errno()) != EADDRNOTAVAIL49)
3617 warn("SIOCGIFDSTADDR_IN6");
3618 (void) memset(&ifr6.ifr_addrifr_ifru.ifru_addr, 0, sizeof(ifr6.ifr_addrifr_ifru.ifru_addr));
3619 ifr6.ifr_addrifr_ifru.ifru_addr.sin6_family = AF_INET624;
3620 ifr6.ifr_addrifr_ifru.ifru_addr.sin6_len = sizeof(struct sockaddr_in6);
3621 }
3622 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addrifr_ifru.ifru_addr;
3623 in6_fillscopeid(sin6);
3624 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
3625 hbuf, sizeof(hbuf), NULL((void *)0), 0, niflag) != 0)
3626 strlcpy(hbuf, "", sizeof hbuf);
3627 printf(" --> %s", hbuf);
3628 }
3629
3630 (void) memset(&ifr6, 0, sizeof(ifr6));
3631 (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name));
3632 ifr6.ifr_addrifr_ifru.ifru_addr = creq->ifr_addrifr_ifru.ifru_addr;
3633 if (ioctl(sock, SIOCGIFNETMASK_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct in6_ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((37)))
, (caddr_t)&ifr6) == -1) {
3634 if (errno(*__errno()) != EADDRNOTAVAIL49)
3635 warn("SIOCGIFNETMASK_IN6");
3636 } else {
3637 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addrifr_ifru.ifru_addr;
3638 printf(" prefixlen %d", prefix(&sin6->sin6_addr,
3639 sizeof(struct in6_addr)));
3640 }
3641
3642 (void) memset(&ifr6, 0, sizeof(ifr6));
3643 (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name));
3644 ifr6.ifr_addrifr_ifru.ifru_addr = creq->ifr_addrifr_ifru.ifru_addr;
3645 if (ioctl(sock, SIOCGIFAFLAG_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct in6_ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((73)))
, (caddr_t)&ifr6) == -1) {
3646 if (errno(*__errno()) != EADDRNOTAVAIL49)
3647 warn("SIOCGIFAFLAG_IN6");
3648 } else {
3649 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST0x01)
3650 printf(" anycast");
3651 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE0x02)
3652 printf(" tentative");
3653 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED0x04)
3654 printf(" duplicated");
3655 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED0x08)
3656 printf(" detached");
3657 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED0x10)
3658 printf(" deprecated");
3659 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_AUTOCONF0x40)
3660 printf(" autoconf");
3661 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TEMPORARY0x80)
3662 printf(" temporary");
3663 }
3664
3665 if (scopeid)
3666 printf(" scopeid 0x%x", scopeid);
3667
3668 if (Lflag) {
3669 struct in6_addrlifetime *lifetime;
3670
3671 (void) memset(&ifr6, 0, sizeof(ifr6));
3672 (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name));
3673 ifr6.ifr_addrifr_ifru.ifru_addr = creq->ifr_addrifr_ifru.ifru_addr;
3674 lifetime = &ifr6.ifr_ifru.ifru_lifetime;
3675 if (ioctl(sock, SIOCGIFALIFETIME_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct in6_ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((81)))
, (caddr_t)&ifr6) == -1) {
3676 if (errno(*__errno()) != EADDRNOTAVAIL49)
3677 warn("SIOCGIFALIFETIME_IN6");
3678 } else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) {
3679 time_t t = time(NULL((void *)0));
3680
3681 printf(" pltime ");
3682 if (lifetime->ia6t_preferred) {
3683 printf("%s", lifetime->ia6t_preferred < t
3684 ? "0" :
3685 sec2str(lifetime->ia6t_preferred - t));
3686 } else
3687 printf("infty");
3688
3689 printf(" vltime ");
3690 if (lifetime->ia6t_expire) {
3691 printf("%s", lifetime->ia6t_expire < t
3692 ? "0"
3693 : sec2str(lifetime->ia6t_expire - t));
3694 } else
3695 printf("infty");
3696 }
3697 }
3698
3699 printf("\n");
3700}
3701
3702void
3703in6_status(int force)
3704{
3705 in6_alias((struct in6_ifreq *)&ifr6);
3706}
3707
3708#ifndef SMALL
3709void
3710settunnel(const char *src, const char *dst)
3711{
3712 char srcbuf[HOST_NAME_MAX255], dstbuf[HOST_NAME_MAX255];
3713 const char *srcport, *dstport;
3714 const char *srcaddr, *dstaddr;
3715 struct addrinfo *srcres, *dstres;
3716 struct addrinfo hints = {
3717 .ai_family = AF_UNSPEC0,
3718 .ai_socktype = SOCK_DGRAM2,
3719 .ai_protocol = IPPROTO_UDP17,
3720 .ai_flags = AI_PASSIVE1,
3721 };
3722 int ecode;
3723 size_t len;
3724 struct if_laddrreq req;
3725
3726 srcport = strchr(src, ':');
3727 if (srcport == NULL((void *)0) || srcport != strrchr(src, ':')) {
3728 /* no port or IPv6 */
3729 srcaddr = src;
3730 srcport = NULL((void *)0);
3731 } else {
3732 len = srcport - src;
3733 if (len >= sizeof(srcbuf))
3734 errx(1, "src %s bad value", src);
3735 memcpy(srcbuf, src, len);
3736 srcbuf[len] = '\0';
3737
3738 srcaddr = srcbuf;
3739 srcport++;
3740 }
3741
3742 dstport = strchr(dst, ':');
3743 if (dstport == NULL((void *)0) || dstport != strrchr(dst, ':')) {
3744 /* no port or IPv6 */
3745 dstaddr = dst;
3746 dstport = NULL((void *)0);
3747 } else {
3748 len = dstport - dst;
3749 if (len >= sizeof(dstbuf))
3750 errx(1, "dst %s bad value", dst);
3751 memcpy(dstbuf, dst, len);
3752 dstbuf[len] = '\0';
3753
3754 dstaddr = dstbuf;
3755 dstport++;
3756 }
3757
3758 if ((ecode = getaddrinfo(srcaddr, srcport, &hints, &srcres)) != 0)
3759 errx(1, "error in parsing address string: %s",
3760 gai_strerror(ecode));
3761
3762 hints.ai_flags = 0;
3763 if ((ecode = getaddrinfo(dstaddr, dstport, &hints, &dstres)) != 0)
3764 errx(1, "error in parsing address string: %s",
3765 gai_strerror(ecode));
3766
3767 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family)
3768 errx(1,
3769 "source and destination address families do not match");
3770
3771 memset(&req, 0, sizeof(req));
3772 (void) strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name));
3773 memcpy(&req.addr, srcres->ai_addr, srcres->ai_addrlen);
3774 memcpy(&req.dstaddr, dstres->ai_addr, dstres->ai_addrlen);
3775 if (ioctl(sock, SIOCSLIFPHYADDR((unsigned long)0x80000000 | ((sizeof(struct if_laddrreq) &
0x1fff) << 16) | ((('i')) << 8) | ((74)))
, &req) == -1)
3776 warn("SIOCSLIFPHYADDR");
3777
3778 freeaddrinfo(srcres);
3779 freeaddrinfo(dstres);
3780}
3781
3782void
3783settunneladdr(const char *src, int ignored)
3784{
3785 char srcbuf[HOST_NAME_MAX255];
3786 const char *srcport;
3787 const char *srcaddr;
3788 struct addrinfo *srcres;
3789 struct addrinfo hints = {
3790 .ai_family = AF_UNSPEC0,
3791 .ai_socktype = SOCK_DGRAM2,
3792 .ai_protocol = IPPROTO_UDP17,
3793 .ai_flags = AI_PASSIVE1,
3794 };
3795 struct if_laddrreq req;
3796 ssize_t len;
3797 int rv;
3798
3799 srcport = strchr(src, ':');
3800 if (srcport == NULL((void *)0) || srcport != strrchr(src, ':')) {
3801 /* no port or IPv6 */
3802 srcaddr = src;
3803 srcport = NULL((void *)0);
3804 } else {
3805 len = srcport - src;
3806 if (len >= sizeof(srcbuf))
3807 errx(1, "src %s bad value", src);
3808 memcpy(srcbuf, src, len);
3809 srcbuf[len] = '\0';
3810
3811 srcaddr = srcbuf;
3812 srcport++;
3813 }
3814
3815 rv = getaddrinfo(srcaddr, srcport, &hints, &srcres);
3816 if (rv != 0)
3817 errx(1, "tunneladdr %s: %s", src, gai_strerror(rv));
3818
3819 memset(&req, 0, sizeof(req));
3820 len = strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name));
3821 if (len >= sizeof(req.iflr_name))
3822 errx(1, "%s: Interface name too long", ifname);
3823
3824 memcpy(&req.addr, srcres->ai_addr, srcres->ai_addrlen);
3825
3826 req.dstaddr.ss_len = 2;
3827 req.dstaddr.ss_family = AF_UNSPEC0;
3828
3829 if (ioctl(sock, SIOCSLIFPHYADDR((unsigned long)0x80000000 | ((sizeof(struct if_laddrreq) &
0x1fff) << 16) | ((('i')) << 8) | ((74)))
, &req) == -1)
3830 warn("tunneladdr %s", src);
3831
3832 freeaddrinfo(srcres);
3833}
3834
3835void
3836deletetunnel(const char *ignored, int alsoignored)
3837{
3838 if (ioctl(sock, SIOCDIFPHYADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((73)))
, &ifr) == -1)
3839 warn("SIOCDIFPHYADDR");
3840}
3841
3842void
3843settunnelinst(const char *id, int param)
3844{
3845 const char *errmsg = NULL((void *)0);
3846 int rdomainid;
3847
3848 rdomainid = strtonum(id, 0, RT_TABLEID_MAX255, &errmsg);
3849 if (errmsg)
3850 errx(1, "rdomain %s: %s", id, errmsg);
3851
3852 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3853 ifr.ifr_rdomainidifr_ifru.ifru_metric = rdomainid;
3854 if (ioctl(sock, SIOCSLIFPHYRTABLE((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((161)))
, (caddr_t)&ifr) == -1)
3855 warn("SIOCSLIFPHYRTABLE");
3856}
3857
3858void
3859unsettunnelinst(const char *ignored, int alsoignored)
3860{
3861 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3862 ifr.ifr_rdomainidifr_ifru.ifru_metric = 0;
3863 if (ioctl(sock, SIOCSLIFPHYRTABLE((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((161)))
, (caddr_t)&ifr) == -1)
3864 warn("SIOCSLIFPHYRTABLE");
3865}
3866
3867void
3868settunnelttl(const char *id, int param)
3869{
3870 const char *errmsg = NULL((void *)0);
3871 int ttl;
3872
3873 if (strcmp(id, "copy") == 0)
3874 ttl = -1;
3875 else {
3876 ttl = strtonum(id, 0, 0xff, &errmsg);
3877 if (errmsg)
3878 errx(1, "tunnelttl %s: %s", id, errmsg);
3879 }
3880
3881 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3882 ifr.ifr_ttlifr_ifru.ifru_metric = ttl;
3883 if (ioctl(sock, SIOCSLIFPHYTTL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((168)))
, (caddr_t)&ifr) == -1)
3884 warn("SIOCSLIFPHYTTL");
3885}
3886
3887void
3888settunneldf(const char *ignored, int alsoignored)
3889{
3890 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3891 ifr.ifr_dfifr_ifru.ifru_metric = 1;
3892 if (ioctl(sock, SIOCSLIFPHYDF((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((193)))
, (caddr_t)&ifr) == -1)
3893 warn("SIOCSLIFPHYDF");
3894}
3895
3896void
3897settunnelnodf(const char *ignored, int alsoignored)
3898{
3899 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3900 ifr.ifr_dfifr_ifru.ifru_metric = 0;
3901 if (ioctl(sock, SIOCSLIFPHYDF((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((193)))
, (caddr_t)&ifr) == -1)
3902 warn("SIOCSLIFPHYDF");
3903}
3904
3905void
3906settunnelecn(const char *ignored, int alsoignored)
3907{
3908 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3909 ifr.ifr_metricifr_ifru.ifru_metric = 1;
3910 if (ioctl(sock, SIOCSLIFPHYECN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((199)))
, (caddr_t)&ifr) == -1)
3911 warn("SIOCSLIFPHYECN");
3912}
3913
3914void
3915settunnelnoecn(const char *ignored, int alsoignored)
3916{
3917 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3918 ifr.ifr_metricifr_ifru.ifru_metric = 0;
3919 if (ioctl(sock, SIOCSLIFPHYECN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((199)))
, (caddr_t)&ifr) == -1)
3920 warn("SIOCSLIFPHYECN");
3921}
3922
3923void
3924setvnetflowid(const char *ignored, int alsoignored)
3925{
3926 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
3927 sizeof(ifr.ifr_name))
3928 errx(1, "vnetflowid: name is too long");
3929
3930 ifr.ifr_vnetidifr_ifru.ifru_vnetid = 1;
3931 if (ioctl(sock, SIOCSVNETFLOWID((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((195)))
, &ifr) == -1)
3932 warn("SIOCSVNETFLOWID");
3933}
3934
3935void
3936delvnetflowid(const char *ignored, int alsoignored)
3937{
3938 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
3939 sizeof(ifr.ifr_name))
3940 errx(1, "vnetflowid: name is too long");
3941
3942 ifr.ifr_vnetidifr_ifru.ifru_vnetid = 0;
3943 if (ioctl(sock, SIOCSVNETFLOWID((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((195)))
, &ifr) == -1)
3944 warn("SIOCSVNETFLOWID");
3945}
3946
3947static void
3948pwe3_neighbor(void)
3949{
3950 const char *prefix = "pwe3 remote label";
3951 struct if_laddrreq req;
3952 char hbuf[NI_MAXHOST256];
3953 struct sockaddr_mpls *smpls;
3954 int error;
3955
3956 memset(&req, 0, sizeof(req));
3957 if (strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)) >=
3958 sizeof(req.iflr_name))
3959 errx(1, "pwe3 neighbor: name is too long");
3960
3961 if (ioctl(sock, SIOCGPWE3NEIGHBOR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct if_laddrreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((222)))
, &req) == -1) {
3962 if (errno(*__errno()) != EADDRNOTAVAIL49)
3963 return;
3964
3965 printf(" %s (unset)", prefix);
3966 return;
3967 }
3968
3969 if (req.dstaddr.ss_family != AF_MPLS33) {
3970 warnc(EPFNOSUPPORT46, "pwe3 neighbor");
3971 return;
3972 }
3973 smpls = (struct sockaddr_mpls *)&req.dstaddr;
3974
3975 error = getnameinfo((struct sockaddr *)&req.addr, sizeof(req.addr),
3976 hbuf, sizeof(hbuf), NULL((void *)0), 0, NI_NUMERICHOST1);
3977 if (error != 0) {
3978 warnx("%s: %s", prefix, gai_strerror(error));
3979 return;
3980 }
3981
3982 printf(" %s %u on %s", prefix, smpls->smpls_label, hbuf);
3983}
3984
3985static void
3986pwe3_cword(void)
3987{
3988 struct ifreq req;
3989
3990 memset(&req, 0, sizeof(req));
3991 if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >=
3992 sizeof(req.ifr_name))
3993 errx(1, "pwe3 control word: name is too long");
3994
3995 if (ioctl(sock, SIOCGPWE3CTRLWORD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((220)))
, &req) == -1) {
3996 return;
3997 }
3998
3999 printf(" %s", req.ifr_pwe3ifr_ifru.ifru_metric ? "cw" : "nocw");
4000}
4001
4002static void
4003pwe3_fword(void)
4004{
4005 struct ifreq req;
4006
4007 memset(&req, 0, sizeof(req));
4008 if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >=
4009 sizeof(req.ifr_name))
4010 errx(1, "pwe3 control word: name is too long");
4011
4012 if (ioctl(sock, SIOCGPWE3FAT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((221)))
, &req) == -1)
4013 return;
4014
4015 printf(" %s", req.ifr_pwe3ifr_ifru.ifru_metric ? "fat" : "nofat");
4016}
4017
4018void
4019mpls_status(void)
4020{
4021 struct shim_hdr shim;
4022
4023 bzero(&shim, sizeof(shim));
4024 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&shim;
4025
4026 if (ioctl(sock, SIOCGETLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((154)))
, (caddr_t)&ifr) == -1) {
4027 if (errno(*__errno()) != EADDRNOTAVAIL49)
4028 return;
4029
4030 printf("\tmpls: label (unset)");
4031 } else
4032 printf("\tmpls: label %u", shim.shim_label);
4033
4034 pwe3_neighbor();
4035 pwe3_cword();
4036 pwe3_fword();
4037
4038 printf("\n");
4039}
4040
4041void
4042setmplslabel(const char *val, int d)
4043{
4044 struct shim_hdr shim;
4045 const char *estr;
4046
4047 bzero(&shim, sizeof(shim));
4048 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&shim;
4049 shim.shim_label = strtonum(val, 0, MPLS_LABEL_MAX((1 << 20) - 1), &estr);
4050
4051 if (estr)
4052 errx(1, "mpls label %s is %s", val, estr);
4053 if (ioctl(sock, SIOCSETLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((153)))
, (caddr_t)&ifr) == -1)
4054 warn("SIOCSETLABEL");
4055}
4056
4057void
4058unsetmplslabel(const char *val, int d)
4059{
4060 struct ifreq req;
4061
4062 memset(&req, 0, sizeof(req));
4063 if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >=
4064 sizeof(req.ifr_name))
4065 errx(1, "interface name is too long");
4066
4067 if (ioctl(sock, SIOCDELLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((151)))
, (caddr_t)&ifr) == -1)
4068 warn("-mplslabel");
4069}
4070
4071static void
4072setpwe3(unsigned long cmd, const char *cmdname, int value)
4073{
4074 struct ifreq req;
4075
4076 memset(&req, 0, sizeof(req));
4077 if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >=
4078 sizeof(req.ifr_name))
4079 errx(1, "interface name is too long");
4080
4081 req.ifr_pwe3ifr_ifru.ifru_metric = value;
4082
4083 if (ioctl(sock, cmd, &req) == -1)
4084 warn("%s", cmdname);
4085}
4086
4087void
4088setpwe3cw(const char *val, int d)
4089{
4090 setpwe3(SIOCSPWE3CTRLWORD((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((220)))
, "pwecw", 1);
4091}
4092
4093void
4094unsetpwe3cw(const char *val, int d)
4095{
4096 setpwe3(SIOCSPWE3CTRLWORD((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((220)))
, "-pwecw", 0);
4097}
4098
4099void
4100setpwe3fat(const char *val, int d)
4101{
4102 setpwe3(SIOCSPWE3FAT((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((221)))
, "pwefat", 1);
4103}
4104
4105void
4106unsetpwe3fat(const char *val, int d)
4107{
4108 setpwe3(SIOCSPWE3FAT((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((221)))
, "-pwefat", 0);
4109}
4110
4111void
4112setpwe3neighbor(const char *label, const char *neighbor)
4113{
4114 struct if_laddrreq req;
4115 struct addrinfo hints, *res;
4116 struct sockaddr_mpls *smpls = (struct sockaddr_mpls *)&req.dstaddr;
4117 const char *errstr;
4118 int error;
4119
4120 memset(&req, 0, sizeof(req));
4121 if (strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)) >=
4122 sizeof(req.iflr_name))
4123 errx(1, "interface name is too long");
4124
4125 memset(&hints, 0, sizeof(hints));
4126 hints.ai_family = AF_UNSPEC0;
4127 hints.ai_socktype = SOCK_DGRAM2;
4128 error = getaddrinfo(neighbor, NULL((void *)0), &hints, &res);
4129 if (error != 0)
4130 errx(1, "pweneighbor %s: %s", neighbor, gai_strerror(error));
4131
4132 smpls->smpls_len = sizeof(*smpls);
4133 smpls->smpls_family = AF_MPLS33;
4134 smpls->smpls_label = strtonum(label,
4135 (MPLS_LABEL_RESERVED_MAX15 + 1), MPLS_LABEL_MAX((1 << 20) - 1), &errstr);
4136 if (errstr != NULL((void *)0))
4137 errx(1, "pweneighbor: invalid label: %s", errstr);
4138
4139
4140 if (res->ai_addrlen > sizeof(req.addr))
4141 errx(1, "pweneighbors: unexpected socklen");
4142
4143 memcpy(&req.addr, res->ai_addr, res->ai_addrlen);
4144
4145 freeaddrinfo(res);
4146
4147 if (ioctl(sock, SIOCSPWE3NEIGHBOR((unsigned long)0x80000000 | ((sizeof(struct if_laddrreq) &
0x1fff) << 16) | ((('i')) << 8) | ((222)))
, &req) == -1)
4148 warn("pweneighbor");
4149}
4150
4151void
4152unsetpwe3neighbor(const char *val, int d)
4153{
4154 struct ifreq req;
4155
4156 memset(&req, 0, sizeof(req));
4157 if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >=
4158 sizeof(req.ifr_name))
4159 errx(1, "interface name is too long");
4160
4161 if (ioctl(sock, SIOCDPWE3NEIGHBOR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((222)))
, &req) == -1)
4162 warn("-pweneighbor");
4163}
4164
4165void
4166transceiver(const char *value, int d)
4167{
4168 showtransceiver = 1;
4169}
4170
4171void
4172transceiverdump(const char *value, int d)
4173{
4174 if (if_sff_info(1) == -1)
4175 err(1, "%s transceiver", ifname);
4176}
4177#endif /* SMALL */
4178
4179void
4180getvnetflowid(struct ifencap *ife)
4181{
4182 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
4183 sizeof(ifr.ifr_name))
4184 errx(1, "vnetflowid: name is too long");
4185
4186 if (ioctl(sock, SIOCGVNETFLOWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((196)))
, &ifr) == -1)
4187 return;
4188
4189 if (ifr.ifr_vnetidifr_ifru.ifru_vnetid)
4190 ife->ife_flags |= IFE_VNETFLOWID0x10;
4191}
4192
4193void
4194setvnetid(const char *id, int param)
4195{
4196 const char *errmsg = NULL((void *)0);
4197 int64_t vnetid;
4198
4199 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
4200
4201 if (strcasecmp("any", id) == 0)
4202 vnetid = -1;
4203 else {
4204 vnetid = strtonum(id, 0, INT64_MAX0x7fffffffffffffffLL, &errmsg);
4205 if (errmsg)
4206 errx(1, "vnetid %s: %s", id, errmsg);
4207 }
4208
4209 ifr.ifr_vnetidifr_ifru.ifru_vnetid = vnetid;
4210 if (ioctl(sock, SIOCSVNETID((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((166)))
, (caddr_t)&ifr) == -1)
4211 warn("SIOCSVNETID");
4212}
4213
4214void
4215delvnetid(const char *ignored, int alsoignored)
4216{
4217 if (ioctl(sock, SIOCDVNETID((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((175)))
, &ifr) == -1)
4218 warn("SIOCDVNETID");
4219}
4220
4221void
4222getvnetid(struct ifencap *ife)
4223{
4224 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
4225 sizeof(ifr.ifr_name))
4226 errx(1, "vnetid: name is too long");
4227
4228 if (ioctl(sock, SIOCGVNETID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((167)))
, &ifr) == -1) {
4229 if (errno(*__errno()) != EADDRNOTAVAIL49)
4230 return;
4231
4232 ife->ife_flags |= IFE_VNETID_NONE0x1;
4233 return;
4234 }
4235
4236 if (ifr.ifr_vnetidifr_ifru.ifru_vnetid < 0) {
4237 ife->ife_flags |= IFE_VNETID_ANY0x2;
4238 return;
4239 }
4240
4241 ife->ife_flags |= IFE_VNETID_SET0x3;
4242 ife->ife_vnetid = ifr.ifr_vnetidifr_ifru.ifru_vnetid;
4243}
4244
4245void
4246setifparent(const char *id, int param)
4247{
4248 struct if_parent ifp;
4249
4250 if (strlcpy(ifp.ifp_name, ifname, sizeof(ifp.ifp_name)) >=
4251 sizeof(ifp.ifp_name))
4252 errx(1, "parent: name too long");
4253
4254 if (strlcpy(ifp.ifp_parent, id, sizeof(ifp.ifp_parent)) >=
4255 sizeof(ifp.ifp_parent))
4256 errx(1, "parent: parent too long");
4257
4258 if (ioctl(sock, SIOCSIFPARENT((unsigned long)0x80000000 | ((sizeof(struct if_parent) &
0x1fff) << 16) | ((('i')) << 8) | ((178)))
, (caddr_t)&ifp) == -1)
4259 warn("%s: %s: SIOCSIFPARENT", ifp.ifp_name, ifp.ifp_parent);
4260}
4261
4262void
4263delifparent(const char *ignored, int alsoignored)
4264{
4265 if (ioctl(sock, SIOCDIFPARENT((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((180)))
, &ifr) == -1)
4266 warn("SIOCDIFPARENT");
4267}
4268
4269void
4270getifparent(struct ifencap *ife)
4271{
4272 struct if_parent ifp;
4273
4274 memset(&ifp, 0, sizeof(ifp));
4275 if (strlcpy(ifp.ifp_name, ifname, sizeof(ifp.ifp_name)) >=
4276 sizeof(ifp.ifp_name))
4277 errx(1, "parent: name too long");
4278
4279 if (ioctl(sock, SIOCGIFPARENT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct if_parent) & 0x1fff) << 16) | ((('i')) <<
8) | ((179)))
, (caddr_t)&ifp) == -1) {
4280 if (errno(*__errno()) != EADDRNOTAVAIL49)
4281 return;
4282
4283 ife->ife_flags |= IFE_PARENT_NONE0x100;
4284 } else {
4285 memcpy(ife->ife_parent, ifp.ifp_parent,
4286 sizeof(ife->ife_parent));
4287 ife->ife_flags |= IFE_PARENT_SET0x200;
4288 }
4289}
4290
4291#ifndef SMALL
4292void
4293gettxprio(struct ifencap *ife)
4294{
4295 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
4296 sizeof(ifr.ifr_name))
4297 errx(1, "hdr prio: name is too long");
4298
4299 if (ioctl(sock, SIOCGTXHPRIO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((198)))
, (caddr_t)&ifr) == -1)
4300 return;
4301
4302 ife->ife_flags |= IFE_TXHPRIO_SET0x1000;
4303 ife->ife_txhprio = ifr.ifr_hdrprioifr_ifru.ifru_metric;
4304}
4305
4306void
4307settxprio(const char *val, int d)
4308{
4309 const char *errmsg = NULL((void *)0);
4310
4311 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
4312 sizeof(ifr.ifr_name))
4313 errx(1, "tx prio: name is too long");
4314
4315 if (strcmp(val, "packet") == 0)
4316 ifr.ifr_hdrprioifr_ifru.ifru_metric = IF_HDRPRIO_PACKET-1;
4317 else if (strcmp(val, "payload") == 0)
4318 ifr.ifr_hdrprioifr_ifru.ifru_metric = IF_HDRPRIO_PAYLOAD-2;
4319 else {
4320 ifr.ifr_hdrprioifr_ifru.ifru_metric = strtonum(val,
4321 IF_HDRPRIO_MIN0, IF_HDRPRIO_MAX8 - 1, &errmsg);
4322 if (errmsg)
4323 errx(1, "tx prio %s: %s", val, errmsg);
4324 }
4325
4326 if (ioctl(sock, SIOCSTXHPRIO((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((197)))
, (caddr_t)&ifr) == -1)
4327 warn("SIOCSTXHPRIO");
4328}
4329
4330void
4331getrxprio(struct ifencap *ife)
4332{
4333 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
4334 sizeof(ifr.ifr_name))
4335 errx(1, "hdr prio: name is too long");
4336
4337 if (ioctl(sock, SIOCGRXHPRIO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((219)))
, (caddr_t)&ifr) == -1)
4338 return;
4339
4340 ife->ife_flags |= IFE_RXHPRIO_SET0x2000;
4341 ife->ife_rxhprio = ifr.ifr_hdrprioifr_ifru.ifru_metric;
4342}
4343
4344void
4345setrxprio(const char *val, int d)
4346{
4347 const char *errmsg = NULL((void *)0);
4348
4349 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
4350 sizeof(ifr.ifr_name))
4351 errx(1, "rx prio: name is too long");
4352
4353 if (strcmp(val, "packet") == 0)
4354 ifr.ifr_hdrprioifr_ifru.ifru_metric = IF_HDRPRIO_PACKET-1;
4355 else if (strcmp(val, "payload") == 0)
4356 ifr.ifr_hdrprioifr_ifru.ifru_metric = IF_HDRPRIO_PAYLOAD-2;
4357 else if (strcmp(val, "outer") == 0)
4358 ifr.ifr_hdrprioifr_ifru.ifru_metric = IF_HDRPRIO_OUTER-3;
4359 else {
4360 ifr.ifr_hdrprioifr_ifru.ifru_metric = strtonum(val,
4361 IF_HDRPRIO_MIN0, IF_HDRPRIO_MAX8 - 1, &errmsg);
4362 if (errmsg)
4363 errx(1, "rx prio %s: %s", val, errmsg);
4364 }
4365
4366 if (ioctl(sock, SIOCSRXHPRIO((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((219)))
, (caddr_t)&ifr) == -1)
4367 warn("SIOCSRXHPRIO");
4368}
4369#endif
4370
4371void
4372getencap(void)
4373{
4374 struct ifencap ife = { .ife_flags = 0 };
4375
4376 getvnetid(&ife);
4377 getvnetflowid(&ife);
4378 getifparent(&ife);
4379#ifndef SMALL
4380 gettxprio(&ife);
4381 getrxprio(&ife);
4382#endif
4383
4384 if (ife.ife_flags == 0)
4385 return;
4386
4387 printf("\tencap:");
4388
4389 switch (ife.ife_flags & IFE_VNETID_MASK0xf) {
4390 case IFE_VNETID_NONE0x1:
4391 printf(" vnetid none");
4392 break;
4393 case IFE_VNETID_ANY0x2:
4394 printf(" vnetid any");
4395 break;
4396 case IFE_VNETID_SET0x3:
4397 printf(" vnetid %lld", ife.ife_vnetid);
4398 if (ife.ife_flags & IFE_VNETFLOWID0x10)
4399 printf("+");
4400 break;
4401 }
4402
4403 switch (ife.ife_flags & IFE_PARENT_MASK0xf00) {
4404 case IFE_PARENT_NONE0x100:
4405 printf(" parent none");
4406 break;
4407 case IFE_PARENT_SET0x200:
4408 printf(" parent %s", ife.ife_parent);
4409 break;
4410 }
4411
4412#ifndef SMALL
4413 if (ife.ife_flags & IFE_TXHPRIO_SET0x1000) {
4414 printf(" txprio ");
4415 switch (ife.ife_txhprio) {
4416 case IF_HDRPRIO_PACKET-1:
4417 printf("packet");
4418 break;
4419 case IF_HDRPRIO_PAYLOAD-2:
4420 printf("payload");
4421 break;
4422 default:
4423 printf("%d", ife.ife_txhprio);
4424 break;
4425 }
4426 }
4427
4428 if (ife.ife_flags & IFE_RXHPRIO_SET0x2000) {
4429 printf(" rxprio ");
4430 switch (ife.ife_rxhprio) {
4431 case IF_HDRPRIO_PACKET-1:
4432 printf("packet");
4433 break;
4434 case IF_HDRPRIO_PAYLOAD-2:
4435 printf("payload");
4436 break;
4437 case IF_HDRPRIO_OUTER-3:
4438 printf("outer");
4439 break;
4440 default:
4441 printf("%d", ife.ife_rxhprio);
4442 break;
4443 }
4444 }
4445#endif
4446
4447 printf("\n");
4448}
4449
4450void
4451settrunkport(const char *val, int d)
4452{
4453 struct trunk_reqport rp;
4454
4455 bzero(&rp, sizeof(rp));
4456 strlcpy(rp.rp_ifname, ifname, sizeof(rp.rp_ifname));
4457 strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
4458
4459 if (ioctl(sock, SIOCSTRUNKPORT((unsigned long)0x80000000 | ((sizeof(struct trunk_reqport) &
0x1fff) << 16) | ((('i')) << 8) | ((141)))
, &rp) == -1)
4460 err(1, "%s %s: SIOCSTRUNKPORT", rp.rp_ifname, rp.rp_portname);
4461}
4462
4463void
4464unsettrunkport(const char *val, int d)
4465{
4466 struct trunk_reqport rp;
4467
4468 bzero(&rp, sizeof(rp));
4469 strlcpy(rp.rp_ifname, ifname, sizeof(rp.rp_ifname));
4470 strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
4471
4472 if (ioctl(sock, SIOCSTRUNKDELPORT((unsigned long)0x80000000 | ((sizeof(struct trunk_reqport) &
0x1fff) << 16) | ((('i')) << 8) | ((142)))
, &rp) == -1)
4473 err(1, "%s: %s: SIOCSTRUNKDELPORT", rp.rp_ifname,
4474 rp.rp_portname);
4475}
4476
4477void
4478settrunkproto(const char *val, int d)
4479{
4480 struct trunk_protos tpr[] = TRUNK_PROTOS{ { "roundrobin", TRUNK_PROTO_ROUNDROBIN }, { "failover", TRUNK_PROTO_FAILOVER
}, { "lacp", TRUNK_PROTO_LACP }, { "loadbalance", TRUNK_PROTO_LOADBALANCE
}, { "broadcast", TRUNK_PROTO_BROADCAST }, { "none", TRUNK_PROTO_NONE
}, { "default", TRUNK_PROTO_ROUNDROBIN } }
;
4481 struct trunk_reqall ra;
4482 int i;
4483
4484 bzero(&ra, sizeof(ra));
4485 ra.ra_proto = TRUNK_PROTO_MAX;
4486
4487 for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) {
4488 if (strcmp(val, tpr[i].tpr_name) == 0) {
4489 ra.ra_proto = tpr[i].tpr_proto;
4490 break;
4491 }
4492 }
4493 if (ra.ra_proto == TRUNK_PROTO_MAX)
4494 errx(1, "Invalid trunk protocol: %s", val);
4495
4496 strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname));
4497 if (ioctl(sock, SIOCSTRUNK((unsigned long)0x80000000 | ((sizeof(struct trunk_reqall) &
0x1fff) << 16) | ((('i')) << 8) | ((144)))
, &ra) != 0)
4498 err(1, "%s: SIOCSTRUNK", ra.ra_ifname);
4499}
4500
4501void
4502settrunklacpmode(const char *val, int d)
4503{
4504 struct trunk_reqall ra;
4505 struct trunk_opts tops;
4506
4507 bzero(&ra, sizeof(ra));
4508 strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname));
4509
4510 if (ioctl(sock, SIOCGTRUNK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct trunk_reqall) & 0x1fff) << 16) | ((('i')) <<
8) | ((143)))
, &ra) != 0)
4511 err(1, "%s: SIOCGTRUNK", ra.ra_ifname);
4512
4513 if (ra.ra_proto != TRUNK_PROTO_LACP)
4514 errx(1, "Invalid option for trunk: %s", ifname);
4515
4516 if (strcmp(val, lacpmodeactive) != 0 &&
4517 strcmp(val, lacpmodepassive) != 0)
4518 errx(1, "Invalid lacpmode option for trunk: %s", ifname);
4519
4520 bzero(&tops, sizeof(tops));
4521 strlcpy(tops.to_ifname, ifname, sizeof(tops.to_ifname));
4522 tops.to_proto = TRUNK_PROTO_LACP;
4523 tops.to_opts |= TRUNK_OPT_LACP_MODE0x01;
4524
4525 if (strcmp(val, lacpmodeactive) == 0)
4526 tops.to_lacpoptsto_psc.rpsc_lacp.lacp_mode = 1;
4527 else
4528 tops.to_lacpoptsto_psc.rpsc_lacp.lacp_mode = 0;
4529
4530 if (ioctl(sock, SIOCSTRUNKOPTS((unsigned long)0x80000000 | ((sizeof(struct trunk_opts) &
0x1fff) << 16) | ((('i')) << 8) | ((146)))
, &tops) != 0)
4531 err(1, "%s: SIOCSTRUNKOPTS", tops.to_ifname);
4532}
4533
4534void
4535settrunklacptimeout(const char *val, int d)
4536{
4537 struct trunk_reqall ra;
4538 struct trunk_opts tops;
4539
4540 bzero(&ra, sizeof(ra));
4541 strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname));
4542
4543 if (ioctl(sock, SIOCGTRUNK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct trunk_reqall) & 0x1fff) << 16) | ((('i')) <<
8) | ((143)))
, &ra) != 0)
4544 err(1, "%s SIOCGTRUNK", ra.ra_ifname);
4545
4546 if (ra.ra_proto != TRUNK_PROTO_LACP)
4547 errx(1, "Invalid option for trunk: %s", ifname);
4548
4549 if (strcmp(val, lacptimeoutfast) != 0 &&
4550 strcmp(val, lacptimeoutslow) != 0)
4551 errx(1, "Invalid lacptimeout option for trunk: %s", ifname);
4552
4553 bzero(&tops, sizeof(tops));
4554 strlcpy(tops.to_ifname, ifname, sizeof(tops.to_ifname));
4555 tops.to_proto = TRUNK_PROTO_LACP;
4556 tops.to_opts |= TRUNK_OPT_LACP_TIMEOUT0x02;
4557
4558 if (strcmp(val, lacptimeoutfast) == 0)
4559 tops.to_lacpoptsto_psc.rpsc_lacp.lacp_timeout = 1;
4560 else
4561 tops.to_lacpoptsto_psc.rpsc_lacp.lacp_timeout = 0;
4562
4563 if (ioctl(sock, SIOCSTRUNKOPTS((unsigned long)0x80000000 | ((sizeof(struct trunk_opts) &
0x1fff) << 16) | ((('i')) << 8) | ((146)))
, &tops) != 0)
4564 err(1, "%s: SIOCSTRUNKOPTS", tops.to_ifname);
4565}
4566
4567void
4568trunk_status(void)
4569{
4570 struct trunk_protos tpr[] = TRUNK_PROTOS{ { "roundrobin", TRUNK_PROTO_ROUNDROBIN }, { "failover", TRUNK_PROTO_FAILOVER
}, { "lacp", TRUNK_PROTO_LACP }, { "loadbalance", TRUNK_PROTO_LOADBALANCE
}, { "broadcast", TRUNK_PROTO_BROADCAST }, { "none", TRUNK_PROTO_NONE
}, { "default", TRUNK_PROTO_ROUNDROBIN } }
;
4571 struct trunk_reqport rp, rpbuf[TRUNK_MAX_PORTS32];
4572 struct trunk_reqall ra;
4573 struct lacp_opreq *lp;
4574 const char *proto = "<unknown>";
4575 int i, isport = 0;
4576
4577 bzero(&rp, sizeof(rp));
4578 bzero(&ra, sizeof(ra));
4579
4580 strlcpy(rp.rp_ifname, ifname, sizeof(rp.rp_ifname));
4581 strlcpy(rp.rp_portname, ifname, sizeof(rp.rp_portname));
4582
4583 if (ioctl(sock, SIOCGTRUNKPORT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct trunk_reqport) & 0x1fff) << 16) | ((('i')) <<
8) | ((140)))
, &rp) == 0)
4584 isport = 1;
4585
4586 strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname));
4587 ra.ra_size = sizeof(rpbuf);
4588 ra.ra_port = rpbuf;
4589
4590 if (ioctl(sock, SIOCGTRUNK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct trunk_reqall) & 0x1fff) << 16) | ((('i')) <<
8) | ((143)))
, &ra) == 0) {
4591 lp = (struct lacp_opreq *)&ra.ra_lacpreqra_psc.rpsc_lacp;
4592
4593 for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) {
4594 if (ra.ra_proto == tpr[i].tpr_proto) {
4595 proto = tpr[i].tpr_name;
4596 break;
4597 }
4598 }
4599
4600 printf("\ttrunk: trunkproto %s", proto);
4601 if (isport)
4602 printf(" trunkdev %s", rp.rp_ifname);
4603 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
4604 if (ra.ra_proto == TRUNK_PROTO_LACP) {
4605 char *act_mac = strdup(
4606 ether_ntoa((struct ether_addr*)lp->actor_mac));
4607 if (act_mac == NULL((void *)0))
4608 err(1, "strdup");
4609 printf("\ttrunk id: [(%04X,%s,%04X,%04X,%04X),\n"
4610 "\t\t (%04X,%s,%04X,%04X,%04X)]\n",
4611 lp->actor_prio, act_mac,
4612 lp->actor_key, lp->actor_portprio, lp->actor_portno,
4613 lp->partner_prio,
4614 ether_ntoa((struct ether_addr*)lp->partner_mac),
4615 lp->partner_key, lp->partner_portprio,
4616 lp->partner_portno);
4617 free(act_mac);
4618 }
4619
4620 for (i = 0; i < ra.ra_ports; i++) {
4621 lp = (struct lacp_opreq *)&(rpbuf[i].rp_lacpreqrp_psc.rpsc_lacp);
4622 if (ra.ra_proto == TRUNK_PROTO_LACP) {
4623 printf("\t\t%s lacp actor "
4624 "system pri 0x%x mac %s, key 0x%x, "
4625 "port pri 0x%x number 0x%x\n",
4626 rpbuf[i].rp_portname,
4627 lp->actor_prio,
4628 ether_ntoa((struct ether_addr*)
4629 lp->actor_mac),
4630 lp->actor_key,
4631 lp->actor_portprio, lp->actor_portno);
4632 printf("\t\t%s lacp actor state ",
4633 rpbuf[i].rp_portname);
4634 printb_status(lp->actor_state,
4635 LACP_STATE_BITS"\020" "\001ACTIVITY" "\002TIMEOUT" "\003AGGREGATION" "\004SYNC"
"\005COLLECTING" "\006DISTRIBUTING" "\007DEFAULTED" "\010EXPIRED"
);
4636 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
4637
4638 printf("\t\t%s lacp partner "
4639 "system pri 0x%x mac %s, key 0x%x, "
4640 "port pri 0x%x number 0x%x\n",
4641 rpbuf[i].rp_portname,
4642 lp->partner_prio,
4643 ether_ntoa((struct ether_addr*)
4644 lp->partner_mac),
4645 lp->partner_key,
4646 lp->partner_portprio, lp->partner_portno);
4647 printf("\t\t%s lacp partner state ",
4648 rpbuf[i].rp_portname);
4649 printb_status(lp->partner_state,
4650 LACP_STATE_BITS"\020" "\001ACTIVITY" "\002TIMEOUT" "\003AGGREGATION" "\004SYNC"
"\005COLLECTING" "\006DISTRIBUTING" "\007DEFAULTED" "\010EXPIRED"
);
4651 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
4652 }
4653
4654 printf("\t\t%s port ", rpbuf[i].rp_portname);
4655 printb_status(rpbuf[i].rp_flags, TRUNK_PORT_BITS"\20\01MASTER\02STACK\03ACTIVE" "\04COLLECTING\05DISTRIBUTING\06DISABLED");
4656 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
4657 }
4658
4659 if (showmediaflag) {
4660 printf("\tsupported trunk protocols:\n");
4661 for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++)
4662 printf("\t\ttrunkproto %s\n", tpr[i].tpr_name);
4663 }
4664 } else if (isport)
4665 printf("\ttrunk: trunkdev %s\n", rp.rp_ifname);
4666}
4667
4668#ifndef SMALL
4669static const char *carp_states[] = { CARP_STATES"INIT", "BACKUP", "MASTER" };
4670static const char *carp_bal_modes[] = { CARP_BAL_MODES"none", "ip", "ip-stealth", "ip-unicast" };
4671
4672void
4673carp_status(void)
4674{
4675 const char *state, *balmode;
4676 struct carpreq carpr;
4677 char peer[32];
4678 int i;
4679
4680 memset((char *)&carpr, 0, sizeof(struct carpreq));
4681 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4682
4683 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4684 return;
4685
4686 if (carpr.carpr_vhids[0] == 0)
4687 return;
4688
4689 if (carpr.carpr_balancing > CARP_BAL_MAXID3)
4690 balmode = "<UNKNOWN>";
4691 else
4692 balmode = carp_bal_modes[carpr.carpr_balancing];
4693
4694 if (carpr.carpr_peer.s_addr != htonl(INADDR_CARP_GROUP)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0xe0000012))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0xe0000012))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0xe0000012))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0xe0000012))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0xe0000012
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0xe0000012))))
)
4695 snprintf(peer, sizeof(peer),
4696 " carppeer %s", inet_ntoa(carpr.carpr_peer));
4697 else
4698 peer[0] = '\0';
4699
4700 for (i = 0; carpr.carpr_vhids[i]; i++) {
4701 if (carpr.carpr_states[i] > CARP_MAXSTATE2)
4702 state = "<UNKNOWN>";
4703 else
4704 state = carp_states[carpr.carpr_states[i]];
4705 if (carpr.carpr_vhids[1] == 0) {
4706 printf("\tcarp: %s carpdev %s vhid %u advbase %d "
4707 "advskew %u%s\n", state,
4708 carpr.carpr_carpdev[0] != '\0' ?
4709 carpr.carpr_carpdev : "none", carpr.carpr_vhids[0],
4710 carpr.carpr_advbase, carpr.carpr_advskews[0],
4711 peer);
4712 } else {
4713 if (i == 0) {
4714 printf("\tcarp: carpdev %s advbase %d"
4715 " balancing %s%s\n",
4716 carpr.carpr_carpdev[0] != '\0' ?
4717 carpr.carpr_carpdev : "none",
4718 carpr.carpr_advbase, balmode, peer);
4719 }
4720 printf("\t\tstate %s vhid %u advskew %u\n", state,
4721 carpr.carpr_vhids[i], carpr.carpr_advskews[i]);
4722 }
4723 }
4724}
4725
4726void
4727setcarp_passwd(const char *val, int d)
4728{
4729 struct carpreq carpr;
4730
4731 bzero(&carpr, sizeof(struct carpreq));
4732 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4733
4734 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4735 err(1, "%s: SIOCGVH", ifr.ifr_name);
4736
4737 bzero(carpr.carpr_key, CARP_KEY_LEN20);
4738 strlcpy((char *)carpr.carpr_key, val, CARP_KEY_LEN20);
4739
4740 if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((245)))
, (caddr_t)&ifr) == -1)
4741 err(1, "%s: SIOCSVH", ifr.ifr_name);
4742}
4743
4744void
4745setcarp_vhid(const char *val, int d)
4746{
4747 const char *errmsg = NULL((void *)0);
4748 struct carpreq carpr;
4749 int vhid;
4750
4751 vhid = strtonum(val, 1, 255, &errmsg);
4752 if (errmsg)
4753 errx(1, "vhid %s: %s", val, errmsg);
4754
4755 bzero(&carpr, sizeof(struct carpreq));
4756 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4757
4758 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4759 err(1, "%s: SIOCGVH", ifr.ifr_name);
4760
4761 carpr.carpr_vhids[0] = vhid;
4762 carpr.carpr_vhids[1] = 0;
4763
4764 if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((245)))
, (caddr_t)&ifr) == -1)
4765 err(1, "%s: SIOCSVH", ifr.ifr_name);
4766}
4767
4768void
4769setcarp_advskew(const char *val, int d)
4770{
4771 const char *errmsg = NULL((void *)0);
4772 struct carpreq carpr;
4773 int advskew;
4774
4775 advskew = strtonum(val, 0, 254, &errmsg);
4776 if (errmsg)
4777 errx(1, "advskew %s: %s", val, errmsg);
4778
4779 bzero(&carpr, sizeof(struct carpreq));
4780 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4781
4782 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4783 err(1, "%s: SIOCGVH", ifr.ifr_name);
4784
4785 carpr.carpr_advskews[0] = advskew;
4786
4787 if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((245)))
, (caddr_t)&ifr) == -1)
4788 err(1, "%s: SIOCSVH", ifr.ifr_name);
4789}
4790
4791void
4792setcarp_advbase(const char *val, int d)
4793{
4794 const char *errmsg = NULL((void *)0);
4795 struct carpreq carpr;
4796 int advbase;
4797
4798 advbase = strtonum(val, 0, 254, &errmsg);
4799 if (errmsg)
4800 errx(1, "advbase %s: %s", val, errmsg);
4801
4802 bzero(&carpr, sizeof(struct carpreq));
4803 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4804
4805 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4806 err(1, "%s: SIOCGVH", ifr.ifr_name);
4807
4808 carpr.carpr_advbase = advbase;
4809
4810 if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((245)))
, (caddr_t)&ifr) == -1)
4811 err(1, "%s: SIOCSVH", ifr.ifr_name);
4812}
4813
4814void
4815setcarppeer(const char *val, int d)
4816{
4817 struct carpreq carpr;
4818 struct addrinfo hints, *peerres;
4819 int ecode;
4820
4821 bzero(&carpr, sizeof(struct carpreq));
4822 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4823
4824 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4825 err(1, "%s: SIOCGVH", ifr.ifr_name);
4826
4827 bzero(&hints, sizeof(hints));
4828 hints.ai_family = AF_INET2;
4829 hints.ai_socktype = SOCK_DGRAM2;
4830
4831 if ((ecode = getaddrinfo(val, NULL((void *)0), &hints, &peerres)) != 0)
4832 errx(1, "error in parsing address string: %s",
4833 gai_strerror(ecode));
4834
4835 if (peerres->ai_addr->sa_family != AF_INET2)
4836 errx(1, "only IPv4 addresses supported for the carppeer");
4837
4838 carpr.carpr_peer.s_addr = ((struct sockaddr_in *)
4839 peerres->ai_addr)->sin_addr.s_addr;
4840
4841 if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((245)))
, (caddr_t)&ifr) == -1)
4842 err(1, "%s: SIOCSVH", ifr.ifr_name);
4843
4844 freeaddrinfo(peerres);
4845}
4846
4847void
4848unsetcarppeer(const char *val, int d)
4849{
4850 struct carpreq carpr;
4851
4852 bzero(&carpr, sizeof(struct carpreq));
4853 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4854
4855 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4856 err(1, "%s: SIOCGVH", ifr.ifr_name);
4857
4858 bzero(&carpr.carpr_peer, sizeof(carpr.carpr_peer));
4859
4860 if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((245)))
, (caddr_t)&ifr) == -1)
4861 err(1, "%s: SIOCSVH", ifr.ifr_name);
4862}
4863
4864void
4865setcarp_state(const char *val, int d)
4866{
4867 struct carpreq carpr;
4868 int i;
4869
4870 bzero(&carpr, sizeof(struct carpreq));
4871 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4872
4873 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4874 err(1, "%s: SIOCGVH", ifr.ifr_name);
4875
4876 for (i = 0; i <= CARP_MAXSTATE2; i++) {
4877 if (!strcasecmp(val, carp_states[i])) {
4878 carpr.carpr_state = i;
4879 break;
4880 }
4881 }
4882
4883 if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((245)))
, (caddr_t)&ifr) == -1)
4884 err(1, "%s: SIOCSVH", ifr.ifr_name);
4885}
4886
4887void
4888setcarpdev(const char *val, int d)
4889{
4890 struct carpreq carpr;
4891
4892 bzero(&carpr, sizeof(struct carpreq));
4893 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4894
4895 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4896 err(1, "%s: SIOCGVH", ifr.ifr_name);
4897
4898 strlcpy(carpr.carpr_carpdev, val, sizeof(carpr.carpr_carpdev));
4899
4900 if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((245)))
, (caddr_t)&ifr) == -1)
4901 err(1, "%s: SIOCSVH", ifr.ifr_name);
4902}
4903
4904void
4905setcarp_nodes(const char *val, int d)
4906{
4907 char *optlist, *str;
4908 int i;
4909 struct carpreq carpr;
4910
4911 bzero(&carpr, sizeof(struct carpreq));
4912 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4913
4914 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4915 err(1, "%s: SIOCGVH", ifr.ifr_name);
4916
4917 bzero(carpr.carpr_vhids, sizeof(carpr.carpr_vhids));
4918 bzero(carpr.carpr_advskews, sizeof(carpr.carpr_advskews));
4919
4920 optlist = strdup(val);
4921 if (optlist == NULL((void *)0))
4922 err(1, "strdup");
4923
4924 str = strtok(optlist, ",");
4925 for (i = 0; str != NULL((void *)0); i++) {
4926 u_int vhid, advskew;
4927
4928 if (i >= CARP_MAXNODES32)
4929 errx(1, "too many carp nodes");
4930 if (sscanf(str, "%u:%u", &vhid, &advskew) != 2) {
4931 errx(1, "non parsable arg: %s", str);
4932 }
4933 if (vhid > 255)
4934 errx(1, "vhid %u: value too large", vhid);
4935 if (advskew >= 255)
4936 errx(1, "advskew %u: value too large", advskew);
4937
4938 carpr.carpr_vhids[i] = vhid;
4939 carpr.carpr_advskews[i] = advskew;
4940 str = strtok(NULL((void *)0), ",");
4941 }
4942 free(optlist);
4943
4944 if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((245)))
, (caddr_t)&ifr) == -1)
4945 err(1, "%s: SIOCSVH", ifr.ifr_name);
4946}
4947
4948void
4949setcarp_balancing(const char *val, int d)
4950{
4951 int i;
4952 struct carpreq carpr;
4953
4954 bzero(&carpr, sizeof(struct carpreq));
4955 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr;
4956
4957 if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((246)))
, (caddr_t)&ifr) == -1)
4958 err(1, "%s: SIOCGVH", ifr.ifr_name);
4959
4960 for (i = 0; i <= CARP_BAL_MAXID3; i++)
4961 if (!strcasecmp(val, carp_bal_modes[i]))
4962 break;
4963
4964 if (i > CARP_BAL_MAXID3)
4965 errx(1, "balancing %s: unknown mode", val);
4966
4967 carpr.carpr_balancing = i;
4968
4969 if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((245)))
, (caddr_t)&ifr) == -1)
4970 err(1, "%s: SIOCSVH", ifr.ifr_name);
4971}
4972
4973void
4974setpfsync_syncdev(const char *val, int d)
4975{
4976 struct pfsyncreq preq;
4977
4978 bzero(&preq, sizeof(struct pfsyncreq));
4979 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
4980
4981 if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((248)))
, (caddr_t)&ifr) == -1)
4982 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name);
4983
4984 strlcpy(preq.pfsyncr_syncdev, val, sizeof(preq.pfsyncr_syncdev));
4985
4986 if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((247)))
, (caddr_t)&ifr) == -1)
4987 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name);
4988}
4989
4990void
4991unsetpfsync_syncdev(const char *val, int d)
4992{
4993 struct pfsyncreq preq;
4994
4995 bzero(&preq, sizeof(struct pfsyncreq));
4996 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
4997
4998 if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((248)))
, (caddr_t)&ifr) == -1)
4999 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name);
5000
5001 bzero(&preq.pfsyncr_syncdev, sizeof(preq.pfsyncr_syncdev));
5002
5003 if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((247)))
, (caddr_t)&ifr) == -1)
5004 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name);
5005}
5006
5007void
5008setpfsync_syncpeer(const char *val, int d)
5009{
5010 struct pfsyncreq preq;
5011 struct addrinfo hints, *peerres;
5012 int ecode;
5013
5014 bzero(&preq, sizeof(struct pfsyncreq));
5015 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5016
5017 if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((248)))
, (caddr_t)&ifr) == -1)
5018 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name);
5019
5020 memset(&hints, 0, sizeof(hints));
5021 hints.ai_family = AF_INET2;
5022 hints.ai_socktype = SOCK_DGRAM2; /*dummy*/
5023
5024 if ((ecode = getaddrinfo(val, NULL((void *)0), &hints, &peerres)) != 0)
5025 errx(1, "error in parsing address string: %s",
5026 gai_strerror(ecode));
5027
5028 if (peerres->ai_addr->sa_family != AF_INET2)
5029 errx(1, "only IPv4 addresses supported for the syncpeer");
5030
5031 preq.pfsyncr_syncpeer.s_addr = ((struct sockaddr_in *)
5032 peerres->ai_addr)->sin_addr.s_addr;
5033
5034 if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((247)))
, (caddr_t)&ifr) == -1)
5035 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name);
5036
5037 freeaddrinfo(peerres);
5038}
5039
5040void
5041unsetpfsync_syncpeer(const char *val, int d)
5042{
5043 struct pfsyncreq preq;
5044
5045 bzero(&preq, sizeof(struct pfsyncreq));
5046 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5047
5048 if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((248)))
, (caddr_t)&ifr) == -1)
5049 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name);
5050
5051 preq.pfsyncr_syncpeer.s_addr = 0;
5052
5053 if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((247)))
, (caddr_t)&ifr) == -1)
5054 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name);
5055}
5056
5057void
5058setpfsync_maxupd(const char *val, int d)
5059{
5060 const char *errmsg = NULL((void *)0);
5061 struct pfsyncreq preq;
5062 int maxupdates;
5063
5064 maxupdates = strtonum(val, 0, 255, &errmsg);
5065 if (errmsg)
5066 errx(1, "maxupd %s: %s", val, errmsg);
5067
5068 bzero(&preq, sizeof(struct pfsyncreq));
5069 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5070
5071 if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((248)))
, (caddr_t)&ifr) == -1)
5072 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name);
5073
5074 preq.pfsyncr_maxupdates = maxupdates;
5075
5076 if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((247)))
, (caddr_t)&ifr) == -1)
5077 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name);
5078}
5079
5080void
5081setpfsync_defer(const char *val, int d)
5082{
5083 struct pfsyncreq preq;
5084
5085 bzero(&preq, sizeof(struct pfsyncreq));
5086 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5087
5088 if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((248)))
, (caddr_t)&ifr) == -1)
5089 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name);
5090
5091 preq.pfsyncr_defer = d;
5092 if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((247)))
, (caddr_t)&ifr) == -1)
5093 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name);
5094}
5095
5096void
5097pfsync_status(void)
5098{
5099 struct pfsyncreq preq;
5100
5101 bzero(&preq, sizeof(struct pfsyncreq));
5102 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5103
5104 if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((248)))
, (caddr_t)&ifr) == -1)
5105 return;
5106
5107 if (preq.pfsyncr_syncdev[0] != '\0') {
5108 printf("\tpfsync: syncdev: %s ", preq.pfsyncr_syncdev);
5109 if (preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0xe00000f0))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0xe00000f0))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0xe00000f0))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0xe00000f0))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0xe00000f0
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0xe00000f0))))
)
5110 printf("syncpeer: %s ",
5111 inet_ntoa(preq.pfsyncr_syncpeer));
5112 printf("maxupd: %d ", preq.pfsyncr_maxupdates);
5113 printf("defer: %s\n", preq.pfsyncr_defer ? "on" : "off");
5114 }
5115}
5116
5117void
5118pflow_status(void)
5119{
5120 struct pflowreq preq;
5121 struct sockaddr_in *sin;
5122 struct sockaddr_in6 *sin6;
5123 int error;
5124 char buf[INET6_ADDRSTRLEN46];
5125
5126 bzero(&preq, sizeof(struct pflowreq));
5127 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5128
5129 if (ioctl(sock, SIOCGETPFLOW(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((254)))
, (caddr_t)&ifr) == -1)
5130 return;
5131
5132 if (preq.flowsrc.ss_family == AF_INET2 || preq.flowsrc.ss_family ==
5133 AF_INET624) {
5134 error = getnameinfo((struct sockaddr*)&preq.flowsrc,
5135 preq.flowsrc.ss_len, buf, sizeof(buf), NULL((void *)0), 0,
5136 NI_NUMERICHOST1);
5137 if (error)
5138 err(1, "sender: %s", gai_strerror(error));
5139 }
5140
5141 printf("\tpflow: ");
5142 switch (preq.flowsrc.ss_family) {
5143 case AF_INET2:
5144 sin = (struct sockaddr_in*) &preq.flowsrc;
5145 if (sin->sin_addr.s_addr != INADDR_ANY((u_int32_t)(0x00000000))) {
5146 printf("sender: %s", buf);
5147 if (sin->sin_port != 0)
5148 printf(":%u", ntohs(sin->sin_port)(__uint16_t)(__builtin_constant_p(sin->sin_port) ? (__uint16_t
)(((__uint16_t)(sin->sin_port) & 0xffU) << 8 | (
(__uint16_t)(sin->sin_port) & 0xff00U) >> 8) : __swap16md
(sin->sin_port))
);
5149 printf(" ");
5150 }
5151 break;
5152 case AF_INET624:
5153 sin6 = (struct sockaddr_in6*) &preq.flowsrc;
5154 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&sin6->sin6_addr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&sin6->sin6_addr)->__u6_addr.__u6_addr8[8
]) == 0) && (*(const u_int32_t *)(const void *)(&
(&sin6->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0)
)
) {
5155 printf("sender: [%s]", buf);
5156 if (sin6->sin6_port != 0)
5157 printf(":%u", ntohs(sin6->sin6_port)(__uint16_t)(__builtin_constant_p(sin6->sin6_port) ? (__uint16_t
)(((__uint16_t)(sin6->sin6_port) & 0xffU) << 8 |
((__uint16_t)(sin6->sin6_port) & 0xff00U) >> 8)
: __swap16md(sin6->sin6_port))
);
5158 printf(" ");
5159 }
5160 default:
5161 break;
5162 }
5163 if (preq.flowdst.ss_family == AF_INET2 || preq.flowdst.ss_family ==
5164 AF_INET624) {
5165 error = getnameinfo((struct sockaddr*)&preq.flowdst,
5166 preq.flowdst.ss_len, buf, sizeof(buf), NULL((void *)0), 0,
5167 NI_NUMERICHOST1);
5168 if (error)
5169 err(1, "receiver: %s", gai_strerror(error));
5170 }
5171 switch (preq.flowdst.ss_family) {
5172 case AF_INET2:
5173 sin = (struct sockaddr_in*)&preq.flowdst;
5174 printf("receiver: %s:", sin->sin_addr.s_addr != INADDR_ANY((u_int32_t)(0x00000000)) ?
5175 buf : "INVALID");
5176 if (sin->sin_port == 0)
5177 printf("%s ", "INVALID");
5178 else
5179 printf("%u ", ntohs(sin->sin_port)(__uint16_t)(__builtin_constant_p(sin->sin_port) ? (__uint16_t
)(((__uint16_t)(sin->sin_port) & 0xffU) << 8 | (
(__uint16_t)(sin->sin_port) & 0xff00U) >> 8) : __swap16md
(sin->sin_port))
);
5180 break;
5181 case AF_INET624:
5182 sin6 = (struct sockaddr_in6*) &preq.flowdst;
5183 printf("receiver: [%s]:",
5184 !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&sin6->sin6_addr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&sin6->sin6_addr)->__u6_addr.__u6_addr8[8
]) == 0) && (*(const u_int32_t *)(const void *)(&
(&sin6->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0)
)
? buf :
5185 "INVALID");
5186 if (sin6->sin6_port == 0)
5187 printf("%s ", "INVALID");
5188 else
5189 printf("%u ", ntohs(sin6->sin6_port)(__uint16_t)(__builtin_constant_p(sin6->sin6_port) ? (__uint16_t
)(((__uint16_t)(sin6->sin6_port) & 0xffU) << 8 |
((__uint16_t)(sin6->sin6_port) & 0xff00U) >> 8)
: __swap16md(sin6->sin6_port))
);
5190 break;
5191 default:
5192 printf("receiver: INVALID:INVALID ");
5193 break;
5194 }
5195 printf("version: %d\n", preq.version);
5196}
5197
5198void
5199pflow_addr(const char *val, struct sockaddr_storage *ss) {
5200 struct addrinfo hints, *res0;
5201 int error, flag;
5202 char *cp, *ip, *port, buf[HOST_NAME_MAX255+1 + sizeof (":65535")];
5203
5204 if (strlcpy(buf, val, sizeof(buf)) >= sizeof(buf))
5205 errx(1, "%s bad value", val);
5206
5207 port = NULL((void *)0);
5208 cp = buf;
5209 if (*cp == '[')
5210 flag = 1;
5211 else
5212 flag = 0;
5213
5214 for(; *cp; ++cp) {
5215 if (*cp == ']' && *(cp + 1) == ':' && flag) {
5216 *cp = '\0';
5217 *(cp + 1) = '\0';
5218 port = cp + 2;
5219 break;
5220 }
5221 if (*cp == ']' && *(cp + 1) == '\0' && flag) {
5222 *cp = '\0';
5223 port = NULL((void *)0);
5224 break;
5225 }
5226 if (*cp == ':' && !flag) {
5227 *cp = '\0';
5228 port = cp + 1;
5229 break;
5230 }
5231 }
5232
5233 ip = buf;
5234 if (flag)
5235 ip++;
5236
5237 bzero(&hints, sizeof(hints));
5238 hints.ai_family = AF_UNSPEC0;
5239 hints.ai_socktype = SOCK_DGRAM2; /*dummy*/
5240 hints.ai_flags = AI_NUMERICHOST4;
5241
5242 if ((error = getaddrinfo(ip, port, &hints, &res0)) != 0)
5243 errx(1, "error in parsing address string: %s",
5244 gai_strerror(error));
5245
5246 memcpy(ss, res0->ai_addr, res0->ai_addr->sa_len);
5247 freeaddrinfo(res0);
5248}
5249
5250void
5251setpflow_sender(const char *val, int d)
5252{
5253 struct pflowreq preq;
5254
5255 bzero(&preq, sizeof(struct pflowreq));
5256 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5257 preq.addrmask |= PFLOW_MASK_SRCIP0x01;
5258 pflow_addr(val, &preq.flowsrc);
5259
5260 if (ioctl(sock, SIOCSETPFLOW((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((253)))
, (caddr_t)&ifr) == -1)
5261 err(1, "%s: SIOCSETPFLOW", ifr.ifr_name);
5262}
5263
5264void
5265unsetpflow_sender(const char *val, int d)
5266{
5267 struct pflowreq preq;
5268
5269 bzero(&preq, sizeof(struct pflowreq));
5270 preq.addrmask |= PFLOW_MASK_SRCIP0x01;
5271 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5272 if (ioctl(sock, SIOCSETPFLOW((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((253)))
, (caddr_t)&ifr) == -1)
5273 err(1, "%s: SIOCSETPFLOW", ifr.ifr_name);
5274}
5275
5276void
5277setpflow_receiver(const char *val, int d)
5278{
5279 struct pflowreq preq;
5280
5281 bzero(&preq, sizeof(struct pflowreq));
5282 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5283 preq.addrmask |= PFLOW_MASK_DSTIP0x02;
5284 pflow_addr(val, &preq.flowdst);
5285
5286 if (ioctl(sock, SIOCSETPFLOW((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((253)))
, (caddr_t)&ifr) == -1)
5287 err(1, "%s: SIOCSETPFLOW", ifr.ifr_name);
5288}
5289
5290void
5291unsetpflow_receiver(const char *val, int d)
5292{
5293 struct pflowreq preq;
5294
5295 bzero(&preq, sizeof(struct pflowreq));
5296 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5297 preq.addrmask |= PFLOW_MASK_DSTIP0x02;
5298 if (ioctl(sock, SIOCSETPFLOW((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((253)))
, (caddr_t)&ifr) == -1)
5299 err(1, "%s: SIOCSETPFLOW", ifr.ifr_name);
5300}
5301
5302/* PFLOWPROTO XXX */
5303void
5304setpflowproto(const char *val, int d)
5305{
5306 struct pflow_protos ppr[] = PFLOW_PROTOS{ { "5", 5 }, { "10", 10 }, };
5307 struct pflowreq preq;
5308 int i;
5309
5310 bzero(&preq, sizeof(preq));
5311 preq.version = PFLOW_PROTO_MAX11;
5312
5313 for (i = 0; i < (sizeof(ppr) / sizeof(ppr[0])); i++) {
5314 if (strcmp(val, ppr[i].ppr_name) == 0) {
5315 preq.version = ppr[i].ppr_proto;
5316 break;
5317 }
5318 }
5319 if (preq.version == PFLOW_PROTO_MAX11)
5320 errx(1, "Invalid pflow protocol: %s", val);
5321
5322 preq.addrmask |= PFLOW_MASK_VERSION0x04;
5323
5324 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq;
5325
5326 if (ioctl(sock, SIOCSETPFLOW((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((253)))
, (caddr_t)&ifr) == -1)
5327 err(1, "%s: SIOCSETPFLOW", ifr.ifr_name);
5328}
5329
5330void
5331pppoe_status(void)
5332{
5333 struct pppoediscparms parms;
5334 struct pppoeconnectionstate state;
5335
5336 memset(&state, 0, sizeof(state));
5337
5338 strlcpy(parms.ifname, ifname, sizeof(parms.ifname));
5339 if (ioctl(sock, PPPOEGETPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pppoediscparms) & 0x1fff) << 16) | ((('i'))
<< 8) | ((111)))
, &parms) == -1)
5340 return;
5341
5342 printf("\tdev: %s ", parms.eth_ifname);
5343
5344 if (*parms.ac_name)
5345 printf("ac: %s ", parms.ac_name);
5346 if (*parms.service_name)
5347 printf("svc: %s ", parms.service_name);
5348
5349 strlcpy(state.ifname, ifname, sizeof(state.ifname));
5350 if (ioctl(sock, PPPOEGETSESSION(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pppoeconnectionstate) & 0x1fff) << 16) | ((
('i')) << 8) | ((112)))
, &state) == -1)
5351 err(1, "PPPOEGETSESSION");
5352
5353 printf("state: ");
5354 switch (state.state) {
5355 case PPPOE_STATE_INITIAL0:
5356 printf("initial"); break;
5357 case PPPOE_STATE_PADI_SENT1:
5358 printf("PADI sent"); break;
5359 case PPPOE_STATE_PADR_SENT2:
5360 printf("PADR sent"); break;
5361 case PPPOE_STATE_SESSION3:
5362 printf("session"); break;
5363 case PPPOE_STATE_CLOSING4:
5364 printf("closing"); break;
5365 }
5366 printf("\n\tsid: 0x%x", state.session_id);
5367 printf(" PADI retries: %d", state.padi_retry_no);
5368 printf(" PADR retries: %d", state.padr_retry_no);
5369
5370 if (state.state == PPPOE_STATE_SESSION3) {
5371 struct timespec temp_time;
5372 time_t diff_time, day = 0;
5373 unsigned int hour = 0, min = 0, sec = 0;
5374
5375 if (state.session_time.tv_sec != 0) {
5376 if (clock_gettime(CLOCK_BOOTTIME6, &temp_time) == -1)
5377 goto notime;
5378 diff_time = temp_time.tv_sec -
5379 state.session_time.tv_sec;
5380
5381 day = diff_time / (60 * 60 * 24);
5382 diff_time %= (60 * 60 * 24);
5383
5384 hour = diff_time / (60 * 60);
5385 diff_time %= (60 * 60);
5386
5387 min = diff_time / 60;
5388 diff_time %= 60;
5389
5390 sec = diff_time;
5391 }
5392 printf(" time: ");
5393 if (day != 0)
5394 printf("%lldd ", (long long)day);
5395 printf("%02u:%02u:%02u", hour, min, sec);
5396 }
5397notime:
5398 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
5399}
5400
5401void
5402setpppoe_dev(const char *val, int d)
5403{
5404 struct pppoediscparms parms;
5405
5406 strlcpy(parms.ifname, ifname, sizeof(parms.ifname));
5407 if (ioctl(sock, PPPOEGETPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pppoediscparms) & 0x1fff) << 16) | ((('i'))
<< 8) | ((111)))
, &parms) == -1)
5408 return;
5409
5410 strlcpy(parms.eth_ifname, val, sizeof(parms.eth_ifname));
5411
5412 if (ioctl(sock, PPPOESETPARMS((unsigned long)0x80000000 | ((sizeof(struct pppoediscparms) &
0x1fff) << 16) | ((('i')) << 8) | ((110)))
, &parms) == -1)
5413 err(1, "PPPOESETPARMS");
5414}
5415
5416void
5417setpppoe_svc(const char *val, int d)
5418{
5419 struct pppoediscparms parms;
5420
5421 strlcpy(parms.ifname, ifname, sizeof(parms.ifname));
5422 if (ioctl(sock, PPPOEGETPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pppoediscparms) & 0x1fff) << 16) | ((('i'))
<< 8) | ((111)))
, &parms) == -1)
5423 return;
5424
5425 if (d == 0)
5426 strlcpy(parms.service_name, val, sizeof(parms.service_name));
5427 else
5428 memset(parms.service_name, 0, sizeof(parms.service_name));
5429
5430 if (ioctl(sock, PPPOESETPARMS((unsigned long)0x80000000 | ((sizeof(struct pppoediscparms) &
0x1fff) << 16) | ((('i')) << 8) | ((110)))
, &parms) == -1)
5431 err(1, "PPPOESETPARMS");
5432}
5433
5434void
5435setpppoe_ac(const char *val, int d)
5436{
5437 struct pppoediscparms parms;
5438
5439 strlcpy(parms.ifname, ifname, sizeof(parms.ifname));
5440 if (ioctl(sock, PPPOEGETPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pppoediscparms) & 0x1fff) << 16) | ((('i'))
<< 8) | ((111)))
, &parms) == -1)
5441 return;
5442
5443 if (d == 0)
5444 strlcpy(parms.ac_name, val, sizeof(parms.ac_name));
5445 else
5446 memset(parms.ac_name, 0, sizeof(parms.ac_name));
5447
5448 if (ioctl(sock, PPPOESETPARMS((unsigned long)0x80000000 | ((sizeof(struct pppoediscparms) &
0x1fff) << 16) | ((('i')) << 8) | ((110)))
, &parms) == -1)
5449 err(1, "PPPOESETPARMS");
5450}
5451
5452void
5453spppauthinfo(struct sauthreq *spa, int d)
5454{
5455 bzero(spa, sizeof(struct sauthreq));
5456
5457 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)spa;
5458 spa->cmd = d == 0 ? SPPPIOGMAUTH((int)(('S' << 24) + (3 << 16) + sizeof(struct sauthreq
)))
: SPPPIOGHAUTH((int)(('S' << 24) + (5 << 16) + sizeof(struct sauthreq
)))
;
5459 if (ioctl(sock, SIOCGSPPPPARAMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((148)))
, &ifr) == -1)
5460 err(1, "%s: SIOCGSPPPPARAMS(SPPPIOGXAUTH)", ifr.ifr_name);
5461}
5462
5463void
5464spppdnsinfo(struct sdnsreq *spd)
5465{
5466 memset(spd, 0, sizeof(*spd));
5467
5468 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)spd;
5469 spd->cmd = SPPPIOGDNS((int)(('S' << 24) + (7 << 16) + sizeof(struct sdnsreq
)))
;
5470 if (ioctl(sock, SIOCGSPPPPARAMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((148)))
, &ifr) == -1)
5471 err(1, "%s: SIOCGSPPPPARAMS(SPPPIOGDNS)", ifr.ifr_name);
5472}
5473
5474void
5475setspppproto(const char *val, int d)
5476{
5477 struct sauthreq spa;
5478
5479 spppauthinfo(&spa, d);
5480
5481 if (strcmp(val, "pap") == 0)
5482 spa.proto = PPP_PAP0xc023;
5483 else if (strcmp(val, "chap") == 0)
5484 spa.proto = PPP_CHAP0xc223;
5485 else if (strcmp(val, "none") == 0)
5486 spa.proto = 0;
5487 else
5488 errx(1, "setpppproto");
5489
5490 spa.cmd = d == 0 ? SPPPIOSMAUTH((int)(('S' << 24) + (4 << 16) + sizeof(struct sauthreq
)))
: SPPPIOSHAUTH((int)(('S' << 24) + (6 << 16) + sizeof(struct sauthreq
)))
;
5491 if (ioctl(sock, SIOCSSPPPPARAMS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((147)))
, &ifr) == -1)
5492 err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name);
5493}
5494
5495void
5496setsppppeerproto(const char *val, int d)
5497{
5498 setspppproto(val, 1);
5499}
5500
5501void
5502setspppname(const char *val, int d)
5503{
5504 struct sauthreq spa;
5505
5506 spppauthinfo(&spa, d);
5507
5508 if (spa.proto == 0)
5509 errx(1, "unspecified protocol");
5510 if (strlcpy(spa.name, val, sizeof(spa.name)) >= sizeof(spa.name))
5511 errx(1, "setspppname");
5512
5513 spa.cmd = d == 0 ? SPPPIOSMAUTH((int)(('S' << 24) + (4 << 16) + sizeof(struct sauthreq
)))
: SPPPIOSHAUTH((int)(('S' << 24) + (6 << 16) + sizeof(struct sauthreq
)))
;
5514 if (ioctl(sock, SIOCSSPPPPARAMS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((147)))
, &ifr) == -1)
5515 err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name);
5516}
5517
5518void
5519setsppppeername(const char *val, int d)
5520{
5521 setspppname(val, 1);
5522}
5523
5524void
5525setspppkey(const char *val, int d)
5526{
5527 struct sauthreq spa;
5528
5529 spppauthinfo(&spa, d);
5530
5531 if (spa.proto == 0)
5532 errx(1, "unspecified protocol");
5533 if (strlcpy(spa.secret, val, sizeof(spa.secret)) >= sizeof(spa.secret))
5534 errx(1, "setspppkey");
5535
5536 spa.cmd = d == 0 ? SPPPIOSMAUTH((int)(('S' << 24) + (4 << 16) + sizeof(struct sauthreq
)))
: SPPPIOSHAUTH((int)(('S' << 24) + (6 << 16) + sizeof(struct sauthreq
)))
;
5537 if (ioctl(sock, SIOCSSPPPPARAMS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((147)))
, &ifr) == -1)
5538 err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name);
5539}
5540
5541void
5542setsppppeerkey(const char *val, int d)
5543{
5544 setspppkey(val, 1);
5545}
5546
5547void
5548setsppppeerflag(const char *val, int d)
5549{
5550 struct sauthreq spa;
5551 int flag;
5552
5553 spppauthinfo(&spa, 1);
5554
5555 if (spa.proto == 0)
5556 errx(1, "unspecified protocol");
5557 if (strcmp(val, "callin") == 0)
5558 flag = AUTHFLAG_NOCALLOUT1;
5559 else if (strcmp(val, "norechallenge") == 0)
5560 flag = AUTHFLAG_NORECHALLENGE2;
5561 else
5562 errx(1, "setppppeerflags");
5563
5564 if (d)
5565 spa.flags &= ~flag;
5566 else
5567 spa.flags |= flag;
5568
5569 spa.cmd = SPPPIOSHAUTH((int)(('S' << 24) + (6 << 16) + sizeof(struct sauthreq
)))
;
5570 if (ioctl(sock, SIOCSSPPPPARAMS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((147)))
, &ifr) == -1)
5571 err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name);
5572}
5573
5574void
5575unsetsppppeerflag(const char *val, int d)
5576{
5577 setsppppeerflag(val, 1);
5578}
5579
5580void
5581sppp_printproto(const char *name, struct sauthreq *auth)
5582{
5583 if (auth->proto == 0)
5584 return;
5585 printf("%sproto ", name);
5586 switch (auth->proto) {
5587 case PPP_PAP0xc023:
5588 printf("pap ");
5589 break;
5590 case PPP_CHAP0xc223:
5591 printf("chap ");
5592 break;
5593 default:
5594 printf("0x%04x ", auth->proto);
5595 break;
5596 }
5597 if (auth->name[0])
5598 printf("%sname \"%s\" ", name, auth->name);
5599 if (auth->secret[0])
5600 printf("%skey \"%s\" ", name, auth->secret);
5601}
5602
5603void
5604sppp_status(void)
5605{
5606 struct spppreq spr;
5607 struct sauthreq spa;
5608 struct sdnsreq spd;
5609 char astr[INET_ADDRSTRLEN16];
5610 int i, n;
5611
5612 bzero(&spr, sizeof(spr));
5613
5614 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&spr;
5615 spr.cmd = SPPPIOGDEFS((int)(('S' << 24) + (1 << 16) + sizeof(struct spppreq
)))
;
5616 if (ioctl(sock, SIOCGSPPPPARAMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((148)))
, &ifr) == -1) {
5617 return;
5618 }
5619
5620 if (spr.phase == PHASE_DEAD)
5621 return;
5622 printf("\tsppp: phase ");
5623 switch (spr.phase) {
5624 case PHASE_ESTABLISH:
5625 printf("establish ");
5626 break;
5627 case PHASE_TERMINATE:
5628 printf("terminate ");
5629 break;
5630 case PHASE_AUTHENTICATE:
5631 printf("authenticate ");
5632 break;
5633 case PHASE_NETWORK:
5634 printf("network ");
5635 break;
5636 default:
5637 printf("illegal ");
5638 break;
5639 }
5640
5641 spppauthinfo(&spa, 0);
5642 sppp_printproto("auth", &spa);
5643 spppauthinfo(&spa, 1);
5644 sppp_printproto("peer", &spa);
5645 if (spa.flags & AUTHFLAG_NOCALLOUT1)
5646 printf("callin ");
5647 if (spa.flags & AUTHFLAG_NORECHALLENGE2)
5648 printf("norechallenge ");
5649 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
5650
5651 spppdnsinfo(&spd);
5652 for (i = 0, n = 0; i < IPCP_MAX_DNSSRV2; i++) {
5653 if (spd.dns[i].s_addr == INADDR_ANY((u_int32_t)(0x00000000)))
5654 break;
5655 printf("%s %s", n++ ? "" : "\tdns:",
5656 inet_ntop(AF_INET2, &spd.dns[i], astr, sizeof(astr)));
5657 }
5658 if (n)
5659 printf("\n");
5660}
5661
5662void
5663setkeepalive(const char *timeout, const char *count)
5664{
5665 const char *errmsg = NULL((void *)0);
5666 struct ifkalivereq ikar;
5667 int t, c;
5668
5669 t = strtonum(timeout, 1, 3600, &errmsg);
5670 if (errmsg)
5671 errx(1, "keepalive period %s: %s", timeout, errmsg);
5672 c = strtonum(count, 2, 600, &errmsg);
5673 if (errmsg)
5674 errx(1, "keepalive count %s: %s", count, errmsg);
5675
5676 strlcpy(ikar.ikar_name, ifname, sizeof(ikar.ikar_name));
5677 ikar.ikar_timeo = t;
5678 ikar.ikar_cnt = c;
5679 if (ioctl(sock, SIOCSETKALIVE((unsigned long)0x80000000 | ((sizeof(struct ifkalivereq) &
0x1fff) << 16) | ((('i')) << 8) | ((163)))
, (caddr_t)&ikar) == -1)
5680 warn("SIOCSETKALIVE");
5681}
5682
5683void
5684unsetkeepalive(const char *val, int d)
5685{
5686 struct ifkalivereq ikar;
5687
5688 bzero(&ikar, sizeof(ikar));
5689 strlcpy(ikar.ikar_name, ifname, sizeof(ikar.ikar_name));
5690 if (ioctl(sock, SIOCSETKALIVE((unsigned long)0x80000000 | ((sizeof(struct ifkalivereq) &
0x1fff) << 16) | ((('i')) << 8) | ((163)))
, (caddr_t)&ikar) == -1)
5691 warn("SIOCSETKALIVE");
5692}
5693
5694void
5695setifpriority(const char *id, int param)
5696{
5697 const char *errmsg = NULL((void *)0);
5698 int prio;
5699
5700 prio = strtonum(id, 0, 15, &errmsg);
5701 if (errmsg)
5702 errx(1, "priority %s: %s", id, errmsg);
5703
5704 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
5705 ifr.ifr_metricifr_ifru.ifru_metric = prio;
5706 if (ioctl(sock, SIOCSIFPRIORITY((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((155)))
, (caddr_t)&ifr) == -1)
5707 warn("SIOCSIFPRIORITY");
5708}
5709
5710/*
5711 * WireGuard configuration
5712 *
5713 * WG_BASE64_KEY_LEN specifies the size of a base64 encoded WireGuard key.
5714 * WG_TMP_KEY_LEN specifies the size of a decoded base64 key. For every 4
5715 * input (base64) bytes, 3 output bytes wil be produced. The output will be
5716 * padded with 0 bits, therefore we need more than the regular 32 bytes of
5717 * space.
5718 */
5719#define WG_BASE64_KEY_LEN(4 * ((32 + 2) / 3)) (4 * ((WG_KEY_LEN32 + 2) / 3))
5720#define WG_LOAD_KEY(dst, src, fn_name)do { uint8_t _tmp[32]; int _r; if (strlen(src) != (4 * ((32 +
2) / 3))) errx(1, fn_name " (key): invalid length"); if ((_r
= __b64_pton(src, _tmp, sizeof(_tmp))) != sizeof(_tmp)) errx
(1, fn_name " (key): invalid base64 %d/%zu", _r, sizeof(_tmp)
); memcpy(dst, _tmp, 32); } while (0)
do { \
5721 uint8_t _tmp[WG_KEY_LEN32]; int _r; \
5722 if (strlen(src) != WG_BASE64_KEY_LEN(4 * ((32 + 2) / 3))) \
5723 errx(1, fn_name " (key): invalid length"); \
5724 if ((_r = b64_pton__b64_pton(src, _tmp, sizeof(_tmp))) != sizeof(_tmp)) \
5725 errx(1, fn_name " (key): invalid base64 %d/%zu", _r, sizeof(_tmp)); \
5726 memcpy(dst, _tmp, WG_KEY_LEN32); \
5727} while (0)
5728
5729struct wg_data_io wgdata = { 0 };
5730struct wg_interface_io *wg_interface = NULL((void *)0);
5731struct wg_peer_io *wg_peer = NULL((void *)0);
5732struct wg_aip_io *wg_aip = NULL((void *)0);
5733
5734void
5735ensurewginterface(void)
5736{
5737 if (wg_interface != NULL((void *)0))
5738 return;
5739 wgdata.wgd_size = sizeof(*wg_interface);
5740 wgdata.wgd_interface = wg_interface = calloc(1, wgdata.wgd_size);
5741 if (wg_interface == NULL((void *)0))
5742 err(1, "calloc");
5743}
5744
5745void
5746growwgdata(size_t by)
5747{
5748 ptrdiff_t peer_offset, aip_offset;
5749
5750 if (wg_interface == NULL((void *)0))
5751 wgdata.wgd_size = sizeof(*wg_interface);
5752
5753 peer_offset = (void *)wg_peer - (void *)wg_interface;
5754 aip_offset = (void *)wg_aip - (void *)wg_interface;
5755
5756 wgdata.wgd_size += by;
5757 wgdata.wgd_interface = realloc(wg_interface, wgdata.wgd_size);
5758 if (wgdata.wgd_interface == NULL((void *)0))
5759 err(1, "calloc");
5760 if (wg_interface == NULL((void *)0))
5761 bzero(wgdata.wgd_interface, sizeof(*wg_interface));
5762 wg_interface = wgdata.wgd_interface;
5763
5764 if (wg_peer != NULL((void *)0))
5765 wg_peer = (void *)wg_interface + peer_offset;
5766 if (wg_aip != NULL((void *)0))
5767 wg_aip = (void *)wg_interface + aip_offset;
5768
5769 bzero((char *)wg_interface + wgdata.wgd_size - by, by);
5770}
5771
5772void
5773setwgpeer(const char *peerkey_b64, int param)
5774{
5775 growwgdata(sizeof(*wg_peer));
5776 if (wg_aip)
5777 wg_peer = (struct wg_peer_io *)wg_aip;
5778 else
5779 wg_peer = &wg_interface->i_peers[0];
5780 wg_aip = &wg_peer->p_aips[0];
5781 wg_peer->p_flags |= WG_PEER_HAS_PUBLIC(1 << 0);
5782 WG_LOAD_KEY(wg_peer->p_public, peerkey_b64, "wgpeer")do { uint8_t _tmp[32]; int _r; if (strlen(peerkey_b64) != (4 *
((32 + 2) / 3))) errx(1, "wgpeer" " (key): invalid length");
if ((_r = __b64_pton(peerkey_b64, _tmp, sizeof(_tmp))) != sizeof
(_tmp)) errx(1, "wgpeer" " (key): invalid base64 %d/%zu", _r,
sizeof(_tmp)); memcpy(wg_peer->p_public, _tmp, 32); } while
(0)
;
5783 wg_interface->i_peers_count++;
5784}
5785
5786void
5787setwgpeerdesc(const char *descr, int param)
5788{
5789 if (wg_peer == NULL((void *)0))
5790 errx(1, "wgdescr: wgpeer not set");
5791 wg_peer->p_flags |= WG_PEER_SET_DESCRIPTION(1 << 7);
5792 strlcpy(wg_peer->p_description, descr, IFDESCRSIZE64);
5793}
5794
5795void
5796setwgpeeraip(const char *aip, int param)
5797{
5798 int res;
5799 if (wg_peer == NULL((void *)0))
5800 errx(1, "wgaip: wgpeer not set");
5801
5802 growwgdata(sizeof(*wg_aip));
5803
5804 if ((res = inet_net_pton(AF_INET2, aip, &wg_aip->a_ipv4a_addr.addr_ipv4,
5805 sizeof(wg_aip->a_ipv4a_addr.addr_ipv4))) != -1) {
5806 wg_aip->a_af = AF_INET2;
5807 } else if ((res = inet_net_pton(AF_INET624, aip, &wg_aip->a_ipv6a_addr.addr_ipv6,
5808 sizeof(wg_aip->a_ipv6a_addr.addr_ipv6))) != -1) {
5809 wg_aip->a_af = AF_INET624;
5810 } else {
5811 errx(1, "wgaip: bad address");
5812 }
5813
5814 wg_aip->a_cidr = res;
5815
5816 wg_peer->p_flags |= WG_PEER_REPLACE_AIPS(1 << 4);
5817 wg_peer->p_aips_count++;
5818
5819 wg_aip++;
5820}
5821
5822void
5823setwgpeerep(const char *host, const char *service)
5824{
5825 int error;
5826 struct addrinfo *ai;
5827
5828 if (wg_peer == NULL((void *)0))
5829 errx(1, "wgendpoint: wgpeer not set");
5830
5831 if ((error = getaddrinfo(host, service, NULL((void *)0), &ai)) != 0)
5832 errx(1, "%s", gai_strerror(error));
5833
5834 wg_peer->p_flags |= WG_PEER_HAS_ENDPOINT(1 << 3);
5835 memcpy(&wg_peer->p_sap_endpoint.sa_sa, ai->ai_addr, ai->ai_addrlen);
5836 freeaddrinfo(ai);
5837}
5838
5839void
5840setwgpeerpsk(const char *psk_b64, int param)
5841{
5842 if (wg_peer == NULL((void *)0))
5843 errx(1, "wgpsk: wgpeer not set");
5844 wg_peer->p_flags |= WG_PEER_HAS_PSK(1 << 1);
5845 WG_LOAD_KEY(wg_peer->p_psk, psk_b64, "wgpsk")do { uint8_t _tmp[32]; int _r; if (strlen(psk_b64) != (4 * ((
32 + 2) / 3))) errx(1, "wgpsk" " (key): invalid length"); if (
(_r = __b64_pton(psk_b64, _tmp, sizeof(_tmp))) != sizeof(_tmp
)) errx(1, "wgpsk" " (key): invalid base64 %d/%zu", _r, sizeof
(_tmp)); memcpy(wg_peer->p_psk, _tmp, 32); } while (0)
;
5846}
5847
5848void
5849setwgpeerpka(const char *pka, int param)
5850{
5851 const char *errmsg = NULL((void *)0);
5852 if (wg_peer == NULL((void *)0))
5853 errx(1, "wgpka: wgpeer not set");
5854 /* 43200 == 12h, reasonable for a 16 bit value */
5855 wg_peer->p_flags |= WG_PEER_HAS_PKA(1 << 2);
5856 wg_peer->p_pka = strtonum(pka, 0, 43200, &errmsg);
5857 if (errmsg)
5858 errx(1, "wgpka: %s, %s", pka, errmsg);
5859}
5860
5861void
5862setwgport(const char *port, int param)
5863{
5864 const char *errmsg = NULL((void *)0);
5865 ensurewginterface();
5866 wg_interface->i_flags |= WG_INTERFACE_HAS_PORT(1 << 2);
5867 wg_interface->i_port = strtonum(port, 0, 65535, &errmsg);
5868 if (errmsg)
5869 errx(1, "wgport: %s, %s", port, errmsg);
5870}
5871
5872void
5873setwgkey(const char *private_b64, int param)
5874{
5875 ensurewginterface();
5876 wg_interface->i_flags |= WG_INTERFACE_HAS_PRIVATE(1 << 1);
5877 WG_LOAD_KEY(wg_interface->i_private, private_b64, "wgkey")do { uint8_t _tmp[32]; int _r; if (strlen(private_b64) != (4 *
((32 + 2) / 3))) errx(1, "wgkey" " (key): invalid length"); if
((_r = __b64_pton(private_b64, _tmp, sizeof(_tmp))) != sizeof
(_tmp)) errx(1, "wgkey" " (key): invalid base64 %d/%zu", _r, sizeof
(_tmp)); memcpy(wg_interface->i_private, _tmp, 32); } while
(0)
;
5878}
5879
5880void
5881setwgrtable(const char *id, int param)
5882{
5883 const char *errmsg = NULL((void *)0);
5884 ensurewginterface();
5885 wg_interface->i_flags |= WG_INTERFACE_HAS_RTABLE(1 << 3);
5886 wg_interface->i_rtable = strtonum(id, 0, RT_TABLEID_MAX255, &errmsg);
5887 if (errmsg)
5888 errx(1, "wgrtable %s: %s", id, errmsg);
5889}
5890
5891void
5892unsetwgpeer(const char *peerkey_b64, int param)
5893{
5894 setwgpeer(peerkey_b64, param);
5895 wg_peer->p_flags |= WG_PEER_REMOVE(1 << 5);
5896}
5897
5898void
5899unsetwgpeerdesc(const char *descr, int param)
5900{
5901 if (wg_peer == NULL((void *)0))
5902 errx(1, "wgdescr: wgpeer not set");
5903 wg_peer->p_flags |= WG_PEER_SET_DESCRIPTION(1 << 7);
5904 strlcpy(wg_peer->p_description, "", IFDESCRSIZE64);
5905}
5906
5907void
5908unsetwgpeerpsk(const char *value, int param)
5909{
5910 if (wg_peer == NULL((void *)0))
5911 errx(1, "wgpsk: wgpeer not set");
5912 wg_peer->p_flags |= WG_PEER_HAS_PSK(1 << 1);
5913 bzero(wg_peer->p_psk, WG_KEY_LEN32);
5914}
5915
5916void
5917unsetwgpeerall(const char *value, int param)
5918{
5919 ensurewginterface();
5920 wg_interface->i_flags |= WG_INTERFACE_REPLACE_PEERS(1 << 4);
5921}
5922
5923void
5924process_wg_commands(void)
5925{
5926 if (actions & A_WIREGUARD0x0040) {
5927 strlcpy(wgdata.wgd_name, ifname, sizeof(wgdata.wgd_name));
5928
5929 if (ioctl(sock, SIOCSWG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wg_data_io) & 0x1fff) << 16) | ((('i')) <<
8) | ((210)))
, (caddr_t)&wgdata) == -1)
5930 err(1, "%s: SIOCSWG", wgdata.wgd_name);
5931 }
5932}
5933
5934void
5935wg_status(int ifaliases)
5936{
5937 size_t i, j, last_size;
5938 struct timespec now;
5939 char hbuf[NI_MAXHOST256], sbuf[NI_MAXSERV32];
5940 char key[WG_BASE64_KEY_LEN(4 * ((32 + 2) / 3)) + 1];
5941
5942 strlcpy(wgdata.wgd_name, ifname, sizeof(wgdata.wgd_name));
5943 wgdata.wgd_size = 0;
5944 wgdata.wgd_interface = NULL((void *)0);
5945 for (last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size) {
5946 if (ioctl(sock, SIOCGWG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wg_data_io) & 0x1fff) << 16) | ((('i')) <<
8) | ((211)))
, (caddr_t)&wgdata) < 0) {
5947 if (errno(*__errno()) == ENOTTY25)
5948 goto out;
5949 err(1, "%s: SIOCGWG", wgdata.wgd_name);
5950 }
5951 if (last_size >= wgdata.wgd_size)
5952 break;
5953 wgdata.wgd_interface = realloc(wgdata.wgd_interface,
5954 wgdata.wgd_size);
5955 if (!wgdata.wgd_interface)
5956 err(1, "realloc");
5957 }
5958 wg_interface = wgdata.wgd_interface;
5959
5960 if (wg_interface->i_flags & WG_INTERFACE_HAS_PORT(1 << 2))
5961 printf("\twgport %hu\n", wg_interface->i_port);
5962 if (wg_interface->i_flags & WG_INTERFACE_HAS_RTABLE(1 << 3))
5963 printf("\twgrtable %d\n", wg_interface->i_rtable);
5964 if (wg_interface->i_flags & WG_INTERFACE_HAS_PUBLIC(1 << 0)) {
5965 b64_ntop__b64_ntop(wg_interface->i_public, WG_KEY_LEN32,
5966 key, sizeof(key));
5967 printf("\twgpubkey %s\n", key);
5968 }
5969
5970 if (ifaliases) {
5971 wg_peer = &wg_interface->i_peers[0];
5972 for (i = 0; i < wg_interface->i_peers_count; i++) {
5973 b64_ntop__b64_ntop(wg_peer->p_public, WG_KEY_LEN32,
5974 key, sizeof(key));
5975 printf("\twgpeer %s\n", key);
5976
5977 if (strlen(wg_peer->p_description))
5978 printf("\t\twgdescr: %s\n",
5979 wg_peer->p_description);
5980
5981 if (wg_peer->p_flags & WG_PEER_HAS_PSK(1 << 1))
5982 printf("\t\twgpsk (present)\n");
5983
5984 if (wg_peer->p_flags & WG_PEER_HAS_PKA(1 << 2) && wg_peer->p_pka)
5985 printf("\t\twgpka %u (sec)\n", wg_peer->p_pka);
5986
5987 if (wg_peer->p_flags & WG_PEER_HAS_ENDPOINT(1 << 3)) {
5988 if (getnameinfo(&wg_peer->p_sap_endpoint.sa_sa, wg_peer->p_sap_endpoint.sa_sa.sa_len,
5989 hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
5990 NI_NUMERICHOST1 | NI_NUMERICSERV2) == 0)
5991 printf("\t\twgendpoint %s %s\n", hbuf, sbuf);
5992 else
5993 printf("\t\twgendpoint unable to print\n");
5994 }
5995
5996 printf("\t\ttx: %llu, rx: %llu\n",
5997 wg_peer->p_txbytes, wg_peer->p_rxbytes);
5998
5999 if (wg_peer->p_last_handshake.tv_sec != 0) {
6000 clock_gettime(CLOCK_REALTIME0, &now);
6001 printf("\t\tlast handshake: %lld seconds ago\n",
6002 now.tv_sec - wg_peer->p_last_handshake.tv_sec);
6003 }
6004
6005
6006 wg_aip = &wg_peer->p_aips[0];
6007 for (j = 0; j < wg_peer->p_aips_count; j++) {
6008 inet_ntop(wg_aip->a_af, &wg_aip->a_addr,
6009 hbuf, sizeof(hbuf));
6010 printf("\t\twgaip %s/%d\n", hbuf, wg_aip->a_cidr);
6011 wg_aip++;
6012 }
6013 wg_peer = (struct wg_peer_io *)wg_aip;
6014 }
6015 }
6016out:
6017 free(wgdata.wgd_interface);
6018}
6019
6020const struct umb_valdescr umb_regstate[] = MBIM_REGSTATE_DESCRIPTIONS{ { 0, "unknown" }, { 1, "not registered" }, { 2, "searching"
}, { 3, "home network" }, { 4, "roaming network" }, { 5, "partner network"
}, { 6, "access denied" }, { 0, ((void *)0) } }
;
6021const struct umb_valdescr umb_dataclass[] = MBIM_DATACLASS_DESCRIPTIONS{ { 0x00000000, "none" }, { 0x00000001, "GPRS" }, { 0x00000002
, "EDGE" }, { 0x00000004, "UMTS" }, { 0x00000008, "HSDPA" }, {
0x00000010, "HSUPA" }, { 0x00000008|0x00000010, "HSPA" }, { 0x00000020
, "LTE" }, { 0x00010000, "CDMA2000" }, { 0x00020000, "CDMA2000"
}, { 0x00040000, "CDMA2000" }, { 0x00080000, "CDMA2000" }, {
0x00100000, "CDMA2000" }, { 0x00200000, "CDMA2000" }, { 0x00400000
, "CDMA2000" }, { 0x80000000, "custom" }, { 0, ((void *)0) } }
;
6022const struct umb_valdescr umb_simstate[] = MBIM_SIMSTATE_DESCRIPTIONS{ { 0, "not initialized" }, { 1, "initialized" }, { 2, "not inserted"
}, { 3, "bad type" }, { 4, "failed" }, { 5, "not activated" }
, { 6, "locked" }, { 0, ((void *)0) } }
;
6023const struct umb_valdescr umb_istate[] = UMB_INTERNAL_STATE_DESCRIPTIONS{ { UMB_S_DOWN, "down" }, { UMB_S_OPEN, "open" }, { UMB_S_CID
, "CID allocated" }, { UMB_S_RADIO, "radio on" }, { UMB_S_SIMREADY
, "SIM is ready" }, { UMB_S_ATTACHED, "attached" }, { UMB_S_CONNECTED
, "connected" }, { UMB_S_UP, "up" }, { 0, ((void *)0) } }
;
6024
6025const struct umb_valdescr umb_classalias[] = {
6026 { MBIM_DATACLASS_GPRS0x00000001 | MBIM_DATACLASS_EDGE0x00000002, "2g" },
6027 { MBIM_DATACLASS_UMTS0x00000004 | MBIM_DATACLASS_HSDPA0x00000008 | MBIM_DATACLASS_HSUPA0x00000010,
6028 "3g" },
6029 { MBIM_DATACLASS_LTE0x00000020, "4g" },
6030 { 0, NULL((void *)0) }
6031};
6032
6033static int
6034umb_descr2val(const struct umb_valdescr *vdp, char *str)
6035{
6036 while (vdp->descr != NULL((void *)0)) {
6037 if (!strcasecmp(vdp->descr, str))
6038 return vdp->val;
6039 vdp++;
6040 }
6041 return 0;
6042}
6043
6044void
6045umb_status(void)
6046{
6047 struct umb_info mi;
6048 char provider[UMB_PROVIDERNAME_MAXLEN20+1];
6049 char providerid[UMB_PROVIDERID_MAXLEN20+1];
6050 char roamingtxt[UMB_ROAMINGTEXT_MAXLEN63+1];
6051 char devid[UMB_DEVID_MAXLEN18+1];
6052 char fwinfo[UMB_FWINFO_MAXLEN30+1];
6053 char hwinfo[UMB_HWINFO_MAXLEN30+1];
6054 char sid[UMB_SUBSCRIBERID_MAXLEN15+1];
6055 char iccid[UMB_ICCID_MAXLEN20+1];
6056 char apn[UMB_APN_MAXLEN100+1];
6057 char pn[UMB_PHONENR_MAXLEN22+1];
6058 int i, n;
6059 char astr[INET6_ADDRSTRLEN46];
6060
6061 memset((char *)&mi, 0, sizeof(mi));
6062 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&mi;
6063 if (ioctl(sock, SIOCGUMBINFO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((190)))
, (caddr_t)&ifr) == -1)
6064 return;
6065
6066 if (mi.nwerror) {
6067 /* 3GPP 24.008 Cause Code */
6068 printf("\terror: ");
6069 switch (mi.nwerror) {
6070 case 2:
6071 printf("SIM not activated");
6072 break;
6073 case 4:
6074 printf("Roaming not supported");
6075 break;
6076 case 6:
6077 printf("SIM reported stolen");
6078 break;
6079 case 7:
6080 printf("No GPRS subscription");
6081 break;
6082 case 8:
6083 printf("GPRS and non-GPRS services not allowed");
6084 break;
6085 case 11:
6086 printf("Subscription expired");
6087 break;
6088 case 12:
6089 printf("Subscription does not cover current location");
6090 break;
6091 case 13:
6092 printf("No roaming in this location");
6093 break;
6094 case 14:
6095 printf("GPRS not supported");
6096 break;
6097 case 15:
6098 printf("No subscription for the service");
6099 break;
6100 case 17:
6101 printf("Registration failed");
6102 break;
6103 case 22:
6104 printf("Network congestion");
6105 break;
6106 default:
6107 printf("Error code %d", mi.nwerror);
6108 break;
6109 }
6110 printf("\n");
6111 }
6112
6113 printf("\troaming %s registration %s",
6114 mi.enable_roaming ? "enabled" : "disabled",
6115 umb_val2descr(umb_regstate, mi.regstate));
6116 utf16_to_char(mi.roamingtxt, UMB_ROAMINGTEXT_MAXLEN63,
6117 roamingtxt, sizeof (roamingtxt));
6118 if (roamingtxt[0])
6119 printf(" [%s]", roamingtxt);
6120 printf("\n");
6121
6122 if (showclasses)
6123 umb_printclasses("available classes", mi.supportedclasses);
6124 printf("\tstate %s cell-class %s",
6125 umb_val2descr(umb_istate, mi.state),
6126 umb_val2descr(umb_dataclass, mi.highestclass));
6127 if (mi.rssi != UMB_VALUE_UNKNOWN-999 && mi.rssi != 0)
6128 printf(" rssi %ddBm", mi.rssi);
6129 if (mi.uplink_speed != 0 || mi.downlink_speed != 0) {
6130 char s[2][FMT_SCALED_STRSIZE7];
6131 if (fmt_scaled(mi.uplink_speed, s[0]) != 0)
6132 snprintf(s[0], sizeof (s[0]), "%llu", mi.uplink_speed);
6133 if (fmt_scaled(mi.downlink_speed, s[1]) != 0)
6134 snprintf(s[1], sizeof (s[1]), "%llu", mi.downlink_speed);
6135 printf(" speed %sbps up %sbps down", s[0], s[1]);
6136 }
6137 printf("\n");
6138
6139 printf("\tSIM %s PIN ", umb_val2descr(umb_simstate, mi.sim_state));
6140 switch (mi.pin_state) {
6141 case UMB_PIN_REQUIRED0:
6142 printf("required");
6143 break;
6144 case UMB_PIN_UNLOCKED1:
6145 printf("valid");
6146 break;
6147 case UMB_PUK_REQUIRED2:
6148 printf("locked (PUK required)");
6149 break;
6150 default:
6151 printf("unknown state (%d)", mi.pin_state);
6152 break;
6153 }
6154 if (mi.pin_attempts_left != UMB_VALUE_UNKNOWN-999)
6155 printf(" (%d attempts left)", mi.pin_attempts_left);
6156 printf("\n");
6157
6158 utf16_to_char(mi.sid, UMB_SUBSCRIBERID_MAXLEN15, sid, sizeof (sid));
6159 utf16_to_char(mi.iccid, UMB_ICCID_MAXLEN20, iccid, sizeof (iccid));
6160 utf16_to_char(mi.provider, UMB_PROVIDERNAME_MAXLEN20,
6161 provider, sizeof (provider));
6162 utf16_to_char(mi.providerid, UMB_PROVIDERID_MAXLEN20,
6163 providerid, sizeof (providerid));
6164 if (sid[0] || iccid[0]) {
6165 printf("\t");
6166 n = 0;
6167 if (sid[0])
6168 printf("%ssubscriber-id %s", n++ ? " " : "", sid);
6169 if (iccid[0])
6170 printf("%sICC-id %s", n++ ? " " : "", iccid);
6171 printf("\n");
6172 }
6173
6174 utf16_to_char(mi.hwinfo, UMB_HWINFO_MAXLEN30, hwinfo, sizeof (hwinfo));
6175 utf16_to_char(mi.devid, UMB_DEVID_MAXLEN18, devid, sizeof (devid));
6176 utf16_to_char(mi.fwinfo, UMB_FWINFO_MAXLEN30, fwinfo, sizeof (fwinfo));
6177 if (hwinfo[0] || devid[0] || fwinfo[0]) {
6178 printf("\t");
6179 n = 0;
6180 if (hwinfo[0])
6181 printf("%sdevice %s", n++ ? " " : "", hwinfo);
6182 if (devid[0]) {
6183 printf("%s", n++ ? " " : "");
6184 switch (mi.cellclass) {
6185 case MBIM_CELLCLASS_GSM0x00000001:
6186 printf("IMEI");
6187 break;
6188 case MBIM_CELLCLASS_CDMA0x00000002:
6189 n = strlen(devid);
6190 if (n == 8 || n == 11) {
6191 printf("ESN");
6192 break;
6193 } else if (n == 14 || n == 18) {
6194 printf("MEID");
6195 break;
6196 }
6197 /*FALLTHROUGH*/
6198 default:
6199 printf("ID");
6200 break;
6201 }
6202 printf(" %s", devid);
6203 }
6204 if (fwinfo[0])
6205 printf("%sfirmware %s", n++ ? " " : "", fwinfo);
6206 printf("\n");
6207 }
6208
6209 utf16_to_char(mi.pn, UMB_PHONENR_MAXLEN22, pn, sizeof (pn));
6210 utf16_to_char(mi.apn, UMB_APN_MAXLEN100, apn, sizeof (apn));
6211 if (pn[0] || apn[0] || provider[0] || providerid[0]) {
6212 printf("\t");
6213 n = 0;
6214 if (pn[0])
6215 printf("%sphone# %s", n++ ? " " : "", pn);
6216 if (apn[0])
6217 printf("%sAPN %s", n++ ? " " : "", apn);
6218 if (provider[0])
6219 printf("%sprovider %s", n++ ? " " : "", provider);
6220 if (providerid[0])
6221 printf("%sprovider-id %s", n ? " " : "", providerid);
6222 printf("\n");
6223 }
6224
6225 for (i = 0, n = 0; i < UMB_MAX_DNSSRV2; i++) {
6226 if (mi.ipv4dns[i].s_addr == INADDR_ANY((u_int32_t)(0x00000000)))
6227 break;
6228 printf("%s %s", n++ ? "" : "\tdns",
6229 inet_ntop(AF_INET2, &mi.ipv4dns[i], astr, sizeof(astr)));
6230 }
6231 for (i = 0; i < UMB_MAX_DNSSRV2; i++) {
6232 if (memcmp(&mi.ipv6dns[i], &in6addr_any,
6233 sizeof (mi.ipv6dns[i])) == 0)
6234 break;
6235 printf("%s %s", n++ ? "" : "\tdns",
6236 inet_ntop(AF_INET624, &mi.ipv6dns[i], astr, sizeof(astr)));
6237 }
6238 if (n)
6239 printf("\n");
6240}
6241
6242void
6243umb_printclasses(char *tag, int c)
6244{
6245 int i;
6246 char *sep = "";
6247
6248 printf("\t%s: ", tag);
6249 i = 0;
6250 while (umb_dataclass[i].descr) {
6251 if (umb_dataclass[i].val & c) {
6252 printf("%s%s", sep, umb_dataclass[i].descr);
6253 sep = ",";
6254 }
6255 i++;
6256 }
6257 printf("\n");
6258}
6259
6260int
6261umb_parse_classes(const char *spec)
6262{
6263 char *optlist, *str;
6264 int c = 0, v;
6265
6266 if ((optlist = strdup(spec)) == NULL((void *)0))
6267 err(1, "strdup");
6268 str = strtok(optlist, ",");
6269 while (str != NULL((void *)0)) {
6270 if ((v = umb_descr2val(umb_dataclass, str)) != 0 ||
6271 (v = umb_descr2val(umb_classalias, str)) != 0)
6272 c |= v;
6273 str = strtok(NULL((void *)0), ",");
6274 }
6275 free(optlist);
6276 return c;
6277}
6278
6279void
6280umb_setpin(const char *pin, int d)
6281{
6282 umb_pinop(MBIM_PIN_OP_ENTER0, 0, pin, NULL((void *)0));
6283}
6284
6285void
6286umb_chgpin(const char *pin, const char *newpin)
6287{
6288 umb_pinop(MBIM_PIN_OP_CHANGE3, 0, pin, newpin);
6289}
6290
6291void
6292umb_puk(const char *pin, const char *newpin)
6293{
6294 umb_pinop(MBIM_PIN_OP_ENTER0, 1, pin, newpin);
6295}
6296
6297void
6298umb_pinop(int op, int is_puk, const char *pin, const char *newpin)
6299{
6300 struct umb_parameter mp;
6301
6302 memset(&mp, 0, sizeof (mp));
6303 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&mp;
6304 if (ioctl(sock, SIOCGUMBPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((192)))
, (caddr_t)&ifr) == -1)
6305 err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name);
6306
6307 mp.op = op;
6308 mp.is_puk = is_puk;
6309 if ((mp.pinlen = char_to_utf16(pin, (uint16_t *)mp.pin,
6310 sizeof (mp.pin))) == -1)
6311 errx(1, "PIN too long");
6312
6313 if (newpin) {
6314 if ((mp.newpinlen = char_to_utf16(newpin, (uint16_t *)mp.newpin,
6315 sizeof (mp.newpin))) == -1)
6316 errx(1, "new PIN too long");
6317 }
6318
6319 if (ioctl(sock, SIOCSUMBPARAM((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((191)))
, (caddr_t)&ifr) == -1)
6320 err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name);
6321}
6322
6323void
6324umb_apn(const char *apn, int d)
6325{
6326 struct umb_parameter mp;
6327
6328 memset(&mp, 0, sizeof (mp));
6329 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&mp;
6330 if (ioctl(sock, SIOCGUMBPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((192)))
, (caddr_t)&ifr) == -1)
6331 err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name);
6332
6333 if (d != 0)
6334 memset(mp.apn, 0, sizeof (mp.apn));
6335 else if ((mp.apnlen = char_to_utf16(apn, mp.apn,
6336 sizeof (mp.apn))) == -1)
6337 errx(1, "APN too long");
6338
6339 if (ioctl(sock, SIOCSUMBPARAM((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((191)))
, (caddr_t)&ifr) == -1)
6340 err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name);
6341}
6342
6343void
6344umb_setclass(const char *val, int d)
6345{
6346 struct umb_parameter mp;
6347
6348 if (val == NULL((void *)0)) {
6349 if (showclasses)
6350 usage();
6351 showclasses = 1;
6352 return;
6353 }
6354
6355 memset(&mp, 0, sizeof (mp));
6356 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&mp;
6357 if (ioctl(sock, SIOCGUMBPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((192)))
, (caddr_t)&ifr) == -1)
6358 err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name);
6359 if (d != -1)
6360 mp.preferredclasses = umb_parse_classes(val);
6361 else
6362 mp.preferredclasses = MBIM_DATACLASS_NONE0x00000000;
6363 if (ioctl(sock, SIOCSUMBPARAM((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((191)))
, (caddr_t)&ifr) == -1)
6364 err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name);
6365}
6366
6367void
6368umb_roaming(const char *val, int d)
6369{
6370 struct umb_parameter mp;
6371
6372 memset(&mp, 0, sizeof (mp));
6373 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&mp;
6374 if (ioctl(sock, SIOCGUMBPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((192)))
, (caddr_t)&ifr) == -1)
6375 err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name);
6376 mp.roaming = d;
6377 if (ioctl(sock, SIOCSUMBPARAM((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((191)))
, (caddr_t)&ifr) == -1)
6378 err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name);
6379}
6380
6381void
6382utf16_to_char(uint16_t *in, int inlen, char *out, size_t outlen)
6383{
6384 uint16_t c;
6385
6386 while (outlen > 0) {
6387 c = inlen > 0 ? letoh16(*in)((__uint16_t)(*in)) : 0;
6388 if (c == 0 || --outlen == 0) {
6389 /* always NUL terminate result */
6390 *out = '\0';
6391 break;
6392 }
6393 *out++ = isascii(c) ? (char)c : '?';
6394 in++;
6395 inlen--;
6396 }
6397}
6398
6399int
6400char_to_utf16(const char *in, uint16_t *out, size_t outlen)
6401{
6402 int n = 0;
6403 uint16_t c;
6404
6405 for (;;) {
6406 c = *in++;
6407
6408 if (c == '\0') {
6409 /*
6410 * NUL termination is not required, but zero out the
6411 * residual buffer
6412 */
6413 memset(out, 0, outlen);
6414 return n;
6415 }
6416 if (outlen < sizeof (*out))
6417 return -1;
6418
6419 *out++ = htole16(c)((__uint16_t)(c));
6420 n += sizeof (*out);
6421 outlen -= sizeof (*out);
6422 }
6423}
6424
6425#endif
6426
6427#define SIN(x)((struct sockaddr_in *) &(x)) ((struct sockaddr_in *) &(x))
6428struct sockaddr_in *sintab[] = {
6429SIN(ridreq.ifr_addr)((struct sockaddr_in *) &(ridreq.ifr_ifru.ifru_addr)), SIN(in_addreq.ifra_addr)((struct sockaddr_in *) &(in_addreq.ifra_ifrau.ifrau_addr
))
,
6430SIN(in_addreq.ifra_mask)((struct sockaddr_in *) &(in_addreq.ifra_mask)), SIN(in_addreq.ifra_broadaddr)((struct sockaddr_in *) &(in_addreq.ifra_dstaddr))};
6431
6432void
6433in_getaddr(const char *s, int which)
6434{
6435 struct sockaddr_in *sin = sintab[which], tsin;
6436 struct hostent *hp;
6437 int bits, l;
6438 char p[3];
6439
6440 bzero(&tsin, sizeof(tsin));
6441 sin->sin_len = sizeof(*sin);
6442 if (which != MASK2)
6443 sin->sin_family = AF_INET2;
6444
6445 if (which == ADDR1 && strrchr(s, '/') != NULL((void *)0) &&
6446 (bits = inet_net_pton(AF_INET2, s, &tsin.sin_addr,
6447 sizeof(tsin.sin_addr))) != -1) {
6448 l = snprintf(p, sizeof(p), "%d", bits);
6449 if (l < 0 || l >= sizeof(p))
6450 errx(1, "%d: bad prefixlen", bits);
6451 in_getprefix(p, MASK2);
6452 memcpy(&sin->sin_addr, &tsin.sin_addr, sizeof(sin->sin_addr));
6453 } else if (inet_aton(s, &sin->sin_addr) == 0) {
6454 if ((hp = gethostbyname(s)))
6455 memcpy(&sin->sin_addr, hp->h_addrh_addr_list[0], hp->h_length);
6456 else
6457 errx(1, "%s: bad value", s);
6458 }
6459 if (which == MASK2 && (ntohl(sin->sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(sin->sin_addr.s_addr) ? (
__uint32_t)(((__uint32_t)(sin->sin_addr.s_addr) & 0xff
) << 24 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff00
) << 8 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff0000
) >> 8 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff000000
) >> 24) : __swap32md(sin->sin_addr.s_addr))
&
6460 (~ntohl(sin->sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(sin->sin_addr.s_addr) ? (
__uint32_t)(((__uint32_t)(sin->sin_addr.s_addr) & 0xff
) << 24 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff00
) << 8 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff0000
) >> 8 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff000000
) >> 24) : __swap32md(sin->sin_addr.s_addr))
>> 1)))
6461 errx(1, "%s: non-contiguous mask", s);
6462}
6463
6464void
6465in_getprefix(const char *plen, int which)
6466{
6467 struct sockaddr_in *sin = sintab[which];
6468 const char *errmsg = NULL((void *)0);
6469 u_char *cp;
6470 int len;
6471
6472 len = strtonum(plen, 0, 32, &errmsg);
6473 if (errmsg)
6474 errx(1, "prefix %s: %s", plen, errmsg);
6475
6476 sin->sin_len = sizeof(*sin);
6477 if (which != MASK2)
6478 sin->sin_family = AF_INET2;
6479 if ((len == 0) || (len == 32)) {
6480 memset(&sin->sin_addr, 0xff, sizeof(struct in_addr));
6481 return;
6482 }
6483 memset((void *)&sin->sin_addr, 0x00, sizeof(sin->sin_addr));
6484 for (cp = (u_char *)&sin->sin_addr; len > 7; len -= 8)
6485 *cp++ = 0xff;
6486 if (len)
6487 *cp = 0xff << (8 - len);
6488}
6489
6490/*
6491 * Print a value a la the %b format of the kernel's printf
6492 */
6493void
6494printb(char *s, unsigned int v, unsigned char *bits)
6495{
6496 int i, any = 0;
6497 unsigned char c;
6498
6499 if (bits && *bits == 8)
6500 printf("%s=%o", s, v);
6501 else
6502 printf("%s=%x", s, v);
6503
6504 if (bits) {
6505 bits++;
6506 putchar('<')(!__isthreaded ? __sputc('<', (&__sF[1])) : (putc)('<'
, (&__sF[1])))
;
6507 while ((i = *bits++)) {
6508 if (v & (1 << (i-1))) {
6509 if (any)
6510 putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', (
&__sF[1])))
;
6511 any = 1;
6512 for (; (c = *bits) > 32; bits++)
6513 putchar(c)(!__isthreaded ? __sputc(c, (&__sF[1])) : (putc)(c, (&
__sF[1])))
;
6514 } else
6515 for (; *bits > 32; bits++)
6516 ;
6517 }
6518 putchar('>')(!__isthreaded ? __sputc('>', (&__sF[1])) : (putc)('>'
, (&__sF[1])))
;
6519 }
6520}
6521
6522/*
6523 * A simple version of printb for status output
6524 */
6525void
6526printb_status(unsigned short v, unsigned char *bits)
6527{
6528 int i, any = 0;
6529 unsigned char c;
6530
6531 if (bits) {
6532 bits++;
6533 while ((i = *bits++)) {
6534 if (v & (1 << (i-1))) {
6535 if (any)
6536 putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', (
&__sF[1])))
;
6537 any = 1;
6538 for (; (c = *bits) > 32; bits++)
6539 putchar(tolower(c))(!__isthreaded ? __sputc(tolower(c), (&__sF[1])) : (putc)
(tolower(c), (&__sF[1])))
;
6540 } else
6541 for (; *bits > 32; bits++)
6542 ;
6543 }
6544 }
6545}
6546
6547#define SIN6(x)((struct sockaddr_in6 *) &(x)) ((struct sockaddr_in6 *) &(x))
6548struct sockaddr_in6 *sin6tab[] = {
6549SIN6(in6_ridreq.ifr_addr)((struct sockaddr_in6 *) &(in6_ridreq.ifr_ifru.ifru_addr)
)
, SIN6(in6_addreq.ifra_addr)((struct sockaddr_in6 *) &(in6_addreq.ifra_ifrau.ifrau_addr
))
,
6550SIN6(in6_addreq.ifra_prefixmask)((struct sockaddr_in6 *) &(in6_addreq.ifra_prefixmask)), SIN6(in6_addreq.ifra_dstaddr)((struct sockaddr_in6 *) &(in6_addreq.ifra_dstaddr))};
6551
6552void
6553in6_getaddr(const char *s, int which)
6554{
6555 struct sockaddr_in6 *sin6 = sin6tab[which];
6556 struct addrinfo hints, *res;
6557 char buf[HOST_NAME_MAX255+1 + sizeof("/128")], *pfxlen;
6558 int error;
6559
6560 memset(&hints, 0, sizeof(hints));
6561 hints.ai_family = AF_INET624;
6562 hints.ai_socktype = SOCK_DGRAM2; /*dummy*/
6563
6564 if (which == ADDR1 && strchr(s, '/') != NULL((void *)0)) {
6565 if (strlcpy(buf, s, sizeof(buf)) >= sizeof(buf))
6566 errx(1, "%s: bad value", s);
6567 pfxlen = strchr(buf, '/');
6568 *pfxlen++ = '\0';
6569 s = buf;
6570 in6_getprefix(pfxlen, MASK2);
6571 explicit_prefix = 1;
6572 }
6573
6574 error = getaddrinfo(s, "0", &hints, &res);
6575 if (error)
6576 errx(1, "%s: %s", s, gai_strerror(error));
6577 memcpy(sin6, res->ai_addr, res->ai_addrlen);
6578#ifdef __KAME__
6579 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))
&&
6580 *(u_int16_t *)&sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[2] == 0 &&
6581 sin6->sin6_scope_id) {
6582 *(u_int16_t *)&sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[2] =
6583 htons(sin6->sin6_scope_id & 0xffff)(__uint16_t)(__builtin_constant_p(sin6->sin6_scope_id &
0xffff) ? (__uint16_t)(((__uint16_t)(sin6->sin6_scope_id &
0xffff) & 0xffU) << 8 | ((__uint16_t)(sin6->sin6_scope_id
& 0xffff) & 0xff00U) >> 8) : __swap16md(sin6->
sin6_scope_id & 0xffff))
;
6584 sin6->sin6_scope_id = 0;
6585 }
6586#endif /* __KAME__ */
6587 freeaddrinfo(res);
6588}
6589
6590void
6591in6_getprefix(const char *plen, int which)
6592{
6593 struct sockaddr_in6 *sin6 = sin6tab[which];
6594 const char *errmsg = NULL((void *)0);
6595 u_char *cp;
6596 int len;
6597
6598 len = strtonum(plen, 0, 128, &errmsg);
6599 if (errmsg)
6600 errx(1, "prefix %s: %s", plen, errmsg);
6601
6602 sin6->sin6_len = sizeof(*sin6);
6603 if (which != MASK2)
6604 sin6->sin6_family = AF_INET624;
6605 if ((len == 0) || (len == 128)) {
6606 memset(&sin6->sin6_addr, 0xff, sizeof(struct in6_addr));
6607 return;
6608 }
6609 memset((void *)&sin6->sin6_addr, 0x00, sizeof(sin6->sin6_addr));
6610 for (cp = (u_char *)&sin6->sin6_addr; len > 7; len -= 8)
6611 *cp++ = 0xff;
6612 if (len)
6613 *cp = 0xff << (8 - len);
6614}
6615
6616int
6617prefix(void *val, int size)
6618{
6619 u_char *nam = (u_char *)val;
6620 int byte, bit, plen = 0;
6621
6622 for (byte = 0; byte < size; byte++, plen += 8)
6623 if (nam[byte] != 0xff)
6624 break;
6625 if (byte == size)
6626 return (plen);
6627 for (bit = 7; bit != 0; bit--, plen++)
6628 if (!(nam[byte] & (1 << bit)))
6629 break;
6630 for (; bit != 0; bit--)
6631 if (nam[byte] & (1 << bit))
6632 return (0);
6633 byte++;
6634 for (; byte < size; byte++)
6635 if (nam[byte])
6636 return (0);
6637 return (plen);
6638}
6639
6640/* Print usage and exit */
6641__dead__attribute__((__noreturn__)) void
6642usage(void)
6643{
6644 fprintf(stderr(&__sF[2]),
6645 "usage: ifconfig [-AaC] [-M lladdr] [interface] [address_family]\n"
6646 "\t\t[address [dest_address]] [parameters]\n");
6647 exit(1);
6648}
6649
6650void
6651getifgroups(void)
6652{
6653 int len, cnt;
6654 struct ifgroupreq ifgr;
6655 struct ifg_req *ifg;
6656
6657 memset(&ifgr, 0, sizeof(ifgr));
6658 strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ16);
6659
6660 if (ioctl(sock, SIOCGIFGROUP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((136)))
, (caddr_t)&ifgr) == -1) {
6661 if (errno(*__errno()) == EINVAL22 || errno(*__errno()) == ENOTTY25)
6662 return;
6663 else
6664 err(1, "%s: SIOCGIFGROUP", ifgr.ifgr_name);
6665 }
6666
6667 len = ifgr.ifgr_len;
6668 ifgr.ifgr_groupsifgr_ifgru.ifgru_groups = calloc(len / sizeof(struct ifg_req),
6669 sizeof(struct ifg_req));
6670 if (ifgr.ifgr_groupsifgr_ifgru.ifgru_groups == NULL((void *)0))
6671 err(1, "getifgroups");
6672 if (ioctl(sock, SIOCGIFGROUP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((136)))
, (caddr_t)&ifgr) == -1)
6673 err(1, "%s: SIOCGIFGROUP", ifgr.ifgr_name);
6674
6675 cnt = 0;
6676 ifg = ifgr.ifgr_groupsifgr_ifgru.ifgru_groups;
6677 for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
6678 len -= sizeof(struct ifg_req);
6679 if (strcmp(ifg->ifgrq_groupifgrq_ifgrqu.ifgrqu_group, "all")) {
6680 if (cnt == 0)
6681 printf("\tgroups:");
6682 cnt++;
6683 printf(" %s", ifg->ifgrq_groupifgrq_ifgrqu.ifgrqu_group);
6684 }
6685 }
6686 if (cnt)
6687 printf("\n");
6688
6689 free(ifgr.ifgr_groupsifgr_ifgru.ifgru_groups);
6690}
6691
6692#ifndef SMALL
6693void
6694printifhwfeatures(const char *unused, int show)
6695{
6696 struct if_data ifrdat;
6697
6698 if (!show) {
6699 if (showcapsflag)
6700 usage();
6701 showcapsflag = 1;
6702 return;
6703 }
6704 bzero(&ifrdat, sizeof(ifrdat));
6705 ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&ifrdat;
6706 if (ioctl(sock, SIOCGIFDATA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((27)))
, (caddr_t)&ifr) == -1)
6707 err(1, "%s: SIOCGIFDATA", ifr.ifr_name);
6708 printb("\thwfeatures", (u_int)ifrdat.ifi_capabilities, HWFEATURESBITS"\024\1CSUM_IPv4\2CSUM_TCPv4\3CSUM_UDPv4" "\5VLAN_MTU\6VLAN_HWTAGGING\10CSUM_TCPv6"
"\11CSUM_UDPv6\15TSOv4\16TSOv6\17LRO\20WOL"
);
6709
6710 if (ioctl(sock, SIOCGIFHARDMTU(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((165)))
, (caddr_t)&ifr) != -1) {
6711 if (ifr.ifr_hardmtuifr_ifru.ifru_metric)
6712 printf(" hardmtu %u", ifr.ifr_hardmtuifr_ifru.ifru_metric);
6713 }
6714 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
6715}
6716#endif
6717
6718char *
6719sec2str(time_t total)
6720{
6721 static char result[256];
6722 char *p = result;
6723 char *end = &result[sizeof(result)];
6724
6725 snprintf(p, end - p, "%lld", (long long)total);
6726 return (result);
6727}
6728
6729void
6730setiflladdr(const char *addr, int param)
6731{
6732 struct ether_addr *eap, eabuf;
6733
6734 if (!strcmp(addr, "random")) {
6735 arc4random_buf(&eabuf, sizeof eabuf);
6736 /* Non-multicast and claim it is a hardware address */
6737 eabuf.ether_addr_octet[0] &= 0xfc;
6738 eap = &eabuf;
6739 } else {
6740 eap = ether_aton(addr);
6741 if (eap == NULL((void *)0)) {
6742 warnx("malformed link-level address");
6743 return;
6744 }
6745 }
6746 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
6747 ifr.ifr_addrifr_ifru.ifru_addr.sa_len = ETHER_ADDR_LEN6;
6748 ifr.ifr_addrifr_ifru.ifru_addr.sa_family = AF_LINK18;
6749 bcopy(eap, ifr.ifr_addrifr_ifru.ifru_addr.sa_data, ETHER_ADDR_LEN6);
6750 if (ioctl(sock, SIOCSIFLLADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((31)))
, (caddr_t)&ifr) == -1)
6751 warn("SIOCSIFLLADDR");
6752}
6753
6754#ifndef SMALL
6755void
6756setrdomain(const char *id, int param)
6757{
6758 const char *errmsg = NULL((void *)0);
6759 int rdomainid;
6760
6761 rdomainid = strtonum(id, 0, RT_TABLEID_MAX255, &errmsg);
6762 if (errmsg)
6763 errx(1, "rdomain %s: %s", id, errmsg);
6764
6765 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
6766 ifr.ifr_rdomainidifr_ifru.ifru_metric = rdomainid;
6767 if (ioctl(sock, SIOCSIFRDOMAIN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((159)))
, (caddr_t)&ifr) == -1)
6768 warn("SIOCSIFRDOMAIN");
6769}
6770
6771void
6772unsetrdomain(const char *ignored, int alsoignored)
6773{
6774 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
6775 ifr.ifr_rdomainidifr_ifru.ifru_metric = 0;
6776 if (ioctl(sock, SIOCSIFRDOMAIN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((159)))
, (caddr_t)&ifr) == -1)
6777 warn("SIOCSIFRDOMAIN");
6778}
6779#endif
6780
6781#ifndef SMALL
6782void
6783setpair(const char *val, int d)
6784{
6785 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
6786 if ((ifr.ifr_indexifr_ifru.ifru_index = if_nametoindex(val)) == 0) {
6787 errno(*__errno()) = ENOENT2;
6788 err(1, "patch %s", val);
6789 }
6790 if (ioctl(sock, SIOCSIFPAIR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((176)))
, (caddr_t)&ifr) == -1)
6791 warn("SIOCSIFPAIR");
6792}
6793
6794void
6795unsetpair(const char *val, int d)
6796{
6797 ifr.ifr_indexifr_ifru.ifru_index = 0;
6798 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
6799 if (ioctl(sock, SIOCSIFPAIR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((176)))
, (caddr_t)&ifr) == -1)
6800 warn("SIOCSIFPAIR");
6801}
6802#endif
6803
6804#ifdef SMALL
6805void
6806setignore(const char *id, int param)
6807{
6808 /* just digest the command */
6809}
6810#endif
6811
6812int
6813findmac(const char *mac)
6814{
6815 struct ifaddrs *ifap, *ifa;
6816 const char *ifnam = NULL((void *)0);
6817 struct if_clonereq *ifcr;
6818 int ret = 0;
6819
6820 ifcr = get_cloners();
6821 if (getifaddrs(&ifap) != 0)
6822 err(1, "getifaddrs");
6823
6824 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
6825 struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
6826
6827 if (sdl != NULL((void *)0) && sdl->sdl_alen &&
6828 (sdl->sdl_type == IFT_ETHER0x06 || sdl->sdl_type == IFT_CARP0xf7)) {
6829 if (strcmp(ether_ntoa((struct ether_addr *)LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen))),
6830 mac) == 0) {
6831 char *cp, *nam = ifa->ifa_name;
6832 int idx, skip = 0;
6833 size_t len;
6834
6835 /* MACs on cloned devices are ignored */
6836 for (len = 0; nam[len]; len++)
6837 if (isdigit((unsigned char)nam[len]))
6838 break;
6839 for (cp = ifcr->ifcr_buffer, idx = 0;
6840 idx < ifcr->ifcr_count;
6841 idx++, cp += IFNAMSIZ16) {
6842 if (strncmp(nam, cp, len) == 0) {
6843 skip = 1;
6844 break;
6845 }
6846 }
6847 if (skip)
6848 continue;
6849
6850 if (ifnam) { /* same MAC on multiple ifp */
6851 ret = 1;
6852 goto done;
6853 }
6854 ifnam = nam;
6855 }
6856 }
6857 }
6858 if (ifnam)
6859 printf("%s\n", ifnam);
6860done:
6861 free(ifcr->ifcr_buffer);
6862 freeifaddrs(ifap);
6863 return ret;
6864}