diff options
| author | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2010-05-25 10:34:27 +0200 |
|---|---|---|
| committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2010-05-25 13:39:39 +0200 |
| commit | 6faebfa663fd008fa28f0d69d0663fe80675ebec (patch) | |
| tree | 27213e271f2ef64ec627bb31cec5b9fee5f6086c /networking | |
| parent | 49ee8393f4d11ee3091dcad41ce36741c6a4b4f8 (diff) | |
| download | busybox-w32-6faebfa663fd008fa28f0d69d0663fe80675ebec.tar.gz busybox-w32-6faebfa663fd008fa28f0d69d0663fe80675ebec.tar.bz2 busybox-w32-6faebfa663fd008fa28f0d69d0663fe80675ebec.zip | |
iplink: support add/delete
function old new delta
do_change - 490 +490
.rodata 135193 135225 +32
do_iplink 1146 1169 +23
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/0 up/down: 545/0) Total: 545 bytes
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Diffstat (limited to 'networking')
| -rw-r--r-- | networking/libiproute/iplink.c | 93 |
1 files changed, 91 insertions, 2 deletions
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index df8a354a1..a28df6e79 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c | |||
| @@ -283,11 +283,98 @@ static int ipaddr_list_link(char **argv) | |||
| 283 | return ipaddr_list_or_flush(argv, 0); | 283 | return ipaddr_list_or_flush(argv, 0); |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | #ifndef NLMSG_TAIL | ||
| 287 | #define NLMSG_TAIL(nmsg) \ | ||
| 288 | ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) | ||
| 289 | #endif | ||
| 290 | /* Return value becomes exitcode. It's okay to not return at all */ | ||
| 291 | static int do_change(char **argv, const unsigned rtm) | ||
| 292 | { | ||
| 293 | static const char keywords[] ALIGN1 = | ||
| 294 | "link\0""name\0""type\0""dev\0"; | ||
| 295 | enum { | ||
| 296 | ARG_link, | ||
| 297 | ARG_name, | ||
| 298 | ARG_type, | ||
| 299 | ARG_dev, | ||
| 300 | }; | ||
| 301 | struct rtnl_handle rth; | ||
| 302 | struct { | ||
| 303 | struct nlmsghdr n; | ||
| 304 | struct ifinfomsg i; | ||
| 305 | char buf[1024]; | ||
| 306 | } req; | ||
| 307 | int arg; | ||
| 308 | char *name_str = NULL, *link_str = NULL, *type_str = NULL, *dev_str = NULL; | ||
| 309 | |||
| 310 | memset(&req, 0, sizeof(req)); | ||
| 311 | |||
| 312 | req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); | ||
| 313 | req.n.nlmsg_flags = NLM_F_REQUEST; | ||
| 314 | req.n.nlmsg_type = rtm; | ||
| 315 | req.i.ifi_family = preferred_family; | ||
| 316 | if (rtm == RTM_NEWLINK) | ||
| 317 | req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; | ||
| 318 | |||
| 319 | while (*argv) { | ||
| 320 | arg = index_in_substrings(keywords, *argv); | ||
| 321 | if (arg == ARG_link) { | ||
| 322 | NEXT_ARG(); | ||
| 323 | link_str = *argv; | ||
| 324 | } else if (arg == ARG_name) { | ||
| 325 | NEXT_ARG(); | ||
| 326 | name_str = *argv; | ||
| 327 | } else if (arg == ARG_type) { | ||
| 328 | NEXT_ARG(); | ||
| 329 | type_str = *argv; | ||
| 330 | } else { | ||
| 331 | if (arg == ARG_dev) { | ||
| 332 | if (dev_str) | ||
| 333 | duparg(*argv, "dev"); | ||
| 334 | NEXT_ARG(); | ||
| 335 | } | ||
| 336 | dev_str = *argv; | ||
| 337 | } | ||
| 338 | argv++; | ||
| 339 | } | ||
| 340 | xrtnl_open(&rth); | ||
| 341 | ll_init_map(&rth); | ||
| 342 | if (type_str) { | ||
| 343 | struct rtattr *linkinfo = NLMSG_TAIL(&req.n); | ||
| 344 | |||
| 345 | addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); | ||
| 346 | addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str, | ||
| 347 | strlen(type_str)); | ||
| 348 | linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; | ||
| 349 | } | ||
| 350 | if (rtm != RTM_NEWLINK) { | ||
| 351 | if (!dev_str) | ||
| 352 | return 1; /* Need a device to delete */ | ||
| 353 | req.i.ifi_index = xll_name_to_index(dev_str); | ||
| 354 | } else { | ||
| 355 | if (!name_str) | ||
| 356 | name_str = dev_str; | ||
| 357 | if (link_str) { | ||
| 358 | int idx = xll_name_to_index(link_str); | ||
| 359 | addattr_l(&req.n, sizeof(req), IFLA_LINK, &idx, 4); | ||
| 360 | } | ||
| 361 | } | ||
| 362 | if (name_str) { | ||
| 363 | const size_t name_len = strlen(name_str) + 1; | ||
| 364 | if (name_len < 2 || name_len > IFNAMSIZ) | ||
| 365 | invarg(name_str, "name"); | ||
| 366 | addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name_str, name_len); | ||
| 367 | } | ||
| 368 | if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) | ||
| 369 | return 2; | ||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 286 | /* Return value becomes exitcode. It's okay to not return at all */ | 373 | /* Return value becomes exitcode. It's okay to not return at all */ |
| 287 | int do_iplink(char **argv) | 374 | int do_iplink(char **argv) |
| 288 | { | 375 | { |
| 289 | static const char keywords[] ALIGN1 = | 376 | static const char keywords[] ALIGN1 = |
| 290 | "set\0""show\0""lst\0""list\0"; | 377 | "add\0""delete\0""set\0""show\0""lst\0""list\0"; |
| 291 | int key; | 378 | int key; |
| 292 | if (!*argv) | 379 | if (!*argv) |
| 293 | return ipaddr_list_link(argv); | 380 | return ipaddr_list_link(argv); |
| @@ -295,7 +382,9 @@ int do_iplink(char **argv) | |||
| 295 | if (key < 0) | 382 | if (key < 0) |
| 296 | bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); | 383 | bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); |
| 297 | argv++; | 384 | argv++; |
| 298 | if (key == 0) /* set */ | 385 | if (key <= 1) /* add/delete */ |
| 386 | return do_change(argv, key ? RTM_DELLINK : RTM_NEWLINK); | ||
| 387 | else if (key == 2) /* set */ | ||
| 299 | return do_set(argv); | 388 | return do_set(argv); |
| 300 | /* show, lst, list */ | 389 | /* show, lst, list */ |
| 301 | return ipaddr_list_link(argv); | 390 | return ipaddr_list_link(argv); |
