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