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