blob: 2f2cabdffcf38b591aac5d235d37127706ec0b1e [file] [log] [blame]
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001/*
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 *
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000011 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16#include <syslog.h>
17#include <fcntl.h>
18#include <sys/ioctl.h>
19#include <sys/socket.h>
20#include <sys/ioctl.h>
Stephen Hemminger3d866ba2008-03-14 15:30:03 -070021#include <sys/errno.h>
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000022#include <netinet/in.h>
23#include <arpa/inet.h>
24#include <string.h>
25#include <fnmatch.h>
26
osdl.org!shemmingere5779fb2004-06-09 22:56:28 +000027#include <linux/netdevice.h>
28#include <linux/if_arp.h>
29#include <linux/sockios.h>
30
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000031#include "rt_names.h"
32#include "utils.h"
33#include "ll_map.h"
34#include "ip_common.h"
35
Daniel Silverstone7b3d3662007-10-19 13:32:24 +020036
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000037static struct
38{
39 int ifindex;
40 int family;
41 int oneline;
42 int showqueue;
43 inet_prefix pfx;
44 int scope, scopemask;
45 int flags, flagmask;
46 int up;
47 char *label;
48 int flushed;
49 char *flushb;
50 int flushp;
51 int flushe;
Vlad Dogaruf960c922011-02-02 20:23:40 +020052 int group;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000053} filter;
54
55static int do_link;
56
57static void usage(void) __attribute__((noreturn));
58
59static void usage(void)
60{
61 if (do_link) {
62 iplink_usage();
63 }
Noriaki TAKAMIYA0aef3662006-11-24 12:26:58 +090064 fprintf(stderr, "Usage: ip addr {add|change|replace} IFADDR dev STRING [ LIFETIME ]\n");
Brian Haleya1f27792009-12-03 10:39:36 +000065 fprintf(stderr, " [ CONFFLAG-LIST ]\n");
Masahide NAKAMURA35546df2006-11-24 12:26:55 +090066 fprintf(stderr, " ip addr del IFADDR dev STRING\n");
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000067 fprintf(stderr, " ip addr {show|flush} [ dev STRING ] [ scope SCOPE-ID ]\n");
68 fprintf(stderr, " [ to PREFIX ] [ FLAG-LIST ] [ label PATTERN ]\n");
69 fprintf(stderr, "IFADDR := PREFIX | ADDR peer PREFIX\n");
70 fprintf(stderr, " [ broadcast ADDR ] [ anycast ADDR ]\n");
71 fprintf(stderr, " [ label STRING ] [ scope SCOPE-ID ]\n");
72 fprintf(stderr, "SCOPE-ID := [ host | link | global | NUMBER ]\n");
73 fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
74 fprintf(stderr, "FLAG := [ permanent | dynamic | secondary | primary |\n");
Brian Haleya1b9ffc2009-09-14 17:01:43 -040075 fprintf(stderr, " tentative | deprecated | dadfailed | temporary |\n");
Brian Haleya1f27792009-12-03 10:39:36 +000076 fprintf(stderr, " CONFFLAG-LIST ]\n");
Noriaki TAKAMIYAbac735c2007-03-08 03:15:43 +090077 fprintf(stderr, "CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG\n");
78 fprintf(stderr, "CONFFLAG := [ home | nodad ]\n");
Masahide NAKAMURA35546df2006-11-24 12:26:55 +090079 fprintf(stderr, "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n");
80 fprintf(stderr, "LFT := forever | SECONDS\n");
81
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000082 exit(-1);
83}
84
85void print_link_flags(FILE *fp, unsigned flags, unsigned mdown)
86{
87 fprintf(fp, "<");
net[shemminger]!shemminger73b49e92005-03-14 18:47:38 +000088 if (flags & IFF_UP && !(flags & IFF_RUNNING))
89 fprintf(fp, "NO-CARRIER%s", flags ? "," : "");
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000090 flags &= ~IFF_RUNNING;
91#define _PF(f) if (flags&IFF_##f) { \
92 flags &= ~IFF_##f ; \
93 fprintf(fp, #f "%s", flags ? "," : ""); }
94 _PF(LOOPBACK);
95 _PF(BROADCAST);
96 _PF(POINTOPOINT);
97 _PF(MULTICAST);
98 _PF(NOARP);
99 _PF(ALLMULTI);
100 _PF(PROMISC);
101 _PF(MASTER);
102 _PF(SLAVE);
103 _PF(DEBUG);
104 _PF(DYNAMIC);
105 _PF(AUTOMEDIA);
106 _PF(PORTSEL);
107 _PF(NOTRAILERS);
108 _PF(UP);
Thomas Grafdcb283c2007-06-19 16:40:40 -0700109 _PF(LOWER_UP);
110 _PF(DORMANT);
Oliver Hartkopp98f9a1d2009-03-27 11:21:29 -0700111 _PF(ECHO);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000112#undef _PF
113 if (flags)
114 fprintf(fp, "%x", flags);
115 if (mdown)
116 fprintf(fp, ",M-DOWN");
117 fprintf(fp, "> ");
118}
119
Stephen Hemminger3d866ba2008-03-14 15:30:03 -0700120static const char *oper_states[] = {
121 "UNKNOWN", "NOTPRESENT", "DOWN", "LOWERLAYERDOWN",
122 "TESTING", "DORMANT", "UP"
123};
124
125static void print_operstate(FILE *f, __u8 state)
126{
127 if (state >= sizeof(oper_states)/sizeof(oper_states[0]))
128 fprintf(f, "state %#x ", state);
129 else
130 fprintf(f, "state %s ", oper_states[state]);
131}
132
Eric Dumazetf78e3162009-10-22 18:13:21 +0000133static void print_queuelen(FILE *f, struct rtattr *tb[IFLA_MAX + 1])
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000134{
Eric Dumazetf78e3162009-10-22 18:13:21 +0000135 int qlen;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000136
Eric Dumazetf78e3162009-10-22 18:13:21 +0000137 if (tb[IFLA_TXQLEN])
138 qlen = *(int *)RTA_DATA(tb[IFLA_TXQLEN]);
139 else {
140 struct ifreq ifr;
141 int s = socket(AF_INET, SOCK_STREAM, 0);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000142
Eric Dumazetf78e3162009-10-22 18:13:21 +0000143 if (s < 0)
144 return;
145
146 memset(&ifr, 0, sizeof(ifr));
147 strcpy(ifr.ifr_name, (char *)RTA_DATA(tb[IFLA_IFNAME]));
148 if (ioctl(s, SIOCGIFTXQLEN, &ifr) < 0) {
149 fprintf(f, "ioctl(SIOCGIFXQLEN) failed: %s\n", strerror(errno));
150 close(s);
151 return;
152 }
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000153 close(s);
Eric Dumazetf78e3162009-10-22 18:13:21 +0000154 qlen = ifr.ifr_qlen;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000155 }
Eric Dumazetf78e3162009-10-22 18:13:21 +0000156 if (qlen)
157 fprintf(f, "qlen %d", qlen);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000158}
159
Patrick McHardy1d934832007-08-22 10:49:01 -0700160static void print_linktype(FILE *fp, struct rtattr *tb)
161{
162 struct rtattr *linkinfo[IFLA_INFO_MAX+1];
163 struct link_util *lu;
164 char *kind;
165
166 parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb);
167
168 if (!linkinfo[IFLA_INFO_KIND])
169 return;
170 kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]);
171
172 fprintf(fp, "%s", _SL_);
173 fprintf(fp, " %s ", kind);
174
175 lu = get_link_kind(kind);
176 if (!lu || !lu->print_opt)
177 return;
178
179 if (1) {
180 struct rtattr *attr[lu->maxattr+1], **data = NULL;
181
182 if (linkinfo[IFLA_INFO_DATA]) {
183 parse_rtattr_nested(attr, lu->maxattr,
184 linkinfo[IFLA_INFO_DATA]);
185 data = attr;
186 }
187 lu->print_opt(lu, fp, data);
188
189 if (linkinfo[IFLA_INFO_XSTATS] && show_stats &&
190 lu->print_xstats)
191 lu->print_xstats(lu, fp, linkinfo[IFLA_INFO_XSTATS]);
192 }
193}
194
Chris Wright3fd86632010-05-18 00:57:00 -0700195static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
196{
197 struct ifla_vf_mac *vf_mac;
198 struct ifla_vf_vlan *vf_vlan;
199 struct ifla_vf_tx_rate *vf_tx_rate;
Greg Rose7b8179c2011-10-13 20:31:32 +0000200 struct ifla_vf_spoofchk *vf_spoofchk;
Chris Wright3fd86632010-05-18 00:57:00 -0700201 struct rtattr *vf[IFLA_VF_MAX+1];
Greg Rose7b8179c2011-10-13 20:31:32 +0000202 struct rtattr *tmp;
Chris Wright3fd86632010-05-18 00:57:00 -0700203 SPRINT_BUF(b1);
204
205 if (vfinfo->rta_type != IFLA_VF_INFO) {
206 fprintf(stderr, "BUG: rta type is %d\n", vfinfo->rta_type);
207 return;
208 }
209
210 parse_rtattr_nested(vf, IFLA_VF_MAX, vfinfo);
211
212 vf_mac = RTA_DATA(vf[IFLA_VF_MAC]);
213 vf_vlan = RTA_DATA(vf[IFLA_VF_VLAN]);
214 vf_tx_rate = RTA_DATA(vf[IFLA_VF_TX_RATE]);
215
Greg Rose7b8179c2011-10-13 20:31:32 +0000216 /* Check if the spoof checking vf info type is supported by
217 * this kernel.
218 */
219 tmp = (struct rtattr *)((char *)vf[IFLA_VF_TX_RATE] +
220 vf[IFLA_VF_TX_RATE]->rta_len);
221
222 if (tmp->rta_type != IFLA_VF_SPOOFCHK)
223 vf_spoofchk = NULL;
224 else
225 vf_spoofchk = RTA_DATA(vf[IFLA_VF_SPOOFCHK]);
226
Chris Wright3fd86632010-05-18 00:57:00 -0700227 fprintf(fp, "\n vf %d MAC %s", vf_mac->vf,
228 ll_addr_n2a((unsigned char *)&vf_mac->mac,
229 ETH_ALEN, 0, b1, sizeof(b1)));
230 if (vf_vlan->vlan)
231 fprintf(fp, ", vlan %d", vf_vlan->vlan);
232 if (vf_vlan->qos)
233 fprintf(fp, ", qos %d", vf_vlan->qos);
234 if (vf_tx_rate->rate)
235 fprintf(fp, ", tx rate %d (Mbps)", vf_tx_rate->rate);
Greg Rose7b8179c2011-10-13 20:31:32 +0000236 if (vf_spoofchk && vf_spoofchk->setting != -1) {
237 if (vf_spoofchk->setting)
238 fprintf(fp, ", spoof checking on");
239 else
240 fprintf(fp, ", spoof checking off");
241 }
Chris Wright3fd86632010-05-18 00:57:00 -0700242}
243
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800244int print_linkinfo(const struct sockaddr_nl *who,
osdl.net!shemminger50772dc2004-12-07 21:48:29 +0000245 struct nlmsghdr *n, void *arg)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000246{
247 FILE *fp = (FILE*)arg;
248 struct ifinfomsg *ifi = NLMSG_DATA(n);
249 struct rtattr * tb[IFLA_MAX+1];
250 int len = n->nlmsg_len;
251 unsigned m_flag = 0;
252
253 if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
254 return 0;
255
256 len -= NLMSG_LENGTH(sizeof(*ifi));
257 if (len < 0)
258 return -1;
259
260 if (filter.ifindex && ifi->ifi_index != filter.ifindex)
261 return 0;
262 if (filter.up && !(ifi->ifi_flags&IFF_UP))
263 return 0;
264
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000265 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
266 if (tb[IFLA_IFNAME] == NULL) {
jamal4cd23bd2008-08-08 10:06:17 -0400267 fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000268 }
269 if (filter.label &&
270 (!filter.family || filter.family == AF_PACKET) &&
271 fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0))
272 return 0;
273
Vlad Dogaruf960c922011-02-02 20:23:40 +0200274 if (tb[IFLA_GROUP]) {
275 int group = *(int*)RTA_DATA(tb[IFLA_GROUP]);
276 if (group != filter.group)
277 return -1;
278 }
279
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000280 if (n->nlmsg_type == RTM_DELLINK)
281 fprintf(fp, "Deleted ");
282
283 fprintf(fp, "%d: %s", ifi->ifi_index,
284 tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>");
285
286 if (tb[IFLA_LINK]) {
287 SPRINT_BUF(b1);
288 int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]);
289 if (iflink == 0)
290 fprintf(fp, "@NONE: ");
291 else {
292 fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
293 m_flag = ll_index_to_flags(iflink);
294 m_flag = !(m_flag & IFF_UP);
295 }
296 } else {
297 fprintf(fp, ": ");
298 }
299 print_link_flags(fp, ifi->ifi_flags, m_flag);
300
301 if (tb[IFLA_MTU])
302 fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));
303 if (tb[IFLA_QDISC])
304 fprintf(fp, "qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000305 if (tb[IFLA_MASTER]) {
306 SPRINT_BUF(b1);
307 fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
308 }
Stephen Hemminger3d866ba2008-03-14 15:30:03 -0700309 if (tb[IFLA_OPERSTATE])
310 print_operstate(fp, *(__u8 *)RTA_DATA(tb[IFLA_OPERSTATE]));
311
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000312 if (filter.showqueue)
Eric Dumazetf78e3162009-10-22 18:13:21 +0000313 print_queuelen(fp, tb);
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800314
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000315 if (!filter.family || filter.family == AF_PACKET) {
316 SPRINT_BUF(b1);
317 fprintf(fp, "%s", _SL_);
318 fprintf(fp, " link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));
319
320 if (tb[IFLA_ADDRESS]) {
321 fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
322 RTA_PAYLOAD(tb[IFLA_ADDRESS]),
323 ifi->ifi_type,
324 b1, sizeof(b1)));
325 }
326 if (tb[IFLA_BROADCAST]) {
327 if (ifi->ifi_flags&IFF_POINTOPOINT)
328 fprintf(fp, " peer ");
329 else
330 fprintf(fp, " brd ");
331 fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
332 RTA_PAYLOAD(tb[IFLA_BROADCAST]),
333 ifi->ifi_type,
334 b1, sizeof(b1)));
335 }
336 }
Patrick McHardy1d934832007-08-22 10:49:01 -0700337
338 if (do_link && tb[IFLA_LINKINFO] && show_details)
339 print_linktype(fp, tb[IFLA_LINKINFO]);
340
Stephen Hemmingerace9c962009-03-23 10:46:47 -0700341 if (do_link && tb[IFLA_IFALIAS])
342 fprintf(fp,"\n alias %s",
343 (const char *) RTA_DATA(tb[IFLA_IFALIAS]));
344
Jan Engelhardt8864ac92010-03-11 10:00:34 +0000345 if (do_link && tb[IFLA_STATS64] && show_stats) {
346 struct rtnl_link_stats64 slocal;
347 struct rtnl_link_stats64 *s = RTA_DATA(tb[IFLA_STATS64]);
348 if (((unsigned long)s) & (sizeof(unsigned long)-1)) {
349 memcpy(&slocal, s, sizeof(slocal));
350 s = &slocal;
351 }
352 fprintf(fp, "%s", _SL_);
353 fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s",
354 s->rx_compressed ? "compressed" : "", _SL_);
355 fprintf(fp, " %-10llu %-8llu %-7llu %-7llu %-7llu %-7llu",
356 (unsigned long long)s->rx_bytes,
357 (unsigned long long)s->rx_packets,
358 (unsigned long long)s->rx_errors,
359 (unsigned long long)s->rx_dropped,
360 (unsigned long long)s->rx_over_errors,
361 (unsigned long long)s->multicast);
362 if (s->rx_compressed)
363 fprintf(fp, " %-7llu",
364 (unsigned long long)s->rx_compressed);
365 if (show_stats > 1) {
366 fprintf(fp, "%s", _SL_);
367 fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_);
368 fprintf(fp, " %-7llu %-7llu %-7llu %-7llu %-7llu",
369 (unsigned long long)s->rx_length_errors,
370 (unsigned long long)s->rx_crc_errors,
371 (unsigned long long)s->rx_frame_errors,
372 (unsigned long long)s->rx_fifo_errors,
373 (unsigned long long)s->rx_missed_errors);
374 }
375 fprintf(fp, "%s", _SL_);
376 fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s",
377 s->tx_compressed ? "compressed" : "", _SL_);
378 fprintf(fp, " %-10llu %-8llu %-7llu %-7llu %-7llu %-7llu",
379 (unsigned long long)s->tx_bytes,
380 (unsigned long long)s->tx_packets,
381 (unsigned long long)s->tx_errors,
382 (unsigned long long)s->tx_dropped,
383 (unsigned long long)s->tx_carrier_errors,
384 (unsigned long long)s->collisions);
385 if (s->tx_compressed)
386 fprintf(fp, " %-7llu",
387 (unsigned long long)s->tx_compressed);
388 if (show_stats > 1) {
389 fprintf(fp, "%s", _SL_);
390 fprintf(fp, " TX errors: aborted fifo window heartbeat%s", _SL_);
391 fprintf(fp, " %-7llu %-7llu %-7llu %-7llu",
392 (unsigned long long)s->tx_aborted_errors,
393 (unsigned long long)s->tx_fifo_errors,
394 (unsigned long long)s->tx_window_errors,
395 (unsigned long long)s->tx_heartbeat_errors);
396 }
397 }
398 if (do_link && !tb[IFLA_STATS64] && tb[IFLA_STATS] && show_stats) {
net[shemminger]!shemmingerae0f1442004-10-19 19:57:38 +0000399 struct rtnl_link_stats slocal;
400 struct rtnl_link_stats *s = RTA_DATA(tb[IFLA_STATS]);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000401 if (((unsigned long)s) & (sizeof(unsigned long)-1)) {
402 memcpy(&slocal, s, sizeof(slocal));
403 s = &slocal;
404 }
405 fprintf(fp, "%s", _SL_);
406 fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s",
407 s->rx_compressed ? "compressed" : "", _SL_);
net[shemminger]!shemmingerae0f1442004-10-19 19:57:38 +0000408 fprintf(fp, " %-10u %-8u %-7u %-7u %-7u %-7u",
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000409 s->rx_bytes, s->rx_packets, s->rx_errors,
410 s->rx_dropped, s->rx_over_errors,
411 s->multicast
412 );
413 if (s->rx_compressed)
net[shemminger]!shemmingerae0f1442004-10-19 19:57:38 +0000414 fprintf(fp, " %-7u", s->rx_compressed);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000415 if (show_stats > 1) {
416 fprintf(fp, "%s", _SL_);
417 fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_);
net[shemminger]!shemmingerae0f1442004-10-19 19:57:38 +0000418 fprintf(fp, " %-7u %-7u %-7u %-7u %-7u",
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000419 s->rx_length_errors,
420 s->rx_crc_errors,
421 s->rx_frame_errors,
422 s->rx_fifo_errors,
423 s->rx_missed_errors
424 );
425 }
426 fprintf(fp, "%s", _SL_);
427 fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s",
428 s->tx_compressed ? "compressed" : "", _SL_);
net[shemminger]!shemmingerae0f1442004-10-19 19:57:38 +0000429 fprintf(fp, " %-10u %-8u %-7u %-7u %-7u %-7u",
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000430 s->tx_bytes, s->tx_packets, s->tx_errors,
431 s->tx_dropped, s->tx_carrier_errors, s->collisions);
432 if (s->tx_compressed)
net[shemminger]!shemmingerae0f1442004-10-19 19:57:38 +0000433 fprintf(fp, " %-7u", s->tx_compressed);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000434 if (show_stats > 1) {
435 fprintf(fp, "%s", _SL_);
436 fprintf(fp, " TX errors: aborted fifo window heartbeat%s", _SL_);
net[shemminger]!shemmingerae0f1442004-10-19 19:57:38 +0000437 fprintf(fp, " %-7u %-7u %-7u %-7u",
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000438 s->tx_aborted_errors,
439 s->tx_fifo_errors,
440 s->tx_window_errors,
441 s->tx_heartbeat_errors
442 );
443 }
444 }
Chris Wright3fd86632010-05-18 00:57:00 -0700445 if (do_link && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) {
446 struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST];
447 int rem = RTA_PAYLOAD(vflist);
448 for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
449 print_vfinfo(fp, i);
Williams, Mitch Aae7229d2010-02-10 01:47:08 +0000450 }
Chris Wright3fd86632010-05-18 00:57:00 -0700451
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000452 fprintf(fp, "\n");
453 fflush(fp);
454 return 0;
455}
456
457static int flush_update(void)
458{
Stephen Hemmingerf31a37f2008-01-31 21:38:58 -0800459 if (rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) {
Stephen Hemminger1fb0a992008-01-26 11:08:31 -0800460 perror("Failed to send flush request");
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000461 return -1;
462 }
463 filter.flushp = 0;
464 return 0;
465}
466
Masahide NAKAMURA35546df2006-11-24 12:26:55 +0900467static int set_lifetime(unsigned int *lifetime, char *argv)
468{
469 if (strcmp(argv, "forever") == 0)
Masahide NAKAMURA141bb602006-11-24 12:27:01 +0900470 *lifetime = INFINITY_LIFE_TIME;
Masahide NAKAMURA35546df2006-11-24 12:26:55 +0900471 else if (get_u32(lifetime, argv, 0))
472 return -1;
473
474 return 0;
475}
476
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800477int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
osdl.net!shemminger6dc9f012004-08-31 17:45:21 +0000478 void *arg)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000479{
480 FILE *fp = (FILE*)arg;
481 struct ifaddrmsg *ifa = NLMSG_DATA(n);
482 int len = n->nlmsg_len;
Benedikt Gollatz037d9502009-01-06 19:36:56 -0800483 int deprecated = 0;
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700484 /* Use local copy of ifa_flags to not interfere with filtering code */
485 unsigned int ifa_flags;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000486 struct rtattr * rta_tb[IFA_MAX+1];
487 char abuf[256];
488 SPRINT_BUF(b1);
489
490 if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
491 return 0;
492 len -= NLMSG_LENGTH(sizeof(*ifa));
493 if (len < 0) {
494 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
495 return -1;
496 }
497
498 if (filter.flushb && n->nlmsg_type != RTM_NEWADDR)
499 return 0;
500
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000501 parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
502
503 if (!rta_tb[IFA_LOCAL])
504 rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
505 if (!rta_tb[IFA_ADDRESS])
506 rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];
507
508 if (filter.ifindex && filter.ifindex != ifa->ifa_index)
509 return 0;
510 if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
511 return 0;
512 if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
513 return 0;
514 if (filter.label) {
515 SPRINT_BUF(b1);
516 const char *label;
517 if (rta_tb[IFA_LABEL])
518 label = RTA_DATA(rta_tb[IFA_LABEL]);
519 else
520 label = ll_idx_n2a(ifa->ifa_index, b1);
521 if (fnmatch(filter.label, label, 0) != 0)
522 return 0;
523 }
524 if (filter.pfx.family) {
525 if (rta_tb[IFA_LOCAL]) {
526 inet_prefix dst;
527 memset(&dst, 0, sizeof(dst));
528 dst.family = ifa->ifa_family;
529 memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL]));
530 if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
531 return 0;
532 }
533 }
534
net[shemminger]!shemminger3eb17312005-02-07 18:28:31 +0000535 if (filter.family && filter.family != ifa->ifa_family)
536 return 0;
537
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000538 if (filter.flushb) {
539 struct nlmsghdr *fn;
540 if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
541 if (flush_update())
542 return -1;
543 }
544 fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
545 memcpy(fn, n, n->nlmsg_len);
546 fn->nlmsg_type = RTM_DELADDR;
547 fn->nlmsg_flags = NLM_F_REQUEST;
shemminger351efcd2005-09-01 19:21:50 +0000548 fn->nlmsg_seq = ++rth.seq;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000549 filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
550 filter.flushed++;
551 if (show_stats < 2)
552 return 0;
553 }
554
555 if (n->nlmsg_type == RTM_DELADDR)
556 fprintf(fp, "Deleted ");
557
558 if (filter.oneline || filter.flushb)
559 fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
560 if (ifa->ifa_family == AF_INET)
561 fprintf(fp, " inet ");
562 else if (ifa->ifa_family == AF_INET6)
563 fprintf(fp, " inet6 ");
564 else if (ifa->ifa_family == AF_DECnet)
565 fprintf(fp, " dnet ");
566 else if (ifa->ifa_family == AF_IPX)
567 fprintf(fp, " ipx ");
568 else
569 fprintf(fp, " family %d ", ifa->ifa_family);
570
571 if (rta_tb[IFA_LOCAL]) {
572 fprintf(fp, "%s", rt_addr_n2a(ifa->ifa_family,
573 RTA_PAYLOAD(rta_tb[IFA_LOCAL]),
574 RTA_DATA(rta_tb[IFA_LOCAL]),
575 abuf, sizeof(abuf)));
576
577 if (rta_tb[IFA_ADDRESS] == NULL ||
578 memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) {
579 fprintf(fp, "/%d ", ifa->ifa_prefixlen);
580 } else {
581 fprintf(fp, " peer %s/%d ",
582 rt_addr_n2a(ifa->ifa_family,
583 RTA_PAYLOAD(rta_tb[IFA_ADDRESS]),
584 RTA_DATA(rta_tb[IFA_ADDRESS]),
585 abuf, sizeof(abuf)),
586 ifa->ifa_prefixlen);
587 }
588 }
589
590 if (rta_tb[IFA_BROADCAST]) {
591 fprintf(fp, "brd %s ",
592 rt_addr_n2a(ifa->ifa_family,
593 RTA_PAYLOAD(rta_tb[IFA_BROADCAST]),
594 RTA_DATA(rta_tb[IFA_BROADCAST]),
595 abuf, sizeof(abuf)));
596 }
597 if (rta_tb[IFA_ANYCAST]) {
598 fprintf(fp, "any %s ",
599 rt_addr_n2a(ifa->ifa_family,
600 RTA_PAYLOAD(rta_tb[IFA_ANYCAST]),
601 RTA_DATA(rta_tb[IFA_ANYCAST]),
602 abuf, sizeof(abuf)));
603 }
604 fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700605 ifa_flags = ifa->ifa_flags;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000606 if (ifa->ifa_flags&IFA_F_SECONDARY) {
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700607 ifa_flags &= ~IFA_F_SECONDARY;
Brian Haleya1b9ffc2009-09-14 17:01:43 -0400608 if (ifa->ifa_family == AF_INET6)
609 fprintf(fp, "temporary ");
610 else
611 fprintf(fp, "secondary ");
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000612 }
613 if (ifa->ifa_flags&IFA_F_TENTATIVE) {
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700614 ifa_flags &= ~IFA_F_TENTATIVE;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000615 fprintf(fp, "tentative ");
616 }
617 if (ifa->ifa_flags&IFA_F_DEPRECATED) {
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700618 ifa_flags &= ~IFA_F_DEPRECATED;
Benedikt Gollatz037d9502009-01-06 19:36:56 -0800619 deprecated = 1;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000620 fprintf(fp, "deprecated ");
621 }
Noriaki TAKAMIYAbac735c2007-03-08 03:15:43 +0900622 if (ifa->ifa_flags&IFA_F_HOMEADDRESS) {
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700623 ifa_flags &= ~IFA_F_HOMEADDRESS;
Noriaki TAKAMIYAbac735c2007-03-08 03:15:43 +0900624 fprintf(fp, "home ");
625 }
626 if (ifa->ifa_flags&IFA_F_NODAD) {
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700627 ifa_flags &= ~IFA_F_NODAD;
Noriaki TAKAMIYAbac735c2007-03-08 03:15:43 +0900628 fprintf(fp, "nodad ");
629 }
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000630 if (!(ifa->ifa_flags&IFA_F_PERMANENT)) {
631 fprintf(fp, "dynamic ");
632 } else
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700633 ifa_flags &= ~IFA_F_PERMANENT;
Brian Haleyf4af8512009-12-01 15:58:44 -0800634 if (ifa->ifa_flags&IFA_F_DADFAILED) {
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700635 ifa_flags &= ~IFA_F_DADFAILED;
Brian Haleyf4af8512009-12-01 15:58:44 -0800636 fprintf(fp, "dadfailed ");
637 }
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700638 if (ifa_flags)
639 fprintf(fp, "flags %02x ", ifa_flags);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000640 if (rta_tb[IFA_LABEL])
641 fprintf(fp, "%s", (char*)RTA_DATA(rta_tb[IFA_LABEL]));
642 if (rta_tb[IFA_CACHEINFO]) {
643 struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000644 fprintf(fp, "%s", _SL_);
Andreas Schwabf66efad2010-11-05 23:26:29 +0000645 fprintf(fp, " valid_lft ");
Masahide NAKAMURA141bb602006-11-24 12:27:01 +0900646 if (ci->ifa_valid == INFINITY_LIFE_TIME)
Andreas Schwabf66efad2010-11-05 23:26:29 +0000647 fprintf(fp, "forever");
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000648 else
Andreas Schwabf66efad2010-11-05 23:26:29 +0000649 fprintf(fp, "%usec", ci->ifa_valid);
650 fprintf(fp, " preferred_lft ");
Masahide NAKAMURA141bb602006-11-24 12:27:01 +0900651 if (ci->ifa_prefered == INFINITY_LIFE_TIME)
Andreas Schwabf66efad2010-11-05 23:26:29 +0000652 fprintf(fp, "forever");
Benedikt Gollatz037d9502009-01-06 19:36:56 -0800653 else {
654 if (deprecated)
Andreas Schwabf66efad2010-11-05 23:26:29 +0000655 fprintf(fp, "%dsec", ci->ifa_prefered);
Benedikt Gollatz037d9502009-01-06 19:36:56 -0800656 else
Andreas Schwabf66efad2010-11-05 23:26:29 +0000657 fprintf(fp, "%usec", ci->ifa_prefered);
Benedikt Gollatz037d9502009-01-06 19:36:56 -0800658 }
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000659 }
660 fprintf(fp, "\n");
661 fflush(fp);
662 return 0;
663}
664
Simon Hormanb49240e2009-12-03 12:08:27 +1100665int print_addrinfo_primary(const struct sockaddr_nl *who, struct nlmsghdr *n,
666 void *arg)
667{
668 struct ifaddrmsg *ifa = NLMSG_DATA(n);
669
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700670 if (ifa->ifa_flags & IFA_F_SECONDARY)
Simon Hormanb49240e2009-12-03 12:08:27 +1100671 return 0;
672
673 return print_addrinfo(who, n, arg);
674}
675
676int print_addrinfo_secondary(const struct sockaddr_nl *who, struct nlmsghdr *n,
677 void *arg)
678{
679 struct ifaddrmsg *ifa = NLMSG_DATA(n);
680
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700681 if (!(ifa->ifa_flags & IFA_F_SECONDARY))
Simon Hormanb49240e2009-12-03 12:08:27 +1100682 return 0;
683
684 return print_addrinfo(who, n, arg);
685}
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000686
687struct nlmsg_list
688{
689 struct nlmsg_list *next;
690 struct nlmsghdr h;
691};
692
Stephen Hemminger3d866ba2008-03-14 15:30:03 -0700693static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000694{
695 for ( ;ainfo ; ainfo = ainfo->next) {
696 struct nlmsghdr *n = &ainfo->h;
697 struct ifaddrmsg *ifa = NLMSG_DATA(n);
698
699 if (n->nlmsg_type != RTM_NEWADDR)
700 continue;
701
702 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa)))
703 return -1;
704
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800705 if (ifa->ifa_index != ifindex ||
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000706 (filter.family && filter.family != ifa->ifa_family))
707 continue;
708
709 print_addrinfo(NULL, n, fp);
710 }
711 return 0;
712}
713
714
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800715static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
osdl.net!shemminger6dc9f012004-08-31 17:45:21 +0000716 void *arg)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000717{
718 struct nlmsg_list **linfo = (struct nlmsg_list**)arg;
719 struct nlmsg_list *h;
720 struct nlmsg_list **lp;
721
722 h = malloc(n->nlmsg_len+sizeof(void*));
723 if (h == NULL)
724 return -1;
725
726 memcpy(&h->h, n, n->nlmsg_len);
727 h->next = NULL;
728
729 for (lp = linfo; *lp; lp = &(*lp)->next) /* NOTHING */;
730 *lp = h;
731
732 ll_remember_index(who, n, NULL);
733 return 0;
734}
735
Stephen Hemminger3d866ba2008-03-14 15:30:03 -0700736static int ipaddr_list_or_flush(int argc, char **argv, int flush)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000737{
738 struct nlmsg_list *linfo = NULL;
739 struct nlmsg_list *ainfo = NULL;
shemminger8ed63ab2005-09-21 19:33:17 +0000740 struct nlmsg_list *l, *n;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000741 char *filter_dev = NULL;
742 int no_link = 0;
743
744 ipaddr_reset_filter(oneline);
745 filter.showqueue = 1;
746
747 if (filter.family == AF_UNSPEC)
748 filter.family = preferred_family;
749
Stephen Hemminger242b8da2011-04-12 14:40:14 -0700750 filter.group = INIT_NETDEV_GROUP;
Vlad Dogaruf960c922011-02-02 20:23:40 +0200751
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000752 if (flush) {
753 if (argc <= 0) {
754 fprintf(stderr, "Flush requires arguments.\n");
Vlad Dogaruf960c922011-02-02 20:23:40 +0200755
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000756 return -1;
757 }
758 if (filter.family == AF_PACKET) {
759 fprintf(stderr, "Cannot flush link addresses.\n");
760 return -1;
761 }
762 }
763
764 while (argc > 0) {
765 if (strcmp(*argv, "to") == 0) {
766 NEXT_ARG();
767 get_prefix(&filter.pfx, *argv, filter.family);
768 if (filter.family == AF_UNSPEC)
769 filter.family = filter.pfx.family;
770 } else if (strcmp(*argv, "scope") == 0) {
shemmingerf332d162005-07-05 22:37:15 +0000771 unsigned scope = 0;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000772 NEXT_ARG();
773 filter.scopemask = -1;
774 if (rtnl_rtscope_a2n(&scope, *argv)) {
775 if (strcmp(*argv, "all") != 0)
776 invarg("invalid \"scope\"\n", *argv);
777 scope = RT_SCOPE_NOWHERE;
778 filter.scopemask = 0;
779 }
780 filter.scope = scope;
781 } else if (strcmp(*argv, "up") == 0) {
782 filter.up = 1;
783 } else if (strcmp(*argv, "dynamic") == 0) {
784 filter.flags &= ~IFA_F_PERMANENT;
785 filter.flagmask |= IFA_F_PERMANENT;
786 } else if (strcmp(*argv, "permanent") == 0) {
787 filter.flags |= IFA_F_PERMANENT;
788 filter.flagmask |= IFA_F_PERMANENT;
Brian Haleya1b9ffc2009-09-14 17:01:43 -0400789 } else if (strcmp(*argv, "secondary") == 0 ||
790 strcmp(*argv, "temporary") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000791 filter.flags |= IFA_F_SECONDARY;
792 filter.flagmask |= IFA_F_SECONDARY;
793 } else if (strcmp(*argv, "primary") == 0) {
794 filter.flags &= ~IFA_F_SECONDARY;
795 filter.flagmask |= IFA_F_SECONDARY;
796 } else if (strcmp(*argv, "tentative") == 0) {
797 filter.flags |= IFA_F_TENTATIVE;
798 filter.flagmask |= IFA_F_TENTATIVE;
799 } else if (strcmp(*argv, "deprecated") == 0) {
800 filter.flags |= IFA_F_DEPRECATED;
801 filter.flagmask |= IFA_F_DEPRECATED;
Noriaki TAKAMIYAbac735c2007-03-08 03:15:43 +0900802 } else if (strcmp(*argv, "home") == 0) {
803 filter.flags |= IFA_F_HOMEADDRESS;
804 filter.flagmask |= IFA_F_HOMEADDRESS;
805 } else if (strcmp(*argv, "nodad") == 0) {
806 filter.flags |= IFA_F_NODAD;
807 filter.flagmask |= IFA_F_NODAD;
Brian Haleya1f27792009-12-03 10:39:36 +0000808 } else if (strcmp(*argv, "dadfailed") == 0) {
809 filter.flags |= IFA_F_DADFAILED;
810 filter.flagmask |= IFA_F_DADFAILED;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000811 } else if (strcmp(*argv, "label") == 0) {
812 NEXT_ARG();
813 filter.label = *argv;
Vlad Dogaruf960c922011-02-02 20:23:40 +0200814 } else if (strcmp(*argv, "group") == 0) {
815 NEXT_ARG();
816 if (rtnl_group_a2n(&filter.group, *argv))
817 invarg("Invalid \"group\" value\n", *argv);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000818 } else {
819 if (strcmp(*argv, "dev") == 0) {
820 NEXT_ARG();
821 }
822 if (matches(*argv, "help") == 0)
823 usage();
824 if (filter_dev)
825 duparg2("dev", *argv);
826 filter_dev = *argv;
827 }
828 argv++; argc--;
829 }
830
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000831 if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) {
832 perror("Cannot send dump request");
833 exit(1);
834 }
835
836 if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) {
837 fprintf(stderr, "Dump terminated\n");
838 exit(1);
839 }
840
841 if (filter_dev) {
842 filter.ifindex = ll_name_to_index(filter_dev);
843 if (filter.ifindex <= 0) {
844 fprintf(stderr, "Device \"%s\" does not exist.\n", filter_dev);
845 return -1;
846 }
847 }
848
849 if (flush) {
850 int round = 0;
851 char flushb[4096-512];
852
853 filter.flushb = flushb;
854 filter.flushp = 0;
855 filter.flushe = sizeof(flushb);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000856
Ben Greear64c79562010-12-01 11:13:51 -0800857 while ((max_flush_loops == 0) || (round < max_flush_loops)) {
Simon Hormanb49240e2009-12-03 12:08:27 +1100858 const struct rtnl_dump_filter_arg a[3] = {
859 {
860 .filter = print_addrinfo_secondary,
861 .arg1 = stdout,
862 .junk = NULL,
863 .arg2 = NULL
864 },
865 {
866 .filter = print_addrinfo_primary,
867 .arg1 = stdout,
868 .junk = NULL,
869 .arg2 = NULL
870 },
871 {
872 .filter = NULL,
873 .arg1 = NULL,
874 .junk = NULL,
875 .arg2 = NULL
876 },
877 };
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000878 if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
879 perror("Cannot send dump request");
880 exit(1);
881 }
882 filter.flushed = 0;
Simon Hormanb49240e2009-12-03 12:08:27 +1100883 if (rtnl_dump_filter_l(&rth, a) < 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000884 fprintf(stderr, "Flush terminated\n");
885 exit(1);
886 }
887 if (filter.flushed == 0) {
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700888flush_done:
Andreas Henrikssonf0b34d22008-08-29 19:52:48 +0200889 if (show_stats) {
890 if (round == 0)
891 printf("Nothing to flush.\n");
892 else
893 printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":"");
894 }
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000895 fflush(stdout);
896 return 0;
897 }
898 round++;
899 if (flush_update() < 0)
shemminger351efcd2005-09-01 19:21:50 +0000900 return 1;
901
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000902 if (show_stats) {
903 printf("\n*** Round %d, deleting %d addresses ***\n", round, filter.flushed);
904 fflush(stdout);
905 }
Ben Greear3bc1c4f2010-08-16 10:00:08 -0700906
907 /* If we are flushing, and specifying primary, then we
908 * want to flush only a single round. Otherwise, we'll
909 * start flushing secondaries that were promoted to
910 * primaries.
911 */
912 if (!(filter.flags & IFA_F_SECONDARY) && (filter.flagmask & IFA_F_SECONDARY))
913 goto flush_done;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000914 }
Ben Greear64c79562010-12-01 11:13:51 -0800915 fprintf(stderr, "*** Flush remains incomplete after %d rounds. ***\n", max_flush_loops);
916 fflush(stderr);
Daniel Silverstone7b3d3662007-10-19 13:32:24 +0200917 return 1;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000918 }
919
920 if (filter.family != AF_PACKET) {
921 if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
922 perror("Cannot send dump request");
923 exit(1);
924 }
925
926 if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) {
927 fprintf(stderr, "Dump terminated\n");
928 exit(1);
929 }
930 }
931
932
933 if (filter.family && filter.family != AF_PACKET) {
934 struct nlmsg_list **lp;
935 lp=&linfo;
936
937 if (filter.oneline)
938 no_link = 1;
939
940 while ((l=*lp)!=NULL) {
941 int ok = 0;
942 struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
943 struct nlmsg_list *a;
944
945 for (a=ainfo; a; a=a->next) {
946 struct nlmsghdr *n = &a->h;
947 struct ifaddrmsg *ifa = NLMSG_DATA(n);
948
Stephen Hemmingerae665a52006-12-05 10:10:22 -0800949 if (ifa->ifa_index != ifi->ifi_index ||
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000950 (filter.family && filter.family != ifa->ifa_family))
951 continue;
952 if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
953 continue;
954 if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
955 continue;
956 if (filter.pfx.family || filter.label) {
957 struct rtattr *tb[IFA_MAX+1];
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000958 parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
959 if (!tb[IFA_LOCAL])
960 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
961
962 if (filter.pfx.family && tb[IFA_LOCAL]) {
963 inet_prefix dst;
964 memset(&dst, 0, sizeof(dst));
965 dst.family = ifa->ifa_family;
966 memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
967 if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
968 continue;
969 }
970 if (filter.label) {
971 SPRINT_BUF(b1);
972 const char *label;
973 if (tb[IFA_LABEL])
974 label = RTA_DATA(tb[IFA_LABEL]);
975 else
976 label = ll_idx_n2a(ifa->ifa_index, b1);
977 if (fnmatch(filter.label, label, 0) != 0)
978 continue;
979 }
980 }
981
982 ok = 1;
983 break;
984 }
985 if (!ok)
986 *lp = l->next;
987 else
988 lp = &l->next;
989 }
990 }
991
shemminger8ed63ab2005-09-21 19:33:17 +0000992 for (l=linfo; l; l = n) {
993 n = l->next;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000994 if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
995 struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
996 if (filter.family != AF_PACKET)
997 print_selected_addrinfo(ifi->ifi_index, ainfo, stdout);
998 }
999 fflush(stdout);
shemminger8ed63ab2005-09-21 19:33:17 +00001000 free(l);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001001 }
1002
shemminger351efcd2005-09-01 19:21:50 +00001003 return 0;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001004}
1005
1006int ipaddr_list_link(int argc, char **argv)
1007{
1008 preferred_family = AF_PACKET;
1009 do_link = 1;
1010 return ipaddr_list_or_flush(argc, argv, 0);
1011}
1012
1013void ipaddr_reset_filter(int oneline)
1014{
1015 memset(&filter, 0, sizeof(filter));
1016 filter.oneline = oneline;
1017}
1018
Stephen Hemminger3d866ba2008-03-14 15:30:03 -07001019static int default_scope(inet_prefix *lcl)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001020{
1021 if (lcl->family == AF_INET) {
1022 if (lcl->bytelen >= 1 && *(__u8*)&lcl->data == 127)
1023 return RT_SCOPE_HOST;
1024 }
1025 return 0;
1026}
1027
Stephen Hemminger3d866ba2008-03-14 15:30:03 -07001028static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001029{
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001030 struct {
1031 struct nlmsghdr n;
1032 struct ifaddrmsg ifa;
1033 char buf[256];
1034 } req;
1035 char *d = NULL;
1036 char *l = NULL;
net[shemminger]!shemmingerf082b642005-03-30 18:16:10 +00001037 char *lcl_arg = NULL;
Masahide NAKAMURA35546df2006-11-24 12:26:55 +09001038 char *valid_lftp = NULL;
1039 char *preferred_lftp = NULL;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001040 inet_prefix lcl;
1041 inet_prefix peer;
1042 int local_len = 0;
1043 int peer_len = 0;
1044 int brd_len = 0;
1045 int any_len = 0;
1046 int scoped = 0;
Masahide NAKAMURA141bb602006-11-24 12:27:01 +09001047 __u32 preferred_lft = INFINITY_LIFE_TIME;
1048 __u32 valid_lft = INFINITY_LIFE_TIME;
Masahide NAKAMURA35546df2006-11-24 12:26:55 +09001049 struct ifa_cacheinfo cinfo;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001050
1051 memset(&req, 0, sizeof(req));
1052
1053 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
Noriaki TAKAMIYA0aef3662006-11-24 12:26:58 +09001054 req.n.nlmsg_flags = NLM_F_REQUEST | flags;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001055 req.n.nlmsg_type = cmd;
1056 req.ifa.ifa_family = preferred_family;
1057
1058 while (argc > 0) {
1059 if (strcmp(*argv, "peer") == 0 ||
1060 strcmp(*argv, "remote") == 0) {
1061 NEXT_ARG();
1062
1063 if (peer_len)
1064 duparg("peer", *argv);
1065 get_prefix(&peer, *argv, req.ifa.ifa_family);
1066 peer_len = peer.bytelen;
1067 if (req.ifa.ifa_family == AF_UNSPEC)
1068 req.ifa.ifa_family = peer.family;
1069 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen);
1070 req.ifa.ifa_prefixlen = peer.bitlen;
1071 } else if (matches(*argv, "broadcast") == 0 ||
1072 strcmp(*argv, "brd") == 0) {
1073 inet_prefix addr;
1074 NEXT_ARG();
1075 if (brd_len)
1076 duparg("broadcast", *argv);
1077 if (strcmp(*argv, "+") == 0)
1078 brd_len = -1;
1079 else if (strcmp(*argv, "-") == 0)
1080 brd_len = -2;
1081 else {
1082 get_addr(&addr, *argv, req.ifa.ifa_family);
1083 if (req.ifa.ifa_family == AF_UNSPEC)
1084 req.ifa.ifa_family = addr.family;
1085 addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen);
1086 brd_len = addr.bytelen;
1087 }
1088 } else if (strcmp(*argv, "anycast") == 0) {
1089 inet_prefix addr;
1090 NEXT_ARG();
1091 if (any_len)
1092 duparg("anycast", *argv);
1093 get_addr(&addr, *argv, req.ifa.ifa_family);
1094 if (req.ifa.ifa_family == AF_UNSPEC)
1095 req.ifa.ifa_family = addr.family;
1096 addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen);
1097 any_len = addr.bytelen;
1098 } else if (strcmp(*argv, "scope") == 0) {
shemmingerf332d162005-07-05 22:37:15 +00001099 unsigned scope = 0;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001100 NEXT_ARG();
1101 if (rtnl_rtscope_a2n(&scope, *argv))
1102 invarg(*argv, "invalid scope value.");
1103 req.ifa.ifa_scope = scope;
1104 scoped = 1;
1105 } else if (strcmp(*argv, "dev") == 0) {
1106 NEXT_ARG();
1107 d = *argv;
1108 } else if (strcmp(*argv, "label") == 0) {
1109 NEXT_ARG();
1110 l = *argv;
1111 addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1);
Masahide NAKAMURA35546df2006-11-24 12:26:55 +09001112 } else if (matches(*argv, "valid_lft") == 0) {
1113 if (valid_lftp)
1114 duparg("valid_lft", *argv);
1115 NEXT_ARG();
1116 valid_lftp = *argv;
1117 if (set_lifetime(&valid_lft, *argv))
1118 invarg("valid_lft value", *argv);
1119 } else if (matches(*argv, "preferred_lft") == 0) {
1120 if (preferred_lftp)
1121 duparg("preferred_lft", *argv);
1122 NEXT_ARG();
1123 preferred_lftp = *argv;
1124 if (set_lifetime(&preferred_lft, *argv))
1125 invarg("preferred_lft value", *argv);
Noriaki TAKAMIYAbac735c2007-03-08 03:15:43 +09001126 } else if (strcmp(*argv, "home") == 0) {
1127 req.ifa.ifa_flags |= IFA_F_HOMEADDRESS;
1128 } else if (strcmp(*argv, "nodad") == 0) {
1129 req.ifa.ifa_flags |= IFA_F_NODAD;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001130 } else {
1131 if (strcmp(*argv, "local") == 0) {
1132 NEXT_ARG();
1133 }
1134 if (matches(*argv, "help") == 0)
1135 usage();
1136 if (local_len)
1137 duparg2("local", *argv);
net[shemminger]!shemmingerf082b642005-03-30 18:16:10 +00001138 lcl_arg = *argv;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001139 get_prefix(&lcl, *argv, req.ifa.ifa_family);
1140 if (req.ifa.ifa_family == AF_UNSPEC)
1141 req.ifa.ifa_family = lcl.family;
1142 addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen);
1143 local_len = lcl.bytelen;
1144 }
1145 argc--; argv++;
1146 }
1147 if (d == NULL) {
1148 fprintf(stderr, "Not enough information: \"dev\" argument is required.\n");
1149 return -1;
1150 }
1151 if (l && matches(d, l) != 0) {
1152 fprintf(stderr, "\"dev\" (%s) must match \"label\" (%s).\n", d, l);
Michele Petrazzo - Unipex1db61e02010-03-06 08:56:53 +00001153 return -1;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001154 }
1155
net[shemminger]!shemmingerf082b642005-03-30 18:16:10 +00001156 if (peer_len == 0 && local_len) {
1157 if (cmd == RTM_DELADDR && lcl.family == AF_INET && !(lcl.flags & PREFIXLEN_SPECIFIED)) {
1158 fprintf(stderr,
1159 "Warning: Executing wildcard deletion to stay compatible with old scripts.\n" \
1160 " Explicitly specify the prefix length (%s/%d) to avoid this warning.\n" \
1161 " This special behaviour is likely to disappear in further releases,\n" \
1162 " fix your scripts!\n", lcl_arg, local_len*8);
1163 } else {
1164 peer = lcl;
1165 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen);
1166 }
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001167 }
1168 if (req.ifa.ifa_prefixlen == 0)
1169 req.ifa.ifa_prefixlen = lcl.bitlen;
1170
1171 if (brd_len < 0 && cmd != RTM_DELADDR) {
1172 inet_prefix brd;
1173 int i;
1174 if (req.ifa.ifa_family != AF_INET) {
1175 fprintf(stderr, "Broadcast can be set only for IPv4 addresses\n");
1176 return -1;
1177 }
1178 brd = peer;
1179 if (brd.bitlen <= 30) {
1180 for (i=31; i>=brd.bitlen; i--) {
1181 if (brd_len == -1)
1182 brd.data[0] |= htonl(1<<(31-i));
1183 else
1184 brd.data[0] &= ~htonl(1<<(31-i));
1185 }
1186 addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen);
1187 brd_len = brd.bytelen;
1188 }
1189 }
1190 if (!scoped && cmd != RTM_DELADDR)
1191 req.ifa.ifa_scope = default_scope(&lcl);
1192
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001193 ll_init_map(&rth);
1194
1195 if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) {
1196 fprintf(stderr, "Cannot find device \"%s\"\n", d);
1197 return -1;
1198 }
1199
Masahide NAKAMURA35546df2006-11-24 12:26:55 +09001200 if (valid_lftp || preferred_lftp) {
1201 if (!valid_lft) {
1202 fprintf(stderr, "valid_lft is zero\n");
1203 return -1;
1204 }
1205 if (valid_lft < preferred_lft) {
1206 fprintf(stderr, "preferred_lft is greater than valid_lft\n");
1207 return -1;
1208 }
1209
1210 memset(&cinfo, 0, sizeof(cinfo));
1211 cinfo.ifa_prefered = preferred_lft;
1212 cinfo.ifa_valid = valid_lft;
1213 addattr_l(&req.n, sizeof(req), IFA_CACHEINFO, &cinfo,
1214 sizeof(cinfo));
1215 }
1216
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001217 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
Michele Petrazzo - Unipex1db61e02010-03-06 08:56:53 +00001218 return -2;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001219
shemminger351efcd2005-09-01 19:21:50 +00001220 return 0;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001221}
1222
1223int do_ipaddr(int argc, char **argv)
1224{
1225 if (argc < 1)
1226 return ipaddr_list_or_flush(0, NULL, 0);
1227 if (matches(*argv, "add") == 0)
Noriaki TAKAMIYA0aef3662006-11-24 12:26:58 +09001228 return ipaddr_modify(RTM_NEWADDR, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1);
1229 if (matches(*argv, "change") == 0 ||
1230 strcmp(*argv, "chg") == 0)
1231 return ipaddr_modify(RTM_NEWADDR, NLM_F_REPLACE, argc-1, argv+1);
1232 if (matches(*argv, "replace") == 0)
1233 return ipaddr_modify(RTM_NEWADDR, NLM_F_CREATE|NLM_F_REPLACE, argc-1, argv+1);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001234 if (matches(*argv, "delete") == 0)
Noriaki TAKAMIYA0aef3662006-11-24 12:26:58 +09001235 return ipaddr_modify(RTM_DELADDR, 0, argc-1, argv+1);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001236 if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
1237 || matches(*argv, "lst") == 0)
1238 return ipaddr_list_or_flush(argc-1, argv+1, 0);
1239 if (matches(*argv, "flush") == 0)
1240 return ipaddr_list_or_flush(argc-1, argv+1, 1);
1241 if (matches(*argv, "help") == 0)
1242 usage();
Alexander Wirtb096fa52007-10-12 10:56:36 +02001243 fprintf(stderr, "Command \"%s\" is unknown, try \"ip addr help\".\n", *argv);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001244 exit(-1);
1245}
1246