File: | src/sbin/ifconfig/brconfig.c |
Warning: | line 816, column 2 Value stored to 'ifrp' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: brconfig.c,v 1.30 2021/11/11 09:39:16 claudio 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 | unsigned long newsize; |
564 | const char *errstr; |
565 | |
566 | bp.ifbrp_csizeifbrp_ifbrpu.ifbrpu_csize = strtonum(arg, 0, UINT32_MAX0xffffffffU, &errstr); |
567 | if (errstr) |
568 | errx(1, "maxaddr %s is: %s", arg, errstr); |
569 | |
570 | strlcpy(bp.ifbrp_name, ifname, sizeof(bp.ifbrp_name)); |
571 | if (ioctl(sock, SIOCBRDGSCACHE((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((64))), (caddr_t)&bp) == -1) |
572 | err(1, "%s", ifname); |
573 | } |
574 | |
575 | void |
576 | bridge_deladdr(const char *addr, int d) |
577 | { |
578 | struct ifbareq ifba; |
579 | struct ether_addr *ea; |
580 | |
581 | strlcpy(ifba.ifba_name, ifname, sizeof(ifba.ifba_name)); |
582 | ea = ether_aton(addr); |
583 | if (ea == NULL((void *)0)) |
584 | err(1, "Invalid address: %s", addr); |
585 | |
586 | bcopy(ea, &ifba.ifba_dst, sizeof(struct ether_addr)); |
587 | |
588 | if (ioctl(sock, SIOCBRDGDADDR((unsigned long)0x80000000 | ((sizeof(struct ifbareq) & 0x1fff ) << 16) | ((('i')) << 8) | ((71))), &ifba) == -1) |
589 | err(1, "%s: %s", ifname, addr); |
590 | } |
591 | |
592 | void |
593 | bridge_ifprio(const char *ifsname, const char *val) |
594 | { |
595 | struct ifbreq breq; |
596 | const char *errstr; |
597 | |
598 | breq.ifbr_priority = strtonum(val, 0, UINT8_MAX0xff, &errstr); |
599 | if (errstr) |
600 | errx(1, "ifpriority %s is: %s", val, errstr); |
601 | |
602 | strlcpy(breq.ifbr_name, ifname, sizeof(breq.ifbr_name)); |
603 | strlcpy(breq.ifbr_ifsname, ifsname, sizeof(breq.ifbr_ifsname)); |
604 | |
605 | if (ioctl(sock, SIOCBRDGSIFPRIO((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((84))), (caddr_t)&breq) == -1) |
606 | err(1, "%s: %s", ifname, val); |
607 | } |
608 | |
609 | void |
610 | bridge_ifcost(const char *ifsname, const char *val) |
611 | { |
612 | struct ifbreq breq; |
613 | const char *errstr; |
614 | |
615 | breq.ifbr_path_cost = strtonum(val, 0, UINT32_MAX0xffffffffU, &errstr); |
616 | if (errstr) |
617 | errx(1, "ifcost %s is: %s", val, errstr); |
618 | |
619 | strlcpy(breq.ifbr_name, ifname, sizeof(breq.ifbr_name)); |
620 | strlcpy(breq.ifbr_ifsname, ifsname, sizeof(breq.ifbr_ifsname)); |
621 | |
622 | if (ioctl(sock, SIOCBRDGSIFCOST((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((85))), (caddr_t)&breq) == -1) |
623 | err(1, "%s: %s", ifname, val); |
624 | } |
625 | |
626 | void |
627 | bridge_noifcost(const char *ifsname, int d) |
628 | { |
629 | struct ifbreq breq; |
630 | |
631 | strlcpy(breq.ifbr_name, ifname, sizeof(breq.ifbr_name)); |
632 | strlcpy(breq.ifbr_ifsname, ifsname, sizeof(breq.ifbr_ifsname)); |
633 | |
634 | breq.ifbr_path_cost = 0; |
635 | |
636 | if (ioctl(sock, SIOCBRDGSIFCOST((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((85))), (caddr_t)&breq) == -1) |
637 | err(1, "%s", ifname); |
638 | } |
639 | |
640 | void |
641 | bridge_addaddr(const char *ifsname, const char *addr) |
642 | { |
643 | struct ifbareq ifba; |
644 | struct ether_addr *ea; |
645 | |
646 | strlcpy(ifba.ifba_name, ifname, sizeof(ifba.ifba_name)); |
647 | strlcpy(ifba.ifba_ifsname, ifsname, sizeof(ifba.ifba_ifsname)); |
648 | |
649 | ea = ether_aton(addr); |
650 | if (ea == NULL((void *)0)) |
651 | errx(1, "Invalid address: %s", addr); |
652 | |
653 | bcopy(ea, &ifba.ifba_dst, sizeof(struct ether_addr)); |
654 | ifba.ifba_flags = IFBAF_STATIC0x01; |
655 | |
656 | if (ioctl(sock, SIOCBRDGSADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbareq) & 0x1fff) << 16) | ((('i')) << 8) | ((68))), &ifba) == -1) |
657 | err(1, "%s: %s", ifname, addr); |
658 | } |
659 | |
660 | void |
661 | bridge_addrs(const char *delim, int d) |
662 | { |
663 | char dstaddr[NI_MAXHOST256]; |
664 | char dstport[NI_MAXSERV32]; |
665 | const int niflag = NI_NUMERICHOST1|NI_DGRAM16; |
666 | struct ifbaconf ifbac; |
667 | struct ifbareq *ifba; |
668 | char *inbuf = NULL((void *)0), buf[sizeof(ifba->ifba_ifsname) + 1], *inb; |
669 | struct sockaddr *sa; |
670 | int i, len = 8192; |
671 | |
672 | /* ifconfig will call us with the argv of the command */ |
673 | if (strcmp(delim, "addr") == 0) |
674 | delim = ""; |
675 | |
676 | while (1) { |
677 | ifbac.ifbac_len = len; |
678 | inb = realloc(inbuf, len); |
679 | if (inb == NULL((void *)0)) |
680 | err(1, "malloc"); |
681 | ifbac.ifbac_bufifbac_ifbacu.ifbacu_buf = inbuf = inb; |
682 | strlcpy(ifbac.ifbac_name, ifname, sizeof(ifbac.ifbac_name)); |
683 | if (ioctl(sock, SIOCBRDGRTS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbaconf) & 0x1fff) << 16) | ((('i')) << 8) | ((67))), &ifbac) == -1) { |
684 | if (errno(*__errno()) == ENETDOWN50) |
685 | return; |
686 | err(1, "%s", ifname); |
687 | } |
688 | if (ifbac.ifbac_len + sizeof(*ifba) < len) |
689 | break; |
690 | len *= 2; |
691 | } |
692 | |
693 | for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { |
694 | ifba = ifbac.ifbac_reqifbac_ifbacu.ifbacu_req + i; |
695 | strlcpy(buf, ifba->ifba_ifsname, sizeof(buf)); |
696 | printf("%s%s %s %u ", delim, ether_ntoa(&ifba->ifba_dst), |
697 | buf, ifba->ifba_age); |
698 | sa = (struct sockaddr *)&ifba->ifba_dstsa; |
699 | printb("flags", ifba->ifba_flags, IFBAFBITS"\020\1STATIC"); |
700 | if (sa->sa_family != AF_UNSPEC0 && |
701 | getnameinfo(sa, sa->sa_len, |
702 | dstaddr, sizeof(dstaddr), |
703 | dstport, sizeof(dstport), niflag) == 0) |
704 | printf(" tunnel %s:%s", dstaddr, dstport); |
705 | printf("\n"); |
706 | } |
707 | free(inbuf); |
708 | } |
709 | |
710 | void |
711 | bridge_holdcnt(const char *value, int d) |
712 | { |
713 | struct ifbrparam bp; |
714 | const char *errstr; |
715 | |
716 | bp.ifbrp_txhcifbrp_ifbrpu.ifbrpu_txhc = strtonum(value, 0, UINT8_MAX0xff, &errstr); |
717 | if (errstr) |
718 | err(1, "holdcnt %s is: %s", value, errstr); |
719 | |
720 | strlcpy(bp.ifbrp_name, ifname, sizeof(bp.ifbrp_name)); |
721 | if (ioctl(sock, SIOCBRDGSTXHC((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((89))), (caddr_t)&bp) == -1) |
722 | err(1, "%s", ifname); |
723 | } |
724 | |
725 | /* |
726 | * Check to make sure interface is really a bridge interface. |
727 | */ |
728 | int |
729 | is_bridge() |
730 | { |
731 | struct ifbaconf ifbac; |
732 | |
733 | ifbac.ifbac_len = 0; |
734 | strlcpy(ifbac.ifbac_name, ifname, sizeof(ifbac.ifbac_name)); |
735 | if (ioctl(sock, SIOCBRDGRTS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbaconf) & 0x1fff) << 16) | ((('i')) << 8) | ((67))), (caddr_t)&ifbac) == -1) { |
736 | if (errno(*__errno()) == ENETDOWN50) |
737 | return (1); |
738 | return (0); |
739 | } |
740 | return (1); |
741 | } |
742 | |
743 | /* no tpmr(4) specific ioctls, name is enough if ifconfig.c:printif() passed */ |
744 | int |
745 | is_tpmr(void) |
746 | { |
747 | return (strncmp(ifname, "tpmr", sizeof("tpmr") - 1) == 0); |
748 | } |
749 | |
750 | void |
751 | bridge_status(void) |
752 | { |
753 | struct ifbrparam bp1, bp2; |
754 | |
755 | if (is_tpmr()) { |
756 | bridge_list("\t"); |
757 | return; |
758 | } |
759 | |
760 | if (!is_bridge()) |
761 | return; |
762 | |
763 | bridge_cfg("\t"); |
764 | bridge_list("\t"); |
765 | |
766 | if (aflag && !ifaliases) |
767 | return; |
768 | |
769 | strlcpy(bp1.ifbrp_name, ifname, sizeof(bp1.ifbrp_name)); |
770 | if (ioctl(sock, SIOCBRDGGCACHE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((65))), (caddr_t)&bp1) == -1) |
771 | return; |
772 | |
773 | strlcpy(bp2.ifbrp_name, ifname, sizeof(bp2.ifbrp_name)); |
774 | if (ioctl(sock, SIOCBRDGGTO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbrparam) & 0x1fff) << 16) | ((('i')) << 8) | ((70))), (caddr_t)&bp2) == -1) |
775 | return; |
776 | |
777 | printf("\tAddresses (max cache: %u, timeout: %u):\n", |
778 | bp1.ifbrp_csizeifbrp_ifbrpu.ifbrpu_csize, bp2.ifbrp_ctimeifbrp_ifbrpu.ifbrpu_ctime); |
779 | |
780 | bridge_addrs("\t\t", 0); |
781 | } |
782 | |
783 | void |
784 | bridge_flushrule(const char *ifsname, int d) |
785 | { |
786 | struct ifbrlreq req; |
787 | |
788 | strlcpy(req.ifbr_name, ifname, sizeof(req.ifbr_name)); |
789 | strlcpy(req.ifbr_ifsname, ifsname, sizeof(req.ifbr_ifsname)); |
790 | if (ioctl(sock, SIOCBRDGFRL((unsigned long)0x80000000 | ((sizeof(struct ifbrlreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((78))), &req) == -1) |
791 | err(1, "%s: %s", ifname, ifsname); |
792 | } |
793 | |
794 | void |
795 | bridge_rules(const char *ifsname, int usetab) |
796 | { |
797 | char *inbuf = NULL((void *)0), *inb; |
798 | struct ifbrlconf ifc; |
799 | struct ifbrlreq *ifrp; |
800 | int len = 8192, i; |
801 | |
802 | while (1) { |
803 | ifc.ifbrl_len = len; |
804 | inb = realloc(inbuf, len); |
805 | if (inb == NULL((void *)0)) |
806 | err(1, "malloc"); |
807 | ifc.ifbrl_bufifbrl_ifbrlu.ifbrlu_buf = inbuf = inb; |
808 | strlcpy(ifc.ifbrl_name, ifname, sizeof(ifc.ifbrl_name)); |
809 | strlcpy(ifc.ifbrl_ifsname, ifsname, sizeof(ifc.ifbrl_ifsname)); |
810 | if (ioctl(sock, SIOCBRDGGRL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifbrlconf) & 0x1fff) << 16) | ((('i')) << 8) | ((79))), &ifc) == -1) |
811 | err(1, "ioctl(SIOCBRDGGRL)"); |
812 | if (ifc.ifbrl_len + sizeof(*ifrp) < len) |
813 | break; |
814 | len *= 2; |
815 | } |
816 | ifrp = ifc.ifbrl_reqifbrl_ifbrlu.ifbrlu_req; |
Value stored to 'ifrp' is never read | |
817 | for (i = 0; i < ifc.ifbrl_len; i += sizeof(*ifrp)) { |
818 | ifrp = (struct ifbrlreq *)((caddr_t)ifc.ifbrl_reqifbrl_ifbrlu.ifbrlu_req + i); |
819 | |
820 | if (usetab) |
821 | printf("\t"); |
822 | |
823 | bridge_showrule(ifrp); |
824 | } |
825 | } |
826 | |
827 | void |
828 | bridge_showrule(struct ifbrlreq *r) |
829 | { |
830 | if (r->ifbr_action == BRL_ACTION_BLOCK0x01) |
831 | printf("block "); |
832 | else if (r->ifbr_action == BRL_ACTION_PASS0x02) |
833 | printf("pass "); |
834 | else |
835 | printf("[neither block nor pass?]\n"); |
836 | |
837 | if ((r->ifbr_flags & (BRL_FLAG_IN0x08 | BRL_FLAG_OUT0x04)) == |
838 | (BRL_FLAG_IN0x08 | BRL_FLAG_OUT0x04)) |
839 | printf("in/out "); |
840 | else if (r->ifbr_flags & BRL_FLAG_IN0x08) |
841 | printf("in "); |
842 | else if (r->ifbr_flags & BRL_FLAG_OUT0x04) |
843 | printf("out "); |
844 | else |
845 | printf("[neither in nor out?]\n"); |
846 | |
847 | printf("on %s", r->ifbr_ifsname); |
848 | |
849 | if (r->ifbr_flags & BRL_FLAG_SRCVALID0x02) |
850 | printf(" src %s", ether_ntoa(&r->ifbr_src)); |
851 | if (r->ifbr_flags & BRL_FLAG_DSTVALID0x01) |
852 | printf(" dst %s", ether_ntoa(&r->ifbr_dst)); |
853 | if (r->ifbr_tagname[0]) |
854 | printf(" tag %s", r->ifbr_tagname); |
855 | |
856 | if (r->ifbr_arpf.brla_flags & BRLA_ARP0x01) |
857 | printf(" arp"); |
858 | if (r->ifbr_arpf.brla_flags & BRLA_RARP0x02) |
859 | printf(" rarp"); |
860 | if (r->ifbr_arpf.brla_op == ARPOP_REQUEST1 || |
861 | r->ifbr_arpf.brla_op == ARPOP_REVREQUEST3) |
862 | printf(" request"); |
863 | if (r->ifbr_arpf.brla_op == ARPOP_REPLY2 || |
864 | r->ifbr_arpf.brla_op == ARPOP_REVREPLY4) |
865 | printf(" reply"); |
866 | if (r->ifbr_arpf.brla_flags & BRLA_SHA0x10) |
867 | printf(" sha %s", ether_ntoa(&r->ifbr_arpf.brla_sha)); |
868 | if (r->ifbr_arpf.brla_flags & BRLA_THA0x40) |
869 | printf(" tha %s", ether_ntoa(&r->ifbr_arpf.brla_tha)); |
870 | if (r->ifbr_arpf.brla_flags & BRLA_SPA0x20) |
871 | printf(" spa %s", inet_ntoa(r->ifbr_arpf.brla_spa)); |
872 | if (r->ifbr_arpf.brla_flags & BRLA_TPA0x80) |
873 | printf(" tpa %s", inet_ntoa(r->ifbr_arpf.brla_tpa)); |
874 | |
875 | printf("\n"); |
876 | } |
877 | |
878 | /* |
879 | * Parse a rule definition and send it upwards. |
880 | * |
881 | * Syntax: |
882 | * {block|pass} {in|out|in/out} on {ifs} [src {mac}] [dst {mac}] |
883 | */ |
884 | int |
885 | bridge_rule(int targc, char **targv, int ln) |
886 | { |
887 | char **argv = targv; |
888 | int argc = targc; |
889 | struct ifbrlreq rule; |
890 | struct ether_addr *ea, *dea; |
891 | |
892 | if (argc == 0) { |
893 | warnx("invalid rule"); |
894 | return (1); |
895 | } |
896 | bzero(&rule, sizeof(rule)); |
897 | strlcpy(rule.ifbr_name, ifname, sizeof(rule.ifbr_name)); |
898 | |
899 | if (strcmp(argv[0], "block") == 0) |
900 | rule.ifbr_action = BRL_ACTION_BLOCK0x01; |
901 | else if (strcmp(argv[0], "pass") == 0) |
902 | rule.ifbr_action = BRL_ACTION_PASS0x02; |
903 | else |
904 | goto bad_rule; |
905 | argc--; argv++; |
906 | |
907 | if (argc == 0) { |
908 | bridge_badrule(targc, targv, ln); |
909 | return (1); |
910 | } |
911 | if (strcmp(argv[0], "in") == 0) |
912 | rule.ifbr_flags |= BRL_FLAG_IN0x08; |
913 | else if (strcmp(argv[0], "out") == 0) |
914 | rule.ifbr_flags |= BRL_FLAG_OUT0x04; |
915 | else if (strcmp(argv[0], "in/out") == 0) |
916 | rule.ifbr_flags |= BRL_FLAG_IN0x08 | BRL_FLAG_OUT0x04; |
917 | else if (strcmp(argv[0], "on") == 0) { |
918 | rule.ifbr_flags |= BRL_FLAG_IN0x08 | BRL_FLAG_OUT0x04; |
919 | argc++; argv--; |
920 | } else |
921 | goto bad_rule; |
922 | argc--; argv++; |
923 | |
924 | if (argc == 0 || strcmp(argv[0], "on")) |
925 | goto bad_rule; |
926 | argc--; argv++; |
927 | |
928 | if (argc == 0) |
929 | goto bad_rule; |
930 | strlcpy(rule.ifbr_ifsname, argv[0], sizeof(rule.ifbr_ifsname)); |
931 | argc--; argv++; |
932 | |
933 | while (argc) { |
934 | dea = NULL((void *)0); |
935 | if (strcmp(argv[0], "dst") == 0) { |
936 | if (rule.ifbr_flags & BRL_FLAG_DSTVALID0x01) |
937 | goto bad_rule; |
938 | rule.ifbr_flags |= BRL_FLAG_DSTVALID0x01; |
939 | dea = &rule.ifbr_dst; |
940 | argc--; argv++; |
941 | } else if (strcmp(argv[0], "src") == 0) { |
942 | if (rule.ifbr_flags & BRL_FLAG_SRCVALID0x02) |
943 | goto bad_rule; |
944 | rule.ifbr_flags |= BRL_FLAG_SRCVALID0x02; |
945 | dea = &rule.ifbr_src; |
946 | argc--; argv++; |
947 | } else if (strcmp(argv[0], "tag") == 0) { |
948 | if (argc < 2) { |
949 | warnx("missing tag name"); |
950 | goto bad_rule; |
951 | } |
952 | if (rule.ifbr_tagname[0]) { |
953 | warnx("tag already defined"); |
954 | goto bad_rule; |
955 | } |
956 | argc--; argv++; |
957 | if (strlcpy(rule.ifbr_tagname, argv[0], |
958 | PF_TAG_NAME_SIZE64) > PF_TAG_NAME_SIZE64) { |
959 | warnx("tag name '%s' too long", argv[0]); |
960 | goto bad_rule; |
961 | } |
962 | argc--; argv++; |
963 | } else if (strcmp(argv[0], "arp") == 0) { |
964 | rule.ifbr_arpf.brla_flags |= BRLA_ARP0x01; |
965 | argc--; argv++; |
966 | if (bridge_arprule(&rule, &argc, &argv) == -1) |
967 | goto bad_rule; |
968 | } else if (strcmp(argv[0], "rarp") == 0) { |
969 | rule.ifbr_arpf.brla_flags |= BRLA_RARP0x02; |
970 | argc--; argv++; |
971 | if (bridge_arprule(&rule, &argc, &argv) == -1) |
972 | goto bad_rule; |
973 | } else |
974 | goto bad_rule; |
975 | |
976 | if (dea != NULL((void *)0)) { |
977 | if (argc == 0) |
978 | goto bad_rule; |
979 | ea = ether_aton(argv[0]); |
980 | if (ea == NULL((void *)0)) { |
981 | warnx("invalid address: %s", argv[0]); |
982 | return (1); |
983 | } |
984 | bcopy(ea, dea, sizeof(*dea)); |
985 | argc--; argv++; |
986 | } |
987 | } |
988 | |
989 | if (ioctl(sock, SIOCBRDGARL((unsigned long)0x80000000 | ((sizeof(struct ifbrlreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((77))), &rule) == -1) { |
990 | warn("%s", ifname); |
991 | return (1); |
992 | } |
993 | return (0); |
994 | |
995 | bad_rule: |
996 | bridge_badrule(targc, targv, ln); |
997 | return (1); |
998 | } |
999 | |
1000 | int |
1001 | bridge_arprule(struct ifbrlreq *rule, int *argc, char ***argv) |
1002 | { |
1003 | while (*argc) { |
1004 | struct ether_addr *ea, *dea = NULL((void *)0); |
1005 | struct in_addr ia, *dia = NULL((void *)0); |
1006 | |
1007 | if (strcmp((*argv)[0], "request") == 0) { |
1008 | if (rule->ifbr_arpf.brla_flags & BRLA_ARP0x01) |
1009 | rule->ifbr_arpf.brla_op = ARPOP_REQUEST1; |
1010 | else if (rule->ifbr_arpf.brla_flags & BRLA_RARP0x02) |
1011 | rule->ifbr_arpf.brla_op = ARPOP_REVREQUEST3; |
1012 | else |
1013 | errx(1, "bridge_arprule: arp/rarp undefined"); |
1014 | } else if (strcmp((*argv)[0], "reply") == 0) { |
1015 | if (rule->ifbr_arpf.brla_flags & BRLA_ARP0x01) |
1016 | rule->ifbr_arpf.brla_op = ARPOP_REPLY2; |
1017 | else if (rule->ifbr_arpf.brla_flags & BRLA_RARP0x02) |
1018 | rule->ifbr_arpf.brla_op = ARPOP_REVREPLY4; |
1019 | else |
1020 | errx(1, "bridge_arprule: arp/rarp undefined"); |
1021 | } else if (strcmp((*argv)[0], "sha") == 0) { |
1022 | rule->ifbr_arpf.brla_flags |= BRLA_SHA0x10; |
1023 | dea = &rule->ifbr_arpf.brla_sha; |
1024 | } else if (strcmp((*argv)[0], "tha") == 0) { |
1025 | rule->ifbr_arpf.brla_flags |= BRLA_THA0x40; |
1026 | dea = &rule->ifbr_arpf.brla_tha; |
1027 | } else if (strcmp((*argv)[0], "spa") == 0) { |
1028 | rule->ifbr_arpf.brla_flags |= BRLA_SPA0x20; |
1029 | dia = &rule->ifbr_arpf.brla_spa; |
1030 | } else if (strcmp((*argv)[0], "tpa") == 0) { |
1031 | rule->ifbr_arpf.brla_flags |= BRLA_TPA0x80; |
1032 | dia = &rule->ifbr_arpf.brla_tpa; |
1033 | } else |
1034 | return (0); |
1035 | |
1036 | (*argc)--; (*argv)++; |
1037 | if (dea != NULL((void *)0)) { |
1038 | if (*argc == 0) |
1039 | return (-1); |
1040 | ea = ether_aton((*argv)[0]); |
1041 | if (ea == NULL((void *)0)) { |
1042 | warnx("invalid address: %s", (*argv)[0]); |
1043 | return (-1); |
1044 | } |
1045 | bcopy(ea, dea, sizeof(*dea)); |
1046 | (*argc)--; (*argv)++; |
1047 | } |
1048 | if (dia != NULL((void *)0)) { |
1049 | if (*argc == 0) |
1050 | return (-1); |
1051 | ia.s_addr = inet_addr((*argv)[0]); |
1052 | if (ia.s_addr == INADDR_NONE((u_int32_t)(0xffffffff))) { |
1053 | warnx("invalid address: %s", (*argv)[0]); |
1054 | return (-1); |
1055 | } |
1056 | bcopy(&ia, dia, sizeof(*dia)); |
1057 | (*argc)--; (*argv)++; |
1058 | } |
1059 | } |
1060 | return (0); |
1061 | } |
1062 | |
1063 | |
1064 | #define MAXRULEWORDS32 32 |
1065 | |
1066 | void |
1067 | bridge_rulefile(const char *fname, int d) |
1068 | { |
1069 | FILE *f; |
1070 | char *str, *argv[MAXRULEWORDS32], buf[1024]; |
1071 | int ln = 0, argc = 0; |
1072 | |
1073 | f = fopen(fname, "r"); |
1074 | if (f == NULL((void *)0)) |
1075 | err(1, "%s", fname); |
1076 | |
1077 | while (fgets(buf, sizeof(buf), f) != NULL((void *)0)) { |
1078 | ln++; |
1079 | if (buf[0] == '#' || buf[0] == '\n') |
1080 | continue; |
1081 | |
1082 | argc = 0; |
1083 | str = strtok(buf, "\n\t\r "); |
1084 | while (str != NULL((void *)0) && argc < MAXRULEWORDS32) { |
1085 | argv[argc++] = str; |
1086 | str = strtok(NULL((void *)0), "\n\t\r "); |
1087 | } |
1088 | |
1089 | /* Rule is too long if there's more. */ |
1090 | if (str != NULL((void *)0)) { |
1091 | warnx("invalid rule: %d: %s ...", ln, buf); |
1092 | continue; |
1093 | } |
1094 | |
1095 | bridge_rule(argc, argv, ln); |
1096 | } |
1097 | fclose(f); |
1098 | } |
1099 | |
1100 | void |
1101 | bridge_badrule(int argc, char *argv[], int ln) |
1102 | { |
1103 | extern const char *__progname; |
1104 | int i; |
1105 | |
1106 | fprintf(stderr(&__sF[2]), "%s: invalid rule: ", __progname); |
1107 | if (ln != -1) |
1108 | fprintf(stderr(&__sF[2]), "%d: ", ln); |
1109 | for (i = 0; i < argc; i++) |
1110 | fprintf(stderr(&__sF[2]), "%s ", argv[i]); |
1111 | fprintf(stderr(&__sF[2]), "\n"); |
1112 | } |
1113 | |
1114 | #endif |