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