Use error_msg instead of fprintf(stderr
[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                 SPRINT_BUF(b1);
234                 const char *label;
235                 if (rta_tb[IFA_LABEL])
236                         label = RTA_DATA(rta_tb[IFA_LABEL]);
237                 else
238                         label = ll_idx_n2a(ifa->ifa_index, b1);
239                 if (fnmatch(filter.label, label, 0) != 0)
240                         return 0;
241         }
242         if (filter.pfx.family) {
243                 if (rta_tb[IFA_LOCAL]) {
244                         inet_prefix dst;
245                         memset(&dst, 0, sizeof(dst));
246                         dst.family = ifa->ifa_family;
247                         memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL]));
248                         if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
249                                 return 0;
250                 }
251         }
252
253         if (n->nlmsg_type == RTM_DELADDR)
254                 fprintf(fp, "Deleted ");
255
256         if (filter.oneline)
257                 fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
258         if (ifa->ifa_family == AF_INET)
259                 fprintf(fp, "    inet ");
260         else if (ifa->ifa_family == AF_INET6)
261                 fprintf(fp, "    inet6 ");
262         else
263                 fprintf(fp, "    family %d ", ifa->ifa_family);
264
265         if (rta_tb[IFA_LOCAL]) {
266                 fprintf(fp, "%s", rt_addr_n2a(ifa->ifa_family,
267                                               RTA_PAYLOAD(rta_tb[IFA_LOCAL]),
268                                               RTA_DATA(rta_tb[IFA_LOCAL]),
269                                               abuf, sizeof(abuf)));
270
271                 if (rta_tb[IFA_ADDRESS] == NULL ||
272                     memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) {
273                         fprintf(fp, "/%d ", ifa->ifa_prefixlen);
274                 } else {
275                         fprintf(fp, " peer %s/%d ",
276                                 rt_addr_n2a(ifa->ifa_family,
277                                             RTA_PAYLOAD(rta_tb[IFA_ADDRESS]),
278                                             RTA_DATA(rta_tb[IFA_ADDRESS]),
279                                             abuf, sizeof(abuf)),
280                                 ifa->ifa_prefixlen);
281                 }
282         }
283
284         if (rta_tb[IFA_BROADCAST]) {
285                 fprintf(fp, "brd %s ",
286                         rt_addr_n2a(ifa->ifa_family,
287                                     RTA_PAYLOAD(rta_tb[IFA_BROADCAST]),
288                                     RTA_DATA(rta_tb[IFA_BROADCAST]),
289                                     abuf, sizeof(abuf)));
290         }
291         if (rta_tb[IFA_ANYCAST]) {
292                 fprintf(fp, "any %s ",
293                         rt_addr_n2a(ifa->ifa_family,
294                                     RTA_PAYLOAD(rta_tb[IFA_ANYCAST]),
295                                     RTA_DATA(rta_tb[IFA_ANYCAST]),
296                                     abuf, sizeof(abuf)));
297         }
298         fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
299         if (ifa->ifa_flags&IFA_F_SECONDARY) {
300                 ifa->ifa_flags &= ~IFA_F_SECONDARY;
301                 fprintf(fp, "secondary ");
302         }
303         if (ifa->ifa_flags&IFA_F_TENTATIVE) {
304                 ifa->ifa_flags &= ~IFA_F_TENTATIVE;
305                 fprintf(fp, "tentative ");
306         }
307         if (ifa->ifa_flags&IFA_F_DEPRECATED) {
308                 ifa->ifa_flags &= ~IFA_F_DEPRECATED;
309                 fprintf(fp, "deprecated ");
310         }
311         if (!(ifa->ifa_flags&IFA_F_PERMANENT)) {
312                 fprintf(fp, "dynamic ");
313         } else
314                 ifa->ifa_flags &= ~IFA_F_PERMANENT;
315         if (ifa->ifa_flags)
316                 fprintf(fp, "flags %02x ", ifa->ifa_flags);
317         if (rta_tb[IFA_LABEL])
318                 fprintf(fp, "%s", (char*)RTA_DATA(rta_tb[IFA_LABEL]));
319         if (rta_tb[IFA_CACHEINFO]) {
320                 struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
321                 char buf[128];
322                 fprintf(fp, "%s", _SL_);
323                 if (ci->ifa_valid == 0xFFFFFFFFU)
324                         sprintf(buf, "valid_lft forever");
325                 else
326                         sprintf(buf, "valid_lft %dsec", ci->ifa_valid);
327                 if (ci->ifa_prefered == 0xFFFFFFFFU)
328                         sprintf(buf+strlen(buf), " preferred_lft forever");
329                 else
330                         sprintf(buf+strlen(buf), " preferred_lft %dsec", ci->ifa_prefered);
331                 fprintf(fp, "       %s", buf);
332         }
333         fprintf(fp, "\n");
334         fflush(fp);
335         return 0;
336 }
337
338
339 struct nlmsg_list
340 {
341         struct nlmsg_list *next;
342         struct nlmsghdr   h;
343 };
344
345 int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp)
346 {
347         for ( ;ainfo ;  ainfo = ainfo->next) {
348                 struct nlmsghdr *n = &ainfo->h;
349                 struct ifaddrmsg *ifa = NLMSG_DATA(n);
350
351                 if (n->nlmsg_type != RTM_NEWADDR)
352                         continue;
353
354                 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa)))
355                         return -1;
356
357                 if (ifa->ifa_index != ifindex || 
358                     (filter.family && filter.family != ifa->ifa_family))
359                         continue;
360
361                 print_addrinfo(NULL, n, fp);
362         }
363         return 0;
364 }
365
366
367 int store_nlmsg(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
368 {
369         struct nlmsg_list **linfo = (struct nlmsg_list**)arg;
370         struct nlmsg_list *h;
371         struct nlmsg_list **lp;
372
373         h = malloc(n->nlmsg_len+sizeof(void*));
374         if (h == NULL)
375                 return -1;
376
377         memcpy(&h->h, n, n->nlmsg_len);
378         h->next = NULL;
379
380         for (lp = linfo; *lp; lp = &(*lp)->next) /* NOTHING */;
381         *lp = h;
382
383         ll_remember_index(who, n, NULL);
384         return 0;
385 }
386
387 int ipaddr_list(int argc, char **argv)
388 {
389         struct nlmsg_list *linfo = NULL;
390         struct nlmsg_list *ainfo = NULL;
391         struct nlmsg_list *l;
392         struct rtnl_handle rth;
393         char *filter_dev = NULL;
394         int no_link = 0;
395
396         ipaddr_reset_filter(oneline);
397         filter.showqueue = 1;
398
399         if (filter.family == AF_UNSPEC)
400                 filter.family = preferred_family;
401
402         while (argc > 0) {
403                 if (strcmp(*argv, "to") == 0) {
404                         NEXT_ARG();
405                         get_prefix(&filter.pfx, *argv, filter.family);
406                         if (filter.family == AF_UNSPEC)
407                                 filter.family = filter.pfx.family;
408                 } else if (strcmp(*argv, "scope") == 0) {
409                         int scope = 0;
410                         NEXT_ARG();
411                         filter.scopemask = -1;
412                         if (rtnl_rtscope_a2n(&scope, *argv)) {
413                                 if (strcmp(*argv, "all") != 0)
414                                         invarg("invalid \"scope\"\n", *argv);
415                                 scope = RT_SCOPE_NOWHERE;
416                                 filter.scopemask = 0;
417                         }
418                         filter.scope = scope;
419                 } else if (strcmp(*argv, "up") == 0) {
420                         filter.up = 1;
421                 } else if (strcmp(*argv, "label") == 0) {
422                         NEXT_ARG();
423                         filter.label = *argv;
424                 } else {
425                         if (strcmp(*argv, "dev") == 0) {
426                                 NEXT_ARG();
427                         }
428                         if (filter_dev)
429                                 duparg2("dev", *argv);
430                         filter_dev = *argv;
431                 }
432                 argv++; argc--;
433         }
434
435         if (rtnl_open(&rth, 0) < 0)
436                 exit(1);
437
438         if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) {
439                 perror_msg_and_die("Cannot send dump request");
440         }
441
442         if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) {
443                 error_msg_and_die("Dump terminated");
444         }
445
446         if (filter_dev) {
447                 filter.ifindex = ll_name_to_index(filter_dev);
448                 if (filter.ifindex <= 0) {
449                         error_msg("Device \"%s\" does not exist.", filter_dev);
450                         return -1;
451                 }
452         }
453
454         if (filter.family != AF_PACKET) {
455                 if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
456                         perror_msg_and_die("Cannot send dump request");
457                 }
458
459                 if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) {
460                         error_msg_and_die("Dump terminated");
461                 }
462         }
463
464
465         if (filter.family && filter.family != AF_PACKET) {
466                 struct nlmsg_list **lp;
467                 lp=&linfo;
468
469                 if (filter.oneline)
470                         no_link = 1;
471
472                 while ((l=*lp)!=NULL) {
473                         int ok = 0;
474                         struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
475                         struct nlmsg_list *a;
476
477                         for (a=ainfo; a; a=a->next) {
478                                 struct nlmsghdr *n = &a->h;
479                                 struct ifaddrmsg *ifa = NLMSG_DATA(n);
480
481                                 if (ifa->ifa_index != ifi->ifi_index || 
482                                     (filter.family && filter.family != ifa->ifa_family))
483                                         continue;
484                                 if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
485                                         continue;
486                                 if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
487                                         continue;
488                                 if (filter.pfx.family || filter.label) {
489                                         struct rtattr *tb[IFA_MAX+1];
490                                         memset(tb, 0, sizeof(tb));
491                                         parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
492                                         if (!tb[IFA_LOCAL])
493                                                 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
494
495                                         if (filter.pfx.family && tb[IFA_LOCAL]) {
496                                                 inet_prefix dst;
497                                                 memset(&dst, 0, sizeof(dst));
498                                                 dst.family = ifa->ifa_family;
499                                                 memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
500                                                 if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
501                                                         continue;
502                                         }
503                                         if (filter.label) {
504                                                 SPRINT_BUF(b1);
505                                                 const char *label;
506                                                 if (tb[IFA_LABEL])
507                                                         label = RTA_DATA(tb[IFA_LABEL]);
508                                                 else
509                                                         label = ll_idx_n2a(ifa->ifa_index, b1);
510                                                 if (fnmatch(filter.label, label, 0) != 0)
511                                                         continue;
512                                         }
513                                 }
514
515                                 ok = 1;
516                                 break;
517                         }
518                         if (!ok)
519                                 *lp = l->next;
520                         else
521                                 lp = &l->next;
522                 }
523         }
524
525         for (l=linfo; l; l = l->next) {
526                 if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
527                         struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
528                         if (filter.family != AF_PACKET)
529                                 print_selected_addrinfo(ifi->ifi_index, ainfo, stdout);
530                 }
531                 fflush(stdout);
532         }
533
534         exit(0);
535 }
536
537 int ipaddr_list_link(int argc, char **argv)
538 {
539         preferred_family = AF_PACKET;
540         do_link = 1;
541         return ipaddr_list(argc, argv);
542 }
543
544 void ipaddr_reset_filter(int oneline)
545 {
546         memset(&filter, 0, sizeof(filter));
547         filter.oneline = oneline;
548 }
549
550 int default_scope(inet_prefix *lcl)
551 {
552         if (lcl->family == AF_INET) {
553                 if (lcl->bytelen >= 1 && *(__u8*)&lcl->data == 127)
554                         return RT_SCOPE_HOST;
555         }
556         return 0;
557 }
558
559 int ipaddr_modify(int cmd, int argc, char **argv)
560 {
561         struct rtnl_handle rth;
562         struct {
563                 struct nlmsghdr         n;
564                 struct ifaddrmsg        ifa;
565                 char                    buf[256];
566         } req;
567         char  *d = NULL;
568         char  *l = NULL;
569         inet_prefix lcl;
570         inet_prefix peer;
571         int local_len = 0;
572         int peer_len = 0;
573         int brd_len = 0;
574         int any_len = 0;
575         int scoped = 0;
576
577         memset(&req, 0, sizeof(req));
578
579         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
580         req.n.nlmsg_flags = NLM_F_REQUEST;
581         req.n.nlmsg_type = cmd;
582         req.ifa.ifa_family = preferred_family;
583
584         while (argc > 0) {
585                 if (strcmp(*argv, "peer") == 0 ||
586                     strcmp(*argv, "remote") == 0) {
587                         NEXT_ARG();
588
589                         if (peer_len)
590                                 duparg("peer", *argv);
591                         get_prefix(&peer, *argv, req.ifa.ifa_family);
592                         peer_len = peer.bytelen;
593                         if (req.ifa.ifa_family == AF_UNSPEC)
594                                 req.ifa.ifa_family = peer.family;
595                         addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen);
596                         req.ifa.ifa_prefixlen = peer.bitlen;
597                 } else if (matches(*argv, "broadcast") == 0 ||
598                            strcmp(*argv, "brd") == 0) {
599                         inet_prefix addr;
600                         NEXT_ARG();
601                         if (brd_len)
602                                 duparg("broadcast", *argv);
603                         if (strcmp(*argv, "+") == 0)
604                                 brd_len = -1;
605                         else if (strcmp(*argv, "-") == 0)
606                                 brd_len = -2;
607                         else {
608                                 get_addr(&addr, *argv, req.ifa.ifa_family);
609                                 if (req.ifa.ifa_family == AF_UNSPEC)
610                                         req.ifa.ifa_family = addr.family;
611                                 addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen);
612                                 brd_len = addr.bytelen;
613                         }
614                 } else if (strcmp(*argv, "anycast") == 0) {
615                         inet_prefix addr;
616                         NEXT_ARG();
617                         if (any_len)
618                                 duparg("anycast", *argv);
619                         get_addr(&addr, *argv, req.ifa.ifa_family);
620                         if (req.ifa.ifa_family == AF_UNSPEC)
621                                 req.ifa.ifa_family = addr.family;
622                         addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen);
623                         any_len = addr.bytelen;
624                 } else if (strcmp(*argv, "scope") == 0) {
625                         int scope = 0;
626                         NEXT_ARG();
627                         if (rtnl_rtscope_a2n(&scope, *argv))
628                                 invarg(*argv, "invalid scope value.");
629                         req.ifa.ifa_scope = scope;
630                         scoped = 1;
631                 } else if (strcmp(*argv, "dev") == 0) {
632                         NEXT_ARG();
633                         d = *argv;
634                 } else if (strcmp(*argv, "label") == 0) {
635                         NEXT_ARG();
636                         l = *argv;
637                         addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1);
638                 } else {
639                         if (strcmp(*argv, "local") == 0) {
640                                 NEXT_ARG();
641                         }
642                         if (local_len)
643                                 duparg2("local", *argv);
644                         get_prefix(&lcl, *argv, req.ifa.ifa_family);
645                         if (req.ifa.ifa_family == AF_UNSPEC)
646                                 req.ifa.ifa_family = lcl.family;
647                         addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen);
648                         local_len = lcl.bytelen;
649                 }
650                 argc--; argv++;
651         }
652         if (d == NULL) {
653                 error_msg("Not enough information: \"dev\" argument is required.");
654                 return -1;
655         }
656         if (l && matches(d, l) != 0) {
657                 error_msg_and_die("\"dev\" (%s) must match \"label\" (%s).", d, l);
658         }
659
660         if (peer_len == 0 && local_len && cmd != RTM_DELADDR) {
661                 peer = lcl;
662                 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen);
663         }
664         if (req.ifa.ifa_prefixlen == 0)
665                 req.ifa.ifa_prefixlen = lcl.bitlen;
666
667         if (brd_len < 0 && cmd != RTM_DELADDR) {
668                 inet_prefix brd;
669                 int i;
670                 if (req.ifa.ifa_family != AF_INET) {
671                         error_msg("Broadcast can be set only for IPv4 addresses");
672                         return -1;
673                 }
674                 brd = peer;
675                 if (brd.bitlen <= 30) {
676                         for (i=31; i>=brd.bitlen; i--) {
677                                 if (brd_len == -1)
678                                         brd.data[0] |= htonl(1<<(31-i));
679                                 else
680                                         brd.data[0] &= ~htonl(1<<(31-i));
681                         }
682                         addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen);
683                         brd_len = brd.bytelen;
684                 }
685         }
686         if (!scoped && cmd != RTM_DELADDR)
687                 req.ifa.ifa_scope = default_scope(&lcl);
688
689         if (rtnl_open(&rth, 0) < 0)
690                 exit(1);
691
692         ll_init_map(&rth);
693
694         if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) {
695                 error_msg("Cannot find device \"%s\"", d);
696                 return -1;
697         }
698
699         if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
700                 exit(2);
701
702         exit(0);
703 }
704
705 int do_ipaddr(int argc, char **argv)
706 {
707         if (argc < 1)
708                 return ipaddr_list(0, NULL);
709         if (matches(*argv, "add") == 0)
710                 return ipaddr_modify(RTM_NEWADDR, argc-1, argv+1);
711         if (matches(*argv, "delete") == 0)
712                 return ipaddr_modify(RTM_DELADDR, argc-1, argv+1);
713         if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
714             || matches(*argv, "lst") == 0)
715                 return ipaddr_list(argc-1, argv+1);
716         error_msg("Command \"%s\" is unknown, try \"ip address help\".", *argv);
717         exit(-1);
718 }