File: | src/sbin/ifconfig/brconfig.c |
Warning: | line 851, column 2 Value stored to 'ifrp' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: brconfig.c,v 1.32 2023/11/23 03:38:34 dlg Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) |
5 | * All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions |
9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. |
15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
24 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
25 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | * POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | |
29 | #ifndef SMALL |
30 | |
31 | #include <stdio.h> |
32 | #include <sys/types.h> |
33 | #include <sys/stdint.h> |
34 | #include <unistd.h> |
35 | #include <stdlib.h> |
36 | #include <sys/socket.h> |
37 | #include <sys/ioctl.h> |
38 | #include <net/if.h> |
39 | #include <netinet/in.h> |
40 | #include <netinet/if_ether.h> |
41 | #include <net/if_bridge.h> |
42 | #include <netdb.h> |
43 | #include <string.h> |
44 | #include <err.h> |
45 | #include <errno(*__errno()).h> |
46 | #include <getopt.h> |
47 | #include <limits.h> |
48 | #include <arpa/inet.h> |
49 | |
50 | #include "ifconfig.h" |
51 | |
52 | void bridge_ifsetflag(const char *, u_int32_t); |
53 | void bridge_ifclrflag(const char *, u_int32_t); |
54 | |
55 | void bridge_list(char *); |
56 | void bridge_cfg(const char *); |
57 | void bridge_badrule(int, char **, int); |
58 | void bridge_showrule(struct ifbrlreq *); |
59 | int bridge_arprule(struct ifbrlreq *, int *, char ***); |
60 | |
61 | #define IFBAFBITS"\020\1STATIC" "\020\1STATIC" |
62 | #define IFBIFBITS"\020\1LEARNING\2DISCOVER\3BLOCKNONIP\4STP\5EDGE\6AUTOEDGE\7PTP\10AUTOPTP\11SPAN\15LOCAL" \ |
63 | "\020\1LEARNING\2DISCOVER\3BLOCKNONIP\4STP\5EDGE\6AUTOEDGE\7PTP\10AUTOPTP\11SPAN\15LOCAL" |
64 | |
65 | #define PV2ID(pv, epri, eaddr)do { epri = pv >> 48; eaddr[0] = pv >> 40; eaddr[ 1] = pv >> 32; eaddr[2] = pv >> 24; eaddr[3] = pv >> 16; eaddr[4] = pv >> 8; eaddr[5] = pv >> 0; } while (0) do { \ |
66 | epri = pv >> 48; \ |
67 | eaddr[0] = pv >> 40; \ |
68 | eaddr[1] = pv >> 32; \ |
69 | eaddr[2] = pv >> 24; \ |
70 | eaddr[3] = pv >> 16; \ |
71 | eaddr[4] = pv >> 8; \ |
72 | eaddr[5] = pv >> 0; \ |
73 | } while (0) |
74 | |
75 | char *stpstates[] = { |
76 | "disabled", |
77 | "listening", |
78 | "learning", |
79 | "forwarding", |
80 | "blocking", |
81 | "discarding" |
82 | }; |
83 | char *stpproto[] = { |
84 | "stp", |
85 | "(none)", |
86 | "rstp", |
87 | }; |
88 | char *stproles[] = { |
89 | "disabled", |
90 | "root", |
91 | "designated", |
92 | "alternate", |
93 | "backup" |
94 | }; |
95 | |
96 | |
97 | void |
98 | setdiscover(const char *val, int d) |
99 | { |
100 | bridge_ifsetflag(val, IFBIF_DISCOVER0x0002); |
101 | } |
102 | |
103 | void |
104 | unsetdiscover(const char *val, int d) |
105 | { |
106 | bridge_ifclrflag(val, IFBIF_DISCOVER0x0002); |
107 | } |
108 | |
109 | void |
110 | setblocknonip(const char *val, int d) |
111 | { |
112 | bridge_ifsetflag(val, IFBIF_BLOCKNONIP0x0004); |
113 | } |
114 | |
115 | void |
116 | unsetblocknonip(const char *val, int d) |
117 | { |
118 | bridge_ifclrflag(val, IFBIF_BLOCKNONIP0x0004); |
119 | } |
120 | |
121 | void |
122 | setlearn(const char *val, int d) |
123 | { |
124 | bridge_ifsetflag(val, IFBIF_LEARNING0x0001); |
125 | } |
126 | |
127 | void |
128 | unsetlearn(const char *val, int d) |
129 | { |
130 | bridge_ifclrflag(val, IFBIF_LEARNING0x0001); |
131 | } |
132 | |
133 | void |
134 | setstp(const char *val, int d) |
135 | { |
136 | bridge_ifsetflag(val, IFBIF_STP0x0008); |
137 | } |
138 | |
139 | void |
140 | unsetstp(const char *val, int d) |
141 | { |
142 | bridge_ifclrflag(val, IFBIF_STP0x0008); |
143 | } |
144 | |
145 | void |
146 | setedge(const char *val, int d) |
147 | { |
148 | bridge_ifsetflag(val, IFBIF_BSTP_EDGE0x0010); |
149 | } |
150 | |
151 | void |
152 | unsetedge(const char *val, int d) |
153 | { |
154 | bridge_ifclrflag(val, IFBIF_BSTP_EDGE0x0010); |
155 | } |
156 | |
157 | void |
158 | setautoedge(const char *val, int d) |
159 | { |
160 | bridge_ifsetflag(val, IFBIF_BSTP_AUTOEDGE0x0020); |
161 | } |
162 | |
163 | void |
164 | unsetautoedge(const char *val, int d) |
165 | { |
166 | bridge_ifclrflag(val, IFBIF_BSTP_AUTOEDGE0x0020); |
167 | } |
168 | |
169 | void |
170 | setptp(const char *val, int d) |
171 | { |
172 | bridge_ifsetflag(val, IFBIF_BSTP_PTP0x0040); |
173 | } |
174 | |
175 | void |
176 | unsetptp(const char *val, int d) |
177 | { |
178 | bridge_ifclrflag(val, IFBIF_BSTP_PTP0x0040); |
179 | } |
180 | |
181 | void |
182 | setautoptp(const char *val, int d) |
183 | { |
184 | bridge_ifsetflag(val, IFBIF_BSTP_AUTOPTP0x0080); |
185 | } |
186 | |
187 | void |
188 | unsetautoptp(const char *val, int d) |
189 | { |
190 | bridge_ifclrflag(val, IFBIF_BSTP_AUTOPTP0x0080); |
191 | } |
192 | |
193 | void |
194 | addlocal(const char *ifsname, int d) |
195 | { |
196 | struct ifbreq breq; |
197 | |
198 | if (strncmp(ifsname, "vether", (sizeof("vether") - 1)) != 0) |
199 | errx(1, "only vether can be local interface"); |
200 | |
201 | /* Add local */ |
202 | strlcpy(breq.ifbr_name, ifname, sizeof(breq.ifbr_name)); |
203 | strlcpy(breq.ifbr_ifsname, ifsname, sizeof(breq.ifbr_ifsname)); |
204 | if (ioctl(sock, SIOCBRDGADDL((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((73))), (caddr_t)&breq) == -1) { |
205 | if (errno(*__errno()) == EEXIST17) |
206 | return; |
207 | else |
208 | err(1, "%s: ioctl SIOCBRDGADDL %s", ifname, ifsname); |
209 | } |
210 | } |
211 | |
212 | void |
213 | bridge_ifsetflag(const char *ifsname, u_int32_t flag) |
214 | { |
215 | struct ifbreq req; |
216 | |
217 | strlcpy(req.ifbr_name, ifname, sizeof(req.ifbr_name)); |
218 | strlcpy(req.ifbr_ifsname, ifsname, sizeof(req.ifbr_ifsname)); |
219 | if (ioctl(sock, SIOCBRDGGIFFLGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbreq) & 0x1fff) << 16) | ((('i')) << 8) | ((62))), (caddr_t)&req) == -1) |
220 | err(1, "%s: ioctl SIOCBRDGGIFFLGS %s", ifname, ifsname); |
221 | |
222 | req.ifbr_ifsflags |= flag & ~IFBIF_RO_MASK0x0f00; |
223 | |
224 | if (ioctl(sock, SIOCBRDGSIFFLGS((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((63))), (caddr_t)&req) == -1) |
225 | err(1, "%s: ioctl SIOCBRDGSIFFLGS %s", ifname, ifsname); |
226 | } |
227 | |
228 | void |
229 | bridge_ifclrflag(const char *ifsname, u_int32_t flag) |
230 | { |
231 | struct ifbreq req; |
232 | |
233 | strlcpy(req.ifbr_name, ifname, sizeof(req.ifbr_name)); |
234 | strlcpy(req.ifbr_ifsname, ifsname, sizeof(req.ifbr_ifsname)); |
235 | |
236 | if (ioctl(sock, SIOCBRDGGIFFLGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbreq) & 0x1fff) << 16) | ((('i')) << 8) | ((62))), (caddr_t)&req) == -1) |
237 | err(1, "%s: ioctl SIOCBRDGGIFFLGS %s", ifname, ifsname); |
238 | |
239 | req.ifbr_ifsflags &= ~(flag | IFBIF_RO_MASK0x0f00); |
240 | |
241 | if (ioctl(sock, SIOCBRDGSIFFLGS((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((63))), (caddr_t)&req) == -1) |
242 | err(1, "%s: ioctl SIOCBRDGSIFFLGS %s", ifname, ifsname); |
243 | } |
244 | |
245 | void |
246 | bridge_flushall(const char *val, int p) |
247 | { |
248 | struct ifbreq req; |
249 | |
250 | strlcpy(req.ifbr_name, ifname, sizeof(req.ifbr_name)); |
251 | req.ifbr_ifsflags = IFBF_FLUSHALL0x1; |
252 | if (ioctl(sock, SIOCBRDGFLUSH((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((72))), &req) == -1) |
253 | err(1, "%s", ifname); |
254 | } |
255 | |
256 | void |
257 | bridge_flush(const char *val, int p) |
258 | { |
259 | struct ifbreq req; |
260 | |
261 | strlcpy(req.ifbr_name, ifname, sizeof(req.ifbr_name)); |
262 | req.ifbr_ifsflags = IFBF_FLUSHDYN0x0; |
263 | if (ioctl(sock, SIOCBRDGFLUSH((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((72))), &req) == -1) |
264 | err(1, "%s", ifname); |
265 | } |
266 | |
267 | void |
268 | bridge_cfg(const char *delim) |
269 | { |
270 | struct ifbropreq ifbp; |
271 | u_int16_t pri; |
272 | u_int8_t ht, fd, ma, hc, proto; |
273 | u_int8_t lladdr[ETHER_ADDR_LEN6]; |
274 | u_int16_t bprio; |
275 | |
276 | strlcpy(ifbp.ifbop_name, ifname, sizeof(ifbp.ifbop_name)); |
277 | if (ioctl(sock, SIOCBRDGGPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbropreq) & 0x1fff) << 16) | ((('i')) << 8) | ((88))), (caddr_t)&ifbp) == -1) { |
278 | if (errno(*__errno()) == ENOTTY25) |
279 | return; |
280 | err(1, "%s SIOCBRDGGPARAM", ifname); |
281 | } |
282 | |
283 | printf("%s", delim); |
284 | pri = ifbp.ifbop_priority; |
285 | ht = ifbp.ifbop_hellotime; |
286 | fd = ifbp.ifbop_fwddelay; |
287 | ma = ifbp.ifbop_maxage; |
288 | hc = ifbp.ifbop_holdcount; |
289 | proto = ifbp.ifbop_protocol; |
290 | |
291 | printf("priority %u hellotime %u fwddelay %u maxage %u " |
292 | "holdcnt %u proto %s\n", pri, ht, fd, ma, hc, stpproto[proto]); |
293 | |
294 | if (aflag) |
295 | return; |
296 | |
297 | PV2ID(ifbp.ifbop_desg_bridge, bprio, lladdr)do { bprio = ifbp.ifbop_desg_bridge >> 48; lladdr[0] = ifbp .ifbop_desg_bridge >> 40; lladdr[1] = ifbp.ifbop_desg_bridge >> 32; lladdr[2] = ifbp.ifbop_desg_bridge >> 24; lladdr[3] = ifbp.ifbop_desg_bridge >> 16; lladdr[4] = ifbp .ifbop_desg_bridge >> 8; lladdr[5] = ifbp.ifbop_desg_bridge >> 0; } while (0); |
298 | printf("\tdesignated: id %s priority %u\n", |
299 | ether_ntoa((struct ether_addr *)lladdr), bprio); |
300 | |
301 | if (ifbp.ifbop_root_bridge == ifbp.ifbop_desg_bridge) |
302 | return; |
303 | |
304 | PV2ID(ifbp.ifbop_root_bridge, bprio, lladdr)do { bprio = ifbp.ifbop_root_bridge >> 48; lladdr[0] = ifbp .ifbop_root_bridge >> 40; lladdr[1] = ifbp.ifbop_root_bridge >> 32; lladdr[2] = ifbp.ifbop_root_bridge >> 24; lladdr[3] = ifbp.ifbop_root_bridge >> 16; lladdr[4] = ifbp .ifbop_root_bridge >> 8; lladdr[5] = ifbp.ifbop_root_bridge >> 0; } while (0); |
305 | printf("\troot: id %s priority %u ifcost %u port %u\n", |
306 | ether_ntoa((struct ether_addr *)lladdr), bprio, |
307 | ifbp.ifbop_root_path_cost, ifbp.ifbop_root_port & 0xfff); |
308 | } |
309 | |
310 | void |
311 | bridge_list(char *delim) |
312 | { |
313 | struct ifbreq *reqp; |
314 | struct ifbifconf bifc; |
315 | int i, len = 8192; |
316 | char buf[sizeof(reqp->ifbr_ifsname) + 1], *inbuf = NULL((void *)0), *inb; |
317 | |
318 | while (1) { |
319 | bifc.ifbic_len = len; |
320 | inb = realloc(inbuf, len); |
321 | if (inb == NULL((void *)0)) |
322 | err(1, "malloc"); |
323 | bifc.ifbic_bufifbic_ifbicu.ifbicu_buf = inbuf = inb; |
324 | strlcpy(bifc.ifbic_name, ifname, sizeof(bifc.ifbic_name)); |
325 | if (ioctl(sock, SIOCBRDGIFS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbreq) & 0x1fff) << 16) | ((('i')) << 8) | ((66))), &bifc) == -1) { |
326 | if (errno(*__errno()) == ENOTTY25) |
327 | return; |
328 | err(1, "%s SIOCBRDGIFS", ifname); |
329 | } |
330 | if (bifc.ifbic_len + sizeof(*reqp) < len) |
331 | break; |
332 | len *= 2; |
333 | } |
334 | for (i = 0; i < bifc.ifbic_len / sizeof(*reqp); i++) { |
335 | reqp = bifc.ifbic_reqifbic_ifbicu.ifbicu_req + i; |
336 | strlcpy(buf, reqp->ifbr_ifsname, sizeof(buf)); |
337 | printf("%s%s ", delim, buf); |
338 | printb("flags", reqp->ifbr_ifsflags, IFBIFBITS"\020\1LEARNING\2DISCOVER\3BLOCKNONIP\4STP\5EDGE\6AUTOEDGE\7PTP\10AUTOPTP\11SPAN\15LOCAL"); |
339 | printf("\n"); |
340 | if (reqp->ifbr_ifsflags & IFBIF_SPAN0x0100) |
341 | continue; |
342 | printf("\t\t"); |
343 | printf("port %u ifpriority %u ifcost %u", |
344 | reqp->ifbr_portno, reqp->ifbr_priority, |
345 | reqp->ifbr_path_cost); |
346 | if (reqp->ifbr_protected) { |
347 | int v; |
348 | |
349 | v = ffs(reqp->ifbr_protected); |
350 | printf(" protected %u", v); |
351 | while (++v < 32) { |
352 | if ((1 << (v - 1)) & reqp->ifbr_protected) |
353 | printf(",%u", v); |
354 | } |
355 | } |
356 | if (reqp->ifbr_ifsflags & IFBIF_STP0x0008) |
357 | printf(" %s role %s", |
358 | stpstates[reqp->ifbr_state], |
359 | stproles[reqp->ifbr_role]); |
360 | printf("\n"); |
361 | bridge_rules(buf, 1); |
362 | } |
363 | free(bifc.ifbic_bufifbic_ifbicu.ifbicu_buf); |
364 | } |
365 | |
366 | void |
367 | bridge_add(const char *ifn, int d) |
368 | { |
369 | struct ifbreq req; |
370 | |
371 | strlcpy(req.ifbr_name, ifname, sizeof(req.ifbr_name)); |
372 | strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); |
373 | if (ioctl(sock, SIOCBRDGADD((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((60))), &req) == -1) { |
374 | if (errno(*__errno()) == EEXIST17) |
375 | return; |
376 | err(1, "%s: %s", ifname, ifn); |
377 | } |
378 | } |
379 | |
380 | void |
381 | bridge_delete(const char *ifn, int d) |
382 | { |
383 | struct ifbreq req; |
384 | |
385 | strlcpy(req.ifbr_name, ifname, sizeof(req.ifbr_name)); |
386 | strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); |
387 | if (ioctl(sock, SIOCBRDGDEL((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((61))), &req) == -1) |
388 | err(1, "%s: %s", ifname, ifn); |
389 | } |
390 | |
391 | void |
392 | bridge_addspan(const char *ifn, int d) |
393 | { |
394 | struct ifbreq req; |
395 | |
396 | strlcpy(req.ifbr_name, ifname, sizeof(req.ifbr_name)); |
397 | strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); |
398 | if (ioctl(sock, SIOCBRDGADDS((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((65))), &req) == -1) { |
399 | if (errno(*__errno()) == EEXIST17) |
400 | return; |
401 | err(1, "%s: %s", ifname, ifn); |
402 | } |
403 | } |
404 | |
405 | void |
406 | bridge_delspan(const char *ifn, int d) |
407 | { |
408 | struct ifbreq req; |
409 | |
410 | strlcpy(req.ifbr_name, ifname, sizeof(req.ifbr_name)); |
411 | strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); |
412 | if (ioctl(sock, SIOCBRDGDELS((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((66))), &req) == -1) |
413 | err(1, "%s: %s", ifname, ifn); |
414 | } |
415 | |
416 | void |
417 | bridge_timeout(const char *arg, int d) |
418 | { |
419 | struct ifbrparam bp; |
420 | const char *errstr; |
421 | |
422 | bp.ifbrp_ctimeifbrp_ifbrpu.ifbrpu_ctime = strtonum(arg, 0, UINT32_MAX0xffffffffU, &errstr); |
423 | if (errstr) |
424 | err(1, "timeout %s is: %s", arg, errstr); |
425 | |
426 | strlcpy(bp.ifbrp_name, ifname, sizeof(bp.ifbrp_name)); |
427 | if (ioctl(sock, SIOCBRDGSTO((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((69))), (caddr_t)&bp) == -1) |
428 | err(1, "%s", ifname); |
429 | } |
430 | |
431 | void |
432 | bridge_maxage(const char *arg, int d) |
433 | { |
434 | struct ifbrparam bp; |
435 | const char *errstr; |
436 | |
437 | bp.ifbrp_maxageifbrp_ifbrpu.ifbrpu_maxage = strtonum(arg, 0, UINT8_MAX0xff, &errstr); |
438 | if (errstr) |
439 | errx(1, "maxage %s is: %s", arg, errstr); |
440 | |
441 | strlcpy(bp.ifbrp_name, ifname, sizeof(bp.ifbrp_name)); |
442 | if (ioctl(sock, SIOCBRDGSMA((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((83))), (caddr_t)&bp) == -1) |
443 | err(1, "%s", ifname); |
444 | } |
445 | |
446 | void |
447 | bridge_priority(const char *arg, int d) |
448 | { |
449 | struct ifbrparam bp; |
450 | const char *errstr; |
451 | |
452 | bp.ifbrp_prioifbrp_ifbrpu.ifbrpu_prio = strtonum(arg, 0, UINT16_MAX0xffff, &errstr); |
453 | if (errstr) |
454 | errx(1, "spanpriority %s is: %s", arg, errstr); |
455 | |
456 | strlcpy(bp.ifbrp_name, ifname, sizeof(bp.ifbrp_name)); |
457 | if (ioctl(sock, SIOCBRDGSPRI((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((80))), (caddr_t)&bp) == -1) |
458 | err(1, "%s", ifname); |
459 | } |
460 | |
461 | void |
462 | bridge_protect(const char *ifsname, const char *val) |
463 | { |
464 | struct ifbreq breq; |
465 | unsigned long v; |
466 | char *optlist, *str; |
467 | const char *errstr; |
468 | |
469 | strlcpy(breq.ifbr_name, ifname, sizeof(breq.ifbr_name)); |
470 | strlcpy(breq.ifbr_ifsname, ifsname, sizeof(breq.ifbr_ifsname)); |
471 | breq.ifbr_protected = 0; |
472 | |
473 | /* We muck with the string, so copy it. */ |
474 | optlist = strdup(val); |
475 | if (optlist == NULL((void *)0)) |
476 | err(1, "strdup"); |
477 | |
478 | str = strtok(optlist, ","); |
479 | while (str != NULL((void *)0)) { |
480 | v = strtonum(str, 1, 31, &errstr); |
481 | if (errstr) |
482 | err(1, "protected domain %s is: %s", str, errstr); |
483 | breq.ifbr_protected |= (1 << (v - 1)); |
484 | str = strtok(NULL((void *)0), ","); |
485 | } |
486 | |
487 | if (ioctl(sock, SIOCBRDGSIFPROT((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((74))), (caddr_t)&breq) == -1) |
488 | err(1, "%s: %s", ifname, val); |
489 | |
490 | free(optlist); |
491 | } |
492 | |
493 | void |
494 | bridge_unprotect(const char *ifsname, int d) |
495 | { |
496 | struct ifbreq breq; |
497 | |
498 | strlcpy(breq.ifbr_name, ifname, sizeof(breq.ifbr_name)); |
499 | strlcpy(breq.ifbr_ifsname, ifsname, sizeof(breq.ifbr_ifsname)); |
500 | |
501 | breq.ifbr_protected = 0; |
502 | |
503 | if (ioctl(sock, SIOCBRDGSIFPROT((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((74))), (caddr_t)&breq) == -1) |
504 | err(1, "%s: %d", ifname, 0); |
505 | } |
506 | |
507 | void |
508 | bridge_proto(const char *arg, int d) |
509 | { |
510 | struct ifbrparam bp; |
511 | int i, proto = -1; |
512 | |
513 | for (i = 0; i <= BSTP_PROTO_MAX0x02; i++) |
514 | if (strcmp(arg, stpproto[i]) == 0) { |
515 | proto = i; |
516 | break; |
517 | } |
518 | if (proto == -1) |
519 | errx(1, "invalid arg for proto: %s", arg); |
520 | |
521 | strlcpy(bp.ifbrp_name, ifname, sizeof(bp.ifbrp_name)); |
522 | bp.ifbrp_prioifbrp_ifbrpu.ifbrpu_prio = proto; |
523 | if (ioctl(sock, SIOCBRDGSPROTO((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((90))), (caddr_t)&bp) == -1) |
524 | err(1, "%s", ifname); |
525 | } |
526 | |
527 | void |
528 | bridge_fwddelay(const char *arg, int d) |
529 | { |
530 | struct ifbrparam bp; |
531 | const char *errstr; |
532 | |
533 | bp.ifbrp_fwddelayifbrp_ifbrpu.ifbrpu_fwddelay = strtonum(arg, 0, UINT8_MAX0xff, &errstr); |
534 | if (errstr) |
535 | errx(1, "fwddelay %s is: %s", arg, errstr); |
536 | |
537 | strlcpy(bp.ifbrp_name, ifname, sizeof(bp.ifbrp_name)); |
538 | |
539 | if (ioctl(sock, SIOCBRDGSFD((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((82))), (caddr_t)&bp) == -1) |
540 | err(1, "%s", ifname); |
541 | } |
542 | |
543 | void |
544 | bridge_hellotime(const char *arg, int d) |
545 | { |
546 | struct ifbrparam bp; |
547 | const char *errstr; |
548 | |
549 | bp.ifbrp_hellotimeifbrp_ifbrpu.ifbrpu_hellotime = strtonum(arg, 0, UINT8_MAX0xff, &errstr); |
550 | if (errstr) |
551 | errx(1, "hellotime %s is: %s", arg, errstr); |
552 | |
553 | strlcpy(bp.ifbrp_name, ifname, sizeof(bp.ifbrp_name)); |
554 | |
555 | if (ioctl(sock, SIOCBRDGSHT((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((81))), (caddr_t)&bp) == -1) |
556 | err(1, "%s", ifname); |
557 | } |
558 | |
559 | void |
560 | bridge_maxaddr(const char *arg, int d) |
561 | { |
562 | struct ifbrparam bp; |
563 | const char *errstr; |
564 | |
565 | bp.ifbrp_csizeifbrp_ifbrpu.ifbrpu_csize = strtonum(arg, 0, UINT32_MAX0xffffffffU, &errstr); |
566 | if (errstr) |
567 | errx(1, "maxaddr %s is: %s", arg, errstr); |
568 | |
569 | strlcpy(bp.ifbrp_name, ifname, sizeof(bp.ifbrp_name)); |
570 | if (ioctl(sock, SIOCBRDGSCACHE((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((64))), (caddr_t)&bp) == -1) |
571 | err(1, "%s", ifname); |
572 | } |
573 | |
574 | void |
575 | bridge_deladdr(const char *addr, int d) |
576 | { |
577 | struct ifbareq ifba; |
578 | struct ether_addr *ea; |
579 | |
580 | strlcpy(ifba.ifba_name, ifname, sizeof(ifba.ifba_name)); |
581 | ea = ether_aton(addr); |
582 | if (ea == NULL((void *)0)) |
583 | err(1, "Invalid address: %s", addr); |
584 | |
585 | bcopy(ea, &ifba.ifba_dst, sizeof(struct ether_addr)); |
586 | |
587 | if (ioctl(sock, SIOCBRDGDADDR((unsigned long)0x80000000 | ((sizeof(struct ifbareq) & 0x1fff ) << 16) | ((('i')) << 8) | ((71))), &ifba) == -1) |
588 | err(1, "%s: %s", ifname, addr); |
589 | } |
590 | |
591 | void |
592 | bridge_ifprio(const char *ifsname, const char *val) |
593 | { |
594 | struct ifbreq breq; |
595 | const char *errstr; |
596 | |
597 | breq.ifbr_priority = strtonum(val, 0, UINT8_MAX0xff, &errstr); |
598 | if (errstr) |
599 | errx(1, "ifpriority %s is: %s", val, errstr); |
600 | |
601 | strlcpy(breq.ifbr_name, ifname, sizeof(breq.ifbr_name)); |
602 | strlcpy(breq.ifbr_ifsname, ifsname, sizeof(breq.ifbr_ifsname)); |
603 | |
604 | if (ioctl(sock, SIOCBRDGSIFPRIO((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((84))), (caddr_t)&breq) == -1) |
605 | err(1, "%s: %s", ifname, val); |
606 | } |
607 | |
608 | void |
609 | bridge_ifcost(const char *ifsname, const char *val) |
610 | { |
611 | struct ifbreq breq; |
612 | const char *errstr; |
613 | |
614 | breq.ifbr_path_cost = strtonum(val, 0, UINT32_MAX0xffffffffU, &errstr); |
615 | if (errstr) |
616 | errx(1, "ifcost %s is: %s", val, errstr); |
617 | |
618 | strlcpy(breq.ifbr_name, ifname, sizeof(breq.ifbr_name)); |
619 | strlcpy(breq.ifbr_ifsname, ifsname, sizeof(breq.ifbr_ifsname)); |
620 | |
621 | if (ioctl(sock, SIOCBRDGSIFCOST((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((85))), (caddr_t)&breq) == -1) |
622 | err(1, "%s: %s", ifname, val); |
623 | } |
624 | |
625 | void |
626 | bridge_noifcost(const char *ifsname, int d) |
627 | { |
628 | struct ifbreq breq; |
629 | |
630 | strlcpy(breq.ifbr_name, ifname, sizeof(breq.ifbr_name)); |
631 | strlcpy(breq.ifbr_ifsname, ifsname, sizeof(breq.ifbr_ifsname)); |
632 | |
633 | breq.ifbr_path_cost = 0; |
634 | |
635 | if (ioctl(sock, SIOCBRDGSIFCOST((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((85))), (caddr_t)&breq) == -1) |
636 | err(1, "%s", ifname); |
637 | } |
638 | |
639 | void |
640 | bridge_addaddr(const char *ifsname, const char *addr) |
641 | { |
642 | struct ifbareq ifba; |
643 | struct ether_addr *ea; |
644 | |
645 | strlcpy(ifba.ifba_name, ifname, sizeof(ifba.ifba_name)); |
646 | strlcpy(ifba.ifba_ifsname, ifsname, sizeof(ifba.ifba_ifsname)); |
647 | |
648 | ea = ether_aton(addr); |
649 | if (ea == NULL((void *)0)) |
650 | errx(1, "Invalid address: %s", addr); |
651 | |
652 | bcopy(ea, &ifba.ifba_dst, sizeof(struct ether_addr)); |
653 | ifba.ifba_flags = IFBAF_STATIC0x01; |
654 | |
655 | if (ioctl(sock, SIOCBRDGSADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbareq) & 0x1fff) << 16) | ((('i')) << 8) | ((68))), &ifba) == -1) |
656 | err(1, "%s: %s", ifname, addr); |
657 | } |
658 | |
659 | void |
660 | bridge_addendpoint(const char *endpoint, const char *addr) |
661 | { |
662 | struct ifbareq ifba; |
663 | struct ether_addr *ea; |
664 | struct addrinfo *res; |
665 | int ecode; |
666 | |
667 | /* should we handle ports? */ |
668 | ecode = getaddrinfo(endpoint, NULL((void *)0), NULL((void *)0), &res); |
669 | if (ecode != 0) { |
670 | errx(1, "%s endpoint %s: %s", ifname, endpoint, |
671 | gai_strerror(ecode)); |
672 | } |
673 | if (res->ai_addrlen > sizeof(ifba.ifba_dstsa)) |
674 | errx(1, "%s: addrlen > dstsa", __func__); |
675 | |
676 | ea = ether_aton(addr); |
677 | if (ea == NULL((void *)0)) { |
678 | errx(1, "%s endpoint %s %s: invalid Ethernet address", |
679 | ifname, endpoint, addr); |
680 | } |
681 | |
682 | memset(&ifba, 0, sizeof(ifba)); |
683 | strlcpy(ifba.ifba_name, ifname, sizeof(ifba.ifba_name)); |
684 | strlcpy(ifba.ifba_ifsname, ifname, sizeof(ifba.ifba_ifsname)); |
685 | memcpy(&ifba.ifba_dst, ea, sizeof(struct ether_addr)); |
686 | memcpy(&ifba.ifba_dstsa, res->ai_addr, res->ai_addrlen); |
687 | ifba.ifba_flags = IFBAF_STATIC0x01; |
688 | |
689 | freeaddrinfo(res); |
690 | |
691 | if (ioctl(sock, SIOCBRDGSADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbareq) & 0x1fff) << 16) | ((('i')) << 8) | ((68))), &ifba) == -1) |
692 | err(1, "%s endpoint %s %s", ifname, endpoint, addr); |
693 | } |
694 | |
695 | void |
696 | bridge_addrs(const char *delim, int d) |
697 | { |
698 | char dstaddr[NI_MAXHOST256]; |
699 | char dstport[NI_MAXSERV32]; |
700 | const int niflag = NI_NUMERICHOST1|NI_DGRAM16; |
701 | struct ifbaconf ifbac; |
702 | struct ifbareq *ifba; |
703 | char *inbuf = NULL((void *)0), buf[sizeof(ifba->ifba_ifsname) + 1], *inb; |
704 | struct sockaddr *sa; |
705 | int i, len = 8192; |
706 | |
707 | /* ifconfig will call us with the argv of the command */ |
708 | if (strcmp(delim, "addr") == 0) |
709 | delim = ""; |
710 | |
711 | while (1) { |
712 | ifbac.ifbac_len = len; |
713 | inb = realloc(inbuf, len); |
714 | if (inb == NULL((void *)0)) |
715 | err(1, "malloc"); |
716 | ifbac.ifbac_bufifbac_ifbacu.ifbacu_buf = inbuf = inb; |
717 | strlcpy(ifbac.ifbac_name, ifname, sizeof(ifbac.ifbac_name)); |
718 | if (ioctl(sock, SIOCBRDGRTS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbaconf) & 0x1fff) << 16) | ((('i')) << 8) | ((67))), &ifbac) == -1) { |
719 | if (errno(*__errno()) == ENETDOWN50) |
720 | return; |
721 | err(1, "%s", ifname); |
722 | } |
723 | if (ifbac.ifbac_len + sizeof(*ifba) < len) |
724 | break; |
725 | len *= 2; |
726 | } |
727 | |
728 | for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { |
729 | ifba = ifbac.ifbac_reqifbac_ifbacu.ifbacu_req + i; |
730 | strlcpy(buf, ifba->ifba_ifsname, sizeof(buf)); |
731 | printf("%s%s %s %u ", delim, ether_ntoa(&ifba->ifba_dst), |
732 | buf, ifba->ifba_age); |
733 | sa = (struct sockaddr *)&ifba->ifba_dstsa; |
734 | printb("flags", ifba->ifba_flags, IFBAFBITS"\020\1STATIC"); |
735 | if (sa->sa_family != AF_UNSPEC0 && |
736 | getnameinfo(sa, sa->sa_len, |
737 | dstaddr, sizeof(dstaddr), |
738 | dstport, sizeof(dstport), niflag) == 0) |
739 | printf(" tunnel %s:%s", dstaddr, dstport); |
740 | printf("\n"); |
741 | } |
742 | free(inbuf); |
743 | } |
744 | |
745 | void |
746 | bridge_holdcnt(const char *value, int d) |
747 | { |
748 | struct ifbrparam bp; |
749 | const char *errstr; |
750 | |
751 | bp.ifbrp_txhcifbrp_ifbrpu.ifbrpu_txhc = strtonum(value, 0, UINT8_MAX0xff, &errstr); |
752 | if (errstr) |
753 | err(1, "holdcnt %s is: %s", value, errstr); |
754 | |
755 | strlcpy(bp.ifbrp_name, ifname, sizeof(bp.ifbrp_name)); |
756 | if (ioctl(sock, SIOCBRDGSTXHC((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((89))), (caddr_t)&bp) == -1) |
757 | err(1, "%s", ifname); |
758 | } |
759 | |
760 | /* |
761 | * Check to make sure interface is really a bridge interface. |
762 | */ |
763 | int |
764 | is_bridge() |
765 | { |
766 | struct ifbaconf ifbac; |
767 | |
768 | ifbac.ifbac_len = 0; |
769 | strlcpy(ifbac.ifbac_name, ifname, sizeof(ifbac.ifbac_name)); |
770 | if (ioctl(sock, SIOCBRDGRTS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbaconf) & 0x1fff) << 16) | ((('i')) << 8) | ((67))), (caddr_t)&ifbac) == -1) { |
771 | if (errno(*__errno()) == ENETDOWN50) |
772 | return (1); |
773 | return (0); |
774 | } |
775 | return (1); |
776 | } |
777 | |
778 | /* no tpmr(4) specific ioctls, name is enough if ifconfig.c:printif() passed */ |
779 | int |
780 | is_tpmr(void) |
781 | { |
782 | return (strncmp(ifname, "tpmr", sizeof("tpmr") - 1) == 0); |
783 | } |
784 | |
785 | void |
786 | bridge_status(void) |
787 | { |
788 | struct ifbrparam bp1, bp2; |
789 | |
790 | if (is_tpmr()) { |
791 | bridge_list("\t"); |
792 | return; |
793 | } |
794 | |
795 | if (!is_bridge()) |
796 | return; |
797 | |
798 | bridge_cfg("\t"); |
799 | bridge_list("\t"); |
800 | |
801 | if (aflag && !ifaliases) |
802 | return; |
803 | |
804 | strlcpy(bp1.ifbrp_name, ifname, sizeof(bp1.ifbrp_name)); |
805 | if (ioctl(sock, SIOCBRDGGCACHE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((65))), (caddr_t)&bp1) == -1) |
806 | return; |
807 | |
808 | strlcpy(bp2.ifbrp_name, ifname, sizeof(bp2.ifbrp_name)); |
809 | if (ioctl(sock, SIOCBRDGGTO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((70))), (caddr_t)&bp2) == -1) |
810 | return; |
811 | |
812 | printf("\tAddresses (max cache: %u, timeout: %u):\n", |
813 | bp1.ifbrp_csizeifbrp_ifbrpu.ifbrpu_csize, bp2.ifbrp_ctimeifbrp_ifbrpu.ifbrpu_ctime); |
814 | |
815 | bridge_addrs("\t\t", 0); |
816 | } |
817 | |
818 | void |
819 | bridge_flushrule(const char *ifsname, int d) |
820 | { |
821 | struct ifbrlreq req; |
822 | |
823 | strlcpy(req.ifbr_name, ifname, sizeof(req.ifbr_name)); |
824 | strlcpy(req.ifbr_ifsname, ifsname, sizeof(req.ifbr_ifsname)); |
825 | if (ioctl(sock, SIOCBRDGFRL((unsigned long)0x80000000 | ((sizeof(struct ifbrlreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((78))), &req) == -1) |
826 | err(1, "%s: %s", ifname, ifsname); |
827 | } |
828 | |
829 | void |
830 | bridge_rules(const char *ifsname, int usetab) |
831 | { |
832 | char *inbuf = NULL((void *)0), *inb; |
833 | struct ifbrlconf ifc; |
834 | struct ifbrlreq *ifrp; |
835 | int len = 8192, i; |
836 | |
837 | while (1) { |
838 | ifc.ifbrl_len = len; |
839 | inb = realloc(inbuf, len); |
840 | if (inb == NULL((void *)0)) |
841 | err(1, "malloc"); |
842 | ifc.ifbrl_bufifbrl_ifbrlu.ifbrlu_buf = inbuf = inb; |
843 | strlcpy(ifc.ifbrl_name, ifname, sizeof(ifc.ifbrl_name)); |
844 | strlcpy(ifc.ifbrl_ifsname, ifsname, sizeof(ifc.ifbrl_ifsname)); |
845 | if (ioctl(sock, SIOCBRDGGRL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbrlconf) & 0x1fff) << 16) | ((('i')) << 8) | ((79))), &ifc) == -1) |
846 | err(1, "ioctl(SIOCBRDGGRL)"); |
847 | if (ifc.ifbrl_len + sizeof(*ifrp) < len) |
848 | break; |
849 | len *= 2; |
850 | } |
851 | ifrp = ifc.ifbrl_reqifbrl_ifbrlu.ifbrlu_req; |
Value stored to 'ifrp' is never read | |
852 | for (i = 0; i < ifc.ifbrl_len; i += sizeof(*ifrp)) { |
853 | ifrp = (struct ifbrlreq *)((caddr_t)ifc.ifbrl_reqifbrl_ifbrlu.ifbrlu_req + i); |
854 | |
855 | if (usetab) |
856 | printf("\t"); |
857 | |
858 | bridge_showrule(ifrp); |
859 | } |
860 | } |
861 | |
862 | void |
863 | bridge_showrule(struct ifbrlreq *r) |
864 | { |
865 | if (r->ifbr_action == BRL_ACTION_BLOCK0x01) |
866 | printf("block "); |
867 | else if (r->ifbr_action == BRL_ACTION_PASS0x02) |
868 | printf("pass "); |
869 | else |
870 | printf("[neither block nor pass?]\n"); |
871 | |
872 | if ((r->ifbr_flags & (BRL_FLAG_IN0x08 | BRL_FLAG_OUT0x04)) == |
873 | (BRL_FLAG_IN0x08 | BRL_FLAG_OUT0x04)) |
874 | printf("in/out "); |
875 | else if (r->ifbr_flags & BRL_FLAG_IN0x08) |
876 | printf("in "); |
877 | else if (r->ifbr_flags & BRL_FLAG_OUT0x04) |
878 | printf("out "); |
879 | else |
880 | printf("[neither in nor out?]\n"); |
881 | |
882 | printf("on %s", r->ifbr_ifsname); |
883 | |
884 | if (r->ifbr_flags & BRL_FLAG_SRCVALID0x02) |
885 | printf(" src %s", ether_ntoa(&r->ifbr_src)); |
886 | if (r->ifbr_flags & BRL_FLAG_DSTVALID0x01) |
887 | printf(" dst %s", ether_ntoa(&r->ifbr_dst)); |
888 | if (r->ifbr_tagname[0]) |
889 | printf(" tag %s", r->ifbr_tagname); |
890 | |
891 | if (r->ifbr_arpf.brla_flags & BRLA_ARP0x01) |
892 | printf(" arp"); |
893 | if (r->ifbr_arpf.brla_flags & BRLA_RARP0x02) |
894 | printf(" rarp"); |
895 | if (r->ifbr_arpf.brla_op == ARPOP_REQUEST1 || |
896 | r->ifbr_arpf.brla_op == ARPOP_REVREQUEST3) |
897 | printf(" request"); |
898 | if (r->ifbr_arpf.brla_op == ARPOP_REPLY2 || |
899 | r->ifbr_arpf.brla_op == ARPOP_REVREPLY4) |
900 | printf(" reply"); |
901 | if (r->ifbr_arpf.brla_flags & BRLA_SHA0x10) |
902 | printf(" sha %s", ether_ntoa(&r->ifbr_arpf.brla_sha)); |
903 | if (r->ifbr_arpf.brla_flags & BRLA_THA0x40) |
904 | printf(" tha %s", ether_ntoa(&r->ifbr_arpf.brla_tha)); |
905 | if (r->ifbr_arpf.brla_flags & BRLA_SPA0x20) |
906 | printf(" spa %s", inet_ntoa(r->ifbr_arpf.brla_spa)); |
907 | if (r->ifbr_arpf.brla_flags & BRLA_TPA0x80) |
908 | printf(" tpa %s", inet_ntoa(r->ifbr_arpf.brla_tpa)); |
909 | |
910 | printf("\n"); |
911 | } |
912 | |
913 | /* |
914 | * Parse a rule definition and send it upwards. |
915 | * |
916 | * Syntax: |
917 | * {block|pass} {in|out|in/out} on {ifs} [src {mac}] [dst {mac}] |
918 | */ |
919 | int |
920 | bridge_rule(int targc, char **targv, int ln) |
921 | { |
922 | char **argv = targv; |
923 | int argc = targc; |
924 | struct ifbrlreq rule; |
925 | struct ether_addr *ea, *dea; |
926 | |
927 | if (argc == 0) { |
928 | warnx("invalid rule"); |
929 | return (1); |
930 | } |
931 | bzero(&rule, sizeof(rule)); |
932 | strlcpy(rule.ifbr_name, ifname, sizeof(rule.ifbr_name)); |
933 | |
934 | if (strcmp(argv[0], "block") == 0) |
935 | rule.ifbr_action = BRL_ACTION_BLOCK0x01; |
936 | else if (strcmp(argv[0], "pass") == 0) |
937 | rule.ifbr_action = BRL_ACTION_PASS0x02; |
938 | else |
939 | goto bad_rule; |
940 | argc--; argv++; |
941 | |
942 | if (argc == 0) { |
943 | bridge_badrule(targc, targv, ln); |
944 | return (1); |
945 | } |
946 | if (strcmp(argv[0], "in") == 0) |
947 | rule.ifbr_flags |= BRL_FLAG_IN0x08; |
948 | else if (strcmp(argv[0], "out") == 0) |
949 | rule.ifbr_flags |= BRL_FLAG_OUT0x04; |
950 | else if (strcmp(argv[0], "in/out") == 0) |
951 | rule.ifbr_flags |= BRL_FLAG_IN0x08 | BRL_FLAG_OUT0x04; |
952 | else if (strcmp(argv[0], "on") == 0) { |
953 | rule.ifbr_flags |= BRL_FLAG_IN0x08 | BRL_FLAG_OUT0x04; |
954 | argc++; argv--; |
955 | } else |
956 | goto bad_rule; |
957 | argc--; argv++; |
958 | |
959 | if (argc == 0 || strcmp(argv[0], "on")) |
960 | goto bad_rule; |
961 | argc--; argv++; |
962 | |
963 | if (argc == 0) |
964 | goto bad_rule; |
965 | strlcpy(rule.ifbr_ifsname, argv[0], sizeof(rule.ifbr_ifsname)); |
966 | argc--; argv++; |
967 | |
968 | while (argc) { |
969 | dea = NULL((void *)0); |
970 | if (strcmp(argv[0], "dst") == 0) { |
971 | if (rule.ifbr_flags & BRL_FLAG_DSTVALID0x01) |
972 | goto bad_rule; |
973 | rule.ifbr_flags |= BRL_FLAG_DSTVALID0x01; |
974 | dea = &rule.ifbr_dst; |
975 | argc--; argv++; |
976 | } else if (strcmp(argv[0], "src") == 0) { |
977 | if (rule.ifbr_flags & BRL_FLAG_SRCVALID0x02) |
978 | goto bad_rule; |
979 | rule.ifbr_flags |= BRL_FLAG_SRCVALID0x02; |
980 | dea = &rule.ifbr_src; |
981 | argc--; argv++; |
982 | } else if (strcmp(argv[0], "tag") == 0) { |
983 | if (argc < 2) { |
984 | warnx("missing tag name"); |
985 | goto bad_rule; |
986 | } |
987 | if (rule.ifbr_tagname[0]) { |
988 | warnx("tag already defined"); |
989 | goto bad_rule; |
990 | } |
991 | argc--; argv++; |
992 | if (strlcpy(rule.ifbr_tagname, argv[0], |
993 | PF_TAG_NAME_SIZE64) > PF_TAG_NAME_SIZE64) { |
994 | warnx("tag name '%s' too long", argv[0]); |
995 | goto bad_rule; |
996 | } |
997 | argc--; argv++; |
998 | } else if (strcmp(argv[0], "arp") == 0) { |
999 | rule.ifbr_arpf.brla_flags |= BRLA_ARP0x01; |
1000 | argc--; argv++; |
1001 | if (bridge_arprule(&rule, &argc, &argv) == -1) |
1002 | goto bad_rule; |
1003 | } else if (strcmp(argv[0], "rarp") == 0) { |
1004 | rule.ifbr_arpf.brla_flags |= BRLA_RARP0x02; |
1005 | argc--; argv++; |
1006 | if (bridge_arprule(&rule, &argc, &argv) == -1) |
1007 | goto bad_rule; |
1008 | } else |
1009 | goto bad_rule; |
1010 | |
1011 | if (dea != NULL((void *)0)) { |
1012 | if (argc == 0) |
1013 | goto bad_rule; |
1014 | ea = ether_aton(argv[0]); |
1015 | if (ea == NULL((void *)0)) { |
1016 | warnx("invalid address: %s", argv[0]); |
1017 | return (1); |
1018 | } |
1019 | bcopy(ea, dea, sizeof(*dea)); |
1020 | argc--; argv++; |
1021 | } |
1022 | } |
1023 | |
1024 | if (ioctl(sock, SIOCBRDGARL((unsigned long)0x80000000 | ((sizeof(struct ifbrlreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((77))), &rule) == -1) { |
1025 | warn("%s", ifname); |
1026 | return (1); |
1027 | } |
1028 | return (0); |
1029 | |
1030 | bad_rule: |
1031 | bridge_badrule(targc, targv, ln); |
1032 | return (1); |
1033 | } |
1034 | |
1035 | int |
1036 | bridge_arprule(struct ifbrlreq *rule, int *argc, char ***argv) |
1037 | { |
1038 | while (*argc) { |
1039 | struct ether_addr *ea, *dea = NULL((void *)0); |
1040 | struct in_addr ia, *dia = NULL((void *)0); |
1041 | |
1042 | if (strcmp((*argv)[0], "request") == 0) { |
1043 | if (rule->ifbr_arpf.brla_flags & BRLA_ARP0x01) |
1044 | rule->ifbr_arpf.brla_op = ARPOP_REQUEST1; |
1045 | else if (rule->ifbr_arpf.brla_flags & BRLA_RARP0x02) |
1046 | rule->ifbr_arpf.brla_op = ARPOP_REVREQUEST3; |
1047 | else |
1048 | errx(1, "bridge_arprule: arp/rarp undefined"); |
1049 | } else if (strcmp((*argv)[0], "reply") == 0) { |
1050 | if (rule->ifbr_arpf.brla_flags & BRLA_ARP0x01) |
1051 | rule->ifbr_arpf.brla_op = ARPOP_REPLY2; |
1052 | else if (rule->ifbr_arpf.brla_flags & BRLA_RARP0x02) |
1053 | rule->ifbr_arpf.brla_op = ARPOP_REVREPLY4; |
1054 | else |
1055 | errx(1, "bridge_arprule: arp/rarp undefined"); |
1056 | } else if (strcmp((*argv)[0], "sha") == 0) { |
1057 | rule->ifbr_arpf.brla_flags |= BRLA_SHA0x10; |
1058 | dea = &rule->ifbr_arpf.brla_sha; |
1059 | } else if (strcmp((*argv)[0], "tha") == 0) { |
1060 | rule->ifbr_arpf.brla_flags |= BRLA_THA0x40; |
1061 | dea = &rule->ifbr_arpf.brla_tha; |
1062 | } else if (strcmp((*argv)[0], "spa") == 0) { |
1063 | rule->ifbr_arpf.brla_flags |= BRLA_SPA0x20; |
1064 | dia = &rule->ifbr_arpf.brla_spa; |
1065 | } else if (strcmp((*argv)[0], "tpa") == 0) { |
1066 | rule->ifbr_arpf.brla_flags |= BRLA_TPA0x80; |
1067 | dia = &rule->ifbr_arpf.brla_tpa; |
1068 | } else |
1069 | return (0); |
1070 | |
1071 | (*argc)--; (*argv)++; |
1072 | if (dea != NULL((void *)0)) { |
1073 | if (*argc == 0) |
1074 | return (-1); |
1075 | ea = ether_aton((*argv)[0]); |
1076 | if (ea == NULL((void *)0)) { |
1077 | warnx("invalid address: %s", (*argv)[0]); |
1078 | return (-1); |
1079 | } |
1080 | bcopy(ea, dea, sizeof(*dea)); |
1081 | (*argc)--; (*argv)++; |
1082 | } |
1083 | if (dia != NULL((void *)0)) { |
1084 | if (*argc == 0) |
1085 | return (-1); |
1086 | ia.s_addr = inet_addr((*argv)[0]); |
1087 | if (ia.s_addr == INADDR_NONE((u_int32_t)(0xffffffff))) { |
1088 | warnx("invalid address: %s", (*argv)[0]); |
1089 | return (-1); |
1090 | } |
1091 | bcopy(&ia, dia, sizeof(*dia)); |
1092 | (*argc)--; (*argv)++; |
1093 | } |
1094 | } |
1095 | return (0); |
1096 | } |
1097 | |
1098 | |
1099 | #define MAXRULEWORDS32 32 |
1100 | |
1101 | void |
1102 | bridge_rulefile(const char *fname, int d) |
1103 | { |
1104 | FILE *f; |
1105 | char *str, *argv[MAXRULEWORDS32], buf[1024]; |
1106 | int ln = 0, argc = 0; |
1107 | |
1108 | f = fopen(fname, "r"); |
1109 | if (f == NULL((void *)0)) |
1110 | err(1, "%s", fname); |
1111 | |
1112 | while (fgets(buf, sizeof(buf), f) != NULL((void *)0)) { |
1113 | ln++; |
1114 | if (buf[0] == '#' || buf[0] == '\n') |
1115 | continue; |
1116 | |
1117 | argc = 0; |
1118 | str = strtok(buf, "\n\t\r "); |
1119 | while (str != NULL((void *)0) && argc < MAXRULEWORDS32) { |
1120 | argv[argc++] = str; |
1121 | str = strtok(NULL((void *)0), "\n\t\r "); |
1122 | } |
1123 | |
1124 | /* Rule is too long if there's more. */ |
1125 | if (str != NULL((void *)0)) { |
1126 | warnx("invalid rule: %d: %s ...", ln, buf); |
1127 | continue; |
1128 | } |
1129 | |
1130 | bridge_rule(argc, argv, ln); |
1131 | } |
1132 | fclose(f); |
1133 | } |
1134 | |
1135 | void |
1136 | bridge_badrule(int argc, char *argv[], int ln) |
1137 | { |
1138 | extern const char *__progname; |
1139 | int i; |
1140 | |
1141 | fprintf(stderr(&__sF[2]), "%s: invalid rule: ", __progname); |
1142 | if (ln != -1) |
1143 | fprintf(stderr(&__sF[2]), "%d: ", ln); |
1144 | for (i = 0; i < argc; i++) |
1145 | fprintf(stderr(&__sF[2]), "%s ", argv[i]); |
1146 | fprintf(stderr(&__sF[2]), "\n"); |
1147 | } |
1148 | |
1149 | #endif |