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 (at) ms2.inr.ac.ru> 10 * 11 */ 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> 21 #include <sys/errno.h> 22 #include <netinet/in.h> 23 #include <arpa/inet.h> 24 #include <string.h> 25 #include <fnmatch.h> 26 27 #include <linux/netdevice.h> 28 #include <linux/if_arp.h> 29 #include <linux/sockios.h> 30 31 #include "rt_names.h" 32 #include "utils.h" 33 #include "ll_map.h" 34 #include "ip_common.h" 35 36 #define MAX_ROUNDS 10 37 38 static struct 39 { 40 int ifindex; 41 int family; 42 int oneline; 43 int showqueue; 44 inet_prefix pfx; 45 int scope, scopemask; 46 int flags, flagmask; 47 int up; 48 char *label; 49 int flushed; 50 char *flushb; 51 int flushp; 52 int flushe; 53 } filter; 54 55 static int do_link; 56 57 static void usage(void) __attribute__((noreturn)); 58 59 static void usage(void) 60 { 61 if (do_link) { 62 iplink_usage(); 63 } 64 fprintf(stderr, "Usage: ip addr {add|change|replace} IFADDR dev STRING [ LIFETIME ]\n"); 65 fprintf(stderr, " [ CONFFLAG-LIST ]\n"); 66 fprintf(stderr, " ip addr del IFADDR dev STRING\n"); 67 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"); 75 fprintf(stderr, " tentative | deprecated | dadfailed | temporary |\n"); 76 fprintf(stderr, " CONFFLAG-LIST ]\n"); 77 fprintf(stderr, "CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG\n"); 78 fprintf(stderr, "CONFFLAG := [ home | nodad ]\n"); 79 fprintf(stderr, "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n"); 80 fprintf(stderr, "LFT := forever | SECONDS\n"); 81 82 exit(-1); 83 } 84 85 void print_link_flags(FILE *fp, unsigned flags, unsigned mdown) 86 { 87 fprintf(fp, "<"); 88 if (flags & IFF_UP && !(flags & IFF_RUNNING)) 89 fprintf(fp, "NO-CARRIER%s", flags ? "," : ""); 90 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); 109 _PF(LOWER_UP); 110 _PF(DORMANT); 111 _PF(ECHO); 112 #undef _PF 113 if (flags) 114 fprintf(fp, "%x", flags); 115 if (mdown) 116 fprintf(fp, ",M-DOWN"); 117 fprintf(fp, "> "); 118 } 119 120 static const char *oper_states[] = { 121 "UNKNOWN", "NOTPRESENT", "DOWN", "LOWERLAYERDOWN", 122 "TESTING", "DORMANT", "UP" 123 }; 124 125 static 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 133 static void print_queuelen(FILE *f, const char *name) 134 { 135 struct ifreq ifr; 136 int s; 137 138 s = socket(AF_INET, SOCK_STREAM, 0); 139 if (s < 0) 140 return; 141 142 memset(&ifr, 0, sizeof(ifr)); 143 strcpy(ifr.ifr_name, name); 144 if (ioctl(s, SIOCGIFTXQLEN, &ifr) < 0) { 145 fprintf(f, "ioctl(SIOCGIFXQLEN) failed: %s\n", strerror(errno)); 146 close(s); 147 return; 148 } 149 close(s); 150 151 if (ifr.ifr_qlen) 152 fprintf(f, "qlen %d", ifr.ifr_qlen); 153 } 154 155 static void print_linktype(FILE *fp, struct rtattr *tb) 156 { 157 struct rtattr *linkinfo[IFLA_INFO_MAX+1]; 158 struct link_util *lu; 159 char *kind; 160 161 parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); 162 163 if (!linkinfo[IFLA_INFO_KIND]) 164 return; 165 kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); 166 167 fprintf(fp, "%s", _SL_); 168 fprintf(fp, " %s ", kind); 169 170 lu = get_link_kind(kind); 171 if (!lu || !lu->print_opt) 172 return; 173 174 if (1) { 175 struct rtattr *attr[lu->maxattr+1], **data = NULL; 176 177 if (linkinfo[IFLA_INFO_DATA]) { 178 parse_rtattr_nested(attr, lu->maxattr, 179 linkinfo[IFLA_INFO_DATA]); 180 data = attr; 181 } 182 lu->print_opt(lu, fp, data); 183 184 if (linkinfo[IFLA_INFO_XSTATS] && show_stats && 185 lu->print_xstats) 186 lu->print_xstats(lu, fp, linkinfo[IFLA_INFO_XSTATS]); 187 } 188 } 189 190 static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) 191 { 192 struct ifla_vf_mac *vf_mac; 193 struct ifla_vf_vlan *vf_vlan; 194 struct ifla_vf_tx_rate *vf_tx_rate; 195 struct rtattr *vf[IFLA_VF_MAX+1]; 196 SPRINT_BUF(b1); 197 198 if (vfinfo->rta_type != IFLA_VF_INFO) { 199 fprintf(stderr, "BUG: rta type is %d\n", vfinfo->rta_type); 200 return; 201 } 202 203 parse_rtattr_nested(vf, IFLA_VF_MAX, vfinfo); 204 205 vf_mac = RTA_DATA(vf[IFLA_VF_MAC]); 206 vf_vlan = RTA_DATA(vf[IFLA_VF_VLAN]); 207 vf_tx_rate = RTA_DATA(vf[IFLA_VF_TX_RATE]); 208 209 fprintf(fp, "\n vf %d MAC %s", vf_mac->vf, 210 ll_addr_n2a((unsigned char *)&vf_mac->mac, 211 ETH_ALEN, 0, b1, sizeof(b1))); 212 if (vf_vlan->vlan) 213 fprintf(fp, ", vlan %d", vf_vlan->vlan); 214 if (vf_vlan->qos) 215 fprintf(fp, ", qos %d", vf_vlan->qos); 216 if (vf_tx_rate->rate) 217 fprintf(fp, ", tx rate %d (Mbps)", vf_tx_rate->rate); 218 } 219 220 int print_linkinfo(const struct sockaddr_nl *who, 221 struct nlmsghdr *n, void *arg) 222 { 223 FILE *fp = (FILE*)arg; 224 struct ifinfomsg *ifi = NLMSG_DATA(n); 225 struct rtattr * tb[IFLA_MAX+1]; 226 int len = n->nlmsg_len; 227 unsigned m_flag = 0; 228 229 if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) 230 return 0; 231 232 len -= NLMSG_LENGTH(sizeof(*ifi)); 233 if (len < 0) 234 return -1; 235 236 if (filter.ifindex && ifi->ifi_index != filter.ifindex) 237 return 0; 238 if (filter.up && !(ifi->ifi_flags&IFF_UP)) 239 return 0; 240 241 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); 242 if (tb[IFLA_IFNAME] == NULL) { 243 fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index); 244 } 245 if (filter.label && 246 (!filter.family || filter.family == AF_PACKET) && 247 fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0)) 248 return 0; 249 250 if (n->nlmsg_type == RTM_DELLINK) 251 fprintf(fp, "Deleted "); 252 253 fprintf(fp, "%d: %s", ifi->ifi_index, 254 tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>"); 255 256 if (tb[IFLA_LINK]) { 257 SPRINT_BUF(b1); 258 int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]); 259 if (iflink == 0) 260 fprintf(fp, "@NONE: "); 261 else { 262 fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1)); 263 m_flag = ll_index_to_flags(iflink); 264 m_flag = !(m_flag & IFF_UP); 265 } 266 } else { 267 fprintf(fp, ": "); 268 } 269 print_link_flags(fp, ifi->ifi_flags, m_flag); 270 271 if (tb[IFLA_MTU]) 272 fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU])); 273 if (tb[IFLA_QDISC]) 274 fprintf(fp, "qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC])); 275 #ifdef IFLA_MASTER 276 if (tb[IFLA_MASTER]) { 277 SPRINT_BUF(b1); 278 fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1)); 279 } 280 #endif 281 if (tb[IFLA_OPERSTATE]) 282 print_operstate(fp, *(__u8 *)RTA_DATA(tb[IFLA_OPERSTATE])); 283 284 if (filter.showqueue) 285 print_queuelen(fp, (char*)RTA_DATA(tb[IFLA_IFNAME])); 286 287 if (!filter.family || filter.family == AF_PACKET) { 288 SPRINT_BUF(b1); 289 fprintf(fp, "%s", _SL_); 290 fprintf(fp, " link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1))); 291 292 if (tb[IFLA_ADDRESS]) { 293 fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]), 294 RTA_PAYLOAD(tb[IFLA_ADDRESS]), 295 ifi->ifi_type, 296 b1, sizeof(b1))); 297 } 298 if (tb[IFLA_BROADCAST]) { 299 if (ifi->ifi_flags&IFF_POINTOPOINT) 300 fprintf(fp, " peer "); 301 else 302 fprintf(fp, " brd "); 303 fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]), 304 RTA_PAYLOAD(tb[IFLA_BROADCAST]), 305 ifi->ifi_type, 306 b1, sizeof(b1))); 307 } 308 } 309 310 if (do_link && tb[IFLA_LINKINFO] && show_details) 311 print_linktype(fp, tb[IFLA_LINKINFO]); 312 313 if (do_link && tb[IFLA_IFALIAS]) 314 fprintf(fp,"\n alias %s", 315 (const char *) RTA_DATA(tb[IFLA_IFALIAS])); 316 317 if (do_link && tb[IFLA_STATS64] && show_stats) { 318 struct rtnl_link_stats64 slocal; 319 struct rtnl_link_stats64 *s = RTA_DATA(tb[IFLA_STATS64]); 320 if (((unsigned long)s) & (sizeof(unsigned long)-1)) { 321 memcpy(&slocal, s, sizeof(slocal)); 322 s = &slocal; 323 } 324 fprintf(fp, "%s", _SL_); 325 fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s", 326 s->rx_compressed ? "compressed" : "", _SL_); 327 fprintf(fp, " %-10llu %-8llu %-7llu %-7llu %-7llu %-7llu", 328 (unsigned long long)s->rx_bytes, 329 (unsigned long long)s->rx_packets, 330 (unsigned long long)s->rx_errors, 331 (unsigned long long)s->rx_dropped, 332 (unsigned long long)s->rx_over_errors, 333 (unsigned long long)s->multicast); 334 if (s->rx_compressed) 335 fprintf(fp, " %-7llu", 336 (unsigned long long)s->rx_compressed); 337 if (show_stats > 1) { 338 fprintf(fp, "%s", _SL_); 339 fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_); 340 fprintf(fp, " %-7llu %-7llu %-7llu %-7llu %-7llu", 341 (unsigned long long)s->rx_length_errors, 342 (unsigned long long)s->rx_crc_errors, 343 (unsigned long long)s->rx_frame_errors, 344 (unsigned long long)s->rx_fifo_errors, 345 (unsigned long long)s->rx_missed_errors); 346 } 347 fprintf(fp, "%s", _SL_); 348 fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s", 349 s->tx_compressed ? "compressed" : "", _SL_); 350 fprintf(fp, " %-10llu %-8llu %-7llu %-7llu %-7llu %-7llu", 351 (unsigned long long)s->tx_bytes, 352 (unsigned long long)s->tx_packets, 353 (unsigned long long)s->tx_errors, 354 (unsigned long long)s->tx_dropped, 355 (unsigned long long)s->tx_carrier_errors, 356 (unsigned long long)s->collisions); 357 if (s->tx_compressed) 358 fprintf(fp, " %-7llu", 359 (unsigned long long)s->tx_compressed); 360 if (show_stats > 1) { 361 fprintf(fp, "%s", _SL_); 362 fprintf(fp, " TX errors: aborted fifo window heartbeat%s", _SL_); 363 fprintf(fp, " %-7llu %-7llu %-7llu %-7llu", 364 (unsigned long long)s->tx_aborted_errors, 365 (unsigned long long)s->tx_fifo_errors, 366 (unsigned long long)s->tx_window_errors, 367 (unsigned long long)s->tx_heartbeat_errors); 368 } 369 } 370 if (do_link && !tb[IFLA_STATS64] && tb[IFLA_STATS] && show_stats) { 371 struct rtnl_link_stats slocal; 372 struct rtnl_link_stats *s = RTA_DATA(tb[IFLA_STATS]); 373 if (((unsigned long)s) & (sizeof(unsigned long)-1)) { 374 memcpy(&slocal, s, sizeof(slocal)); 375 s = &slocal; 376 } 377 fprintf(fp, "%s", _SL_); 378 fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s", 379 s->rx_compressed ? "compressed" : "", _SL_); 380 fprintf(fp, " %-10u %-8u %-7u %-7u %-7u %-7u", 381 s->rx_bytes, s->rx_packets, s->rx_errors, 382 s->rx_dropped, s->rx_over_errors, 383 s->multicast 384 ); 385 if (s->rx_compressed) 386 fprintf(fp, " %-7u", s->rx_compressed); 387 if (show_stats > 1) { 388 fprintf(fp, "%s", _SL_); 389 fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_); 390 fprintf(fp, " %-7u %-7u %-7u %-7u %-7u", 391 s->rx_length_errors, 392 s->rx_crc_errors, 393 s->rx_frame_errors, 394 s->rx_fifo_errors, 395 s->rx_missed_errors 396 ); 397 } 398 fprintf(fp, "%s", _SL_); 399 fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s", 400 s->tx_compressed ? "compressed" : "", _SL_); 401 fprintf(fp, " %-10u %-8u %-7u %-7u %-7u %-7u", 402 s->tx_bytes, s->tx_packets, s->tx_errors, 403 s->tx_dropped, s->tx_carrier_errors, s->collisions); 404 if (s->tx_compressed) 405 fprintf(fp, " %-7u", s->tx_compressed); 406 if (show_stats > 1) { 407 fprintf(fp, "%s", _SL_); 408 fprintf(fp, " TX errors: aborted fifo window heartbeat%s", _SL_); 409 fprintf(fp, " %-7u %-7u %-7u %-7u", 410 s->tx_aborted_errors, 411 s->tx_fifo_errors, 412 s->tx_window_errors, 413 s->tx_heartbeat_errors 414 ); 415 } 416 } 417 if (do_link && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) { 418 struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST]; 419 int rem = RTA_PAYLOAD(vflist); 420 for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) 421 print_vfinfo(fp, i); 422 } 423 424 fprintf(fp, "\n"); 425 fflush(fp); 426 return 0; 427 } 428 429 static int flush_update(void) 430 { 431 if (rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) { 432 perror("Failed to send flush request"); 433 return -1; 434 } 435 filter.flushp = 0; 436 return 0; 437 } 438 439 static int set_lifetime(unsigned int *lifetime, char *argv) 440 { 441 if (strcmp(argv, "forever") == 0) 442 *lifetime = INFINITY_LIFE_TIME; 443 else if (get_u32(lifetime, argv, 0)) 444 return -1; 445 446 return 0; 447 } 448 449 int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, 450 void *arg) 451 { 452 FILE *fp = (FILE*)arg; 453 struct ifaddrmsg *ifa = NLMSG_DATA(n); 454 int len = n->nlmsg_len; 455 int deprecated = 0; 456 struct rtattr * rta_tb[IFA_MAX+1]; 457 char abuf[256]; 458 SPRINT_BUF(b1); 459 460 if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR) 461 return 0; 462 len -= NLMSG_LENGTH(sizeof(*ifa)); 463 if (len < 0) { 464 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 465 return -1; 466 } 467 468 if (filter.flushb && n->nlmsg_type != RTM_NEWADDR) 469 return 0; 470 471 parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); 472 473 if (!rta_tb[IFA_LOCAL]) 474 rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; 475 if (!rta_tb[IFA_ADDRESS]) 476 rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL]; 477 478 if (filter.ifindex && filter.ifindex != ifa->ifa_index) 479 return 0; 480 if ((filter.scope^ifa->ifa_scope)&filter.scopemask) 481 return 0; 482 if ((filter.flags^ifa->ifa_flags)&filter.flagmask) 483 return 0; 484 if (filter.label) { 485 SPRINT_BUF(b1); 486 const char *label; 487 if (rta_tb[IFA_LABEL]) 488 label = RTA_DATA(rta_tb[IFA_LABEL]); 489 else 490 label = ll_idx_n2a(ifa->ifa_index, b1); 491 if (fnmatch(filter.label, label, 0) != 0) 492 return 0; 493 } 494 if (filter.pfx.family) { 495 if (rta_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(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL])); 500 if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) 501 return 0; 502 } 503 } 504 505 if (filter.family && filter.family != ifa->ifa_family) 506 return 0; 507 508 if (filter.flushb) { 509 struct nlmsghdr *fn; 510 if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) { 511 if (flush_update()) 512 return -1; 513 } 514 fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp)); 515 memcpy(fn, n, n->nlmsg_len); 516 fn->nlmsg_type = RTM_DELADDR; 517 fn->nlmsg_flags = NLM_F_REQUEST; 518 fn->nlmsg_seq = ++rth.seq; 519 filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; 520 filter.flushed++; 521 if (show_stats < 2) 522 return 0; 523 } 524 525 if (n->nlmsg_type == RTM_DELADDR) 526 fprintf(fp, "Deleted "); 527 528 if (filter.oneline || filter.flushb) 529 fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index)); 530 if (ifa->ifa_family == AF_INET) 531 fprintf(fp, " inet "); 532 else if (ifa->ifa_family == AF_INET6) 533 fprintf(fp, " inet6 "); 534 else if (ifa->ifa_family == AF_DECnet) 535 fprintf(fp, " dnet "); 536 else if (ifa->ifa_family == AF_IPX) 537 fprintf(fp, " ipx "); 538 else 539 fprintf(fp, " family %d ", ifa->ifa_family); 540 541 if (rta_tb[IFA_LOCAL]) { 542 fprintf(fp, "%s", rt_addr_n2a(ifa->ifa_family, 543 RTA_PAYLOAD(rta_tb[IFA_LOCAL]), 544 RTA_DATA(rta_tb[IFA_LOCAL]), 545 abuf, sizeof(abuf))); 546 547 if (rta_tb[IFA_ADDRESS] == NULL || 548 memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) { 549 fprintf(fp, "/%d ", ifa->ifa_prefixlen); 550 } else { 551 fprintf(fp, " peer %s/%d ", 552 rt_addr_n2a(ifa->ifa_family, 553 RTA_PAYLOAD(rta_tb[IFA_ADDRESS]), 554 RTA_DATA(rta_tb[IFA_ADDRESS]), 555 abuf, sizeof(abuf)), 556 ifa->ifa_prefixlen); 557 } 558 } 559 560 if (rta_tb[IFA_BROADCAST]) { 561 fprintf(fp, "brd %s ", 562 rt_addr_n2a(ifa->ifa_family, 563 RTA_PAYLOAD(rta_tb[IFA_BROADCAST]), 564 RTA_DATA(rta_tb[IFA_BROADCAST]), 565 abuf, sizeof(abuf))); 566 } 567 if (rta_tb[IFA_ANYCAST]) { 568 fprintf(fp, "any %s ", 569 rt_addr_n2a(ifa->ifa_family, 570 RTA_PAYLOAD(rta_tb[IFA_ANYCAST]), 571 RTA_DATA(rta_tb[IFA_ANYCAST]), 572 abuf, sizeof(abuf))); 573 } 574 fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1))); 575 if (ifa->ifa_flags&IFA_F_SECONDARY) { 576 ifa->ifa_flags &= ~IFA_F_SECONDARY; 577 if (ifa->ifa_family == AF_INET6) 578 fprintf(fp, "temporary "); 579 else 580 fprintf(fp, "secondary "); 581 } 582 if (ifa->ifa_flags&IFA_F_TENTATIVE) { 583 ifa->ifa_flags &= ~IFA_F_TENTATIVE; 584 fprintf(fp, "tentative "); 585 } 586 if (ifa->ifa_flags&IFA_F_DEPRECATED) { 587 ifa->ifa_flags &= ~IFA_F_DEPRECATED; 588 deprecated = 1; 589 fprintf(fp, "deprecated "); 590 } 591 if (ifa->ifa_flags&IFA_F_HOMEADDRESS) { 592 ifa->ifa_flags &= ~IFA_F_HOMEADDRESS; 593 fprintf(fp, "home "); 594 } 595 if (ifa->ifa_flags&IFA_F_NODAD) { 596 ifa->ifa_flags &= ~IFA_F_NODAD; 597 fprintf(fp, "nodad "); 598 } 599 if (!(ifa->ifa_flags&IFA_F_PERMANENT)) { 600 fprintf(fp, "dynamic "); 601 } else 602 ifa->ifa_flags &= ~IFA_F_PERMANENT; 603 if (ifa->ifa_flags&IFA_F_DADFAILED) { 604 ifa->ifa_flags &= ~IFA_F_DADFAILED; 605 fprintf(fp, "dadfailed "); 606 } 607 if (ifa->ifa_flags) 608 fprintf(fp, "flags %02x ", ifa->ifa_flags); 609 if (rta_tb[IFA_LABEL]) 610 fprintf(fp, "%s", (char*)RTA_DATA(rta_tb[IFA_LABEL])); 611 if (rta_tb[IFA_CACHEINFO]) { 612 struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]); 613 char buf[128]; 614 fprintf(fp, "%s", _SL_); 615 if (ci->ifa_valid == INFINITY_LIFE_TIME) 616 sprintf(buf, "valid_lft forever"); 617 else 618 sprintf(buf, "valid_lft %usec", ci->ifa_valid); 619 if (ci->ifa_prefered == INFINITY_LIFE_TIME) 620 sprintf(buf+strlen(buf), " preferred_lft forever"); 621 else { 622 if (deprecated) 623 sprintf(buf+strlen(buf), " preferred_lft %dsec", 624 ci->ifa_prefered); 625 else 626 sprintf(buf+strlen(buf), " preferred_lft %usec", 627 ci->ifa_prefered); 628 } 629 fprintf(fp, " %s", buf); 630 } 631 fprintf(fp, "\n"); 632 fflush(fp); 633 return 0; 634 } 635 636 int print_addrinfo_primary(const struct sockaddr_nl *who, struct nlmsghdr *n, 637 void *arg) 638 { 639 struct ifaddrmsg *ifa = NLMSG_DATA(n); 640 641 if (!ifa->ifa_flags & IFA_F_SECONDARY) 642 return 0; 643 644 return print_addrinfo(who, n, arg); 645 } 646 647 int print_addrinfo_secondary(const struct sockaddr_nl *who, struct nlmsghdr *n, 648 void *arg) 649 { 650 struct ifaddrmsg *ifa = NLMSG_DATA(n); 651 652 if (ifa->ifa_flags & IFA_F_SECONDARY) 653 return 0; 654 655 return print_addrinfo(who, n, arg); 656 } 657 658 struct nlmsg_list 659 { 660 struct nlmsg_list *next; 661 struct nlmsghdr h; 662 }; 663 664 static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp) 665 { 666 for ( ;ainfo ; ainfo = ainfo->next) { 667 struct nlmsghdr *n = &ainfo->h; 668 struct ifaddrmsg *ifa = NLMSG_DATA(n); 669 670 if (n->nlmsg_type != RTM_NEWADDR) 671 continue; 672 673 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa))) 674 return -1; 675 676 if (ifa->ifa_index != ifindex || 677 (filter.family && filter.family != ifa->ifa_family)) 678 continue; 679 680 print_addrinfo(NULL, n, fp); 681 } 682 return 0; 683 } 684 685 686 static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, 687 void *arg) 688 { 689 struct nlmsg_list **linfo = (struct nlmsg_list**)arg; 690 struct nlmsg_list *h; 691 struct nlmsg_list **lp; 692 693 h = malloc(n->nlmsg_len+sizeof(void*)); 694 if (h == NULL) 695 return -1; 696 697 memcpy(&h->h, n, n->nlmsg_len); 698 h->next = NULL; 699 700 for (lp = linfo; *lp; lp = &(*lp)->next) /* NOTHING */; 701 *lp = h; 702 703 ll_remember_index(who, n, NULL); 704 return 0; 705 } 706 707 static int ipaddr_list_or_flush(int argc, char **argv, int flush) 708 { 709 struct nlmsg_list *linfo = NULL; 710 struct nlmsg_list *ainfo = NULL; 711 struct nlmsg_list *l, *n; 712 char *filter_dev = NULL; 713 int no_link = 0; 714 715 ipaddr_reset_filter(oneline); 716 filter.showqueue = 1; 717 718 if (filter.family == AF_UNSPEC) 719 filter.family = preferred_family; 720 721 if (flush) { 722 if (argc <= 0) { 723 fprintf(stderr, "Flush requires arguments.\n"); 724 return -1; 725 } 726 if (filter.family == AF_PACKET) { 727 fprintf(stderr, "Cannot flush link addresses.\n"); 728 return -1; 729 } 730 } 731 732 while (argc > 0) { 733 if (strcmp(*argv, "to") == 0) { 734 NEXT_ARG(); 735 get_prefix(&filter.pfx, *argv, filter.family); 736 if (filter.family == AF_UNSPEC) 737 filter.family = filter.pfx.family; 738 } else if (strcmp(*argv, "scope") == 0) { 739 unsigned scope = 0; 740 NEXT_ARG(); 741 filter.scopemask = -1; 742 if (rtnl_rtscope_a2n(&scope, *argv)) { 743 if (strcmp(*argv, "all") != 0) 744 invarg("invalid \"scope\"\n", *argv); 745 scope = RT_SCOPE_NOWHERE; 746 filter.scopemask = 0; 747 } 748 filter.scope = scope; 749 } else if (strcmp(*argv, "up") == 0) { 750 filter.up = 1; 751 } else if (strcmp(*argv, "dynamic") == 0) { 752 filter.flags &= ~IFA_F_PERMANENT; 753 filter.flagmask |= IFA_F_PERMANENT; 754 } else if (strcmp(*argv, "permanent") == 0) { 755 filter.flags |= IFA_F_PERMANENT; 756 filter.flagmask |= IFA_F_PERMANENT; 757 } else if (strcmp(*argv, "secondary") == 0 || 758 strcmp(*argv, "temporary") == 0) { 759 filter.flags |= IFA_F_SECONDARY; 760 filter.flagmask |= IFA_F_SECONDARY; 761 } else if (strcmp(*argv, "primary") == 0) { 762 filter.flags &= ~IFA_F_SECONDARY; 763 filter.flagmask |= IFA_F_SECONDARY; 764 } else if (strcmp(*argv, "tentative") == 0) { 765 filter.flags |= IFA_F_TENTATIVE; 766 filter.flagmask |= IFA_F_TENTATIVE; 767 } else if (strcmp(*argv, "deprecated") == 0) { 768 filter.flags |= IFA_F_DEPRECATED; 769 filter.flagmask |= IFA_F_DEPRECATED; 770 } else if (strcmp(*argv, "home") == 0) { 771 filter.flags |= IFA_F_HOMEADDRESS; 772 filter.flagmask |= IFA_F_HOMEADDRESS; 773 } else if (strcmp(*argv, "nodad") == 0) { 774 filter.flags |= IFA_F_NODAD; 775 filter.flagmask |= IFA_F_NODAD; 776 } else if (strcmp(*argv, "dadfailed") == 0) { 777 filter.flags |= IFA_F_DADFAILED; 778 filter.flagmask |= IFA_F_DADFAILED; 779 } else if (strcmp(*argv, "label") == 0) { 780 NEXT_ARG(); 781 filter.label = *argv; 782 } else { 783 if (strcmp(*argv, "dev") == 0) { 784 NEXT_ARG(); 785 } 786 if (matches(*argv, "help") == 0) 787 usage(); 788 if (filter_dev) 789 duparg2("dev", *argv); 790 filter_dev = *argv; 791 } 792 argv++; argc--; 793 } 794 795 if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) { 796 perror("Cannot send dump request"); 797 exit(1); 798 } 799 800 if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) { 801 fprintf(stderr, "Dump terminated\n"); 802 exit(1); 803 } 804 805 if (filter_dev) { 806 filter.ifindex = ll_name_to_index(filter_dev); 807 if (filter.ifindex <= 0) { 808 fprintf(stderr, "Device \"%s\" does not exist.\n", filter_dev); 809 return -1; 810 } 811 } 812 813 if (flush) { 814 int round = 0; 815 char flushb[4096-512]; 816 817 filter.flushb = flushb; 818 filter.flushp = 0; 819 filter.flushe = sizeof(flushb); 820 821 while (round < MAX_ROUNDS) { 822 const struct rtnl_dump_filter_arg a[3] = { 823 { 824 .filter = print_addrinfo_secondary, 825 .arg1 = stdout, 826 .junk = NULL, 827 .arg2 = NULL 828 }, 829 { 830 .filter = print_addrinfo_primary, 831 .arg1 = stdout, 832 .junk = NULL, 833 .arg2 = NULL 834 }, 835 { 836 .filter = NULL, 837 .arg1 = NULL, 838 .junk = NULL, 839 .arg2 = NULL 840 }, 841 }; 842 if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { 843 perror("Cannot send dump request"); 844 exit(1); 845 } 846 filter.flushed = 0; 847 if (rtnl_dump_filter_l(&rth, a) < 0) { 848 fprintf(stderr, "Flush terminated\n"); 849 exit(1); 850 } 851 if (filter.flushed == 0) { 852 if (show_stats) { 853 if (round == 0) 854 printf("Nothing to flush.\n"); 855 else 856 printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":""); 857 } 858 fflush(stdout); 859 return 0; 860 } 861 round++; 862 if (flush_update() < 0) 863 return 1; 864 865 if (show_stats) { 866 printf("\n*** Round %d, deleting %d addresses ***\n", round, filter.flushed); 867 fflush(stdout); 868 } 869 } 870 fprintf(stderr, "*** Flush remains incomplete after %d rounds. ***\n", MAX_ROUNDS); fflush(stderr); 871 return 1; 872 } 873 874 if (filter.family != AF_PACKET) { 875 if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { 876 perror("Cannot send dump request"); 877 exit(1); 878 } 879 880 if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) { 881 fprintf(stderr, "Dump terminated\n"); 882 exit(1); 883 } 884 } 885 886 887 if (filter.family && filter.family != AF_PACKET) { 888 struct nlmsg_list **lp; 889 lp=&linfo; 890 891 if (filter.oneline) 892 no_link = 1; 893 894 while ((l=*lp)!=NULL) { 895 int ok = 0; 896 struct ifinfomsg *ifi = NLMSG_DATA(&l->h); 897 struct nlmsg_list *a; 898 899 for (a=ainfo; a; a=a->next) { 900 struct nlmsghdr *n = &a->h; 901 struct ifaddrmsg *ifa = NLMSG_DATA(n); 902 903 if (ifa->ifa_index != ifi->ifi_index || 904 (filter.family && filter.family != ifa->ifa_family)) 905 continue; 906 if ((filter.scope^ifa->ifa_scope)&filter.scopemask) 907 continue; 908 if ((filter.flags^ifa->ifa_flags)&filter.flagmask) 909 continue; 910 if (filter.pfx.family || filter.label) { 911 struct rtattr *tb[IFA_MAX+1]; 912 parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); 913 if (!tb[IFA_LOCAL]) 914 tb[IFA_LOCAL] = tb[IFA_ADDRESS]; 915 916 if (filter.pfx.family && tb[IFA_LOCAL]) { 917 inet_prefix dst; 918 memset(&dst, 0, sizeof(dst)); 919 dst.family = ifa->ifa_family; 920 memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL])); 921 if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) 922 continue; 923 } 924 if (filter.label) { 925 SPRINT_BUF(b1); 926 const char *label; 927 if (tb[IFA_LABEL]) 928 label = RTA_DATA(tb[IFA_LABEL]); 929 else 930 label = ll_idx_n2a(ifa->ifa_index, b1); 931 if (fnmatch(filter.label, label, 0) != 0) 932 continue; 933 } 934 } 935 936 ok = 1; 937 break; 938 } 939 if (!ok) 940 *lp = l->next; 941 else 942 lp = &l->next; 943 } 944 } 945 946 for (l=linfo; l; l = n) { 947 n = l->next; 948 if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) { 949 struct ifinfomsg *ifi = NLMSG_DATA(&l->h); 950 if (filter.family != AF_PACKET) 951 print_selected_addrinfo(ifi->ifi_index, ainfo, stdout); 952 } 953 fflush(stdout); 954 free(l); 955 } 956 957 return 0; 958 } 959 960 int ipaddr_list_link(int argc, char **argv) 961 { 962 preferred_family = AF_PACKET; 963 do_link = 1; 964 return ipaddr_list_or_flush(argc, argv, 0); 965 } 966 967 void ipaddr_reset_filter(int oneline) 968 { 969 memset(&filter, 0, sizeof(filter)); 970 filter.oneline = oneline; 971 } 972 973 static int default_scope(inet_prefix *lcl) 974 { 975 if (lcl->family == AF_INET) { 976 if (lcl->bytelen >= 1 && *(__u8*)&lcl->data == 127) 977 return RT_SCOPE_HOST; 978 } 979 return 0; 980 } 981 982 static int ipaddr_modify(int cmd, int flags, int argc, char **argv) 983 { 984 struct { 985 struct nlmsghdr n; 986 struct ifaddrmsg ifa; 987 char buf[256]; 988 } req; 989 char *d = NULL; 990 char *l = NULL; 991 char *lcl_arg = NULL; 992 char *valid_lftp = NULL; 993 char *preferred_lftp = NULL; 994 inet_prefix lcl; 995 inet_prefix peer; 996 int local_len = 0; 997 int peer_len = 0; 998 int brd_len = 0; 999 int any_len = 0; 1000 int scoped = 0; 1001 __u32 preferred_lft = INFINITY_LIFE_TIME; 1002 __u32 valid_lft = INFINITY_LIFE_TIME; 1003 struct ifa_cacheinfo cinfo; 1004 1005 memset(&req, 0, sizeof(req)); 1006 1007 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); 1008 req.n.nlmsg_flags = NLM_F_REQUEST | flags; 1009 req.n.nlmsg_type = cmd; 1010 req.ifa.ifa_family = preferred_family; 1011 1012 while (argc > 0) { 1013 if (strcmp(*argv, "peer") == 0 || 1014 strcmp(*argv, "remote") == 0) { 1015 NEXT_ARG(); 1016 1017 if (peer_len) 1018 duparg("peer", *argv); 1019 get_prefix(&peer, *argv, req.ifa.ifa_family); 1020 peer_len = peer.bytelen; 1021 if (req.ifa.ifa_family == AF_UNSPEC) 1022 req.ifa.ifa_family = peer.family; 1023 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen); 1024 req.ifa.ifa_prefixlen = peer.bitlen; 1025 } else if (matches(*argv, "broadcast") == 0 || 1026 strcmp(*argv, "brd") == 0) { 1027 inet_prefix addr; 1028 NEXT_ARG(); 1029 if (brd_len) 1030 duparg("broadcast", *argv); 1031 if (strcmp(*argv, "+") == 0) 1032 brd_len = -1; 1033 else if (strcmp(*argv, "-") == 0) 1034 brd_len = -2; 1035 else { 1036 get_addr(&addr, *argv, req.ifa.ifa_family); 1037 if (req.ifa.ifa_family == AF_UNSPEC) 1038 req.ifa.ifa_family = addr.family; 1039 addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen); 1040 brd_len = addr.bytelen; 1041 } 1042 } else if (strcmp(*argv, "anycast") == 0) { 1043 inet_prefix addr; 1044 NEXT_ARG(); 1045 if (any_len) 1046 duparg("anycast", *argv); 1047 get_addr(&addr, *argv, req.ifa.ifa_family); 1048 if (req.ifa.ifa_family == AF_UNSPEC) 1049 req.ifa.ifa_family = addr.family; 1050 addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen); 1051 any_len = addr.bytelen; 1052 } else if (strcmp(*argv, "scope") == 0) { 1053 unsigned scope = 0; 1054 NEXT_ARG(); 1055 if (rtnl_rtscope_a2n(&scope, *argv)) 1056 invarg(*argv, "invalid scope value."); 1057 req.ifa.ifa_scope = scope; 1058 scoped = 1; 1059 } else if (strcmp(*argv, "dev") == 0) { 1060 NEXT_ARG(); 1061 d = *argv; 1062 } else if (strcmp(*argv, "label") == 0) { 1063 NEXT_ARG(); 1064 l = *argv; 1065 addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1); 1066 } else if (matches(*argv, "valid_lft") == 0) { 1067 if (valid_lftp) 1068 duparg("valid_lft", *argv); 1069 NEXT_ARG(); 1070 valid_lftp = *argv; 1071 if (set_lifetime(&valid_lft, *argv)) 1072 invarg("valid_lft value", *argv); 1073 } else if (matches(*argv, "preferred_lft") == 0) { 1074 if (preferred_lftp) 1075 duparg("preferred_lft", *argv); 1076 NEXT_ARG(); 1077 preferred_lftp = *argv; 1078 if (set_lifetime(&preferred_lft, *argv)) 1079 invarg("preferred_lft value", *argv); 1080 } else if (strcmp(*argv, "home") == 0) { 1081 req.ifa.ifa_flags |= IFA_F_HOMEADDRESS; 1082 } else if (strcmp(*argv, "nodad") == 0) { 1083 req.ifa.ifa_flags |= IFA_F_NODAD; 1084 } else { 1085 if (strcmp(*argv, "local") == 0) { 1086 NEXT_ARG(); 1087 } 1088 if (matches(*argv, "help") == 0) 1089 usage(); 1090 if (local_len) 1091 duparg2("local", *argv); 1092 lcl_arg = *argv; 1093 get_prefix(&lcl, *argv, req.ifa.ifa_family); 1094 if (req.ifa.ifa_family == AF_UNSPEC) 1095 req.ifa.ifa_family = lcl.family; 1096 addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen); 1097 local_len = lcl.bytelen; 1098 } 1099 argc--; argv++; 1100 } 1101 if (d == NULL) { 1102 fprintf(stderr, "Not enough information: \"dev\" argument is required.\n"); 1103 return -1; 1104 } 1105 if (l && matches(d, l) != 0) { 1106 fprintf(stderr, "\"dev\" (%s) must match \"label\" (%s).\n", d, l); 1107 return -1; 1108 } 1109 1110 if (peer_len == 0 && local_len) { 1111 if (cmd == RTM_DELADDR && lcl.family == AF_INET && !(lcl.flags & PREFIXLEN_SPECIFIED)) { 1112 fprintf(stderr, 1113 "Warning: Executing wildcard deletion to stay compatible with old scripts.\n" \ 1114 " Explicitly specify the prefix length (%s/%d) to avoid this warning.\n" \ 1115 " This special behaviour is likely to disappear in further releases,\n" \ 1116 " fix your scripts!\n", lcl_arg, local_len*8); 1117 } else { 1118 peer = lcl; 1119 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen); 1120 } 1121 } 1122 if (req.ifa.ifa_prefixlen == 0) 1123 req.ifa.ifa_prefixlen = lcl.bitlen; 1124 1125 if (brd_len < 0 && cmd != RTM_DELADDR) { 1126 inet_prefix brd; 1127 int i; 1128 if (req.ifa.ifa_family != AF_INET) { 1129 fprintf(stderr, "Broadcast can be set only for IPv4 addresses\n"); 1130 return -1; 1131 } 1132 brd = peer; 1133 if (brd.bitlen <= 30) { 1134 for (i=31; i>=brd.bitlen; i--) { 1135 if (brd_len == -1) 1136 brd.data[0] |= htonl(1<<(31-i)); 1137 else 1138 brd.data[0] &= ~htonl(1<<(31-i)); 1139 } 1140 addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen); 1141 brd_len = brd.bytelen; 1142 } 1143 } 1144 if (!scoped && cmd != RTM_DELADDR) 1145 req.ifa.ifa_scope = default_scope(&lcl); 1146 1147 ll_init_map(&rth); 1148 1149 if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) { 1150 fprintf(stderr, "Cannot find device \"%s\"\n", d); 1151 return -1; 1152 } 1153 1154 if (valid_lftp || preferred_lftp) { 1155 if (!valid_lft) { 1156 fprintf(stderr, "valid_lft is zero\n"); 1157 return -1; 1158 } 1159 if (valid_lft < preferred_lft) { 1160 fprintf(stderr, "preferred_lft is greater than valid_lft\n"); 1161 return -1; 1162 } 1163 1164 memset(&cinfo, 0, sizeof(cinfo)); 1165 cinfo.ifa_prefered = preferred_lft; 1166 cinfo.ifa_valid = valid_lft; 1167 addattr_l(&req.n, sizeof(req), IFA_CACHEINFO, &cinfo, 1168 sizeof(cinfo)); 1169 } 1170 1171 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) 1172 return -2; 1173 1174 return 0; 1175 } 1176 1177 int do_ipaddr(int argc, char **argv) 1178 { 1179 if (argc < 1) 1180 return ipaddr_list_or_flush(0, NULL, 0); 1181 if (matches(*argv, "add") == 0) 1182 return ipaddr_modify(RTM_NEWADDR, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1); 1183 if (matches(*argv, "change") == 0 || 1184 strcmp(*argv, "chg") == 0) 1185 return ipaddr_modify(RTM_NEWADDR, NLM_F_REPLACE, argc-1, argv+1); 1186 if (matches(*argv, "replace") == 0) 1187 return ipaddr_modify(RTM_NEWADDR, NLM_F_CREATE|NLM_F_REPLACE, argc-1, argv+1); 1188 if (matches(*argv, "delete") == 0) 1189 return ipaddr_modify(RTM_DELADDR, 0, argc-1, argv+1); 1190 if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0 1191 || matches(*argv, "lst") == 0) 1192 return ipaddr_list_or_flush(argc-1, argv+1, 0); 1193 if (matches(*argv, "flush") == 0) 1194 return ipaddr_list_or_flush(argc-1, argv+1, 1); 1195 if (matches(*argv, "help") == 0) 1196 usage(); 1197 fprintf(stderr, "Command \"%s\" is unknown, try \"ip addr help\".\n", *argv); 1198 exit(-1); 1199 } 1200 1201