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