1 /* vi: set sw=4 ts=4: */
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
5 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
8 * Laszlo Valko <valko@linux.karinthy.hu> 990223: address label must be zero terminated
13 #include <net/if_arp.h>
15 #include "ip_common.h" /* #include "libbb.h" is inside */
21 #define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
27 struct rtnl_handle
*rth
;
40 typedef struct filter_t filter_t
;
42 #define G_filter (*(filter_t*)&bb_common_bufsiz1)
45 static void print_link_flags(unsigned flags
, unsigned mdown
)
47 static const int flag_masks
[] = {
48 IFF_LOOPBACK
, IFF_BROADCAST
, IFF_POINTOPOINT
,
49 IFF_MULTICAST
, IFF_NOARP
, IFF_UP
, IFF_LOWER_UP
};
50 static const char flag_labels
[] ALIGN1
=
51 "LOOPBACK\0""BROADCAST\0""POINTOPOINT\0"
52 "MULTICAST\0""NOARP\0""UP\0""LOWER_UP\0";
55 if (flags
& IFF_UP
&& !(flags
& IFF_RUNNING
))
56 printf("NO-CARRIER,");
57 flags
&= ~IFF_RUNNING
;
69 flags
= print_flags_separated(flag_masks
, flag_labels
, flags
, ",");
77 static void print_queuelen(char *name
)
82 s
= socket(AF_INET
, SOCK_STREAM
, 0);
86 memset(&ifr
, 0, sizeof(ifr
));
87 strncpy_IFNAMSIZ(ifr
.ifr_name
, name
);
88 if (ioctl_or_warn(s
, SIOCGIFTXQLEN
, &ifr
) < 0) {
95 printf("qlen %d", ifr
.ifr_qlen
);
98 static NOINLINE
int print_linkinfo(const struct nlmsghdr
*n
)
100 struct ifinfomsg
*ifi
= NLMSG_DATA(n
);
101 struct rtattr
*tb
[IFLA_MAX
+1];
102 int len
= n
->nlmsg_len
;
104 if (n
->nlmsg_type
!= RTM_NEWLINK
&& n
->nlmsg_type
!= RTM_DELLINK
)
107 len
-= NLMSG_LENGTH(sizeof(*ifi
));
111 if (G_filter
.ifindex
&& ifi
->ifi_index
!= G_filter
.ifindex
)
113 if (G_filter
.up
&& !(ifi
->ifi_flags
& IFF_UP
))
116 memset(tb
, 0, sizeof(tb
));
117 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), len
);
118 if (tb
[IFLA_IFNAME
] == NULL
) {
119 bb_error_msg("nil ifname");
123 && (!G_filter
.family
|| G_filter
.family
== AF_PACKET
)
124 && fnmatch(G_filter
.label
, RTA_DATA(tb
[IFLA_IFNAME
]), 0)
129 if (n
->nlmsg_type
== RTM_DELLINK
)
132 printf("%d: %s", ifi
->ifi_index
,
133 /*tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>" - we checked tb[IFLA_IFNAME] above*/
134 (char*)RTA_DATA(tb
[IFLA_IFNAME
])
141 int iflink
= *(int*)RTA_DATA(tb
[IFLA_LINK
]);
145 printf("@%s: ", ll_idx_n2a(iflink
, b1
));
146 m_flag
= ll_index_to_flags(iflink
);
147 m_flag
= !(m_flag
& IFF_UP
);
152 print_link_flags(ifi
->ifi_flags
, m_flag
);
156 printf("mtu %u ", *(int*)RTA_DATA(tb
[IFLA_MTU
]));
158 printf("qdisc %s ", (char*)RTA_DATA(tb
[IFLA_QDISC
]));
160 if (tb
[IFLA_MASTER
]) {
162 printf("master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb
[IFLA_MASTER
]), b1
));
165 /* IFLA_OPERSTATE was added to kernel with the same commit as IFF_DORMANT */
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
])));
175 if (G_filter
.showqueue
)
176 print_queuelen((char*)RTA_DATA(tb
[IFLA_IFNAME
]));
178 if (!G_filter
.family
|| G_filter
.family
== AF_PACKET
) {
180 printf("%c link/%s ", _SL_
, ll_type_n2a(ifi
->ifi_type
, b1
));
182 if (tb
[IFLA_ADDRESS
]) {
183 fputs(ll_addr_n2a(RTA_DATA(tb
[IFLA_ADDRESS
]),
184 RTA_PAYLOAD(tb
[IFLA_ADDRESS
]),
186 b1
, sizeof(b1
)), stdout
);
188 if (tb
[IFLA_BROADCAST
]) {
189 if (ifi
->ifi_flags
& IFF_POINTOPOINT
)
193 fputs(ll_addr_n2a(RTA_DATA(tb
[IFLA_BROADCAST
]),
194 RTA_PAYLOAD(tb
[IFLA_BROADCAST
]),
196 b1
, sizeof(b1
)), stdout
);
204 static int flush_update(void)
206 if (rtnl_send(G_filter
.rth
, G_filter
.flushb
, G_filter
.flushp
) < 0) {
207 bb_perror_msg("can't send flush request");
214 static int FAST_FUNC
print_addrinfo(const struct sockaddr_nl
*who UNUSED_PARAM
,
215 struct nlmsghdr
*n
, void *arg UNUSED_PARAM
)
217 struct ifaddrmsg
*ifa
= NLMSG_DATA(n
);
218 int len
= n
->nlmsg_len
;
219 struct rtattr
* rta_tb
[IFA_MAX
+1];
223 if (n
->nlmsg_type
!= RTM_NEWADDR
&& n
->nlmsg_type
!= RTM_DELADDR
)
225 len
-= NLMSG_LENGTH(sizeof(*ifa
));
227 bb_error_msg("wrong nlmsg len %d", len
);
231 if (G_filter
.flushb
&& n
->nlmsg_type
!= RTM_NEWADDR
)
234 memset(rta_tb
, 0, sizeof(rta_tb
));
235 parse_rtattr(rta_tb
, IFA_MAX
, IFA_RTA(ifa
), n
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifa
)));
237 if (!rta_tb
[IFA_LOCAL
])
238 rta_tb
[IFA_LOCAL
] = rta_tb
[IFA_ADDRESS
];
239 if (!rta_tb
[IFA_ADDRESS
])
240 rta_tb
[IFA_ADDRESS
] = rta_tb
[IFA_LOCAL
];
242 if (G_filter
.ifindex
&& G_filter
.ifindex
!= ifa
->ifa_index
)
244 if ((G_filter
.scope
^ ifa
->ifa_scope
) & G_filter
.scopemask
)
246 if ((G_filter
.flags
^ ifa
->ifa_flags
) & G_filter
.flagmask
)
248 if (G_filter
.label
) {
250 if (rta_tb
[IFA_LABEL
])
251 label
= RTA_DATA(rta_tb
[IFA_LABEL
]);
253 label
= ll_idx_n2a(ifa
->ifa_index
, b1
);
254 if (fnmatch(G_filter
.label
, label
, 0) != 0)
257 if (G_filter
.pfx
.family
) {
258 if (rta_tb
[IFA_LOCAL
]) {
260 memset(&dst
, 0, sizeof(dst
));
261 dst
.family
= ifa
->ifa_family
;
262 memcpy(&dst
.data
, RTA_DATA(rta_tb
[IFA_LOCAL
]), RTA_PAYLOAD(rta_tb
[IFA_LOCAL
]));
263 if (inet_addr_match(&dst
, &G_filter
.pfx
, G_filter
.pfx
.bitlen
))
268 if (G_filter
.flushb
) {
270 if (NLMSG_ALIGN(G_filter
.flushp
) + n
->nlmsg_len
> G_filter
.flushe
) {
274 fn
= (struct nlmsghdr
*)(G_filter
.flushb
+ NLMSG_ALIGN(G_filter
.flushp
));
275 memcpy(fn
, n
, n
->nlmsg_len
);
276 fn
->nlmsg_type
= RTM_DELADDR
;
277 fn
->nlmsg_flags
= NLM_F_REQUEST
;
278 fn
->nlmsg_seq
= ++G_filter
.rth
->seq
;
279 G_filter
.flushp
= (((char*)fn
) + n
->nlmsg_len
) - G_filter
.flushb
;
280 G_filter
.flushed
= 1;
284 if (n
->nlmsg_type
== RTM_DELADDR
)
287 if (G_filter
.oneline
)
288 printf("%u: %s", ifa
->ifa_index
, ll_index_to_name(ifa
->ifa_index
));
289 if (ifa
->ifa_family
== AF_INET
)
291 else if (ifa
->ifa_family
== AF_INET6
)
294 printf(" family %d ", ifa
->ifa_family
);
296 if (rta_tb
[IFA_LOCAL
]) {
297 fputs(rt_addr_n2a(ifa
->ifa_family
,
298 RTA_DATA(rta_tb
[IFA_LOCAL
]),
299 abuf
, sizeof(abuf
)), stdout
);
301 if (rta_tb
[IFA_ADDRESS
] == NULL
302 || memcmp(RTA_DATA(rta_tb
[IFA_ADDRESS
]), RTA_DATA(rta_tb
[IFA_LOCAL
]), 4) == 0
304 printf("/%d ", ifa
->ifa_prefixlen
);
306 printf(" peer %s/%d ",
307 rt_addr_n2a(ifa
->ifa_family
,
308 RTA_DATA(rta_tb
[IFA_ADDRESS
]),
314 if (rta_tb
[IFA_BROADCAST
]) {
316 rt_addr_n2a(ifa
->ifa_family
,
317 RTA_DATA(rta_tb
[IFA_BROADCAST
]),
321 if (rta_tb
[IFA_ANYCAST
]) {
323 rt_addr_n2a(ifa
->ifa_family
,
324 RTA_DATA(rta_tb
[IFA_ANYCAST
]),
328 printf("scope %s ", rtnl_rtscope_n2a(ifa
->ifa_scope
, b1
));
329 if (ifa
->ifa_flags
& IFA_F_SECONDARY
) {
330 ifa
->ifa_flags
&= ~IFA_F_SECONDARY
;
331 printf("secondary ");
333 if (ifa
->ifa_flags
& IFA_F_TENTATIVE
) {
334 ifa
->ifa_flags
&= ~IFA_F_TENTATIVE
;
335 printf("tentative ");
337 if (ifa
->ifa_flags
& IFA_F_DEPRECATED
) {
338 ifa
->ifa_flags
&= ~IFA_F_DEPRECATED
;
339 printf("deprecated ");
341 if (!(ifa
->ifa_flags
& IFA_F_PERMANENT
)) {
344 ifa
->ifa_flags
&= ~IFA_F_PERMANENT
;
346 printf("flags %02x ", ifa
->ifa_flags
);
347 if (rta_tb
[IFA_LABEL
])
348 fputs((char*)RTA_DATA(rta_tb
[IFA_LABEL
]), stdout
);
349 if (rta_tb
[IFA_CACHEINFO
]) {
350 struct ifa_cacheinfo
*ci
= RTA_DATA(rta_tb
[IFA_CACHEINFO
]);
353 if (ci
->ifa_valid
== 0xFFFFFFFFU
)
354 sprintf(buf
, "valid_lft forever");
356 sprintf(buf
, "valid_lft %dsec", ci
->ifa_valid
);
357 if (ci
->ifa_prefered
== 0xFFFFFFFFU
)
358 sprintf(buf
+strlen(buf
), " preferred_lft forever");
360 sprintf(buf
+strlen(buf
), " preferred_lft %dsec", ci
->ifa_prefered
);
370 struct nlmsg_list
*next
;
374 static int print_selected_addrinfo(int ifindex
, struct nlmsg_list
*ainfo
)
376 for (; ainfo
; ainfo
= ainfo
->next
) {
377 struct nlmsghdr
*n
= &ainfo
->h
;
378 struct ifaddrmsg
*ifa
= NLMSG_DATA(n
);
380 if (n
->nlmsg_type
!= RTM_NEWADDR
)
382 if (n
->nlmsg_len
< NLMSG_LENGTH(sizeof(ifa
)))
384 if (ifa
->ifa_index
!= ifindex
385 || (G_filter
.family
&& G_filter
.family
!= ifa
->ifa_family
)
389 print_addrinfo(NULL
, n
, NULL
);
395 static int FAST_FUNC
store_nlmsg(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
, void *arg
)
397 struct nlmsg_list
**linfo
= (struct nlmsg_list
**)arg
;
398 struct nlmsg_list
*h
;
399 struct nlmsg_list
**lp
;
401 h
= xzalloc(n
->nlmsg_len
+ sizeof(void*));
403 memcpy(&h
->h
, n
, n
->nlmsg_len
);
404 /*h->next = NULL; - xzalloc did it */
406 for (lp
= linfo
; *lp
; lp
= &(*lp
)->next
)
410 ll_remember_index(who
, n
, NULL
);
414 static void ipaddr_reset_filter(int _oneline
)
416 memset(&G_filter
, 0, sizeof(G_filter
));
417 G_filter
.oneline
= _oneline
;
420 /* Return value becomes exitcode. It's okay to not return at all */
421 int FAST_FUNC
ipaddr_list_or_flush(char **argv
, int flush
)
423 static const char option
[] ALIGN1
= "to\0""scope\0""up\0""label\0""dev\0";
425 struct nlmsg_list
*linfo
= NULL
;
426 struct nlmsg_list
*ainfo
= NULL
;
427 struct nlmsg_list
*l
;
428 struct rtnl_handle rth
;
429 char *filter_dev
= NULL
;
432 ipaddr_reset_filter(oneline
);
433 G_filter
.showqueue
= 1;
435 if (G_filter
.family
== AF_UNSPEC
)
436 G_filter
.family
= preferred_family
;
440 bb_error_msg_and_die(bb_msg_requires_arg
, "flush");
442 if (G_filter
.family
== AF_PACKET
) {
443 bb_error_msg_and_die("can't flush link addresses");
448 const smalluint key
= index_in_strings(option
, *argv
);
449 if (key
== 0) { /* to */
451 get_prefix(&G_filter
.pfx
, *argv
, G_filter
.family
);
452 if (G_filter
.family
== AF_UNSPEC
) {
453 G_filter
.family
= G_filter
.pfx
.family
;
455 } else if (key
== 1) { /* scope */
458 G_filter
.scopemask
= -1;
459 if (rtnl_rtscope_a2n(&scope
, *argv
)) {
460 if (strcmp(*argv
, "all") != 0) {
461 invarg(*argv
, "scope");
463 scope
= RT_SCOPE_NOWHERE
;
464 G_filter
.scopemask
= 0;
466 G_filter
.scope
= scope
;
467 } else if (key
== 2) { /* up */
469 } else if (key
== 3) { /* label */
471 G_filter
.label
= *argv
;
473 if (key
== 4) /* dev */
476 duparg2("dev", *argv
);
484 xrtnl_wilddump_request(&rth
, preferred_family
, RTM_GETLINK
);
485 xrtnl_dump_filter(&rth
, store_nlmsg
, &linfo
);
488 G_filter
.ifindex
= xll_name_to_index(filter_dev
);
492 char flushb
[4096-512];
494 G_filter
.flushb
= flushb
;
496 G_filter
.flushe
= sizeof(flushb
);
500 xrtnl_wilddump_request(&rth
, G_filter
.family
, RTM_GETADDR
);
501 G_filter
.flushed
= 0;
502 xrtnl_dump_filter(&rth
, print_addrinfo
, NULL
);
503 if (G_filter
.flushed
== 0) {
506 if (flush_update() < 0) {
512 if (G_filter
.family
!= AF_PACKET
) {
513 xrtnl_wilddump_request(&rth
, G_filter
.family
, RTM_GETADDR
);
514 xrtnl_dump_filter(&rth
, store_nlmsg
, &ainfo
);
518 if (G_filter
.family
&& G_filter
.family
!= AF_PACKET
) {
519 struct nlmsg_list
**lp
;
522 if (G_filter
.oneline
)
525 while ((l
= *lp
) != NULL
) {
527 struct ifinfomsg
*ifi
= NLMSG_DATA(&l
->h
);
528 struct nlmsg_list
*a
;
530 for (a
= ainfo
; a
; a
= a
->next
) {
531 struct nlmsghdr
*n
= &a
->h
;
532 struct ifaddrmsg
*ifa
= NLMSG_DATA(n
);
534 if (ifa
->ifa_index
!= ifi
->ifi_index
535 || (G_filter
.family
&& G_filter
.family
!= ifa
->ifa_family
)
539 if ((G_filter
.scope
^ ifa
->ifa_scope
) & G_filter
.scopemask
)
541 if ((G_filter
.flags
^ ifa
->ifa_flags
) & G_filter
.flagmask
)
543 if (G_filter
.pfx
.family
|| G_filter
.label
) {
544 struct rtattr
*tb
[IFA_MAX
+1];
545 memset(tb
, 0, sizeof(tb
));
546 parse_rtattr(tb
, IFA_MAX
, IFA_RTA(ifa
), IFA_PAYLOAD(n
));
548 tb
[IFA_LOCAL
] = tb
[IFA_ADDRESS
];
550 if (G_filter
.pfx
.family
&& tb
[IFA_LOCAL
]) {
552 memset(&dst
, 0, sizeof(dst
));
553 dst
.family
= ifa
->ifa_family
;
554 memcpy(&dst
.data
, RTA_DATA(tb
[IFA_LOCAL
]), RTA_PAYLOAD(tb
[IFA_LOCAL
]));
555 if (inet_addr_match(&dst
, &G_filter
.pfx
, G_filter
.pfx
.bitlen
))
558 if (G_filter
.label
) {
562 label
= RTA_DATA(tb
[IFA_LABEL
]);
564 label
= ll_idx_n2a(ifa
->ifa_index
, b1
);
565 if (fnmatch(G_filter
.label
, label
, 0) != 0)
580 for (l
= linfo
; l
; l
= l
->next
) {
581 if (no_link
|| print_linkinfo(&l
->h
) == 0) {
582 struct ifinfomsg
*ifi
= NLMSG_DATA(&l
->h
);
583 if (G_filter
.family
!= AF_PACKET
)
584 print_selected_addrinfo(ifi
->ifi_index
, ainfo
);
591 static int default_scope(inet_prefix
*lcl
)
593 if (lcl
->family
== AF_INET
) {
594 if (lcl
->bytelen
>= 1 && *(uint8_t*)&lcl
->data
== 127)
595 return RT_SCOPE_HOST
;
600 /* Return value becomes exitcode. It's okay to not return at all */
601 static int ipaddr_modify(int cmd
, char **argv
)
603 static const char option
[] ALIGN1
=
604 "peer\0""remote\0""broadcast\0""brd\0"
605 "anycast\0""scope\0""dev\0""label\0""local\0";
606 struct rtnl_handle rth
;
609 struct ifaddrmsg ifa
;
622 memset(&req
, 0, sizeof(req
));
624 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifaddrmsg
));
625 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
626 req
.n
.nlmsg_type
= cmd
;
627 req
.ifa
.ifa_family
= preferred_family
;
630 const smalluint arg
= index_in_strings(option
, *argv
);
631 if (arg
<= 1) { /* peer, remote */
635 duparg("peer", *argv
);
637 get_prefix(&peer
, *argv
, req
.ifa
.ifa_family
);
638 peer_len
= peer
.bytelen
;
639 if (req
.ifa
.ifa_family
== AF_UNSPEC
) {
640 req
.ifa
.ifa_family
= peer
.family
;
642 addattr_l(&req
.n
, sizeof(req
), IFA_ADDRESS
, &peer
.data
, peer
.bytelen
);
643 req
.ifa
.ifa_prefixlen
= peer
.bitlen
;
644 } else if (arg
<= 3) { /* broadcast, brd */
648 duparg("broadcast", *argv
);
650 if (LONE_CHAR(*argv
, '+')) {
652 } else if (LONE_DASH(*argv
)) {
655 get_addr(&addr
, *argv
, req
.ifa
.ifa_family
);
656 if (req
.ifa
.ifa_family
== AF_UNSPEC
)
657 req
.ifa
.ifa_family
= addr
.family
;
658 addattr_l(&req
.n
, sizeof(req
), IFA_BROADCAST
, &addr
.data
, addr
.bytelen
);
659 brd_len
= addr
.bytelen
;
661 } else if (arg
== 4) { /* anycast */
665 duparg("anycast", *argv
);
667 get_addr(&addr
, *argv
, req
.ifa
.ifa_family
);
668 if (req
.ifa
.ifa_family
== AF_UNSPEC
) {
669 req
.ifa
.ifa_family
= addr
.family
;
671 addattr_l(&req
.n
, sizeof(req
), IFA_ANYCAST
, &addr
.data
, addr
.bytelen
);
672 any_len
= addr
.bytelen
;
673 } else if (arg
== 5) { /* scope */
676 if (rtnl_rtscope_a2n(&scope
, *argv
)) {
677 invarg(*argv
, "scope");
679 req
.ifa
.ifa_scope
= scope
;
681 } else if (arg
== 6) { /* dev */
684 } else if (arg
== 7) { /* label */
687 addattr_l(&req
.n
, sizeof(req
), IFA_LABEL
, l
, strlen(l
) + 1);
689 if (arg
== 8) /* local */
692 duparg2("local", *argv
);
694 get_prefix(&lcl
, *argv
, req
.ifa
.ifa_family
);
695 if (req
.ifa
.ifa_family
== AF_UNSPEC
) {
696 req
.ifa
.ifa_family
= lcl
.family
;
698 addattr_l(&req
.n
, sizeof(req
), IFA_LOCAL
, &lcl
.data
, lcl
.bytelen
);
699 local_len
= lcl
.bytelen
;
705 /* There was no "dev IFACE", but we need that */
706 bb_error_msg_and_die("need \"dev IFACE\"");
708 if (l
&& strncmp(d
, l
, strlen(d
)) != 0) {
709 bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s)", d
, l
);
712 if (peer_len
== 0 && local_len
&& cmd
!= RTM_DELADDR
) {
714 addattr_l(&req
.n
, sizeof(req
), IFA_ADDRESS
, &lcl
.data
, lcl
.bytelen
);
716 if (req
.ifa
.ifa_prefixlen
== 0)
717 req
.ifa
.ifa_prefixlen
= lcl
.bitlen
;
719 if (brd_len
< 0 && cmd
!= RTM_DELADDR
) {
722 if (req
.ifa
.ifa_family
!= AF_INET
) {
723 bb_error_msg_and_die("broadcast can be set only for IPv4 addresses");
726 if (brd
.bitlen
<= 30) {
727 for (i
=31; i
>=brd
.bitlen
; i
--) {
729 brd
.data
[0] |= htonl(1<<(31-i
));
731 brd
.data
[0] &= ~htonl(1<<(31-i
));
733 addattr_l(&req
.n
, sizeof(req
), IFA_BROADCAST
, &brd
.data
, brd
.bytelen
);
734 brd_len
= brd
.bytelen
;
737 if (!scoped
&& cmd
!= RTM_DELADDR
)
738 req
.ifa
.ifa_scope
= default_scope(&lcl
);
744 req
.ifa
.ifa_index
= xll_name_to_index(d
);
746 if (rtnl_talk(&rth
, &req
.n
, 0, 0, NULL
, NULL
, NULL
) < 0)
752 /* Return value becomes exitcode. It's okay to not return at all */
753 int FAST_FUNC
do_ipaddr(char **argv
)
755 static const char commands
[] ALIGN1
=
756 "add\0""delete\0""list\0""show\0""lst\0""flush\0";
759 cmd
= index_in_substrings(commands
, *argv
);
761 bb_error_msg_and_die(bb_msg_invalid_arg
, *argv
, applet_name
);
764 return ipaddr_modify((cmd
== 0) ? RTM_NEWADDR
: RTM_DELADDR
, argv
);
766 /* 2 == list, 3 == show, 4 == lst */
767 return ipaddr_list_or_flush(argv
, cmd
== 5);