1 /* 2 * iproute.c "ip route". 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 <string.h> 19 #include <time.h> 20 #include <sys/time.h> 21 #include <sys/socket.h> 22 #include <netinet/in.h> 23 #include <netinet/ip.h> 24 #include <arpa/inet.h> 25 #include <linux/in_route.h> 26 #include <linux/icmpv6.h> 27 #include <errno.h> 28 29 #include "rt_names.h" 30 #include "utils.h" 31 #include "ip_common.h" 32 #include "iproute_lwtunnel.h" 33 34 #ifndef RTAX_RTTVAR 35 #define RTAX_RTTVAR RTAX_HOPS 36 #endif 37 38 enum list_action { 39 IPROUTE_LIST, 40 IPROUTE_FLUSH, 41 IPROUTE_SAVE, 42 }; 43 static const char *mx_names[RTAX_MAX+1] = { 44 [RTAX_MTU] = "mtu", 45 [RTAX_WINDOW] = "window", 46 [RTAX_RTT] = "rtt", 47 [RTAX_RTTVAR] = "rttvar", 48 [RTAX_SSTHRESH] = "ssthresh", 49 [RTAX_CWND] = "cwnd", 50 [RTAX_ADVMSS] = "advmss", 51 [RTAX_REORDERING]="reordering", 52 [RTAX_HOPLIMIT] = "hoplimit", 53 [RTAX_INITCWND] = "initcwnd", 54 [RTAX_FEATURES] = "features", 55 [RTAX_RTO_MIN] = "rto_min", 56 [RTAX_INITRWND] = "initrwnd", 57 [RTAX_QUICKACK] = "quickack", 58 [RTAX_CC_ALGO] = "congctl", 59 }; 60 static void usage(void) __attribute__((noreturn)); 61 62 static void usage(void) 63 { 64 fprintf(stderr, "Usage: ip route { list | flush } SELECTOR\n"); 65 fprintf(stderr, " ip route save SELECTOR\n"); 66 fprintf(stderr, " ip route restore\n"); 67 fprintf(stderr, " ip route showdump\n"); 68 fprintf(stderr, " ip route get ADDRESS [ from ADDRESS iif STRING ]\n"); 69 fprintf(stderr, " [ oif STRING ] [ tos TOS ]\n"); 70 fprintf(stderr, " [ mark NUMBER ] [ uid NUMBER ]\n"); 71 fprintf(stderr, " ip route { add | del | change | append | replace } ROUTE\n"); 72 fprintf(stderr, "SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]\n"); 73 fprintf(stderr, " [ table TABLE_ID ] [ proto RTPROTO ]\n"); 74 fprintf(stderr, " [ type TYPE ] [ scope SCOPE ]\n"); 75 fprintf(stderr, "ROUTE := NODE_SPEC [ INFO_SPEC ]\n"); 76 fprintf(stderr, "NODE_SPEC := [ TYPE ] PREFIX [ tos TOS ]\n"); 77 fprintf(stderr, " [ table TABLE_ID ] [ proto RTPROTO ]\n"); 78 fprintf(stderr, " [ scope SCOPE ] [ metric METRIC ]\n"); 79 fprintf(stderr, "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n"); 80 fprintf(stderr, "NH := [ encap ENCAPTYPE ENCAPHDR ] [ via [ FAMILY ] ADDRESS ]\n"); 81 fprintf(stderr, " [ dev STRING ] [ weight NUMBER ] NHFLAGS\n"); 82 fprintf(stderr, "FAMILY := [ inet | inet6 | ipx | dnet | mpls | bridge | link ]\n"); 83 fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]\n"); 84 fprintf(stderr, " [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n"); 85 fprintf(stderr, " [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n"); 86 fprintf(stderr, " [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n"); 87 fprintf(stderr, " [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n"); 88 fprintf(stderr, " [ features FEATURES ] [ quickack BOOL ] [ congctl NAME ]\n"); 89 fprintf(stderr, " [ pref PREF ] [ expires TIME ]\n"); 90 fprintf(stderr, "TYPE := [ unicast | local | broadcast | multicast | throw |\n"); 91 fprintf(stderr, " unreachable | prohibit | blackhole | nat ]\n"); 92 fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n"); 93 fprintf(stderr, "SCOPE := [ host | link | global | NUMBER ]\n"); 94 fprintf(stderr, "NHFLAGS := [ onlink | pervasive ]\n"); 95 fprintf(stderr, "RTPROTO := [ kernel | boot | static | NUMBER ]\n"); 96 fprintf(stderr, "PREF := [ low | medium | high ]\n"); 97 fprintf(stderr, "TIME := NUMBER[s|ms]\n"); 98 fprintf(stderr, "BOOL := [1|0]\n"); 99 fprintf(stderr, "FEATURES := ecn\n"); 100 fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 ]\n"); 101 fprintf(stderr, "ENCAPHDR := [ MPLSLABEL ]\n"); 102 exit(-1); 103 } 104 105 106 static struct 107 { 108 unsigned int tb; 109 int cloned; 110 int flushed; 111 char *flushb; 112 int flushp; 113 int flushe; 114 int protocol, protocolmask; 115 int scope, scopemask; 116 int type, typemask; 117 int tos, tosmask; 118 int iif, iifmask; 119 int oif, oifmask; 120 int mark, markmask; 121 int realm, realmmask; 122 inet_prefix rprefsrc; 123 inet_prefix rvia; 124 inet_prefix rdst; 125 inet_prefix mdst; 126 inet_prefix rsrc; 127 inet_prefix msrc; 128 } filter; 129 130 static int flush_update(void) 131 { 132 if (rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) { 133 perror("Failed to send flush request"); 134 return -1; 135 } 136 filter.flushp = 0; 137 return 0; 138 } 139 140 static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) 141 { 142 struct rtmsg *r = NLMSG_DATA(n); 143 inet_prefix dst; 144 inet_prefix src; 145 inet_prefix via; 146 inet_prefix prefsrc; 147 __u32 table; 148 static int ip6_multiple_tables; 149 150 table = rtm_get_table(r, tb); 151 152 if (preferred_family != AF_UNSPEC && r->rtm_family != preferred_family) 153 return 0; 154 155 if (r->rtm_family == AF_INET6 && table != RT_TABLE_MAIN) 156 ip6_multiple_tables = 1; 157 158 if (filter.cloned == !(r->rtm_flags&RTM_F_CLONED)) 159 return 0; 160 161 if (r->rtm_family == AF_INET6 && !ip6_multiple_tables) { 162 if (filter.tb) { 163 if (filter.tb == RT_TABLE_LOCAL) { 164 if (r->rtm_type != RTN_LOCAL) 165 return 0; 166 } else if (filter.tb == RT_TABLE_MAIN) { 167 if (r->rtm_type == RTN_LOCAL) 168 return 0; 169 } else { 170 return 0; 171 } 172 } 173 } else { 174 if (filter.tb > 0 && filter.tb != table) 175 return 0; 176 } 177 if ((filter.protocol^r->rtm_protocol)&filter.protocolmask) 178 return 0; 179 if ((filter.scope^r->rtm_scope)&filter.scopemask) 180 return 0; 181 if ((filter.type^r->rtm_type)&filter.typemask) 182 return 0; 183 if ((filter.tos^r->rtm_tos)&filter.tosmask) 184 return 0; 185 if (filter.rdst.family && 186 (r->rtm_family != filter.rdst.family || filter.rdst.bitlen > r->rtm_dst_len)) 187 return 0; 188 if (filter.mdst.family && 189 (r->rtm_family != filter.mdst.family || 190 (filter.mdst.bitlen >= 0 && filter.mdst.bitlen < r->rtm_dst_len))) 191 return 0; 192 if (filter.rsrc.family && 193 (r->rtm_family != filter.rsrc.family || filter.rsrc.bitlen > r->rtm_src_len)) 194 return 0; 195 if (filter.msrc.family && 196 (r->rtm_family != filter.msrc.family || 197 (filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len))) 198 return 0; 199 if (filter.rvia.family) { 200 int family = r->rtm_family; 201 if (tb[RTA_VIA]) { 202 struct rtvia *via = RTA_DATA(tb[RTA_VIA]); 203 family = via->rtvia_family; 204 } 205 if (family != filter.rvia.family) 206 return 0; 207 } 208 if (filter.rprefsrc.family && r->rtm_family != filter.rprefsrc.family) 209 return 0; 210 211 memset(&dst, 0, sizeof(dst)); 212 dst.family = r->rtm_family; 213 if (tb[RTA_DST]) 214 memcpy(&dst.data, RTA_DATA(tb[RTA_DST]), (r->rtm_dst_len+7)/8); 215 if (filter.rsrc.family || filter.msrc.family) { 216 memset(&src, 0, sizeof(src)); 217 src.family = r->rtm_family; 218 if (tb[RTA_SRC]) 219 memcpy(&src.data, RTA_DATA(tb[RTA_SRC]), (r->rtm_src_len+7)/8); 220 } 221 if (filter.rvia.bitlen>0) { 222 memset(&via, 0, sizeof(via)); 223 via.family = r->rtm_family; 224 if (tb[RTA_GATEWAY]) 225 memcpy(&via.data, RTA_DATA(tb[RTA_GATEWAY]), host_len/8); 226 if (tb[RTA_VIA]) { 227 size_t len = RTA_PAYLOAD(tb[RTA_VIA]) - 2; 228 struct rtvia *rtvia = RTA_DATA(tb[RTA_VIA]); 229 via.family = rtvia->rtvia_family; 230 memcpy(&via.data, rtvia->rtvia_addr, len); 231 } 232 } 233 if (filter.rprefsrc.bitlen>0) { 234 memset(&prefsrc, 0, sizeof(prefsrc)); 235 prefsrc.family = r->rtm_family; 236 if (tb[RTA_PREFSRC]) 237 memcpy(&prefsrc.data, RTA_DATA(tb[RTA_PREFSRC]), host_len/8); 238 } 239 240 if (filter.rdst.family && inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen)) 241 return 0; 242 if (filter.mdst.family && filter.mdst.bitlen >= 0 && 243 inet_addr_match(&dst, &filter.mdst, r->rtm_dst_len)) 244 return 0; 245 246 if (filter.rsrc.family && inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen)) 247 return 0; 248 if (filter.msrc.family && filter.msrc.bitlen >= 0 && 249 inet_addr_match(&src, &filter.msrc, r->rtm_src_len)) 250 return 0; 251 252 if (filter.rvia.family && inet_addr_match(&via, &filter.rvia, filter.rvia.bitlen)) 253 return 0; 254 if (filter.rprefsrc.family && inet_addr_match(&prefsrc, &filter.rprefsrc, filter.rprefsrc.bitlen)) 255 return 0; 256 if (filter.realmmask) { 257 __u32 realms = 0; 258 if (tb[RTA_FLOW]) 259 realms = rta_getattr_u32(tb[RTA_FLOW]); 260 if ((realms^filter.realm)&filter.realmmask) 261 return 0; 262 } 263 if (filter.iifmask) { 264 int iif = 0; 265 if (tb[RTA_IIF]) 266 iif = *(int*)RTA_DATA(tb[RTA_IIF]); 267 if ((iif^filter.iif)&filter.iifmask) 268 return 0; 269 } 270 if (filter.oifmask) { 271 int oif = 0; 272 if (tb[RTA_OIF]) 273 oif = *(int*)RTA_DATA(tb[RTA_OIF]); 274 if ((oif^filter.oif)&filter.oifmask) 275 return 0; 276 } 277 if (filter.markmask) { 278 int mark = 0; 279 if (tb[RTA_MARK]) 280 mark = *(int *)RTA_DATA(tb[RTA_MARK]); 281 if ((mark ^ filter.mark) & filter.markmask) 282 return 0; 283 } 284 if (filter.flushb && 285 r->rtm_family == AF_INET6 && 286 r->rtm_dst_len == 0 && 287 r->rtm_type == RTN_UNREACHABLE && 288 tb[RTA_PRIORITY] && 289 *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1) 290 return 0; 291 292 return 1; 293 } 294 295 static void print_rtax_features(FILE *fp, unsigned int features) 296 { 297 unsigned int of = features; 298 299 if (features & RTAX_FEATURE_ECN) { 300 fprintf(fp, " ecn"); 301 features &= ~RTAX_FEATURE_ECN; 302 } 303 304 if (features) 305 fprintf(fp, " 0x%x", of); 306 } 307 308 int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) 309 { 310 FILE *fp = (FILE*)arg; 311 struct rtmsg *r = NLMSG_DATA(n); 312 int len = n->nlmsg_len; 313 struct rtattr * tb[RTA_MAX+1]; 314 char abuf[256]; 315 int host_len; 316 __u32 table; 317 SPRINT_BUF(b1); 318 static int hz; 319 320 if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) { 321 fprintf(stderr, "Not a route: %08x %08x %08x\n", 322 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 323 return 0; 324 } 325 if (filter.flushb && n->nlmsg_type != RTM_NEWROUTE) 326 return 0; 327 len -= NLMSG_LENGTH(sizeof(*r)); 328 if (len < 0) { 329 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); 330 return -1; 331 } 332 333 host_len = af_bit_len(r->rtm_family); 334 335 parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); 336 table = rtm_get_table(r, tb); 337 338 if (!filter_nlmsg(n, tb, host_len)) 339 return 0; 340 341 if (filter.flushb) { 342 struct nlmsghdr *fn; 343 if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) { 344 if (flush_update()) 345 return -1; 346 } 347 fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp)); 348 memcpy(fn, n, n->nlmsg_len); 349 fn->nlmsg_type = RTM_DELROUTE; 350 fn->nlmsg_flags = NLM_F_REQUEST; 351 fn->nlmsg_seq = ++rth.seq; 352 filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; 353 filter.flushed++; 354 if (show_stats < 2) 355 return 0; 356 } 357 358 if (n->nlmsg_type == RTM_DELROUTE) 359 fprintf(fp, "Deleted "); 360 if ((r->rtm_type != RTN_UNICAST || show_details > 0) && !filter.type) 361 fprintf(fp, "%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); 362 363 if (tb[RTA_DST]) { 364 if (r->rtm_dst_len != host_len) { 365 fprintf(fp, "%s/%u ", rt_addr_n2a(r->rtm_family, 366 RTA_PAYLOAD(tb[RTA_DST]), 367 RTA_DATA(tb[RTA_DST]), 368 abuf, sizeof(abuf)), 369 r->rtm_dst_len 370 ); 371 } else { 372 fprintf(fp, "%s ", format_host(r->rtm_family, 373 RTA_PAYLOAD(tb[RTA_DST]), 374 RTA_DATA(tb[RTA_DST]), 375 abuf, sizeof(abuf)) 376 ); 377 } 378 } else if (r->rtm_dst_len) { 379 fprintf(fp, "0/%d ", r->rtm_dst_len); 380 } else { 381 fprintf(fp, "default "); 382 } 383 if (tb[RTA_SRC]) { 384 if (r->rtm_src_len != host_len) { 385 fprintf(fp, "from %s/%u ", rt_addr_n2a(r->rtm_family, 386 RTA_PAYLOAD(tb[RTA_SRC]), 387 RTA_DATA(tb[RTA_SRC]), 388 abuf, sizeof(abuf)), 389 r->rtm_src_len 390 ); 391 } else { 392 fprintf(fp, "from %s ", format_host(r->rtm_family, 393 RTA_PAYLOAD(tb[RTA_SRC]), 394 RTA_DATA(tb[RTA_SRC]), 395 abuf, sizeof(abuf)) 396 ); 397 } 398 } else if (r->rtm_src_len) { 399 fprintf(fp, "from 0/%u ", r->rtm_src_len); 400 } 401 if (tb[RTA_NEWDST]) { 402 fprintf(fp, "as to %s ", format_host(r->rtm_family, 403 RTA_PAYLOAD(tb[RTA_NEWDST]), 404 RTA_DATA(tb[RTA_NEWDST]), 405 abuf, sizeof(abuf)) 406 ); 407 } 408 409 if (tb[RTA_ENCAP]) 410 lwt_print_encap(fp, tb[RTA_ENCAP_TYPE], tb[RTA_ENCAP]); 411 412 if (r->rtm_tos && filter.tosmask != -1) { 413 SPRINT_BUF(b1); 414 fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1))); 415 } 416 417 if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len) { 418 fprintf(fp, "via %s ", 419 format_host(r->rtm_family, 420 RTA_PAYLOAD(tb[RTA_GATEWAY]), 421 RTA_DATA(tb[RTA_GATEWAY]), 422 abuf, sizeof(abuf))); 423 } 424 if (tb[RTA_VIA]) { 425 size_t len = RTA_PAYLOAD(tb[RTA_VIA]) - 2; 426 struct rtvia *via = RTA_DATA(tb[RTA_VIA]); 427 fprintf(fp, "via %s %s ", 428 family_name(via->rtvia_family), 429 format_host(via->rtvia_family, len, via->rtvia_addr, 430 abuf, sizeof(abuf))); 431 } 432 if (tb[RTA_OIF] && filter.oifmask != -1) 433 fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF]))); 434 435 if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb) 436 fprintf(fp, " table %s ", rtnl_rttable_n2a(table, b1, sizeof(b1))); 437 if (!(r->rtm_flags&RTM_F_CLONED)) { 438 if ((r->rtm_protocol != RTPROT_BOOT || show_details > 0) && filter.protocolmask != -1) 439 fprintf(fp, " proto %s ", rtnl_rtprot_n2a(r->rtm_protocol, b1, sizeof(b1))); 440 if ((r->rtm_scope != RT_SCOPE_UNIVERSE || show_details > 0) && filter.scopemask != -1) 441 fprintf(fp, " scope %s ", rtnl_rtscope_n2a(r->rtm_scope, b1, sizeof(b1))); 442 } 443 if (tb[RTA_PREFSRC] && filter.rprefsrc.bitlen != host_len) { 444 /* Do not use format_host(). It is our local addr 445 and symbolic name will not be useful. 446 */ 447 fprintf(fp, " src %s ", 448 rt_addr_n2a(r->rtm_family, 449 RTA_PAYLOAD(tb[RTA_PREFSRC]), 450 RTA_DATA(tb[RTA_PREFSRC]), 451 abuf, sizeof(abuf))); 452 } 453 if (tb[RTA_PRIORITY]) 454 fprintf(fp, " metric %u ", rta_getattr_u32(tb[RTA_PRIORITY])); 455 if (r->rtm_flags & RTNH_F_DEAD) 456 fprintf(fp, "dead "); 457 if (r->rtm_flags & RTNH_F_ONLINK) 458 fprintf(fp, "onlink "); 459 if (r->rtm_flags & RTNH_F_PERVASIVE) 460 fprintf(fp, "pervasive "); 461 if (r->rtm_flags & RTNH_F_OFFLOAD) 462 fprintf(fp, "offload "); 463 if (r->rtm_flags & RTM_F_NOTIFY) 464 fprintf(fp, "notify "); 465 if (r->rtm_flags & RTNH_F_LINKDOWN) 466 fprintf(fp, "linkdown "); 467 if (tb[RTA_MARK]) { 468 unsigned int mark = *(unsigned int*)RTA_DATA(tb[RTA_MARK]); 469 if (mark) { 470 if (mark >= 16) 471 fprintf(fp, " mark 0x%x", mark); 472 else 473 fprintf(fp, " mark %u", mark); 474 } 475 } 476 477 if (tb[RTA_FLOW] && filter.realmmask != ~0U) { 478 __u32 to = rta_getattr_u32(tb[RTA_FLOW]); 479 __u32 from = to>>16; 480 to &= 0xFFFF; 481 fprintf(fp, "realm%s ", from ? "s" : ""); 482 if (from) { 483 fprintf(fp, "%s/", 484 rtnl_rtrealm_n2a(from, b1, sizeof(b1))); 485 } 486 fprintf(fp, "%s ", 487 rtnl_rtrealm_n2a(to, b1, sizeof(b1))); 488 } 489 490 if (tb[RTA_UID]) 491 fprintf(fp, "uid %u ", rta_getattr_u32(tb[RTA_UID])); 492 493 if ((r->rtm_flags&RTM_F_CLONED) && r->rtm_family == AF_INET) { 494 __u32 flags = r->rtm_flags&~0xFFFF; 495 int first = 1; 496 497 fprintf(fp, "%s cache ", _SL_); 498 499 #define PRTFL(fl,flname) if (flags&RTCF_##fl) { \ 500 flags &= ~RTCF_##fl; \ 501 fprintf(fp, "%s" flname "%s", first ? "<" : "", flags ? "," : "> "); \ 502 first = 0; } 503 PRTFL(LOCAL, "local"); 504 PRTFL(REJECT, "reject"); 505 PRTFL(MULTICAST, "mc"); 506 PRTFL(BROADCAST, "brd"); 507 PRTFL(DNAT, "dst-nat"); 508 PRTFL(SNAT, "src-nat"); 509 PRTFL(MASQ, "masq"); 510 PRTFL(DIRECTDST, "dst-direct"); 511 PRTFL(DIRECTSRC, "src-direct"); 512 PRTFL(REDIRECTED, "redirected"); 513 PRTFL(DOREDIRECT, "redirect"); 514 PRTFL(FAST, "fastroute"); 515 PRTFL(NOTIFY, "notify"); 516 PRTFL(TPROXY, "proxy"); 517 518 if (flags) 519 fprintf(fp, "%s%x> ", first ? "<" : "", flags); 520 if (tb[RTA_CACHEINFO]) { 521 struct rta_cacheinfo *ci = RTA_DATA(tb[RTA_CACHEINFO]); 522 if (!hz) 523 hz = get_user_hz(); 524 if (ci->rta_expires != 0) 525 fprintf(fp, " expires %dsec", ci->rta_expires/hz); 526 if (ci->rta_error != 0) 527 fprintf(fp, " error %d", ci->rta_error); 528 if (show_stats) { 529 if (ci->rta_clntref) 530 fprintf(fp, " users %d", ci->rta_clntref); 531 if (ci->rta_used != 0) 532 fprintf(fp, " used %d", ci->rta_used); 533 if (ci->rta_lastuse != 0) 534 fprintf(fp, " age %dsec", ci->rta_lastuse/hz); 535 } 536 if (ci->rta_id) 537 fprintf(fp, " ipid 0x%04x", ci->rta_id); 538 if (ci->rta_ts || ci->rta_tsage) 539 fprintf(fp, " ts 0x%x tsage %dsec", 540 ci->rta_ts, ci->rta_tsage); 541 } 542 } else if (r->rtm_family == AF_INET6) { 543 struct rta_cacheinfo *ci = NULL; 544 if (tb[RTA_CACHEINFO]) 545 ci = RTA_DATA(tb[RTA_CACHEINFO]); 546 if ((r->rtm_flags & RTM_F_CLONED) || (ci && ci->rta_expires)) { 547 if (!hz) 548 hz = get_user_hz(); 549 if (r->rtm_flags & RTM_F_CLONED) 550 fprintf(fp, "%s cache ", _SL_); 551 if (ci->rta_expires) 552 fprintf(fp, " expires %dsec", ci->rta_expires/hz); 553 if (ci->rta_error != 0) 554 fprintf(fp, " error %d", ci->rta_error); 555 if (show_stats) { 556 if (ci->rta_clntref) 557 fprintf(fp, " users %d", ci->rta_clntref); 558 if (ci->rta_used != 0) 559 fprintf(fp, " used %d", ci->rta_used); 560 if (ci->rta_lastuse != 0) 561 fprintf(fp, " age %dsec", ci->rta_lastuse/hz); 562 } 563 } else if (ci) { 564 if (ci->rta_error != 0) 565 fprintf(fp, " error %d", ci->rta_error); 566 } 567 } 568 if (tb[RTA_METRICS]) { 569 int i; 570 unsigned mxlock = 0; 571 struct rtattr *mxrta[RTAX_MAX+1]; 572 573 parse_rtattr(mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), 574 RTA_PAYLOAD(tb[RTA_METRICS])); 575 if (mxrta[RTAX_LOCK]) 576 mxlock = *(unsigned*)RTA_DATA(mxrta[RTAX_LOCK]); 577 578 for (i=2; i<= RTAX_MAX; i++) { 579 __u32 val; 580 581 if (mxrta[i] == NULL) 582 continue; 583 584 if (i != RTAX_CC_ALGO) 585 val = rta_getattr_u32(mxrta[i]); 586 587 if (i == RTAX_HOPLIMIT && (int)val == -1) 588 continue; 589 590 if (i < sizeof(mx_names)/sizeof(char*) && mx_names[i]) 591 fprintf(fp, " %s", mx_names[i]); 592 else 593 fprintf(fp, " metric %d", i); 594 595 if (mxlock & (1<<i)) 596 fprintf(fp, " lock"); 597 598 switch (i) { 599 case RTAX_FEATURES: 600 print_rtax_features(fp, val); 601 break; 602 default: 603 fprintf(fp, " %u", val); 604 break; 605 606 case RTAX_RTT: 607 case RTAX_RTTVAR: 608 case RTAX_RTO_MIN: 609 if (i == RTAX_RTT) 610 val /= 8; 611 else if (i == RTAX_RTTVAR) 612 val /= 4; 613 614 if (val >= 1000) 615 fprintf(fp, " %gs", val/1e3); 616 else 617 fprintf(fp, " %ums", val); 618 break; 619 case RTAX_CC_ALGO: 620 fprintf(fp, " %s", rta_getattr_str(mxrta[i])); 621 break; 622 } 623 } 624 } 625 if (tb[RTA_IIF] && filter.iifmask != -1) { 626 fprintf(fp, " iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF]))); 627 } 628 if (tb[RTA_MULTIPATH]) { 629 struct rtnexthop *nh = RTA_DATA(tb[RTA_MULTIPATH]); 630 int first = 0; 631 632 len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); 633 634 for (;;) { 635 if (len < sizeof(*nh)) 636 break; 637 if (nh->rtnh_len > len) 638 break; 639 if (r->rtm_flags&RTM_F_CLONED && r->rtm_type == RTN_MULTICAST) { 640 if (first) 641 fprintf(fp, " Oifs:"); 642 else 643 fprintf(fp, " "); 644 } else 645 fprintf(fp, "%s\tnexthop", _SL_); 646 if (nh->rtnh_len > sizeof(*nh)) { 647 parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh), nh->rtnh_len - sizeof(*nh)); 648 649 if (tb[RTA_ENCAP]) 650 lwt_print_encap(fp, 651 tb[RTA_ENCAP_TYPE], 652 tb[RTA_ENCAP]); 653 654 if (tb[RTA_GATEWAY]) { 655 fprintf(fp, " via %s ", 656 format_host(r->rtm_family, 657 RTA_PAYLOAD(tb[RTA_GATEWAY]), 658 RTA_DATA(tb[RTA_GATEWAY]), 659 abuf, sizeof(abuf))); 660 } 661 if (tb[RTA_VIA]) { 662 size_t len = RTA_PAYLOAD(tb[RTA_VIA]) - 2; 663 struct rtvia *via = RTA_DATA(tb[RTA_VIA]); 664 fprintf(fp, "via %s %s ", 665 family_name(via->rtvia_family), 666 format_host(via->rtvia_family, len, via->rtvia_addr, 667 abuf, sizeof(abuf))); 668 } 669 if (tb[RTA_FLOW]) { 670 __u32 to = rta_getattr_u32(tb[RTA_FLOW]); 671 __u32 from = to>>16; 672 to &= 0xFFFF; 673 fprintf(fp, " realm%s ", from ? "s" : ""); 674 if (from) { 675 fprintf(fp, "%s/", 676 rtnl_rtrealm_n2a(from, b1, sizeof(b1))); 677 } 678 fprintf(fp, "%s", 679 rtnl_rtrealm_n2a(to, b1, sizeof(b1))); 680 } 681 } 682 if (r->rtm_flags&RTM_F_CLONED && r->rtm_type == RTN_MULTICAST) { 683 fprintf(fp, " %s", ll_index_to_name(nh->rtnh_ifindex)); 684 if (nh->rtnh_hops != 1) 685 fprintf(fp, "(ttl>%d)", nh->rtnh_hops); 686 } else { 687 fprintf(fp, " dev %s", ll_index_to_name(nh->rtnh_ifindex)); 688 fprintf(fp, " weight %d", nh->rtnh_hops+1); 689 } 690 if (nh->rtnh_flags & RTNH_F_DEAD) 691 fprintf(fp, " dead"); 692 if (nh->rtnh_flags & RTNH_F_ONLINK) 693 fprintf(fp, " onlink"); 694 if (nh->rtnh_flags & RTNH_F_PERVASIVE) 695 fprintf(fp, " pervasive"); 696 if (nh->rtnh_flags & RTNH_F_LINKDOWN) 697 fprintf(fp, " linkdown"); 698 len -= NLMSG_ALIGN(nh->rtnh_len); 699 nh = RTNH_NEXT(nh); 700 } 701 } 702 if (tb[RTA_PREF]) { 703 unsigned int pref = rta_getattr_u8(tb[RTA_PREF]); 704 fprintf(fp, " pref "); 705 706 switch (pref) { 707 case ICMPV6_ROUTER_PREF_LOW: 708 fprintf(fp, "low"); 709 break; 710 case ICMPV6_ROUTER_PREF_MEDIUM: 711 fprintf(fp, "medium"); 712 break; 713 case ICMPV6_ROUTER_PREF_HIGH: 714 fprintf(fp, "high"); 715 break; 716 default: 717 fprintf(fp, "%u", pref); 718 } 719 } 720 fprintf(fp, "\n"); 721 fflush(fp); 722 return 0; 723 } 724 725 static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, 726 struct rtattr *rta, struct rtnexthop *rtnh, 727 int *argcp, char ***argvp) 728 { 729 int argc = *argcp; 730 char **argv = *argvp; 731 732 while (++argv, --argc > 0) { 733 if (strcmp(*argv, "via") == 0) { 734 inet_prefix addr; 735 int family; 736 NEXT_ARG(); 737 family = read_family(*argv); 738 if (family == AF_UNSPEC) 739 family = r->rtm_family; 740 else 741 NEXT_ARG(); 742 get_addr(&addr, *argv, family); 743 if (r->rtm_family == AF_UNSPEC) 744 r->rtm_family = addr.family; 745 if (addr.family == r->rtm_family) { 746 rta_addattr_l(rta, 4096, RTA_GATEWAY, &addr.data, addr.bytelen); 747 rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen; 748 } else { 749 rta_addattr_l(rta, 4096, RTA_VIA, &addr.family, addr.bytelen+2); 750 rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen+2; 751 } 752 } else if (strcmp(*argv, "dev") == 0) { 753 NEXT_ARG(); 754 if ((rtnh->rtnh_ifindex = ll_name_to_index(*argv)) == 0) { 755 fprintf(stderr, "Cannot find device \"%s\"\n", *argv); 756 exit(1); 757 } 758 } else if (strcmp(*argv, "weight") == 0) { 759 unsigned w; 760 NEXT_ARG(); 761 if (get_unsigned(&w, *argv, 0) || w == 0 || w > 256) 762 invarg("\"weight\" is invalid\n", *argv); 763 rtnh->rtnh_hops = w - 1; 764 } else if (strcmp(*argv, "onlink") == 0) { 765 rtnh->rtnh_flags |= RTNH_F_ONLINK; 766 } else if (matches(*argv, "realms") == 0) { 767 __u32 realm; 768 NEXT_ARG(); 769 if (get_rt_realms_or_raw(&realm, *argv)) 770 invarg("\"realm\" value is invalid\n", *argv); 771 rta_addattr32(rta, 4096, RTA_FLOW, realm); 772 rtnh->rtnh_len += sizeof(struct rtattr) + 4; 773 } else if (strcmp(*argv, "encap") == 0) { 774 int len = rta->rta_len; 775 776 lwt_parse_encap(rta, 4096, &argc, &argv); 777 rtnh->rtnh_len += rta->rta_len - len; 778 } else 779 break; 780 } 781 *argcp = argc; 782 *argvp = argv; 783 return 0; 784 } 785 786 static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, 787 int argc, char **argv) 788 { 789 char buf[1024]; 790 struct rtattr *rta = (void*)buf; 791 struct rtnexthop *rtnh; 792 793 rta->rta_type = RTA_MULTIPATH; 794 rta->rta_len = RTA_LENGTH(0); 795 rtnh = RTA_DATA(rta); 796 797 while (argc > 0) { 798 if (strcmp(*argv, "nexthop") != 0) { 799 fprintf(stderr, "Error: \"nexthop\" or end of line is expected instead of \"%s\"\n", *argv); 800 exit(-1); 801 } 802 if (argc <= 1) { 803 fprintf(stderr, "Error: unexpected end of line after \"nexthop\"\n"); 804 exit(-1); 805 } 806 memset(rtnh, 0, sizeof(*rtnh)); 807 rtnh->rtnh_len = sizeof(*rtnh); 808 rta->rta_len += rtnh->rtnh_len; 809 parse_one_nh(n, r, rta, rtnh, &argc, &argv); 810 rtnh = RTNH_NEXT(rtnh); 811 } 812 813 if (rta->rta_len > RTA_LENGTH(0)) 814 addattr_l(n, 1024, RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta)); 815 return 0; 816 } 817 818 static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) 819 { 820 struct { 821 struct nlmsghdr n; 822 struct rtmsg r; 823 char buf[1024]; 824 } req; 825 char mxbuf[256]; 826 struct rtattr * mxrta = (void*)mxbuf; 827 unsigned mxlock = 0; 828 char *d = NULL; 829 int gw_ok = 0; 830 int dst_ok = 0; 831 int nhs_ok = 0; 832 int scope_ok = 0; 833 int table_ok = 0; 834 int raw = 0; 835 int type_ok = 0; 836 static int hz; 837 838 memset(&req, 0, sizeof(req)); 839 840 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 841 req.n.nlmsg_flags = NLM_F_REQUEST|flags; 842 req.n.nlmsg_type = cmd; 843 req.r.rtm_family = preferred_family; 844 req.r.rtm_table = RT_TABLE_MAIN; 845 req.r.rtm_scope = RT_SCOPE_NOWHERE; 846 847 if (cmd != RTM_DELROUTE) { 848 req.r.rtm_protocol = RTPROT_BOOT; 849 req.r.rtm_scope = RT_SCOPE_UNIVERSE; 850 req.r.rtm_type = RTN_UNICAST; 851 } 852 853 mxrta->rta_type = RTA_METRICS; 854 mxrta->rta_len = RTA_LENGTH(0); 855 856 while (argc > 0) { 857 if (strcmp(*argv, "src") == 0) { 858 inet_prefix addr; 859 NEXT_ARG(); 860 get_addr(&addr, *argv, req.r.rtm_family); 861 if (req.r.rtm_family == AF_UNSPEC) 862 req.r.rtm_family = addr.family; 863 addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen); 864 } else if (strcmp(*argv, "as") == 0) { 865 inet_prefix addr; 866 NEXT_ARG(); 867 if (strcmp(*argv, "to") == 0) { 868 NEXT_ARG(); 869 } 870 get_addr(&addr, *argv, req.r.rtm_family); 871 if (req.r.rtm_family == AF_UNSPEC) 872 req.r.rtm_family = addr.family; 873 addattr_l(&req.n, sizeof(req), RTA_NEWDST, &addr.data, addr.bytelen); 874 } else if (strcmp(*argv, "via") == 0) { 875 inet_prefix addr; 876 int family; 877 gw_ok = 1; 878 NEXT_ARG(); 879 family = read_family(*argv); 880 if (family == AF_UNSPEC) 881 family = req.r.rtm_family; 882 else 883 NEXT_ARG(); 884 get_addr(&addr, *argv, family); 885 if (req.r.rtm_family == AF_UNSPEC) 886 req.r.rtm_family = addr.family; 887 if (addr.family == req.r.rtm_family) 888 addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen); 889 else 890 addattr_l(&req.n, sizeof(req), RTA_VIA, &addr.family, addr.bytelen+2); 891 } else if (strcmp(*argv, "from") == 0) { 892 inet_prefix addr; 893 NEXT_ARG(); 894 get_prefix(&addr, *argv, req.r.rtm_family); 895 if (req.r.rtm_family == AF_UNSPEC) 896 req.r.rtm_family = addr.family; 897 if (addr.bytelen) 898 addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen); 899 req.r.rtm_src_len = addr.bitlen; 900 } else if (strcmp(*argv, "tos") == 0 || 901 matches(*argv, "dsfield") == 0) { 902 __u32 tos; 903 NEXT_ARG(); 904 if (rtnl_dsfield_a2n(&tos, *argv)) 905 invarg("\"tos\" value is invalid\n", *argv); 906 req.r.rtm_tos = tos; 907 } else if (strcmp(*argv, "expires") == 0 ) { 908 __u32 expires; 909 NEXT_ARG(); 910 if (get_u32(&expires, *argv, 0)) 911 invarg("\"expires\" value is invalid\n", *argv); 912 if (!hz) 913 hz = get_user_hz(); 914 addattr32(&req.n, sizeof(req), RTA_EXPIRES, expires*hz); 915 } else if (matches(*argv, "metric") == 0 || 916 matches(*argv, "priority") == 0 || 917 strcmp(*argv, "preference") == 0) { 918 __u32 metric; 919 NEXT_ARG(); 920 if (get_u32(&metric, *argv, 0)) 921 invarg("\"metric\" value is invalid\n", *argv); 922 addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric); 923 } else if (strcmp(*argv, "scope") == 0) { 924 __u32 scope = 0; 925 NEXT_ARG(); 926 if (rtnl_rtscope_a2n(&scope, *argv)) 927 invarg("invalid \"scope\" value\n", *argv); 928 req.r.rtm_scope = scope; 929 scope_ok = 1; 930 } else if (strcmp(*argv, "mtu") == 0) { 931 unsigned mtu; 932 NEXT_ARG(); 933 if (strcmp(*argv, "lock") == 0) { 934 mxlock |= (1<<RTAX_MTU); 935 NEXT_ARG(); 936 } 937 if (get_unsigned(&mtu, *argv, 0)) 938 invarg("\"mtu\" value is invalid\n", *argv); 939 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu); 940 } else if (strcmp(*argv, "hoplimit") == 0) { 941 unsigned hoplimit; 942 NEXT_ARG(); 943 if (strcmp(*argv, "lock") == 0) { 944 mxlock |= (1<<RTAX_HOPLIMIT); 945 NEXT_ARG(); 946 } 947 if (get_unsigned(&hoplimit, *argv, 0) || hoplimit > 255) 948 invarg("\"hoplimit\" value is invalid\n", *argv); 949 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_HOPLIMIT, hoplimit); 950 } else if (strcmp(*argv, "advmss") == 0) { 951 unsigned mss; 952 NEXT_ARG(); 953 if (strcmp(*argv, "lock") == 0) { 954 mxlock |= (1<<RTAX_ADVMSS); 955 NEXT_ARG(); 956 } 957 if (get_unsigned(&mss, *argv, 0)) 958 invarg("\"mss\" value is invalid\n", *argv); 959 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_ADVMSS, mss); 960 } else if (matches(*argv, "reordering") == 0) { 961 unsigned reord; 962 NEXT_ARG(); 963 if (strcmp(*argv, "lock") == 0) { 964 mxlock |= (1<<RTAX_REORDERING); 965 NEXT_ARG(); 966 } 967 if (get_unsigned(&reord, *argv, 0)) 968 invarg("\"reordering\" value is invalid\n", *argv); 969 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_REORDERING, reord); 970 } else if (strcmp(*argv, "rtt") == 0) { 971 unsigned rtt; 972 NEXT_ARG(); 973 if (strcmp(*argv, "lock") == 0) { 974 mxlock |= (1<<RTAX_RTT); 975 NEXT_ARG(); 976 } 977 if (get_time_rtt(&rtt, *argv, &raw)) 978 invarg("\"rtt\" value is invalid\n", *argv); 979 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTT, 980 (raw) ? rtt : rtt * 8); 981 } else if (strcmp(*argv, "rto_min") == 0) { 982 unsigned rto_min; 983 NEXT_ARG(); 984 mxlock |= (1<<RTAX_RTO_MIN); 985 if (get_time_rtt(&rto_min, *argv, &raw)) 986 invarg("\"rto_min\" value is invalid\n", 987 *argv); 988 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTO_MIN, 989 rto_min); 990 } else if (matches(*argv, "window") == 0) { 991 unsigned win; 992 NEXT_ARG(); 993 if (strcmp(*argv, "lock") == 0) { 994 mxlock |= (1<<RTAX_WINDOW); 995 NEXT_ARG(); 996 } 997 if (get_unsigned(&win, *argv, 0)) 998 invarg("\"window\" value is invalid\n", *argv); 999 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_WINDOW, win); 1000 } else if (matches(*argv, "cwnd") == 0) { 1001 unsigned win; 1002 NEXT_ARG(); 1003 if (strcmp(*argv, "lock") == 0) { 1004 mxlock |= (1<<RTAX_CWND); 1005 NEXT_ARG(); 1006 } 1007 if (get_unsigned(&win, *argv, 0)) 1008 invarg("\"cwnd\" value is invalid\n", *argv); 1009 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_CWND, win); 1010 } else if (matches(*argv, "initcwnd") == 0) { 1011 unsigned win; 1012 NEXT_ARG(); 1013 if (strcmp(*argv, "lock") == 0) { 1014 mxlock |= (1<<RTAX_INITCWND); 1015 NEXT_ARG(); 1016 } 1017 if (get_unsigned(&win, *argv, 0)) 1018 invarg("\"initcwnd\" value is invalid\n", *argv); 1019 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITCWND, win); 1020 } else if (matches(*argv, "initrwnd") == 0) { 1021 unsigned win; 1022 NEXT_ARG(); 1023 if (strcmp(*argv, "lock") == 0) { 1024 mxlock |= (1<<RTAX_INITRWND); 1025 NEXT_ARG(); 1026 } 1027 if (get_unsigned(&win, *argv, 0)) 1028 invarg("\"initrwnd\" value is invalid\n", *argv); 1029 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITRWND, win); 1030 } else if (matches(*argv, "features") == 0) { 1031 unsigned int features = 0; 1032 1033 while (argc > 0) { 1034 NEXT_ARG(); 1035 1036 if (strcmp(*argv, "ecn") == 0) 1037 features |= RTAX_FEATURE_ECN; 1038 else 1039 invarg("\"features\" value not valid\n", *argv); 1040 break; 1041 } 1042 1043 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_FEATURES, features); 1044 } else if (matches(*argv, "quickack") == 0) { 1045 unsigned quickack; 1046 NEXT_ARG(); 1047 if (get_unsigned(&quickack, *argv, 0)) 1048 invarg("\"quickack\" value is invalid\n", *argv); 1049 if (quickack != 1 && quickack != 0) 1050 invarg("\"quickack\" value should be 0 or 1\n", *argv); 1051 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_QUICKACK, quickack); 1052 } else if (matches(*argv, "congctl") == 0) { 1053 NEXT_ARG(); 1054 if (strcmp(*argv, "lock") == 0) { 1055 mxlock |= 1 << RTAX_CC_ALGO; 1056 NEXT_ARG(); 1057 } 1058 rta_addattr_l(mxrta, sizeof(mxbuf), RTAX_CC_ALGO, *argv, 1059 strlen(*argv)); 1060 } else if (matches(*argv, "rttvar") == 0) { 1061 unsigned win; 1062 NEXT_ARG(); 1063 if (strcmp(*argv, "lock") == 0) { 1064 mxlock |= (1<<RTAX_RTTVAR); 1065 NEXT_ARG(); 1066 } 1067 if (get_time_rtt(&win, *argv, &raw)) 1068 invarg("\"rttvar\" value is invalid\n", *argv); 1069 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTTVAR, 1070 (raw) ? win : win * 4); 1071 } else if (matches(*argv, "ssthresh") == 0) { 1072 unsigned win; 1073 NEXT_ARG(); 1074 if (strcmp(*argv, "lock") == 0) { 1075 mxlock |= (1<<RTAX_SSTHRESH); 1076 NEXT_ARG(); 1077 } 1078 if (get_unsigned(&win, *argv, 0)) 1079 invarg("\"ssthresh\" value is invalid\n", *argv); 1080 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_SSTHRESH, win); 1081 } else if (matches(*argv, "realms") == 0) { 1082 __u32 realm; 1083 NEXT_ARG(); 1084 if (get_rt_realms_or_raw(&realm, *argv)) 1085 invarg("\"realm\" value is invalid\n", *argv); 1086 addattr32(&req.n, sizeof(req), RTA_FLOW, realm); 1087 } else if (strcmp(*argv, "onlink") == 0) { 1088 req.r.rtm_flags |= RTNH_F_ONLINK; 1089 } else if (strcmp(*argv, "nexthop") == 0) { 1090 nhs_ok = 1; 1091 break; 1092 } else if (matches(*argv, "protocol") == 0) { 1093 __u32 prot; 1094 NEXT_ARG(); 1095 if (rtnl_rtprot_a2n(&prot, *argv)) 1096 invarg("\"protocol\" value is invalid\n", *argv); 1097 req.r.rtm_protocol = prot; 1098 } else if (matches(*argv, "table") == 0) { 1099 __u32 tid; 1100 NEXT_ARG(); 1101 if (rtnl_rttable_a2n(&tid, *argv)) 1102 invarg("\"table\" value is invalid\n", *argv); 1103 if (tid < 256) 1104 req.r.rtm_table = tid; 1105 else { 1106 req.r.rtm_table = RT_TABLE_UNSPEC; 1107 addattr32(&req.n, sizeof(req), RTA_TABLE, tid); 1108 } 1109 table_ok = 1; 1110 } else if (strcmp(*argv, "dev") == 0 || 1111 strcmp(*argv, "oif") == 0) { 1112 NEXT_ARG(); 1113 d = *argv; 1114 } else if (matches(*argv, "pref") == 0) { 1115 __u8 pref; 1116 NEXT_ARG(); 1117 if (strcmp(*argv, "low") == 0) 1118 pref = ICMPV6_ROUTER_PREF_LOW; 1119 else if (strcmp(*argv, "medium") == 0) 1120 pref = ICMPV6_ROUTER_PREF_MEDIUM; 1121 else if (strcmp(*argv, "high") == 0) 1122 pref = ICMPV6_ROUTER_PREF_HIGH; 1123 else if (get_u8(&pref, *argv, 0)) 1124 invarg("\"pref\" value is invalid\n", *argv); 1125 addattr8(&req.n, sizeof(req), RTA_PREF, pref); 1126 } else if (strcmp(*argv, "encap") == 0) { 1127 char buf[1024]; 1128 struct rtattr *rta = (void*)buf; 1129 1130 rta->rta_type = RTA_ENCAP; 1131 rta->rta_len = RTA_LENGTH(0); 1132 1133 lwt_parse_encap(rta, sizeof(buf), &argc, &argv); 1134 1135 if (rta->rta_len > RTA_LENGTH(0)) 1136 addraw_l(&req.n, 1024, RTA_DATA(rta), RTA_PAYLOAD(rta)); 1137 } else { 1138 int type; 1139 inet_prefix dst; 1140 1141 if (strcmp(*argv, "to") == 0) { 1142 NEXT_ARG(); 1143 } 1144 if ((**argv < '0' || **argv > '9') && 1145 rtnl_rtntype_a2n(&type, *argv) == 0) { 1146 NEXT_ARG(); 1147 req.r.rtm_type = type; 1148 type_ok = 1; 1149 } 1150 1151 if (matches(*argv, "help") == 0) 1152 usage(); 1153 if (dst_ok) 1154 duparg2("to", *argv); 1155 get_prefix(&dst, *argv, req.r.rtm_family); 1156 if (req.r.rtm_family == AF_UNSPEC) 1157 req.r.rtm_family = dst.family; 1158 req.r.rtm_dst_len = dst.bitlen; 1159 dst_ok = 1; 1160 if (dst.bytelen) 1161 addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); 1162 } 1163 argc--; argv++; 1164 } 1165 1166 if (!dst_ok) 1167 usage(); 1168 1169 if (d || nhs_ok) { 1170 int idx; 1171 1172 if (d) { 1173 if ((idx = ll_name_to_index(d)) == 0) { 1174 fprintf(stderr, "Cannot find device \"%s\"\n", d); 1175 return -1; 1176 } 1177 addattr32(&req.n, sizeof(req), RTA_OIF, idx); 1178 } 1179 } 1180 1181 if (mxrta->rta_len > RTA_LENGTH(0)) { 1182 if (mxlock) 1183 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_LOCK, mxlock); 1184 addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta)); 1185 } 1186 1187 if (nhs_ok) 1188 parse_nexthops(&req.n, &req.r, argc, argv); 1189 1190 if (req.r.rtm_family == AF_UNSPEC) 1191 req.r.rtm_family = AF_INET; 1192 1193 if (!table_ok) { 1194 if (req.r.rtm_type == RTN_LOCAL || 1195 req.r.rtm_type == RTN_BROADCAST || 1196 req.r.rtm_type == RTN_NAT || 1197 req.r.rtm_type == RTN_ANYCAST) 1198 req.r.rtm_table = RT_TABLE_LOCAL; 1199 } 1200 if (!scope_ok) { 1201 if (req.r.rtm_family == AF_INET6 || 1202 req.r.rtm_family == AF_MPLS) 1203 req.r.rtm_scope = RT_SCOPE_UNIVERSE; 1204 else if (req.r.rtm_type == RTN_LOCAL || 1205 req.r.rtm_type == RTN_NAT) 1206 req.r.rtm_scope = RT_SCOPE_HOST; 1207 else if (req.r.rtm_type == RTN_BROADCAST || 1208 req.r.rtm_type == RTN_MULTICAST || 1209 req.r.rtm_type == RTN_ANYCAST) 1210 req.r.rtm_scope = RT_SCOPE_LINK; 1211 else if (req.r.rtm_type == RTN_UNICAST || 1212 req.r.rtm_type == RTN_UNSPEC) { 1213 if (cmd == RTM_DELROUTE) 1214 req.r.rtm_scope = RT_SCOPE_NOWHERE; 1215 else if (!gw_ok && !nhs_ok) 1216 req.r.rtm_scope = RT_SCOPE_LINK; 1217 } 1218 } 1219 1220 if (!type_ok && req.r.rtm_family == AF_MPLS) 1221 req.r.rtm_type = RTN_UNICAST; 1222 1223 if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) 1224 return -2; 1225 1226 return 0; 1227 } 1228 1229 static int rtnl_rtcache_request(struct rtnl_handle *rth, int family) 1230 { 1231 struct { 1232 struct nlmsghdr nlh; 1233 struct rtmsg rtm; 1234 } req; 1235 struct sockaddr_nl nladdr; 1236 1237 memset(&nladdr, 0, sizeof(nladdr)); 1238 memset(&req, 0, sizeof(req)); 1239 nladdr.nl_family = AF_NETLINK; 1240 1241 req.nlh.nlmsg_len = sizeof(req); 1242 req.nlh.nlmsg_type = RTM_GETROUTE; 1243 req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST; 1244 req.nlh.nlmsg_pid = 0; 1245 req.nlh.nlmsg_seq = rth->dump = ++rth->seq; 1246 req.rtm.rtm_family = family; 1247 req.rtm.rtm_flags |= RTM_F_CLONED; 1248 1249 return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)); 1250 } 1251 1252 static int iproute_flush_cache(void) 1253 { 1254 #define ROUTE_FLUSH_PATH "/proc/sys/net/ipv4/route/flush" 1255 1256 int len; 1257 int flush_fd = open (ROUTE_FLUSH_PATH, O_WRONLY); 1258 char *buffer = "-1"; 1259 1260 if (flush_fd < 0) { 1261 fprintf (stderr, "Cannot open \"%s\": %s\n", 1262 ROUTE_FLUSH_PATH, strerror(errno)); 1263 return -1; 1264 } 1265 1266 len = strlen (buffer); 1267 1268 if ((write (flush_fd, (void *)buffer, len)) < len) { 1269 fprintf (stderr, "Cannot flush routing cache\n"); 1270 close(flush_fd); 1271 return -1; 1272 } 1273 close(flush_fd); 1274 return 0; 1275 } 1276 1277 static __u32 route_dump_magic = 0x45311224; 1278 1279 static int save_route(const struct sockaddr_nl *who, struct nlmsghdr *n, 1280 void *arg) 1281 { 1282 int ret; 1283 int len = n->nlmsg_len; 1284 struct rtmsg *r = NLMSG_DATA(n); 1285 struct rtattr *tb[RTA_MAX+1]; 1286 int host_len; 1287 1288 host_len = af_bit_len(r->rtm_family); 1289 len -= NLMSG_LENGTH(sizeof(*r)); 1290 parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); 1291 1292 if (!filter_nlmsg(n, tb, host_len)) 1293 return 0; 1294 1295 ret = write(STDOUT_FILENO, n, n->nlmsg_len); 1296 if ((ret > 0) && (ret != n->nlmsg_len)) { 1297 fprintf(stderr, "Short write while saving nlmsg\n"); 1298 ret = -EIO; 1299 } 1300 1301 return ret == n->nlmsg_len ? 0 : ret; 1302 } 1303 1304 static int save_route_prep(void) 1305 { 1306 int ret; 1307 1308 if (isatty(STDOUT_FILENO)) { 1309 fprintf(stderr, "Not sending a binary stream to stdout\n"); 1310 return -1; 1311 } 1312 1313 ret = write(STDOUT_FILENO, &route_dump_magic, sizeof(route_dump_magic)); 1314 if (ret != sizeof(route_dump_magic)) { 1315 fprintf(stderr, "Can't write magic to dump file\n"); 1316 return -1; 1317 } 1318 1319 return 0; 1320 } 1321 1322 static int iproute_list_flush_or_save(int argc, char **argv, int action) 1323 { 1324 int do_ipv6 = preferred_family; 1325 char *id = NULL; 1326 char *od = NULL; 1327 unsigned int mark = 0; 1328 rtnl_filter_t filter_fn; 1329 1330 if (action == IPROUTE_SAVE) { 1331 if (save_route_prep()) 1332 return -1; 1333 1334 filter_fn = save_route; 1335 } else 1336 filter_fn = print_route; 1337 1338 iproute_reset_filter(0); 1339 filter.tb = RT_TABLE_MAIN; 1340 1341 if ((action == IPROUTE_FLUSH) && argc <= 0) { 1342 fprintf(stderr, "\"ip route flush\" requires arguments.\n"); 1343 return -1; 1344 } 1345 1346 while (argc > 0) { 1347 if (matches(*argv, "table") == 0) { 1348 __u32 tid; 1349 NEXT_ARG(); 1350 if (rtnl_rttable_a2n(&tid, *argv)) { 1351 if (strcmp(*argv, "all") == 0) { 1352 filter.tb = 0; 1353 } else if (strcmp(*argv, "cache") == 0) { 1354 filter.cloned = 1; 1355 } else if (strcmp(*argv, "help") == 0) { 1356 usage(); 1357 } else { 1358 invarg("table id value is invalid\n", *argv); 1359 } 1360 } else 1361 filter.tb = tid; 1362 } else if (matches(*argv, "cached") == 0 || 1363 matches(*argv, "cloned") == 0) { 1364 filter.cloned = 1; 1365 } else if (strcmp(*argv, "tos") == 0 || 1366 matches(*argv, "dsfield") == 0) { 1367 __u32 tos; 1368 NEXT_ARG(); 1369 if (rtnl_dsfield_a2n(&tos, *argv)) 1370 invarg("TOS value is invalid\n", *argv); 1371 filter.tos = tos; 1372 filter.tosmask = -1; 1373 } else if (matches(*argv, "protocol") == 0) { 1374 __u32 prot = 0; 1375 NEXT_ARG(); 1376 filter.protocolmask = -1; 1377 if (rtnl_rtprot_a2n(&prot, *argv)) { 1378 if (strcmp(*argv, "all") != 0) 1379 invarg("invalid \"protocol\"\n", *argv); 1380 prot = 0; 1381 filter.protocolmask = 0; 1382 } 1383 filter.protocol = prot; 1384 } else if (matches(*argv, "scope") == 0) { 1385 __u32 scope = 0; 1386 NEXT_ARG(); 1387 filter.scopemask = -1; 1388 if (rtnl_rtscope_a2n(&scope, *argv)) { 1389 if (strcmp(*argv, "all") != 0) 1390 invarg("invalid \"scope\"\n", *argv); 1391 scope = RT_SCOPE_NOWHERE; 1392 filter.scopemask = 0; 1393 } 1394 filter.scope = scope; 1395 } else if (matches(*argv, "type") == 0) { 1396 int type; 1397 NEXT_ARG(); 1398 filter.typemask = -1; 1399 if (rtnl_rtntype_a2n(&type, *argv)) 1400 invarg("node type value is invalid\n", *argv); 1401 filter.type = type; 1402 } else if (strcmp(*argv, "dev") == 0 || 1403 strcmp(*argv, "oif") == 0) { 1404 NEXT_ARG(); 1405 od = *argv; 1406 } else if (strcmp(*argv, "iif") == 0) { 1407 NEXT_ARG(); 1408 id = *argv; 1409 } else if (strcmp(*argv, "mark") == 0) { 1410 NEXT_ARG(); 1411 get_unsigned(&mark, *argv, 0); 1412 filter.markmask = -1; 1413 } else if (strcmp(*argv, "via") == 0) { 1414 int family; 1415 NEXT_ARG(); 1416 family = read_family(*argv); 1417 if (family == AF_UNSPEC) 1418 family = do_ipv6; 1419 else 1420 NEXT_ARG(); 1421 get_prefix(&filter.rvia, *argv, family); 1422 } else if (strcmp(*argv, "src") == 0) { 1423 NEXT_ARG(); 1424 get_prefix(&filter.rprefsrc, *argv, do_ipv6); 1425 } else if (matches(*argv, "realms") == 0) { 1426 __u32 realm; 1427 NEXT_ARG(); 1428 if (get_rt_realms_or_raw(&realm, *argv)) 1429 invarg("invalid realms\n", *argv); 1430 filter.realm = realm; 1431 filter.realmmask = ~0U; 1432 if ((filter.realm&0xFFFF) == 0 && 1433 (*argv)[strlen(*argv) - 1] == '/') 1434 filter.realmmask &= ~0xFFFF; 1435 if ((filter.realm&0xFFFF0000U) == 0 && 1436 (strchr(*argv, '/') == NULL || 1437 (*argv)[0] == '/')) 1438 filter.realmmask &= ~0xFFFF0000U; 1439 } else if (matches(*argv, "from") == 0) { 1440 NEXT_ARG(); 1441 if (matches(*argv, "root") == 0) { 1442 NEXT_ARG(); 1443 get_prefix(&filter.rsrc, *argv, do_ipv6); 1444 } else if (matches(*argv, "match") == 0) { 1445 NEXT_ARG(); 1446 get_prefix(&filter.msrc, *argv, do_ipv6); 1447 } else { 1448 if (matches(*argv, "exact") == 0) { 1449 NEXT_ARG(); 1450 } 1451 get_prefix(&filter.msrc, *argv, do_ipv6); 1452 filter.rsrc = filter.msrc; 1453 } 1454 } else { 1455 if (matches(*argv, "to") == 0) { 1456 NEXT_ARG(); 1457 } 1458 if (matches(*argv, "root") == 0) { 1459 NEXT_ARG(); 1460 get_prefix(&filter.rdst, *argv, do_ipv6); 1461 } else if (matches(*argv, "match") == 0) { 1462 NEXT_ARG(); 1463 get_prefix(&filter.mdst, *argv, do_ipv6); 1464 } else { 1465 if (matches(*argv, "exact") == 0) { 1466 NEXT_ARG(); 1467 } 1468 get_prefix(&filter.mdst, *argv, do_ipv6); 1469 filter.rdst = filter.mdst; 1470 } 1471 } 1472 argc--; argv++; 1473 } 1474 1475 if (do_ipv6 == AF_UNSPEC && filter.tb) 1476 do_ipv6 = AF_INET; 1477 1478 if (id || od) { 1479 int idx; 1480 1481 if (id) { 1482 if ((idx = ll_name_to_index(id)) == 0) { 1483 fprintf(stderr, "Cannot find device \"%s\"\n", id); 1484 return -1; 1485 } 1486 filter.iif = idx; 1487 filter.iifmask = -1; 1488 } 1489 if (od) { 1490 if ((idx = ll_name_to_index(od)) == 0) { 1491 fprintf(stderr, "Cannot find device \"%s\"\n", od); 1492 return -1; 1493 } 1494 filter.oif = idx; 1495 filter.oifmask = -1; 1496 } 1497 } 1498 filter.mark = mark; 1499 1500 if (action == IPROUTE_FLUSH) { 1501 int round = 0; 1502 char flushb[4096-512]; 1503 time_t start = time(0); 1504 1505 if (filter.cloned) { 1506 if (do_ipv6 != AF_INET6) { 1507 iproute_flush_cache(); 1508 if (show_stats) 1509 printf("*** IPv4 routing cache is flushed.\n"); 1510 } 1511 if (do_ipv6 == AF_INET) 1512 return 0; 1513 } 1514 1515 filter.flushb = flushb; 1516 filter.flushp = 0; 1517 filter.flushe = sizeof(flushb); 1518 1519 for (;;) { 1520 if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { 1521 perror("Cannot send dump request"); 1522 exit(1); 1523 } 1524 filter.flushed = 0; 1525 if (rtnl_dump_filter(&rth, filter_fn, stdout) < 0) { 1526 fprintf(stderr, "Flush terminated\n"); 1527 exit(1); 1528 } 1529 if (filter.flushed == 0) { 1530 if (show_stats) { 1531 if (round == 0 && (!filter.cloned || do_ipv6 == AF_INET6)) 1532 printf("Nothing to flush.\n"); 1533 else 1534 printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":""); 1535 } 1536 fflush(stdout); 1537 return 0; 1538 } 1539 round++; 1540 if (flush_update() < 0) 1541 exit(1); 1542 1543 if (time(0) - start > 30) { 1544 printf("\n*** Flush not completed after %ld seconds, %d entries remain ***\n", 1545 (long)(time(0) - start), filter.flushed); 1546 exit(1); 1547 } 1548 1549 if (show_stats) { 1550 printf("\n*** Round %d, deleting %d entries ***\n", round, filter.flushed); 1551 fflush(stdout); 1552 } 1553 } 1554 } 1555 1556 if (!filter.cloned) { 1557 if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { 1558 perror("Cannot send dump request"); 1559 exit(1); 1560 } 1561 } else { 1562 if (rtnl_rtcache_request(&rth, do_ipv6) < 0) { 1563 perror("Cannot send dump request"); 1564 exit(1); 1565 } 1566 } 1567 1568 if (rtnl_dump_filter(&rth, filter_fn, stdout) < 0) { 1569 fprintf(stderr, "Dump terminated\n"); 1570 exit(1); 1571 } 1572 1573 exit(0); 1574 } 1575 1576 1577 static int iproute_get(int argc, char **argv) 1578 { 1579 struct { 1580 struct nlmsghdr n; 1581 struct rtmsg r; 1582 char buf[1024]; 1583 } req; 1584 char *idev = NULL; 1585 char *odev = NULL; 1586 int connected = 0; 1587 int from_ok = 0; 1588 unsigned int mark = 0; 1589 1590 memset(&req, 0, sizeof(req)); 1591 1592 iproute_reset_filter(0); 1593 filter.cloned = 2; 1594 1595 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 1596 req.n.nlmsg_flags = NLM_F_REQUEST; 1597 req.n.nlmsg_type = RTM_GETROUTE; 1598 req.r.rtm_family = preferred_family; 1599 req.r.rtm_table = 0; 1600 req.r.rtm_protocol = 0; 1601 req.r.rtm_scope = 0; 1602 req.r.rtm_type = 0; 1603 req.r.rtm_src_len = 0; 1604 req.r.rtm_dst_len = 0; 1605 req.r.rtm_tos = 0; 1606 1607 while (argc > 0) { 1608 if (strcmp(*argv, "tos") == 0 || 1609 matches(*argv, "dsfield") == 0) { 1610 __u32 tos; 1611 NEXT_ARG(); 1612 if (rtnl_dsfield_a2n(&tos, *argv)) 1613 invarg("TOS value is invalid\n", *argv); 1614 req.r.rtm_tos = tos; 1615 } else if (matches(*argv, "from") == 0) { 1616 inet_prefix addr; 1617 NEXT_ARG(); 1618 if (matches(*argv, "help") == 0) 1619 usage(); 1620 from_ok = 1; 1621 get_prefix(&addr, *argv, req.r.rtm_family); 1622 if (req.r.rtm_family == AF_UNSPEC) 1623 req.r.rtm_family = addr.family; 1624 if (addr.bytelen) 1625 addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen); 1626 req.r.rtm_src_len = addr.bitlen; 1627 } else if (matches(*argv, "iif") == 0) { 1628 NEXT_ARG(); 1629 idev = *argv; 1630 } else if (matches(*argv, "mark") == 0) { 1631 NEXT_ARG(); 1632 get_unsigned(&mark, *argv, 0); 1633 } else if (matches(*argv, "oif") == 0 || 1634 strcmp(*argv, "dev") == 0) { 1635 NEXT_ARG(); 1636 odev = *argv; 1637 } else if (matches(*argv, "notify") == 0) { 1638 req.r.rtm_flags |= RTM_F_NOTIFY; 1639 } else if (matches(*argv, "connected") == 0) { 1640 connected = 1; 1641 } else if (matches(*argv, "uid") == 0) { 1642 uid_t uid; 1643 1644 NEXT_ARG(); 1645 if (get_unsigned(&uid, *argv, 0)) 1646 invarg("invalid UID\n", *argv); 1647 addattr32(&req.n, sizeof(req), RTA_UID, uid); 1648 } else { 1649 inet_prefix addr; 1650 if (strcmp(*argv, "to") == 0) { 1651 NEXT_ARG(); 1652 } 1653 if (matches(*argv, "help") == 0) 1654 usage(); 1655 get_prefix(&addr, *argv, req.r.rtm_family); 1656 if (req.r.rtm_family == AF_UNSPEC) 1657 req.r.rtm_family = addr.family; 1658 if (addr.bytelen) 1659 addattr_l(&req.n, sizeof(req), RTA_DST, &addr.data, addr.bytelen); 1660 req.r.rtm_dst_len = addr.bitlen; 1661 } 1662 argc--; argv++; 1663 } 1664 1665 if (req.r.rtm_dst_len == 0) { 1666 fprintf(stderr, "need at least a destination address\n"); 1667 exit(1); 1668 } 1669 1670 if (idev || odev) { 1671 int idx; 1672 1673 if (idev) { 1674 if ((idx = ll_name_to_index(idev)) == 0) { 1675 fprintf(stderr, "Cannot find device \"%s\"\n", idev); 1676 return -1; 1677 } 1678 addattr32(&req.n, sizeof(req), RTA_IIF, idx); 1679 } 1680 if (odev) { 1681 if ((idx = ll_name_to_index(odev)) == 0) { 1682 fprintf(stderr, "Cannot find device \"%s\"\n", odev); 1683 return -1; 1684 } 1685 addattr32(&req.n, sizeof(req), RTA_OIF, idx); 1686 } 1687 } 1688 if (mark) 1689 addattr32(&req.n, sizeof(req), RTA_MARK, mark); 1690 1691 if (req.r.rtm_family == AF_UNSPEC) 1692 req.r.rtm_family = AF_INET; 1693 1694 req.r.rtm_flags |= RTM_F_LOOKUP_TABLE; 1695 1696 if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) 1697 return -2; 1698 1699 if (connected && !from_ok) { 1700 struct rtmsg *r = NLMSG_DATA(&req.n); 1701 int len = req.n.nlmsg_len; 1702 struct rtattr * tb[RTA_MAX+1]; 1703 1704 if (print_route(NULL, &req.n, (void*)stdout) < 0) { 1705 fprintf(stderr, "An error :-)\n"); 1706 exit(1); 1707 } 1708 1709 if (req.n.nlmsg_type != RTM_NEWROUTE) { 1710 fprintf(stderr, "Not a route?\n"); 1711 return -1; 1712 } 1713 len -= NLMSG_LENGTH(sizeof(*r)); 1714 if (len < 0) { 1715 fprintf(stderr, "Wrong len %d\n", len); 1716 return -1; 1717 } 1718 1719 parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); 1720 1721 if (tb[RTA_PREFSRC]) { 1722 tb[RTA_PREFSRC]->rta_type = RTA_SRC; 1723 r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]); 1724 } else if (!tb[RTA_SRC]) { 1725 fprintf(stderr, "Failed to connect the route\n"); 1726 return -1; 1727 } 1728 if (!odev && tb[RTA_OIF]) 1729 tb[RTA_OIF]->rta_type = 0; 1730 if (tb[RTA_GATEWAY]) 1731 tb[RTA_GATEWAY]->rta_type = 0; 1732 if (tb[RTA_VIA]) 1733 tb[RTA_VIA]->rta_type = 0; 1734 if (!idev && tb[RTA_IIF]) 1735 tb[RTA_IIF]->rta_type = 0; 1736 req.n.nlmsg_flags = NLM_F_REQUEST; 1737 req.n.nlmsg_type = RTM_GETROUTE; 1738 1739 if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) 1740 return -2; 1741 } 1742 1743 if (print_route(NULL, &req.n, (void*)stdout) < 0) { 1744 fprintf(stderr, "An error :-)\n"); 1745 return -1; 1746 } 1747 1748 return 0; 1749 } 1750 1751 static int restore_handler(const struct sockaddr_nl *nl, 1752 struct rtnl_ctrl_data *ctrl, 1753 struct nlmsghdr *n, void *arg) 1754 { 1755 int ret; 1756 1757 n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK; 1758 1759 ll_init_map(&rth); 1760 1761 ret = rtnl_talk(&rth, n, n, sizeof(*n)); 1762 if ((ret < 0) && (errno == EEXIST)) 1763 ret = 0; 1764 1765 return ret; 1766 } 1767 1768 static int route_dump_check_magic(void) 1769 { 1770 int ret; 1771 __u32 magic = 0; 1772 1773 if (isatty(STDIN_FILENO)) { 1774 fprintf(stderr, "Can't restore route dump from a terminal\n"); 1775 return -1; 1776 } 1777 1778 ret = fread(&magic, sizeof(magic), 1, stdin); 1779 if (magic != route_dump_magic) { 1780 fprintf(stderr, "Magic mismatch (%d elems, %x magic)\n", ret, magic); 1781 return -1; 1782 } 1783 1784 return 0; 1785 } 1786 1787 static int iproute_restore(void) 1788 { 1789 if (route_dump_check_magic()) 1790 exit(-1); 1791 1792 exit(rtnl_from_file(stdin, &restore_handler, NULL)); 1793 } 1794 1795 static int show_handler(const struct sockaddr_nl *nl, 1796 struct rtnl_ctrl_data *ctrl, 1797 struct nlmsghdr *n, void *arg) 1798 { 1799 print_route(nl, n, stdout); 1800 return 0; 1801 } 1802 1803 static int iproute_showdump(void) 1804 { 1805 if (route_dump_check_magic()) 1806 exit(-1); 1807 1808 exit(rtnl_from_file(stdin, &show_handler, NULL)); 1809 } 1810 1811 void iproute_reset_filter(int ifindex) 1812 { 1813 memset(&filter, 0, sizeof(filter)); 1814 filter.mdst.bitlen = -1; 1815 filter.msrc.bitlen = -1; 1816 filter.oif = ifindex; 1817 if (filter.oif > 0) 1818 filter.oifmask = -1; 1819 } 1820 1821 int do_iproute(int argc, char **argv) 1822 { 1823 if (argc < 1) 1824 return iproute_list_flush_or_save(0, NULL, IPROUTE_LIST); 1825 1826 if (matches(*argv, "add") == 0) 1827 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_EXCL, 1828 argc-1, argv+1); 1829 if (matches(*argv, "change") == 0 || strcmp(*argv, "chg") == 0) 1830 return iproute_modify(RTM_NEWROUTE, NLM_F_REPLACE, 1831 argc-1, argv+1); 1832 if (matches(*argv, "replace") == 0) 1833 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_REPLACE, 1834 argc-1, argv+1); 1835 if (matches(*argv, "prepend") == 0) 1836 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE, 1837 argc-1, argv+1); 1838 if (matches(*argv, "append") == 0) 1839 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_APPEND, 1840 argc-1, argv+1); 1841 if (matches(*argv, "test") == 0) 1842 return iproute_modify(RTM_NEWROUTE, NLM_F_EXCL, 1843 argc-1, argv+1); 1844 if (matches(*argv, "delete") == 0) 1845 return iproute_modify(RTM_DELROUTE, 0, 1846 argc-1, argv+1); 1847 if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0 1848 || matches(*argv, "lst") == 0) 1849 return iproute_list_flush_or_save(argc-1, argv+1, IPROUTE_LIST); 1850 if (matches(*argv, "get") == 0) 1851 return iproute_get(argc-1, argv+1); 1852 if (matches(*argv, "flush") == 0) 1853 return iproute_list_flush_or_save(argc-1, argv+1, IPROUTE_FLUSH); 1854 if (matches(*argv, "save") == 0) 1855 return iproute_list_flush_or_save(argc-1, argv+1, IPROUTE_SAVE); 1856 if (matches(*argv, "restore") == 0) 1857 return iproute_restore(); 1858 if (matches(*argv, "showdump") == 0) 1859 return iproute_showdump(); 1860 if (matches(*argv, "help") == 0) 1861 usage(); 1862 fprintf(stderr, "Command \"%s\" is unknown, try \"ip route help\".\n", *argv); 1863 exit(-1); 1864 } 1865