Enable ip commands to be compiled seperate from ip, modifed patch from Bastian Blank
[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 static int do_link;
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 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 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 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 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 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 int ipaddr_list(int argc, char **argv)
387 {
388         struct nlmsg_list *linfo = NULL;
389         struct nlmsg_list *ainfo = NULL;
390         struct nlmsg_list *l;
391         struct rtnl_handle rth;
392         char *filter_dev = NULL;
393         int no_link = 0;
394
395         ipaddr_reset_filter(oneline);
396         filter.showqueue = 1;
397
398         if (filter.family == AF_UNSPEC)
399                 filter.family = preferred_family;
400
401         while (argc > 0) {
402                 if (strcmp(*argv, "to") == 0) {
403                         NEXT_ARG();
404                         get_prefix(&filter.pfx, *argv, filter.family);
405                         if (filter.family == AF_UNSPEC)
406                                 filter.family = filter.pfx.family;
407                 } else if (strcmp(*argv, "scope") == 0) {
408                         int scope = 0;
409                         NEXT_ARG();
410                         filter.scopemask = -1;
411                         if (rtnl_rtscope_a2n(&scope, *argv)) {
412                                 if (strcmp(*argv, "all") != 0)
413                                         invarg("invalid \"scope\"\n", *argv);
414                                 scope = RT_SCOPE_NOWHERE;
415                                 filter.scopemask = 0;
416                         }
417                         filter.scope = scope;
418                 } else if (strcmp(*argv, "up") == 0) {
419                         filter.up = 1;
420                 } else if (strcmp(*argv, "label") == 0) {
421                         NEXT_ARG();
422                         filter.label = *argv;
423                 } else {
424                         if (strcmp(*argv, "dev") == 0) {
425                                 NEXT_ARG();
426                         }
427                         if (filter_dev)
428                                 duparg2("dev", *argv);
429                         filter_dev = *argv;
430                 }
431                 argv++; argc--;
432         }
433
434         if (rtnl_open(&rth, 0) < 0)
435                 exit(1);
436
437         if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) {
438                 perror_msg_and_die("Cannot send dump request");
439         }
440
441         if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) {
442                 error_msg_and_die("Dump terminated");
443         }
444
445         if (filter_dev) {
446                 filter.ifindex = ll_name_to_index(filter_dev);
447                 if (filter.ifindex <= 0) {
448                         error_msg("Device \"%s\" does not exist.", filter_dev);
449                         return -1;
450                 }
451         }
452
453         if (filter.family != AF_PACKET) {
454                 if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
455                         perror_msg_and_die("Cannot send dump request");
456                 }
457
458                 if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) {
459                         error_msg_and_die("Dump terminated");
460                 }
461         }
462
463
464         if (filter.family && filter.family != AF_PACKET) {
465                 struct nlmsg_list **lp;
466                 lp=&linfo;
467
468                 if (filter.oneline)
469                         no_link = 1;
470
471                 while ((l=*lp)!=NULL) {
472                         int ok = 0;
473                         struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
474                         struct nlmsg_list *a;
475
476                         for (a=ainfo; a; a=a->next) {
477                                 struct nlmsghdr *n = &a->h;
478                                 struct ifaddrmsg *ifa = NLMSG_DATA(n);
479
480                                 if (ifa->ifa_index != ifi->ifi_index || 
481                                     (filter.family && filter.family != ifa->ifa_family))
482                                         continue;
483                                 if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
484                                         continue;
485                                 if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
486                                         continue;
487                                 if (filter.pfx.family || filter.label) {
488                                         struct rtattr *tb[IFA_MAX+1];
489                                         memset(tb, 0, sizeof(tb));
490                                         parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
491                                         if (!tb[IFA_LOCAL])
492                                                 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
493
494                                         if (filter.pfx.family && tb[IFA_LOCAL]) {
495                                                 inet_prefix dst;
496                                                 memset(&dst, 0, sizeof(dst));
497                                                 dst.family = ifa->ifa_family;
498                                                 memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
499                                                 if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
500                                                         continue;
501                                         }
502                                         if (filter.label) {
503                                                 SPRINT_BUF(b1);
504                                                 const char *label;
505                                                 if (tb[IFA_LABEL])
506                                                         label = RTA_DATA(tb[IFA_LABEL]);
507                                                 else
508                                                         label = ll_idx_n2a(ifa->ifa_index, b1);
509                                                 if (fnmatch(filter.label, label, 0) != 0)
510                                                         continue;
511                                         }
512                                 }
513
514                                 ok = 1;
515                                 break;
516                         }
517                         if (!ok)
518                                 *lp = l->next;
519                         else
520                                 lp = &l->next;
521                 }
522         }
523
524         for (l=linfo; l; l = l->next) {
525                 if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
526                         struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
527                         if (filter.family != AF_PACKET)
528                                 print_selected_addrinfo(ifi->ifi_index, ainfo, stdout);
529                 }
530                 fflush(stdout);
531         }
532
533         exit(0);
534 }
535
536 int ipaddr_list_link(int argc, char **argv)
537 {
538         preferred_family = AF_PACKET;
539         do_link = 1;
540         return ipaddr_list(argc, argv);
541 }
542
543 void ipaddr_reset_filter(int _oneline)
544 {
545         memset(&filter, 0, sizeof(filter));
546         filter.oneline = _oneline;
547 }
548
549 int default_scope(inet_prefix *lcl)
550 {
551         if (lcl->family == AF_INET) {
552                 if (lcl->bytelen >= 1 && *(__u8*)&lcl->data == 127)
553                         return RT_SCOPE_HOST;
554         }
555         return 0;
556 }
557
558 int ipaddr_modify(int cmd, int argc, char **argv)
559 {
560         struct rtnl_handle rth;
561         struct {
562                 struct nlmsghdr         n;
563                 struct ifaddrmsg        ifa;
564                 char                    buf[256];
565         } req;
566         char  *d = NULL;
567         char  *l = NULL;
568         inet_prefix lcl;
569         inet_prefix peer;
570         int local_len = 0;
571         int peer_len = 0;
572         int brd_len = 0;
573         int any_len = 0;
574         int scoped = 0;
575
576         memset(&req, 0, sizeof(req));
577
578         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
579         req.n.nlmsg_flags = NLM_F_REQUEST;
580         req.n.nlmsg_type = cmd;
581         req.ifa.ifa_family = preferred_family;
582
583         while (argc > 0) {
584                 if (strcmp(*argv, "peer") == 0 ||
585                     strcmp(*argv, "remote") == 0) {
586                         NEXT_ARG();
587
588                         if (peer_len)
589                                 duparg("peer", *argv);
590                         get_prefix(&peer, *argv, req.ifa.ifa_family);
591                         peer_len = peer.bytelen;
592                         if (req.ifa.ifa_family == AF_UNSPEC)
593                                 req.ifa.ifa_family = peer.family;
594                         addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen);
595                         req.ifa.ifa_prefixlen = peer.bitlen;
596                 } else if (matches(*argv, "broadcast") == 0 ||
597                            strcmp(*argv, "brd") == 0) {
598                         inet_prefix addr;
599                         NEXT_ARG();
600                         if (brd_len)
601                                 duparg("broadcast", *argv);
602                         if (strcmp(*argv, "+") == 0)
603                                 brd_len = -1;
604                         else if (strcmp(*argv, "-") == 0)
605                                 brd_len = -2;
606                         else {
607                                 get_addr(&addr, *argv, req.ifa.ifa_family);
608                                 if (req.ifa.ifa_family == AF_UNSPEC)
609                                         req.ifa.ifa_family = addr.family;
610                                 addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen);
611                                 brd_len = addr.bytelen;
612                         }
613                 } else if (strcmp(*argv, "anycast") == 0) {
614                         inet_prefix addr;
615                         NEXT_ARG();
616                         if (any_len)
617                                 duparg("anycast", *argv);
618                         get_addr(&addr, *argv, req.ifa.ifa_family);
619                         if (req.ifa.ifa_family == AF_UNSPEC)
620                                 req.ifa.ifa_family = addr.family;
621                         addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen);
622                         any_len = addr.bytelen;
623                 } else if (strcmp(*argv, "scope") == 0) {
624                         int scope = 0;
625                         NEXT_ARG();
626                         if (rtnl_rtscope_a2n(&scope, *argv))
627                                 invarg(*argv, "invalid scope value.");
628                         req.ifa.ifa_scope = scope;
629                         scoped = 1;
630                 } else if (strcmp(*argv, "dev") == 0) {
631                         NEXT_ARG();
632                         d = *argv;
633                 } else if (strcmp(*argv, "label") == 0) {
634                         NEXT_ARG();
635                         l = *argv;
636                         addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1);
637                 } else {
638                         if (strcmp(*argv, "local") == 0) {
639                                 NEXT_ARG();
640                         }
641                         if (local_len)
642                                 duparg2("local", *argv);
643                         get_prefix(&lcl, *argv, req.ifa.ifa_family);
644                         if (req.ifa.ifa_family == AF_UNSPEC)
645                                 req.ifa.ifa_family = lcl.family;
646                         addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen);
647                         local_len = lcl.bytelen;
648                 }
649                 argc--; argv++;
650         }
651         if (d == NULL) {
652                 error_msg("Not enough information: \"dev\" argument is required.");
653                 return -1;
654         }
655         if (l && matches(d, l) != 0) {
656                 error_msg_and_die("\"dev\" (%s) must match \"label\" (%s).", d, l);
657         }
658
659         if (peer_len == 0 && local_len && cmd != RTM_DELADDR) {
660                 peer = lcl;
661                 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen);
662         }
663         if (req.ifa.ifa_prefixlen == 0)
664                 req.ifa.ifa_prefixlen = lcl.bitlen;
665
666         if (brd_len < 0 && cmd != RTM_DELADDR) {
667                 inet_prefix brd;
668                 int i;
669                 if (req.ifa.ifa_family != AF_INET) {
670                         error_msg("Broadcast can be set only for IPv4 addresses");
671                         return -1;
672                 }
673                 brd = peer;
674                 if (brd.bitlen <= 30) {
675                         for (i=31; i>=brd.bitlen; i--) {
676                                 if (brd_len == -1)
677                                         brd.data[0] |= htonl(1<<(31-i));
678                                 else
679                                         brd.data[0] &= ~htonl(1<<(31-i));
680                         }
681                         addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen);
682                         brd_len = brd.bytelen;
683                 }
684         }
685         if (!scoped && cmd != RTM_DELADDR)
686                 req.ifa.ifa_scope = default_scope(&lcl);
687
688         if (rtnl_open(&rth, 0) < 0)
689                 exit(1);
690
691         ll_init_map(&rth);
692
693         if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) {
694                 error_msg("Cannot find device \"%s\"", d);
695                 return -1;
696         }
697
698         if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
699                 exit(2);
700
701         exit(0);
702 }
703
704 int do_ipaddr(int argc, char **argv)
705 {
706         if (argc < 1)
707                 return ipaddr_list(0, NULL);
708         if (matches(*argv, "add") == 0)
709                 return ipaddr_modify(RTM_NEWADDR, argc-1, argv+1);
710         if (matches(*argv, "delete") == 0)
711                 return ipaddr_modify(RTM_DELADDR, argc-1, argv+1);
712         if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
713             || matches(*argv, "lst") == 0)
714                 return ipaddr_list(argc-1, argv+1);
715         error_msg("Command \"%s\" is unknown, try \"ip address help\".", *argv);
716         exit(-1);
717 }