1 |
|
|
/* $OpenBSD: ifconfig.c,v 1.324 2016/06/15 19:39:33 gerhard 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/types.h> |
64 |
|
|
#include <sys/socket.h> |
65 |
|
|
#include <sys/ioctl.h> |
66 |
|
|
#include <sys/param.h> |
67 |
|
|
|
68 |
|
|
#include <net/if.h> |
69 |
|
|
#include <net/if_dl.h> |
70 |
|
|
#include <net/if_media.h> |
71 |
|
|
#include <net/if_types.h> |
72 |
|
|
#include <netinet/in.h> |
73 |
|
|
#include <netinet/in_var.h> |
74 |
|
|
#include <netinet6/in6_var.h> |
75 |
|
|
#include <netinet6/nd6.h> |
76 |
|
|
#include <arpa/inet.h> |
77 |
|
|
#include <netinet/ip_ipsp.h> |
78 |
|
|
#include <netinet/if_ether.h> |
79 |
|
|
#include <net/if_enc.h> |
80 |
|
|
#include <net80211/ieee80211.h> |
81 |
|
|
#include <net80211/ieee80211_ioctl.h> |
82 |
|
|
#include <net/pfvar.h> |
83 |
|
|
#include <net/if_pfsync.h> |
84 |
|
|
#include <net/if_pflow.h> |
85 |
|
|
#include <net/if_pppoe.h> |
86 |
|
|
#include <net/if_trunk.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.h> |
101 |
|
|
#include <stdio.h> |
102 |
|
|
#include <stdlib.h> |
103 |
|
|
#include <string.h> |
104 |
|
|
#include <unistd.h> |
105 |
|
|
#include <limits.h> |
106 |
|
|
#include <util.h> |
107 |
|
|
#include <ifaddrs.h> |
108 |
|
|
|
109 |
|
|
#include "brconfig.h" |
110 |
|
|
#ifndef SMALL |
111 |
|
|
#include <dev/usb/mbim.h> |
112 |
|
|
#include <dev/usb/if_umb.h> |
113 |
|
|
#endif /* SMALL */ |
114 |
|
|
|
115 |
|
|
#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) |
116 |
|
|
#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) |
117 |
|
|
|
118 |
|
|
#define HWFEATURESBITS \ |
119 |
|
|
"\024\1CSUM_IPv4\2CSUM_TCPv4\3CSUM_UDPv4" \ |
120 |
|
|
"\5VLAN_MTU\6VLAN_HWTAGGING\10CSUM_TCPv6" \ |
121 |
|
|
"\11CSUM_UDPv6\20WOL" |
122 |
|
|
|
123 |
|
|
struct ifreq ifr, ridreq; |
124 |
|
|
struct in_aliasreq in_addreq; |
125 |
|
|
struct in6_ifreq ifr6; |
126 |
|
|
struct in6_ifreq in6_ridreq; |
127 |
|
|
struct in6_aliasreq in6_addreq; |
128 |
|
|
struct sockaddr_in netmask; |
129 |
|
|
|
130 |
|
|
#ifndef SMALL |
131 |
|
|
struct ifaliasreq addreq; |
132 |
|
|
|
133 |
|
|
int wconfig = 0; |
134 |
|
|
int wcwconfig = 0; |
135 |
|
|
struct ifmpwreq imrsave; |
136 |
|
|
#endif /* SMALL */ |
137 |
|
|
|
138 |
|
|
char name[IFNAMSIZ]; |
139 |
|
|
int flags, xflags, setaddr, setipdst, doalias; |
140 |
|
|
u_long metric, mtu; |
141 |
|
|
int rdomainid; |
142 |
|
|
int llprio; |
143 |
|
|
int clearaddr, s; |
144 |
|
|
int newaddr = 0; |
145 |
|
|
int af = AF_INET; |
146 |
|
|
int explicit_prefix = 0; |
147 |
|
|
int Lflag = 1; |
148 |
|
|
|
149 |
|
|
int showmediaflag; |
150 |
|
|
int showcapsflag; |
151 |
|
|
int shownet80211chans; |
152 |
|
|
int shownet80211nodes; |
153 |
|
|
int showclasses; |
154 |
|
|
|
155 |
|
|
void notealias(const char *, int); |
156 |
|
|
void setifaddr(const char *, int); |
157 |
|
|
void setifrtlabel(const char *, int); |
158 |
|
|
void setiflladdr(const char *, int); |
159 |
|
|
void setifdstaddr(const char *, int); |
160 |
|
|
void setifflags(const char *, int); |
161 |
|
|
void setifxflags(const char *, int); |
162 |
|
|
void addaf(const char *, int); |
163 |
|
|
void removeaf(const char *, int); |
164 |
|
|
void setifbroadaddr(const char *, int); |
165 |
|
|
void setifmtu(const char *, int); |
166 |
|
|
void setifllprio(const char *, int); |
167 |
|
|
void setifnwid(const char *, int); |
168 |
|
|
void setifbssid(const char *, int); |
169 |
|
|
void setifnwkey(const char *, int); |
170 |
|
|
void setifwpa(const char *, int); |
171 |
|
|
void setifwpaprotos(const char *, int); |
172 |
|
|
void setifwpaakms(const char *, int); |
173 |
|
|
void setifwpaciphers(const char *, int); |
174 |
|
|
void setifwpagroupcipher(const char *, int); |
175 |
|
|
void setifwpakey(const char *, int); |
176 |
|
|
void setifchan(const char *, int); |
177 |
|
|
void setifscan(const char *, int); |
178 |
|
|
void setifnwflag(const char *, int); |
179 |
|
|
void unsetifnwflag(const char *, int); |
180 |
|
|
void setifnetmask(const char *, int); |
181 |
|
|
void setifprefixlen(const char *, int); |
182 |
|
|
void settunnel(const char *, const char *); |
183 |
|
|
void deletetunnel(const char *, int); |
184 |
|
|
void settunnelinst(const char *, int); |
185 |
|
|
void settunnelttl(const char *, int); |
186 |
|
|
void setvnetid(const char *, int); |
187 |
|
|
void delvnetid(const char *, int); |
188 |
|
|
void getvnetid(void); |
189 |
|
|
void setifparent(const char *, int); |
190 |
|
|
void delifparent(const char *, int); |
191 |
|
|
void getifparent(void); |
192 |
|
|
void setia6flags(const char *, int); |
193 |
|
|
void setia6pltime(const char *, int); |
194 |
|
|
void setia6vltime(const char *, int); |
195 |
|
|
void setia6lifetime(const char *, const char *); |
196 |
|
|
void setia6eui64(const char *, int); |
197 |
|
|
void setkeepalive(const char *, const char *); |
198 |
|
|
void unsetkeepalive(const char *, int); |
199 |
|
|
void setmedia(const char *, int); |
200 |
|
|
void setmediaopt(const char *, int); |
201 |
|
|
void setmediamode(const char *, int); |
202 |
|
|
void unsetmediamode(const char *, int); |
203 |
|
|
void clone_create(const char *, int); |
204 |
|
|
void clone_destroy(const char *, int); |
205 |
|
|
void unsetmediaopt(const char *, int); |
206 |
|
|
void setmediainst(const char *, int); |
207 |
|
|
void settimeslot(const char *, int); |
208 |
|
|
void timeslot_status(void); |
209 |
|
|
void setmpelabel(const char *, int); |
210 |
|
|
void process_mpw_commands(void); |
211 |
|
|
void setmpwencap(const char *, int); |
212 |
|
|
void setmpwlabel(const char *, const char *); |
213 |
|
|
void setmpwneighbor(const char *, int); |
214 |
|
|
void setmpwcontrolword(const char *, int); |
215 |
|
|
void setvlantag(const char *, int); |
216 |
|
|
void setvlandev(const char *, int); |
217 |
|
|
void unsetvlandev(const char *, int); |
218 |
|
|
void mpe_status(void); |
219 |
|
|
void mpw_status(void); |
220 |
|
|
void vlan_status(void); |
221 |
|
|
void setinstance(const char *, int); |
222 |
|
|
int main(int, char *[]); |
223 |
|
|
int prefix(void *val, int); |
224 |
|
|
void getifgroups(void); |
225 |
|
|
void setifgroup(const char *, int); |
226 |
|
|
void unsetifgroup(const char *, int); |
227 |
|
|
void setgroupattribs(char *, int, char *[]); |
228 |
|
|
int printgroup(char *, int); |
229 |
|
|
void setautoconf(const char *, int); |
230 |
|
|
void settrunkport(const char *, int); |
231 |
|
|
void unsettrunkport(const char *, int); |
232 |
|
|
void settrunkproto(const char *, int); |
233 |
|
|
void trunk_status(void); |
234 |
|
|
void list_cloners(void); |
235 |
|
|
|
236 |
|
|
#ifndef SMALL |
237 |
|
|
void carp_status(void); |
238 |
|
|
void setcarp_advbase(const char *,int); |
239 |
|
|
void setcarp_advskew(const char *, int); |
240 |
|
|
void setcarppeer(const char *, int); |
241 |
|
|
void unsetcarppeer(const char *, int); |
242 |
|
|
void setcarp_passwd(const char *, int); |
243 |
|
|
void setcarp_vhid(const char *, int); |
244 |
|
|
void setcarp_state(const char *, int); |
245 |
|
|
void setcarpdev(const char *, int); |
246 |
|
|
void setcarp_nodes(const char *, int); |
247 |
|
|
void setcarp_balancing(const char *, int); |
248 |
|
|
void setpfsync_syncdev(const char *, int); |
249 |
|
|
void setpfsync_maxupd(const char *, int); |
250 |
|
|
void unsetpfsync_syncdev(const char *, int); |
251 |
|
|
void setpfsync_syncpeer(const char *, int); |
252 |
|
|
void unsetpfsync_syncpeer(const char *, int); |
253 |
|
|
void setpfsync_defer(const char *, int); |
254 |
|
|
void pfsync_status(void); |
255 |
|
|
void setpppoe_dev(const char *,int); |
256 |
|
|
void setpppoe_svc(const char *,int); |
257 |
|
|
void setpppoe_ac(const char *,int); |
258 |
|
|
void pppoe_status(void); |
259 |
|
|
void setspppproto(const char *, int); |
260 |
|
|
void setspppname(const char *, int); |
261 |
|
|
void setspppkey(const char *, int); |
262 |
|
|
void setsppppeerproto(const char *, int); |
263 |
|
|
void setsppppeername(const char *, int); |
264 |
|
|
void setsppppeerkey(const char *, int); |
265 |
|
|
void setsppppeerflag(const char *, int); |
266 |
|
|
void unsetsppppeerflag(const char *, int); |
267 |
|
|
void sppp_status(void); |
268 |
|
|
void sppp_printproto(const char *, struct sauthreq *); |
269 |
|
|
void setifpriority(const char *, int); |
270 |
|
|
void setifpowersave(const char *, int); |
271 |
|
|
void setifmetric(const char *, int); |
272 |
|
|
void pflow_status(void); |
273 |
|
|
void pflow_addr(const char*, struct sockaddr_storage *); |
274 |
|
|
void setpflow_sender(const char *, int); |
275 |
|
|
void unsetpflow_sender(const char *, int); |
276 |
|
|
void setpflow_receiver(const char *, int); |
277 |
|
|
void unsetpflow_receiver(const char *, int); |
278 |
|
|
void setpflowproto(const char *, int); |
279 |
|
|
void setifipdst(const char *, int); |
280 |
|
|
void setifdesc(const char *, int); |
281 |
|
|
void unsetifdesc(const char *, int); |
282 |
|
|
void printifhwfeatures(const char *, int); |
283 |
|
|
void setpair(const char *, int); |
284 |
|
|
void unsetpair(const char *, int); |
285 |
|
|
void umb_status(void); |
286 |
|
|
void umb_printclasses(char *, int); |
287 |
|
|
int umb_parse_classes(const char *); |
288 |
|
|
void umb_setpin(const char *, int); |
289 |
|
|
void umb_chgpin(const char *, const char *); |
290 |
|
|
void umb_puk(const char *, const char *); |
291 |
|
|
void umb_pinop(int, int, const char *, const char *); |
292 |
|
|
void umb_apn(const char *, int); |
293 |
|
|
void umb_setclass(const char *, int); |
294 |
|
|
void umb_roaming(const char *, int); |
295 |
|
|
void utf16_to_char(uint16_t *, int, char *, size_t); |
296 |
|
|
int char_to_utf16(const char *, uint16_t *, size_t); |
297 |
|
|
#else |
298 |
|
|
void setignore(const char *, int); |
299 |
|
|
#endif |
300 |
|
|
|
301 |
|
|
/* |
302 |
|
|
* Media stuff. Whenever a media command is first performed, the |
303 |
|
|
* currently select media is grabbed for this interface. If `media' |
304 |
|
|
* is given, the current media word is modified. `mediaopt' commands |
305 |
|
|
* only modify the set and clear words. They then operate on the |
306 |
|
|
* current media word later. |
307 |
|
|
*/ |
308 |
|
|
uint64_t media_current; |
309 |
|
|
uint64_t mediaopt_set; |
310 |
|
|
uint64_t mediaopt_clear; |
311 |
|
|
|
312 |
|
|
int actions; /* Actions performed */ |
313 |
|
|
|
314 |
|
|
#define A_MEDIA 0x0001 /* media command */ |
315 |
|
|
#define A_MEDIAOPTSET 0x0002 /* mediaopt command */ |
316 |
|
|
#define A_MEDIAOPTCLR 0x0004 /* -mediaopt command */ |
317 |
|
|
#define A_MEDIAOPT (A_MEDIAOPTSET|A_MEDIAOPTCLR) |
318 |
|
|
#define A_MEDIAINST 0x0008 /* instance or inst command */ |
319 |
|
|
#define A_MEDIAMODE 0x0010 /* mode command */ |
320 |
|
|
#define A_SILENT 0x8000000 /* doing operation, do not print */ |
321 |
|
|
|
322 |
|
|
#define NEXTARG0 0xffffff |
323 |
|
|
#define NEXTARG 0xfffffe |
324 |
|
|
#define NEXTARG2 0xfffffd |
325 |
|
|
|
326 |
|
|
const struct cmd { |
327 |
|
|
char *c_name; |
328 |
|
|
int c_parameter; /* NEXTARG means next argv */ |
329 |
|
|
int c_action; /* defered action */ |
330 |
|
|
void (*c_func)(const char *, int); |
331 |
|
|
void (*c_func2)(const char *, const char *); |
332 |
|
|
} cmds[] = { |
333 |
|
|
{ "up", IFF_UP, 0, setifflags } , |
334 |
|
|
{ "down", -IFF_UP, 0, setifflags }, |
335 |
|
|
{ "arp", -IFF_NOARP, 0, setifflags }, |
336 |
|
|
{ "-arp", IFF_NOARP, 0, setifflags }, |
337 |
|
|
{ "debug", IFF_DEBUG, 0, setifflags }, |
338 |
|
|
{ "-debug", -IFF_DEBUG, 0, setifflags }, |
339 |
|
|
{ "alias", IFF_UP, 0, notealias }, |
340 |
|
|
{ "-alias", -IFF_UP, 0, notealias }, |
341 |
|
|
{ "delete", -IFF_UP, 0, notealias }, |
342 |
|
|
#ifdef notdef |
343 |
|
|
#define EN_SWABIPS 0x1000 |
344 |
|
|
{ "swabips", EN_SWABIPS, 0, setifflags }, |
345 |
|
|
{ "-swabips", -EN_SWABIPS, 0, setifflags }, |
346 |
|
|
#endif /* notdef */ |
347 |
|
|
{ "netmask", NEXTARG, 0, setifnetmask }, |
348 |
|
|
{ "mtu", NEXTARG, 0, setifmtu }, |
349 |
|
|
{ "nwid", NEXTARG, 0, setifnwid }, |
350 |
|
|
{ "-nwid", -1, 0, setifnwid }, |
351 |
|
|
{ "bssid", NEXTARG, 0, setifbssid }, |
352 |
|
|
{ "-bssid", -1, 0, setifbssid }, |
353 |
|
|
{ "nwkey", NEXTARG, 0, setifnwkey }, |
354 |
|
|
{ "-nwkey", -1, 0, setifnwkey }, |
355 |
|
|
{ "wpa", 1, 0, setifwpa }, |
356 |
|
|
{ "-wpa", 0, 0, setifwpa }, |
357 |
|
|
{ "wpaakms", NEXTARG, 0, setifwpaakms }, |
358 |
|
|
{ "wpaciphers", NEXTARG, 0, setifwpaciphers }, |
359 |
|
|
{ "wpagroupcipher", NEXTARG, 0, setifwpagroupcipher }, |
360 |
|
|
{ "wpaprotos", NEXTARG, 0, setifwpaprotos }, |
361 |
|
|
{ "wpakey", NEXTARG, 0, setifwpakey }, |
362 |
|
|
{ "-wpakey", -1, 0, setifwpakey }, |
363 |
|
|
{ "chan", NEXTARG0, 0, setifchan }, |
364 |
|
|
{ "-chan", -1, 0, setifchan }, |
365 |
|
|
{ "scan", NEXTARG0, 0, setifscan }, |
366 |
|
|
{ "broadcast", NEXTARG, 0, setifbroadaddr }, |
367 |
|
|
{ "prefixlen", NEXTARG, 0, setifprefixlen}, |
368 |
|
|
{ "vlan", NEXTARG, 0, setvlantag }, |
369 |
|
|
{ "vlandev", NEXTARG, 0, setvlandev }, |
370 |
|
|
{ "-vlandev", 1, 0, unsetvlandev }, |
371 |
|
|
{ "group", NEXTARG, 0, setifgroup }, |
372 |
|
|
{ "-group", NEXTARG, 0, unsetifgroup }, |
373 |
|
|
{ "autoconf", 1, 0, setautoconf }, |
374 |
|
|
{ "-autoconf", -1, 0, setautoconf }, |
375 |
|
|
{ "trunkport", NEXTARG, 0, settrunkport }, |
376 |
|
|
{ "-trunkport", NEXTARG, 0, unsettrunkport }, |
377 |
|
|
{ "trunkproto", NEXTARG, 0, settrunkproto }, |
378 |
|
|
{ "anycast", IN6_IFF_ANYCAST, 0, setia6flags }, |
379 |
|
|
{ "-anycast", -IN6_IFF_ANYCAST, 0, setia6flags }, |
380 |
|
|
{ "tentative", IN6_IFF_TENTATIVE, 0, setia6flags }, |
381 |
|
|
{ "-tentative", -IN6_IFF_TENTATIVE, 0, setia6flags }, |
382 |
|
|
{ "pltime", NEXTARG, 0, setia6pltime }, |
383 |
|
|
{ "vltime", NEXTARG, 0, setia6vltime }, |
384 |
|
|
{ "eui64", 0, 0, setia6eui64 }, |
385 |
|
|
{ "autoconfprivacy", -IFXF_INET6_NOPRIVACY, 0, setifxflags }, |
386 |
|
|
{ "-autoconfprivacy", IFXF_INET6_NOPRIVACY, 0, setifxflags }, |
387 |
|
|
#ifndef SMALL |
388 |
|
|
{ "hwfeatures", NEXTARG0, 0, printifhwfeatures }, |
389 |
|
|
{ "metric", NEXTARG, 0, setifmetric }, |
390 |
|
|
{ "powersave", NEXTARG0, 0, setifpowersave }, |
391 |
|
|
{ "-powersave", -1, 0, setifpowersave }, |
392 |
|
|
{ "priority", NEXTARG, 0, setifpriority }, |
393 |
|
|
{ "rtlabel", NEXTARG, 0, setifrtlabel }, |
394 |
|
|
{ "-rtlabel", -1, 0, setifrtlabel }, |
395 |
|
|
{ "rdomain", NEXTARG, 0, setinstance }, |
396 |
|
|
{ "mpls", IFXF_MPLS, 0, setifxflags }, |
397 |
|
|
{ "-mpls", -IFXF_MPLS, 0, setifxflags }, |
398 |
|
|
{ "mplslabel", NEXTARG, 0, setmpelabel }, |
399 |
|
|
{ "mpwlabel", NEXTARG2, 0, NULL, setmpwlabel }, |
400 |
|
|
{ "neighbor", NEXTARG, 0, setmpwneighbor }, |
401 |
|
|
{ "controlword", 1, 0, setmpwcontrolword }, |
402 |
|
|
{ "-controlword", 0, 0, setmpwcontrolword }, |
403 |
|
|
{ "encap", NEXTARG, 0, setmpwencap }, |
404 |
|
|
{ "advbase", NEXTARG, 0, setcarp_advbase }, |
405 |
|
|
{ "advskew", NEXTARG, 0, setcarp_advskew }, |
406 |
|
|
{ "carppeer", NEXTARG, 0, setcarppeer }, |
407 |
|
|
{ "-carppeer", 1, 0, unsetcarppeer }, |
408 |
|
|
{ "pass", NEXTARG, 0, setcarp_passwd }, |
409 |
|
|
{ "vhid", NEXTARG, 0, setcarp_vhid }, |
410 |
|
|
{ "state", NEXTARG, 0, setcarp_state }, |
411 |
|
|
{ "carpdev", NEXTARG, 0, setcarpdev }, |
412 |
|
|
{ "carpnodes", NEXTARG, 0, setcarp_nodes }, |
413 |
|
|
{ "balancing", NEXTARG, 0, setcarp_balancing }, |
414 |
|
|
{ "syncdev", NEXTARG, 0, setpfsync_syncdev }, |
415 |
|
|
{ "-syncdev", 1, 0, unsetpfsync_syncdev }, |
416 |
|
|
{ "syncif", NEXTARG, 0, setpfsync_syncdev }, |
417 |
|
|
{ "-syncif", 1, 0, unsetpfsync_syncdev }, |
418 |
|
|
{ "syncpeer", NEXTARG, 0, setpfsync_syncpeer }, |
419 |
|
|
{ "-syncpeer", 1, 0, unsetpfsync_syncpeer }, |
420 |
|
|
{ "maxupd", NEXTARG, 0, setpfsync_maxupd }, |
421 |
|
|
{ "defer", 1, 0, setpfsync_defer }, |
422 |
|
|
{ "-defer", 0, 0, setpfsync_defer }, |
423 |
|
|
/* giftunnel is for backward compat */ |
424 |
|
|
{ "giftunnel", NEXTARG2, 0, NULL, settunnel } , |
425 |
|
|
{ "tunnel", NEXTARG2, 0, NULL, settunnel } , |
426 |
|
|
{ "deletetunnel", 0, 0, deletetunnel } , |
427 |
|
|
{ "tunneldomain", NEXTARG, 0, settunnelinst } , |
428 |
|
|
{ "tunnelttl", NEXTARG, 0, settunnelttl } , |
429 |
|
|
{ "vnetid", NEXTARG, 0, setvnetid }, |
430 |
|
|
{ "-vnetid", 0, 0, delvnetid }, |
431 |
|
|
{ "parent", NEXTARG, 0, setifparent }, |
432 |
|
|
{ "-parent", 1, 0, delifparent }, |
433 |
|
|
{ "pppoedev", NEXTARG, 0, setpppoe_dev }, |
434 |
|
|
{ "pppoesvc", NEXTARG, 0, setpppoe_svc }, |
435 |
|
|
{ "-pppoesvc", 1, 0, setpppoe_svc }, |
436 |
|
|
{ "pppoeac", NEXTARG, 0, setpppoe_ac }, |
437 |
|
|
{ "-pppoeac", 1, 0, setpppoe_ac }, |
438 |
|
|
{ "timeslot", NEXTARG, 0, settimeslot }, |
439 |
|
|
{ "authproto", NEXTARG, 0, setspppproto }, |
440 |
|
|
{ "authname", NEXTARG, 0, setspppname }, |
441 |
|
|
{ "authkey", NEXTARG, 0, setspppkey }, |
442 |
|
|
{ "peerproto", NEXTARG, 0, setsppppeerproto }, |
443 |
|
|
{ "peername", NEXTARG, 0, setsppppeername }, |
444 |
|
|
{ "peerkey", NEXTARG, 0, setsppppeerkey }, |
445 |
|
|
{ "peerflag", NEXTARG, 0, setsppppeerflag }, |
446 |
|
|
{ "-peerflag", NEXTARG, 0, unsetsppppeerflag }, |
447 |
|
|
{ "nwflag", NEXTARG, 0, setifnwflag }, |
448 |
|
|
{ "-nwflag", NEXTARG, 0, unsetifnwflag }, |
449 |
|
|
{ "flowsrc", NEXTARG, 0, setpflow_sender }, |
450 |
|
|
{ "-flowsrc", 1, 0, unsetpflow_sender }, |
451 |
|
|
{ "flowdst", NEXTARG, 0, setpflow_receiver }, |
452 |
|
|
{ "-flowdst", 1, 0, unsetpflow_receiver }, |
453 |
|
|
{ "pflowproto", NEXTARG, 0, setpflowproto }, |
454 |
|
|
{ "-inet", AF_INET, 0, removeaf }, |
455 |
|
|
{ "-inet6", AF_INET6, 0, removeaf }, |
456 |
|
|
{ "keepalive", NEXTARG2, 0, NULL, setkeepalive }, |
457 |
|
|
{ "-keepalive", 1, 0, unsetkeepalive }, |
458 |
|
|
{ "add", NEXTARG, 0, bridge_add }, |
459 |
|
|
{ "del", NEXTARG, 0, bridge_delete }, |
460 |
|
|
{ "addspan", NEXTARG, 0, bridge_addspan }, |
461 |
|
|
{ "delspan", NEXTARG, 0, bridge_delspan }, |
462 |
|
|
{ "discover", NEXTARG, 0, setdiscover }, |
463 |
|
|
{ "-discover", NEXTARG, 0, unsetdiscover }, |
464 |
|
|
{ "blocknonip", NEXTARG, 0, setblocknonip }, |
465 |
|
|
{ "-blocknonip",NEXTARG, 0, unsetblocknonip }, |
466 |
|
|
{ "learn", NEXTARG, 0, setlearn }, |
467 |
|
|
{ "-learn", NEXTARG, 0, unsetlearn }, |
468 |
|
|
{ "stp", NEXTARG, 0, setstp }, |
469 |
|
|
{ "-stp", NEXTARG, 0, unsetstp }, |
470 |
|
|
{ "edge", NEXTARG, 0, setedge }, |
471 |
|
|
{ "-edge", NEXTARG, 0, unsetedge }, |
472 |
|
|
{ "autoedge", NEXTARG, 0, setautoedge }, |
473 |
|
|
{ "-autoedge", NEXTARG, 0, unsetautoedge }, |
474 |
|
|
{ "ptp", NEXTARG, 0, setptp }, |
475 |
|
|
{ "-ptp", NEXTARG, 0, unsetptp }, |
476 |
|
|
{ "autoptp", NEXTARG, 0, setautoptp }, |
477 |
|
|
{ "-autoptp", NEXTARG, 0, unsetautoptp }, |
478 |
|
|
{ "flush", 0, 0, bridge_flush }, |
479 |
|
|
{ "flushall", 0, 0, bridge_flushall }, |
480 |
|
|
{ "static", NEXTARG2, 0, NULL, bridge_addaddr }, |
481 |
|
|
{ "deladdr", NEXTARG, 0, bridge_deladdr }, |
482 |
|
|
{ "maxaddr", NEXTARG, 0, bridge_maxaddr }, |
483 |
|
|
{ "addr", 0, 0, bridge_addrs }, |
484 |
|
|
{ "hellotime", NEXTARG, 0, bridge_hellotime }, |
485 |
|
|
{ "fwddelay", NEXTARG, 0, bridge_fwddelay }, |
486 |
|
|
{ "maxage", NEXTARG, 0, bridge_maxage }, |
487 |
|
|
{ "proto", NEXTARG, 0, bridge_proto }, |
488 |
|
|
{ "ifpriority", NEXTARG2, 0, NULL, bridge_ifprio }, |
489 |
|
|
{ "ifcost", NEXTARG2, 0, NULL, bridge_ifcost }, |
490 |
|
|
{ "-ifcost", NEXTARG, 0, bridge_noifcost }, |
491 |
|
|
{ "timeout", NEXTARG, 0, bridge_timeout }, |
492 |
|
|
{ "holdcnt", NEXTARG, 0, bridge_holdcnt }, |
493 |
|
|
{ "spanpriority", NEXTARG, 0, bridge_priority }, |
494 |
|
|
{ "ipdst", NEXTARG, 0, setifipdst }, |
495 |
|
|
#if 0 |
496 |
|
|
/* XXX `rule` special-cased below */ |
497 |
|
|
{ "rule", 0, 0, bridge_rule }, |
498 |
|
|
#endif |
499 |
|
|
{ "rules", NEXTARG, 0, bridge_rules }, |
500 |
|
|
{ "rulefile", NEXTARG, 0, bridge_rulefile }, |
501 |
|
|
{ "flushrule", NEXTARG, 0, bridge_flushrule }, |
502 |
|
|
{ "description", NEXTARG, 0, setifdesc }, |
503 |
|
|
{ "descr", NEXTARG, 0, setifdesc }, |
504 |
|
|
{ "-description", 1, 0, unsetifdesc }, |
505 |
|
|
{ "-descr", 1, 0, unsetifdesc }, |
506 |
|
|
{ "wol", IFXF_WOL, 0, setifxflags }, |
507 |
|
|
{ "-wol", -IFXF_WOL, 0, setifxflags }, |
508 |
|
|
{ "pin", NEXTARG, 0, umb_setpin }, |
509 |
|
|
{ "chgpin", NEXTARG2, 0, NULL, umb_chgpin }, |
510 |
|
|
{ "puk", NEXTARG2, 0, NULL, umb_puk }, |
511 |
|
|
{ "apn", NEXTARG, 0, umb_apn }, |
512 |
|
|
{ "-apn", -1, 0, umb_apn }, |
513 |
|
|
{ "class", NEXTARG0, 0, umb_setclass }, |
514 |
|
|
{ "-class", -1, 0, umb_setclass }, |
515 |
|
|
{ "roaming", 1, 0, umb_roaming }, |
516 |
|
|
{ "-roaming", 0, 0, umb_roaming }, |
517 |
|
|
{ "patch", NEXTARG, 0, setpair }, |
518 |
|
|
{ "-patch", 1, 0, unsetpair }, |
519 |
|
|
#else /* SMALL */ |
520 |
|
|
{ "powersave", NEXTARG0, 0, setignore }, |
521 |
|
|
{ "priority", NEXTARG, 0, setignore }, |
522 |
|
|
{ "rtlabel", NEXTARG, 0, setignore }, |
523 |
|
|
{ "mpls", IFXF_MPLS, 0, setignore }, |
524 |
|
|
{ "nwflag", NEXTARG, 0, setignore }, |
525 |
|
|
{ "rdomain", NEXTARG, 0, setignore }, |
526 |
|
|
{ "-inet", AF_INET, 0, removeaf }, |
527 |
|
|
{ "-inet6", AF_INET6, 0, removeaf }, |
528 |
|
|
{ "description", NEXTARG, 0, setignore }, |
529 |
|
|
{ "descr", NEXTARG, 0, setignore }, |
530 |
|
|
{ "wol", IFXF_WOL, 0, setignore }, |
531 |
|
|
{ "-wol", -IFXF_WOL, 0, setignore }, |
532 |
|
|
#endif /* SMALL */ |
533 |
|
|
#if 0 |
534 |
|
|
/* XXX `create' special-cased below */ |
535 |
|
|
{ "create", 0, 0, clone_create } , |
536 |
|
|
#endif |
537 |
|
|
{ "destroy", 0, 0, clone_destroy } , |
538 |
|
|
{ "link0", IFF_LINK0, 0, setifflags } , |
539 |
|
|
{ "-link0", -IFF_LINK0, 0, setifflags } , |
540 |
|
|
{ "link1", IFF_LINK1, 0, setifflags } , |
541 |
|
|
{ "-link1", -IFF_LINK1, 0, setifflags } , |
542 |
|
|
{ "link2", IFF_LINK2, 0, setifflags } , |
543 |
|
|
{ "-link2", -IFF_LINK2, 0, setifflags } , |
544 |
|
|
{ "media", NEXTARG0, A_MEDIA, setmedia }, |
545 |
|
|
{ "mediaopt", NEXTARG, A_MEDIAOPTSET, setmediaopt }, |
546 |
|
|
{ "-mediaopt", NEXTARG, A_MEDIAOPTCLR, unsetmediaopt }, |
547 |
|
|
{ "mode", NEXTARG, A_MEDIAMODE, setmediamode }, |
548 |
|
|
{ "-mode", 0, A_MEDIAMODE, unsetmediamode }, |
549 |
|
|
{ "instance", NEXTARG, A_MEDIAINST, setmediainst }, |
550 |
|
|
{ "inst", NEXTARG, A_MEDIAINST, setmediainst }, |
551 |
|
|
{ "lladdr", NEXTARG, 0, setiflladdr }, |
552 |
|
|
{ "llprio", NEXTARG, 0, setifllprio }, |
553 |
|
|
{ NULL, /*src*/ 0, 0, setifaddr }, |
554 |
|
|
{ NULL, /*dst*/ 0, 0, setifdstaddr }, |
555 |
|
|
{ NULL, /*illegal*/0, 0, NULL }, |
556 |
|
|
}; |
557 |
|
|
|
558 |
|
|
int getinfo(struct ifreq *, int); |
559 |
|
|
void getsock(int); |
560 |
|
|
void printgroupattribs(char *); |
561 |
|
|
void printif(char *, int); |
562 |
|
|
void printb_status(unsigned short, unsigned char *); |
563 |
|
|
const char *get_linkstate(int, int); |
564 |
|
|
void status(int, struct sockaddr_dl *, int); |
565 |
|
|
void usage(int); |
566 |
|
|
const char *get_string(const char *, const char *, u_int8_t *, int *); |
567 |
|
|
void print_string(const u_int8_t *, int); |
568 |
|
|
char *sec2str(time_t); |
569 |
|
|
|
570 |
|
|
const char *get_media_type_string(uint64_t); |
571 |
|
|
const char *get_media_subtype_string(uint64_t); |
572 |
|
|
uint64_t get_media_mode(uint64_t, const char *); |
573 |
|
|
uint64_t get_media_subtype(uint64_t, const char *); |
574 |
|
|
uint64_t get_media_options(uint64_t, const char *); |
575 |
|
|
uint64_t lookup_media_word(const struct ifmedia_description *, uint64_t, |
576 |
|
|
const char *); |
577 |
|
|
void print_media_word(uint64_t, int, int); |
578 |
|
|
void process_media_commands(void); |
579 |
|
|
void init_current_media(void); |
580 |
|
|
|
581 |
|
|
unsigned long get_ts_map(int, int, int); |
582 |
|
|
|
583 |
|
|
void in_status(int); |
584 |
|
|
void in_getaddr(const char *, int); |
585 |
|
|
void in_getprefix(const char *, int); |
586 |
|
|
void in6_fillscopeid(struct sockaddr_in6 *sin6); |
587 |
|
|
void in6_alias(struct in6_ifreq *); |
588 |
|
|
void in6_status(int); |
589 |
|
|
void in6_getaddr(const char *, int); |
590 |
|
|
void in6_getprefix(const char *, int); |
591 |
|
|
void ieee80211_status(void); |
592 |
|
|
void ieee80211_listchans(void); |
593 |
|
|
void ieee80211_listnodes(void); |
594 |
|
|
void ieee80211_printnode(struct ieee80211_nodereq *); |
595 |
|
|
u_int getwpacipher(const char *name); |
596 |
|
|
void print_cipherset(u_int32_t cipherset); |
597 |
|
|
|
598 |
|
|
void spppauthinfo(struct sauthreq *spa, int d); |
599 |
|
|
|
600 |
|
|
/* Known address families */ |
601 |
|
|
const struct afswtch { |
602 |
|
|
char *af_name; |
603 |
|
|
short af_af; |
604 |
|
|
void (*af_status)(int); |
605 |
|
|
void (*af_getaddr)(const char *, int); |
606 |
|
|
void (*af_getprefix)(const char *, int); |
607 |
|
|
u_long af_difaddr; |
608 |
|
|
u_long af_aifaddr; |
609 |
|
|
caddr_t af_ridreq; |
610 |
|
|
caddr_t af_addreq; |
611 |
|
|
} afs[] = { |
612 |
|
|
#define C(x) ((caddr_t) &x) |
613 |
|
|
{ "inet", AF_INET, in_status, in_getaddr, in_getprefix, |
614 |
|
|
SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(in_addreq) }, |
615 |
|
|
{ "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, |
616 |
|
|
SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, C(in6_ridreq), C(in6_addreq) }, |
617 |
|
|
{ 0, 0, 0, 0 } |
618 |
|
|
}; |
619 |
|
|
|
620 |
|
|
const struct afswtch *afp; /*the address family being set or asked about*/ |
621 |
|
|
|
622 |
|
|
int ifaliases = 0; |
623 |
|
|
int aflag = 0; |
624 |
|
|
|
625 |
|
|
int |
626 |
|
|
main(int argc, char *argv[]) |
627 |
|
102 |
{ |
628 |
|
102 |
const struct afswtch *rafp = NULL; |
629 |
|
102 |
int create = 0; |
630 |
|
102 |
int Cflag = 0; |
631 |
|
102 |
int gflag = 0; |
632 |
|
|
int i; |
633 |
|
|
|
634 |
|
|
/* If no args at all, print all interfaces. */ |
635 |
✗✓ |
102 |
if (argc < 2) { |
636 |
|
|
aflag = 1; |
637 |
|
|
printif(NULL, 0); |
638 |
|
|
exit(0); |
639 |
|
|
} |
640 |
|
102 |
argc--, argv++; |
641 |
✗✓ |
102 |
if (*argv[0] == '-') { |
642 |
|
|
int nomore = 0; |
643 |
|
|
|
644 |
|
|
for (i = 1; argv[0][i]; i++) { |
645 |
|
|
switch (argv[0][i]) { |
646 |
|
|
case 'a': |
647 |
|
|
aflag = 1; |
648 |
|
|
nomore = 1; |
649 |
|
|
break; |
650 |
|
|
case 'A': |
651 |
|
|
aflag = 1; |
652 |
|
|
ifaliases = 1; |
653 |
|
|
nomore = 1; |
654 |
|
|
break; |
655 |
|
|
case 'g': |
656 |
|
|
gflag = 1; |
657 |
|
|
break; |
658 |
|
|
case 'C': |
659 |
|
|
Cflag = 1; |
660 |
|
|
nomore = 1; |
661 |
|
|
break; |
662 |
|
|
default: |
663 |
|
|
usage(1); |
664 |
|
|
break; |
665 |
|
|
} |
666 |
|
|
} |
667 |
|
|
if (nomore == 0) { |
668 |
|
|
argc--, argv++; |
669 |
|
|
if (argc < 1) |
670 |
|
|
usage(1); |
671 |
|
|
if (strlcpy(name, *argv, sizeof(name)) >= IFNAMSIZ) |
672 |
|
|
errx(1, "interface name '%s' too long", *argv); |
673 |
|
|
} |
674 |
✗✓ |
102 |
} else if (strlcpy(name, *argv, sizeof(name)) >= IFNAMSIZ) |
675 |
|
|
errx(1, "interface name '%s' too long", *argv); |
676 |
|
102 |
argc--, argv++; |
677 |
✓✗ |
102 |
if (argc > 0) { |
678 |
✓✓ |
298 |
for (afp = rafp = afs; rafp->af_name; rafp++) |
679 |
✓✓ |
204 |
if (strcmp(rafp->af_name, *argv) == 0) { |
680 |
|
8 |
afp = rafp; |
681 |
|
8 |
argc--; |
682 |
|
8 |
argv++; |
683 |
|
8 |
break; |
684 |
|
|
} |
685 |
|
102 |
rafp = afp; |
686 |
|
102 |
af = ifr.ifr_addr.sa_family = rafp->af_af; |
687 |
|
|
} |
688 |
✗✓ |
102 |
if (Cflag) { |
689 |
|
|
if (argc > 0 || aflag) |
690 |
|
|
usage(1); |
691 |
|
|
list_cloners(); |
692 |
|
|
exit(0); |
693 |
|
|
} |
694 |
✗✓ |
102 |
if (gflag) { |
695 |
|
|
if (argc == 0) |
696 |
|
|
printgroupattribs(name); |
697 |
|
|
else |
698 |
|
|
setgroupattribs(name, argc, argv); |
699 |
|
|
exit(0); |
700 |
|
|
} |
701 |
|
102 |
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
702 |
|
|
|
703 |
|
|
/* initialization */ |
704 |
|
102 |
in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; |
705 |
|
102 |
in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; |
706 |
|
|
|
707 |
|
|
/* |
708 |
|
|
* NOTE: We must special-case the `create' command right |
709 |
|
|
* here as we would otherwise fail in getinfo(). |
710 |
|
|
*/ |
711 |
✓✗✗✓
|
102 |
if (argc > 0 && strcmp(argv[0], "create") == 0) { |
712 |
|
|
clone_create(argv[0], 0); |
713 |
|
|
argc--, argv++; |
714 |
|
|
if (argc == 0) |
715 |
|
|
exit(0); |
716 |
|
|
} |
717 |
✓✗ |
102 |
if (aflag == 0) { |
718 |
✓✗✓✓
|
102 |
create = (argc > 0) && strcmp(argv[0], "destroy") != 0; |
719 |
|
102 |
(void)getinfo(&ifr, create); |
720 |
|
|
} |
721 |
|
|
|
722 |
✓✗✓✓
|
102 |
if (argc != 0 && af == AF_INET6) |
723 |
|
8 |
addaf(name, AF_INET6); |
724 |
|
|
|
725 |
✓✓ |
380 |
while (argc > 0) { |
726 |
|
|
const struct cmd *p; |
727 |
|
|
|
728 |
✓✓ |
23954 |
for (p = cmds; p->c_name; p++) |
729 |
✓✓ |
23860 |
if (strcmp(*argv, p->c_name) == 0) |
730 |
|
184 |
break; |
731 |
|
|
#ifndef SMALL |
732 |
✗✓ |
278 |
if (strcmp(*argv, "rule") == 0) { |
733 |
|
|
argc--, argv++; |
734 |
|
|
return bridge_rule(argc, argv, -1); |
735 |
|
|
} |
736 |
|
|
#endif |
737 |
✓✓✗✓
|
278 |
if (p->c_name == 0 && setaddr) |
738 |
|
|
for (i = setaddr; i > 0; i--) { |
739 |
|
|
p++; |
740 |
|
|
if (p->c_func == NULL) |
741 |
|
|
errx(1, "%s: bad value", *argv); |
742 |
|
|
} |
743 |
✗✓✗✗
|
278 |
if (p->c_func || p->c_func2) { |
744 |
✗✓ |
278 |
if (p->c_parameter == NEXTARG0) { |
745 |
|
|
const struct cmd *p0; |
746 |
|
|
int noarg = 1; |
747 |
|
|
|
748 |
|
|
if (argv[1]) { |
749 |
|
|
for (p0 = cmds; p0->c_name; p0++) |
750 |
|
|
if (strcmp(argv[1], |
751 |
|
|
p0->c_name) == 0) { |
752 |
|
|
noarg = 0; |
753 |
|
|
break; |
754 |
|
|
} |
755 |
|
|
} else |
756 |
|
|
noarg = 0; |
757 |
|
|
|
758 |
|
|
if (noarg == 0) |
759 |
|
|
(*p->c_func)(NULL, 0); |
760 |
|
|
else |
761 |
|
|
goto nextarg; |
762 |
✓✓ |
278 |
} else if (p->c_parameter == NEXTARG) { |
763 |
|
88 |
nextarg: |
764 |
✗✓ |
88 |
if (argv[1] == NULL) |
765 |
|
|
errx(1, "'%s' requires argument", |
766 |
|
|
p->c_name); |
767 |
|
88 |
(*p->c_func)(argv[1], 0); |
768 |
|
88 |
argc--, argv++; |
769 |
|
88 |
actions = actions | A_SILENT | p->c_action; |
770 |
✗✓ |
190 |
} else if (p->c_parameter == NEXTARG2) { |
771 |
|
|
if ((argv[1] == NULL) || |
772 |
|
|
(argv[2] == NULL)) |
773 |
|
|
errx(1, "'%s' requires 2 arguments", |
774 |
|
|
p->c_name); |
775 |
|
|
(*p->c_func2)(argv[1], argv[2]); |
776 |
|
|
argc -= 2; |
777 |
|
|
argv += 2; |
778 |
|
|
actions = actions | A_SILENT | p->c_action; |
779 |
|
|
} else { |
780 |
|
190 |
(*p->c_func)(*argv, p->c_parameter); |
781 |
|
190 |
actions = actions | A_SILENT | p->c_action; |
782 |
|
|
} |
783 |
|
|
} |
784 |
|
278 |
argc--, argv++; |
785 |
|
|
} |
786 |
|
|
|
787 |
✓✗✗✓
|
102 |
if (argc == 0 && actions == 0) { |
788 |
|
|
printif(ifr.ifr_name, aflag ? ifaliases : 1); |
789 |
|
|
exit(0); |
790 |
|
|
} |
791 |
|
|
|
792 |
|
|
/* Process any media commands that may have been issued. */ |
793 |
|
102 |
process_media_commands(); |
794 |
|
|
|
795 |
|
|
#ifndef SMALL |
796 |
|
|
/* Process mpw commands */ |
797 |
|
102 |
process_mpw_commands(); |
798 |
|
|
#endif |
799 |
|
|
|
800 |
✓✓✓✓
|
102 |
if (af == AF_INET6 && explicit_prefix == 0) { |
801 |
|
|
/* |
802 |
|
|
* Aggregatable address architecture defines all prefixes |
803 |
|
|
* are 64. So, it is convenient to set prefixlen to 64 if |
804 |
|
|
* it is not specified. |
805 |
|
|
*/ |
806 |
|
2 |
setifprefixlen("64", 0); |
807 |
|
|
/* in6_getprefix("64", MASK) if MASK is available here... */ |
808 |
|
|
} |
809 |
|
|
|
810 |
✓✓ |
102 |
if (clearaddr) { |
811 |
|
94 |
(void) strlcpy(rafp->af_ridreq, name, sizeof(ifr.ifr_name)); |
812 |
✓✓ |
94 |
if (ioctl(s, rafp->af_difaddr, rafp->af_ridreq) < 0) { |
813 |
✓✗✗✓
|
10 |
if (errno == EADDRNOTAVAIL && (doalias >= 0)) { |
814 |
|
|
/* means no previous address for interface */ |
815 |
|
|
} else |
816 |
|
|
err(1, "SIOCDIFADDR"); |
817 |
|
|
} |
818 |
|
|
} |
819 |
✓✓ |
102 |
if (newaddr) { |
820 |
|
94 |
(void) strlcpy(rafp->af_addreq, name, sizeof(ifr.ifr_name)); |
821 |
✗✓ |
94 |
if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0) |
822 |
|
|
err(1, "SIOCAIFADDR"); |
823 |
|
|
} |
824 |
|
102 |
exit(0); |
825 |
|
|
} |
826 |
|
|
|
827 |
|
|
void |
828 |
|
|
getsock(int naf) |
829 |
|
102 |
{ |
830 |
|
|
static int oaf = -1; |
831 |
|
|
|
832 |
✗✓ |
102 |
if (oaf == naf) |
833 |
|
|
return; |
834 |
✗✓ |
102 |
if (oaf != -1) |
835 |
|
|
close(s); |
836 |
|
102 |
s = socket(naf, SOCK_DGRAM, 0); |
837 |
✗✓ |
102 |
if (s < 0) |
838 |
|
|
oaf = -1; |
839 |
|
|
else |
840 |
|
102 |
oaf = naf; |
841 |
|
|
} |
842 |
|
|
|
843 |
|
|
int |
844 |
|
|
getinfo(struct ifreq *ifr, int create) |
845 |
|
102 |
{ |
846 |
|
|
|
847 |
|
102 |
getsock(af); |
848 |
✗✓ |
102 |
if (s < 0) |
849 |
|
|
err(1, "socket"); |
850 |
✗✓ |
102 |
if (!isdigit((unsigned char)name[strlen(name) - 1])) |
851 |
|
|
return (-1); /* ignore groups here */ |
852 |
✓✓ |
102 |
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)ifr) < 0) { |
853 |
|
4 |
int oerrno = errno; |
854 |
|
|
|
855 |
✗✓ |
4 |
if (!create) |
856 |
|
|
return (-1); |
857 |
✗✓ |
4 |
if (ioctl(s, SIOCIFCREATE, (caddr_t)ifr) < 0) { |
858 |
|
|
errno = oerrno; |
859 |
|
|
return (-1); |
860 |
|
|
} |
861 |
✗✓ |
4 |
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)ifr) < 0) |
862 |
|
|
return (-1); |
863 |
|
|
} |
864 |
|
102 |
flags = ifr->ifr_flags & 0xffff; |
865 |
✗✓ |
102 |
if (ioctl(s, SIOCGIFXFLAGS, (caddr_t)ifr) < 0) |
866 |
|
|
ifr->ifr_flags = 0; |
867 |
|
102 |
xflags = ifr->ifr_flags; |
868 |
✗✓ |
102 |
if (ioctl(s, SIOCGIFMETRIC, (caddr_t)ifr) < 0) |
869 |
|
|
metric = 0; |
870 |
|
|
else |
871 |
|
102 |
metric = ifr->ifr_metric; |
872 |
|
|
#ifdef SMALL |
873 |
|
|
if (ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0) |
874 |
|
|
#else |
875 |
✓✗✗✓
|
102 |
if (is_bridge(name) || ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0) |
876 |
|
|
#endif |
877 |
|
|
mtu = 0; |
878 |
|
|
else |
879 |
|
102 |
mtu = ifr->ifr_mtu; |
880 |
|
|
#ifndef SMALL |
881 |
✗✓ |
102 |
if (ioctl(s, SIOCGIFRDOMAIN, (caddr_t)ifr) < 0) |
882 |
|
|
rdomainid = 0; |
883 |
|
|
else |
884 |
|
102 |
rdomainid = ifr->ifr_rdomainid; |
885 |
|
|
#endif |
886 |
✗✓ |
102 |
if (ioctl(s, SIOCGIFLLPRIO, (caddr_t)ifr) < 0) |
887 |
|
|
llprio = 0; |
888 |
|
|
else |
889 |
|
102 |
llprio = ifr->ifr_llprio; |
890 |
|
|
|
891 |
|
102 |
return (0); |
892 |
|
|
} |
893 |
|
|
|
894 |
|
|
int |
895 |
|
|
printgroup(char *groupname, int ifaliases) |
896 |
|
|
{ |
897 |
|
|
struct ifgroupreq ifgr; |
898 |
|
|
struct ifg_req *ifg; |
899 |
|
|
int len, cnt = 0; |
900 |
|
|
|
901 |
|
|
getsock(AF_INET); |
902 |
|
|
bzero(&ifgr, sizeof(ifgr)); |
903 |
|
|
strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); |
904 |
|
|
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) { |
905 |
|
|
if (errno == EINVAL || errno == ENOTTY || |
906 |
|
|
errno == ENOENT) |
907 |
|
|
return (-1); |
908 |
|
|
else |
909 |
|
|
err(1, "SIOCGIFGMEMB"); |
910 |
|
|
} |
911 |
|
|
|
912 |
|
|
len = ifgr.ifgr_len; |
913 |
|
|
if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) |
914 |
|
|
err(1, "printgroup"); |
915 |
|
|
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) |
916 |
|
|
err(1, "SIOCGIFGMEMB"); |
917 |
|
|
|
918 |
|
|
for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req); |
919 |
|
|
ifg++) { |
920 |
|
|
len -= sizeof(struct ifg_req); |
921 |
|
|
printif(ifg->ifgrq_member, ifaliases); |
922 |
|
|
cnt++; |
923 |
|
|
} |
924 |
|
|
free(ifgr.ifgr_groups); |
925 |
|
|
|
926 |
|
|
return (cnt); |
927 |
|
|
} |
928 |
|
|
|
929 |
|
|
void |
930 |
|
|
printgroupattribs(char *groupname) |
931 |
|
|
{ |
932 |
|
|
struct ifgroupreq ifgr; |
933 |
|
|
|
934 |
|
|
getsock(AF_INET); |
935 |
|
|
bzero(&ifgr, sizeof(ifgr)); |
936 |
|
|
strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); |
937 |
|
|
if (ioctl(s, SIOCGIFGATTR, (caddr_t)&ifgr) == -1) |
938 |
|
|
err(1, "SIOCGIFGATTR"); |
939 |
|
|
|
940 |
|
|
printf("%s:", groupname); |
941 |
|
|
printf(" carp demote count %d", ifgr.ifgr_attrib.ifg_carp_demoted); |
942 |
|
|
printf("\n"); |
943 |
|
|
} |
944 |
|
|
|
945 |
|
|
void |
946 |
|
|
setgroupattribs(char *groupname, int argc, char *argv[]) |
947 |
|
|
{ |
948 |
|
|
const char *errstr; |
949 |
|
|
char *p = argv[0]; |
950 |
|
|
int neg = 1; |
951 |
|
|
|
952 |
|
|
struct ifgroupreq ifgr; |
953 |
|
|
|
954 |
|
|
getsock(AF_INET); |
955 |
|
|
bzero(&ifgr, sizeof(ifgr)); |
956 |
|
|
strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); |
957 |
|
|
|
958 |
|
|
if (argc > 1) { |
959 |
|
|
neg = strtonum(argv[1], 0, 128, &errstr); |
960 |
|
|
if (errstr) |
961 |
|
|
errx(1, "invalid carp demotion: %s", errstr); |
962 |
|
|
} |
963 |
|
|
|
964 |
|
|
if (p[0] == '-') { |
965 |
|
|
neg = neg * -1; |
966 |
|
|
p++; |
967 |
|
|
} |
968 |
|
|
if (!strcmp(p, "carpdemote")) |
969 |
|
|
ifgr.ifgr_attrib.ifg_carp_demoted = neg; |
970 |
|
|
else |
971 |
|
|
usage(1); |
972 |
|
|
|
973 |
|
|
if (ioctl(s, SIOCSIFGATTR, (caddr_t)&ifgr) == -1) |
974 |
|
|
err(1, "SIOCSIFGATTR"); |
975 |
|
|
} |
976 |
|
|
|
977 |
|
|
void |
978 |
|
|
printif(char *ifname, int ifaliases) |
979 |
|
|
{ |
980 |
|
|
struct ifaddrs *ifap, *ifa; |
981 |
|
|
struct if_data *ifdata; |
982 |
|
|
const char *namep; |
983 |
|
|
char *oname = NULL; |
984 |
|
|
struct ifreq *ifrp; |
985 |
|
|
int count = 0, noinet = 1; |
986 |
|
|
size_t nlen = 0; |
987 |
|
|
|
988 |
|
|
if (aflag) |
989 |
|
|
ifname = NULL; |
990 |
|
|
if (ifname) { |
991 |
|
|
if ((oname = strdup(ifname)) == NULL) |
992 |
|
|
err(1, "strdup"); |
993 |
|
|
nlen = strlen(oname); |
994 |
|
|
/* is it a group? */ |
995 |
|
|
if (nlen && !isdigit((unsigned char)oname[nlen - 1])) |
996 |
|
|
if (printgroup(oname, ifaliases) != -1) { |
997 |
|
|
free(oname); |
998 |
|
|
return; |
999 |
|
|
} |
1000 |
|
|
} |
1001 |
|
|
|
1002 |
|
|
if (getifaddrs(&ifap) != 0) |
1003 |
|
|
err(1, "getifaddrs"); |
1004 |
|
|
|
1005 |
|
|
namep = NULL; |
1006 |
|
|
for (ifa = ifap; ifa; ifa = ifa->ifa_next) { |
1007 |
|
|
if (oname) { |
1008 |
|
|
if (nlen && isdigit((unsigned char)oname[nlen - 1])) { |
1009 |
|
|
/* must have exact match */ |
1010 |
|
|
if (strcmp(oname, ifa->ifa_name) != 0) |
1011 |
|
|
continue; |
1012 |
|
|
} else { |
1013 |
|
|
/* partial match OK if it ends w/ digit */ |
1014 |
|
|
if (strncmp(oname, ifa->ifa_name, nlen) != 0 || |
1015 |
|
|
!isdigit((unsigned char)ifa->ifa_name[nlen])) |
1016 |
|
|
continue; |
1017 |
|
|
} |
1018 |
|
|
} |
1019 |
|
|
/* quickhack: sizeof(ifr) < sizeof(ifr6) */ |
1020 |
|
|
if (ifa->ifa_addr->sa_family == AF_INET6) { |
1021 |
|
|
memset(&ifr6, 0, sizeof(ifr6)); |
1022 |
|
|
memcpy(&ifr6.ifr_addr, ifa->ifa_addr, |
1023 |
|
|
MINIMUM(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len)); |
1024 |
|
|
ifrp = (struct ifreq *)&ifr6; |
1025 |
|
|
} else { |
1026 |
|
|
memset(&ifr, 0, sizeof(ifr)); |
1027 |
|
|
memcpy(&ifr.ifr_addr, ifa->ifa_addr, |
1028 |
|
|
MINIMUM(sizeof(ifr.ifr_addr), ifa->ifa_addr->sa_len)); |
1029 |
|
|
ifrp = 𝔦 |
1030 |
|
|
} |
1031 |
|
|
strlcpy(name, ifa->ifa_name, sizeof(name)); |
1032 |
|
|
strlcpy(ifrp->ifr_name, ifa->ifa_name, sizeof(ifrp->ifr_name)); |
1033 |
|
|
|
1034 |
|
|
if (ifa->ifa_addr->sa_family == AF_LINK) { |
1035 |
|
|
namep = ifa->ifa_name; |
1036 |
|
|
if (getinfo(ifrp, 0) < 0) |
1037 |
|
|
continue; |
1038 |
|
|
ifdata = ifa->ifa_data; |
1039 |
|
|
status(1, (struct sockaddr_dl *)ifa->ifa_addr, |
1040 |
|
|
ifdata->ifi_link_state); |
1041 |
|
|
count++; |
1042 |
|
|
noinet = 1; |
1043 |
|
|
continue; |
1044 |
|
|
} |
1045 |
|
|
|
1046 |
|
|
if (!namep || !strcmp(namep, ifa->ifa_name)) { |
1047 |
|
|
const struct afswtch *p; |
1048 |
|
|
|
1049 |
|
|
if (ifa->ifa_addr->sa_family == AF_INET && |
1050 |
|
|
ifaliases == 0 && noinet == 0) |
1051 |
|
|
continue; |
1052 |
|
|
if ((p = afp) != NULL) { |
1053 |
|
|
if (ifa->ifa_addr->sa_family == p->af_af) |
1054 |
|
|
p->af_status(1); |
1055 |
|
|
} else { |
1056 |
|
|
for (p = afs; p->af_name; p++) { |
1057 |
|
|
if (ifa->ifa_addr->sa_family == |
1058 |
|
|
p->af_af) |
1059 |
|
|
p->af_status(0); |
1060 |
|
|
} |
1061 |
|
|
} |
1062 |
|
|
count++; |
1063 |
|
|
if (ifa->ifa_addr->sa_family == AF_INET) |
1064 |
|
|
noinet = 0; |
1065 |
|
|
continue; |
1066 |
|
|
} |
1067 |
|
|
} |
1068 |
|
|
freeifaddrs(ifap); |
1069 |
|
|
free(oname); |
1070 |
|
|
if (count == 0) { |
1071 |
|
|
fprintf(stderr, "%s: no such interface\n", name); |
1072 |
|
|
exit(1); |
1073 |
|
|
} |
1074 |
|
|
} |
1075 |
|
|
|
1076 |
|
|
/*ARGSUSED*/ |
1077 |
|
|
void |
1078 |
|
|
clone_create(const char *addr, int param) |
1079 |
|
|
{ |
1080 |
|
|
|
1081 |
|
|
/* We're called early... */ |
1082 |
|
|
getsock(AF_INET); |
1083 |
|
|
|
1084 |
|
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
1085 |
|
|
if (ioctl(s, SIOCIFCREATE, &ifr) == -1) |
1086 |
|
|
err(1, "SIOCIFCREATE"); |
1087 |
|
|
} |
1088 |
|
|
|
1089 |
|
|
/*ARGSUSED*/ |
1090 |
|
|
void |
1091 |
|
|
clone_destroy(const char *addr, int param) |
1092 |
|
4 |
{ |
1093 |
|
|
|
1094 |
|
4 |
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
1095 |
✗✓ |
4 |
if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) |
1096 |
|
|
err(1, "SIOCIFDESTROY"); |
1097 |
|
4 |
} |
1098 |
|
|
|
1099 |
|
|
void |
1100 |
|
|
list_cloners(void) |
1101 |
|
|
{ |
1102 |
|
|
struct if_clonereq ifcr; |
1103 |
|
|
char *cp, *buf; |
1104 |
|
|
int idx; |
1105 |
|
|
|
1106 |
|
|
memset(&ifcr, 0, sizeof(ifcr)); |
1107 |
|
|
|
1108 |
|
|
getsock(AF_INET); |
1109 |
|
|
|
1110 |
|
|
if (ioctl(s, SIOCIFGCLONERS, &ifcr) == -1) |
1111 |
|
|
err(1, "SIOCIFGCLONERS for count"); |
1112 |
|
|
|
1113 |
|
|
buf = calloc(ifcr.ifcr_total, IFNAMSIZ); |
1114 |
|
|
if (buf == NULL) |
1115 |
|
|
err(1, "unable to allocate cloner name buffer"); |
1116 |
|
|
|
1117 |
|
|
ifcr.ifcr_count = ifcr.ifcr_total; |
1118 |
|
|
ifcr.ifcr_buffer = buf; |
1119 |
|
|
|
1120 |
|
|
if (ioctl(s, SIOCIFGCLONERS, &ifcr) == -1) |
1121 |
|
|
err(1, "SIOCIFGCLONERS for names"); |
1122 |
|
|
|
1123 |
|
|
/* |
1124 |
|
|
* In case some disappeared in the mean time, clamp it down. |
1125 |
|
|
*/ |
1126 |
|
|
if (ifcr.ifcr_count > ifcr.ifcr_total) |
1127 |
|
|
ifcr.ifcr_count = ifcr.ifcr_total; |
1128 |
|
|
|
1129 |
|
|
qsort(buf, ifcr.ifcr_count, IFNAMSIZ, |
1130 |
|
|
(int(*)(const void *, const void *))strcmp); |
1131 |
|
|
|
1132 |
|
|
for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) { |
1133 |
|
|
if (idx > 0) |
1134 |
|
|
putchar(' '); |
1135 |
|
|
printf("%s", cp); |
1136 |
|
|
} |
1137 |
|
|
|
1138 |
|
|
putchar('\n'); |
1139 |
|
|
free(buf); |
1140 |
|
|
} |
1141 |
|
|
|
1142 |
|
|
#define RIDADDR 0 |
1143 |
|
|
#define ADDR 1 |
1144 |
|
|
#define MASK 2 |
1145 |
|
|
#define DSTADDR 3 |
1146 |
|
|
|
1147 |
|
|
/*ARGSUSED*/ |
1148 |
|
|
void |
1149 |
|
|
setifaddr(const char *addr, int param) |
1150 |
|
94 |
{ |
1151 |
|
|
/* |
1152 |
|
|
* Delay the ioctl to set the interface addr until flags are all set. |
1153 |
|
|
* The address interpretation may depend on the flags, |
1154 |
|
|
* and the flags may change when the address is set. |
1155 |
|
|
*/ |
1156 |
|
94 |
setaddr++; |
1157 |
✓✗ |
94 |
if (doalias >= 0) |
1158 |
|
94 |
newaddr = 1; |
1159 |
✓✗ |
94 |
if (doalias == 0) |
1160 |
|
94 |
clearaddr = 1; |
1161 |
|
94 |
afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR)); |
1162 |
|
94 |
} |
1163 |
|
|
|
1164 |
|
|
#ifndef SMALL |
1165 |
|
|
void |
1166 |
|
|
setifrtlabel(const char *label, int d) |
1167 |
|
|
{ |
1168 |
|
|
if (d != 0) |
1169 |
|
|
ifr.ifr_data = (caddr_t)(const char *)""; |
1170 |
|
|
else |
1171 |
|
|
ifr.ifr_data = (caddr_t)label; |
1172 |
|
|
if (ioctl(s, SIOCSIFRTLABEL, &ifr) < 0) |
1173 |
|
|
warn("SIOCSIFRTLABEL"); |
1174 |
|
|
} |
1175 |
|
|
#endif |
1176 |
|
|
|
1177 |
|
|
/* ARGSUSED */ |
1178 |
|
|
void |
1179 |
|
|
setifnetmask(const char *addr, int ignored) |
1180 |
|
|
{ |
1181 |
|
|
afp->af_getaddr(addr, MASK); |
1182 |
|
|
} |
1183 |
|
|
|
1184 |
|
|
/* ARGSUSED */ |
1185 |
|
|
void |
1186 |
|
|
setifbroadaddr(const char *addr, int ignored) |
1187 |
|
|
{ |
1188 |
|
|
afp->af_getaddr(addr, DSTADDR); |
1189 |
|
|
} |
1190 |
|
|
|
1191 |
|
|
#ifndef SMALL |
1192 |
|
|
/* ARGSUSED */ |
1193 |
|
|
void |
1194 |
|
|
setifdesc(const char *val, int ignored) |
1195 |
|
|
{ |
1196 |
|
|
ifr.ifr_data = (caddr_t)val; |
1197 |
|
|
if (ioctl(s, SIOCSIFDESCR, &ifr) < 0) |
1198 |
|
|
warn("SIOCSIFDESCR"); |
1199 |
|
|
} |
1200 |
|
|
|
1201 |
|
|
/* ARGSUSED */ |
1202 |
|
|
void |
1203 |
|
|
unsetifdesc(const char *noval, int ignored) |
1204 |
|
|
{ |
1205 |
|
|
ifr.ifr_data = (caddr_t)(const char *)""; |
1206 |
|
|
if (ioctl(s, SIOCSIFDESCR, &ifr) < 0) |
1207 |
|
|
warn("SIOCSIFDESCR"); |
1208 |
|
|
} |
1209 |
|
|
|
1210 |
|
|
/* ARGSUSED */ |
1211 |
|
|
void |
1212 |
|
|
setifipdst(const char *addr, int ignored) |
1213 |
|
|
{ |
1214 |
|
|
in_getaddr(addr, DSTADDR); |
1215 |
|
|
setipdst++; |
1216 |
|
|
clearaddr = 0; |
1217 |
|
|
newaddr = 0; |
1218 |
|
|
} |
1219 |
|
|
#endif |
1220 |
|
|
|
1221 |
|
|
#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) |
1222 |
|
|
/*ARGSUSED*/ |
1223 |
|
|
void |
1224 |
|
|
notealias(const char *addr, int param) |
1225 |
|
|
{ |
1226 |
|
|
if (setaddr && doalias == 0 && param < 0) |
1227 |
|
|
memcpy(rqtosa(af_ridreq), rqtosa(af_addreq), |
1228 |
|
|
rqtosa(af_addreq)->sa_len); |
1229 |
|
|
doalias = param; |
1230 |
|
|
if (param < 0) { |
1231 |
|
|
clearaddr = 1; |
1232 |
|
|
newaddr = 0; |
1233 |
|
|
} else |
1234 |
|
|
clearaddr = 0; |
1235 |
|
|
} |
1236 |
|
|
|
1237 |
|
|
/*ARGSUSED*/ |
1238 |
|
|
void |
1239 |
|
|
setifdstaddr(const char *addr, int param) |
1240 |
|
|
{ |
1241 |
|
|
setaddr++; |
1242 |
|
|
afp->af_getaddr(addr, DSTADDR); |
1243 |
|
|
} |
1244 |
|
|
|
1245 |
|
|
/* |
1246 |
|
|
* Note: doing an SIOCGIFFLAGS scribbles on the union portion |
1247 |
|
|
* of the ifreq structure, which may confuse other parts of ifconfig. |
1248 |
|
|
* Make a private copy so we can avoid that. |
1249 |
|
|
*/ |
1250 |
|
|
/* ARGSUSED */ |
1251 |
|
|
void |
1252 |
|
|
setifflags(const char *vname, int value) |
1253 |
|
90 |
{ |
1254 |
|
|
struct ifreq my_ifr; |
1255 |
|
|
|
1256 |
|
90 |
bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); |
1257 |
|
|
|
1258 |
✗✓ |
90 |
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) |
1259 |
|
|
err(1, "SIOCGIFFLAGS"); |
1260 |
|
90 |
(void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name)); |
1261 |
|
90 |
flags = my_ifr.ifr_flags; |
1262 |
|
|
|
1263 |
✓✓ |
90 |
if (value < 0) { |
1264 |
|
2 |
value = -value; |
1265 |
|
2 |
flags &= ~value; |
1266 |
|
|
} else |
1267 |
|
88 |
flags |= value; |
1268 |
|
90 |
my_ifr.ifr_flags = flags; |
1269 |
✗✓ |
90 |
if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) |
1270 |
|
|
err(1, "SIOCSIFFLAGS"); |
1271 |
|
90 |
} |
1272 |
|
|
|
1273 |
|
|
/* ARGSUSED */ |
1274 |
|
|
void |
1275 |
|
|
setifxflags(const char *vname, int value) |
1276 |
|
|
{ |
1277 |
|
|
struct ifreq my_ifr; |
1278 |
|
|
|
1279 |
|
|
bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); |
1280 |
|
|
|
1281 |
|
|
if (ioctl(s, SIOCGIFXFLAGS, (caddr_t)&my_ifr) < 0) |
1282 |
|
|
warn("SIOCGIFXFLAGS"); |
1283 |
|
|
(void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name)); |
1284 |
|
|
xflags = my_ifr.ifr_flags; |
1285 |
|
|
|
1286 |
|
|
if (value < 0) { |
1287 |
|
|
value = -value; |
1288 |
|
|
xflags &= ~value; |
1289 |
|
|
} else |
1290 |
|
|
xflags |= value; |
1291 |
|
|
my_ifr.ifr_flags = xflags; |
1292 |
|
|
if (ioctl(s, SIOCSIFXFLAGS, (caddr_t)&my_ifr) < 0) |
1293 |
|
|
warn("SIOCSIFXFLAGS"); |
1294 |
|
|
} |
1295 |
|
|
|
1296 |
|
|
void |
1297 |
|
|
addaf(const char *vname, int value) |
1298 |
|
10 |
{ |
1299 |
|
|
struct if_afreq ifar; |
1300 |
|
|
|
1301 |
|
10 |
strlcpy(ifar.ifar_name, name, sizeof(ifar.ifar_name)); |
1302 |
|
10 |
ifar.ifar_af = value; |
1303 |
✗✓ |
10 |
if (ioctl(s, SIOCIFAFATTACH, (caddr_t)&ifar) < 0) |
1304 |
|
|
warn("SIOCIFAFATTACH"); |
1305 |
|
10 |
} |
1306 |
|
|
|
1307 |
|
|
void |
1308 |
|
|
removeaf(const char *vname, int value) |
1309 |
|
|
{ |
1310 |
|
|
struct if_afreq ifar; |
1311 |
|
|
|
1312 |
|
|
strlcpy(ifar.ifar_name, name, sizeof(ifar.ifar_name)); |
1313 |
|
|
ifar.ifar_af = value; |
1314 |
|
|
if (ioctl(s, SIOCIFAFDETACH, (caddr_t)&ifar) < 0) |
1315 |
|
|
warn("SIOCIFAFDETACH"); |
1316 |
|
|
} |
1317 |
|
|
|
1318 |
|
|
void |
1319 |
|
|
setia6flags(const char *vname, int value) |
1320 |
|
|
{ |
1321 |
|
|
|
1322 |
|
|
if (value < 0) { |
1323 |
|
|
value = -value; |
1324 |
|
|
in6_addreq.ifra_flags &= ~value; |
1325 |
|
|
} else |
1326 |
|
|
in6_addreq.ifra_flags |= value; |
1327 |
|
|
} |
1328 |
|
|
|
1329 |
|
|
void |
1330 |
|
|
setia6pltime(const char *val, int d) |
1331 |
|
|
{ |
1332 |
|
|
|
1333 |
|
|
setia6lifetime("pltime", val); |
1334 |
|
|
} |
1335 |
|
|
|
1336 |
|
|
void |
1337 |
|
|
setia6vltime(const char *val, int d) |
1338 |
|
|
{ |
1339 |
|
|
|
1340 |
|
|
setia6lifetime("vltime", val); |
1341 |
|
|
} |
1342 |
|
|
|
1343 |
|
|
void |
1344 |
|
|
setia6lifetime(const char *cmd, const char *val) |
1345 |
|
|
{ |
1346 |
|
|
const char *errmsg = NULL; |
1347 |
|
|
time_t newval, t; |
1348 |
|
|
|
1349 |
|
|
newval = strtonum(val, 0, 1000000, &errmsg); |
1350 |
|
|
if (errmsg) |
1351 |
|
|
errx(1, "invalid %s %s: %s", cmd, val, errmsg); |
1352 |
|
|
|
1353 |
|
|
t = time(NULL); |
1354 |
|
|
|
1355 |
|
|
if (afp->af_af != AF_INET6) |
1356 |
|
|
errx(1, "%s not allowed for the AF", cmd); |
1357 |
|
|
if (strcmp(cmd, "vltime") == 0) { |
1358 |
|
|
in6_addreq.ifra_lifetime.ia6t_expire = t + newval; |
1359 |
|
|
in6_addreq.ifra_lifetime.ia6t_vltime = newval; |
1360 |
|
|
} else if (strcmp(cmd, "pltime") == 0) { |
1361 |
|
|
in6_addreq.ifra_lifetime.ia6t_preferred = t + newval; |
1362 |
|
|
in6_addreq.ifra_lifetime.ia6t_pltime = newval; |
1363 |
|
|
} |
1364 |
|
|
} |
1365 |
|
|
|
1366 |
|
|
void |
1367 |
|
|
setia6eui64(const char *cmd, int val) |
1368 |
|
2 |
{ |
1369 |
|
|
struct ifaddrs *ifap, *ifa; |
1370 |
|
2 |
const struct sockaddr_in6 *sin6 = NULL; |
1371 |
|
2 |
const struct in6_addr *lladdr = NULL; |
1372 |
|
|
struct in6_addr *in6; |
1373 |
|
|
|
1374 |
✗✓ |
2 |
if (afp->af_af != AF_INET6) |
1375 |
|
|
errx(1, "%s not allowed for the AF", cmd); |
1376 |
|
|
|
1377 |
|
2 |
addaf(name, AF_INET6); |
1378 |
|
|
|
1379 |
|
2 |
in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr; |
1380 |
✗✓ |
2 |
if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0) |
1381 |
|
|
errx(1, "interface index is already filled"); |
1382 |
✗✓ |
2 |
if (getifaddrs(&ifap) != 0) |
1383 |
|
|
err(1, "getifaddrs"); |
1384 |
✓✗ |
23 |
for (ifa = ifap; ifa; ifa = ifa->ifa_next) { |
1385 |
✓✓✓✓
|
23 |
if (ifa->ifa_addr->sa_family == AF_INET6 && |
1386 |
|
|
strcmp(ifa->ifa_name, name) == 0) { |
1387 |
|
4 |
sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr; |
1388 |
✓✓✓✗
|
4 |
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { |
1389 |
|
2 |
lladdr = &sin6->sin6_addr; |
1390 |
|
2 |
break; |
1391 |
|
|
} |
1392 |
|
|
} |
1393 |
|
|
} |
1394 |
✗✓ |
2 |
if (!lladdr) |
1395 |
|
|
errx(1, "could not determine link local address"); |
1396 |
|
|
|
1397 |
|
2 |
memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8); |
1398 |
|
|
|
1399 |
|
2 |
freeifaddrs(ifap); |
1400 |
|
2 |
} |
1401 |
|
|
|
1402 |
|
|
void |
1403 |
|
|
setautoconf(const char *cmd, int val) |
1404 |
|
|
{ |
1405 |
|
|
switch (afp->af_af) { |
1406 |
|
|
case AF_INET6: |
1407 |
|
|
setifxflags("inet6", val * IFXF_AUTOCONF6); |
1408 |
|
|
break; |
1409 |
|
|
default: |
1410 |
|
|
errx(1, "autoconf not allowed for this AF"); |
1411 |
|
|
} |
1412 |
|
|
} |
1413 |
|
|
|
1414 |
|
|
#ifndef SMALL |
1415 |
|
|
/* ARGSUSED */ |
1416 |
|
|
void |
1417 |
|
|
setifmetric(const char *val, int ignored) |
1418 |
|
|
{ |
1419 |
|
|
const char *errmsg = NULL; |
1420 |
|
|
|
1421 |
|
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
1422 |
|
|
|
1423 |
|
|
ifr.ifr_metric = strtonum(val, 0, INT_MAX, &errmsg); |
1424 |
|
|
if (errmsg) |
1425 |
|
|
errx(1, "metric %s: %s", val, errmsg); |
1426 |
|
|
if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) |
1427 |
|
|
warn("SIOCSIFMETRIC"); |
1428 |
|
|
} |
1429 |
|
|
#endif |
1430 |
|
|
|
1431 |
|
|
/* ARGSUSED */ |
1432 |
|
|
void |
1433 |
|
|
setifmtu(const char *val, int d) |
1434 |
|
|
{ |
1435 |
|
|
const char *errmsg = NULL; |
1436 |
|
|
|
1437 |
|
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
1438 |
|
|
|
1439 |
|
|
ifr.ifr_mtu = strtonum(val, 0, INT_MAX, &errmsg); |
1440 |
|
|
if (errmsg) |
1441 |
|
|
errx(1, "mtu %s: %s", val, errmsg); |
1442 |
|
|
if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) |
1443 |
|
|
warn("SIOCSIFMTU"); |
1444 |
|
|
} |
1445 |
|
|
|
1446 |
|
|
/* ARGSUSED */ |
1447 |
|
|
void |
1448 |
|
|
setifllprio(const char *val, int d) |
1449 |
|
|
{ |
1450 |
|
|
const char *errmsg = NULL; |
1451 |
|
|
|
1452 |
|
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
1453 |
|
|
|
1454 |
|
|
ifr.ifr_mtu = strtonum(val, 0, UCHAR_MAX, &errmsg); |
1455 |
|
|
if (errmsg) |
1456 |
|
|
errx(1, "mtu %s: %s", val, errmsg); |
1457 |
|
|
if (ioctl(s, SIOCSIFLLPRIO, (caddr_t)&ifr) < 0) |
1458 |
|
|
warn("SIOCSIFLLPRIO"); |
1459 |
|
|
} |
1460 |
|
|
|
1461 |
|
|
/* ARGSUSED */ |
1462 |
|
|
void |
1463 |
|
|
setifgroup(const char *group_name, int dummy) |
1464 |
|
|
{ |
1465 |
|
|
struct ifgroupreq ifgr; |
1466 |
|
|
|
1467 |
|
|
memset(&ifgr, 0, sizeof(ifgr)); |
1468 |
|
|
strlcpy(ifgr.ifgr_name, name, IFNAMSIZ); |
1469 |
|
|
|
1470 |
|
|
if (group_name[0] && |
1471 |
|
|
isdigit((unsigned char)group_name[strlen(group_name) - 1])) |
1472 |
|
|
errx(1, "setifgroup: group names may not end in a digit"); |
1473 |
|
|
|
1474 |
|
|
if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ) |
1475 |
|
|
errx(1, "setifgroup: group name too long"); |
1476 |
|
|
if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) == -1) { |
1477 |
|
|
if (errno != EEXIST) |
1478 |
|
|
err(1," SIOCAIFGROUP"); |
1479 |
|
|
} |
1480 |
|
|
} |
1481 |
|
|
|
1482 |
|
|
/* ARGSUSED */ |
1483 |
|
|
void |
1484 |
|
|
unsetifgroup(const char *group_name, int dummy) |
1485 |
|
|
{ |
1486 |
|
|
struct ifgroupreq ifgr; |
1487 |
|
|
|
1488 |
|
|
memset(&ifgr, 0, sizeof(ifgr)); |
1489 |
|
|
strlcpy(ifgr.ifgr_name, name, IFNAMSIZ); |
1490 |
|
|
|
1491 |
|
|
if (group_name[0] && |
1492 |
|
|
isdigit((unsigned char)group_name[strlen(group_name) - 1])) |
1493 |
|
|
errx(1, "unsetifgroup: group names may not end in a digit"); |
1494 |
|
|
|
1495 |
|
|
if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ) |
1496 |
|
|
errx(1, "unsetifgroup: group name too long"); |
1497 |
|
|
if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1) |
1498 |
|
|
err(1, "SIOCDIFGROUP"); |
1499 |
|
|
} |
1500 |
|
|
|
1501 |
|
|
const char * |
1502 |
|
|
get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp) |
1503 |
|
|
{ |
1504 |
|
|
int len = *lenp, hexstr; |
1505 |
|
|
u_int8_t *p = buf; |
1506 |
|
|
|
1507 |
|
|
hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x'); |
1508 |
|
|
if (hexstr) |
1509 |
|
|
val += 2; |
1510 |
|
|
for (;;) { |
1511 |
|
|
if (*val == '\0') |
1512 |
|
|
break; |
1513 |
|
|
if (sep != NULL && strchr(sep, *val) != NULL) { |
1514 |
|
|
val++; |
1515 |
|
|
break; |
1516 |
|
|
} |
1517 |
|
|
if (hexstr) { |
1518 |
|
|
if (!isxdigit((u_char)val[0]) || |
1519 |
|
|
!isxdigit((u_char)val[1])) { |
1520 |
|
|
warnx("bad hexadecimal digits"); |
1521 |
|
|
return NULL; |
1522 |
|
|
} |
1523 |
|
|
} |
1524 |
|
|
if (p > buf + len) { |
1525 |
|
|
if (hexstr) |
1526 |
|
|
warnx("hexadecimal digits too long"); |
1527 |
|
|
else |
1528 |
|
|
warnx("strings too long"); |
1529 |
|
|
return NULL; |
1530 |
|
|
} |
1531 |
|
|
if (hexstr) { |
1532 |
|
|
#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10) |
1533 |
|
|
*p++ = (tohex((u_char)val[0]) << 4) | |
1534 |
|
|
tohex((u_char)val[1]); |
1535 |
|
|
#undef tohex |
1536 |
|
|
val += 2; |
1537 |
|
|
} else { |
1538 |
|
|
if (*val == '\\' && |
1539 |
|
|
sep != NULL && strchr(sep, *(val + 1)) != NULL) |
1540 |
|
|
val++; |
1541 |
|
|
*p++ = *val++; |
1542 |
|
|
} |
1543 |
|
|
} |
1544 |
|
|
len = p - buf; |
1545 |
|
|
if (len < *lenp) |
1546 |
|
|
memset(p, 0, *lenp - len); |
1547 |
|
|
*lenp = len; |
1548 |
|
|
return val; |
1549 |
|
|
} |
1550 |
|
|
|
1551 |
|
|
void |
1552 |
|
|
print_string(const u_int8_t *buf, int len) |
1553 |
|
|
{ |
1554 |
|
|
int i = 0, hasspc = 0; |
1555 |
|
|
|
1556 |
|
|
if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') { |
1557 |
|
|
for (; i < len; i++) { |
1558 |
|
|
/* Only print 7-bit ASCII keys */ |
1559 |
|
|
if (buf[i] & 0x80 || !isprint(buf[i])) |
1560 |
|
|
break; |
1561 |
|
|
if (isspace(buf[i])) |
1562 |
|
|
hasspc++; |
1563 |
|
|
} |
1564 |
|
|
} |
1565 |
|
|
if (i == len) { |
1566 |
|
|
if (hasspc || len == 0) |
1567 |
|
|
printf("\"%.*s\"", len, buf); |
1568 |
|
|
else |
1569 |
|
|
printf("%.*s", len, buf); |
1570 |
|
|
} else { |
1571 |
|
|
printf("0x"); |
1572 |
|
|
for (i = 0; i < len; i++) |
1573 |
|
|
printf("%02x", buf[i]); |
1574 |
|
|
} |
1575 |
|
|
} |
1576 |
|
|
|
1577 |
|
|
void |
1578 |
|
|
setifnwid(const char *val, int d) |
1579 |
|
|
{ |
1580 |
|
|
struct ieee80211_nwid nwid; |
1581 |
|
|
int len; |
1582 |
|
|
|
1583 |
|
|
if (d != 0) { |
1584 |
|
|
/* no network id is especially desired */ |
1585 |
|
|
memset(&nwid, 0, sizeof(nwid)); |
1586 |
|
|
len = 0; |
1587 |
|
|
} else { |
1588 |
|
|
len = sizeof(nwid.i_nwid); |
1589 |
|
|
if (get_string(val, NULL, nwid.i_nwid, &len) == NULL) |
1590 |
|
|
return; |
1591 |
|
|
} |
1592 |
|
|
nwid.i_len = len; |
1593 |
|
|
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
1594 |
|
|
ifr.ifr_data = (caddr_t)&nwid; |
1595 |
|
|
if (ioctl(s, SIOCS80211NWID, (caddr_t)&ifr) < 0) |
1596 |
|
|
warn("SIOCS80211NWID"); |
1597 |
|
|
} |
1598 |
|
|
|
1599 |
|
|
void |
1600 |
|
|
setifbssid(const char *val, int d) |
1601 |
|
|
{ |
1602 |
|
|
|
1603 |
|
|
struct ieee80211_bssid bssid; |
1604 |
|
|
struct ether_addr *ea; |
1605 |
|
|
|
1606 |
|
|
if (d != 0) { |
1607 |
|
|
/* no BSSID is especially desired */ |
1608 |
|
|
memset(&bssid.i_bssid, 0, sizeof(bssid.i_bssid)); |
1609 |
|
|
} else { |
1610 |
|
|
ea = ether_aton((char*)val); |
1611 |
|
|
if (ea == NULL) { |
1612 |
|
|
warnx("malformed BSSID: %s", val); |
1613 |
|
|
return; |
1614 |
|
|
} |
1615 |
|
|
memcpy(&bssid.i_bssid, ea->ether_addr_octet, |
1616 |
|
|
sizeof(bssid.i_bssid)); |
1617 |
|
|
} |
1618 |
|
|
strlcpy(bssid.i_name, name, sizeof(bssid.i_name)); |
1619 |
|
|
if (ioctl(s, SIOCS80211BSSID, &bssid) == -1) |
1620 |
|
|
warn("SIOCS80211BSSID"); |
1621 |
|
|
} |
1622 |
|
|
|
1623 |
|
|
void |
1624 |
|
|
setifnwkey(const char *val, int d) |
1625 |
|
|
{ |
1626 |
|
|
int i, len; |
1627 |
|
|
struct ieee80211_nwkey nwkey; |
1628 |
|
|
u_int8_t keybuf[IEEE80211_WEP_NKID][16]; |
1629 |
|
|
|
1630 |
|
|
bzero(&nwkey, sizeof(nwkey)); |
1631 |
|
|
bzero(&keybuf, sizeof(keybuf)); |
1632 |
|
|
|
1633 |
|
|
nwkey.i_wepon = IEEE80211_NWKEY_WEP; |
1634 |
|
|
nwkey.i_defkid = 1; |
1635 |
|
|
if (d == -1) { |
1636 |
|
|
/* disable WEP encryption */ |
1637 |
|
|
nwkey.i_wepon = 0; |
1638 |
|
|
i = 0; |
1639 |
|
|
} else if (strcasecmp("persist", val) == 0) { |
1640 |
|
|
/* use all values from persistent memory */ |
1641 |
|
|
nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST; |
1642 |
|
|
nwkey.i_defkid = 0; |
1643 |
|
|
for (i = 0; i < IEEE80211_WEP_NKID; i++) |
1644 |
|
|
nwkey.i_key[i].i_keylen = -1; |
1645 |
|
|
} else if (strncasecmp("persist:", val, 8) == 0) { |
1646 |
|
|
val += 8; |
1647 |
|
|
/* program keys in persistent memory */ |
1648 |
|
|
nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST; |
1649 |
|
|
goto set_nwkey; |
1650 |
|
|
} else { |
1651 |
|
|
set_nwkey: |
1652 |
|
|
if (isdigit((unsigned char)val[0]) && val[1] == ':') { |
1653 |
|
|
/* specifying a full set of four keys */ |
1654 |
|
|
nwkey.i_defkid = val[0] - '0'; |
1655 |
|
|
val += 2; |
1656 |
|
|
for (i = 0; i < IEEE80211_WEP_NKID; i++) { |
1657 |
|
|
len = sizeof(keybuf[i]); |
1658 |
|
|
val = get_string(val, ",", keybuf[i], &len); |
1659 |
|
|
if (val == NULL) |
1660 |
|
|
return; |
1661 |
|
|
nwkey.i_key[i].i_keylen = len; |
1662 |
|
|
nwkey.i_key[i].i_keydat = keybuf[i]; |
1663 |
|
|
} |
1664 |
|
|
if (*val != '\0') { |
1665 |
|
|
warnx("SIOCS80211NWKEY: too many keys."); |
1666 |
|
|
return; |
1667 |
|
|
} |
1668 |
|
|
} else { |
1669 |
|
|
/* |
1670 |
|
|
* length of each key must be either a 5 |
1671 |
|
|
* character ASCII string or 10 hex digits for |
1672 |
|
|
* 40 bit encryption, or 13 character ASCII |
1673 |
|
|
* string or 26 hex digits for 128 bit |
1674 |
|
|
* encryption. |
1675 |
|
|
*/ |
1676 |
|
|
int j; |
1677 |
|
|
char *tmp = NULL; |
1678 |
|
|
size_t vlen = strlen(val); |
1679 |
|
|
switch(vlen) { |
1680 |
|
|
case 10: |
1681 |
|
|
case 26: |
1682 |
|
|
/* 0x must be missing for these lengths */ |
1683 |
|
|
j = asprintf(&tmp, "0x%s", val); |
1684 |
|
|
if (j == -1) { |
1685 |
|
|
warnx("malloc failed"); |
1686 |
|
|
return; |
1687 |
|
|
} |
1688 |
|
|
val = tmp; |
1689 |
|
|
break; |
1690 |
|
|
case 12: |
1691 |
|
|
case 28: |
1692 |
|
|
case 5: |
1693 |
|
|
case 13: |
1694 |
|
|
/* 0xkey or string case - all is ok */ |
1695 |
|
|
break; |
1696 |
|
|
default: |
1697 |
|
|
warnx("Invalid WEP key length"); |
1698 |
|
|
return; |
1699 |
|
|
} |
1700 |
|
|
len = sizeof(keybuf[0]); |
1701 |
|
|
val = get_string(val, NULL, keybuf[0], &len); |
1702 |
|
|
free(tmp); |
1703 |
|
|
if (val == NULL) |
1704 |
|
|
return; |
1705 |
|
|
nwkey.i_key[0].i_keylen = len; |
1706 |
|
|
nwkey.i_key[0].i_keydat = keybuf[0]; |
1707 |
|
|
i = 1; |
1708 |
|
|
} |
1709 |
|
|
} |
1710 |
|
|
(void)strlcpy(nwkey.i_name, name, sizeof(nwkey.i_name)); |
1711 |
|
|
if (ioctl(s, SIOCS80211NWKEY, (caddr_t)&nwkey) == -1) |
1712 |
|
|
warn("SIOCS80211NWKEY"); |
1713 |
|
|
} |
1714 |
|
|
|
1715 |
|
|
/* ARGSUSED */ |
1716 |
|
|
void |
1717 |
|
|
setifwpa(const char *val, int d) |
1718 |
|
|
{ |
1719 |
|
|
struct ieee80211_wpaparams wpa; |
1720 |
|
|
|
1721 |
|
|
memset(&wpa, 0, sizeof(wpa)); |
1722 |
|
|
(void)strlcpy(wpa.i_name, name, sizeof(wpa.i_name)); |
1723 |
|
|
if (ioctl(s, SIOCG80211WPAPARMS, (caddr_t)&wpa) < 0) |
1724 |
|
|
err(1, "SIOCG80211WPAPARMS"); |
1725 |
|
|
wpa.i_enabled = d; |
1726 |
|
|
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0) |
1727 |
|
|
err(1, "SIOCS80211WPAPARMS"); |
1728 |
|
|
} |
1729 |
|
|
|
1730 |
|
|
/* ARGSUSED */ |
1731 |
|
|
void |
1732 |
|
|
setifwpaprotos(const char *val, int d) |
1733 |
|
|
{ |
1734 |
|
|
struct ieee80211_wpaparams wpa; |
1735 |
|
|
char *optlist, *str; |
1736 |
|
|
u_int rval = 0; |
1737 |
|
|
|
1738 |
|
|
if ((optlist = strdup(val)) == NULL) |
1739 |
|
|
err(1, "strdup"); |
1740 |
|
|
str = strtok(optlist, ","); |
1741 |
|
|
while (str != NULL) { |
1742 |
|
|
if (strcasecmp(str, "wpa1") == 0) |
1743 |
|
|
rval |= IEEE80211_WPA_PROTO_WPA1; |
1744 |
|
|
else if (strcasecmp(str, "wpa2") == 0) |
1745 |
|
|
rval |= IEEE80211_WPA_PROTO_WPA2; |
1746 |
|
|
else |
1747 |
|
|
errx(1, "wpaprotos: unknown protocol: %s", str); |
1748 |
|
|
str = strtok(NULL, ","); |
1749 |
|
|
} |
1750 |
|
|
free(optlist); |
1751 |
|
|
|
1752 |
|
|
memset(&wpa, 0, sizeof(wpa)); |
1753 |
|
|
(void)strlcpy(wpa.i_name, name, sizeof(wpa.i_name)); |
1754 |
|
|
if (ioctl(s, SIOCG80211WPAPARMS, (caddr_t)&wpa) < 0) |
1755 |
|
|
err(1, "SIOCG80211WPAPARMS"); |
1756 |
|
|
wpa.i_protos = rval; |
1757 |
|
|
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0) |
1758 |
|
|
err(1, "SIOCS80211WPAPARMS"); |
1759 |
|
|
} |
1760 |
|
|
|
1761 |
|
|
/* ARGSUSED */ |
1762 |
|
|
void |
1763 |
|
|
setifwpaakms(const char *val, int d) |
1764 |
|
|
{ |
1765 |
|
|
struct ieee80211_wpaparams wpa; |
1766 |
|
|
char *optlist, *str; |
1767 |
|
|
u_int rval = 0; |
1768 |
|
|
|
1769 |
|
|
if ((optlist = strdup(val)) == NULL) |
1770 |
|
|
err(1, "strdup"); |
1771 |
|
|
str = strtok(optlist, ","); |
1772 |
|
|
while (str != NULL) { |
1773 |
|
|
if (strcasecmp(str, "psk") == 0) |
1774 |
|
|
rval |= IEEE80211_WPA_AKM_PSK; |
1775 |
|
|
else if (strcasecmp(str, "802.1x") == 0) |
1776 |
|
|
rval |= IEEE80211_WPA_AKM_8021X; |
1777 |
|
|
else |
1778 |
|
|
errx(1, "wpaakms: unknown akm: %s", str); |
1779 |
|
|
str = strtok(NULL, ","); |
1780 |
|
|
} |
1781 |
|
|
free(optlist); |
1782 |
|
|
|
1783 |
|
|
memset(&wpa, 0, sizeof(wpa)); |
1784 |
|
|
(void)strlcpy(wpa.i_name, name, sizeof(wpa.i_name)); |
1785 |
|
|
if (ioctl(s, SIOCG80211WPAPARMS, (caddr_t)&wpa) < 0) |
1786 |
|
|
err(1, "SIOCG80211WPAPARMS"); |
1787 |
|
|
wpa.i_akms = rval; |
1788 |
|
|
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0) |
1789 |
|
|
err(1, "SIOCS80211WPAPARMS"); |
1790 |
|
|
} |
1791 |
|
|
|
1792 |
|
|
static const struct { |
1793 |
|
|
const char *name; |
1794 |
|
|
u_int cipher; |
1795 |
|
|
} ciphers[] = { |
1796 |
|
|
{ "usegroup", IEEE80211_WPA_CIPHER_USEGROUP }, |
1797 |
|
|
{ "wep40", IEEE80211_WPA_CIPHER_WEP40 }, |
1798 |
|
|
{ "tkip", IEEE80211_WPA_CIPHER_TKIP }, |
1799 |
|
|
{ "ccmp", IEEE80211_WPA_CIPHER_CCMP }, |
1800 |
|
|
{ "wep104", IEEE80211_WPA_CIPHER_WEP104 } |
1801 |
|
|
}; |
1802 |
|
|
|
1803 |
|
|
u_int |
1804 |
|
|
getwpacipher(const char *name) |
1805 |
|
|
{ |
1806 |
|
|
int i; |
1807 |
|
|
|
1808 |
|
|
for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); i++) |
1809 |
|
|
if (strcasecmp(name, ciphers[i].name) == 0) |
1810 |
|
|
return ciphers[i].cipher; |
1811 |
|
|
return IEEE80211_WPA_CIPHER_NONE; |
1812 |
|
|
} |
1813 |
|
|
|
1814 |
|
|
/* ARGSUSED */ |
1815 |
|
|
void |
1816 |
|
|
setifwpaciphers(const char *val, int d) |
1817 |
|
|
{ |
1818 |
|
|
struct ieee80211_wpaparams wpa; |
1819 |
|
|
char *optlist, *str; |
1820 |
|
|
u_int rval = 0; |
1821 |
|
|
|
1822 |
|
|
if ((optlist = strdup(val)) == NULL) |
1823 |
|
|
err(1, "strdup"); |
1824 |
|
|
str = strtok(optlist, ","); |
1825 |
|
|
while (str != NULL) { |
1826 |
|
|
u_int cipher = getwpacipher(str); |
1827 |
|
|
if (cipher == IEEE80211_WPA_CIPHER_NONE) |
1828 |
|
|
errx(1, "wpaciphers: unknown cipher: %s", str); |
1829 |
|
|
|
1830 |
|
|
rval |= cipher; |
1831 |
|
|
str = strtok(NULL, ","); |
1832 |
|
|
} |
1833 |
|
|
free(optlist); |
1834 |
|
|
|
1835 |
|
|
memset(&wpa, 0, sizeof(wpa)); |
1836 |
|
|
(void)strlcpy(wpa.i_name, name, sizeof(wpa.i_name)); |
1837 |
|
|
if (ioctl(s, SIOCG80211WPAPARMS, (caddr_t)&wpa) < 0) |
1838 |
|
|
err(1, "SIOCG80211WPAPARMS"); |
1839 |
|
|
wpa.i_ciphers = rval; |
1840 |
|
|
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0) |
1841 |
|
|
err(1, "SIOCS80211WPAPARMS"); |
1842 |
|
|
} |
1843 |
|
|
|
1844 |
|
|
/* ARGSUSED */ |
1845 |
|
|
void |
1846 |
|
|
setifwpagroupcipher(const char *val, int d) |
1847 |
|
|
{ |
1848 |
|
|
struct ieee80211_wpaparams wpa; |
1849 |
|
|
u_int cipher; |
1850 |
|
|
|
1851 |
|
|
cipher = getwpacipher(val); |
1852 |
|
|
if (cipher == IEEE80211_WPA_CIPHER_NONE) |
1853 |
|
|
errx(1, "wpagroupcipher: unknown cipher: %s", val); |
1854 |
|
|
|
1855 |
|
|
memset(&wpa, 0, sizeof(wpa)); |
1856 |
|
|
(void)strlcpy(wpa.i_name, name, sizeof(wpa.i_name)); |
1857 |
|
|
if (ioctl(s, SIOCG80211WPAPARMS, (caddr_t)&wpa) < 0) |
1858 |
|
|
err(1, "SIOCG80211WPAPARMS"); |
1859 |
|
|
wpa.i_groupcipher = cipher; |
1860 |
|
|
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0) |
1861 |
|
|
err(1, "SIOCS80211WPAPARMS"); |
1862 |
|
|
} |
1863 |
|
|
|
1864 |
|
|
void |
1865 |
|
|
setifwpakey(const char *val, int d) |
1866 |
|
|
{ |
1867 |
|
|
struct ieee80211_wpaparams wpa; |
1868 |
|
|
struct ieee80211_wpapsk psk; |
1869 |
|
|
struct ieee80211_nwid nwid; |
1870 |
|
|
int passlen; |
1871 |
|
|
|
1872 |
|
|
memset(&psk, 0, sizeof(psk)); |
1873 |
|
|
if (d != -1) { |
1874 |
|
|
memset(&ifr, 0, sizeof(ifr)); |
1875 |
|
|
ifr.ifr_data = (caddr_t)&nwid; |
1876 |
|
|
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
1877 |
|
|
if (ioctl(s, SIOCG80211NWID, (caddr_t)&ifr)) |
1878 |
|
|
err(1, "SIOCG80211NWID"); |
1879 |
|
|
|
1880 |
|
|
passlen = strlen(val); |
1881 |
|
|
if (passlen == 2 + 2 * sizeof(psk.i_psk) && |
1882 |
|
|
val[0] == '0' && val[1] == 'x') { |
1883 |
|
|
/* Parse a WPA hex key (must be full-length) */ |
1884 |
|
|
passlen = sizeof(psk.i_psk); |
1885 |
|
|
val = get_string(val, NULL, psk.i_psk, &passlen); |
1886 |
|
|
if (val == NULL || passlen != sizeof(psk.i_psk)) |
1887 |
|
|
errx(1, "wpakey: invalid pre-shared key"); |
1888 |
|
|
} else { |
1889 |
|
|
/* Parse a WPA passphrase */ |
1890 |
|
|
if (passlen < 8 || passlen > 63) |
1891 |
|
|
errx(1, "wpakey: passphrase must be between " |
1892 |
|
|
"8 and 63 characters"); |
1893 |
|
|
if (nwid.i_len == 0) |
1894 |
|
|
errx(1, "wpakey: nwid not set"); |
1895 |
|
|
if (pkcs5_pbkdf2(val, passlen, nwid.i_nwid, nwid.i_len, |
1896 |
|
|
psk.i_psk, sizeof(psk.i_psk), 4096) != 0) |
1897 |
|
|
errx(1, "wpakey: passphrase hashing failed"); |
1898 |
|
|
} |
1899 |
|
|
psk.i_enabled = 1; |
1900 |
|
|
} else |
1901 |
|
|
psk.i_enabled = 0; |
1902 |
|
|
|
1903 |
|
|
(void)strlcpy(psk.i_name, name, sizeof(psk.i_name)); |
1904 |
|
|
if (ioctl(s, SIOCS80211WPAPSK, (caddr_t)&psk) < 0) |
1905 |
|
|
err(1, "SIOCS80211WPAPSK"); |
1906 |
|
|
|
1907 |
|
|
/* And ... automatically enable or disable WPA */ |
1908 |
|
|
memset(&wpa, 0, sizeof(wpa)); |
1909 |
|
|
(void)strlcpy(wpa.i_name, name, sizeof(wpa.i_name)); |
1910 |
|
|
if (ioctl(s, SIOCG80211WPAPARMS, (caddr_t)&wpa) < 0) |
1911 |
|
|
err(1, "SIOCG80211WPAPARMS"); |
1912 |
|
|
wpa.i_enabled = psk.i_enabled; |
1913 |
|
|
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0) |
1914 |
|
|
err(1, "SIOCS80211WPAPARMS"); |
1915 |
|
|
} |
1916 |
|
|
|
1917 |
|
|
void |
1918 |
|
|
setifchan(const char *val, int d) |
1919 |
|
|
{ |
1920 |
|
|
struct ieee80211chanreq channel; |
1921 |
|
|
const char *errstr; |
1922 |
|
|
int chan; |
1923 |
|
|
|
1924 |
|
|
if (val == NULL) { |
1925 |
|
|
if (shownet80211chans || shownet80211nodes) |
1926 |
|
|
usage(1); |
1927 |
|
|
shownet80211chans = 1; |
1928 |
|
|
return; |
1929 |
|
|
} |
1930 |
|
|
if (d != 0) |
1931 |
|
|
chan = IEEE80211_CHAN_ANY; |
1932 |
|
|
else { |
1933 |
|
|
chan = strtonum(val, 1, 256, &errstr); |
1934 |
|
|
if (errstr) { |
1935 |
|
|
warnx("invalid channel %s: %s", val, errstr); |
1936 |
|
|
return; |
1937 |
|
|
} |
1938 |
|
|
} |
1939 |
|
|
|
1940 |
|
|
strlcpy(channel.i_name, name, sizeof(channel.i_name)); |
1941 |
|
|
channel.i_channel = (u_int16_t)chan; |
1942 |
|
|
if (ioctl(s, SIOCS80211CHANNEL, (caddr_t)&channel) == -1) |
1943 |
|
|
warn("SIOCS80211CHANNEL"); |
1944 |
|
|
} |
1945 |
|
|
|
1946 |
|
|
/* ARGSUSED */ |
1947 |
|
|
void |
1948 |
|
|
setifscan(const char *val, int d) |
1949 |
|
|
{ |
1950 |
|
|
if (shownet80211chans || shownet80211nodes) |
1951 |
|
|
usage(1); |
1952 |
|
|
shownet80211nodes = 1; |
1953 |
|
|
} |
1954 |
|
|
|
1955 |
|
|
#ifndef SMALL |
1956 |
|
|
|
1957 |
|
|
void |
1958 |
|
|
setifnwflag(const char *val, int d) |
1959 |
|
|
{ |
1960 |
|
|
static const struct ieee80211_flags nwflags[] = IEEE80211_FLAGS; |
1961 |
|
|
u_int i, flag = 0; |
1962 |
|
|
|
1963 |
|
|
for (i = 0; i < (sizeof(nwflags) / sizeof(nwflags[0])); i++) { |
1964 |
|
|
if (strcmp(val, nwflags[i].f_name) == 0) { |
1965 |
|
|
flag = nwflags[i].f_flag; |
1966 |
|
|
break; |
1967 |
|
|
} |
1968 |
|
|
} |
1969 |
|
|
if (flag == 0) |
1970 |
|
|
errx(1, "Invalid nwflag: %s", val); |
1971 |
|
|
|
1972 |
|
|
if (ioctl(s, SIOCG80211FLAGS, (caddr_t)&ifr) != 0) |
1973 |
|
|
err(1, "SIOCG80211FLAGS"); |
1974 |
|
|
|
1975 |
|
|
if (d) |
1976 |
|
|
ifr.ifr_flags &= ~flag; |
1977 |
|
|
else |
1978 |
|
|
ifr.ifr_flags |= flag; |
1979 |
|
|
|
1980 |
|
|
if (ioctl(s, SIOCS80211FLAGS, (caddr_t)&ifr) != 0) |
1981 |
|
|
err(1, "SIOCS80211FLAGS"); |
1982 |
|
|
} |
1983 |
|
|
|
1984 |
|
|
void |
1985 |
|
|
unsetifnwflag(const char *val, int d) |
1986 |
|
|
{ |
1987 |
|
|
setifnwflag(val, 1); |
1988 |
|
|
} |
1989 |
|
|
|
1990 |
|
|
/* ARGSUSED */ |
1991 |
|
|
void |
1992 |
|
|
setifpowersave(const char *val, int d) |
1993 |
|
|
{ |
1994 |
|
|
struct ieee80211_power power; |
1995 |
|
|
const char *errmsg = NULL; |
1996 |
|
|
|
1997 |
|
|
(void)strlcpy(power.i_name, name, sizeof(power.i_name)); |
1998 |
|
|
if (ioctl(s, SIOCG80211POWER, (caddr_t)&power) == -1) { |
1999 |
|
|
warn("SIOCG80211POWER"); |
2000 |
|
|
return; |
2001 |
|
|
} |
2002 |
|
|
|
2003 |
|
|
if (d != -1 && val != NULL) { |
2004 |
|
|
power.i_maxsleep = strtonum(val, 0, INT_MAX, &errmsg); |
2005 |
|
|
if (errmsg) |
2006 |
|
|
errx(1, "powersave %s: %s", val, errmsg); |
2007 |
|
|
} |
2008 |
|
|
|
2009 |
|
|
power.i_enabled = d == -1 ? 0 : 1; |
2010 |
|
|
if (ioctl(s, SIOCS80211POWER, (caddr_t)&power) == -1) |
2011 |
|
|
warn("SIOCS80211POWER"); |
2012 |
|
|
} |
2013 |
|
|
#endif |
2014 |
|
|
|
2015 |
|
|
void |
2016 |
|
|
print_cipherset(u_int32_t cipherset) |
2017 |
|
|
{ |
2018 |
|
|
const char *sep = ""; |
2019 |
|
|
int i; |
2020 |
|
|
|
2021 |
|
|
if (cipherset == IEEE80211_WPA_CIPHER_NONE) { |
2022 |
|
|
printf("none"); |
2023 |
|
|
return; |
2024 |
|
|
} |
2025 |
|
|
for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); i++) { |
2026 |
|
|
if (cipherset & ciphers[i].cipher) { |
2027 |
|
|
printf("%s%s", sep, ciphers[i].name); |
2028 |
|
|
sep = ","; |
2029 |
|
|
} |
2030 |
|
|
} |
2031 |
|
|
} |
2032 |
|
|
|
2033 |
|
|
void |
2034 |
|
|
ieee80211_status(void) |
2035 |
|
|
{ |
2036 |
|
|
int len, i, nwkey_verbose, inwid, inwkey, ipsk, ichan, ipwr; |
2037 |
|
|
int ibssid, iwpa; |
2038 |
|
|
struct ieee80211_nwid nwid; |
2039 |
|
|
struct ieee80211_nwkey nwkey; |
2040 |
|
|
struct ieee80211_wpapsk psk; |
2041 |
|
|
struct ieee80211_power power; |
2042 |
|
|
struct ieee80211chanreq channel; |
2043 |
|
|
struct ieee80211_bssid bssid; |
2044 |
|
|
struct ieee80211_wpaparams wpa; |
2045 |
|
|
struct ieee80211_nodereq nr; |
2046 |
|
|
u_int8_t zero_bssid[IEEE80211_ADDR_LEN]; |
2047 |
|
|
u_int8_t keybuf[IEEE80211_WEP_NKID][16]; |
2048 |
|
|
struct ether_addr ea; |
2049 |
|
|
|
2050 |
|
|
/* get current status via ioctls */ |
2051 |
|
|
memset(&ifr, 0, sizeof(ifr)); |
2052 |
|
|
ifr.ifr_data = (caddr_t)&nwid; |
2053 |
|
|
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
2054 |
|
|
inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr); |
2055 |
|
|
|
2056 |
|
|
memset(&nwkey, 0, sizeof(nwkey)); |
2057 |
|
|
strlcpy(nwkey.i_name, name, sizeof(nwkey.i_name)); |
2058 |
|
|
inwkey = ioctl(s, SIOCG80211NWKEY, (caddr_t)&nwkey); |
2059 |
|
|
|
2060 |
|
|
memset(&psk, 0, sizeof(psk)); |
2061 |
|
|
strlcpy(psk.i_name, name, sizeof(psk.i_name)); |
2062 |
|
|
ipsk = ioctl(s, SIOCG80211WPAPSK, (caddr_t)&psk); |
2063 |
|
|
|
2064 |
|
|
memset(&power, 0, sizeof(power)); |
2065 |
|
|
strlcpy(power.i_name, name, sizeof(power.i_name)); |
2066 |
|
|
ipwr = ioctl(s, SIOCG80211POWER, &power); |
2067 |
|
|
|
2068 |
|
|
memset(&channel, 0, sizeof(channel)); |
2069 |
|
|
strlcpy(channel.i_name, name, sizeof(channel.i_name)); |
2070 |
|
|
ichan = ioctl(s, SIOCG80211CHANNEL, (caddr_t)&channel); |
2071 |
|
|
|
2072 |
|
|
memset(&bssid, 0, sizeof(bssid)); |
2073 |
|
|
strlcpy(bssid.i_name, name, sizeof(bssid.i_name)); |
2074 |
|
|
ibssid = ioctl(s, SIOCG80211BSSID, &bssid); |
2075 |
|
|
|
2076 |
|
|
memset(&wpa, 0, sizeof(wpa)); |
2077 |
|
|
strlcpy(wpa.i_name, name, sizeof(wpa.i_name)); |
2078 |
|
|
iwpa = ioctl(s, SIOCG80211WPAPARMS, &wpa); |
2079 |
|
|
|
2080 |
|
|
/* check if any ieee80211 option is active */ |
2081 |
|
|
if (inwid == 0 || inwkey == 0 || ipsk == 0 || ipwr == 0 || |
2082 |
|
|
ichan == 0 || ibssid == 0 || iwpa == 0) |
2083 |
|
|
fputs("\tieee80211:", stdout); |
2084 |
|
|
else |
2085 |
|
|
return; |
2086 |
|
|
|
2087 |
|
|
if (inwid == 0) { |
2088 |
|
|
/* nwid.i_nwid is not NUL terminated. */ |
2089 |
|
|
len = nwid.i_len; |
2090 |
|
|
if (len > IEEE80211_NWID_LEN) |
2091 |
|
|
len = IEEE80211_NWID_LEN; |
2092 |
|
|
fputs(" nwid ", stdout); |
2093 |
|
|
print_string(nwid.i_nwid, len); |
2094 |
|
|
} |
2095 |
|
|
|
2096 |
|
|
if (ichan == 0 && channel.i_channel != 0 && |
2097 |
|
|
channel.i_channel != IEEE80211_CHAN_ANY) |
2098 |
|
|
printf(" chan %u", channel.i_channel); |
2099 |
|
|
|
2100 |
|
|
memset(&zero_bssid, 0, sizeof(zero_bssid)); |
2101 |
|
|
if (ibssid == 0 && |
2102 |
|
|
memcmp(bssid.i_bssid, zero_bssid, IEEE80211_ADDR_LEN) != 0) { |
2103 |
|
|
memcpy(&ea.ether_addr_octet, bssid.i_bssid, |
2104 |
|
|
sizeof(ea.ether_addr_octet)); |
2105 |
|
|
printf(" bssid %s", ether_ntoa(&ea)); |
2106 |
|
|
|
2107 |
|
|
bzero(&nr, sizeof(nr)); |
2108 |
|
|
bcopy(bssid.i_bssid, &nr.nr_macaddr, sizeof(nr.nr_macaddr)); |
2109 |
|
|
strlcpy(nr.nr_ifname, name, sizeof(nr.nr_ifname)); |
2110 |
|
|
if (ioctl(s, SIOCG80211NODE, &nr) == 0 && nr.nr_rssi) { |
2111 |
|
|
if (nr.nr_max_rssi) |
2112 |
|
|
printf(" %u%%", IEEE80211_NODEREQ_RSSI(&nr)); |
2113 |
|
|
else |
2114 |
|
|
printf(" %ddBm", nr.nr_rssi); |
2115 |
|
|
} |
2116 |
|
|
} |
2117 |
|
|
|
2118 |
|
|
if (inwkey == 0 && nwkey.i_wepon > 0) { |
2119 |
|
|
fputs(" nwkey ", stdout); |
2120 |
|
|
/* try to retrieve WEP keys */ |
2121 |
|
|
for (i = 0; i < IEEE80211_WEP_NKID; i++) { |
2122 |
|
|
nwkey.i_key[i].i_keydat = keybuf[i]; |
2123 |
|
|
nwkey.i_key[i].i_keylen = sizeof(keybuf[i]); |
2124 |
|
|
} |
2125 |
|
|
if (ioctl(s, SIOCG80211NWKEY, (caddr_t)&nwkey) == -1) { |
2126 |
|
|
fputs("<not displayed>", stdout); |
2127 |
|
|
} else { |
2128 |
|
|
nwkey_verbose = 0; |
2129 |
|
|
/* |
2130 |
|
|
* check to see non default key |
2131 |
|
|
* or multiple keys defined |
2132 |
|
|
*/ |
2133 |
|
|
if (nwkey.i_defkid != 1) { |
2134 |
|
|
nwkey_verbose = 1; |
2135 |
|
|
} else { |
2136 |
|
|
for (i = 1; i < IEEE80211_WEP_NKID; i++) { |
2137 |
|
|
if (nwkey.i_key[i].i_keylen != 0) { |
2138 |
|
|
nwkey_verbose = 1; |
2139 |
|
|
break; |
2140 |
|
|
} |
2141 |
|
|
} |
2142 |
|
|
} |
2143 |
|
|
/* check extra ambiguity with keywords */ |
2144 |
|
|
if (!nwkey_verbose) { |
2145 |
|
|
if (nwkey.i_key[0].i_keylen >= 2 && |
2146 |
|
|
isdigit((unsigned char)nwkey.i_key[0].i_keydat[0]) && |
2147 |
|
|
nwkey.i_key[0].i_keydat[1] == ':') |
2148 |
|
|
nwkey_verbose = 1; |
2149 |
|
|
else if (nwkey.i_key[0].i_keylen >= 7 && |
2150 |
|
|
strncasecmp("persist", |
2151 |
|
|
(char *)nwkey.i_key[0].i_keydat, 7) == 0) |
2152 |
|
|
nwkey_verbose = 1; |
2153 |
|
|
} |
2154 |
|
|
if (nwkey_verbose) |
2155 |
|
|
printf("%d:", nwkey.i_defkid); |
2156 |
|
|
for (i = 0; i < IEEE80211_WEP_NKID; i++) { |
2157 |
|
|
if (i > 0) |
2158 |
|
|
putchar(','); |
2159 |
|
|
if (nwkey.i_key[i].i_keylen < 0) { |
2160 |
|
|
fputs("persist", stdout); |
2161 |
|
|
} else { |
2162 |
|
|
/* |
2163 |
|
|
* XXX |
2164 |
|
|
* sanity check nwkey.i_key[i].i_keylen |
2165 |
|
|
*/ |
2166 |
|
|
print_string(nwkey.i_key[i].i_keydat, |
2167 |
|
|
nwkey.i_key[i].i_keylen); |
2168 |
|
|
} |
2169 |
|
|
if (!nwkey_verbose) |
2170 |
|
|
break; |
2171 |
|
|
} |
2172 |
|
|
} |
2173 |
|
|
} |
2174 |
|
|
|
2175 |
|
|
if (ipsk == 0 && psk.i_enabled) { |
2176 |
|
|
fputs(" wpakey ", stdout); |
2177 |
|
|
if (psk.i_enabled == 2) |
2178 |
|
|
fputs("<not displayed>", stdout); |
2179 |
|
|
else |
2180 |
|
|
print_string(psk.i_psk, sizeof(psk.i_psk)); |
2181 |
|
|
} |
2182 |
|
|
if (iwpa == 0 && wpa.i_enabled) { |
2183 |
|
|
const char *sep; |
2184 |
|
|
|
2185 |
|
|
fputs(" wpaprotos ", stdout); sep = ""; |
2186 |
|
|
if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA1) { |
2187 |
|
|
fputs("wpa1", stdout); |
2188 |
|
|
sep = ","; |
2189 |
|
|
} |
2190 |
|
|
if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) |
2191 |
|
|
printf("%swpa2", sep); |
2192 |
|
|
|
2193 |
|
|
fputs(" wpaakms ", stdout); sep = ""; |
2194 |
|
|
if (wpa.i_akms & IEEE80211_WPA_AKM_PSK) { |
2195 |
|
|
fputs("psk", stdout); |
2196 |
|
|
sep = ","; |
2197 |
|
|
} |
2198 |
|
|
if (wpa.i_akms & IEEE80211_WPA_AKM_8021X) |
2199 |
|
|
printf("%s802.1x", sep); |
2200 |
|
|
|
2201 |
|
|
fputs(" wpaciphers ", stdout); |
2202 |
|
|
print_cipherset(wpa.i_ciphers); |
2203 |
|
|
|
2204 |
|
|
fputs(" wpagroupcipher ", stdout); |
2205 |
|
|
print_cipherset(wpa.i_groupcipher); |
2206 |
|
|
} |
2207 |
|
|
|
2208 |
|
|
if (ipwr == 0 && power.i_enabled) |
2209 |
|
|
printf(" powersave on (%dms sleep)", power.i_maxsleep); |
2210 |
|
|
|
2211 |
|
|
if (ioctl(s, SIOCG80211FLAGS, (caddr_t)&ifr) == 0 && |
2212 |
|
|
ifr.ifr_flags) { |
2213 |
|
|
putchar(' '); |
2214 |
|
|
printb_status(ifr.ifr_flags, IEEE80211_F_USERBITS); |
2215 |
|
|
} |
2216 |
|
|
|
2217 |
|
|
putchar('\n'); |
2218 |
|
|
if (shownet80211chans) |
2219 |
|
|
ieee80211_listchans(); |
2220 |
|
|
else if (shownet80211nodes) |
2221 |
|
|
ieee80211_listnodes(); |
2222 |
|
|
} |
2223 |
|
|
|
2224 |
|
|
void |
2225 |
|
|
ieee80211_listchans(void) |
2226 |
|
|
{ |
2227 |
|
|
static struct ieee80211_channel chans[256+1]; |
2228 |
|
|
struct ieee80211_chanreq_all ca; |
2229 |
|
|
int i; |
2230 |
|
|
|
2231 |
|
|
bzero(&ca, sizeof(ca)); |
2232 |
|
|
bzero(chans, sizeof(chans)); |
2233 |
|
|
ca.i_chans = chans; |
2234 |
|
|
strlcpy(ca.i_name, name, sizeof(ca.i_name)); |
2235 |
|
|
|
2236 |
|
|
if (ioctl(s, SIOCG80211ALLCHANS, &ca) != 0) { |
2237 |
|
|
warn("SIOCG80211ALLCHANS"); |
2238 |
|
|
return; |
2239 |
|
|
} |
2240 |
|
|
printf("\t\t%4s %-8s %s\n", "chan", "freq", "properties"); |
2241 |
|
|
for (i = 1; i <= 256; i++) { |
2242 |
|
|
if (chans[i].ic_flags == 0) |
2243 |
|
|
continue; |
2244 |
|
|
printf("\t\t%4d %4d MHz ", i, chans[i].ic_freq); |
2245 |
|
|
if (chans[i].ic_flags & IEEE80211_CHAN_PASSIVE) |
2246 |
|
|
printf("passive scan"); |
2247 |
|
|
else |
2248 |
|
|
putchar('-'); |
2249 |
|
|
putchar('\n'); |
2250 |
|
|
} |
2251 |
|
|
} |
2252 |
|
|
|
2253 |
|
|
/* |
2254 |
|
|
* Returns an integer less than, equal to, or greater than zero if nr1's |
2255 |
|
|
* RSSI is respectively greater than, equal to, or less than nr2's RSSI. |
2256 |
|
|
*/ |
2257 |
|
|
static int |
2258 |
|
|
rssicmp(const void *nr1, const void *nr2) |
2259 |
|
|
{ |
2260 |
|
|
const struct ieee80211_nodereq *x = nr1, *y = nr2; |
2261 |
|
|
return y->nr_rssi < x->nr_rssi ? -1 : y->nr_rssi > x->nr_rssi; |
2262 |
|
|
} |
2263 |
|
|
|
2264 |
|
|
void |
2265 |
|
|
ieee80211_listnodes(void) |
2266 |
|
|
{ |
2267 |
|
|
struct ieee80211_nodereq_all na; |
2268 |
|
|
struct ieee80211_nodereq nr[512]; |
2269 |
|
|
struct ifreq ifr; |
2270 |
|
|
int i, down = 0; |
2271 |
|
|
|
2272 |
|
|
if ((flags & IFF_UP) == 0) { |
2273 |
|
|
down = 1; |
2274 |
|
|
setifflags("up", IFF_UP); |
2275 |
|
|
} |
2276 |
|
|
|
2277 |
|
|
bzero(&ifr, sizeof(ifr)); |
2278 |
|
|
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
2279 |
|
|
|
2280 |
|
|
if (ioctl(s, SIOCS80211SCAN, (caddr_t)&ifr) != 0) { |
2281 |
|
|
if (errno == EPERM) |
2282 |
|
|
printf("\t\tno permission to scan\n"); |
2283 |
|
|
goto done; |
2284 |
|
|
} |
2285 |
|
|
|
2286 |
|
|
bzero(&na, sizeof(na)); |
2287 |
|
|
bzero(&nr, sizeof(nr)); |
2288 |
|
|
na.na_node = nr; |
2289 |
|
|
na.na_size = sizeof(nr); |
2290 |
|
|
strlcpy(na.na_ifname, name, sizeof(na.na_ifname)); |
2291 |
|
|
|
2292 |
|
|
if (ioctl(s, SIOCG80211ALLNODES, &na) != 0) { |
2293 |
|
|
warn("SIOCG80211ALLNODES"); |
2294 |
|
|
goto done; |
2295 |
|
|
} |
2296 |
|
|
|
2297 |
|
|
if (!na.na_nodes) |
2298 |
|
|
printf("\t\tnone\n"); |
2299 |
|
|
else |
2300 |
|
|
qsort(nr, na.na_nodes, sizeof(*nr), rssicmp); |
2301 |
|
|
|
2302 |
|
|
for (i = 0; i < na.na_nodes; i++) { |
2303 |
|
|
printf("\t\t"); |
2304 |
|
|
ieee80211_printnode(&nr[i]); |
2305 |
|
|
putchar('\n'); |
2306 |
|
|
} |
2307 |
|
|
|
2308 |
|
|
done: |
2309 |
|
|
if (down) |
2310 |
|
|
setifflags("restore", -IFF_UP); |
2311 |
|
|
} |
2312 |
|
|
|
2313 |
|
|
void |
2314 |
|
|
ieee80211_printnode(struct ieee80211_nodereq *nr) |
2315 |
|
|
{ |
2316 |
|
|
int len, i; |
2317 |
|
|
|
2318 |
|
|
if (nr->nr_flags & IEEE80211_NODEREQ_AP || |
2319 |
|
|
nr->nr_capinfo & IEEE80211_CAPINFO_IBSS) { |
2320 |
|
|
len = nr->nr_nwid_len; |
2321 |
|
|
if (len > IEEE80211_NWID_LEN) |
2322 |
|
|
len = IEEE80211_NWID_LEN; |
2323 |
|
|
printf("nwid "); |
2324 |
|
|
print_string(nr->nr_nwid, len); |
2325 |
|
|
putchar(' '); |
2326 |
|
|
|
2327 |
|
|
printf("chan %u ", nr->nr_channel); |
2328 |
|
|
|
2329 |
|
|
printf("bssid %s ", |
2330 |
|
|
ether_ntoa((struct ether_addr*)nr->nr_bssid)); |
2331 |
|
|
} |
2332 |
|
|
|
2333 |
|
|
if ((nr->nr_flags & IEEE80211_NODEREQ_AP) == 0) |
2334 |
|
|
printf("lladdr %s ", |
2335 |
|
|
ether_ntoa((struct ether_addr*)nr->nr_macaddr)); |
2336 |
|
|
|
2337 |
|
|
if (nr->nr_max_rssi) |
2338 |
|
|
printf("%u%% ", IEEE80211_NODEREQ_RSSI(nr)); |
2339 |
|
|
else |
2340 |
|
|
printf("%ddBm ", nr->nr_rssi); |
2341 |
|
|
|
2342 |
|
|
if (nr->nr_pwrsave) |
2343 |
|
|
printf("powersave "); |
2344 |
|
|
/* Only print the fastest rate */ |
2345 |
|
|
if (nr->nr_max_rxrate) { |
2346 |
|
|
printf("%uM HT ", nr->nr_max_rxrate); |
2347 |
|
|
} else if (nr->nr_rxmcs[0] != 0) { |
2348 |
|
|
for (i = IEEE80211_HT_NUM_MCS - 1; i >= 0; i--) { |
2349 |
|
|
if (isset(nr->nr_rxmcs, i)) |
2350 |
|
|
break; |
2351 |
|
|
} |
2352 |
|
|
printf("HT-MCS%d ", i); |
2353 |
|
|
} else if (nr->nr_nrates) { |
2354 |
|
|
printf("%uM", |
2355 |
|
|
(nr->nr_rates[nr->nr_nrates - 1] & IEEE80211_RATE_VAL) / 2); |
2356 |
|
|
putchar(' '); |
2357 |
|
|
} |
2358 |
|
|
/* ESS is the default, skip it */ |
2359 |
|
|
nr->nr_capinfo &= ~IEEE80211_CAPINFO_ESS; |
2360 |
|
|
if (nr->nr_capinfo) { |
2361 |
|
|
printb_status(nr->nr_capinfo, IEEE80211_CAPINFO_BITS); |
2362 |
|
|
if (nr->nr_capinfo & IEEE80211_CAPINFO_PRIVACY) { |
2363 |
|
|
if (nr->nr_rsnciphers & IEEE80211_WPA_CIPHER_CCMP) |
2364 |
|
|
fputs(",wpa2", stdout); |
2365 |
|
|
else if (nr->nr_rsnciphers & IEEE80211_WPA_CIPHER_TKIP) |
2366 |
|
|
fputs(",wpa1", stdout); |
2367 |
|
|
else |
2368 |
|
|
fputs(",wep", stdout); |
2369 |
|
|
|
2370 |
|
|
if (nr->nr_rsnakms & IEEE80211_WPA_AKM_8021X || |
2371 |
|
|
nr->nr_rsnakms & IEEE80211_WPA_AKM_SHA256_8021X) |
2372 |
|
|
fputs(",802.1x", stdout); |
2373 |
|
|
} |
2374 |
|
|
putchar(' '); |
2375 |
|
|
} |
2376 |
|
|
|
2377 |
|
|
if ((nr->nr_flags & IEEE80211_NODEREQ_AP) == 0) |
2378 |
|
|
printb_status(IEEE80211_NODEREQ_STATE(nr->nr_state), |
2379 |
|
|
IEEE80211_NODEREQ_STATE_BITS); |
2380 |
|
|
} |
2381 |
|
|
|
2382 |
|
|
void |
2383 |
|
|
init_current_media(void) |
2384 |
|
|
{ |
2385 |
|
|
struct ifmediareq ifmr; |
2386 |
|
|
|
2387 |
|
|
/* |
2388 |
|
|
* If we have not yet done so, grab the currently-selected |
2389 |
|
|
* media. |
2390 |
|
|
*/ |
2391 |
|
|
if ((actions & (A_MEDIA|A_MEDIAOPT|A_MEDIAMODE)) == 0) { |
2392 |
|
|
(void) memset(&ifmr, 0, sizeof(ifmr)); |
2393 |
|
|
(void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); |
2394 |
|
|
|
2395 |
|
|
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { |
2396 |
|
|
/* |
2397 |
|
|
* If we get E2BIG, the kernel is telling us |
2398 |
|
|
* that there are more, so we can ignore it. |
2399 |
|
|
*/ |
2400 |
|
|
if (errno != E2BIG) |
2401 |
|
|
err(1, "SIOCGIFMEDIA"); |
2402 |
|
|
} |
2403 |
|
|
|
2404 |
|
|
media_current = ifmr.ifm_current; |
2405 |
|
|
} |
2406 |
|
|
|
2407 |
|
|
/* Sanity. */ |
2408 |
|
|
if (IFM_TYPE(media_current) == 0) |
2409 |
|
|
errx(1, "%s: no link type?", name); |
2410 |
|
|
} |
2411 |
|
|
|
2412 |
|
|
void |
2413 |
|
|
process_media_commands(void) |
2414 |
|
102 |
{ |
2415 |
|
|
|
2416 |
✓✗ |
102 |
if ((actions & (A_MEDIA|A_MEDIAOPT|A_MEDIAMODE)) == 0) { |
2417 |
|
|
/* Nothing to do. */ |
2418 |
|
102 |
return; |
2419 |
|
|
} |
2420 |
|
|
|
2421 |
|
|
/* |
2422 |
|
|
* Media already set up, and commands sanity-checked. Set/clear |
2423 |
|
|
* any options, and we're ready to go. |
2424 |
|
|
*/ |
2425 |
|
|
media_current |= mediaopt_set; |
2426 |
|
|
media_current &= ~mediaopt_clear; |
2427 |
|
|
|
2428 |
|
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
2429 |
|
|
ifr.ifr_media = media_current; |
2430 |
|
|
|
2431 |
|
|
if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) |
2432 |
|
|
; |
2433 |
|
|
} |
2434 |
|
|
|
2435 |
|
|
/* ARGSUSED */ |
2436 |
|
|
void |
2437 |
|
|
setmedia(const char *val, int d) |
2438 |
|
|
{ |
2439 |
|
|
uint64_t type, subtype, inst; |
2440 |
|
|
|
2441 |
|
|
if (val == NULL) { |
2442 |
|
|
if (showmediaflag) |
2443 |
|
|
usage(1); |
2444 |
|
|
showmediaflag = 1; |
2445 |
|
|
return; |
2446 |
|
|
} |
2447 |
|
|
|
2448 |
|
|
init_current_media(); |
2449 |
|
|
|
2450 |
|
|
/* Only one media command may be given. */ |
2451 |
|
|
if (actions & A_MEDIA) |
2452 |
|
|
errx(1, "only one `media' command may be issued"); |
2453 |
|
|
|
2454 |
|
|
/* Must not come after mode commands */ |
2455 |
|
|
if (actions & A_MEDIAMODE) |
2456 |
|
|
errx(1, "may not issue `media' after `mode' commands"); |
2457 |
|
|
|
2458 |
|
|
/* Must not come after mediaopt commands */ |
2459 |
|
|
if (actions & A_MEDIAOPT) |
2460 |
|
|
errx(1, "may not issue `media' after `mediaopt' commands"); |
2461 |
|
|
|
2462 |
|
|
/* |
2463 |
|
|
* No need to check if `instance' has been issued; setmediainst() |
2464 |
|
|
* craps out if `media' has not been specified. |
2465 |
|
|
*/ |
2466 |
|
|
|
2467 |
|
|
type = IFM_TYPE(media_current); |
2468 |
|
|
inst = IFM_INST(media_current); |
2469 |
|
|
|
2470 |
|
|
/* Look up the subtype. */ |
2471 |
|
|
subtype = get_media_subtype(type, val); |
2472 |
|
|
|
2473 |
|
|
/* Build the new current media word. */ |
2474 |
|
|
media_current = IFM_MAKEWORD(type, subtype, 0, inst); |
2475 |
|
|
|
2476 |
|
|
/* Media will be set after other processing is complete. */ |
2477 |
|
|
} |
2478 |
|
|
|
2479 |
|
|
/* ARGSUSED */ |
2480 |
|
|
void |
2481 |
|
|
setmediamode(const char *val, int d) |
2482 |
|
|
{ |
2483 |
|
|
uint64_t type, subtype, options, inst, mode; |
2484 |
|
|
|
2485 |
|
|
init_current_media(); |
2486 |
|
|
|
2487 |
|
|
/* Can only issue `mode' once. */ |
2488 |
|
|
if (actions & A_MEDIAMODE) |
2489 |
|
|
errx(1, "only one `mode' command may be issued"); |
2490 |
|
|
|
2491 |
|
|
type = IFM_TYPE(media_current); |
2492 |
|
|
subtype = IFM_SUBTYPE(media_current); |
2493 |
|
|
options = IFM_OPTIONS(media_current); |
2494 |
|
|
inst = IFM_INST(media_current); |
2495 |
|
|
|
2496 |
|
|
if ((mode = get_media_mode(type, val)) == -1) |
2497 |
|
|
errx(1, "invalid media mode: %s", val); |
2498 |
|
|
media_current = IFM_MAKEWORD(type, subtype, options, inst) | mode; |
2499 |
|
|
/* Media will be set after other processing is complete. */ |
2500 |
|
|
} |
2501 |
|
|
|
2502 |
|
|
void |
2503 |
|
|
unsetmediamode(const char *val, int d) |
2504 |
|
|
{ |
2505 |
|
|
uint64_t type, subtype, options, inst; |
2506 |
|
|
|
2507 |
|
|
init_current_media(); |
2508 |
|
|
|
2509 |
|
|
/* Can only issue `mode' once. */ |
2510 |
|
|
if (actions & A_MEDIAMODE) |
2511 |
|
|
errx(1, "only one `mode' command may be issued"); |
2512 |
|
|
|
2513 |
|
|
type = IFM_TYPE(media_current); |
2514 |
|
|
subtype = IFM_SUBTYPE(media_current); |
2515 |
|
|
options = IFM_OPTIONS(media_current); |
2516 |
|
|
inst = IFM_INST(media_current); |
2517 |
|
|
|
2518 |
|
|
media_current = IFM_MAKEWORD(type, subtype, options, inst) | |
2519 |
|
|
(IFM_AUTO << IFM_MSHIFT); |
2520 |
|
|
/* Media will be set after other processing is complete. */ |
2521 |
|
|
} |
2522 |
|
|
|
2523 |
|
|
void |
2524 |
|
|
setmediaopt(const char *val, int d) |
2525 |
|
|
{ |
2526 |
|
|
|
2527 |
|
|
init_current_media(); |
2528 |
|
|
|
2529 |
|
|
/* Can only issue `mediaopt' once. */ |
2530 |
|
|
if (actions & A_MEDIAOPTSET) |
2531 |
|
|
errx(1, "only one `mediaopt' command may be issued"); |
2532 |
|
|
|
2533 |
|
|
/* Can't issue `mediaopt' if `instance' has already been issued. */ |
2534 |
|
|
if (actions & A_MEDIAINST) |
2535 |
|
|
errx(1, "may not issue `mediaopt' after `instance'"); |
2536 |
|
|
|
2537 |
|
|
mediaopt_set = get_media_options(IFM_TYPE(media_current), val); |
2538 |
|
|
|
2539 |
|
|
/* Media will be set after other processing is complete. */ |
2540 |
|
|
} |
2541 |
|
|
|
2542 |
|
|
/* ARGSUSED */ |
2543 |
|
|
void |
2544 |
|
|
unsetmediaopt(const char *val, int d) |
2545 |
|
|
{ |
2546 |
|
|
|
2547 |
|
|
init_current_media(); |
2548 |
|
|
|
2549 |
|
|
/* Can only issue `-mediaopt' once. */ |
2550 |
|
|
if (actions & A_MEDIAOPTCLR) |
2551 |
|
|
errx(1, "only one `-mediaopt' command may be issued"); |
2552 |
|
|
|
2553 |
|
|
/* May not issue `media' and `-mediaopt'. */ |
2554 |
|
|
if (actions & A_MEDIA) |
2555 |
|
|
errx(1, "may not issue both `media' and `-mediaopt'"); |
2556 |
|
|
|
2557 |
|
|
/* |
2558 |
|
|
* No need to check for A_MEDIAINST, since the test for A_MEDIA |
2559 |
|
|
* implicitly checks for A_MEDIAINST. |
2560 |
|
|
*/ |
2561 |
|
|
|
2562 |
|
|
mediaopt_clear = get_media_options(IFM_TYPE(media_current), val); |
2563 |
|
|
|
2564 |
|
|
/* Media will be set after other processing is complete. */ |
2565 |
|
|
} |
2566 |
|
|
|
2567 |
|
|
/* ARGSUSED */ |
2568 |
|
|
void |
2569 |
|
|
setmediainst(const char *val, int d) |
2570 |
|
|
{ |
2571 |
|
|
uint64_t type, subtype, options, inst; |
2572 |
|
|
const char *errmsg = NULL; |
2573 |
|
|
|
2574 |
|
|
init_current_media(); |
2575 |
|
|
|
2576 |
|
|
/* Can only issue `instance' once. */ |
2577 |
|
|
if (actions & A_MEDIAINST) |
2578 |
|
|
errx(1, "only one `instance' command may be issued"); |
2579 |
|
|
|
2580 |
|
|
/* Must have already specified `media' */ |
2581 |
|
|
if ((actions & A_MEDIA) == 0) |
2582 |
|
|
errx(1, "must specify `media' before `instance'"); |
2583 |
|
|
|
2584 |
|
|
type = IFM_TYPE(media_current); |
2585 |
|
|
subtype = IFM_SUBTYPE(media_current); |
2586 |
|
|
options = IFM_OPTIONS(media_current); |
2587 |
|
|
|
2588 |
|
|
inst = strtonum(val, 0, IFM_INST_MAX, &errmsg); |
2589 |
|
|
if (errmsg) |
2590 |
|
|
errx(1, "media instance %s: %s", val, errmsg); |
2591 |
|
|
|
2592 |
|
|
media_current = IFM_MAKEWORD(type, subtype, options, inst); |
2593 |
|
|
|
2594 |
|
|
/* Media will be set after other processing is complete. */ |
2595 |
|
|
} |
2596 |
|
|
|
2597 |
|
|
/* |
2598 |
|
|
* Note: |
2599 |
|
|
* bits: 0 1 2 3 4 5 .... 24 25 ... 30 31 |
2600 |
|
|
* T1 mode: N/A ch1 ch2 ch3 ch4 ch5 ch24 N/A N/A N/A |
2601 |
|
|
* E1 mode: ts0 ts1 ts2 ts3 ts4 ts5 ts24 ts25 ts30 ts31 |
2602 |
|
|
*/ |
2603 |
|
|
#ifndef SMALL |
2604 |
|
|
/* ARGSUSED */ |
2605 |
|
|
void |
2606 |
|
|
settimeslot(const char *val, int d) |
2607 |
|
|
{ |
2608 |
|
|
#define SINGLE_CHANNEL 0x1 |
2609 |
|
|
#define RANGE_CHANNEL 0x2 |
2610 |
|
|
#define ALL_CHANNELS 0xFFFFFFFF |
2611 |
|
|
unsigned long ts_map = 0; |
2612 |
|
|
char *ptr = (char *)val; |
2613 |
|
|
int ts_flag = 0; |
2614 |
|
|
int ts = 0, ts_start = 0; |
2615 |
|
|
|
2616 |
|
|
if (strcmp(val,"all") == 0) { |
2617 |
|
|
ts_map = ALL_CHANNELS; |
2618 |
|
|
} else { |
2619 |
|
|
while (*ptr != '\0') { |
2620 |
|
|
if (isdigit((unsigned char)*ptr)) { |
2621 |
|
|
ts = strtoul(ptr, &ptr, 10); |
2622 |
|
|
ts_flag |= SINGLE_CHANNEL; |
2623 |
|
|
} else { |
2624 |
|
|
if (*ptr == '-') { |
2625 |
|
|
ts_flag |= RANGE_CHANNEL; |
2626 |
|
|
ts_start = ts; |
2627 |
|
|
} else { |
2628 |
|
|
ts_map |= get_ts_map(ts_flag, |
2629 |
|
|
ts_start, ts); |
2630 |
|
|
ts_flag = 0; |
2631 |
|
|
} |
2632 |
|
|
ptr++; |
2633 |
|
|
} |
2634 |
|
|
} |
2635 |
|
|
if (ts_flag) |
2636 |
|
|
ts_map |= get_ts_map(ts_flag, ts_start, ts); |
2637 |
|
|
|
2638 |
|
|
} |
2639 |
|
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
2640 |
|
|
ifr.ifr_data = (caddr_t)&ts_map; |
2641 |
|
|
|
2642 |
|
|
if (ioctl(s, SIOCSIFTIMESLOT, (caddr_t)&ifr) < 0) |
2643 |
|
|
err(1, "SIOCSIFTIMESLOT"); |
2644 |
|
|
} |
2645 |
|
|
|
2646 |
|
|
unsigned long |
2647 |
|
|
get_ts_map(int ts_flag, int ts_start, int ts_stop) |
2648 |
|
|
{ |
2649 |
|
|
int i = 0; |
2650 |
|
|
unsigned long map = 0, mask = 0; |
2651 |
|
|
|
2652 |
|
|
if ((ts_flag & (SINGLE_CHANNEL | RANGE_CHANNEL)) == 0) |
2653 |
|
|
return 0; |
2654 |
|
|
if (ts_flag & RANGE_CHANNEL) { /* Range of channels */ |
2655 |
|
|
for (i = ts_start; i <= ts_stop; i++) { |
2656 |
|
|
mask = 1 << i; |
2657 |
|
|
map |=mask; |
2658 |
|
|
} |
2659 |
|
|
} else { /* Single channel */ |
2660 |
|
|
mask = 1 << ts_stop; |
2661 |
|
|
map |= mask; |
2662 |
|
|
} |
2663 |
|
|
return map; |
2664 |
|
|
} |
2665 |
|
|
|
2666 |
|
|
void |
2667 |
|
|
timeslot_status(void) |
2668 |
|
|
{ |
2669 |
|
|
char *sep = " "; |
2670 |
|
|
unsigned long ts_map = 0; |
2671 |
|
|
int i, start = -1; |
2672 |
|
|
|
2673 |
|
|
ifr.ifr_data = (caddr_t)&ts_map; |
2674 |
|
|
|
2675 |
|
|
if (ioctl(s, SIOCGIFTIMESLOT, (caddr_t)&ifr) == -1) |
2676 |
|
|
return; |
2677 |
|
|
|
2678 |
|
|
printf("\ttimeslot:"); |
2679 |
|
|
for (i = 0; i < sizeof(ts_map) * 8; i++) { |
2680 |
|
|
if (start == -1 && ts_map & (1 << i)) |
2681 |
|
|
start = i; |
2682 |
|
|
else if (start != -1 && !(ts_map & (1 << i))) { |
2683 |
|
|
if (start == i - 1) |
2684 |
|
|
printf("%s%d", sep, start); |
2685 |
|
|
else |
2686 |
|
|
printf("%s%d-%d", sep, start, i-1); |
2687 |
|
|
sep = ","; |
2688 |
|
|
start = -1; |
2689 |
|
|
} |
2690 |
|
|
} |
2691 |
|
|
if (start != -1) { |
2692 |
|
|
if (start == i - 1) |
2693 |
|
|
printf("%s%d", sep, start); |
2694 |
|
|
else |
2695 |
|
|
printf("%s%d-%d", sep, start, i-1); |
2696 |
|
|
} |
2697 |
|
|
printf("\n"); |
2698 |
|
|
} |
2699 |
|
|
#endif |
2700 |
|
|
|
2701 |
|
|
|
2702 |
|
|
const struct ifmedia_description ifm_type_descriptions[] = |
2703 |
|
|
IFM_TYPE_DESCRIPTIONS; |
2704 |
|
|
|
2705 |
|
|
const struct ifmedia_description ifm_subtype_descriptions[] = |
2706 |
|
|
IFM_SUBTYPE_DESCRIPTIONS; |
2707 |
|
|
|
2708 |
|
|
struct ifmedia_description ifm_mode_descriptions[] = |
2709 |
|
|
IFM_MODE_DESCRIPTIONS; |
2710 |
|
|
|
2711 |
|
|
const struct ifmedia_description ifm_option_descriptions[] = |
2712 |
|
|
IFM_OPTION_DESCRIPTIONS; |
2713 |
|
|
|
2714 |
|
|
const char * |
2715 |
|
|
get_media_type_string(uint64_t mword) |
2716 |
|
|
{ |
2717 |
|
|
const struct ifmedia_description *desc; |
2718 |
|
|
|
2719 |
|
|
for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; |
2720 |
|
|
desc++) { |
2721 |
|
|
if (IFM_TYPE(mword) == desc->ifmt_word) |
2722 |
|
|
return (desc->ifmt_string); |
2723 |
|
|
} |
2724 |
|
|
return ("<unknown type>"); |
2725 |
|
|
} |
2726 |
|
|
|
2727 |
|
|
const char * |
2728 |
|
|
get_media_subtype_string(uint64_t mword) |
2729 |
|
|
{ |
2730 |
|
|
const struct ifmedia_description *desc; |
2731 |
|
|
|
2732 |
|
|
for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL; |
2733 |
|
|
desc++) { |
2734 |
|
|
if (IFM_TYPE_MATCH(desc->ifmt_word, mword) && |
2735 |
|
|
IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(mword)) |
2736 |
|
|
return (desc->ifmt_string); |
2737 |
|
|
} |
2738 |
|
|
return ("<unknown subtype>"); |
2739 |
|
|
} |
2740 |
|
|
|
2741 |
|
|
uint64_t |
2742 |
|
|
get_media_subtype(uint64_t type, const char *val) |
2743 |
|
|
{ |
2744 |
|
|
uint64_t rval; |
2745 |
|
|
|
2746 |
|
|
rval = lookup_media_word(ifm_subtype_descriptions, type, val); |
2747 |
|
|
if (rval == -1) |
2748 |
|
|
errx(1, "unknown %s media subtype: %s", |
2749 |
|
|
get_media_type_string(type), val); |
2750 |
|
|
|
2751 |
|
|
return (rval); |
2752 |
|
|
} |
2753 |
|
|
|
2754 |
|
|
uint64_t |
2755 |
|
|
get_media_mode(uint64_t type, const char *val) |
2756 |
|
|
{ |
2757 |
|
|
uint64_t rval; |
2758 |
|
|
|
2759 |
|
|
rval = lookup_media_word(ifm_mode_descriptions, type, val); |
2760 |
|
|
if (rval == -1) |
2761 |
|
|
errx(1, "unknown %s media mode: %s", |
2762 |
|
|
get_media_type_string(type), val); |
2763 |
|
|
return (rval); |
2764 |
|
|
} |
2765 |
|
|
|
2766 |
|
|
uint64_t |
2767 |
|
|
get_media_options(uint64_t type, const char *val) |
2768 |
|
|
{ |
2769 |
|
|
char *optlist, *str; |
2770 |
|
|
uint64_t option, rval = 0; |
2771 |
|
|
|
2772 |
|
|
/* We muck with the string, so copy it. */ |
2773 |
|
|
optlist = strdup(val); |
2774 |
|
|
if (optlist == NULL) |
2775 |
|
|
err(1, "strdup"); |
2776 |
|
|
str = optlist; |
2777 |
|
|
|
2778 |
|
|
/* |
2779 |
|
|
* Look up the options in the user-provided comma-separated list. |
2780 |
|
|
*/ |
2781 |
|
|
for (; (str = strtok(str, ",")) != NULL; str = NULL) { |
2782 |
|
|
option = lookup_media_word(ifm_option_descriptions, type, str); |
2783 |
|
|
if (option == -1) |
2784 |
|
|
errx(1, "unknown %s media option: %s", |
2785 |
|
|
get_media_type_string(type), str); |
2786 |
|
|
rval |= IFM_OPTIONS(option); |
2787 |
|
|
} |
2788 |
|
|
|
2789 |
|
|
free(optlist); |
2790 |
|
|
return (rval); |
2791 |
|
|
} |
2792 |
|
|
|
2793 |
|
|
uint64_t |
2794 |
|
|
lookup_media_word(const struct ifmedia_description *desc, uint64_t type, |
2795 |
|
|
const char *val) |
2796 |
|
|
{ |
2797 |
|
|
|
2798 |
|
|
for (; desc->ifmt_string != NULL; desc++) { |
2799 |
|
|
if (IFM_TYPE_MATCH(desc->ifmt_word, type) && |
2800 |
|
|
strcasecmp(desc->ifmt_string, val) == 0) |
2801 |
|
|
return (desc->ifmt_word); |
2802 |
|
|
} |
2803 |
|
|
return (-1); |
2804 |
|
|
} |
2805 |
|
|
|
2806 |
|
|
void |
2807 |
|
|
print_media_word(uint64_t ifmw, int print_type, int as_syntax) |
2808 |
|
|
{ |
2809 |
|
|
const struct ifmedia_description *desc; |
2810 |
|
|
uint64_t seen_option = 0; |
2811 |
|
|
|
2812 |
|
|
if (print_type) |
2813 |
|
|
printf("%s ", get_media_type_string(ifmw)); |
2814 |
|
|
printf("%s%s", as_syntax ? "media " : "", |
2815 |
|
|
get_media_subtype_string(ifmw)); |
2816 |
|
|
|
2817 |
|
|
/* Find mode. */ |
2818 |
|
|
if (IFM_MODE(ifmw) != 0) { |
2819 |
|
|
for (desc = ifm_mode_descriptions; desc->ifmt_string != NULL; |
2820 |
|
|
desc++) { |
2821 |
|
|
if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) && |
2822 |
|
|
IFM_MODE(ifmw) == IFM_MODE(desc->ifmt_word)) { |
2823 |
|
|
printf(" mode %s", desc->ifmt_string); |
2824 |
|
|
break; |
2825 |
|
|
} |
2826 |
|
|
} |
2827 |
|
|
} |
2828 |
|
|
|
2829 |
|
|
/* Find options. */ |
2830 |
|
|
for (desc = ifm_option_descriptions; desc->ifmt_string != NULL; |
2831 |
|
|
desc++) { |
2832 |
|
|
if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) && |
2833 |
|
|
(IFM_OPTIONS(ifmw) & IFM_OPTIONS(desc->ifmt_word)) != 0 && |
2834 |
|
|
(seen_option & IFM_OPTIONS(desc->ifmt_word)) == 0) { |
2835 |
|
|
if (seen_option == 0) |
2836 |
|
|
printf(" %s", as_syntax ? "mediaopt " : ""); |
2837 |
|
|
printf("%s%s", seen_option ? "," : "", |
2838 |
|
|
desc->ifmt_string); |
2839 |
|
|
seen_option |= IFM_OPTIONS(desc->ifmt_word); |
2840 |
|
|
} |
2841 |
|
|
} |
2842 |
|
|
if (IFM_INST(ifmw) != 0) |
2843 |
|
|
printf(" instance %lld", IFM_INST(ifmw)); |
2844 |
|
|
} |
2845 |
|
|
|
2846 |
|
|
/* ARGSUSED */ |
2847 |
|
|
static void |
2848 |
|
|
phys_status(int force) |
2849 |
|
|
{ |
2850 |
|
|
char psrcaddr[NI_MAXHOST]; |
2851 |
|
|
char pdstaddr[NI_MAXHOST]; |
2852 |
|
|
const char *ver = ""; |
2853 |
|
|
const int niflag = NI_NUMERICHOST; |
2854 |
|
|
struct if_laddrreq req; |
2855 |
|
|
in_port_t dstport = 0; |
2856 |
|
|
|
2857 |
|
|
psrcaddr[0] = pdstaddr[0] = '\0'; |
2858 |
|
|
|
2859 |
|
|
memset(&req, 0, sizeof(req)); |
2860 |
|
|
(void) strlcpy(req.iflr_name, name, sizeof(req.iflr_name)); |
2861 |
|
|
if (ioctl(s, SIOCGLIFPHYADDR, (caddr_t)&req) < 0) |
2862 |
|
|
return; |
2863 |
|
|
if (req.addr.ss_family == AF_INET6) |
2864 |
|
|
in6_fillscopeid((struct sockaddr_in6 *)&req.addr); |
2865 |
|
|
if (getnameinfo((struct sockaddr *)&req.addr, req.addr.ss_len, |
2866 |
|
|
psrcaddr, sizeof(psrcaddr), 0, 0, niflag) != 0) |
2867 |
|
|
strlcpy(psrcaddr, "<error>", sizeof(psrcaddr)); |
2868 |
|
|
if (req.addr.ss_family == AF_INET6) |
2869 |
|
|
ver = "6"; |
2870 |
|
|
|
2871 |
|
|
if (req.dstaddr.ss_family == AF_INET) |
2872 |
|
|
dstport = ((struct sockaddr_in *)&req.dstaddr)->sin_port; |
2873 |
|
|
else if (req.dstaddr.ss_family == AF_INET6) { |
2874 |
|
|
in6_fillscopeid((struct sockaddr_in6 *)&req.dstaddr); |
2875 |
|
|
dstport = ((struct sockaddr_in6 *)&req.dstaddr)->sin6_port; |
2876 |
|
|
} |
2877 |
|
|
if (getnameinfo((struct sockaddr *)&req.dstaddr, req.dstaddr.ss_len, |
2878 |
|
|
pdstaddr, sizeof(pdstaddr), 0, 0, niflag) != 0) |
2879 |
|
|
strlcpy(pdstaddr, "<error>", sizeof(pdstaddr)); |
2880 |
|
|
|
2881 |
|
|
printf("\ttunnel: inet%s %s -> %s", ver, |
2882 |
|
|
psrcaddr, pdstaddr); |
2883 |
|
|
|
2884 |
|
|
if (dstport) |
2885 |
|
|
printf(":%u", ntohs(dstport)); |
2886 |
|
|
if (ioctl(s, SIOCGLIFPHYTTL, (caddr_t)&ifr) == 0 && ifr.ifr_ttl > 0) |
2887 |
|
|
printf(" ttl %d", ifr.ifr_ttl); |
2888 |
|
|
#ifndef SMALL |
2889 |
|
|
if (ioctl(s, SIOCGLIFPHYRTABLE, (caddr_t)&ifr) == 0 && |
2890 |
|
|
(rdomainid != 0 || ifr.ifr_rdomainid != 0)) |
2891 |
|
|
printf(" rdomain %d", ifr.ifr_rdomainid); |
2892 |
|
|
#endif |
2893 |
|
|
printf("\n"); |
2894 |
|
|
} |
2895 |
|
|
|
2896 |
|
|
#ifndef SMALL |
2897 |
|
|
const uint64_t ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; |
2898 |
|
|
|
2899 |
|
|
const struct ifmedia_status_description ifm_status_descriptions[] = |
2900 |
|
|
IFM_STATUS_DESCRIPTIONS; |
2901 |
|
|
#endif |
2902 |
|
|
|
2903 |
|
|
const struct if_status_description if_status_descriptions[] = |
2904 |
|
|
LINK_STATE_DESCRIPTIONS; |
2905 |
|
|
|
2906 |
|
|
const char * |
2907 |
|
|
get_linkstate(int mt, int link_state) |
2908 |
|
|
{ |
2909 |
|
|
const struct if_status_description *p; |
2910 |
|
|
static char buf[8]; |
2911 |
|
|
|
2912 |
|
|
for (p = if_status_descriptions; p->ifs_string != NULL; p++) { |
2913 |
|
|
if (LINK_STATE_DESC_MATCH(p, mt, link_state)) |
2914 |
|
|
return (p->ifs_string); |
2915 |
|
|
} |
2916 |
|
|
snprintf(buf, sizeof(buf), "[#%d]", link_state); |
2917 |
|
|
return buf; |
2918 |
|
|
} |
2919 |
|
|
|
2920 |
|
|
/* |
2921 |
|
|
* Print the status of the interface. If an address family was |
2922 |
|
|
* specified, show it and it only; otherwise, show them all. |
2923 |
|
|
*/ |
2924 |
|
|
void |
2925 |
|
|
status(int link, struct sockaddr_dl *sdl, int ls) |
2926 |
|
|
{ |
2927 |
|
|
const struct afswtch *p = afp; |
2928 |
|
|
struct ifmediareq ifmr; |
2929 |
|
|
#ifndef SMALL |
2930 |
|
|
struct ifreq ifrdesc; |
2931 |
|
|
struct ifkalivereq ikardesc; |
2932 |
|
|
char ifdescr[IFDESCRSIZE]; |
2933 |
|
|
char ifname[IF_NAMESIZE]; |
2934 |
|
|
#endif |
2935 |
|
|
uint64_t *media_list; |
2936 |
|
|
int i; |
2937 |
|
|
char sep; |
2938 |
|
|
|
2939 |
|
|
|
2940 |
|
|
printf("%s: ", name); |
2941 |
|
|
printb("flags", flags | (xflags << 16), IFFBITS); |
2942 |
|
|
if (rdomainid) |
2943 |
|
|
printf(" rdomain %d", rdomainid); |
2944 |
|
|
if (metric) |
2945 |
|
|
printf(" metric %lu", metric); |
2946 |
|
|
if (mtu) |
2947 |
|
|
printf(" mtu %lu", mtu); |
2948 |
|
|
putchar('\n'); |
2949 |
|
|
#ifndef SMALL |
2950 |
|
|
if (showcapsflag) |
2951 |
|
|
printifhwfeatures(NULL, 1); |
2952 |
|
|
#endif |
2953 |
|
|
if (sdl != NULL && sdl->sdl_alen && |
2954 |
|
|
(sdl->sdl_type == IFT_ETHER || sdl->sdl_type == IFT_CARP)) |
2955 |
|
|
(void)printf("\tlladdr %s\n", ether_ntoa( |
2956 |
|
|
(struct ether_addr *)LLADDR(sdl))); |
2957 |
|
|
|
2958 |
|
|
sep = '\t'; |
2959 |
|
|
#ifndef SMALL |
2960 |
|
|
(void) memset(&ifrdesc, 0, sizeof(ifrdesc)); |
2961 |
|
|
(void) strlcpy(ifrdesc.ifr_name, name, sizeof(ifrdesc.ifr_name)); |
2962 |
|
|
ifrdesc.ifr_data = (caddr_t)&ifdescr; |
2963 |
|
|
if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0 && |
2964 |
|
|
strlen(ifrdesc.ifr_data)) |
2965 |
|
|
printf("\tdescription: %s\n", ifrdesc.ifr_data); |
2966 |
|
|
|
2967 |
|
|
if (sdl != NULL) { |
2968 |
|
|
printf("%cindex %u", sep, sdl->sdl_index); |
2969 |
|
|
sep = ' '; |
2970 |
|
|
} |
2971 |
|
|
if (!is_bridge(name) && ioctl(s, SIOCGIFPRIORITY, &ifrdesc) == 0) { |
2972 |
|
|
printf("%cpriority %d", sep, ifrdesc.ifr_metric); |
2973 |
|
|
sep = ' '; |
2974 |
|
|
} |
2975 |
|
|
#endif |
2976 |
|
|
printf("%cllprio %d\n", sep, llprio); |
2977 |
|
|
|
2978 |
|
|
#ifndef SMALL |
2979 |
|
|
(void) memset(&ikardesc, 0, sizeof(ikardesc)); |
2980 |
|
|
(void) strlcpy(ikardesc.ikar_name, name, sizeof(ikardesc.ikar_name)); |
2981 |
|
|
if (ioctl(s, SIOCGETKALIVE, &ikardesc) == 0 && |
2982 |
|
|
(ikardesc.ikar_timeo != 0 || ikardesc.ikar_cnt != 0)) |
2983 |
|
|
printf("\tkeepalive: timeout %d count %d\n", |
2984 |
|
|
ikardesc.ikar_timeo, ikardesc.ikar_cnt); |
2985 |
|
|
if (ioctl(s, SIOCGIFPAIR, &ifrdesc) == 0 && ifrdesc.ifr_index != 0 && |
2986 |
|
|
if_indextoname(ifrdesc.ifr_index, ifname) != NULL) |
2987 |
|
|
printf("\tpatch: %s\n", ifname); |
2988 |
|
|
#endif |
2989 |
|
|
vlan_status(); |
2990 |
|
|
getvnetid(); |
2991 |
|
|
getifparent(); |
2992 |
|
|
#ifndef SMALL |
2993 |
|
|
carp_status(); |
2994 |
|
|
pfsync_status(); |
2995 |
|
|
pppoe_status(); |
2996 |
|
|
timeslot_status(); |
2997 |
|
|
sppp_status(); |
2998 |
|
|
mpe_status(); |
2999 |
|
|
mpw_status(); |
3000 |
|
|
pflow_status(); |
3001 |
|
|
umb_status(); |
3002 |
|
|
#endif |
3003 |
|
|
trunk_status(); |
3004 |
|
|
getifgroups(); |
3005 |
|
|
|
3006 |
|
|
(void) memset(&ifmr, 0, sizeof(ifmr)); |
3007 |
|
|
(void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); |
3008 |
|
|
|
3009 |
|
|
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { |
3010 |
|
|
/* |
3011 |
|
|
* Interface doesn't support SIOC{G,S}IFMEDIA. |
3012 |
|
|
*/ |
3013 |
|
|
if (ls != LINK_STATE_UNKNOWN) |
3014 |
|
|
printf("\tstatus: %s\n", |
3015 |
|
|
get_linkstate(sdl->sdl_type, ls)); |
3016 |
|
|
goto proto_status; |
3017 |
|
|
} |
3018 |
|
|
|
3019 |
|
|
if (ifmr.ifm_count == 0) { |
3020 |
|
|
warnx("%s: no media types?", name); |
3021 |
|
|
goto proto_status; |
3022 |
|
|
} |
3023 |
|
|
|
3024 |
|
|
media_list = calloc(ifmr.ifm_count, sizeof(*media_list)); |
3025 |
|
|
if (media_list == NULL) |
3026 |
|
|
err(1, "calloc"); |
3027 |
|
|
ifmr.ifm_ulist = media_list; |
3028 |
|
|
|
3029 |
|
|
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) |
3030 |
|
|
err(1, "SIOCGIFMEDIA"); |
3031 |
|
|
|
3032 |
|
|
printf("\tmedia: "); |
3033 |
|
|
print_media_word(ifmr.ifm_current, 1, 0); |
3034 |
|
|
if (ifmr.ifm_active != ifmr.ifm_current) { |
3035 |
|
|
putchar(' '); |
3036 |
|
|
putchar('('); |
3037 |
|
|
print_media_word(ifmr.ifm_active, 0, 0); |
3038 |
|
|
putchar(')'); |
3039 |
|
|
} |
3040 |
|
|
putchar('\n'); |
3041 |
|
|
|
3042 |
|
|
#ifdef SMALL |
3043 |
|
|
printf("\tstatus: %s\n", get_linkstate(sdl->sdl_type, ls)); |
3044 |
|
|
#else |
3045 |
|
|
if (ifmr.ifm_status & IFM_AVALID) { |
3046 |
|
|
const struct ifmedia_status_description *ifms; |
3047 |
|
|
int bitno, found = 0; |
3048 |
|
|
|
3049 |
|
|
printf("\tstatus: "); |
3050 |
|
|
for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) { |
3051 |
|
|
for (ifms = ifm_status_descriptions; |
3052 |
|
|
ifms->ifms_valid != 0; ifms++) { |
3053 |
|
|
if (ifms->ifms_type != |
3054 |
|
|
IFM_TYPE(ifmr.ifm_current) || |
3055 |
|
|
ifms->ifms_valid != |
3056 |
|
|
ifm_status_valid_list[bitno]) |
3057 |
|
|
continue; |
3058 |
|
|
printf("%s%s", found ? ", " : "", |
3059 |
|
|
IFM_STATUS_DESC(ifms, ifmr.ifm_status)); |
3060 |
|
|
found = 1; |
3061 |
|
|
|
3062 |
|
|
/* |
3063 |
|
|
* For each valid indicator bit, there's |
3064 |
|
|
* only one entry for each media type, so |
3065 |
|
|
* terminate the inner loop now. |
3066 |
|
|
*/ |
3067 |
|
|
break; |
3068 |
|
|
} |
3069 |
|
|
} |
3070 |
|
|
|
3071 |
|
|
if (found == 0) |
3072 |
|
|
printf("unknown"); |
3073 |
|
|
putchar('\n'); |
3074 |
|
|
} |
3075 |
|
|
#endif |
3076 |
|
|
ieee80211_status(); |
3077 |
|
|
|
3078 |
|
|
if (showmediaflag) { |
3079 |
|
|
uint64_t type; |
3080 |
|
|
int printed_type = 0; |
3081 |
|
|
|
3082 |
|
|
for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) { |
3083 |
|
|
for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) { |
3084 |
|
|
if (IFM_TYPE(media_list[i]) == type) { |
3085 |
|
|
|
3086 |
|
|
/* |
3087 |
|
|
* Don't advertise media with fixed |
3088 |
|
|
* data rates for wireless interfaces. |
3089 |
|
|
* Normal people don't need these. |
3090 |
|
|
*/ |
3091 |
|
|
if (type == IFM_IEEE80211 && |
3092 |
|
|
(media_list[i] & IFM_TMASK) != |
3093 |
|
|
IFM_AUTO) |
3094 |
|
|
continue; |
3095 |
|
|
|
3096 |
|
|
if (printed_type == 0) { |
3097 |
|
|
printf("\tsupported media:\n"); |
3098 |
|
|
printed_type = 1; |
3099 |
|
|
} |
3100 |
|
|
printf("\t\t"); |
3101 |
|
|
print_media_word(media_list[i], 0, 1); |
3102 |
|
|
printf("\n"); |
3103 |
|
|
} |
3104 |
|
|
} |
3105 |
|
|
} |
3106 |
|
|
} |
3107 |
|
|
|
3108 |
|
|
free(media_list); |
3109 |
|
|
|
3110 |
|
|
proto_status: |
3111 |
|
|
if (link == 0) { |
3112 |
|
|
if ((p = afp) != NULL) { |
3113 |
|
|
p->af_status(1); |
3114 |
|
|
} else for (p = afs; p->af_name; p++) { |
3115 |
|
|
ifr.ifr_addr.sa_family = p->af_af; |
3116 |
|
|
p->af_status(0); |
3117 |
|
|
} |
3118 |
|
|
} |
3119 |
|
|
|
3120 |
|
|
phys_status(0); |
3121 |
|
|
#ifndef SMALL |
3122 |
|
|
bridge_status(); |
3123 |
|
|
#endif |
3124 |
|
|
} |
3125 |
|
|
|
3126 |
|
|
/* ARGSUSED */ |
3127 |
|
|
void |
3128 |
|
|
in_status(int force) |
3129 |
|
|
{ |
3130 |
|
|
struct sockaddr_in *sin, sin2; |
3131 |
|
|
|
3132 |
|
|
getsock(AF_INET); |
3133 |
|
|
if (s < 0) { |
3134 |
|
|
if (errno == EPROTONOSUPPORT) |
3135 |
|
|
return; |
3136 |
|
|
err(1, "socket"); |
3137 |
|
|
} |
3138 |
|
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
3139 |
|
|
sin = (struct sockaddr_in *)&ifr.ifr_addr; |
3140 |
|
|
|
3141 |
|
|
/* |
3142 |
|
|
* We keep the interface address and reset it before each |
3143 |
|
|
* ioctl() so we can get ifaliases information (as opposed |
3144 |
|
|
* to the primary interface netmask/dstaddr/broadaddr, if |
3145 |
|
|
* the ifr_addr field is zero). |
3146 |
|
|
*/ |
3147 |
|
|
memcpy(&sin2, &ifr.ifr_addr, sizeof(sin2)); |
3148 |
|
|
|
3149 |
|
|
printf("\tinet %s", inet_ntoa(sin->sin_addr)); |
3150 |
|
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
3151 |
|
|
if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { |
3152 |
|
|
if (errno != EADDRNOTAVAIL) |
3153 |
|
|
warn("SIOCGIFNETMASK"); |
3154 |
|
|
memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); |
3155 |
|
|
} else |
3156 |
|
|
netmask.sin_addr = |
3157 |
|
|
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; |
3158 |
|
|
if (flags & IFF_POINTOPOINT) { |
3159 |
|
|
memcpy(&ifr.ifr_addr, &sin2, sizeof(sin2)); |
3160 |
|
|
if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { |
3161 |
|
|
if (errno == EADDRNOTAVAIL) |
3162 |
|
|
memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); |
3163 |
|
|
else |
3164 |
|
|
warn("SIOCGIFDSTADDR"); |
3165 |
|
|
} |
3166 |
|
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
3167 |
|
|
sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; |
3168 |
|
|
printf(" --> %s", inet_ntoa(sin->sin_addr)); |
3169 |
|
|
} |
3170 |
|
|
printf(" netmask 0x%x", ntohl(netmask.sin_addr.s_addr)); |
3171 |
|
|
if (flags & IFF_BROADCAST) { |
3172 |
|
|
memcpy(&ifr.ifr_addr, &sin2, sizeof(sin2)); |
3173 |
|
|
if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { |
3174 |
|
|
if (errno == EADDRNOTAVAIL) |
3175 |
|
|
memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); |
3176 |
|
|
else |
3177 |
|
|
warn("SIOCGIFBRDADDR"); |
3178 |
|
|
} |
3179 |
|
|
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
3180 |
|
|
sin = (struct sockaddr_in *)&ifr.ifr_addr; |
3181 |
|
|
if (sin->sin_addr.s_addr != 0) |
3182 |
|
|
printf(" broadcast %s", inet_ntoa(sin->sin_addr)); |
3183 |
|
|
} |
3184 |
|
|
putchar('\n'); |
3185 |
|
|
} |
3186 |
|
|
|
3187 |
|
|
/* ARGSUSED */ |
3188 |
|
|
void |
3189 |
|
|
setifprefixlen(const char *addr, int d) |
3190 |
|
2 |
{ |
3191 |
✓✗ |
2 |
if (afp->af_getprefix) |
3192 |
|
2 |
afp->af_getprefix(addr, MASK); |
3193 |
|
2 |
explicit_prefix = 1; |
3194 |
|
2 |
} |
3195 |
|
|
|
3196 |
|
|
void |
3197 |
|
|
in6_fillscopeid(struct sockaddr_in6 *sin6) |
3198 |
|
|
{ |
3199 |
|
|
#ifdef __KAME__ |
3200 |
|
|
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { |
3201 |
|
|
sin6->sin6_scope_id = |
3202 |
|
|
ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); |
3203 |
|
|
sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; |
3204 |
|
|
} |
3205 |
|
|
#endif /* __KAME__ */ |
3206 |
|
|
} |
3207 |
|
|
|
3208 |
|
|
/* XXX not really an alias */ |
3209 |
|
|
void |
3210 |
|
|
in6_alias(struct in6_ifreq *creq) |
3211 |
|
|
{ |
3212 |
|
|
struct sockaddr_in6 *sin6; |
3213 |
|
|
struct in6_ifreq ifr6; /* shadows file static variable */ |
3214 |
|
|
u_int32_t scopeid; |
3215 |
|
|
char hbuf[NI_MAXHOST]; |
3216 |
|
|
const int niflag = NI_NUMERICHOST; |
3217 |
|
|
|
3218 |
|
|
/* Get the non-alias address for this interface. */ |
3219 |
|
|
getsock(AF_INET6); |
3220 |
|
|
if (s < 0) { |
3221 |
|
|
if (errno == EPROTONOSUPPORT) |
3222 |
|
|
return; |
3223 |
|
|
err(1, "socket"); |
3224 |
|
|
} |
3225 |
|
|
|
3226 |
|
|
sin6 = (struct sockaddr_in6 *)&creq->ifr_addr; |
3227 |
|
|
|
3228 |
|
|
in6_fillscopeid(sin6); |
3229 |
|
|
scopeid = sin6->sin6_scope_id; |
3230 |
|
|
if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, |
3231 |
|
|
hbuf, sizeof(hbuf), NULL, 0, niflag) != 0) |
3232 |
|
|
strlcpy(hbuf, "", sizeof hbuf); |
3233 |
|
|
printf("\tinet6 %s", hbuf); |
3234 |
|
|
|
3235 |
|
|
if (flags & IFF_POINTOPOINT) { |
3236 |
|
|
(void) memset(&ifr6, 0, sizeof(ifr6)); |
3237 |
|
|
(void) strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); |
3238 |
|
|
ifr6.ifr_addr = creq->ifr_addr; |
3239 |
|
|
if (ioctl(s, SIOCGIFDSTADDR_IN6, (caddr_t)&ifr6) < 0) { |
3240 |
|
|
if (errno != EADDRNOTAVAIL) |
3241 |
|
|
warn("SIOCGIFDSTADDR_IN6"); |
3242 |
|
|
(void) memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr)); |
3243 |
|
|
ifr6.ifr_addr.sin6_family = AF_INET6; |
3244 |
|
|
ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6); |
3245 |
|
|
} |
3246 |
|
|
sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; |
3247 |
|
|
in6_fillscopeid(sin6); |
3248 |
|
|
if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, |
3249 |
|
|
hbuf, sizeof(hbuf), NULL, 0, niflag) != 0) |
3250 |
|
|
strlcpy(hbuf, "", sizeof hbuf); |
3251 |
|
|
printf(" -> %s", hbuf); |
3252 |
|
|
} |
3253 |
|
|
|
3254 |
|
|
(void) memset(&ifr6, 0, sizeof(ifr6)); |
3255 |
|
|
(void) strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); |
3256 |
|
|
ifr6.ifr_addr = creq->ifr_addr; |
3257 |
|
|
if (ioctl(s, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) { |
3258 |
|
|
if (errno != EADDRNOTAVAIL) |
3259 |
|
|
warn("SIOCGIFNETMASK_IN6"); |
3260 |
|
|
} else { |
3261 |
|
|
sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; |
3262 |
|
|
printf(" prefixlen %d", prefix(&sin6->sin6_addr, |
3263 |
|
|
sizeof(struct in6_addr))); |
3264 |
|
|
} |
3265 |
|
|
|
3266 |
|
|
(void) memset(&ifr6, 0, sizeof(ifr6)); |
3267 |
|
|
(void) strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); |
3268 |
|
|
ifr6.ifr_addr = creq->ifr_addr; |
3269 |
|
|
if (ioctl(s, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) < 0) { |
3270 |
|
|
if (errno != EADDRNOTAVAIL) |
3271 |
|
|
warn("SIOCGIFAFLAG_IN6"); |
3272 |
|
|
} else { |
3273 |
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST) |
3274 |
|
|
printf(" anycast"); |
3275 |
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE) |
3276 |
|
|
printf(" tentative"); |
3277 |
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED) |
3278 |
|
|
printf(" duplicated"); |
3279 |
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED) |
3280 |
|
|
printf(" detached"); |
3281 |
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED) |
3282 |
|
|
printf(" deprecated"); |
3283 |
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_AUTOCONF) |
3284 |
|
|
printf(" autoconf"); |
3285 |
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_PRIVACY) |
3286 |
|
|
printf(" autoconfprivacy"); |
3287 |
|
|
} |
3288 |
|
|
|
3289 |
|
|
if (scopeid) |
3290 |
|
|
printf(" scopeid 0x%x", scopeid); |
3291 |
|
|
|
3292 |
|
|
if (Lflag) { |
3293 |
|
|
struct in6_addrlifetime *lifetime; |
3294 |
|
|
|
3295 |
|
|
(void) memset(&ifr6, 0, sizeof(ifr6)); |
3296 |
|
|
(void) strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); |
3297 |
|
|
ifr6.ifr_addr = creq->ifr_addr; |
3298 |
|
|
lifetime = &ifr6.ifr_ifru.ifru_lifetime; |
3299 |
|
|
if (ioctl(s, SIOCGIFALIFETIME_IN6, (caddr_t)&ifr6) < 0) { |
3300 |
|
|
if (errno != EADDRNOTAVAIL) |
3301 |
|
|
warn("SIOCGIFALIFETIME_IN6"); |
3302 |
|
|
} else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) { |
3303 |
|
|
time_t t = time(NULL); |
3304 |
|
|
|
3305 |
|
|
printf(" pltime "); |
3306 |
|
|
if (lifetime->ia6t_preferred) { |
3307 |
|
|
printf("%s", lifetime->ia6t_preferred < t |
3308 |
|
|
? "0" : |
3309 |
|
|
sec2str(lifetime->ia6t_preferred - t)); |
3310 |
|
|
} else |
3311 |
|
|
printf("infty"); |
3312 |
|
|
|
3313 |
|
|
printf(" vltime "); |
3314 |
|
|
if (lifetime->ia6t_expire) { |
3315 |
|
|
printf("%s", lifetime->ia6t_expire < t |
3316 |
|
|
? "0" |
3317 |
|
|
: sec2str(lifetime->ia6t_expire - t)); |
3318 |
|
|
} else |
3319 |
|
|
printf("infty"); |
3320 |
|
|
} |
3321 |
|
|
} |
3322 |
|
|
|
3323 |
|
|
printf("\n"); |
3324 |
|
|
} |
3325 |
|
|
|
3326 |
|
|
void |
3327 |
|
|
in6_status(int force) |
3328 |
|
|
{ |
3329 |
|
|
in6_alias((struct in6_ifreq *)&ifr6); |
3330 |
|
|
} |
3331 |
|
|
|
3332 |
|
|
#ifndef SMALL |
3333 |
|
|
void |
3334 |
|
|
settunnel(const char *src, const char *dst) |
3335 |
|
|
{ |
3336 |
|
|
char buf[HOST_NAME_MAX+1 + sizeof (":65535")], *dstport; |
3337 |
|
|
const char *dstip; |
3338 |
|
|
struct addrinfo *srcres, *dstres; |
3339 |
|
|
int ecode; |
3340 |
|
|
struct if_laddrreq req; |
3341 |
|
|
|
3342 |
|
|
if (strchr(dst, ':') == NULL || strchr(dst, ':') != strrchr(dst, ':')) { |
3343 |
|
|
/* no port or IPv6 */ |
3344 |
|
|
dstip = dst; |
3345 |
|
|
dstport = NULL; |
3346 |
|
|
} else { |
3347 |
|
|
if (strlcpy(buf, dst, sizeof(buf)) >= sizeof(buf)) |
3348 |
|
|
errx(1, "%s bad value", dst); |
3349 |
|
|
dstport = strchr(buf, ':'); |
3350 |
|
|
*dstport++ = '\0'; |
3351 |
|
|
dstip = buf; |
3352 |
|
|
} |
3353 |
|
|
|
3354 |
|
|
if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0) |
3355 |
|
|
errx(1, "error in parsing address string: %s", |
3356 |
|
|
gai_strerror(ecode)); |
3357 |
|
|
|
3358 |
|
|
if ((ecode = getaddrinfo(dstip, dstport, NULL, &dstres)) != 0) |
3359 |
|
|
errx(1, "error in parsing address string: %s", |
3360 |
|
|
gai_strerror(ecode)); |
3361 |
|
|
|
3362 |
|
|
if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) |
3363 |
|
|
errx(1, |
3364 |
|
|
"source and destination address families do not match"); |
3365 |
|
|
|
3366 |
|
|
if (srcres->ai_addrlen > sizeof(req.addr) || |
3367 |
|
|
dstres->ai_addrlen > sizeof(req.dstaddr)) |
3368 |
|
|
errx(1, "invalid sockaddr"); |
3369 |
|
|
|
3370 |
|
|
memset(&req, 0, sizeof(req)); |
3371 |
|
|
(void) strlcpy(req.iflr_name, name, sizeof(req.iflr_name)); |
3372 |
|
|
memcpy(&req.addr, srcres->ai_addr, srcres->ai_addrlen); |
3373 |
|
|
memcpy(&req.dstaddr, dstres->ai_addr, dstres->ai_addrlen); |
3374 |
|
|
if (ioctl(s, SIOCSLIFPHYADDR, &req) < 0) |
3375 |
|
|
warn("SIOCSLIFPHYADDR"); |
3376 |
|
|
|
3377 |
|
|
freeaddrinfo(srcres); |
3378 |
|
|
freeaddrinfo(dstres); |
3379 |
|
|
} |
3380 |
|
|
|
3381 |
|
|
/* ARGSUSED */ |
3382 |
|
|
void |
3383 |
|
|
deletetunnel(const char *ignored, int alsoignored) |
3384 |
|
|
{ |
3385 |
|
|
if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) |
3386 |
|
|
warn("SIOCDIFPHYADDR"); |
3387 |
|
|
} |
3388 |
|
|
|
3389 |
|
|
void |
3390 |
|
|
settunnelinst(const char *id, int param) |
3391 |
|
|
{ |
3392 |
|
|
const char *errmsg = NULL; |
3393 |
|
|
int rdomainid; |
3394 |
|
|
|
3395 |
|
|
rdomainid = strtonum(id, 0, RT_TABLEID_MAX, &errmsg); |
3396 |
|
|
if (errmsg) |
3397 |
|
|
errx(1, "rdomain %s: %s", id, errmsg); |
3398 |
|
|
|
3399 |
|
|
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
3400 |
|
|
ifr.ifr_rdomainid = rdomainid; |
3401 |
|
|
if (ioctl(s, SIOCSLIFPHYRTABLE, (caddr_t)&ifr) < 0) |
3402 |
|
|
warn("SIOCSLIFPHYRTABLE"); |
3403 |
|
|
} |
3404 |
|
|
|
3405 |
|
|
void |
3406 |
|
|
settunnelttl(const char *id, int param) |
3407 |
|
|
{ |
3408 |
|
|
const char *errmsg = NULL; |
3409 |
|
|
int ttl; |
3410 |
|
|
|
3411 |
|
|
ttl = strtonum(id, 0, 0xff, &errmsg); |
3412 |
|
|
if (errmsg) |
3413 |
|
|
errx(1, "tunnelttl %s: %s", id, errmsg); |
3414 |
|
|
|
3415 |
|
|
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
3416 |
|
|
ifr.ifr_ttl = ttl; |
3417 |
|
|
if (ioctl(s, SIOCSLIFPHYTTL, (caddr_t)&ifr) < 0) |
3418 |
|
|
warn("SIOCSLIFPHYTTL"); |
3419 |
|
|
} |
3420 |
|
|
|
3421 |
|
|
void |
3422 |
|
|
mpe_status(void) |
3423 |
|
|
{ |
3424 |
|
|
struct shim_hdr shim; |
3425 |
|
|
|
3426 |
|
|
bzero(&shim, sizeof(shim)); |
3427 |
|
|
ifr.ifr_data = (caddr_t)&shim; |
3428 |
|
|
|
3429 |
|
|
if (ioctl(s, SIOCGETLABEL , (caddr_t)&ifr) == -1) |
3430 |
|
|
return; |
3431 |
|
|
printf("\tmpls label: %d\n", shim.shim_label); |
3432 |
|
|
} |
3433 |
|
|
|
3434 |
|
|
void |
3435 |
|
|
mpw_status(void) |
3436 |
|
|
{ |
3437 |
|
|
struct sockaddr_in *sin; |
3438 |
|
|
struct ifmpwreq imr; |
3439 |
|
|
|
3440 |
|
|
bzero(&imr, sizeof(imr)); |
3441 |
|
|
ifr.ifr_data = (caddr_t) &imr; |
3442 |
|
|
if (ioctl(s, SIOCGETMPWCFG, (caddr_t) &ifr) == -1) |
3443 |
|
|
return; |
3444 |
|
|
|
3445 |
|
|
printf("\tencapsulation-type "); |
3446 |
|
|
switch (imr.imr_type) { |
3447 |
|
|
case IMR_TYPE_NONE: |
3448 |
|
|
printf("none"); |
3449 |
|
|
break; |
3450 |
|
|
case IMR_TYPE_ETHERNET: |
3451 |
|
|
printf("ethernet"); |
3452 |
|
|
break; |
3453 |
|
|
case IMR_TYPE_ETHERNET_TAGGED: |
3454 |
|
|
printf("ethernet-tagged"); |
3455 |
|
|
break; |
3456 |
|
|
default: |
3457 |
|
|
printf("unknown"); |
3458 |
|
|
break; |
3459 |
|
|
} |
3460 |
|
|
|
3461 |
|
|
if (imr.imr_flags & IMR_FLAG_CONTROLWORD) |
3462 |
|
|
printf(", control-word"); |
3463 |
|
|
|
3464 |
|
|
printf("\n"); |
3465 |
|
|
|
3466 |
|
|
printf("\tmpls label: "); |
3467 |
|
|
if (imr.imr_lshim.shim_label == 0) |
3468 |
|
|
printf("local none "); |
3469 |
|
|
else |
3470 |
|
|
printf("local %u ", imr.imr_lshim.shim_label); |
3471 |
|
|
|
3472 |
|
|
if (imr.imr_rshim.shim_label == 0) |
3473 |
|
|
printf("remote none\n"); |
3474 |
|
|
else |
3475 |
|
|
printf("remote %u\n", imr.imr_rshim.shim_label); |
3476 |
|
|
|
3477 |
|
|
sin = (struct sockaddr_in *) &imr.imr_nexthop; |
3478 |
|
|
if (sin->sin_addr.s_addr == 0) |
3479 |
|
|
printf("\tneighbor: none\n"); |
3480 |
|
|
else |
3481 |
|
|
printf("\tneighbor: %s\n", inet_ntoa(sin->sin_addr)); |
3482 |
|
|
} |
3483 |
|
|
|
3484 |
|
|
/* ARGSUSED */ |
3485 |
|
|
void |
3486 |
|
|
setmpelabel(const char *val, int d) |
3487 |
|
|
{ |
3488 |
|
|
struct shim_hdr shim; |
3489 |
|
|
const char *estr; |
3490 |
|
|
|
3491 |
|
|
bzero(&shim, sizeof(shim)); |
3492 |
|
|
ifr.ifr_data = (caddr_t)&shim; |
3493 |
|
|
shim.shim_label = strtonum(val, 0, MPLS_LABEL_MAX, &estr); |
3494 |
|
|
|
3495 |
|
|
if (estr) |
3496 |
|
|
errx(1, "mpls label %s is %s", val, estr); |
3497 |
|
|
if (ioctl(s, SIOCSETLABEL, (caddr_t)&ifr) == -1) |
3498 |
|
|
warn("SIOCSETLABEL"); |
3499 |
|
|
} |
3500 |
|
|
|
3501 |
|
|
void |
3502 |
|
|
process_mpw_commands(void) |
3503 |
|
102 |
{ |
3504 |
|
|
struct sockaddr_in *sin, *sinn; |
3505 |
|
|
struct ifmpwreq imr; |
3506 |
|
|
|
3507 |
✗✓ |
102 |
if (wconfig == 0) |
3508 |
|
102 |
return; |
3509 |
|
|
|
3510 |
|
|
bzero(&imr, sizeof(imr)); |
3511 |
|
|
ifr.ifr_data = (caddr_t) &imr; |
3512 |
|
|
if (ioctl(s, SIOCGETMPWCFG, (caddr_t) &ifr) == -1) |
3513 |
|
|
err(1, "SIOCGETMPWCFG"); |
3514 |
|
|
|
3515 |
|
|
if (imrsave.imr_type == 0) { |
3516 |
|
|
if (imr.imr_type == 0) |
3517 |
|
|
imrsave.imr_type = IMR_TYPE_ETHERNET; |
3518 |
|
|
|
3519 |
|
|
imrsave.imr_type = imr.imr_type; |
3520 |
|
|
} |
3521 |
|
|
if (wcwconfig == 0) |
3522 |
|
|
imrsave.imr_flags |= imr.imr_flags; |
3523 |
|
|
|
3524 |
|
|
if (imrsave.imr_lshim.shim_label == 0 || |
3525 |
|
|
imrsave.imr_rshim.shim_label == 0) { |
3526 |
|
|
if (imr.imr_lshim.shim_label == 0 || |
3527 |
|
|
imr.imr_rshim.shim_label == 0) |
3528 |
|
|
errx(1, "mpw local / remote label not specified"); |
3529 |
|
|
|
3530 |
|
|
imrsave.imr_lshim.shim_label = imr.imr_lshim.shim_label; |
3531 |
|
|
imrsave.imr_rshim.shim_label = imr.imr_rshim.shim_label; |
3532 |
|
|
} |
3533 |
|
|
|
3534 |
|
|
sin = (struct sockaddr_in *) &imrsave.imr_nexthop; |
3535 |
|
|
sinn = (struct sockaddr_in *) &imr.imr_nexthop; |
3536 |
|
|
if (sin->sin_addr.s_addr == 0) { |
3537 |
|
|
if (sinn->sin_addr.s_addr == 0) |
3538 |
|
|
errx(1, "mpw neighbor address not specified"); |
3539 |
|
|
|
3540 |
|
|
sin->sin_family = sinn->sin_family; |
3541 |
|
|
sin->sin_addr.s_addr = sinn->sin_addr.s_addr; |
3542 |
|
|
} |
3543 |
|
|
|
3544 |
|
|
ifr.ifr_data = (caddr_t) &imrsave; |
3545 |
|
|
if (ioctl(s, SIOCSETMPWCFG, (caddr_t) &ifr) == -1) |
3546 |
|
|
err(1, "SIOCSETMPWCFG"); |
3547 |
|
|
} |
3548 |
|
|
|
3549 |
|
|
void |
3550 |
|
|
setmpwencap(const char *value, int d) |
3551 |
|
|
{ |
3552 |
|
|
wconfig = 1; |
3553 |
|
|
|
3554 |
|
|
if (strcmp(value, "ethernet") == 0) |
3555 |
|
|
imrsave.imr_type = IMR_TYPE_ETHERNET; |
3556 |
|
|
else if (strcmp(value, "ethernet-tagged") == 0) |
3557 |
|
|
imrsave.imr_type = IMR_TYPE_ETHERNET_TAGGED; |
3558 |
|
|
else |
3559 |
|
|
errx(1, "invalid mpw encapsulation type"); |
3560 |
|
|
} |
3561 |
|
|
|
3562 |
|
|
void |
3563 |
|
|
setmpwlabel(const char *local, const char *remote) |
3564 |
|
|
{ |
3565 |
|
|
const char *errstr; |
3566 |
|
|
|
3567 |
|
|
wconfig = 1; |
3568 |
|
|
|
3569 |
|
|
imrsave.imr_lshim.shim_label = strtonum(local, |
3570 |
|
|
(MPLS_LABEL_RESERVED_MAX + 1), MPLS_LABEL_MAX, &errstr); |
3571 |
|
|
if (errstr != NULL) |
3572 |
|
|
errx(1, "invalid local label: %s", errstr); |
3573 |
|
|
|
3574 |
|
|
imrsave.imr_rshim.shim_label = strtonum(remote, |
3575 |
|
|
(MPLS_LABEL_RESERVED_MAX + 1), MPLS_LABEL_MAX, &errstr); |
3576 |
|
|
if (errstr != NULL) |
3577 |
|
|
errx(1, "invalid remote label: %s", errstr); |
3578 |
|
|
} |
3579 |
|
|
|
3580 |
|
|
void |
3581 |
|
|
setmpwneighbor(const char *value, int d) |
3582 |
|
|
{ |
3583 |
|
|
struct sockaddr_in *sin; |
3584 |
|
|
|
3585 |
|
|
wconfig = 1; |
3586 |
|
|
|
3587 |
|
|
sin = (struct sockaddr_in *) &imrsave.imr_nexthop; |
3588 |
|
|
if (inet_aton(value, &sin->sin_addr) == 0) |
3589 |
|
|
errx(1, "invalid neighbor addresses"); |
3590 |
|
|
|
3591 |
|
|
sin->sin_family = AF_INET; |
3592 |
|
|
} |
3593 |
|
|
|
3594 |
|
|
void |
3595 |
|
|
setmpwcontrolword(const char *value, int d) |
3596 |
|
|
{ |
3597 |
|
|
wconfig = 1; |
3598 |
|
|
wcwconfig = 1; |
3599 |
|
|
|
3600 |
|
|
if (d == 1) |
3601 |
|
|
imrsave.imr_flags |= IMR_FLAG_CONTROLWORD; |
3602 |
|
|
else |
3603 |
|
|
imrsave.imr_flags &= ~IMR_FLAG_CONTROLWORD; |
3604 |
|
|
} |
3605 |
|
|
#endif /* SMALL */ |
3606 |
|
|
|
3607 |
|
|
void |
3608 |
|
|
setvnetid(const char *id, int param) |
3609 |
|
|
{ |
3610 |
|
|
const char *errmsg = NULL; |
3611 |
|
|
uint32_t vnetid; |
3612 |
|
|
|
3613 |
|
|
vnetid = strtonum(id, 0, UINT_MAX, &errmsg); |
3614 |
|
|
if (errmsg) |
3615 |
|
|
errx(1, "vnetid %s: %s", id, errmsg); |
3616 |
|
|
|
3617 |
|
|
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
3618 |
|
|
ifr.ifr_vnetid = vnetid; |
3619 |
|
|
if (ioctl(s, SIOCSVNETID, (caddr_t)&ifr) < 0) |
3620 |
|
|
warn("SIOCSVNETID"); |
3621 |
|
|
} |
3622 |
|
|
|
3623 |
|
|
/* ARGSUSED */ |
3624 |
|
|
void |
3625 |
|
|
delvnetid(const char *ignored, int alsoignored) |
3626 |
|
|
{ |
3627 |
|
|
if (ioctl(s, SIOCDVNETID, &ifr) < 0) |
3628 |
|
|
warn("SIOCDVNETID"); |
3629 |
|
|
} |
3630 |
|
|
|
3631 |
|
|
void |
3632 |
|
|
getvnetid(void) |
3633 |
|
|
{ |
3634 |
|
|
if (strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)) >= |
3635 |
|
|
sizeof(ifr.ifr_name)) |
3636 |
|
|
errx(1, "vnetid: name is too long"); |
3637 |
|
|
|
3638 |
|
|
if (ioctl(s, SIOCGVNETID, &ifr) == -1) { |
3639 |
|
|
if (errno != EADDRNOTAVAIL) |
3640 |
|
|
return; |
3641 |
|
|
|
3642 |
|
|
printf("\tvnetid: none\n"); |
3643 |
|
|
|
3644 |
|
|
return; |
3645 |
|
|
} |
3646 |
|
|
|
3647 |
|
|
printf("\tvnetid: %u\n", ifr.ifr_vnetid); |
3648 |
|
|
} |
3649 |
|
|
|
3650 |
|
|
void |
3651 |
|
|
setifparent(const char *id, int param) |
3652 |
|
|
{ |
3653 |
|
|
struct if_parent ifp; |
3654 |
|
|
|
3655 |
|
|
if (strlcpy(ifp.ifp_name, name, sizeof(ifp.ifp_name)) >= |
3656 |
|
|
sizeof(ifp.ifp_name)) |
3657 |
|
|
errx(1, "parent: name too long"); |
3658 |
|
|
|
3659 |
|
|
if (strlcpy(ifp.ifp_parent, id, sizeof(ifp.ifp_parent)) >= |
3660 |
|
|
sizeof(ifp.ifp_parent)) |
3661 |
|
|
errx(1, "parent: parent too long"); |
3662 |
|
|
|
3663 |
|
|
if (ioctl(s, SIOCSIFPARENT, (caddr_t)&ifp) < 0) |
3664 |
|
|
warn("SIOCSIFPARENT"); |
3665 |
|
|
} |
3666 |
|
|
|
3667 |
|
|
/* ARGSUSED */ |
3668 |
|
|
void |
3669 |
|
|
delifparent(const char *ignored, int alsoignored) |
3670 |
|
|
{ |
3671 |
|
|
if (ioctl(s, SIOCDIFPARENT, &ifr) < 0) |
3672 |
|
|
warn("SIOCDIFPARENT"); |
3673 |
|
|
} |
3674 |
|
|
|
3675 |
|
|
void |
3676 |
|
|
getifparent(void) |
3677 |
|
|
{ |
3678 |
|
|
struct if_parent ifp; |
3679 |
|
|
const char *parent = "none"; |
3680 |
|
|
|
3681 |
|
|
memset(&ifp, 0, sizeof(ifp)); |
3682 |
|
|
if (strlcpy(ifp.ifp_name, name, sizeof(ifp.ifp_name)) >= |
3683 |
|
|
sizeof(ifp.ifp_name)) |
3684 |
|
|
errx(1, "parent: name too long"); |
3685 |
|
|
|
3686 |
|
|
if (ioctl(s, SIOCGIFPARENT, (caddr_t)&ifp) == -1) { |
3687 |
|
|
if (errno != EADDRNOTAVAIL) |
3688 |
|
|
return; |
3689 |
|
|
} else |
3690 |
|
|
parent = ifp.ifp_parent; |
3691 |
|
|
|
3692 |
|
|
printf("\tparent: %s\n", parent); |
3693 |
|
|
} |
3694 |
|
|
|
3695 |
|
|
static int __tag = 0; |
3696 |
|
|
static int __have_tag = 0; |
3697 |
|
|
|
3698 |
|
|
void |
3699 |
|
|
vlan_status(void) |
3700 |
|
|
{ |
3701 |
|
|
struct vlanreq vreq; |
3702 |
|
|
|
3703 |
|
|
bzero((char *)&vreq, sizeof(struct vlanreq)); |
3704 |
|
|
ifr.ifr_data = (caddr_t)&vreq; |
3705 |
|
|
|
3706 |
|
|
if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) |
3707 |
|
|
return; |
3708 |
|
|
|
3709 |
|
|
if (vreq.vlr_tag || (vreq.vlr_parent[0] != '\0')) |
3710 |
|
|
printf("\tvlan: %d parent interface: %s\n", |
3711 |
|
|
vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ? |
3712 |
|
|
"<none>" : vreq.vlr_parent); |
3713 |
|
|
} |
3714 |
|
|
|
3715 |
|
|
/* ARGSUSED */ |
3716 |
|
|
void |
3717 |
|
|
setvlantag(const char *val, int d) |
3718 |
|
|
{ |
3719 |
|
|
u_int16_t tag; |
3720 |
|
|
struct vlanreq vreq; |
3721 |
|
|
const char *errmsg = NULL; |
3722 |
|
|
|
3723 |
|
|
__tag = tag = strtonum(val, 0, 4095, &errmsg); |
3724 |
|
|
if (errmsg) |
3725 |
|
|
errx(1, "vlan tag %s: %s", val, errmsg); |
3726 |
|
|
__have_tag = 1; |
3727 |
|
|
|
3728 |
|
|
bzero((char *)&vreq, sizeof(struct vlanreq)); |
3729 |
|
|
ifr.ifr_data = (caddr_t)&vreq; |
3730 |
|
|
|
3731 |
|
|
if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) |
3732 |
|
|
err(1, "SIOCGETVLAN"); |
3733 |
|
|
|
3734 |
|
|
vreq.vlr_tag = tag; |
3735 |
|
|
|
3736 |
|
|
if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) |
3737 |
|
|
err(1, "SIOCSETVLAN"); |
3738 |
|
|
} |
3739 |
|
|
|
3740 |
|
|
/* ARGSUSED */ |
3741 |
|
|
void |
3742 |
|
|
setvlandev(const char *val, int d) |
3743 |
|
|
{ |
3744 |
|
|
struct vlanreq vreq; |
3745 |
|
|
int tag; |
3746 |
|
|
size_t skip; |
3747 |
|
|
const char *estr; |
3748 |
|
|
|
3749 |
|
|
bzero((char *)&vreq, sizeof(struct vlanreq)); |
3750 |
|
|
ifr.ifr_data = (caddr_t)&vreq; |
3751 |
|
|
|
3752 |
|
|
if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) |
3753 |
|
|
err(1, "SIOCGETVLAN"); |
3754 |
|
|
|
3755 |
|
|
(void) strlcpy(vreq.vlr_parent, val, sizeof(vreq.vlr_parent)); |
3756 |
|
|
|
3757 |
|
|
if (!__have_tag && vreq.vlr_tag == 0) { |
3758 |
|
|
skip = strcspn(ifr.ifr_name, "0123456789"); |
3759 |
|
|
tag = strtonum(ifr.ifr_name + skip, 0, 4095, &estr); |
3760 |
|
|
if (estr != NULL) |
3761 |
|
|
errx(1, "invalid vlan tag and device specification"); |
3762 |
|
|
vreq.vlr_tag = tag; |
3763 |
|
|
} else if (__have_tag) |
3764 |
|
|
vreq.vlr_tag = __tag; |
3765 |
|
|
|
3766 |
|
|
if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) |
3767 |
|
|
err(1, "SIOCSETVLAN"); |
3768 |
|
|
} |
3769 |
|
|
|
3770 |
|
|
/* ARGSUSED */ |
3771 |
|
|
void |
3772 |
|
|
unsetvlandev(const char *val, int d) |
3773 |
|
|
{ |
3774 |
|
|
struct vlanreq vreq; |
3775 |
|
|
|
3776 |
|
|
bzero((char *)&vreq, sizeof(struct vlanreq)); |
3777 |
|
|
ifr.ifr_data = (caddr_t)&vreq; |
3778 |
|
|
|
3779 |
|
|
if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) |
3780 |
|
|
err(1, "SIOCGETVLAN"); |
3781 |
|
|
|
3782 |
|
|
bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent)); |
3783 |
|
|
vreq.vlr_tag = 0; |
3784 |
|
|
|
3785 |
|
|
if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) |
3786 |
|
|
err(1, "SIOCSETVLAN"); |
3787 |
|
|
} |
3788 |
|
|
|
3789 |
|
|
void |
3790 |
|
|
settrunkport(const char *val, int d) |
3791 |
|
|
{ |
3792 |
|
|
struct trunk_reqport rp; |
3793 |
|
|
|
3794 |
|
|
bzero(&rp, sizeof(rp)); |
3795 |
|
|
strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname)); |
3796 |
|
|
strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname)); |
3797 |
|
|
|
3798 |
|
|
if (ioctl(s, SIOCSTRUNKPORT, &rp)) |
3799 |
|
|
err(1, "SIOCSTRUNKPORT"); |
3800 |
|
|
} |
3801 |
|
|
|
3802 |
|
|
void |
3803 |
|
|
unsettrunkport(const char *val, int d) |
3804 |
|
|
{ |
3805 |
|
|
struct trunk_reqport rp; |
3806 |
|
|
|
3807 |
|
|
bzero(&rp, sizeof(rp)); |
3808 |
|
|
strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname)); |
3809 |
|
|
strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname)); |
3810 |
|
|
|
3811 |
|
|
if (ioctl(s, SIOCSTRUNKDELPORT, &rp)) |
3812 |
|
|
err(1, "SIOCSTRUNKDELPORT"); |
3813 |
|
|
} |
3814 |
|
|
|
3815 |
|
|
void |
3816 |
|
|
settrunkproto(const char *val, int d) |
3817 |
|
|
{ |
3818 |
|
|
struct trunk_protos tpr[] = TRUNK_PROTOS; |
3819 |
|
|
struct trunk_reqall ra; |
3820 |
|
|
int i; |
3821 |
|
|
|
3822 |
|
|
bzero(&ra, sizeof(ra)); |
3823 |
|
|
ra.ra_proto = TRUNK_PROTO_MAX; |
3824 |
|
|
|
3825 |
|
|
for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) { |
3826 |
|
|
if (strcmp(val, tpr[i].tpr_name) == 0) { |
3827 |
|
|
ra.ra_proto = tpr[i].tpr_proto; |
3828 |
|
|
break; |
3829 |
|
|
} |
3830 |
|
|
} |
3831 |
|
|
if (ra.ra_proto == TRUNK_PROTO_MAX) |
3832 |
|
|
errx(1, "Invalid trunk protocol: %s", val); |
3833 |
|
|
|
3834 |
|
|
strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname)); |
3835 |
|
|
if (ioctl(s, SIOCSTRUNK, &ra) != 0) |
3836 |
|
|
err(1, "SIOCSTRUNK"); |
3837 |
|
|
} |
3838 |
|
|
|
3839 |
|
|
void |
3840 |
|
|
trunk_status(void) |
3841 |
|
|
{ |
3842 |
|
|
struct trunk_protos tpr[] = TRUNK_PROTOS; |
3843 |
|
|
struct trunk_reqport rp, rpbuf[TRUNK_MAX_PORTS]; |
3844 |
|
|
struct trunk_reqall ra; |
3845 |
|
|
struct lacp_opreq *lp; |
3846 |
|
|
const char *proto = "<unknown>"; |
3847 |
|
|
int i, isport = 0; |
3848 |
|
|
|
3849 |
|
|
bzero(&rp, sizeof(rp)); |
3850 |
|
|
bzero(&ra, sizeof(ra)); |
3851 |
|
|
|
3852 |
|
|
strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname)); |
3853 |
|
|
strlcpy(rp.rp_portname, name, sizeof(rp.rp_portname)); |
3854 |
|
|
|
3855 |
|
|
if (ioctl(s, SIOCGTRUNKPORT, &rp) == 0) |
3856 |
|
|
isport = 1; |
3857 |
|
|
|
3858 |
|
|
strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname)); |
3859 |
|
|
ra.ra_size = sizeof(rpbuf); |
3860 |
|
|
ra.ra_port = rpbuf; |
3861 |
|
|
|
3862 |
|
|
if (ioctl(s, SIOCGTRUNK, &ra) == 0) { |
3863 |
|
|
lp = (struct lacp_opreq *)&ra.ra_lacpreq; |
3864 |
|
|
|
3865 |
|
|
for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) { |
3866 |
|
|
if (ra.ra_proto == tpr[i].tpr_proto) { |
3867 |
|
|
proto = tpr[i].tpr_name; |
3868 |
|
|
break; |
3869 |
|
|
} |
3870 |
|
|
} |
3871 |
|
|
|
3872 |
|
|
printf("\ttrunk: trunkproto %s", proto); |
3873 |
|
|
if (isport) |
3874 |
|
|
printf(" trunkdev %s", rp.rp_ifname); |
3875 |
|
|
putchar('\n'); |
3876 |
|
|
if (ra.ra_proto == TRUNK_PROTO_LACP) { |
3877 |
|
|
char *act_mac = strdup( |
3878 |
|
|
ether_ntoa((struct ether_addr*)lp->actor_mac)); |
3879 |
|
|
if (act_mac == NULL) |
3880 |
|
|
err(1, "strdup"); |
3881 |
|
|
printf("\ttrunk id: [(%04X,%s,%04X,%04X,%04X),\n" |
3882 |
|
|
"\t\t (%04X,%s,%04X,%04X,%04X)]\n", |
3883 |
|
|
lp->actor_prio, act_mac, |
3884 |
|
|
lp->actor_key, lp->actor_portprio, lp->actor_portno, |
3885 |
|
|
lp->partner_prio, |
3886 |
|
|
ether_ntoa((struct ether_addr*)lp->partner_mac), |
3887 |
|
|
lp->partner_key, lp->partner_portprio, |
3888 |
|
|
lp->partner_portno); |
3889 |
|
|
free(act_mac); |
3890 |
|
|
} |
3891 |
|
|
|
3892 |
|
|
for (i = 0; i < ra.ra_ports; i++) { |
3893 |
|
|
printf("\t\ttrunkport %s ", rpbuf[i].rp_portname); |
3894 |
|
|
printb_status(rpbuf[i].rp_flags, TRUNK_PORT_BITS); |
3895 |
|
|
putchar('\n'); |
3896 |
|
|
} |
3897 |
|
|
|
3898 |
|
|
if (showmediaflag) { |
3899 |
|
|
printf("\tsupported trunk protocols:\n"); |
3900 |
|
|
for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) |
3901 |
|
|
printf("\t\ttrunkproto %s\n", tpr[i].tpr_name); |
3902 |
|
|
} |
3903 |
|
|
} else if (isport) |
3904 |
|
|
printf("\ttrunk: trunkdev %s\n", rp.rp_ifname); |
3905 |
|
|
} |
3906 |
|
|
|
3907 |
|
|
#ifndef SMALL |
3908 |
|
|
static const char *carp_states[] = { CARP_STATES }; |
3909 |
|
|
static const char *carp_bal_modes[] = { CARP_BAL_MODES }; |
3910 |
|
|
|
3911 |
|
|
void |
3912 |
|
|
carp_status(void) |
3913 |
|
|
{ |
3914 |
|
|
const char *state, *balmode; |
3915 |
|
|
struct carpreq carpr; |
3916 |
|
|
char peer[32]; |
3917 |
|
|
int i; |
3918 |
|
|
|
3919 |
|
|
memset((char *)&carpr, 0, sizeof(struct carpreq)); |
3920 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
3921 |
|
|
|
3922 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
3923 |
|
|
return; |
3924 |
|
|
|
3925 |
|
|
if (carpr.carpr_vhids[0] == 0) |
3926 |
|
|
return; |
3927 |
|
|
|
3928 |
|
|
if (carpr.carpr_balancing > CARP_BAL_MAXID) |
3929 |
|
|
balmode = "<UNKNOWN>"; |
3930 |
|
|
else |
3931 |
|
|
balmode = carp_bal_modes[carpr.carpr_balancing]; |
3932 |
|
|
|
3933 |
|
|
if (carpr.carpr_peer.s_addr != htonl(INADDR_CARP_GROUP)) |
3934 |
|
|
snprintf(peer, sizeof(peer), |
3935 |
|
|
" carppeer %s", inet_ntoa(carpr.carpr_peer)); |
3936 |
|
|
else |
3937 |
|
|
peer[0] = '\0'; |
3938 |
|
|
|
3939 |
|
|
for (i = 0; carpr.carpr_vhids[i]; i++) { |
3940 |
|
|
if (carpr.carpr_states[i] > CARP_MAXSTATE) |
3941 |
|
|
state = "<UNKNOWN>"; |
3942 |
|
|
else |
3943 |
|
|
state = carp_states[carpr.carpr_states[i]]; |
3944 |
|
|
if (carpr.carpr_vhids[1] == 0) { |
3945 |
|
|
printf("\tcarp: %s carpdev %s vhid %u advbase %d " |
3946 |
|
|
"advskew %u%s\n", state, |
3947 |
|
|
carpr.carpr_carpdev[0] != '\0' ? |
3948 |
|
|
carpr.carpr_carpdev : "none", carpr.carpr_vhids[0], |
3949 |
|
|
carpr.carpr_advbase, carpr.carpr_advskews[0], |
3950 |
|
|
peer); |
3951 |
|
|
} else { |
3952 |
|
|
if (i == 0) { |
3953 |
|
|
printf("\tcarp: carpdev %s advbase %d" |
3954 |
|
|
" balancing %s%s\n", |
3955 |
|
|
carpr.carpr_carpdev[0] != '\0' ? |
3956 |
|
|
carpr.carpr_carpdev : "none", |
3957 |
|
|
carpr.carpr_advbase, balmode, peer); |
3958 |
|
|
} |
3959 |
|
|
printf("\t\tstate %s vhid %u advskew %u\n", state, |
3960 |
|
|
carpr.carpr_vhids[i], carpr.carpr_advskews[i]); |
3961 |
|
|
} |
3962 |
|
|
} |
3963 |
|
|
} |
3964 |
|
|
|
3965 |
|
|
/* ARGSUSED */ |
3966 |
|
|
void |
3967 |
|
|
setcarp_passwd(const char *val, int d) |
3968 |
|
|
{ |
3969 |
|
|
struct carpreq carpr; |
3970 |
|
|
|
3971 |
|
|
bzero(&carpr, sizeof(struct carpreq)); |
3972 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
3973 |
|
|
|
3974 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
3975 |
|
|
err(1, "SIOCGVH"); |
3976 |
|
|
|
3977 |
|
|
bzero(carpr.carpr_key, CARP_KEY_LEN); |
3978 |
|
|
strlcpy((char *)carpr.carpr_key, val, CARP_KEY_LEN); |
3979 |
|
|
|
3980 |
|
|
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
3981 |
|
|
err(1, "SIOCSVH"); |
3982 |
|
|
} |
3983 |
|
|
|
3984 |
|
|
/* ARGSUSED */ |
3985 |
|
|
void |
3986 |
|
|
setcarp_vhid(const char *val, int d) |
3987 |
|
|
{ |
3988 |
|
|
const char *errmsg = NULL; |
3989 |
|
|
struct carpreq carpr; |
3990 |
|
|
int vhid; |
3991 |
|
|
|
3992 |
|
|
vhid = strtonum(val, 1, 255, &errmsg); |
3993 |
|
|
if (errmsg) |
3994 |
|
|
errx(1, "vhid %s: %s", val, errmsg); |
3995 |
|
|
|
3996 |
|
|
bzero(&carpr, sizeof(struct carpreq)); |
3997 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
3998 |
|
|
|
3999 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
4000 |
|
|
err(1, "SIOCGVH"); |
4001 |
|
|
|
4002 |
|
|
carpr.carpr_vhids[0] = vhid; |
4003 |
|
|
carpr.carpr_vhids[1] = 0; |
4004 |
|
|
|
4005 |
|
|
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
4006 |
|
|
err(1, "SIOCSVH"); |
4007 |
|
|
} |
4008 |
|
|
|
4009 |
|
|
/* ARGSUSED */ |
4010 |
|
|
void |
4011 |
|
|
setcarp_advskew(const char *val, int d) |
4012 |
|
|
{ |
4013 |
|
|
const char *errmsg = NULL; |
4014 |
|
|
struct carpreq carpr; |
4015 |
|
|
int advskew; |
4016 |
|
|
|
4017 |
|
|
advskew = strtonum(val, 0, 254, &errmsg); |
4018 |
|
|
if (errmsg) |
4019 |
|
|
errx(1, "advskew %s: %s", val, errmsg); |
4020 |
|
|
|
4021 |
|
|
bzero(&carpr, sizeof(struct carpreq)); |
4022 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
4023 |
|
|
|
4024 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
4025 |
|
|
err(1, "SIOCGVH"); |
4026 |
|
|
|
4027 |
|
|
carpr.carpr_advskews[0] = advskew; |
4028 |
|
|
|
4029 |
|
|
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
4030 |
|
|
err(1, "SIOCSVH"); |
4031 |
|
|
} |
4032 |
|
|
|
4033 |
|
|
/* ARGSUSED */ |
4034 |
|
|
void |
4035 |
|
|
setcarp_advbase(const char *val, int d) |
4036 |
|
|
{ |
4037 |
|
|
const char *errmsg = NULL; |
4038 |
|
|
struct carpreq carpr; |
4039 |
|
|
int advbase; |
4040 |
|
|
|
4041 |
|
|
advbase = strtonum(val, 0, 254, &errmsg); |
4042 |
|
|
if (errmsg) |
4043 |
|
|
errx(1, "advbase %s: %s", val, errmsg); |
4044 |
|
|
|
4045 |
|
|
bzero(&carpr, sizeof(struct carpreq)); |
4046 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
4047 |
|
|
|
4048 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
4049 |
|
|
err(1, "SIOCGVH"); |
4050 |
|
|
|
4051 |
|
|
carpr.carpr_advbase = advbase; |
4052 |
|
|
|
4053 |
|
|
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
4054 |
|
|
err(1, "SIOCSVH"); |
4055 |
|
|
} |
4056 |
|
|
|
4057 |
|
|
/* ARGSUSED */ |
4058 |
|
|
void |
4059 |
|
|
setcarppeer(const char *val, int d) |
4060 |
|
|
{ |
4061 |
|
|
struct carpreq carpr; |
4062 |
|
|
struct addrinfo hints, *peerres; |
4063 |
|
|
int ecode; |
4064 |
|
|
|
4065 |
|
|
bzero(&carpr, sizeof(struct carpreq)); |
4066 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
4067 |
|
|
|
4068 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
4069 |
|
|
err(1, "SIOCGVH"); |
4070 |
|
|
|
4071 |
|
|
bzero(&hints, sizeof(hints)); |
4072 |
|
|
hints.ai_family = AF_INET; |
4073 |
|
|
hints.ai_socktype = SOCK_DGRAM; |
4074 |
|
|
|
4075 |
|
|
if ((ecode = getaddrinfo(val, NULL, &hints, &peerres)) != 0) |
4076 |
|
|
errx(1, "error in parsing address string: %s", |
4077 |
|
|
gai_strerror(ecode)); |
4078 |
|
|
|
4079 |
|
|
if (peerres->ai_addr->sa_family != AF_INET) |
4080 |
|
|
errx(1, "only IPv4 addresses supported for the carppeer"); |
4081 |
|
|
|
4082 |
|
|
carpr.carpr_peer.s_addr = ((struct sockaddr_in *) |
4083 |
|
|
peerres->ai_addr)->sin_addr.s_addr; |
4084 |
|
|
|
4085 |
|
|
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
4086 |
|
|
err(1, "SIOCSVH"); |
4087 |
|
|
|
4088 |
|
|
freeaddrinfo(peerres); |
4089 |
|
|
} |
4090 |
|
|
|
4091 |
|
|
void |
4092 |
|
|
unsetcarppeer(const char *val, int d) |
4093 |
|
|
{ |
4094 |
|
|
struct carpreq carpr; |
4095 |
|
|
|
4096 |
|
|
bzero(&carpr, sizeof(struct carpreq)); |
4097 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
4098 |
|
|
|
4099 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
4100 |
|
|
err(1, "SIOCGVH"); |
4101 |
|
|
|
4102 |
|
|
bzero(&carpr.carpr_peer, sizeof(carpr.carpr_peer)); |
4103 |
|
|
|
4104 |
|
|
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
4105 |
|
|
err(1, "SIOCSVH"); |
4106 |
|
|
} |
4107 |
|
|
|
4108 |
|
|
/* ARGSUSED */ |
4109 |
|
|
void |
4110 |
|
|
setcarp_state(const char *val, int d) |
4111 |
|
|
{ |
4112 |
|
|
struct carpreq carpr; |
4113 |
|
|
int i; |
4114 |
|
|
|
4115 |
|
|
bzero(&carpr, sizeof(struct carpreq)); |
4116 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
4117 |
|
|
|
4118 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
4119 |
|
|
err(1, "SIOCGVH"); |
4120 |
|
|
|
4121 |
|
|
for (i = 0; i <= CARP_MAXSTATE; i++) { |
4122 |
|
|
if (!strcasecmp(val, carp_states[i])) { |
4123 |
|
|
carpr.carpr_state = i; |
4124 |
|
|
break; |
4125 |
|
|
} |
4126 |
|
|
} |
4127 |
|
|
|
4128 |
|
|
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
4129 |
|
|
err(1, "SIOCSVH"); |
4130 |
|
|
} |
4131 |
|
|
|
4132 |
|
|
/* ARGSUSED */ |
4133 |
|
|
void |
4134 |
|
|
setcarpdev(const char *val, int d) |
4135 |
|
|
{ |
4136 |
|
|
struct carpreq carpr; |
4137 |
|
|
|
4138 |
|
|
bzero(&carpr, sizeof(struct carpreq)); |
4139 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
4140 |
|
|
|
4141 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
4142 |
|
|
err(1, "SIOCGVH"); |
4143 |
|
|
|
4144 |
|
|
strlcpy(carpr.carpr_carpdev, val, sizeof(carpr.carpr_carpdev)); |
4145 |
|
|
|
4146 |
|
|
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
4147 |
|
|
err(1, "SIOCSVH"); |
4148 |
|
|
} |
4149 |
|
|
|
4150 |
|
|
void |
4151 |
|
|
setcarp_nodes(const char *val, int d) |
4152 |
|
|
{ |
4153 |
|
|
char *optlist, *str; |
4154 |
|
|
int i; |
4155 |
|
|
struct carpreq carpr; |
4156 |
|
|
|
4157 |
|
|
bzero(&carpr, sizeof(struct carpreq)); |
4158 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
4159 |
|
|
|
4160 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
4161 |
|
|
err(1, "SIOCGVH"); |
4162 |
|
|
|
4163 |
|
|
bzero(carpr.carpr_vhids, sizeof(carpr.carpr_vhids)); |
4164 |
|
|
bzero(carpr.carpr_advskews, sizeof(carpr.carpr_advskews)); |
4165 |
|
|
|
4166 |
|
|
optlist = strdup(val); |
4167 |
|
|
if (optlist == NULL) |
4168 |
|
|
err(1, "strdup"); |
4169 |
|
|
|
4170 |
|
|
str = strtok(optlist, ","); |
4171 |
|
|
for (i = 0; str != NULL; i++) { |
4172 |
|
|
u_int vhid, advskew; |
4173 |
|
|
|
4174 |
|
|
if (i >= CARP_MAXNODES) |
4175 |
|
|
errx(1, "too many carp nodes"); |
4176 |
|
|
if (sscanf(str, "%u:%u", &vhid, &advskew) != 2) { |
4177 |
|
|
errx(1, "non parsable arg: %s", str); |
4178 |
|
|
} |
4179 |
|
|
if (vhid > 255) |
4180 |
|
|
errx(1, "vhid %u: value too large", vhid); |
4181 |
|
|
if (advskew >= 255) |
4182 |
|
|
errx(1, "advskew %u: value too large", advskew); |
4183 |
|
|
|
4184 |
|
|
carpr.carpr_vhids[i] = vhid; |
4185 |
|
|
carpr.carpr_advskews[i] = advskew; |
4186 |
|
|
str = strtok(NULL, ","); |
4187 |
|
|
} |
4188 |
|
|
free(optlist); |
4189 |
|
|
|
4190 |
|
|
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
4191 |
|
|
err(1, "SIOCSVH"); |
4192 |
|
|
} |
4193 |
|
|
|
4194 |
|
|
void |
4195 |
|
|
setcarp_balancing(const char *val, int d) |
4196 |
|
|
{ |
4197 |
|
|
int i; |
4198 |
|
|
struct carpreq carpr; |
4199 |
|
|
|
4200 |
|
|
bzero(&carpr, sizeof(struct carpreq)); |
4201 |
|
|
ifr.ifr_data = (caddr_t)&carpr; |
4202 |
|
|
|
4203 |
|
|
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
4204 |
|
|
err(1, "SIOCGVH"); |
4205 |
|
|
|
4206 |
|
|
for (i = 0; i <= CARP_BAL_MAXID; i++) |
4207 |
|
|
if (!strcasecmp(val, carp_bal_modes[i])) |
4208 |
|
|
break; |
4209 |
|
|
|
4210 |
|
|
if (i > CARP_BAL_MAXID) |
4211 |
|
|
errx(1, "balancing %s: unknown mode", val); |
4212 |
|
|
|
4213 |
|
|
carpr.carpr_balancing = i; |
4214 |
|
|
|
4215 |
|
|
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
4216 |
|
|
err(1, "SIOCSVH"); |
4217 |
|
|
} |
4218 |
|
|
|
4219 |
|
|
void |
4220 |
|
|
setpfsync_syncdev(const char *val, int d) |
4221 |
|
|
{ |
4222 |
|
|
struct pfsyncreq preq; |
4223 |
|
|
|
4224 |
|
|
bzero(&preq, sizeof(struct pfsyncreq)); |
4225 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4226 |
|
|
|
4227 |
|
|
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) |
4228 |
|
|
err(1, "SIOCGETPFSYNC"); |
4229 |
|
|
|
4230 |
|
|
strlcpy(preq.pfsyncr_syncdev, val, sizeof(preq.pfsyncr_syncdev)); |
4231 |
|
|
|
4232 |
|
|
if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) |
4233 |
|
|
err(1, "SIOCSETPFSYNC"); |
4234 |
|
|
} |
4235 |
|
|
|
4236 |
|
|
/* ARGSUSED */ |
4237 |
|
|
void |
4238 |
|
|
unsetpfsync_syncdev(const char *val, int d) |
4239 |
|
|
{ |
4240 |
|
|
struct pfsyncreq preq; |
4241 |
|
|
|
4242 |
|
|
bzero(&preq, sizeof(struct pfsyncreq)); |
4243 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4244 |
|
|
|
4245 |
|
|
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) |
4246 |
|
|
err(1, "SIOCGETPFSYNC"); |
4247 |
|
|
|
4248 |
|
|
bzero(&preq.pfsyncr_syncdev, sizeof(preq.pfsyncr_syncdev)); |
4249 |
|
|
|
4250 |
|
|
if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) |
4251 |
|
|
err(1, "SIOCSETPFSYNC"); |
4252 |
|
|
} |
4253 |
|
|
|
4254 |
|
|
/* ARGSUSED */ |
4255 |
|
|
void |
4256 |
|
|
setpfsync_syncpeer(const char *val, int d) |
4257 |
|
|
{ |
4258 |
|
|
struct pfsyncreq preq; |
4259 |
|
|
struct addrinfo hints, *peerres; |
4260 |
|
|
int ecode; |
4261 |
|
|
|
4262 |
|
|
bzero(&preq, sizeof(struct pfsyncreq)); |
4263 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4264 |
|
|
|
4265 |
|
|
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) |
4266 |
|
|
err(1, "SIOCGETPFSYNC"); |
4267 |
|
|
|
4268 |
|
|
memset(&hints, 0, sizeof(hints)); |
4269 |
|
|
hints.ai_family = AF_INET; |
4270 |
|
|
hints.ai_socktype = SOCK_DGRAM; /*dummy*/ |
4271 |
|
|
|
4272 |
|
|
if ((ecode = getaddrinfo(val, NULL, &hints, &peerres)) != 0) |
4273 |
|
|
errx(1, "error in parsing address string: %s", |
4274 |
|
|
gai_strerror(ecode)); |
4275 |
|
|
|
4276 |
|
|
if (peerres->ai_addr->sa_family != AF_INET) |
4277 |
|
|
errx(1, "only IPv4 addresses supported for the syncpeer"); |
4278 |
|
|
|
4279 |
|
|
preq.pfsyncr_syncpeer.s_addr = ((struct sockaddr_in *) |
4280 |
|
|
peerres->ai_addr)->sin_addr.s_addr; |
4281 |
|
|
|
4282 |
|
|
if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) |
4283 |
|
|
err(1, "SIOCSETPFSYNC"); |
4284 |
|
|
|
4285 |
|
|
freeaddrinfo(peerres); |
4286 |
|
|
} |
4287 |
|
|
|
4288 |
|
|
/* ARGSUSED */ |
4289 |
|
|
void |
4290 |
|
|
unsetpfsync_syncpeer(const char *val, int d) |
4291 |
|
|
{ |
4292 |
|
|
struct pfsyncreq preq; |
4293 |
|
|
|
4294 |
|
|
bzero(&preq, sizeof(struct pfsyncreq)); |
4295 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4296 |
|
|
|
4297 |
|
|
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) |
4298 |
|
|
err(1, "SIOCGETPFSYNC"); |
4299 |
|
|
|
4300 |
|
|
preq.pfsyncr_syncpeer.s_addr = 0; |
4301 |
|
|
|
4302 |
|
|
if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) |
4303 |
|
|
err(1, "SIOCSETPFSYNC"); |
4304 |
|
|
} |
4305 |
|
|
|
4306 |
|
|
/* ARGSUSED */ |
4307 |
|
|
void |
4308 |
|
|
setpfsync_maxupd(const char *val, int d) |
4309 |
|
|
{ |
4310 |
|
|
const char *errmsg = NULL; |
4311 |
|
|
struct pfsyncreq preq; |
4312 |
|
|
int maxupdates; |
4313 |
|
|
|
4314 |
|
|
maxupdates = strtonum(val, 0, 255, &errmsg); |
4315 |
|
|
if (errmsg) |
4316 |
|
|
errx(1, "maxupd %s: %s", val, errmsg); |
4317 |
|
|
|
4318 |
|
|
bzero(&preq, sizeof(struct pfsyncreq)); |
4319 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4320 |
|
|
|
4321 |
|
|
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) |
4322 |
|
|
err(1, "SIOCGETPFSYNC"); |
4323 |
|
|
|
4324 |
|
|
preq.pfsyncr_maxupdates = maxupdates; |
4325 |
|
|
|
4326 |
|
|
if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) |
4327 |
|
|
err(1, "SIOCSETPFSYNC"); |
4328 |
|
|
} |
4329 |
|
|
|
4330 |
|
|
void |
4331 |
|
|
setpfsync_defer(const char *val, int d) |
4332 |
|
|
{ |
4333 |
|
|
struct pfsyncreq preq; |
4334 |
|
|
|
4335 |
|
|
bzero(&preq, sizeof(struct pfsyncreq)); |
4336 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4337 |
|
|
|
4338 |
|
|
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) |
4339 |
|
|
err(1, "SIOCGETPFSYNC"); |
4340 |
|
|
|
4341 |
|
|
preq.pfsyncr_defer = d; |
4342 |
|
|
if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) |
4343 |
|
|
err(1, "SIOCSETPFSYNC"); |
4344 |
|
|
} |
4345 |
|
|
|
4346 |
|
|
void |
4347 |
|
|
pfsync_status(void) |
4348 |
|
|
{ |
4349 |
|
|
struct pfsyncreq preq; |
4350 |
|
|
|
4351 |
|
|
bzero(&preq, sizeof(struct pfsyncreq)); |
4352 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4353 |
|
|
|
4354 |
|
|
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) |
4355 |
|
|
return; |
4356 |
|
|
|
4357 |
|
|
if (preq.pfsyncr_syncdev[0] != '\0') { |
4358 |
|
|
printf("\tpfsync: syncdev: %s ", preq.pfsyncr_syncdev); |
4359 |
|
|
if (preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)) |
4360 |
|
|
printf("syncpeer: %s ", |
4361 |
|
|
inet_ntoa(preq.pfsyncr_syncpeer)); |
4362 |
|
|
printf("maxupd: %d ", preq.pfsyncr_maxupdates); |
4363 |
|
|
printf("defer: %s\n", preq.pfsyncr_defer ? "on" : "off"); |
4364 |
|
|
} |
4365 |
|
|
} |
4366 |
|
|
|
4367 |
|
|
void |
4368 |
|
|
pflow_status(void) |
4369 |
|
|
{ |
4370 |
|
|
struct pflowreq preq; |
4371 |
|
|
struct sockaddr_in *sin; |
4372 |
|
|
struct sockaddr_in6 *sin6; |
4373 |
|
|
int error; |
4374 |
|
|
char buf[INET6_ADDRSTRLEN]; |
4375 |
|
|
|
4376 |
|
|
bzero(&preq, sizeof(struct pflowreq)); |
4377 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4378 |
|
|
|
4379 |
|
|
if (ioctl(s, SIOCGETPFLOW, (caddr_t)&ifr) == -1) |
4380 |
|
|
return; |
4381 |
|
|
|
4382 |
|
|
if (preq.flowsrc.ss_family == AF_INET || preq.flowsrc.ss_family == |
4383 |
|
|
AF_INET6) { |
4384 |
|
|
error = getnameinfo((struct sockaddr*)&preq.flowsrc, |
4385 |
|
|
preq.flowsrc.ss_len, buf, sizeof(buf), NULL, 0, |
4386 |
|
|
NI_NUMERICHOST); |
4387 |
|
|
if (error) |
4388 |
|
|
err(1, "sender: %s", gai_strerror(error)); |
4389 |
|
|
} |
4390 |
|
|
|
4391 |
|
|
printf("\tpflow: "); |
4392 |
|
|
switch (preq.flowsrc.ss_family) { |
4393 |
|
|
case AF_INET: |
4394 |
|
|
sin = (struct sockaddr_in*) &preq.flowsrc; |
4395 |
|
|
if (sin->sin_addr.s_addr != INADDR_ANY) { |
4396 |
|
|
printf("sender: %s", buf); |
4397 |
|
|
if (sin->sin_port != 0) |
4398 |
|
|
printf(":%u", ntohs(sin->sin_port)); |
4399 |
|
|
printf(" "); |
4400 |
|
|
} |
4401 |
|
|
break; |
4402 |
|
|
case AF_INET6: |
4403 |
|
|
sin6 = (struct sockaddr_in6*) &preq.flowsrc; |
4404 |
|
|
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { |
4405 |
|
|
printf("sender: [%s]", buf); |
4406 |
|
|
if (sin6->sin6_port != 0) |
4407 |
|
|
printf(":%u", ntohs(sin6->sin6_port)); |
4408 |
|
|
printf(" "); |
4409 |
|
|
} |
4410 |
|
|
default: |
4411 |
|
|
break; |
4412 |
|
|
} |
4413 |
|
|
if (preq.flowdst.ss_family == AF_INET || preq.flowdst.ss_family == |
4414 |
|
|
AF_INET6) { |
4415 |
|
|
error = getnameinfo((struct sockaddr*)&preq.flowdst, |
4416 |
|
|
preq.flowdst.ss_len, buf, sizeof(buf), NULL, 0, |
4417 |
|
|
NI_NUMERICHOST); |
4418 |
|
|
if (error) |
4419 |
|
|
err(1, "receiver: %s", gai_strerror(error)); |
4420 |
|
|
} |
4421 |
|
|
switch (preq.flowdst.ss_family) { |
4422 |
|
|
case AF_INET: |
4423 |
|
|
sin = (struct sockaddr_in*)&preq.flowdst; |
4424 |
|
|
printf("receiver: %s:", sin->sin_addr.s_addr != INADDR_ANY ? |
4425 |
|
|
buf : "INVALID"); |
4426 |
|
|
if (sin->sin_port == 0) |
4427 |
|
|
printf("%s ", "INVALID"); |
4428 |
|
|
else |
4429 |
|
|
printf("%u ", ntohs(sin->sin_port)); |
4430 |
|
|
break; |
4431 |
|
|
case AF_INET6: |
4432 |
|
|
sin6 = (struct sockaddr_in6*) &preq.flowdst; |
4433 |
|
|
printf("receiver: [%s]:", |
4434 |
|
|
!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ? buf : |
4435 |
|
|
"INVALID"); |
4436 |
|
|
if (sin6->sin6_port == 0) |
4437 |
|
|
printf("%s ", "INVALID"); |
4438 |
|
|
else |
4439 |
|
|
printf("%u ", ntohs(sin6->sin6_port)); |
4440 |
|
|
break; |
4441 |
|
|
default: |
4442 |
|
|
printf("receiver: INVALID:INVALID "); |
4443 |
|
|
break; |
4444 |
|
|
} |
4445 |
|
|
printf("version: %d\n", preq.version); |
4446 |
|
|
} |
4447 |
|
|
|
4448 |
|
|
void |
4449 |
|
|
pflow_addr(const char *val, struct sockaddr_storage *ss) { |
4450 |
|
|
struct addrinfo hints, *res0; |
4451 |
|
|
int error, flag; |
4452 |
|
|
char *cp, *ip, *port, buf[HOST_NAME_MAX+1 + sizeof (":65535")]; |
4453 |
|
|
|
4454 |
|
|
if (strlcpy(buf, val, sizeof(buf)) >= sizeof(buf)) |
4455 |
|
|
errx(1, "%s bad value", val); |
4456 |
|
|
|
4457 |
|
|
port = NULL; |
4458 |
|
|
cp = buf; |
4459 |
|
|
if (*cp == '[') |
4460 |
|
|
flag = 1; |
4461 |
|
|
else |
4462 |
|
|
flag = 0; |
4463 |
|
|
|
4464 |
|
|
for(; *cp; ++cp) { |
4465 |
|
|
if (*cp == ']' && *(cp + 1) == ':' && flag) { |
4466 |
|
|
*cp = '\0'; |
4467 |
|
|
*(cp + 1) = '\0'; |
4468 |
|
|
port = cp + 2; |
4469 |
|
|
break; |
4470 |
|
|
} |
4471 |
|
|
if (*cp == ']' && *(cp + 1) == '\0' && flag) { |
4472 |
|
|
*cp = '\0'; |
4473 |
|
|
port = NULL; |
4474 |
|
|
break; |
4475 |
|
|
} |
4476 |
|
|
if (*cp == ':' && !flag) { |
4477 |
|
|
*cp = '\0'; |
4478 |
|
|
port = cp + 1; |
4479 |
|
|
break; |
4480 |
|
|
} |
4481 |
|
|
} |
4482 |
|
|
|
4483 |
|
|
ip = buf; |
4484 |
|
|
if (flag) |
4485 |
|
|
ip++; |
4486 |
|
|
|
4487 |
|
|
bzero(&hints, sizeof(hints)); |
4488 |
|
|
hints.ai_family = AF_UNSPEC; |
4489 |
|
|
hints.ai_socktype = SOCK_DGRAM; /*dummy*/ |
4490 |
|
|
|
4491 |
|
|
if ((error = getaddrinfo(ip, port, &hints, &res0)) != 0) |
4492 |
|
|
errx(1, "error in parsing address string: %s", |
4493 |
|
|
gai_strerror(error)); |
4494 |
|
|
|
4495 |
|
|
memcpy(ss, res0->ai_addr, res0->ai_addr->sa_len); |
4496 |
|
|
freeaddrinfo(res0); |
4497 |
|
|
} |
4498 |
|
|
|
4499 |
|
|
void |
4500 |
|
|
setpflow_sender(const char *val, int d) |
4501 |
|
|
{ |
4502 |
|
|
struct pflowreq preq; |
4503 |
|
|
|
4504 |
|
|
bzero(&preq, sizeof(struct pflowreq)); |
4505 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4506 |
|
|
preq.addrmask |= PFLOW_MASK_SRCIP; |
4507 |
|
|
pflow_addr(val, &preq.flowsrc); |
4508 |
|
|
|
4509 |
|
|
if (ioctl(s, SIOCSETPFLOW, (caddr_t)&ifr) == -1) |
4510 |
|
|
err(1, "SIOCSETPFLOW"); |
4511 |
|
|
} |
4512 |
|
|
|
4513 |
|
|
void |
4514 |
|
|
unsetpflow_sender(const char *val, int d) |
4515 |
|
|
{ |
4516 |
|
|
struct pflowreq preq; |
4517 |
|
|
|
4518 |
|
|
bzero(&preq, sizeof(struct pflowreq)); |
4519 |
|
|
preq.addrmask |= PFLOW_MASK_SRCIP; |
4520 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4521 |
|
|
if (ioctl(s, SIOCSETPFLOW, (caddr_t)&ifr) == -1) |
4522 |
|
|
err(1, "SIOCSETPFLOW"); |
4523 |
|
|
} |
4524 |
|
|
|
4525 |
|
|
void |
4526 |
|
|
setpflow_receiver(const char *val, int d) |
4527 |
|
|
{ |
4528 |
|
|
struct pflowreq preq; |
4529 |
|
|
|
4530 |
|
|
bzero(&preq, sizeof(struct pflowreq)); |
4531 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4532 |
|
|
preq.addrmask |= PFLOW_MASK_DSTIP; |
4533 |
|
|
pflow_addr(val, &preq.flowdst); |
4534 |
|
|
|
4535 |
|
|
if (ioctl(s, SIOCSETPFLOW, (caddr_t)&ifr) == -1) |
4536 |
|
|
err(1, "SIOCSETPFLOW"); |
4537 |
|
|
} |
4538 |
|
|
|
4539 |
|
|
void |
4540 |
|
|
unsetpflow_receiver(const char *val, int d) |
4541 |
|
|
{ |
4542 |
|
|
struct pflowreq preq; |
4543 |
|
|
|
4544 |
|
|
bzero(&preq, sizeof(struct pflowreq)); |
4545 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4546 |
|
|
preq.addrmask |= PFLOW_MASK_DSTIP; |
4547 |
|
|
if (ioctl(s, SIOCSETPFLOW, (caddr_t)&ifr) == -1) |
4548 |
|
|
err(1, "SIOCSETPFLOW"); |
4549 |
|
|
} |
4550 |
|
|
|
4551 |
|
|
/* PFLOWPROTO XXX */ |
4552 |
|
|
void |
4553 |
|
|
setpflowproto(const char *val, int d) |
4554 |
|
|
{ |
4555 |
|
|
struct pflow_protos ppr[] = PFLOW_PROTOS; |
4556 |
|
|
struct pflowreq preq; |
4557 |
|
|
int i; |
4558 |
|
|
|
4559 |
|
|
bzero(&preq, sizeof(preq)); |
4560 |
|
|
preq.version = PFLOW_PROTO_MAX; |
4561 |
|
|
|
4562 |
|
|
for (i = 0; i < (sizeof(ppr) / sizeof(ppr[0])); i++) { |
4563 |
|
|
if (strcmp(val, ppr[i].ppr_name) == 0) { |
4564 |
|
|
preq.version = ppr[i].ppr_proto; |
4565 |
|
|
break; |
4566 |
|
|
} |
4567 |
|
|
} |
4568 |
|
|
if (preq.version == PFLOW_PROTO_MAX) |
4569 |
|
|
errx(1, "Invalid pflow protocol: %s", val); |
4570 |
|
|
|
4571 |
|
|
preq.addrmask |= PFLOW_MASK_VERSION; |
4572 |
|
|
|
4573 |
|
|
ifr.ifr_data = (caddr_t)&preq; |
4574 |
|
|
|
4575 |
|
|
if (ioctl(s, SIOCSETPFLOW, (caddr_t)&ifr) == -1) |
4576 |
|
|
err(1, "SIOCSETPFLOW"); |
4577 |
|
|
} |
4578 |
|
|
|
4579 |
|
|
void |
4580 |
|
|
pppoe_status(void) |
4581 |
|
|
{ |
4582 |
|
|
struct pppoediscparms parms; |
4583 |
|
|
struct pppoeconnectionstate state; |
4584 |
|
|
|
4585 |
|
|
memset(&state, 0, sizeof(state)); |
4586 |
|
|
|
4587 |
|
|
strlcpy(parms.ifname, name, sizeof(parms.ifname)); |
4588 |
|
|
if (ioctl(s, PPPOEGETPARMS, &parms)) |
4589 |
|
|
return; |
4590 |
|
|
|
4591 |
|
|
printf("\tdev: %s ", parms.eth_ifname); |
4592 |
|
|
|
4593 |
|
|
if (*parms.ac_name) |
4594 |
|
|
printf("ac: %s ", parms.ac_name); |
4595 |
|
|
if (*parms.service_name) |
4596 |
|
|
printf("svc: %s ", parms.service_name); |
4597 |
|
|
|
4598 |
|
|
strlcpy(state.ifname, name, sizeof(state.ifname)); |
4599 |
|
|
if (ioctl(s, PPPOEGETSESSION, &state)) |
4600 |
|
|
err(1, "PPPOEGETSESSION"); |
4601 |
|
|
|
4602 |
|
|
printf("state: "); |
4603 |
|
|
switch (state.state) { |
4604 |
|
|
case PPPOE_STATE_INITIAL: |
4605 |
|
|
printf("initial"); break; |
4606 |
|
|
case PPPOE_STATE_PADI_SENT: |
4607 |
|
|
printf("PADI sent"); break; |
4608 |
|
|
case PPPOE_STATE_PADR_SENT: |
4609 |
|
|
printf("PADR sent"); break; |
4610 |
|
|
case PPPOE_STATE_SESSION: |
4611 |
|
|
printf("session"); break; |
4612 |
|
|
case PPPOE_STATE_CLOSING: |
4613 |
|
|
printf("closing"); break; |
4614 |
|
|
} |
4615 |
|
|
printf("\n\tsid: 0x%x", state.session_id); |
4616 |
|
|
printf(" PADI retries: %d", state.padi_retry_no); |
4617 |
|
|
printf(" PADR retries: %d", state.padr_retry_no); |
4618 |
|
|
|
4619 |
|
|
if (state.state == PPPOE_STATE_SESSION) { |
4620 |
|
|
struct timeval temp_time; |
4621 |
|
|
time_t diff_time, day = 0; |
4622 |
|
|
unsigned int hour = 0, min = 0, sec = 0; |
4623 |
|
|
|
4624 |
|
|
if (state.session_time.tv_sec != 0) { |
4625 |
|
|
gettimeofday(&temp_time, NULL); |
4626 |
|
|
diff_time = temp_time.tv_sec - |
4627 |
|
|
state.session_time.tv_sec; |
4628 |
|
|
|
4629 |
|
|
day = diff_time / (60 * 60 * 24); |
4630 |
|
|
diff_time %= (60 * 60 * 24); |
4631 |
|
|
|
4632 |
|
|
hour = diff_time / (60 * 60); |
4633 |
|
|
diff_time %= (60 * 60); |
4634 |
|
|
|
4635 |
|
|
min = diff_time / 60; |
4636 |
|
|
diff_time %= 60; |
4637 |
|
|
|
4638 |
|
|
sec = diff_time; |
4639 |
|
|
} |
4640 |
|
|
printf(" time: "); |
4641 |
|
|
if (day != 0) |
4642 |
|
|
printf("%lldd ", (long long)day); |
4643 |
|
|
printf("%02u:%02u:%02u", hour, min, sec); |
4644 |
|
|
} |
4645 |
|
|
putchar('\n'); |
4646 |
|
|
} |
4647 |
|
|
|
4648 |
|
|
/* ARGSUSED */ |
4649 |
|
|
void |
4650 |
|
|
setpppoe_dev(const char *val, int d) |
4651 |
|
|
{ |
4652 |
|
|
struct pppoediscparms parms; |
4653 |
|
|
|
4654 |
|
|
strlcpy(parms.ifname, name, sizeof(parms.ifname)); |
4655 |
|
|
if (ioctl(s, PPPOEGETPARMS, &parms)) |
4656 |
|
|
return; |
4657 |
|
|
|
4658 |
|
|
strlcpy(parms.eth_ifname, val, sizeof(parms.eth_ifname)); |
4659 |
|
|
|
4660 |
|
|
if (ioctl(s, PPPOESETPARMS, &parms)) |
4661 |
|
|
err(1, "PPPOESETPARMS"); |
4662 |
|
|
} |
4663 |
|
|
|
4664 |
|
|
/* ARGSUSED */ |
4665 |
|
|
void |
4666 |
|
|
setpppoe_svc(const char *val, int d) |
4667 |
|
|
{ |
4668 |
|
|
struct pppoediscparms parms; |
4669 |
|
|
|
4670 |
|
|
strlcpy(parms.ifname, name, sizeof(parms.ifname)); |
4671 |
|
|
if (ioctl(s, PPPOEGETPARMS, &parms)) |
4672 |
|
|
return; |
4673 |
|
|
|
4674 |
|
|
if (d == 0) |
4675 |
|
|
strlcpy(parms.service_name, val, sizeof(parms.service_name)); |
4676 |
|
|
else |
4677 |
|
|
memset(parms.service_name, 0, sizeof(parms.service_name)); |
4678 |
|
|
|
4679 |
|
|
if (ioctl(s, PPPOESETPARMS, &parms)) |
4680 |
|
|
err(1, "PPPOESETPARMS"); |
4681 |
|
|
} |
4682 |
|
|
|
4683 |
|
|
/* ARGSUSED */ |
4684 |
|
|
void |
4685 |
|
|
setpppoe_ac(const char *val, int d) |
4686 |
|
|
{ |
4687 |
|
|
struct pppoediscparms parms; |
4688 |
|
|
|
4689 |
|
|
strlcpy(parms.ifname, name, sizeof(parms.ifname)); |
4690 |
|
|
if (ioctl(s, PPPOEGETPARMS, &parms)) |
4691 |
|
|
return; |
4692 |
|
|
|
4693 |
|
|
if (d == 0) |
4694 |
|
|
strlcpy(parms.ac_name, val, sizeof(parms.ac_name)); |
4695 |
|
|
else |
4696 |
|
|
memset(parms.ac_name, 0, sizeof(parms.ac_name)); |
4697 |
|
|
|
4698 |
|
|
if (ioctl(s, PPPOESETPARMS, &parms)) |
4699 |
|
|
err(1, "PPPOESETPARMS"); |
4700 |
|
|
} |
4701 |
|
|
|
4702 |
|
|
void |
4703 |
|
|
spppauthinfo(struct sauthreq *spa, int d) |
4704 |
|
|
{ |
4705 |
|
|
bzero(spa, sizeof(struct sauthreq)); |
4706 |
|
|
|
4707 |
|
|
ifr.ifr_data = (caddr_t)spa; |
4708 |
|
|
spa->cmd = d == 0 ? SPPPIOGMAUTH : SPPPIOGHAUTH; |
4709 |
|
|
if (ioctl(s, SIOCGSPPPPARAMS, &ifr) == -1) |
4710 |
|
|
err(1, "SIOCGSPPPPARAMS(SPPPIOGXAUTH)"); |
4711 |
|
|
} |
4712 |
|
|
|
4713 |
|
|
void |
4714 |
|
|
setspppproto(const char *val, int d) |
4715 |
|
|
{ |
4716 |
|
|
struct sauthreq spa; |
4717 |
|
|
|
4718 |
|
|
spppauthinfo(&spa, d); |
4719 |
|
|
|
4720 |
|
|
if (strcmp(val, "pap") == 0) |
4721 |
|
|
spa.proto = PPP_PAP; |
4722 |
|
|
else if (strcmp(val, "chap") == 0) |
4723 |
|
|
spa.proto = PPP_CHAP; |
4724 |
|
|
else if (strcmp(val, "none") == 0) |
4725 |
|
|
spa.proto = 0; |
4726 |
|
|
else |
4727 |
|
|
errx(1, "setpppproto"); |
4728 |
|
|
|
4729 |
|
|
spa.cmd = d == 0 ? SPPPIOSMAUTH : SPPPIOSHAUTH; |
4730 |
|
|
if (ioctl(s, SIOCSSPPPPARAMS, &ifr) == -1) |
4731 |
|
|
err(1, "SIOCSSPPPPARAMS(SPPPIOSXAUTH)"); |
4732 |
|
|
} |
4733 |
|
|
|
4734 |
|
|
void |
4735 |
|
|
setsppppeerproto(const char *val, int d) |
4736 |
|
|
{ |
4737 |
|
|
setspppproto(val, 1); |
4738 |
|
|
} |
4739 |
|
|
|
4740 |
|
|
void |
4741 |
|
|
setspppname(const char *val, int d) |
4742 |
|
|
{ |
4743 |
|
|
struct sauthreq spa; |
4744 |
|
|
|
4745 |
|
|
spppauthinfo(&spa, d); |
4746 |
|
|
|
4747 |
|
|
if (spa.proto == 0) |
4748 |
|
|
errx(1, "unspecified protocol"); |
4749 |
|
|
if (strlcpy(spa.name, val, sizeof(spa.name)) >= sizeof(spa.name)) |
4750 |
|
|
errx(1, "setspppname"); |
4751 |
|
|
|
4752 |
|
|
spa.cmd = d == 0 ? SPPPIOSMAUTH : SPPPIOSHAUTH; |
4753 |
|
|
if (ioctl(s, SIOCSSPPPPARAMS, &ifr) == -1) |
4754 |
|
|
err(1, "SIOCSSPPPPARAMS(SPPPIOSXAUTH)"); |
4755 |
|
|
} |
4756 |
|
|
|
4757 |
|
|
void |
4758 |
|
|
setsppppeername(const char *val, int d) |
4759 |
|
|
{ |
4760 |
|
|
setspppname(val, 1); |
4761 |
|
|
} |
4762 |
|
|
|
4763 |
|
|
void |
4764 |
|
|
setspppkey(const char *val, int d) |
4765 |
|
|
{ |
4766 |
|
|
struct sauthreq spa; |
4767 |
|
|
|
4768 |
|
|
spppauthinfo(&spa, d); |
4769 |
|
|
|
4770 |
|
|
if (spa.proto == 0) |
4771 |
|
|
errx(1, "unspecified protocol"); |
4772 |
|
|
if (strlcpy(spa.secret, val, sizeof(spa.secret)) >= sizeof(spa.secret)) |
4773 |
|
|
errx(1, "setspppkey"); |
4774 |
|
|
|
4775 |
|
|
spa.cmd = d == 0 ? SPPPIOSMAUTH : SPPPIOSHAUTH; |
4776 |
|
|
if (ioctl(s, SIOCSSPPPPARAMS, &ifr) == -1) |
4777 |
|
|
err(1, "SIOCSSPPPPARAMS(SPPPIOSXAUTH)"); |
4778 |
|
|
} |
4779 |
|
|
|
4780 |
|
|
void |
4781 |
|
|
setsppppeerkey(const char *val, int d) |
4782 |
|
|
{ |
4783 |
|
|
setspppkey(val, 1); |
4784 |
|
|
} |
4785 |
|
|
|
4786 |
|
|
void |
4787 |
|
|
setsppppeerflag(const char *val, int d) |
4788 |
|
|
{ |
4789 |
|
|
struct sauthreq spa; |
4790 |
|
|
int flag; |
4791 |
|
|
|
4792 |
|
|
spppauthinfo(&spa, 1); |
4793 |
|
|
|
4794 |
|
|
if (spa.proto == 0) |
4795 |
|
|
errx(1, "unspecified protocol"); |
4796 |
|
|
if (strcmp(val, "callin") == 0) |
4797 |
|
|
flag = AUTHFLAG_NOCALLOUT; |
4798 |
|
|
else if (strcmp(val, "norechallenge") == 0) |
4799 |
|
|
flag = AUTHFLAG_NORECHALLENGE; |
4800 |
|
|
else |
4801 |
|
|
errx(1, "setppppeerflags"); |
4802 |
|
|
|
4803 |
|
|
if (d) |
4804 |
|
|
spa.flags &= ~flag; |
4805 |
|
|
else |
4806 |
|
|
spa.flags |= flag; |
4807 |
|
|
|
4808 |
|
|
spa.cmd = SPPPIOSHAUTH; |
4809 |
|
|
if (ioctl(s, SIOCSSPPPPARAMS, &ifr) == -1) |
4810 |
|
|
err(1, "SIOCSSPPPPARAMS(SPPPIOSXAUTH)"); |
4811 |
|
|
} |
4812 |
|
|
|
4813 |
|
|
void |
4814 |
|
|
unsetsppppeerflag(const char *val, int d) |
4815 |
|
|
{ |
4816 |
|
|
setsppppeerflag(val, 1); |
4817 |
|
|
} |
4818 |
|
|
|
4819 |
|
|
void |
4820 |
|
|
sppp_printproto(const char *name, struct sauthreq *auth) |
4821 |
|
|
{ |
4822 |
|
|
if (auth->proto == 0) |
4823 |
|
|
return; |
4824 |
|
|
printf("%sproto ", name); |
4825 |
|
|
switch (auth->proto) { |
4826 |
|
|
case PPP_PAP: |
4827 |
|
|
printf("pap "); |
4828 |
|
|
break; |
4829 |
|
|
case PPP_CHAP: |
4830 |
|
|
printf("chap "); |
4831 |
|
|
break; |
4832 |
|
|
default: |
4833 |
|
|
printf("0x%04x ", auth->proto); |
4834 |
|
|
break; |
4835 |
|
|
} |
4836 |
|
|
if (auth->name[0]) |
4837 |
|
|
printf("%sname \"%s\" ", name, auth->name); |
4838 |
|
|
if (auth->secret[0]) |
4839 |
|
|
printf("%skey \"%s\" ", name, auth->secret); |
4840 |
|
|
} |
4841 |
|
|
|
4842 |
|
|
void |
4843 |
|
|
sppp_status(void) |
4844 |
|
|
{ |
4845 |
|
|
struct spppreq spr; |
4846 |
|
|
struct sauthreq spa; |
4847 |
|
|
|
4848 |
|
|
bzero(&spr, sizeof(spr)); |
4849 |
|
|
|
4850 |
|
|
ifr.ifr_data = (caddr_t)&spr; |
4851 |
|
|
spr.cmd = SPPPIOGDEFS; |
4852 |
|
|
if (ioctl(s, SIOCGSPPPPARAMS, &ifr) == -1) { |
4853 |
|
|
return; |
4854 |
|
|
} |
4855 |
|
|
|
4856 |
|
|
if (spr.phase == PHASE_DEAD) |
4857 |
|
|
return; |
4858 |
|
|
printf("\tsppp: phase "); |
4859 |
|
|
switch (spr.phase) { |
4860 |
|
|
case PHASE_ESTABLISH: |
4861 |
|
|
printf("establish "); |
4862 |
|
|
break; |
4863 |
|
|
case PHASE_TERMINATE: |
4864 |
|
|
printf("terminate "); |
4865 |
|
|
break; |
4866 |
|
|
case PHASE_AUTHENTICATE: |
4867 |
|
|
printf("authenticate "); |
4868 |
|
|
break; |
4869 |
|
|
case PHASE_NETWORK: |
4870 |
|
|
printf("network "); |
4871 |
|
|
break; |
4872 |
|
|
default: |
4873 |
|
|
printf("illegal "); |
4874 |
|
|
break; |
4875 |
|
|
} |
4876 |
|
|
|
4877 |
|
|
spppauthinfo(&spa, 0); |
4878 |
|
|
sppp_printproto("auth", &spa); |
4879 |
|
|
spppauthinfo(&spa, 1); |
4880 |
|
|
sppp_printproto("peer", &spa); |
4881 |
|
|
if (spa.flags & AUTHFLAG_NOCALLOUT) |
4882 |
|
|
printf("callin "); |
4883 |
|
|
if (spa.flags & AUTHFLAG_NORECHALLENGE) |
4884 |
|
|
printf("norechallenge "); |
4885 |
|
|
putchar('\n'); |
4886 |
|
|
} |
4887 |
|
|
|
4888 |
|
|
void |
4889 |
|
|
setkeepalive(const char *timeout, const char *count) |
4890 |
|
|
{ |
4891 |
|
|
const char *errmsg = NULL; |
4892 |
|
|
struct ifkalivereq ikar; |
4893 |
|
|
int t, c; |
4894 |
|
|
|
4895 |
|
|
t = strtonum(timeout, 1, 3600, &errmsg); |
4896 |
|
|
if (errmsg) |
4897 |
|
|
errx(1, "keepalive period %s: %s", timeout, errmsg); |
4898 |
|
|
c = strtonum(count, 2, 600, &errmsg); |
4899 |
|
|
if (errmsg) |
4900 |
|
|
errx(1, "keepalive count %s: %s", count, errmsg); |
4901 |
|
|
|
4902 |
|
|
strlcpy(ikar.ikar_name, name, sizeof(ikar.ikar_name)); |
4903 |
|
|
ikar.ikar_timeo = t; |
4904 |
|
|
ikar.ikar_cnt = c; |
4905 |
|
|
if (ioctl(s, SIOCSETKALIVE, (caddr_t)&ikar) < 0) |
4906 |
|
|
warn("SIOCSETKALIVE"); |
4907 |
|
|
} |
4908 |
|
|
|
4909 |
|
|
void |
4910 |
|
|
unsetkeepalive(const char *val, int d) |
4911 |
|
|
{ |
4912 |
|
|
struct ifkalivereq ikar; |
4913 |
|
|
|
4914 |
|
|
bzero(&ikar, sizeof(ikar)); |
4915 |
|
|
strlcpy(ikar.ikar_name, name, sizeof(ikar.ikar_name)); |
4916 |
|
|
if (ioctl(s, SIOCSETKALIVE, (caddr_t)&ikar) < 0) |
4917 |
|
|
warn("SIOCSETKALIVE"); |
4918 |
|
|
} |
4919 |
|
|
|
4920 |
|
|
void |
4921 |
|
|
setifpriority(const char *id, int param) |
4922 |
|
|
{ |
4923 |
|
|
const char *errmsg = NULL; |
4924 |
|
|
int prio; |
4925 |
|
|
|
4926 |
|
|
prio = strtonum(id, 0, 15, &errmsg); |
4927 |
|
|
if (errmsg) |
4928 |
|
|
errx(1, "priority %s: %s", id, errmsg); |
4929 |
|
|
|
4930 |
|
|
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
4931 |
|
|
ifr.ifr_metric = prio; |
4932 |
|
|
if (ioctl(s, SIOCSIFPRIORITY, (caddr_t)&ifr) < 0) |
4933 |
|
|
warn("SIOCSIFPRIORITY"); |
4934 |
|
|
} |
4935 |
|
|
|
4936 |
|
|
|
4937 |
|
|
const struct umb_valdescr umb_regstate[] = MBIM_REGSTATE_DESCRIPTIONS; |
4938 |
|
|
const struct umb_valdescr umb_dataclass[] = MBIM_DATACLASS_DESCRIPTIONS; |
4939 |
|
|
const struct umb_valdescr umb_simstate[] = MBIM_SIMSTATE_DESCRIPTIONS; |
4940 |
|
|
const struct umb_valdescr umb_istate[] = UMB_INTERNAL_STATE_DESCRIPTIONS; |
4941 |
|
|
const struct umb_valdescr umb_pktstate[] = MBIM_PKTSRV_STATE_DESCRIPTIONS; |
4942 |
|
|
const struct umb_valdescr umb_actstate[] = MBIM_ACTIVATION_STATE_DESCRIPTIONS; |
4943 |
|
|
|
4944 |
|
|
const struct umb_valdescr umb_classalias[] = { |
4945 |
|
|
{ MBIM_DATACLASS_GPRS | MBIM_DATACLASS_EDGE, "2g" }, |
4946 |
|
|
{ MBIM_DATACLASS_UMTS | MBIM_DATACLASS_HSDPA | MBIM_DATACLASS_HSUPA, |
4947 |
|
|
"3g" }, |
4948 |
|
|
{ MBIM_DATACLASS_LTE, "4g" }, |
4949 |
|
|
{ 0, NULL } |
4950 |
|
|
}; |
4951 |
|
|
|
4952 |
|
|
int |
4953 |
|
|
umb_descr2val(const struct umb_valdescr *vdp, char *str) |
4954 |
|
|
{ |
4955 |
|
|
while (vdp->descr != NULL) { |
4956 |
|
|
if (!strcasecmp(vdp->descr, str)) |
4957 |
|
|
return vdp->val; |
4958 |
|
|
vdp++; |
4959 |
|
|
} |
4960 |
|
|
return 0; |
4961 |
|
|
} |
4962 |
|
|
|
4963 |
|
|
void |
4964 |
|
|
umb_status(void) |
4965 |
|
|
{ |
4966 |
|
|
struct umb_info mi; |
4967 |
|
|
char provider[UMB_PROVIDERNAME_MAXLEN+1]; |
4968 |
|
|
char roamingtxt[UMB_ROAMINGTEXT_MAXLEN+1]; |
4969 |
|
|
char devid[UMB_DEVID_MAXLEN+1]; |
4970 |
|
|
char fwinfo[UMB_FWINFO_MAXLEN+1]; |
4971 |
|
|
char hwinfo[UMB_HWINFO_MAXLEN+1]; |
4972 |
|
|
char sid[UMB_SUBSCRIBERID_MAXLEN+1]; |
4973 |
|
|
char iccid[UMB_ICCID_MAXLEN+1]; |
4974 |
|
|
char apn[UMB_APN_MAXLEN+1]; |
4975 |
|
|
char pn[UMB_PHONENR_MAXLEN+1]; |
4976 |
|
|
int i, n; |
4977 |
|
|
|
4978 |
|
|
memset((char *)&mi, 0, sizeof(mi)); |
4979 |
|
|
ifr.ifr_data = (caddr_t)&mi; |
4980 |
|
|
if (ioctl(s, SIOCGUMBINFO, (caddr_t)&ifr) == -1) |
4981 |
|
|
return; |
4982 |
|
|
|
4983 |
|
|
if (mi.nwerror) { |
4984 |
|
|
/* 3GPP 24.008 Cause Code */ |
4985 |
|
|
printf("\terror: "); |
4986 |
|
|
switch (mi.nwerror) { |
4987 |
|
|
case 2: |
4988 |
|
|
printf("SIM not activated"); |
4989 |
|
|
break; |
4990 |
|
|
case 4: |
4991 |
|
|
printf("Roaming not supported"); |
4992 |
|
|
break; |
4993 |
|
|
case 6: |
4994 |
|
|
printf("SIM reported stolen"); |
4995 |
|
|
break; |
4996 |
|
|
case 7: |
4997 |
|
|
printf("No GPRS subscription"); |
4998 |
|
|
break; |
4999 |
|
|
case 8: |
5000 |
|
|
printf("GPRS and non-GPRS services not allowed"); |
5001 |
|
|
break; |
5002 |
|
|
case 11: |
5003 |
|
|
printf("Subscription expired"); |
5004 |
|
|
break; |
5005 |
|
|
case 12: |
5006 |
|
|
printf("Subscription does not cover current location"); |
5007 |
|
|
break; |
5008 |
|
|
case 13: |
5009 |
|
|
printf("No roaming in this location"); |
5010 |
|
|
break; |
5011 |
|
|
case 14: |
5012 |
|
|
printf("GPRS not supported"); |
5013 |
|
|
break; |
5014 |
|
|
case 15: |
5015 |
|
|
printf("No subscription for the service"); |
5016 |
|
|
break; |
5017 |
|
|
case 17: |
5018 |
|
|
printf("Registration failed"); |
5019 |
|
|
break; |
5020 |
|
|
case 22: |
5021 |
|
|
printf("Network congestion"); |
5022 |
|
|
break; |
5023 |
|
|
default: |
5024 |
|
|
printf("Error code %d", mi.nwerror); |
5025 |
|
|
break; |
5026 |
|
|
} |
5027 |
|
|
printf("\n"); |
5028 |
|
|
} |
5029 |
|
|
|
5030 |
|
|
printf("\troaming %s registration %s", |
5031 |
|
|
mi.enable_roaming ? "enabled" : "disabled", |
5032 |
|
|
umb_val2descr(umb_regstate, mi.regstate)); |
5033 |
|
|
utf16_to_char(mi.roamingtxt, UMB_ROAMINGTEXT_MAXLEN, |
5034 |
|
|
roamingtxt, sizeof (roamingtxt)); |
5035 |
|
|
if (roamingtxt[0]) |
5036 |
|
|
printf(" [%s]", roamingtxt); |
5037 |
|
|
printf("\n"); |
5038 |
|
|
|
5039 |
|
|
if (showclasses) |
5040 |
|
|
umb_printclasses("available classes", mi.supportedclasses); |
5041 |
|
|
printf("\tstate %s cell-class %s", |
5042 |
|
|
umb_val2descr(umb_istate, mi.state), |
5043 |
|
|
umb_val2descr(umb_dataclass, mi.highestclass)); |
5044 |
|
|
if (mi.rssi != UMB_VALUE_UNKNOWN && mi.rssi != 0) |
5045 |
|
|
printf(" rssi %ddBm", mi.rssi); |
5046 |
|
|
if (mi.uplink_speed != 0 || mi.downlink_speed != 0) { |
5047 |
|
|
char s[2][FMT_SCALED_STRSIZE]; |
5048 |
|
|
if (fmt_scaled(mi.uplink_speed, s[0]) != 0) |
5049 |
|
|
snprintf(s[0], sizeof (s[0]), "%llu", mi.uplink_speed); |
5050 |
|
|
if (fmt_scaled(mi.downlink_speed, s[1]) != 0) |
5051 |
|
|
snprintf(s[1], sizeof (s[1]), "%llu", mi.downlink_speed); |
5052 |
|
|
printf(" speed %sps up %sps down", s[0], s[1]); |
5053 |
|
|
} |
5054 |
|
|
printf("\n"); |
5055 |
|
|
|
5056 |
|
|
printf("\tSIM %s PIN ", umb_val2descr(umb_simstate, mi.sim_state)); |
5057 |
|
|
switch (mi.pin_state) { |
5058 |
|
|
case UMB_PIN_REQUIRED: |
5059 |
|
|
printf("required"); |
5060 |
|
|
break; |
5061 |
|
|
case UMB_PIN_UNLOCKED: |
5062 |
|
|
printf("valid"); |
5063 |
|
|
break; |
5064 |
|
|
case UMB_PUK_REQUIRED: |
5065 |
|
|
printf("locked (PUK required)"); |
5066 |
|
|
break; |
5067 |
|
|
default: |
5068 |
|
|
printf("unknown state (%d)", mi.pin_state); |
5069 |
|
|
break; |
5070 |
|
|
} |
5071 |
|
|
if (mi.pin_attempts_left != UMB_VALUE_UNKNOWN) |
5072 |
|
|
printf(" (%d attempts left)", mi.pin_attempts_left); |
5073 |
|
|
printf("\n"); |
5074 |
|
|
|
5075 |
|
|
utf16_to_char(mi.sid, UMB_SUBSCRIBERID_MAXLEN, sid, sizeof (sid)); |
5076 |
|
|
utf16_to_char(mi.iccid, UMB_ICCID_MAXLEN, iccid, sizeof (iccid)); |
5077 |
|
|
utf16_to_char(mi.provider, UMB_PROVIDERNAME_MAXLEN, |
5078 |
|
|
provider, sizeof (provider)); |
5079 |
|
|
if (sid[0] || iccid[0] || provider[0]) { |
5080 |
|
|
printf("\t"); |
5081 |
|
|
n = 0; |
5082 |
|
|
if (sid[0]) |
5083 |
|
|
printf("%ssubscriber-id %s", n++ ? " " : "", sid); |
5084 |
|
|
if (iccid[0]) |
5085 |
|
|
printf("%sICC-id %s", n++ ? " " : "", iccid); |
5086 |
|
|
if (provider[0]) |
5087 |
|
|
printf("%sprovider %s", n ? " " : "", provider); |
5088 |
|
|
printf("\n"); |
5089 |
|
|
} |
5090 |
|
|
|
5091 |
|
|
utf16_to_char(mi.hwinfo, UMB_HWINFO_MAXLEN, hwinfo, sizeof (hwinfo)); |
5092 |
|
|
utf16_to_char(mi.devid, UMB_DEVID_MAXLEN, devid, sizeof (devid)); |
5093 |
|
|
utf16_to_char(mi.fwinfo, UMB_FWINFO_MAXLEN, fwinfo, sizeof (fwinfo)); |
5094 |
|
|
if (hwinfo[0] || devid[0] || fwinfo[0]) { |
5095 |
|
|
printf("\t"); |
5096 |
|
|
n = 0; |
5097 |
|
|
if (hwinfo[0]) |
5098 |
|
|
printf("%sdevice %s", n++ ? " " : "", hwinfo); |
5099 |
|
|
if (devid[0]) { |
5100 |
|
|
printf("%s", n++ ? " " : ""); |
5101 |
|
|
switch (mi.cellclass) { |
5102 |
|
|
case MBIM_CELLCLASS_GSM: |
5103 |
|
|
printf("IMEI"); |
5104 |
|
|
break; |
5105 |
|
|
case MBIM_CELLCLASS_CDMA: |
5106 |
|
|
n = strlen(devid); |
5107 |
|
|
if (n == 8 || n == 11) { |
5108 |
|
|
printf("ESN"); |
5109 |
|
|
break; |
5110 |
|
|
} else if (n == 14 || n == 18) { |
5111 |
|
|
printf("MEID"); |
5112 |
|
|
break; |
5113 |
|
|
} |
5114 |
|
|
/*FALLTHROUGH*/ |
5115 |
|
|
default: |
5116 |
|
|
printf("ID"); |
5117 |
|
|
break; |
5118 |
|
|
} |
5119 |
|
|
printf(" %s", devid); |
5120 |
|
|
} |
5121 |
|
|
if (fwinfo[0]) |
5122 |
|
|
printf("%sfirmware %s", n++ ? " " : "", fwinfo); |
5123 |
|
|
printf("\n"); |
5124 |
|
|
} |
5125 |
|
|
|
5126 |
|
|
utf16_to_char(mi.pn, UMB_PHONENR_MAXLEN, pn, sizeof (pn)); |
5127 |
|
|
utf16_to_char(mi.apn, UMB_APN_MAXLEN, apn, sizeof (apn)); |
5128 |
|
|
if (pn[0] || apn[0]) { |
5129 |
|
|
printf("\t"); |
5130 |
|
|
n = 0; |
5131 |
|
|
if (pn[0]) |
5132 |
|
|
printf("%sphone# +%s", n++ ? " " : "", pn); |
5133 |
|
|
if (apn[0]) |
5134 |
|
|
printf("%sAPN %s", n++ ? " " : "", apn); |
5135 |
|
|
printf("\n"); |
5136 |
|
|
} |
5137 |
|
|
|
5138 |
|
|
for (i = 0, n = 0; i < UMB_MAX_DNSSRV; i++) { |
5139 |
|
|
if (mi.ipv4dns[i] == INADDR_ANY) |
5140 |
|
|
break; |
5141 |
|
|
printf("%s %s", n++ ? "" : "\tdns", |
5142 |
|
|
inet_ntoa(*(struct in_addr *)&mi.ipv4dns[i])); |
5143 |
|
|
} |
5144 |
|
|
if (n) |
5145 |
|
|
printf("\n"); |
5146 |
|
|
} |
5147 |
|
|
|
5148 |
|
|
void |
5149 |
|
|
umb_printclasses(char *tag, int c) |
5150 |
|
|
{ |
5151 |
|
|
int i; |
5152 |
|
|
char *sep = ""; |
5153 |
|
|
|
5154 |
|
|
printf("\t%s: ", tag); |
5155 |
|
|
i = 0; |
5156 |
|
|
while (umb_dataclass[i].descr) { |
5157 |
|
|
if (umb_dataclass[i].val & c) { |
5158 |
|
|
printf("%s%s", sep, umb_dataclass[i].descr); |
5159 |
|
|
sep = ","; |
5160 |
|
|
} |
5161 |
|
|
i++; |
5162 |
|
|
} |
5163 |
|
|
printf("\n"); |
5164 |
|
|
} |
5165 |
|
|
|
5166 |
|
|
int |
5167 |
|
|
umb_parse_classes(const char *spec) |
5168 |
|
|
{ |
5169 |
|
|
char *optlist, *str; |
5170 |
|
|
int c = 0, v; |
5171 |
|
|
|
5172 |
|
|
if ((optlist = strdup(spec)) == NULL) |
5173 |
|
|
err(1, "strdup"); |
5174 |
|
|
str = strtok(optlist, ","); |
5175 |
|
|
while (str != NULL) { |
5176 |
|
|
if ((v = umb_descr2val(umb_dataclass, str)) != 0 || |
5177 |
|
|
(v = umb_descr2val(umb_classalias, str)) != 0) |
5178 |
|
|
c |= v; |
5179 |
|
|
str = strtok(NULL, ","); |
5180 |
|
|
} |
5181 |
|
|
free(optlist); |
5182 |
|
|
return c; |
5183 |
|
|
} |
5184 |
|
|
|
5185 |
|
|
void |
5186 |
|
|
umb_setpin(const char *pin, int d) |
5187 |
|
|
{ |
5188 |
|
|
umb_pinop(MBIM_PIN_OP_ENTER, 0, pin, NULL); |
5189 |
|
|
} |
5190 |
|
|
|
5191 |
|
|
void |
5192 |
|
|
umb_chgpin(const char *pin, const char *newpin) |
5193 |
|
|
{ |
5194 |
|
|
umb_pinop(MBIM_PIN_OP_CHANGE, 0, pin, newpin); |
5195 |
|
|
} |
5196 |
|
|
|
5197 |
|
|
void |
5198 |
|
|
umb_puk(const char *pin, const char *newpin) |
5199 |
|
|
{ |
5200 |
|
|
umb_pinop(MBIM_PIN_OP_ENTER, 1, pin, newpin); |
5201 |
|
|
} |
5202 |
|
|
|
5203 |
|
|
void |
5204 |
|
|
umb_pinop(int op, int is_puk, const char *pin, const char *newpin) |
5205 |
|
|
{ |
5206 |
|
|
struct umb_parameter mp; |
5207 |
|
|
|
5208 |
|
|
memset(&mp, 0, sizeof (mp)); |
5209 |
|
|
ifr.ifr_data = (caddr_t)∓ |
5210 |
|
|
if (ioctl(s, SIOCGUMBPARAM, (caddr_t)&ifr) == -1) |
5211 |
|
|
err(1, "SIOCGUMBPARAM"); |
5212 |
|
|
|
5213 |
|
|
mp.op = op; |
5214 |
|
|
mp.is_puk = is_puk; |
5215 |
|
|
if ((mp.pinlen = char_to_utf16(pin, (uint16_t *)mp.pin, |
5216 |
|
|
sizeof (mp.pin))) == -1) |
5217 |
|
|
errx(1, "PIN too long"); |
5218 |
|
|
|
5219 |
|
|
if (newpin) { |
5220 |
|
|
if ((mp.newpinlen = char_to_utf16(newpin, (uint16_t *)mp.newpin, |
5221 |
|
|
sizeof (mp.newpin))) == -1) |
5222 |
|
|
errx(1, "new PIN too long"); |
5223 |
|
|
} |
5224 |
|
|
|
5225 |
|
|
if (ioctl(s, SIOCSUMBPARAM, (caddr_t)&ifr) == -1) |
5226 |
|
|
err(1, "SIOCSUMBPARAM"); |
5227 |
|
|
} |
5228 |
|
|
|
5229 |
|
|
void |
5230 |
|
|
umb_apn(const char *apn, int d) |
5231 |
|
|
{ |
5232 |
|
|
struct umb_parameter mp; |
5233 |
|
|
|
5234 |
|
|
memset(&mp, 0, sizeof (mp)); |
5235 |
|
|
ifr.ifr_data = (caddr_t)∓ |
5236 |
|
|
if (ioctl(s, SIOCGUMBPARAM, (caddr_t)&ifr) == -1) |
5237 |
|
|
err(1, "SIOCGUMBPARAM"); |
5238 |
|
|
|
5239 |
|
|
if (d != 0) |
5240 |
|
|
memset(mp.apn, 0, sizeof (mp.apn)); |
5241 |
|
|
else if ((mp.apnlen = char_to_utf16(apn, mp.apn, |
5242 |
|
|
sizeof (mp.apn))) == -1) |
5243 |
|
|
errx(1, "APN too long"); |
5244 |
|
|
|
5245 |
|
|
if (ioctl(s, SIOCSUMBPARAM, (caddr_t)&ifr) == -1) |
5246 |
|
|
err(1, "SIOCSUMBPARAM"); |
5247 |
|
|
} |
5248 |
|
|
|
5249 |
|
|
void |
5250 |
|
|
umb_setclass(const char *val, int d) |
5251 |
|
|
{ |
5252 |
|
|
struct umb_parameter mp; |
5253 |
|
|
|
5254 |
|
|
if (val == NULL) { |
5255 |
|
|
if (showclasses) |
5256 |
|
|
usage(1); |
5257 |
|
|
showclasses = 1; |
5258 |
|
|
return; |
5259 |
|
|
} |
5260 |
|
|
|
5261 |
|
|
memset(&mp, 0, sizeof (mp)); |
5262 |
|
|
ifr.ifr_data = (caddr_t)∓ |
5263 |
|
|
if (ioctl(s, SIOCGUMBPARAM, (caddr_t)&ifr) == -1) |
5264 |
|
|
err(1, "SIOCGUMBPARAM"); |
5265 |
|
|
if (d != -1) |
5266 |
|
|
mp.preferredclasses = umb_parse_classes(val); |
5267 |
|
|
else |
5268 |
|
|
mp.preferredclasses = MBIM_DATACLASS_NONE; |
5269 |
|
|
if (ioctl(s, SIOCSUMBPARAM, (caddr_t)&ifr) == -1) |
5270 |
|
|
err(1, "SIOCSUMBPARAM"); |
5271 |
|
|
} |
5272 |
|
|
|
5273 |
|
|
void |
5274 |
|
|
umb_roaming(const char *val, int d) |
5275 |
|
|
{ |
5276 |
|
|
struct umb_parameter mp; |
5277 |
|
|
|
5278 |
|
|
memset(&mp, 0, sizeof (mp)); |
5279 |
|
|
ifr.ifr_data = (caddr_t)∓ |
5280 |
|
|
if (ioctl(s, SIOCGUMBPARAM, (caddr_t)&ifr) == -1) |
5281 |
|
|
err(1, "SIOCGUMBPARAM"); |
5282 |
|
|
mp.roaming = d; |
5283 |
|
|
if (ioctl(s, SIOCSUMBPARAM, (caddr_t)&ifr) == -1) |
5284 |
|
|
err(1, "SIOCSUMBPARAM"); |
5285 |
|
|
} |
5286 |
|
|
|
5287 |
|
|
void |
5288 |
|
|
utf16_to_char(uint16_t *in, int inlen, char *out, size_t outlen) |
5289 |
|
|
{ |
5290 |
|
|
uint16_t c; |
5291 |
|
|
|
5292 |
|
|
while (outlen > 0) { |
5293 |
|
|
c = inlen > 0 ? letoh16(*in) : 0; |
5294 |
|
|
if (c == 0 || --outlen == 0) { |
5295 |
|
|
/* always NUL terminate result */ |
5296 |
|
|
done: |
5297 |
|
|
*out = '\0'; |
5298 |
|
|
break; |
5299 |
|
|
} |
5300 |
|
|
*out++ = isascii(c) ? (char)c : '?'; |
5301 |
|
|
in++; |
5302 |
|
|
inlen -= sizeof (*in); |
5303 |
|
|
} |
5304 |
|
|
} |
5305 |
|
|
|
5306 |
|
|
int |
5307 |
|
|
char_to_utf16(const char *in, uint16_t *out, size_t outlen) |
5308 |
|
|
{ |
5309 |
|
|
int n = 0; |
5310 |
|
|
uint16_t c; |
5311 |
|
|
|
5312 |
|
|
for (;;) { |
5313 |
|
|
c = *in++; |
5314 |
|
|
|
5315 |
|
|
if (c == '\0') { |
5316 |
|
|
/* |
5317 |
|
|
* NUL termination is not required, but zero out the |
5318 |
|
|
* residual buffer |
5319 |
|
|
*/ |
5320 |
|
|
memset(out, 0, outlen); |
5321 |
|
|
return n; |
5322 |
|
|
} |
5323 |
|
|
if (outlen < sizeof (*out)) |
5324 |
|
|
return -1; |
5325 |
|
|
|
5326 |
|
|
*out++ = htole16(c); |
5327 |
|
|
n += sizeof (*out); |
5328 |
|
|
outlen -= sizeof (*out); |
5329 |
|
|
} |
5330 |
|
|
} |
5331 |
|
|
|
5332 |
|
|
#endif |
5333 |
|
|
|
5334 |
|
|
#define SIN(x) ((struct sockaddr_in *) &(x)) |
5335 |
|
|
struct sockaddr_in *sintab[] = { |
5336 |
|
|
SIN(ridreq.ifr_addr), SIN(in_addreq.ifra_addr), |
5337 |
|
|
SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr)}; |
5338 |
|
|
|
5339 |
|
|
void |
5340 |
|
|
in_getaddr(const char *s, int which) |
5341 |
|
88 |
{ |
5342 |
|
88 |
struct sockaddr_in *sin = sintab[which], tsin; |
5343 |
|
|
struct hostent *hp; |
5344 |
|
|
struct netent *np; |
5345 |
|
|
int bits, l; |
5346 |
|
|
char p[3]; |
5347 |
|
|
|
5348 |
|
88 |
bzero(&tsin, sizeof(tsin)); |
5349 |
|
88 |
sin->sin_len = sizeof(*sin); |
5350 |
✓✗ |
88 |
if (which != MASK) |
5351 |
|
88 |
sin->sin_family = AF_INET; |
5352 |
|
|
|
5353 |
✓✗✓✗ ✓✗ |
176 |
if (which == ADDR && strrchr(s, '/') != NULL && |
5354 |
|
|
(bits = inet_net_pton(AF_INET, s, &tsin.sin_addr, |
5355 |
|
|
sizeof(tsin.sin_addr))) != -1) { |
5356 |
|
88 |
l = snprintf(p, sizeof(p), "%d", bits); |
5357 |
✗✓ |
88 |
if (l >= sizeof(p) || l == -1) |
5358 |
|
|
errx(1, "%d: bad prefixlen", bits); |
5359 |
|
88 |
in_getprefix(p, MASK); |
5360 |
|
88 |
memcpy(&sin->sin_addr, &tsin.sin_addr, sizeof(sin->sin_addr)); |
5361 |
|
|
} else if (inet_aton(s, &sin->sin_addr) == 0) { |
5362 |
|
|
if ((hp = gethostbyname(s))) |
5363 |
|
|
memcpy(&sin->sin_addr, hp->h_addr, hp->h_length); |
5364 |
|
|
else if ((np = getnetbyname(s))) |
5365 |
|
|
sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); |
5366 |
|
|
else |
5367 |
|
|
errx(1, "%s: bad value", s); |
5368 |
|
|
} |
5369 |
|
88 |
} |
5370 |
|
|
|
5371 |
|
|
/* ARGSUSED */ |
5372 |
|
|
void |
5373 |
|
|
in_getprefix(const char *plen, int which) |
5374 |
|
88 |
{ |
5375 |
|
88 |
struct sockaddr_in *sin = sintab[which]; |
5376 |
|
88 |
const char *errmsg = NULL; |
5377 |
|
|
u_char *cp; |
5378 |
|
|
int len; |
5379 |
|
|
|
5380 |
|
88 |
len = strtonum(plen, 0, 32, &errmsg); |
5381 |
✗✓ |
88 |
if (errmsg) |
5382 |
|
|
errx(1, "prefix %s: %s", plen, errmsg); |
5383 |
|
|
|
5384 |
|
88 |
sin->sin_len = sizeof(*sin); |
5385 |
✗✓ |
88 |
if (which != MASK) |
5386 |
|
|
sin->sin_family = AF_INET; |
5387 |
✓✗ |
88 |
if ((len == 0) || (len == 32)) { |
5388 |
|
88 |
memset(&sin->sin_addr, 0xff, sizeof(struct in_addr)); |
5389 |
|
88 |
return; |
5390 |
|
|
} |
5391 |
|
|
memset((void *)&sin->sin_addr, 0x00, sizeof(sin->sin_addr)); |
5392 |
|
|
for (cp = (u_char *)&sin->sin_addr; len > 7; len -= 8) |
5393 |
|
|
*cp++ = 0xff; |
5394 |
|
|
if (len) |
5395 |
|
|
*cp = 0xff << (8 - len); |
5396 |
|
|
} |
5397 |
|
|
|
5398 |
|
|
/* |
5399 |
|
|
* Print a value a la the %b format of the kernel's printf |
5400 |
|
|
*/ |
5401 |
|
|
void |
5402 |
|
|
printb(char *s, unsigned int v, unsigned char *bits) |
5403 |
|
|
{ |
5404 |
|
|
int i, any = 0; |
5405 |
|
|
unsigned char c; |
5406 |
|
|
|
5407 |
|
|
if (bits && *bits == 8) |
5408 |
|
|
printf("%s=%o", s, v); |
5409 |
|
|
else |
5410 |
|
|
printf("%s=%x", s, v); |
5411 |
|
|
|
5412 |
|
|
if (bits) { |
5413 |
|
|
bits++; |
5414 |
|
|
putchar('<'); |
5415 |
|
|
while ((i = *bits++)) { |
5416 |
|
|
if (v & (1 << (i-1))) { |
5417 |
|
|
if (any) |
5418 |
|
|
putchar(','); |
5419 |
|
|
any = 1; |
5420 |
|
|
for (; (c = *bits) > 32; bits++) |
5421 |
|
|
putchar(c); |
5422 |
|
|
} else |
5423 |
|
|
for (; *bits > 32; bits++) |
5424 |
|
|
; |
5425 |
|
|
} |
5426 |
|
|
putchar('>'); |
5427 |
|
|
} |
5428 |
|
|
} |
5429 |
|
|
|
5430 |
|
|
/* |
5431 |
|
|
* A simple version of printb for status output |
5432 |
|
|
*/ |
5433 |
|
|
void |
5434 |
|
|
printb_status(unsigned short v, unsigned char *bits) |
5435 |
|
|
{ |
5436 |
|
|
int i, any = 0; |
5437 |
|
|
unsigned char c; |
5438 |
|
|
|
5439 |
|
|
if (bits) { |
5440 |
|
|
bits++; |
5441 |
|
|
while ((i = *bits++)) { |
5442 |
|
|
if (v & (1 << (i-1))) { |
5443 |
|
|
if (any) |
5444 |
|
|
putchar(','); |
5445 |
|
|
any = 1; |
5446 |
|
|
for (; (c = *bits) > 32; bits++) |
5447 |
|
|
putchar(tolower(c)); |
5448 |
|
|
} else |
5449 |
|
|
for (; *bits > 32; bits++) |
5450 |
|
|
; |
5451 |
|
|
} |
5452 |
|
|
} |
5453 |
|
|
} |
5454 |
|
|
|
5455 |
|
|
#define SIN6(x) ((struct sockaddr_in6 *) &(x)) |
5456 |
|
|
struct sockaddr_in6 *sin6tab[] = { |
5457 |
|
|
SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), |
5458 |
|
|
SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; |
5459 |
|
|
|
5460 |
|
|
void |
5461 |
|
|
in6_getaddr(const char *s, int which) |
5462 |
|
6 |
{ |
5463 |
|
6 |
struct sockaddr_in6 *sin6 = sin6tab[which]; |
5464 |
|
|
struct addrinfo hints, *res; |
5465 |
|
|
char buf[HOST_NAME_MAX+1 + sizeof("/128")], *pfxlen; |
5466 |
|
|
int error; |
5467 |
|
|
|
5468 |
|
6 |
memset(&hints, 0, sizeof(hints)); |
5469 |
|
6 |
hints.ai_family = AF_INET6; |
5470 |
|
6 |
hints.ai_socktype = SOCK_DGRAM; /*dummy*/ |
5471 |
|
|
|
5472 |
✓✗✓✗
|
6 |
if (which == ADDR && strchr(s, '/') != NULL) { |
5473 |
✗✓ |
6 |
if (strlcpy(buf, s, sizeof(buf)) >= sizeof(buf)) |
5474 |
|
|
errx(1, "%s: bad value", s); |
5475 |
|
6 |
pfxlen = strchr(buf, '/'); |
5476 |
|
6 |
*pfxlen++ = '\0'; |
5477 |
|
6 |
s = buf; |
5478 |
|
6 |
in6_getprefix(pfxlen, MASK); |
5479 |
|
6 |
explicit_prefix = 1; |
5480 |
|
|
} |
5481 |
|
|
|
5482 |
|
6 |
error = getaddrinfo(s, "0", &hints, &res); |
5483 |
✗✓ |
6 |
if (error) |
5484 |
|
|
errx(1, "%s: %s", s, gai_strerror(error)); |
5485 |
✗✓ |
6 |
if (res->ai_addrlen != sizeof(struct sockaddr_in6)) |
5486 |
|
|
errx(1, "%s: bad value", s); |
5487 |
|
6 |
memcpy(sin6, res->ai_addr, res->ai_addrlen); |
5488 |
|
|
#ifdef __KAME__ |
5489 |
✗✓✗✗ ✗✗✗✗
|
6 |
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && |
5490 |
|
|
*(u_int16_t *)&sin6->sin6_addr.s6_addr[2] == 0 && |
5491 |
|
|
sin6->sin6_scope_id) { |
5492 |
|
|
*(u_int16_t *)&sin6->sin6_addr.s6_addr[2] = |
5493 |
|
|
htons(sin6->sin6_scope_id & 0xffff); |
5494 |
|
|
sin6->sin6_scope_id = 0; |
5495 |
|
|
} |
5496 |
|
|
#endif /* __KAME__ */ |
5497 |
|
6 |
freeaddrinfo(res); |
5498 |
|
6 |
} |
5499 |
|
|
|
5500 |
|
|
void |
5501 |
|
|
in6_getprefix(const char *plen, int which) |
5502 |
|
8 |
{ |
5503 |
|
8 |
struct sockaddr_in6 *sin6 = sin6tab[which]; |
5504 |
|
8 |
const char *errmsg = NULL; |
5505 |
|
|
u_char *cp; |
5506 |
|
|
int len; |
5507 |
|
|
|
5508 |
|
8 |
len = strtonum(plen, 0, 128, &errmsg); |
5509 |
✗✓ |
8 |
if (errmsg) |
5510 |
|
|
errx(1, "prefix %s: %s", plen, errmsg); |
5511 |
|
|
|
5512 |
|
8 |
sin6->sin6_len = sizeof(*sin6); |
5513 |
✗✓ |
8 |
if (which != MASK) |
5514 |
|
|
sin6->sin6_family = AF_INET6; |
5515 |
✗✓ |
8 |
if ((len == 0) || (len == 128)) { |
5516 |
|
|
memset(&sin6->sin6_addr, 0xff, sizeof(struct in6_addr)); |
5517 |
|
|
return; |
5518 |
|
|
} |
5519 |
|
8 |
memset((void *)&sin6->sin6_addr, 0x00, sizeof(sin6->sin6_addr)); |
5520 |
✓✓ |
72 |
for (cp = (u_char *)&sin6->sin6_addr; len > 7; len -= 8) |
5521 |
|
64 |
*cp++ = 0xff; |
5522 |
✗✓ |
8 |
if (len) |
5523 |
|
|
*cp = 0xff << (8 - len); |
5524 |
|
|
} |
5525 |
|
|
|
5526 |
|
|
int |
5527 |
|
|
prefix(void *val, int size) |
5528 |
|
|
{ |
5529 |
|
|
u_char *nam = (u_char *)val; |
5530 |
|
|
int byte, bit, plen = 0; |
5531 |
|
|
|
5532 |
|
|
for (byte = 0; byte < size; byte++, plen += 8) |
5533 |
|
|
if (nam[byte] != 0xff) |
5534 |
|
|
break; |
5535 |
|
|
if (byte == size) |
5536 |
|
|
return (plen); |
5537 |
|
|
for (bit = 7; bit != 0; bit--, plen++) |
5538 |
|
|
if (!(nam[byte] & (1 << bit))) |
5539 |
|
|
break; |
5540 |
|
|
for (; bit != 0; bit--) |
5541 |
|
|
if (nam[byte] & (1 << bit)) |
5542 |
|
|
return (0); |
5543 |
|
|
byte++; |
5544 |
|
|
for (; byte < size; byte++) |
5545 |
|
|
if (nam[byte]) |
5546 |
|
|
return (0); |
5547 |
|
|
return (plen); |
5548 |
|
|
} |
5549 |
|
|
|
5550 |
|
|
/* Print usage, exit(value) if value is non-zero. */ |
5551 |
|
|
void |
5552 |
|
|
usage(int value) |
5553 |
|
|
{ |
5554 |
|
|
fprintf(stderr, |
5555 |
|
|
"usage: ifconfig [-AaC] [interface] [address_family] " |
5556 |
|
|
"[address [dest_address]]\n" |
5557 |
|
|
"\t\t[parameters]\n"); |
5558 |
|
|
exit(value); |
5559 |
|
|
} |
5560 |
|
|
|
5561 |
|
|
void |
5562 |
|
|
getifgroups(void) |
5563 |
|
|
{ |
5564 |
|
|
int len, cnt; |
5565 |
|
|
struct ifgroupreq ifgr; |
5566 |
|
|
struct ifg_req *ifg; |
5567 |
|
|
|
5568 |
|
|
memset(&ifgr, 0, sizeof(ifgr)); |
5569 |
|
|
strlcpy(ifgr.ifgr_name, name, IFNAMSIZ); |
5570 |
|
|
|
5571 |
|
|
if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { |
5572 |
|
|
if (errno == EINVAL || errno == ENOTTY) |
5573 |
|
|
return; |
5574 |
|
|
else |
5575 |
|
|
err(1, "SIOCGIFGROUP"); |
5576 |
|
|
} |
5577 |
|
|
|
5578 |
|
|
len = ifgr.ifgr_len; |
5579 |
|
|
ifgr.ifgr_groups = calloc(len / sizeof(struct ifg_req), |
5580 |
|
|
sizeof(struct ifg_req)); |
5581 |
|
|
if (ifgr.ifgr_groups == NULL) |
5582 |
|
|
err(1, "getifgroups"); |
5583 |
|
|
if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) |
5584 |
|
|
err(1, "SIOCGIFGROUP"); |
5585 |
|
|
|
5586 |
|
|
cnt = 0; |
5587 |
|
|
ifg = ifgr.ifgr_groups; |
5588 |
|
|
for (; ifg && len >= sizeof(struct ifg_req); ifg++) { |
5589 |
|
|
len -= sizeof(struct ifg_req); |
5590 |
|
|
if (strcmp(ifg->ifgrq_group, "all")) { |
5591 |
|
|
if (cnt == 0) |
5592 |
|
|
printf("\tgroups:"); |
5593 |
|
|
cnt++; |
5594 |
|
|
printf(" %s", ifg->ifgrq_group); |
5595 |
|
|
} |
5596 |
|
|
} |
5597 |
|
|
if (cnt) |
5598 |
|
|
printf("\n"); |
5599 |
|
|
|
5600 |
|
|
free(ifgr.ifgr_groups); |
5601 |
|
|
} |
5602 |
|
|
|
5603 |
|
|
#ifndef SMALL |
5604 |
|
|
void |
5605 |
|
|
printifhwfeatures(const char *unused, int show) |
5606 |
|
|
{ |
5607 |
|
|
struct if_data ifrdat; |
5608 |
|
|
|
5609 |
|
|
if (!show) { |
5610 |
|
|
if (showcapsflag) |
5611 |
|
|
usage(1); |
5612 |
|
|
showcapsflag = 1; |
5613 |
|
|
return; |
5614 |
|
|
} |
5615 |
|
|
bzero(&ifrdat, sizeof(ifrdat)); |
5616 |
|
|
ifr.ifr_data = (caddr_t)&ifrdat; |
5617 |
|
|
if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1) |
5618 |
|
|
err(1, "SIOCGIFDATA"); |
5619 |
|
|
printb("\thwfeatures", (u_int)ifrdat.ifi_capabilities, HWFEATURESBITS); |
5620 |
|
|
|
5621 |
|
|
if (ioctl(s, SIOCGIFHARDMTU, (caddr_t)&ifr) != -1) { |
5622 |
|
|
if (ifr.ifr_hardmtu) |
5623 |
|
|
printf(" hardmtu %u", ifr.ifr_hardmtu); |
5624 |
|
|
} |
5625 |
|
|
putchar('\n'); |
5626 |
|
|
} |
5627 |
|
|
#endif |
5628 |
|
|
|
5629 |
|
|
char * |
5630 |
|
|
sec2str(time_t total) |
5631 |
|
|
{ |
5632 |
|
|
static char result[256]; |
5633 |
|
|
char *p = result; |
5634 |
|
|
char *end = &result[sizeof(result)]; |
5635 |
|
|
|
5636 |
|
|
snprintf(p, end - p, "%lld", (long long)total); |
5637 |
|
|
return (result); |
5638 |
|
|
} |
5639 |
|
|
|
5640 |
|
|
/*ARGSUSED*/ |
5641 |
|
|
void |
5642 |
|
|
setiflladdr(const char *addr, int param) |
5643 |
|
|
{ |
5644 |
|
|
struct ether_addr *eap, eabuf; |
5645 |
|
|
|
5646 |
|
|
if (!strcmp(addr, "random")) { |
5647 |
|
|
arc4random_buf(&eabuf, sizeof eabuf); |
5648 |
|
|
/* Non-multicast and claim it is a hardware address */ |
5649 |
|
|
eabuf.ether_addr_octet[0] &= 0xfc; |
5650 |
|
|
eap = &eabuf; |
5651 |
|
|
} else { |
5652 |
|
|
eap = ether_aton(addr); |
5653 |
|
|
if (eap == NULL) { |
5654 |
|
|
warnx("malformed link-level address"); |
5655 |
|
|
return; |
5656 |
|
|
} |
5657 |
|
|
} |
5658 |
|
|
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
5659 |
|
|
ifr.ifr_addr.sa_len = ETHER_ADDR_LEN; |
5660 |
|
|
ifr.ifr_addr.sa_family = AF_LINK; |
5661 |
|
|
bcopy(eap, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN); |
5662 |
|
|
if (ioctl(s, SIOCSIFLLADDR, (caddr_t)&ifr) < 0) |
5663 |
|
|
warn("SIOCSIFLLADDR"); |
5664 |
|
|
} |
5665 |
|
|
|
5666 |
|
|
#ifndef SMALL |
5667 |
|
|
void |
5668 |
|
|
setinstance(const char *id, int param) |
5669 |
|
88 |
{ |
5670 |
|
88 |
const char *errmsg = NULL; |
5671 |
|
|
int rdomainid; |
5672 |
|
|
|
5673 |
|
88 |
rdomainid = strtonum(id, 0, RT_TABLEID_MAX, &errmsg); |
5674 |
✗✓ |
88 |
if (errmsg) |
5675 |
|
|
errx(1, "rdomain %s: %s", id, errmsg); |
5676 |
|
|
|
5677 |
|
88 |
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
5678 |
|
88 |
ifr.ifr_rdomainid = rdomainid; |
5679 |
✗✓ |
88 |
if (ioctl(s, SIOCSIFRDOMAIN, (caddr_t)&ifr) < 0) |
5680 |
|
|
warn("SIOCSIFRDOMAIN"); |
5681 |
|
88 |
} |
5682 |
|
|
#endif |
5683 |
|
|
|
5684 |
|
|
#ifndef SMALL |
5685 |
|
|
void |
5686 |
|
|
setpair(const char *val, int d) |
5687 |
|
|
{ |
5688 |
|
|
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
5689 |
|
|
if ((ifr.ifr_index = if_nametoindex(val)) == 0) { |
5690 |
|
|
errno = ENOENT; |
5691 |
|
|
err(1, "patch %s", val); |
5692 |
|
|
} |
5693 |
|
|
if (ioctl(s, SIOCSIFPAIR, (caddr_t)&ifr) < 0) |
5694 |
|
|
warn("SIOCSIFPAIR"); |
5695 |
|
|
} |
5696 |
|
|
|
5697 |
|
|
void |
5698 |
|
|
unsetpair(const char *val, int d) |
5699 |
|
|
{ |
5700 |
|
|
ifr.ifr_index = 0; |
5701 |
|
|
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); |
5702 |
|
|
if (ioctl(s, SIOCSIFPAIR, (caddr_t)&ifr) < 0) |
5703 |
|
|
warn("SIOCSIFPAIR"); |
5704 |
|
|
} |
5705 |
|
|
#endif |
5706 |
|
|
|
5707 |
|
|
#ifdef SMALL |
5708 |
|
|
void |
5709 |
|
|
setignore(const char *id, int param) |
5710 |
|
|
{ |
5711 |
|
|
/* just digest the command */ |
5712 |
|
|
} |
5713 |
|
|
#endif |