Only included headers that are used.
[platform/upstream/busybox.git] / networking / libiproute / ipaddress.c
1 /*
2  * ipaddress.c          "ip address".
3  *
4  *              This program is free software; you can redistribute it and/or
5  *              modify it under the terms of the GNU General Public License
6  *              as published by the Free Software Foundation; either version
7  *              2 of the License, or (at your option) any later version.
8  *
9  * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10  *
11  * Changes:
12  *      Laszlo Valko <valko@linux.karinthy.hu> 990223: address label must be zero terminated
13  */
14
15 #include <sys/socket.h>
16 #include <sys/ioctl.h>
17
18 #include <fnmatch.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 #include <arpa/inet.h>
24
25 #define sysinfo kernel_sysinfo
26 #include <linux/if_arp.h>
27 #undef sysinfo
28
29 #include "rt_names.h"
30 #include "utils.h"
31
32 #include "libbb.h"
33
34 static struct
35 {
36         int ifindex;
37         int family;
38         int oneline;
39         int showqueue;
40         inet_prefix pfx;
41         int scope, scopemask;
42         int flags, flagmask;
43         int up;
44         char *label;
45         struct rtnl_handle *rth;
46 } filter;
47
48 void print_link_flags(FILE *fp, unsigned flags, unsigned mdown)
49 {
50         fprintf(fp, "<");
51         flags &= ~IFF_RUNNING;
52 #define _PF(f) if (flags&IFF_##f) { \
53                   flags &= ~IFF_##f ; \
54                   fprintf(fp, #f "%s", flags ? "," : ""); }
55         _PF(LOOPBACK);
56         _PF(BROADCAST);
57         _PF(POINTOPOINT);
58         _PF(MULTICAST);
59         _PF(NOARP);
60 #if 0
61         _PF(ALLMULTI);
62         _PF(PROMISC);
63         _PF(MASTER);
64         _PF(SLAVE);
65         _PF(DEBUG);
66         _PF(DYNAMIC);
67         _PF(AUTOMEDIA);
68         _PF(PORTSEL);
69         _PF(NOTRAILERS);
70 #endif
71         _PF(UP);
72 #undef _PF
73         if (flags)
74                 fprintf(fp, "%x", flags);
75         if (mdown)
76                 fprintf(fp, ",M-DOWN");
77         fprintf(fp, "> ");
78 }
79
80 static void print_queuelen(char *name)
81 {
82         struct ifreq ifr;
83         int s;
84
85         s = socket(AF_INET, SOCK_STREAM, 0);
86         if (s < 0)
87                 return;
88
89         memset(&ifr, 0, sizeof(ifr));
90         strcpy(ifr.ifr_name, name);
91         if (ioctl(s, SIOCGIFTXQLEN, &ifr) < 0) { 
92                 perror("SIOCGIFXQLEN");
93                 close(s);
94                 return;
95         }
96         close(s);
97
98         if (ifr.ifr_qlen)
99                 printf("qlen %d", ifr.ifr_qlen);
100 }
101
102 static int print_linkinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
103 {
104         FILE *fp = (FILE*)arg;
105         struct ifinfomsg *ifi = NLMSG_DATA(n);
106         struct rtattr * tb[IFLA_MAX+1];
107         int len = n->nlmsg_len;
108         unsigned m_flag = 0;
109
110         if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
111                 return 0;
112
113         len -= NLMSG_LENGTH(sizeof(*ifi));
114         if (len < 0)
115                 return -1;
116
117         if (filter.ifindex && ifi->ifi_index != filter.ifindex)
118                 return 0;
119         if (filter.up && !(ifi->ifi_flags&IFF_UP))
120                 return 0;
121
122         memset(tb, 0, sizeof(tb));
123         parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
124         if (tb[IFLA_IFNAME] == NULL) {
125                 error_msg("nil ifname");
126                 return -1;
127         }
128         if (filter.label &&
129             (!filter.family || filter.family == AF_PACKET) &&
130             fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0))
131                 return 0;
132
133         if (n->nlmsg_type == RTM_DELLINK)
134                 fprintf(fp, "Deleted ");
135
136         fprintf(fp, "%d: %s", ifi->ifi_index,
137                 tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>");
138
139         if (tb[IFLA_LINK]) {
140                 SPRINT_BUF(b1);
141                 int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]);
142                 if (iflink == 0)
143                         fprintf(fp, "@NONE: ");
144                 else {
145                         fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
146                         m_flag = ll_index_to_flags(iflink);
147                         m_flag = !(m_flag & IFF_UP);
148                 }
149         } else {
150                 fprintf(fp, ": ");
151         }
152         print_link_flags(fp, ifi->ifi_flags, m_flag);
153
154         if (tb[IFLA_MTU])
155                 fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));
156         if (tb[IFLA_QDISC])
157                 fprintf(fp, "qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));
158 #ifdef IFLA_MASTER
159         if (tb[IFLA_MASTER]) {
160                 SPRINT_BUF(b1);
161                 fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
162         }
163 #endif
164         if (filter.showqueue)
165                 print_queuelen((char*)RTA_DATA(tb[IFLA_IFNAME]));
166         
167         if (!filter.family || filter.family == AF_PACKET) {
168                 SPRINT_BUF(b1);
169                 fprintf(fp, "%s", _SL_);
170                 fprintf(fp, "    link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));
171
172                 if (tb[IFLA_ADDRESS]) {
173                         fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
174                                                       RTA_PAYLOAD(tb[IFLA_ADDRESS]),
175                                                       ifi->ifi_type,
176                                                       b1, sizeof(b1)));
177                 }
178                 if (tb[IFLA_BROADCAST]) {
179                         if (ifi->ifi_flags&IFF_POINTOPOINT)
180                                 fprintf(fp, " peer ");
181                         else
182                                 fprintf(fp, " brd ");
183                         fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
184                                                       RTA_PAYLOAD(tb[IFLA_BROADCAST]),
185                                                       ifi->ifi_type,
186                                                       b1, sizeof(b1)));
187                 }
188         }
189         fprintf(fp, "\n");
190         fflush(fp);
191         return 0;
192 }
193
194 static int print_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
195 {
196         FILE *fp = (FILE*)arg;
197         struct ifaddrmsg *ifa = NLMSG_DATA(n);
198         int len = n->nlmsg_len;
199         struct rtattr * rta_tb[IFA_MAX+1];
200         char abuf[256];
201         SPRINT_BUF(b1);
202
203         if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
204                 return 0;
205         len -= NLMSG_LENGTH(sizeof(*ifa));
206         if (len < 0) {
207                 error_msg("wrong nlmsg len %d", len);
208                 return -1;
209         }
210
211         memset(rta_tb, 0, sizeof(rta_tb));
212         parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
213
214         if (!rta_tb[IFA_LOCAL])
215                 rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
216         if (!rta_tb[IFA_ADDRESS])
217                 rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];
218
219         if (filter.ifindex && filter.ifindex != ifa->ifa_index)
220                 return 0;
221         if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
222                 return 0;
223         if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
224                 return 0;
225         if (filter.label) {
226                 const char *label;
227                 if (rta_tb[IFA_LABEL])
228                         label = RTA_DATA(rta_tb[IFA_LABEL]);
229                 else
230                         label = ll_idx_n2a(ifa->ifa_index, b1);
231                 if (fnmatch(filter.label, label, 0) != 0)
232                         return 0;
233         }
234         if (filter.pfx.family) {
235                 if (rta_tb[IFA_LOCAL]) {
236                         inet_prefix dst;
237                         memset(&dst, 0, sizeof(dst));
238                         dst.family = ifa->ifa_family;
239                         memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL]));
240                         if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
241                                 return 0;
242                 }
243         }
244
245         if (n->nlmsg_type == RTM_DELADDR)
246                 fprintf(fp, "Deleted ");
247
248         if (filter.oneline)
249                 fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
250         if (ifa->ifa_family == AF_INET)
251                 fprintf(fp, "    inet ");
252         else if (ifa->ifa_family == AF_INET6)
253                 fprintf(fp, "    inet6 ");
254         else
255                 fprintf(fp, "    family %d ", ifa->ifa_family);
256
257         if (rta_tb[IFA_LOCAL]) {
258                 fprintf(fp, "%s", rt_addr_n2a(ifa->ifa_family,
259                                               RTA_PAYLOAD(rta_tb[IFA_LOCAL]),
260                                               RTA_DATA(rta_tb[IFA_LOCAL]),
261                                               abuf, sizeof(abuf)));
262
263                 if (rta_tb[IFA_ADDRESS] == NULL ||
264                     memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) {
265                         fprintf(fp, "/%d ", ifa->ifa_prefixlen);
266                 } else {
267                         fprintf(fp, " peer %s/%d ",
268                                 rt_addr_n2a(ifa->ifa_family,
269                                             RTA_PAYLOAD(rta_tb[IFA_ADDRESS]),
270                                             RTA_DATA(rta_tb[IFA_ADDRESS]),
271                                             abuf, sizeof(abuf)),
272                                 ifa->ifa_prefixlen);
273                 }
274         }
275
276         if (rta_tb[IFA_BROADCAST]) {
277                 fprintf(fp, "brd %s ",
278                         rt_addr_n2a(ifa->ifa_family,
279                                     RTA_PAYLOAD(rta_tb[IFA_BROADCAST]),
280                                     RTA_DATA(rta_tb[IFA_BROADCAST]),
281                                     abuf, sizeof(abuf)));
282         }
283         if (rta_tb[IFA_ANYCAST]) {
284                 fprintf(fp, "any %s ",
285                         rt_addr_n2a(ifa->ifa_family,
286                                     RTA_PAYLOAD(rta_tb[IFA_ANYCAST]),
287                                     RTA_DATA(rta_tb[IFA_ANYCAST]),
288                                     abuf, sizeof(abuf)));
289         }
290         fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
291         if (ifa->ifa_flags&IFA_F_SECONDARY) {
292                 ifa->ifa_flags &= ~IFA_F_SECONDARY;
293                 fprintf(fp, "secondary ");
294         }
295         if (ifa->ifa_flags&IFA_F_TENTATIVE) {
296                 ifa->ifa_flags &= ~IFA_F_TENTATIVE;
297                 fprintf(fp, "tentative ");
298         }
299         if (ifa->ifa_flags&IFA_F_DEPRECATED) {
300                 ifa->ifa_flags &= ~IFA_F_DEPRECATED;
301                 fprintf(fp, "deprecated ");
302         }
303         if (!(ifa->ifa_flags&IFA_F_PERMANENT)) {
304                 fprintf(fp, "dynamic ");
305         } else
306                 ifa->ifa_flags &= ~IFA_F_PERMANENT;
307         if (ifa->ifa_flags)
308                 fprintf(fp, "flags %02x ", ifa->ifa_flags);
309         if (rta_tb[IFA_LABEL])
310                 fprintf(fp, "%s", (char*)RTA_DATA(rta_tb[IFA_LABEL]));
311         if (rta_tb[IFA_CACHEINFO]) {
312                 struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
313                 char buf[128];
314                 fprintf(fp, "%s", _SL_);
315                 if (ci->ifa_valid == 0xFFFFFFFFU)
316                         sprintf(buf, "valid_lft forever");
317                 else
318                         sprintf(buf, "valid_lft %dsec", ci->ifa_valid);
319                 if (ci->ifa_prefered == 0xFFFFFFFFU)
320                         sprintf(buf+strlen(buf), " preferred_lft forever");
321                 else
322                         sprintf(buf+strlen(buf), " preferred_lft %dsec", ci->ifa_prefered);
323                 fprintf(fp, "       %s", buf);
324         }
325         fprintf(fp, "\n");
326         fflush(fp);
327         return 0;
328 }
329
330
331 struct nlmsg_list
332 {
333         struct nlmsg_list *next;
334         struct nlmsghdr   h;
335 };
336
337 static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp)
338 {
339         for ( ;ainfo ;  ainfo = ainfo->next) {
340                 struct nlmsghdr *n = &ainfo->h;
341                 struct ifaddrmsg *ifa = NLMSG_DATA(n);
342
343                 if (n->nlmsg_type != RTM_NEWADDR)
344                         continue;
345
346                 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa)))
347                         return -1;
348
349                 if (ifa->ifa_index != ifindex || 
350                     (filter.family && filter.family != ifa->ifa_family))
351                         continue;
352
353                 print_addrinfo(NULL, n, fp);
354         }
355         return 0;
356 }
357
358
359 static int store_nlmsg(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
360 {
361         struct nlmsg_list **linfo = (struct nlmsg_list**)arg;
362         struct nlmsg_list *h;
363         struct nlmsg_list **lp;
364
365         h = malloc(n->nlmsg_len+sizeof(void*));
366         if (h == NULL)
367                 return -1;
368
369         memcpy(&h->h, n, n->nlmsg_len);
370         h->next = NULL;
371
372         for (lp = linfo; *lp; lp = &(*lp)->next) /* NOTHING */;
373         *lp = h;
374
375         ll_remember_index(who, n, NULL);
376         return 0;
377 }
378
379 static void ipaddr_reset_filter(int _oneline)
380 {
381         memset(&filter, 0, sizeof(filter));
382         filter.oneline = _oneline;
383 }
384
385 extern int ipaddr_list(int argc, char **argv)
386 {
387         const char *option[] = { "to", "scope", "up", "label", "dev", 0 };
388         struct nlmsg_list *linfo = NULL;
389         struct nlmsg_list *ainfo = NULL;
390         struct nlmsg_list *l;
391         struct rtnl_handle rth;
392         char *filter_dev = NULL;
393         int no_link = 0;
394
395         ipaddr_reset_filter(oneline);
396         filter.showqueue = 1;
397
398         if (filter.family == AF_UNSPEC)
399                 filter.family = preferred_family;
400
401         while (argc > 0) {
402                 const unsigned short option_num = compare_string_array(option, *argv);
403                 switch (option_num) {
404                         case 0: /* to */
405                                 NEXT_ARG();
406                                 get_prefix(&filter.pfx, *argv, filter.family);
407                                 if (filter.family == AF_UNSPEC) {
408                                         filter.family = filter.pfx.family;
409                                 }
410                                 break;
411                         case 1: /* scope */
412                         {
413                                 int scope = 0;
414                                 NEXT_ARG();
415                                 filter.scopemask = -1;
416                                 if (rtnl_rtscope_a2n(&scope, *argv)) {
417                                         if (strcmp(*argv, "all") != 0) {
418                                                 invarg("invalid \"scope\"\n", *argv);
419                                         }
420                                         scope = RT_SCOPE_NOWHERE;
421                                         filter.scopemask = 0;
422                                 }
423                                 filter.scope = scope;
424                                 break;
425                         }
426                         case 2: /* up */
427                                 filter.up = 1;
428                                 break;
429                         case 3: /* label */
430                                 NEXT_ARG();
431                                 filter.label = *argv;
432                                 break;
433                         case 4: /* dev */
434                                 NEXT_ARG();
435                         default:
436                                 if (filter_dev) {
437                                         duparg2("dev", *argv);
438                                 }
439                                 filter_dev = *argv;
440                 }
441                 argv++;
442                 argc--;
443         }
444
445         if (rtnl_open(&rth, 0) < 0)
446                 exit(1);
447
448         if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) {
449                 perror_msg_and_die("Cannot send dump request");
450         }
451
452         if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) {
453                 error_msg_and_die("Dump terminated");
454         }
455
456         if (filter_dev) {
457                 filter.ifindex = ll_name_to_index(filter_dev);
458                 if (filter.ifindex <= 0) {
459                         error_msg("Device \"%s\" does not exist.", filter_dev);
460                         return -1;
461                 }
462         }
463
464         if (filter.family != AF_PACKET) {
465                 if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
466                         perror_msg_and_die("Cannot send dump request");
467                 }
468
469                 if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) {
470                         error_msg_and_die("Dump terminated");
471                 }
472         }
473
474
475         if (filter.family && filter.family != AF_PACKET) {
476                 struct nlmsg_list **lp;
477                 lp=&linfo;
478
479                 if (filter.oneline)
480                         no_link = 1;
481
482                 while ((l=*lp)!=NULL) {
483                         int ok = 0;
484                         struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
485                         struct nlmsg_list *a;
486
487                         for (a=ainfo; a; a=a->next) {
488                                 struct nlmsghdr *n = &a->h;
489                                 struct ifaddrmsg *ifa = NLMSG_DATA(n);
490
491                                 if (ifa->ifa_index != ifi->ifi_index || 
492                                     (filter.family && filter.family != ifa->ifa_family))
493                                         continue;
494                                 if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
495                                         continue;
496                                 if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
497                                         continue;
498                                 if (filter.pfx.family || filter.label) {
499                                         struct rtattr *tb[IFA_MAX+1];
500                                         memset(tb, 0, sizeof(tb));
501                                         parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
502                                         if (!tb[IFA_LOCAL])
503                                                 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
504
505                                         if (filter.pfx.family && tb[IFA_LOCAL]) {
506                                                 inet_prefix dst;
507                                                 memset(&dst, 0, sizeof(dst));
508                                                 dst.family = ifa->ifa_family;
509                                                 memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
510                                                 if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
511                                                         continue;
512                                         }
513                                         if (filter.label) {
514                                                 SPRINT_BUF(b1);
515                                                 const char *label;
516                                                 if (tb[IFA_LABEL])
517                                                         label = RTA_DATA(tb[IFA_LABEL]);
518                                                 else
519                                                         label = ll_idx_n2a(ifa->ifa_index, b1);
520                                                 if (fnmatch(filter.label, label, 0) != 0)
521                                                         continue;
522                                         }
523                                 }
524
525                                 ok = 1;
526                                 break;
527                         }
528                         if (!ok)
529                                 *lp = l->next;
530                         else
531                                 lp = &l->next;
532                 }
533         }
534
535         for (l=linfo; l; l = l->next) {
536                 if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
537                         struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
538                         if (filter.family != AF_PACKET)
539                                 print_selected_addrinfo(ifi->ifi_index, ainfo, stdout);
540                 }
541                 fflush(stdout);
542         }
543
544         exit(0);
545 }
546
547 static int default_scope(inet_prefix *lcl)
548 {
549         if (lcl->family == AF_INET) {
550                 if (lcl->bytelen >= 1 && *(__u8*)&lcl->data == 127)
551                         return RT_SCOPE_HOST;
552         }
553         return 0;
554 }
555
556 static int ipaddr_modify(int cmd, int argc, char **argv)
557 {
558         const char *option[] = { "peer", "remote", "broadcast", "brd",
559                 "anycast", "scope", "dev", "label", "local", 0 };
560         struct rtnl_handle rth;
561         struct {
562                 struct nlmsghdr         n;
563                 struct ifaddrmsg        ifa;
564                 char                    buf[256];
565         } req;
566         char  *d = NULL;
567         char  *l = NULL;
568         inet_prefix lcl;
569         inet_prefix peer;
570         int local_len = 0;
571         int peer_len = 0;
572         int brd_len = 0;
573         int any_len = 0;
574         int scoped = 0;
575
576         memset(&req, 0, sizeof(req));
577
578         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
579         req.n.nlmsg_flags = NLM_F_REQUEST;
580         req.n.nlmsg_type = cmd;
581         req.ifa.ifa_family = preferred_family;
582
583         while (argc > 0) {
584                 const unsigned short option_num = compare_string_array(option, *argv);
585                 switch (option_num) {
586                         case 0: /* peer */
587                         case 1: /* remote */
588                                 NEXT_ARG();
589
590                                 if (peer_len) {
591                                         duparg("peer", *argv);
592                                 }
593                                 get_prefix(&peer, *argv, req.ifa.ifa_family);
594                                 peer_len = peer.bytelen;
595                                 if (req.ifa.ifa_family == AF_UNSPEC) {
596                                         req.ifa.ifa_family = peer.family;
597                                 }
598                                 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen);
599                                 req.ifa.ifa_prefixlen = peer.bitlen;
600                                 break;
601                         case 2: /* broadcast */
602                         case 3: /* brd */
603                         {
604                                 inet_prefix addr;
605                                 NEXT_ARG();
606                                 if (brd_len) {
607                                         duparg("broadcast", *argv);
608                                 }
609                                 if (strcmp(*argv, "+") == 0) {
610                                         brd_len = -1;
611                                 }
612                                 else if (strcmp(*argv, "-") == 0) {
613                                         brd_len = -2;
614                                 } else {
615                                         get_addr(&addr, *argv, req.ifa.ifa_family);
616                                         if (req.ifa.ifa_family == AF_UNSPEC)
617                                                 req.ifa.ifa_family = addr.family;
618                                         addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen);
619                                         brd_len = addr.bytelen;
620                                 }
621                                 break;
622                         }
623                         case 4: /* anycast */
624                         {
625                                 inet_prefix addr;
626                                 NEXT_ARG();
627                                 if (any_len) {
628                                         duparg("anycast", *argv);
629                                 }
630                                 get_addr(&addr, *argv, req.ifa.ifa_family);
631                                 if (req.ifa.ifa_family == AF_UNSPEC) {
632                                         req.ifa.ifa_family = addr.family;
633                                 }
634                                 addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen);
635                                 any_len = addr.bytelen;
636                                 break;
637                         }
638                         case 5: /* scope */
639                         {
640                                 int scope = 0;
641                                 NEXT_ARG();
642                                 if (rtnl_rtscope_a2n(&scope, *argv)) {
643                                         invarg(*argv, "invalid scope value.");
644                                 }
645                                 req.ifa.ifa_scope = scope;
646                                 scoped = 1;
647                                 break;
648                         }
649                         case 6: /* dev */
650                                 NEXT_ARG();
651                                 d = *argv;
652                                 break;
653                         case 7: /* label */
654                                 NEXT_ARG();
655                                 l = *argv;
656                                 addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1);
657                                 break;
658                         case 8: /* local */
659                                 NEXT_ARG();
660                         default:
661                                 if (local_len) {
662                                         duparg2("local", *argv);
663                                 }
664                                 get_prefix(&lcl, *argv, req.ifa.ifa_family);
665                                 if (req.ifa.ifa_family == AF_UNSPEC) {
666                                         req.ifa.ifa_family = lcl.family;
667                                 }
668                                 addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen);
669                                 local_len = lcl.bytelen;
670                 }
671                 argc--;
672                 argv++;
673         }
674
675         if (d == NULL) {
676                 error_msg("Not enough information: \"dev\" argument is required.");
677                 return -1;
678         }
679         if (l && matches(d, l) != 0) {
680                 error_msg_and_die("\"dev\" (%s) must match \"label\" (%s).", d, l);
681         }
682
683         if (peer_len == 0 && local_len && cmd != RTM_DELADDR) {
684                 peer = lcl;
685                 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen);
686         }
687         if (req.ifa.ifa_prefixlen == 0)
688                 req.ifa.ifa_prefixlen = lcl.bitlen;
689
690         if (brd_len < 0 && cmd != RTM_DELADDR) {
691                 inet_prefix brd;
692                 int i;
693                 if (req.ifa.ifa_family != AF_INET) {
694                         error_msg("Broadcast can be set only for IPv4 addresses");
695                         return -1;
696                 }
697                 brd = peer;
698                 if (brd.bitlen <= 30) {
699                         for (i=31; i>=brd.bitlen; i--) {
700                                 if (brd_len == -1)
701                                         brd.data[0] |= htonl(1<<(31-i));
702                                 else
703                                         brd.data[0] &= ~htonl(1<<(31-i));
704                         }
705                         addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen);
706                         brd_len = brd.bytelen;
707                 }
708         }
709         if (!scoped && cmd != RTM_DELADDR)
710                 req.ifa.ifa_scope = default_scope(&lcl);
711
712         if (rtnl_open(&rth, 0) < 0)
713                 exit(1);
714
715         ll_init_map(&rth);
716
717         if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) {
718                 error_msg("Cannot find device \"%s\"", d);
719                 return -1;
720         }
721
722         if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
723                 exit(2);
724
725         exit(0);
726 }
727
728 extern int do_ipaddr(int argc, char **argv)
729 {
730         const char *commands[] = { "add", "delete", "list", "show", "lst", 0 };
731         unsigned short command_num = 2;
732
733         if (*argv) {
734                 command_num = compare_string_array(commands, *argv);
735         }
736         switch (command_num) {
737                 case 0: /* add */
738                         return ipaddr_modify(RTM_NEWADDR, argc-1, argv+1);
739                 case 1: /* delete */
740                         return ipaddr_modify(RTM_DELADDR, argc-1, argv+1);
741                 case 2: /* list */
742                 case 3: /* show */
743                 case 4: /* lst */
744                         return ipaddr_list(argc-1, argv+1);
745         }
746         error_msg_and_die("Unknown command %s", *argv);
747 }