1 /* vi: set sw=4 ts=4: */
3 * ipaddress.c "ip address".
5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 * Laszlo Valko <valko@linux.karinthy.hu> 990223: address label must be zero terminated
15 #include <net/if_arp.h>
17 #include "ip_common.h" /* #include "libbb.h" is inside */
23 #define IFF_LOWER_UP 0x10000 /* driver signals L1 up*/
29 struct rtnl_handle *rth;
42 typedef struct filter_t filter_t;
44 #define G_filter (*(filter_t*)&bb_common_bufsiz1)
47 static void print_link_flags(unsigned flags, unsigned mdown)
49 static const int flag_masks[] = {
50 IFF_LOOPBACK, IFF_BROADCAST, IFF_POINTOPOINT,
51 IFF_MULTICAST, IFF_NOARP, IFF_UP, IFF_LOWER_UP };
52 static const char flag_labels[] ALIGN1 =
53 "LOOPBACK\0""BROADCAST\0""POINTOPOINT\0"
54 "MULTICAST\0""NOARP\0""UP\0""LOWER_UP\0";
57 if (flags & IFF_UP && !(flags & IFF_RUNNING))
58 printf("NO-CARRIER,");
59 flags &= ~IFF_RUNNING;
71 flags = print_flags_separated(flag_masks, flag_labels, flags, ",");
79 static void print_queuelen(char *name)
84 s = socket(AF_INET, SOCK_STREAM, 0);
88 memset(&ifr, 0, sizeof(ifr));
89 strncpy_IFNAMSIZ(ifr.ifr_name, name);
90 if (ioctl_or_warn(s, SIOCGIFTXQLEN, &ifr) < 0) {
97 printf("qlen %d", ifr.ifr_qlen);
100 static NOINLINE int print_linkinfo(const struct nlmsghdr *n)
102 struct ifinfomsg *ifi = NLMSG_DATA(n);
103 struct rtattr *tb[IFLA_MAX+1];
104 int len = n->nlmsg_len;
106 if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
109 len -= NLMSG_LENGTH(sizeof(*ifi));
113 if (G_filter.ifindex && ifi->ifi_index != G_filter.ifindex)
115 if (G_filter.up && !(ifi->ifi_flags & IFF_UP))
118 memset(tb, 0, sizeof(tb));
119 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
120 if (tb[IFLA_IFNAME] == NULL) {
121 bb_error_msg("nil ifname");
125 && (!G_filter.family || G_filter.family == AF_PACKET)
126 && fnmatch(G_filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0)
131 if (n->nlmsg_type == RTM_DELLINK)
134 printf("%d: %s", ifi->ifi_index,
135 /*tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>" - we checked tb[IFLA_IFNAME] above*/
136 (char*)RTA_DATA(tb[IFLA_IFNAME])
143 int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]);
147 printf("@%s: ", ll_idx_n2a(iflink, b1));
148 m_flag = ll_index_to_flags(iflink);
149 m_flag = !(m_flag & IFF_UP);
154 print_link_flags(ifi->ifi_flags, m_flag);
158 printf("mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));
160 printf("qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));
162 if (tb[IFLA_MASTER]) {
164 printf("master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
167 if (tb[IFLA_OPERSTATE]) {
168 static const char operstate_labels[] ALIGN1 =
169 "UNKNOWN\0""NOTPRESENT\0""DOWN\0""LOWERLAYERDOWN\0"
170 "TESTING\0""DORMANT\0""UP\0";
171 printf("state %s ", nth_string(operstate_labels,
172 *(uint8_t *)RTA_DATA(tb[IFLA_OPERSTATE])));
174 if (G_filter.showqueue)
175 print_queuelen((char*)RTA_DATA(tb[IFLA_IFNAME]));
177 if (!G_filter.family || G_filter.family == AF_PACKET) {
179 printf("%c link/%s ", _SL_, ll_type_n2a(ifi->ifi_type, b1));
181 if (tb[IFLA_ADDRESS]) {
182 fputs(ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
183 RTA_PAYLOAD(tb[IFLA_ADDRESS]),
185 b1, sizeof(b1)), stdout);
187 if (tb[IFLA_BROADCAST]) {
188 if (ifi->ifi_flags & IFF_POINTOPOINT)
192 fputs(ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
193 RTA_PAYLOAD(tb[IFLA_BROADCAST]),
195 b1, sizeof(b1)), stdout);
203 static int flush_update(void)
205 if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
206 bb_perror_msg("can't send flush request");
213 static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
214 struct nlmsghdr *n, void *arg UNUSED_PARAM)
216 struct ifaddrmsg *ifa = NLMSG_DATA(n);
217 int len = n->nlmsg_len;
218 struct rtattr * rta_tb[IFA_MAX+1];
222 if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
224 len -= NLMSG_LENGTH(sizeof(*ifa));
226 bb_error_msg("wrong nlmsg len %d", len);
230 if (G_filter.flushb && n->nlmsg_type != RTM_NEWADDR)
233 memset(rta_tb, 0, sizeof(rta_tb));
234 parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
236 if (!rta_tb[IFA_LOCAL])
237 rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
238 if (!rta_tb[IFA_ADDRESS])
239 rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];
241 if (G_filter.ifindex && G_filter.ifindex != ifa->ifa_index)
243 if ((G_filter.scope ^ ifa->ifa_scope) & G_filter.scopemask)
245 if ((G_filter.flags ^ ifa->ifa_flags) & G_filter.flagmask)
247 if (G_filter.label) {
249 if (rta_tb[IFA_LABEL])
250 label = RTA_DATA(rta_tb[IFA_LABEL]);
252 label = ll_idx_n2a(ifa->ifa_index, b1);
253 if (fnmatch(G_filter.label, label, 0) != 0)
256 if (G_filter.pfx.family) {
257 if (rta_tb[IFA_LOCAL]) {
259 memset(&dst, 0, sizeof(dst));
260 dst.family = ifa->ifa_family;
261 memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL]));
262 if (inet_addr_match(&dst, &G_filter.pfx, G_filter.pfx.bitlen))
267 if (G_filter.flushb) {
269 if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) {
273 fn = (struct nlmsghdr*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp));
274 memcpy(fn, n, n->nlmsg_len);
275 fn->nlmsg_type = RTM_DELADDR;
276 fn->nlmsg_flags = NLM_F_REQUEST;
277 fn->nlmsg_seq = ++G_filter.rth->seq;
278 G_filter.flushp = (((char*)fn) + n->nlmsg_len) - G_filter.flushb;
279 G_filter.flushed = 1;
283 if (n->nlmsg_type == RTM_DELADDR)
286 if (G_filter.oneline)
287 printf("%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
288 if (ifa->ifa_family == AF_INET)
290 else if (ifa->ifa_family == AF_INET6)
293 printf(" family %d ", ifa->ifa_family);
295 if (rta_tb[IFA_LOCAL]) {
296 fputs(rt_addr_n2a(ifa->ifa_family,
297 RTA_DATA(rta_tb[IFA_LOCAL]),
298 abuf, sizeof(abuf)), stdout);
300 if (rta_tb[IFA_ADDRESS] == NULL
301 || memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0
303 printf("/%d ", ifa->ifa_prefixlen);
305 printf(" peer %s/%d ",
306 rt_addr_n2a(ifa->ifa_family,
307 RTA_DATA(rta_tb[IFA_ADDRESS]),
313 if (rta_tb[IFA_BROADCAST]) {
315 rt_addr_n2a(ifa->ifa_family,
316 RTA_DATA(rta_tb[IFA_BROADCAST]),
317 abuf, sizeof(abuf)));
319 if (rta_tb[IFA_ANYCAST]) {
321 rt_addr_n2a(ifa->ifa_family,
322 RTA_DATA(rta_tb[IFA_ANYCAST]),
323 abuf, sizeof(abuf)));
325 printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1));
326 if (ifa->ifa_flags & IFA_F_SECONDARY) {
327 ifa->ifa_flags &= ~IFA_F_SECONDARY;
328 printf("secondary ");
330 if (ifa->ifa_flags & IFA_F_TENTATIVE) {
331 ifa->ifa_flags &= ~IFA_F_TENTATIVE;
332 printf("tentative ");
334 if (ifa->ifa_flags & IFA_F_DEPRECATED) {
335 ifa->ifa_flags &= ~IFA_F_DEPRECATED;
336 printf("deprecated ");
338 if (!(ifa->ifa_flags & IFA_F_PERMANENT)) {
341 ifa->ifa_flags &= ~IFA_F_PERMANENT;
343 printf("flags %02x ", ifa->ifa_flags);
344 if (rta_tb[IFA_LABEL])
345 fputs((char*)RTA_DATA(rta_tb[IFA_LABEL]), stdout);
346 if (rta_tb[IFA_CACHEINFO]) {
347 struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
350 if (ci->ifa_valid == 0xFFFFFFFFU)
351 sprintf(buf, "valid_lft forever");
353 sprintf(buf, "valid_lft %dsec", ci->ifa_valid);
354 if (ci->ifa_prefered == 0xFFFFFFFFU)
355 sprintf(buf+strlen(buf), " preferred_lft forever");
357 sprintf(buf+strlen(buf), " preferred_lft %dsec", ci->ifa_prefered);
367 struct nlmsg_list *next;
371 static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo)
373 for (; ainfo; ainfo = ainfo->next) {
374 struct nlmsghdr *n = &ainfo->h;
375 struct ifaddrmsg *ifa = NLMSG_DATA(n);
377 if (n->nlmsg_type != RTM_NEWADDR)
379 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa)))
381 if (ifa->ifa_index != ifindex
382 || (G_filter.family && G_filter.family != ifa->ifa_family)
386 print_addrinfo(NULL, n, NULL);
392 static int FAST_FUNC store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
394 struct nlmsg_list **linfo = (struct nlmsg_list**)arg;
395 struct nlmsg_list *h;
396 struct nlmsg_list **lp;
398 h = xzalloc(n->nlmsg_len + sizeof(void*));
400 memcpy(&h->h, n, n->nlmsg_len);
401 /*h->next = NULL; - xzalloc did it */
403 for (lp = linfo; *lp; lp = &(*lp)->next)
407 ll_remember_index(who, n, NULL);
411 static void ipaddr_reset_filter(int _oneline)
413 memset(&G_filter, 0, sizeof(G_filter));
414 G_filter.oneline = _oneline;
417 /* Return value becomes exitcode. It's okay to not return at all */
418 int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush)
420 static const char option[] ALIGN1 = "to\0""scope\0""up\0""label\0""dev\0";
422 struct nlmsg_list *linfo = NULL;
423 struct nlmsg_list *ainfo = NULL;
424 struct nlmsg_list *l;
425 struct rtnl_handle rth;
426 char *filter_dev = NULL;
429 ipaddr_reset_filter(oneline);
430 G_filter.showqueue = 1;
432 if (G_filter.family == AF_UNSPEC)
433 G_filter.family = preferred_family;
437 bb_error_msg_and_die(bb_msg_requires_arg, "flush");
439 if (G_filter.family == AF_PACKET) {
440 bb_error_msg_and_die("can't flush link addresses");
445 const smalluint key = index_in_strings(option, *argv);
446 if (key == 0) { /* to */
448 get_prefix(&G_filter.pfx, *argv, G_filter.family);
449 if (G_filter.family == AF_UNSPEC) {
450 G_filter.family = G_filter.pfx.family;
452 } else if (key == 1) { /* scope */
455 G_filter.scopemask = -1;
456 if (rtnl_rtscope_a2n(&scope, *argv)) {
457 if (strcmp(*argv, "all") != 0) {
458 invarg(*argv, "scope");
460 scope = RT_SCOPE_NOWHERE;
461 G_filter.scopemask = 0;
463 G_filter.scope = scope;
464 } else if (key == 2) { /* up */
466 } else if (key == 3) { /* label */
468 G_filter.label = *argv;
470 if (key == 4) /* dev */
473 duparg2("dev", *argv);
481 xrtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK);
482 xrtnl_dump_filter(&rth, store_nlmsg, &linfo);
485 G_filter.ifindex = xll_name_to_index(filter_dev);
489 char flushb[4096-512];
491 G_filter.flushb = flushb;
493 G_filter.flushe = sizeof(flushb);
497 xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETADDR);
498 G_filter.flushed = 0;
499 xrtnl_dump_filter(&rth, print_addrinfo, NULL);
500 if (G_filter.flushed == 0) {
503 if (flush_update() < 0) {
509 if (G_filter.family != AF_PACKET) {
510 xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETADDR);
511 xrtnl_dump_filter(&rth, store_nlmsg, &ainfo);
515 if (G_filter.family && G_filter.family != AF_PACKET) {
516 struct nlmsg_list **lp;
519 if (G_filter.oneline)
522 while ((l = *lp) != NULL) {
524 struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
525 struct nlmsg_list *a;
527 for (a = ainfo; a; a = a->next) {
528 struct nlmsghdr *n = &a->h;
529 struct ifaddrmsg *ifa = NLMSG_DATA(n);
531 if (ifa->ifa_index != ifi->ifi_index
532 || (G_filter.family && G_filter.family != ifa->ifa_family)
536 if ((G_filter.scope ^ ifa->ifa_scope) & G_filter.scopemask)
538 if ((G_filter.flags ^ ifa->ifa_flags) & G_filter.flagmask)
540 if (G_filter.pfx.family || G_filter.label) {
541 struct rtattr *tb[IFA_MAX+1];
542 memset(tb, 0, sizeof(tb));
543 parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
545 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
547 if (G_filter.pfx.family && tb[IFA_LOCAL]) {
549 memset(&dst, 0, sizeof(dst));
550 dst.family = ifa->ifa_family;
551 memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
552 if (inet_addr_match(&dst, &G_filter.pfx, G_filter.pfx.bitlen))
555 if (G_filter.label) {
559 label = RTA_DATA(tb[IFA_LABEL]);
561 label = ll_idx_n2a(ifa->ifa_index, b1);
562 if (fnmatch(G_filter.label, label, 0) != 0)
577 for (l = linfo; l; l = l->next) {
578 if (no_link || print_linkinfo(&l->h) == 0) {
579 struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
580 if (G_filter.family != AF_PACKET)
581 print_selected_addrinfo(ifi->ifi_index, ainfo);
588 static int default_scope(inet_prefix *lcl)
590 if (lcl->family == AF_INET) {
591 if (lcl->bytelen >= 1 && *(uint8_t*)&lcl->data == 127)
592 return RT_SCOPE_HOST;
597 /* Return value becomes exitcode. It's okay to not return at all */
598 static int ipaddr_modify(int cmd, char **argv)
600 static const char option[] ALIGN1 =
601 "peer\0""remote\0""broadcast\0""brd\0"
602 "anycast\0""scope\0""dev\0""label\0""local\0";
603 struct rtnl_handle rth;
606 struct ifaddrmsg ifa;
619 memset(&req, 0, sizeof(req));
621 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
622 req.n.nlmsg_flags = NLM_F_REQUEST;
623 req.n.nlmsg_type = cmd;
624 req.ifa.ifa_family = preferred_family;
627 const smalluint arg = index_in_strings(option, *argv);
628 if (arg <= 1) { /* peer, remote */
632 duparg("peer", *argv);
634 get_prefix(&peer, *argv, req.ifa.ifa_family);
635 peer_len = peer.bytelen;
636 if (req.ifa.ifa_family == AF_UNSPEC) {
637 req.ifa.ifa_family = peer.family;
639 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen);
640 req.ifa.ifa_prefixlen = peer.bitlen;
641 } else if (arg <= 3) { /* broadcast, brd */
645 duparg("broadcast", *argv);
647 if (LONE_CHAR(*argv, '+')) {
649 } else if (LONE_DASH(*argv)) {
652 get_addr(&addr, *argv, req.ifa.ifa_family);
653 if (req.ifa.ifa_family == AF_UNSPEC)
654 req.ifa.ifa_family = addr.family;
655 addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen);
656 brd_len = addr.bytelen;
658 } else if (arg == 4) { /* anycast */
662 duparg("anycast", *argv);
664 get_addr(&addr, *argv, req.ifa.ifa_family);
665 if (req.ifa.ifa_family == AF_UNSPEC) {
666 req.ifa.ifa_family = addr.family;
668 addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen);
669 any_len = addr.bytelen;
670 } else if (arg == 5) { /* scope */
673 if (rtnl_rtscope_a2n(&scope, *argv)) {
674 invarg(*argv, "scope");
676 req.ifa.ifa_scope = scope;
678 } else if (arg == 6) { /* dev */
681 } else if (arg == 7) { /* label */
684 addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l) + 1);
686 if (arg == 8) /* local */
689 duparg2("local", *argv);
691 get_prefix(&lcl, *argv, req.ifa.ifa_family);
692 if (req.ifa.ifa_family == AF_UNSPEC) {
693 req.ifa.ifa_family = lcl.family;
695 addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen);
696 local_len = lcl.bytelen;
702 /* There was no "dev IFACE", but we need that */
703 bb_error_msg_and_die("need \"dev IFACE\"");
705 if (l && strncmp(d, l, strlen(d)) != 0) {
706 bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s)", d, l);
709 if (peer_len == 0 && local_len && cmd != RTM_DELADDR) {
711 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen);
713 if (req.ifa.ifa_prefixlen == 0)
714 req.ifa.ifa_prefixlen = lcl.bitlen;
716 if (brd_len < 0 && cmd != RTM_DELADDR) {
719 if (req.ifa.ifa_family != AF_INET) {
720 bb_error_msg_and_die("broadcast can be set only for IPv4 addresses");
723 if (brd.bitlen <= 30) {
724 for (i=31; i>=brd.bitlen; i--) {
726 brd.data[0] |= htonl(1<<(31-i));
728 brd.data[0] &= ~htonl(1<<(31-i));
730 addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen);
731 brd_len = brd.bytelen;
734 if (!scoped && cmd != RTM_DELADDR)
735 req.ifa.ifa_scope = default_scope(&lcl);
741 req.ifa.ifa_index = xll_name_to_index(d);
743 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
749 /* Return value becomes exitcode. It's okay to not return at all */
750 int FAST_FUNC do_ipaddr(char **argv)
752 static const char commands[] ALIGN1 =
753 "add\0""delete\0""list\0""show\0""lst\0""flush\0";
756 cmd = index_in_substrings(commands, *argv);
758 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
761 return ipaddr_modify((cmd == 0) ? RTM_NEWADDR : RTM_DELADDR, argv);
763 /* 2 == list, 3 == show, 4 == lst */
764 return ipaddr_list_or_flush(argv, cmd == 5);