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