diff options
Diffstat (limited to 'networking/libiproute/iplink.c')
-rw-r--r-- | networking/libiproute/iplink.c | 300 |
1 files changed, 135 insertions, 165 deletions
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index ae3ef0ceb..aef5f6490 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c | |||
@@ -52,6 +52,9 @@ struct ifla_vlan_flags { | |||
52 | # define dbg(...) ((void)0) | 52 | # define dbg(...) ((void)0) |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | |||
56 | #define str_on_off "on\0""off\0" | ||
57 | |||
55 | /* Exits on error */ | 58 | /* Exits on error */ |
56 | static int get_ctl_fd(void) | 59 | static int get_ctl_fd(void) |
57 | { | 60 | { |
@@ -204,12 +207,14 @@ static int do_set(char **argv) | |||
204 | struct ifreq ifr0, ifr1; | 207 | struct ifreq ifr0, ifr1; |
205 | char *newname = NULL; | 208 | char *newname = NULL; |
206 | int htype, halen; | 209 | int htype, halen; |
210 | /* If you add stuff here, update iplink_full_usage */ | ||
207 | static const char keywords[] ALIGN1 = | 211 | static const char keywords[] ALIGN1 = |
208 | "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" | 212 | "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" |
209 | "arp\0""address\0""dev\0"; | 213 | "arp\0""promisc\0""address\0" |
214 | "dev\0" /* must be last */; | ||
210 | enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, | 215 | enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, |
211 | ARG_arp, ARG_addr, ARG_dev }; | 216 | ARG_arp, ARG_promisc, ARG_addr, |
212 | static const char str_on_off[] ALIGN1 = "on\0""off\0"; | 217 | ARG_dev }; |
213 | enum { PARM_on = 0, PARM_off }; | 218 | enum { PARM_on = 0, PARM_off }; |
214 | smalluint key; | 219 | smalluint key; |
215 | 220 | ||
@@ -232,6 +237,7 @@ static int do_set(char **argv) | |||
232 | duparg("mtu", *argv); | 237 | duparg("mtu", *argv); |
233 | mtu = get_unsigned(*argv, "mtu"); | 238 | mtu = get_unsigned(*argv, "mtu"); |
234 | } else if (key == ARG_qlen) { | 239 | } else if (key == ARG_qlen) { |
240 | //TODO: txqueuelen, txqlen are synonyms to qlen | ||
235 | NEXT_ARG(); | 241 | NEXT_ARG(); |
236 | if (qlen != -1) | 242 | if (qlen != -1) |
237 | duparg("qlen", *argv); | 243 | duparg("qlen", *argv); |
@@ -240,6 +246,7 @@ static int do_set(char **argv) | |||
240 | NEXT_ARG(); | 246 | NEXT_ARG(); |
241 | newaddr = *argv; | 247 | newaddr = *argv; |
242 | } else if (key >= ARG_dev) { | 248 | } else if (key >= ARG_dev) { |
249 | /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ | ||
243 | if (key == ARG_dev) { | 250 | if (key == ARG_dev) { |
244 | NEXT_ARG(); | 251 | NEXT_ARG(); |
245 | } | 252 | } |
@@ -247,6 +254,7 @@ static int do_set(char **argv) | |||
247 | duparg2("dev", *argv); | 254 | duparg2("dev", *argv); |
248 | dev = *argv; | 255 | dev = *argv; |
249 | } else { | 256 | } else { |
257 | /* "on|off" options */ | ||
250 | int param; | 258 | int param; |
251 | NEXT_ARG(); | 259 | NEXT_ARG(); |
252 | param = index_in_strings(str_on_off, *argv); | 260 | param = index_in_strings(str_on_off, *argv); |
@@ -266,8 +274,132 @@ static int do_set(char **argv) | |||
266 | flags &= ~IFF_NOARP; | 274 | flags &= ~IFF_NOARP; |
267 | else | 275 | else |
268 | flags |= IFF_NOARP; | 276 | flags |= IFF_NOARP; |
277 | } else if (key == ARG_promisc) { | ||
278 | if (param < 0) | ||
279 | die_must_be_on_off("promisc"); | ||
280 | mask |= IFF_PROMISC; | ||
281 | if (param == PARM_on) | ||
282 | flags |= IFF_PROMISC; | ||
283 | else | ||
284 | flags &= ~IFF_PROMISC; | ||
269 | } | 285 | } |
270 | } | 286 | } |
287 | |||
288 | /* Other keywords recognized by iproute2-3.12.0: */ | ||
289 | #if 0 | ||
290 | } else if (matches(*argv, "broadcast") == 0 || | ||
291 | strcmp(*argv, "brd") == 0) { | ||
292 | NEXT_ARG(); | ||
293 | len = ll_addr_a2n(abuf, sizeof(abuf), *argv); | ||
294 | if (len < 0) | ||
295 | return -1; | ||
296 | addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len); | ||
297 | } else if (strcmp(*argv, "netns") == 0) { | ||
298 | NEXT_ARG(); | ||
299 | if (netns != -1) | ||
300 | duparg("netns", *argv); | ||
301 | if ((netns = get_netns_fd(*argv)) >= 0) | ||
302 | addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4); | ||
303 | else if (get_integer(&netns, *argv, 0) == 0) | ||
304 | addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4); | ||
305 | else | ||
306 | invarg_1_to_2(*argv, "netns"); | ||
307 | } else if (strcmp(*argv, "allmulticast") == 0) { | ||
308 | NEXT_ARG(); | ||
309 | req->i.ifi_change |= IFF_ALLMULTI; | ||
310 | if (strcmp(*argv, "on") == 0) { | ||
311 | req->i.ifi_flags |= IFF_ALLMULTI; | ||
312 | } else if (strcmp(*argv, "off") == 0) { | ||
313 | req->i.ifi_flags &= ~IFF_ALLMULTI; | ||
314 | } else | ||
315 | return on_off("allmulticast", *argv); | ||
316 | } else if (strcmp(*argv, "trailers") == 0) { | ||
317 | NEXT_ARG(); | ||
318 | req->i.ifi_change |= IFF_NOTRAILERS; | ||
319 | if (strcmp(*argv, "off") == 0) { | ||
320 | req->i.ifi_flags |= IFF_NOTRAILERS; | ||
321 | } else if (strcmp(*argv, "on") == 0) { | ||
322 | req->i.ifi_flags &= ~IFF_NOTRAILERS; | ||
323 | } else | ||
324 | return on_off("trailers", *argv); | ||
325 | } else if (strcmp(*argv, "vf") == 0) { | ||
326 | struct rtattr *vflist; | ||
327 | NEXT_ARG(); | ||
328 | if (get_integer(&vf, *argv, 0)) { | ||
329 | invarg_1_to_2(*argv, "vf"); | ||
330 | } | ||
331 | vflist = addattr_nest(&req->n, sizeof(*req), | ||
332 | IFLA_VFINFO_LIST); | ||
333 | len = iplink_parse_vf(vf, &argc, &argv, req); | ||
334 | if (len < 0) | ||
335 | return -1; | ||
336 | addattr_nest_end(&req->n, vflist); | ||
337 | } else if (matches(*argv, "master") == 0) { | ||
338 | int ifindex; | ||
339 | NEXT_ARG(); | ||
340 | ifindex = ll_name_to_index(*argv); | ||
341 | if (!ifindex) | ||
342 | invarg_1_to_2(*argv, "master"); | ||
343 | addattr_l(&req->n, sizeof(*req), IFLA_MASTER, | ||
344 | &ifindex, 4); | ||
345 | } else if (matches(*argv, "nomaster") == 0) { | ||
346 | int ifindex = 0; | ||
347 | addattr_l(&req->n, sizeof(*req), IFLA_MASTER, | ||
348 | &ifindex, 4); | ||
349 | } else if (matches(*argv, "dynamic") == 0) { | ||
350 | NEXT_ARG(); | ||
351 | req->i.ifi_change |= IFF_DYNAMIC; | ||
352 | if (strcmp(*argv, "on") == 0) { | ||
353 | req->i.ifi_flags |= IFF_DYNAMIC; | ||
354 | } else if (strcmp(*argv, "off") == 0) { | ||
355 | req->i.ifi_flags &= ~IFF_DYNAMIC; | ||
356 | } else | ||
357 | return on_off("dynamic", *argv); | ||
358 | } else if (matches(*argv, "alias") == 0) { | ||
359 | NEXT_ARG(); | ||
360 | addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS, | ||
361 | *argv, strlen(*argv)); | ||
362 | argc--; argv++; | ||
363 | break; | ||
364 | } else if (strcmp(*argv, "group") == 0) { | ||
365 | NEXT_ARG(); | ||
366 | if (*group != -1) | ||
367 | duparg("group", *argv); | ||
368 | if (rtnl_group_a2n(group, *argv)) | ||
369 | invarg_1_to_2(*argv, "group"); | ||
370 | } else if (strcmp(*argv, "mode") == 0) { | ||
371 | int mode; | ||
372 | NEXT_ARG(); | ||
373 | mode = get_link_mode(*argv); | ||
374 | if (mode < 0) | ||
375 | invarg_1_to_2(*argv, "mode"); | ||
376 | addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode); | ||
377 | } else if (strcmp(*argv, "state") == 0) { | ||
378 | int state; | ||
379 | NEXT_ARG(); | ||
380 | state = get_operstate(*argv); | ||
381 | if (state < 0) | ||
382 | invarg_1_to_2(*argv, "state"); | ||
383 | addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state); | ||
384 | } else if (matches(*argv, "numtxqueues") == 0) { | ||
385 | NEXT_ARG(); | ||
386 | if (numtxqueues != -1) | ||
387 | duparg("numtxqueues", *argv); | ||
388 | if (get_integer(&numtxqueues, *argv, 0)) | ||
389 | invarg_1_to_2(*argv, "numtxqueues"); | ||
390 | addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES, | ||
391 | &numtxqueues, 4); | ||
392 | } else if (matches(*argv, "numrxqueues") == 0) { | ||
393 | NEXT_ARG(); | ||
394 | if (numrxqueues != -1) | ||
395 | duparg("numrxqueues", *argv); | ||
396 | if (get_integer(&numrxqueues, *argv, 0)) | ||
397 | invarg_1_to_2(*argv, "numrxqueues"); | ||
398 | addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES, | ||
399 | &numrxqueues, 4); | ||
400 | } | ||
401 | #endif | ||
402 | |||
271 | argv++; | 403 | argv++; |
272 | } | 404 | } |
273 | 405 | ||
@@ -322,10 +454,6 @@ static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size) | |||
322 | "802.1q\0" | 454 | "802.1q\0" |
323 | "802.1ad\0" | 455 | "802.1ad\0" |
324 | ; | 456 | ; |
325 | static const char str_on_off[] ALIGN1 = | ||
326 | "on\0" | ||
327 | "off\0" | ||
328 | ; | ||
329 | enum { | 457 | enum { |
330 | ARG_id = 0, | 458 | ARG_id = 0, |
331 | ARG_reorder_hdr, | 459 | ARG_reorder_hdr, |
@@ -520,164 +648,6 @@ static int do_add_or_delete(char **argv, const unsigned rtm) | |||
520 | return 0; | 648 | return 0; |
521 | } | 649 | } |
522 | 650 | ||
523 | /* Other keywords recognized by iproute2-3.12.0: */ | ||
524 | #if 0 | ||
525 | } else if (matches(*argv, "broadcast") == 0 || | ||
526 | strcmp(*argv, "brd") == 0) { | ||
527 | NEXT_ARG(); | ||
528 | len = ll_addr_a2n(abuf, sizeof(abuf), *argv); | ||
529 | if (len < 0) | ||
530 | return -1; | ||
531 | addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len); | ||
532 | } else if (matches(*argv, "txqueuelen") == 0 || | ||
533 | strcmp(*argv, "qlen") == 0 || | ||
534 | matches(*argv, "txqlen") == 0) { | ||
535 | NEXT_ARG(); | ||
536 | if (qlen != -1) | ||
537 | duparg("txqueuelen", *argv); | ||
538 | if (get_integer(&qlen, *argv, 0)) | ||
539 | invarg_1_to_2(*argv, "txqueuelen"); | ||
540 | addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4); | ||
541 | } else if (strcmp(*argv, "mtu") == 0) { | ||
542 | NEXT_ARG(); | ||
543 | if (mtu != -1) | ||
544 | duparg("mtu", *argv); | ||
545 | if (get_integer(&mtu, *argv, 0)) | ||
546 | invarg_1_to_2(*argv, "mtu"); | ||
547 | addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4); | ||
548 | } else if (strcmp(*argv, "netns") == 0) { | ||
549 | NEXT_ARG(); | ||
550 | if (netns != -1) | ||
551 | duparg("netns", *argv); | ||
552 | if ((netns = get_netns_fd(*argv)) >= 0) | ||
553 | addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4); | ||
554 | else if (get_integer(&netns, *argv, 0) == 0) | ||
555 | addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4); | ||
556 | else | ||
557 | invarg_1_to_2(*argv, "netns"); | ||
558 | } else if (strcmp(*argv, "multicast") == 0) { | ||
559 | NEXT_ARG(); | ||
560 | req->i.ifi_change |= IFF_MULTICAST; | ||
561 | if (strcmp(*argv, "on") == 0) { | ||
562 | req->i.ifi_flags |= IFF_MULTICAST; | ||
563 | } else if (strcmp(*argv, "off") == 0) { | ||
564 | req->i.ifi_flags &= ~IFF_MULTICAST; | ||
565 | } else | ||
566 | return on_off("multicast", *argv); | ||
567 | } else if (strcmp(*argv, "allmulticast") == 0) { | ||
568 | NEXT_ARG(); | ||
569 | req->i.ifi_change |= IFF_ALLMULTI; | ||
570 | if (strcmp(*argv, "on") == 0) { | ||
571 | req->i.ifi_flags |= IFF_ALLMULTI; | ||
572 | } else if (strcmp(*argv, "off") == 0) { | ||
573 | req->i.ifi_flags &= ~IFF_ALLMULTI; | ||
574 | } else | ||
575 | return on_off("allmulticast", *argv); | ||
576 | } else if (strcmp(*argv, "promisc") == 0) { | ||
577 | NEXT_ARG(); | ||
578 | req->i.ifi_change |= IFF_PROMISC; | ||
579 | if (strcmp(*argv, "on") == 0) { | ||
580 | req->i.ifi_flags |= IFF_PROMISC; | ||
581 | } else if (strcmp(*argv, "off") == 0) { | ||
582 | req->i.ifi_flags &= ~IFF_PROMISC; | ||
583 | } else | ||
584 | return on_off("promisc", *argv); | ||
585 | } else if (strcmp(*argv, "trailers") == 0) { | ||
586 | NEXT_ARG(); | ||
587 | req->i.ifi_change |= IFF_NOTRAILERS; | ||
588 | if (strcmp(*argv, "off") == 0) { | ||
589 | req->i.ifi_flags |= IFF_NOTRAILERS; | ||
590 | } else if (strcmp(*argv, "on") == 0) { | ||
591 | req->i.ifi_flags &= ~IFF_NOTRAILERS; | ||
592 | } else | ||
593 | return on_off("trailers", *argv); | ||
594 | } else if (strcmp(*argv, "arp") == 0) { | ||
595 | NEXT_ARG(); | ||
596 | req->i.ifi_change |= IFF_NOARP; | ||
597 | if (strcmp(*argv, "on") == 0) { | ||
598 | req->i.ifi_flags &= ~IFF_NOARP; | ||
599 | } else if (strcmp(*argv, "off") == 0) { | ||
600 | req->i.ifi_flags |= IFF_NOARP; | ||
601 | } else | ||
602 | return on_off("noarp", *argv); | ||
603 | } else if (strcmp(*argv, "vf") == 0) { | ||
604 | struct rtattr *vflist; | ||
605 | NEXT_ARG(); | ||
606 | if (get_integer(&vf, *argv, 0)) { | ||
607 | invarg_1_to_2(*argv, "vf"); | ||
608 | } | ||
609 | vflist = addattr_nest(&req->n, sizeof(*req), | ||
610 | IFLA_VFINFO_LIST); | ||
611 | len = iplink_parse_vf(vf, &argc, &argv, req); | ||
612 | if (len < 0) | ||
613 | return -1; | ||
614 | addattr_nest_end(&req->n, vflist); | ||
615 | } else if (matches(*argv, "master") == 0) { | ||
616 | int ifindex; | ||
617 | NEXT_ARG(); | ||
618 | ifindex = ll_name_to_index(*argv); | ||
619 | if (!ifindex) | ||
620 | invarg_1_to_2(*argv, "master"); | ||
621 | addattr_l(&req->n, sizeof(*req), IFLA_MASTER, | ||
622 | &ifindex, 4); | ||
623 | } else if (matches(*argv, "nomaster") == 0) { | ||
624 | int ifindex = 0; | ||
625 | addattr_l(&req->n, sizeof(*req), IFLA_MASTER, | ||
626 | &ifindex, 4); | ||
627 | } else if (matches(*argv, "dynamic") == 0) { | ||
628 | NEXT_ARG(); | ||
629 | req->i.ifi_change |= IFF_DYNAMIC; | ||
630 | if (strcmp(*argv, "on") == 0) { | ||
631 | req->i.ifi_flags |= IFF_DYNAMIC; | ||
632 | } else if (strcmp(*argv, "off") == 0) { | ||
633 | req->i.ifi_flags &= ~IFF_DYNAMIC; | ||
634 | } else | ||
635 | return on_off("dynamic", *argv); | ||
636 | } else if (matches(*argv, "alias") == 0) { | ||
637 | NEXT_ARG(); | ||
638 | addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS, | ||
639 | *argv, strlen(*argv)); | ||
640 | argc--; argv++; | ||
641 | break; | ||
642 | } else if (strcmp(*argv, "group") == 0) { | ||
643 | NEXT_ARG(); | ||
644 | if (*group != -1) | ||
645 | duparg("group", *argv); | ||
646 | if (rtnl_group_a2n(group, *argv)) | ||
647 | invarg_1_to_2(*argv, "group"); | ||
648 | } else if (strcmp(*argv, "mode") == 0) { | ||
649 | int mode; | ||
650 | NEXT_ARG(); | ||
651 | mode = get_link_mode(*argv); | ||
652 | if (mode < 0) | ||
653 | invarg_1_to_2(*argv, "mode"); | ||
654 | addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode); | ||
655 | } else if (strcmp(*argv, "state") == 0) { | ||
656 | int state; | ||
657 | NEXT_ARG(); | ||
658 | state = get_operstate(*argv); | ||
659 | if (state < 0) | ||
660 | invarg_1_to_2(*argv, "state"); | ||
661 | addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state); | ||
662 | } else if (matches(*argv, "numtxqueues") == 0) { | ||
663 | NEXT_ARG(); | ||
664 | if (numtxqueues != -1) | ||
665 | duparg("numtxqueues", *argv); | ||
666 | if (get_integer(&numtxqueues, *argv, 0)) | ||
667 | invarg_1_to_2(*argv, "numtxqueues"); | ||
668 | addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES, | ||
669 | &numtxqueues, 4); | ||
670 | } else if (matches(*argv, "numrxqueues") == 0) { | ||
671 | NEXT_ARG(); | ||
672 | if (numrxqueues != -1) | ||
673 | duparg("numrxqueues", *argv); | ||
674 | if (get_integer(&numrxqueues, *argv, 0)) | ||
675 | invarg_1_to_2(*argv, "numrxqueues"); | ||
676 | addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES, | ||
677 | &numrxqueues, 4); | ||
678 | } | ||
679 | #endif | ||
680 | |||
681 | /* Return value becomes exitcode. It's okay to not return at all */ | 651 | /* Return value becomes exitcode. It's okay to not return at all */ |
682 | int FAST_FUNC do_iplink(char **argv) | 652 | int FAST_FUNC do_iplink(char **argv) |
683 | { | 653 | { |