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_UID]) 478 fprintf(fp, " uid %u ", rta_getattr_u32(tb[RTA_UID])); 479 480 if (tb[RTA_FLOW] && filter.realmmask != ~0U) { 481 __u32 to = rta_getattr_u32(tb[RTA_FLOW]); 482 __u32 from = to>>16; 483 to &= 0xFFFF; 484 fprintf(fp, "realm%s ", from ? "s" : ""); 485 if (from) { 486 fprintf(fp, "%s/", 487 rtnl_rtrealm_n2a(from, b1, sizeof(b1))); 488 } 489 fprintf(fp, "%s ", 490 rtnl_rtrealm_n2a(to, b1, sizeof(b1))); 491 } 492 if ((r->rtm_flags&RTM_F_CLONED) && r->rtm_family == AF_INET) { 493 __u32 flags = r->rtm_flags&~0xFFFF; 494 int first = 1; 495 496 fprintf(fp, "%s cache ", _SL_); 497 498 #define PRTFL(fl,flname) if (flags&RTCF_##fl) { \ 499 flags &= ~RTCF_##fl; \ 500 fprintf(fp, "%s" flname "%s", first ? "<" : "", flags ? "," : "> "); \ 501 first = 0; } 502 PRTFL(LOCAL, "local"); 503 PRTFL(REJECT, "reject"); 504 PRTFL(MULTICAST, "mc"); 505 PRTFL(BROADCAST, "brd"); 506 PRTFL(DNAT, "dst-nat"); 507 PRTFL(SNAT, "src-nat"); 508 PRTFL(MASQ, "masq"); 509 PRTFL(DIRECTDST, "dst-direct"); 510 PRTFL(DIRECTSRC, "src-direct"); 511 PRTFL(REDIRECTED, "redirected"); 512 PRTFL(DOREDIRECT, "redirect"); 513 PRTFL(FAST, "fastroute"); 514 PRTFL(NOTIFY, "notify"); 515 PRTFL(TPROXY, "proxy"); 516 517 if (flags) 518 fprintf(fp, "%s%x> ", first ? "<" : "", flags); 519 if (tb[RTA_CACHEINFO]) { 520 struct rta_cacheinfo *ci = RTA_DATA(tb[RTA_CACHEINFO]); 521 if (!hz) 522 hz = get_user_hz(); 523 if (ci->rta_expires != 0) 524 fprintf(fp, " expires %dsec", ci->rta_expires/hz); 525 if (ci->rta_error != 0) 526 fprintf(fp, " error %d", ci->rta_error); 527 if (show_stats) { 528 if (ci->rta_clntref) 529 fprintf(fp, " users %d", ci->rta_clntref); 530 if (ci->rta_used != 0) 531 fprintf(fp, " used %d", ci->rta_used); 532 if (ci->rta_lastuse != 0) 533 fprintf(fp, " age %dsec", ci->rta_lastuse/hz); 534 } 535 if (ci->rta_id) 536 fprintf(fp, " ipid 0x%04x", ci->rta_id); 537 if (ci->rta_ts || ci->rta_tsage) 538 fprintf(fp, " ts 0x%x tsage %dsec", 539 ci->rta_ts, ci->rta_tsage); 540 } 541 } else if (r->rtm_family == AF_INET6) { 542 struct rta_cacheinfo *ci = NULL; 543 if (tb[RTA_CACHEINFO]) 544 ci = RTA_DATA(tb[RTA_CACHEINFO]); 545 if ((r->rtm_flags & RTM_F_CLONED) || (ci && ci->rta_expires)) { 546 if (!hz) 547 hz = get_user_hz(); 548 if (r->rtm_flags & RTM_F_CLONED) 549 fprintf(fp, "%s cache ", _SL_); 550 if (ci->rta_expires) 551 fprintf(fp, " expires %dsec", ci->rta_expires/hz); 552 if (ci->rta_error != 0) 553 fprintf(fp, " error %d", ci->rta_error); 554 if (show_stats) { 555 if (ci->rta_clntref) 556 fprintf(fp, " users %d", ci->rta_clntref); 557 if (ci->rta_used != 0) 558 fprintf(fp, " used %d", ci->rta_used); 559 if (ci->rta_lastuse != 0) 560 fprintf(fp, " age %dsec", ci->rta_lastuse/hz); 561 } 562 } else if (ci) { 563 if (ci->rta_error != 0) 564 fprintf(fp, " error %d", ci->rta_error); 565 } 566 } 567 if (tb[RTA_METRICS]) { 568 int i; 569 unsigned mxlock = 0; 570 struct rtattr *mxrta[RTAX_MAX+1]; 571 572 parse_rtattr(mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), 573 RTA_PAYLOAD(tb[RTA_METRICS])); 574 if (mxrta[RTAX_LOCK]) 575 mxlock = *(unsigned*)RTA_DATA(mxrta[RTAX_LOCK]); 576 577 for (i=2; i<= RTAX_MAX; i++) { 578 __u32 val; 579 580 if (mxrta[i] == NULL) 581 continue; 582 583 if (i != RTAX_CC_ALGO) 584 val = rta_getattr_u32(mxrta[i]); 585 586 if (i == RTAX_HOPLIMIT && (int)val == -1) 587 continue; 588 589 if (i < sizeof(mx_names)/sizeof(char*) && mx_names[i]) 590 fprintf(fp, " %s", mx_names[i]); 591 else 592 fprintf(fp, " metric %d", i); 593 594 if (mxlock & (1<<i)) 595 fprintf(fp, " lock"); 596 597 switch (i) { 598 case RTAX_FEATURES: 599 print_rtax_features(fp, val); 600 break; 601 default: 602 fprintf(fp, " %u", val); 603 break; 604 605 case RTAX_RTT: 606 case RTAX_RTTVAR: 607 case RTAX_RTO_MIN: 608 if (i == RTAX_RTT) 609 val /= 8; 610 else if (i == RTAX_RTTVAR) 611 val /= 4; 612 613 if (val >= 1000) 614 fprintf(fp, " %gs", val/1e3); 615 else 616 fprintf(fp, " %ums", val); 617 break; 618 case RTAX_CC_ALGO: 619 fprintf(fp, " %s", rta_getattr_str(mxrta[i])); 620 break; 621 } 622 } 623 } 624 if (tb[RTA_IIF] && filter.iifmask != -1) { 625 fprintf(fp, " iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF]))); 626 } 627 if (tb[RTA_MULTIPATH]) { 628 struct rtnexthop *nh = RTA_DATA(tb[RTA_MULTIPATH]); 629 int first = 0; 630 631 len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); 632 633 for (;;) { 634 if (len < sizeof(*nh)) 635 break; 636 if (nh->rtnh_len > len) 637 break; 638 if (r->rtm_flags&RTM_F_CLONED && r->rtm_type == RTN_MULTICAST) { 639 if (first) 640 fprintf(fp, " Oifs:"); 641 else 642 fprintf(fp, " "); 643 } else 644 fprintf(fp, "%s\tnexthop", _SL_); 645 if (nh->rtnh_len > sizeof(*nh)) { 646 parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh), nh->rtnh_len - sizeof(*nh)); 647 648 if (tb[RTA_ENCAP]) 649 lwt_print_encap(fp, 650 tb[RTA_ENCAP_TYPE], 651 tb[RTA_ENCAP]); 652 653 if (tb[RTA_GATEWAY]) { 654 fprintf(fp, " via %s ", 655 format_host(r->rtm_family, 656 RTA_PAYLOAD(tb[RTA_GATEWAY]), 657 RTA_DATA(tb[RTA_GATEWAY]), 658 abuf, sizeof(abuf))); 659 } 660 if (tb[RTA_VIA]) { 661 size_t len = RTA_PAYLOAD(tb[RTA_VIA]) - 2; 662 struct rtvia *via = RTA_DATA(tb[RTA_VIA]); 663 fprintf(fp, "via %s %s ", 664 family_name(via->rtvia_family), 665 format_host(via->rtvia_family, len, via->rtvia_addr, 666 abuf, sizeof(abuf))); 667 } 668 if (tb[RTA_FLOW]) { 669 __u32 to = rta_getattr_u32(tb[RTA_FLOW]); 670 __u32 from = to>>16; 671 to &= 0xFFFF; 672 fprintf(fp, " realm%s ", from ? "s" : ""); 673 if (from) { 674 fprintf(fp, "%s/", 675 rtnl_rtrealm_n2a(from, b1, sizeof(b1))); 676 } 677 fprintf(fp, "%s", 678 rtnl_rtrealm_n2a(to, b1, sizeof(b1))); 679 } 680 } 681 if (r->rtm_flags&RTM_F_CLONED && r->rtm_type == RTN_MULTICAST) { 682 fprintf(fp, " %s", ll_index_to_name(nh->rtnh_ifindex)); 683 if (nh->rtnh_hops != 1) 684 fprintf(fp, "(ttl>%d)", nh->rtnh_hops); 685 } else { 686 fprintf(fp, " dev %s", ll_index_to_name(nh->rtnh_ifindex)); 687 fprintf(fp, " weight %d", nh->rtnh_hops+1); 688 } 689 if (nh->rtnh_flags & RTNH_F_DEAD) 690 fprintf(fp, " dead"); 691 if (nh->rtnh_flags & RTNH_F_ONLINK) 692 fprintf(fp, " onlink"); 693 if (nh->rtnh_flags & RTNH_F_PERVASIVE) 694 fprintf(fp, " pervasive"); 695 if (nh->rtnh_flags & RTNH_F_LINKDOWN) 696 fprintf(fp, " linkdown"); 697 len -= NLMSG_ALIGN(nh->rtnh_len); 698 nh = RTNH_NEXT(nh); 699 } 700 } 701 if (tb[RTA_PREF]) { 702 unsigned int pref = rta_getattr_u8(tb[RTA_PREF]); 703 fprintf(fp, " pref "); 704 705 switch (pref) { 706 case ICMPV6_ROUTER_PREF_LOW: 707 fprintf(fp, "low"); 708 break; 709 case ICMPV6_ROUTER_PREF_MEDIUM: 710 fprintf(fp, "medium"); 711 break; 712 case ICMPV6_ROUTER_PREF_HIGH: 713 fprintf(fp, "high"); 714 break; 715 default: 716 fprintf(fp, "%u", pref); 717 } 718 } 719 fprintf(fp, "\n"); 720 fflush(fp); 721 return 0; 722 } 723 724 static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, 725 struct rtattr *rta, struct rtnexthop *rtnh, 726 int *argcp, char ***argvp) 727 { 728 int argc = *argcp; 729 char **argv = *argvp; 730 731 while (++argv, --argc > 0) { 732 if (strcmp(*argv, "via") == 0) { 733 inet_prefix addr; 734 int family; 735 NEXT_ARG(); 736 family = read_family(*argv); 737 if (family == AF_UNSPEC) 738 family = r->rtm_family; 739 else 740 NEXT_ARG(); 741 get_addr(&addr, *argv, family); 742 if (r->rtm_family == AF_UNSPEC) 743 r->rtm_family = addr.family; 744 if (addr.family == r->rtm_family) { 745 rta_addattr_l(rta, 4096, RTA_GATEWAY, &addr.data, addr.bytelen); 746 rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen; 747 } else { 748 rta_addattr_l(rta, 4096, RTA_VIA, &addr.family, addr.bytelen+2); 749 rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen+2; 750 } 751 } else if (strcmp(*argv, "dev") == 0) { 752 NEXT_ARG(); 753 if ((rtnh->rtnh_ifindex = ll_name_to_index(*argv)) == 0) { 754 fprintf(stderr, "Cannot find device \"%s\"\n", *argv); 755 exit(1); 756 } 757 } else if (strcmp(*argv, "weight") == 0) { 758 unsigned w; 759 NEXT_ARG(); 760 if (get_unsigned(&w, *argv, 0) || w == 0 || w > 256) 761 invarg("\"weight\" is invalid\n", *argv); 762 rtnh->rtnh_hops = w - 1; 763 } else if (strcmp(*argv, "onlink") == 0) { 764 rtnh->rtnh_flags |= RTNH_F_ONLINK; 765 } else if (matches(*argv, "realms") == 0) { 766 __u32 realm; 767 NEXT_ARG(); 768 if (get_rt_realms_or_raw(&realm, *argv)) 769 invarg("\"realm\" value is invalid\n", *argv); 770 rta_addattr32(rta, 4096, RTA_FLOW, realm); 771 rtnh->rtnh_len += sizeof(struct rtattr) + 4; 772 } else if (strcmp(*argv, "encap") == 0) { 773 int len = rta->rta_len; 774 775 lwt_parse_encap(rta, 4096, &argc, &argv); 776 rtnh->rtnh_len += rta->rta_len - len; 777 } else 778 break; 779 } 780 *argcp = argc; 781 *argvp = argv; 782 return 0; 783 } 784 785 static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, 786 int argc, char **argv) 787 { 788 char buf[1024]; 789 struct rtattr *rta = (void*)buf; 790 struct rtnexthop *rtnh; 791 792 rta->rta_type = RTA_MULTIPATH; 793 rta->rta_len = RTA_LENGTH(0); 794 rtnh = RTA_DATA(rta); 795 796 while (argc > 0) { 797 if (strcmp(*argv, "nexthop") != 0) { 798 fprintf(stderr, "Error: \"nexthop\" or end of line is expected instead of \"%s\"\n", *argv); 799 exit(-1); 800 } 801 if (argc <= 1) { 802 fprintf(stderr, "Error: unexpected end of line after \"nexthop\"\n"); 803 exit(-1); 804 } 805 memset(rtnh, 0, sizeof(*rtnh)); 806 rtnh->rtnh_len = sizeof(*rtnh); 807 rta->rta_len += rtnh->rtnh_len; 808 parse_one_nh(n, r, rta, rtnh, &argc, &argv); 809 rtnh = RTNH_NEXT(rtnh); 810 } 811 812 if (rta->rta_len > RTA_LENGTH(0)) 813 addattr_l(n, 1024, RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta)); 814 return 0; 815 } 816 817 static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) 818 { 819 struct { 820 struct nlmsghdr n; 821 struct rtmsg r; 822 char buf[1024]; 823 } req; 824 char mxbuf[256]; 825 struct rtattr * mxrta = (void*)mxbuf; 826 unsigned mxlock = 0; 827 char *d = NULL; 828 int gw_ok = 0; 829 int dst_ok = 0; 830 int nhs_ok = 0; 831 int scope_ok = 0; 832 int table_ok = 0; 833 int raw = 0; 834 int type_ok = 0; 835 static int hz; 836 837 memset(&req, 0, sizeof(req)); 838 839 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 840 req.n.nlmsg_flags = NLM_F_REQUEST|flags; 841 req.n.nlmsg_type = cmd; 842 req.r.rtm_family = preferred_family; 843 req.r.rtm_table = RT_TABLE_MAIN; 844 req.r.rtm_scope = RT_SCOPE_NOWHERE; 845 846 if (cmd != RTM_DELROUTE) { 847 req.r.rtm_protocol = RTPROT_BOOT; 848 req.r.rtm_scope = RT_SCOPE_UNIVERSE; 849 req.r.rtm_type = RTN_UNICAST; 850 } 851 852 mxrta->rta_type = RTA_METRICS; 853 mxrta->rta_len = RTA_LENGTH(0); 854 855 while (argc > 0) { 856 if (strcmp(*argv, "src") == 0) { 857 inet_prefix addr; 858 NEXT_ARG(); 859 get_addr(&addr, *argv, req.r.rtm_family); 860 if (req.r.rtm_family == AF_UNSPEC) 861 req.r.rtm_family = addr.family; 862 addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen); 863 } else if (strcmp(*argv, "as") == 0) { 864 inet_prefix addr; 865 NEXT_ARG(); 866 if (strcmp(*argv, "to") == 0) { 867 NEXT_ARG(); 868 } 869 get_addr(&addr, *argv, req.r.rtm_family); 870 if (req.r.rtm_family == AF_UNSPEC) 871 req.r.rtm_family = addr.family; 872 addattr_l(&req.n, sizeof(req), RTA_NEWDST, &addr.data, addr.bytelen); 873 } else if (strcmp(*argv, "via") == 0) { 874 inet_prefix addr; 875 int family; 876 gw_ok = 1; 877 NEXT_ARG(); 878 family = read_family(*argv); 879 if (family == AF_UNSPEC) 880 family = req.r.rtm_family; 881 else 882 NEXT_ARG(); 883 get_addr(&addr, *argv, family); 884 if (req.r.rtm_family == AF_UNSPEC) 885 req.r.rtm_family = addr.family; 886 if (addr.family == req.r.rtm_family) 887 addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen); 888 else 889 addattr_l(&req.n, sizeof(req), RTA_VIA, &addr.family, addr.bytelen+2); 890 } else if (strcmp(*argv, "from") == 0) { 891 inet_prefix addr; 892 NEXT_ARG(); 893 get_prefix(&addr, *argv, req.r.rtm_family); 894 if (req.r.rtm_family == AF_UNSPEC) 895 req.r.rtm_family = addr.family; 896 if (addr.bytelen) 897 addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen); 898 req.r.rtm_src_len = addr.bitlen; 899 } else if (strcmp(*argv, "tos") == 0 || 900 matches(*argv, "dsfield") == 0) { 901 __u32 tos; 902 NEXT_ARG(); 903 if (rtnl_dsfield_a2n(&tos, *argv)) 904 invarg("\"tos\" value is invalid\n", *argv); 905 req.r.rtm_tos = tos; 906 } else if (strcmp(*argv, "expires") == 0 ) { 907 __u32 expires; 908 NEXT_ARG(); 909 if (get_u32(&expires, *argv, 0)) 910 invarg("\"expires\" value is invalid\n", *argv); 911 if (!hz) 912 hz = get_user_hz(); 913 addattr32(&req.n, sizeof(req), RTA_EXPIRES, expires*hz); 914 } else if (matches(*argv, "metric") == 0 || 915 matches(*argv, "priority") == 0 || 916 strcmp(*argv, "preference") == 0) { 917 __u32 metric; 918 NEXT_ARG(); 919 if (get_u32(&metric, *argv, 0)) 920 invarg("\"metric\" value is invalid\n", *argv); 921 addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric); 922 } else if (strcmp(*argv, "scope") == 0) { 923 __u32 scope = 0; 924 NEXT_ARG(); 925 if (rtnl_rtscope_a2n(&scope, *argv)) 926 invarg("invalid \"scope\" value\n", *argv); 927 req.r.rtm_scope = scope; 928 scope_ok = 1; 929 } else if (strcmp(*argv, "mtu") == 0) { 930 unsigned mtu; 931 NEXT_ARG(); 932 if (strcmp(*argv, "lock") == 0) { 933 mxlock |= (1<<RTAX_MTU); 934 NEXT_ARG(); 935 } 936 if (get_unsigned(&mtu, *argv, 0)) 937 invarg("\"mtu\" value is invalid\n", *argv); 938 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu); 939 } else if (strcmp(*argv, "hoplimit") == 0) { 940 unsigned hoplimit; 941 NEXT_ARG(); 942 if (strcmp(*argv, "lock") == 0) { 943 mxlock |= (1<<RTAX_HOPLIMIT); 944 NEXT_ARG(); 945 } 946 if (get_unsigned(&hoplimit, *argv, 0) || hoplimit > 255) 947 invarg("\"hoplimit\" value is invalid\n", *argv); 948 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_HOPLIMIT, hoplimit); 949 } else if (strcmp(*argv, "advmss") == 0) { 950 unsigned mss; 951 NEXT_ARG(); 952 if (strcmp(*argv, "lock") == 0) { 953 mxlock |= (1<<RTAX_ADVMSS); 954 NEXT_ARG(); 955 } 956 if (get_unsigned(&mss, *argv, 0)) 957 invarg("\"mss\" value is invalid\n", *argv); 958 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_ADVMSS, mss); 959 } else if (matches(*argv, "reordering") == 0) { 960 unsigned reord; 961 NEXT_ARG(); 962 if (strcmp(*argv, "lock") == 0) { 963 mxlock |= (1<<RTAX_REORDERING); 964 NEXT_ARG(); 965 } 966 if (get_unsigned(&reord, *argv, 0)) 967 invarg("\"reordering\" value is invalid\n", *argv); 968 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_REORDERING, reord); 969 } else if (strcmp(*argv, "rtt") == 0) { 970 unsigned rtt; 971 NEXT_ARG(); 972 if (strcmp(*argv, "lock") == 0) { 973 mxlock |= (1<<RTAX_RTT); 974 NEXT_ARG(); 975 } 976 if (get_time_rtt(&rtt, *argv, &raw)) 977 invarg("\"rtt\" value is invalid\n", *argv); 978 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTT, 979 (raw) ? rtt : rtt * 8); 980 } else if (strcmp(*argv, "rto_min") == 0) { 981 unsigned rto_min; 982 NEXT_ARG(); 983 mxlock |= (1<<RTAX_RTO_MIN); 984 if (get_time_rtt(&rto_min, *argv, &raw)) 985 invarg("\"rto_min\" value is invalid\n", 986 *argv); 987 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTO_MIN, 988 rto_min); 989 } else if (matches(*argv, "window") == 0) { 990 unsigned win; 991 NEXT_ARG(); 992 if (strcmp(*argv, "lock") == 0) { 993 mxlock |= (1<<RTAX_WINDOW); 994 NEXT_ARG(); 995 } 996 if (get_unsigned(&win, *argv, 0)) 997 invarg("\"window\" value is invalid\n", *argv); 998 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_WINDOW, win); 999 } else if (matches(*argv, "cwnd") == 0) { 1000 unsigned win; 1001 NEXT_ARG(); 1002 if (strcmp(*argv, "lock") == 0) { 1003 mxlock |= (1<<RTAX_CWND); 1004 NEXT_ARG(); 1005 } 1006 if (get_unsigned(&win, *argv, 0)) 1007 invarg("\"cwnd\" value is invalid\n", *argv); 1008 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_CWND, win); 1009 } else if (matches(*argv, "initcwnd") == 0) { 1010 unsigned win; 1011 NEXT_ARG(); 1012 if (strcmp(*argv, "lock") == 0) { 1013 mxlock |= (1<<RTAX_INITCWND); 1014 NEXT_ARG(); 1015 } 1016 if (get_unsigned(&win, *argv, 0)) 1017 invarg("\"initcwnd\" value is invalid\n", *argv); 1018 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITCWND, win); 1019 } else if (matches(*argv, "initrwnd") == 0) { 1020 unsigned win; 1021 NEXT_ARG(); 1022 if (strcmp(*argv, "lock") == 0) { 1023 mxlock |= (1<<RTAX_INITRWND); 1024 NEXT_ARG(); 1025 } 1026 if (get_unsigned(&win, *argv, 0)) 1027 invarg("\"initrwnd\" value is invalid\n", *argv); 1028 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITRWND, win); 1029 } else if (matches(*argv, "features") == 0) { 1030 unsigned int features = 0; 1031 1032 while (argc > 0) { 1033 NEXT_ARG(); 1034 1035 if (strcmp(*argv, "ecn") == 0) 1036 features |= RTAX_FEATURE_ECN; 1037 else 1038 invarg("\"features\" value not valid\n", *argv); 1039 break; 1040 } 1041 1042 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_FEATURES, features); 1043 } else if (matches(*argv, "quickack") == 0) { 1044 unsigned quickack; 1045 NEXT_ARG(); 1046 if (get_unsigned(&quickack, *argv, 0)) 1047 invarg("\"quickack\" value is invalid\n", *argv); 1048 if (quickack != 1 && quickack != 0) 1049 invarg("\"quickack\" value should be 0 or 1\n", *argv); 1050 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_QUICKACK, quickack); 1051 } else if (matches(*argv, "congctl") == 0) { 1052 NEXT_ARG(); 1053 if (strcmp(*argv, "lock") == 0) { 1054 mxlock |= 1 << RTAX_CC_ALGO; 1055 NEXT_ARG(); 1056 } 1057 rta_addattr_l(mxrta, sizeof(mxbuf), RTAX_CC_ALGO, *argv, 1058 strlen(*argv)); 1059 } else if (matches(*argv, "rttvar") == 0) { 1060 unsigned win; 1061 NEXT_ARG(); 1062 if (strcmp(*argv, "lock") == 0) { 1063 mxlock |= (1<<RTAX_RTTVAR); 1064 NEXT_ARG(); 1065 } 1066 if (get_time_rtt(&win, *argv, &raw)) 1067 invarg("\"rttvar\" value is invalid\n", *argv); 1068 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTTVAR, 1069 (raw) ? win : win * 4); 1070 } else if (matches(*argv, "ssthresh") == 0) { 1071 unsigned win; 1072 NEXT_ARG(); 1073 if (strcmp(*argv, "lock") == 0) { 1074 mxlock |= (1<<RTAX_SSTHRESH); 1075 NEXT_ARG(); 1076 } 1077 if (get_unsigned(&win, *argv, 0)) 1078 invarg("\"ssthresh\" value is invalid\n", *argv); 1079 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_SSTHRESH, win); 1080 } else if (matches(*argv, "realms") == 0) { 1081 __u32 realm; 1082 NEXT_ARG(); 1083 if (get_rt_realms_or_raw(&realm, *argv)) 1084 invarg("\"realm\" value is invalid\n", *argv); 1085 addattr32(&req.n, sizeof(req), RTA_FLOW, realm); 1086 } else if (strcmp(*argv, "onlink") == 0) { 1087 req.r.rtm_flags |= RTNH_F_ONLINK; 1088 } else if (strcmp(*argv, "nexthop") == 0) { 1089 nhs_ok = 1; 1090 break; 1091 } else if (matches(*argv, "protocol") == 0) { 1092 __u32 prot; 1093 NEXT_ARG(); 1094 if (rtnl_rtprot_a2n(&prot, *argv)) 1095 invarg("\"protocol\" value is invalid\n", *argv); 1096 req.r.rtm_protocol = prot; 1097 } else if (matches(*argv, "table") == 0) { 1098 __u32 tid; 1099 NEXT_ARG(); 1100 if (rtnl_rttable_a2n(&tid, *argv)) 1101 invarg("\"table\" value is invalid\n", *argv); 1102 if (tid < 256) 1103 req.r.rtm_table = tid; 1104 else { 1105 req.r.rtm_table = RT_TABLE_UNSPEC; 1106 addattr32(&req.n, sizeof(req), RTA_TABLE, tid); 1107 } 1108 table_ok = 1; 1109 } else if (strcmp(*argv, "dev") == 0 || 1110 strcmp(*argv, "oif") == 0) { 1111 NEXT_ARG(); 1112 d = *argv; 1113 } else if (matches(*argv, "pref") == 0) { 1114 __u8 pref; 1115 NEXT_ARG(); 1116 if (strcmp(*argv, "low") == 0) 1117 pref = ICMPV6_ROUTER_PREF_LOW; 1118 else if (strcmp(*argv, "medium") == 0) 1119 pref = ICMPV6_ROUTER_PREF_MEDIUM; 1120 else if (strcmp(*argv, "high") == 0) 1121 pref = ICMPV6_ROUTER_PREF_HIGH; 1122 else if (get_u8(&pref, *argv, 0)) 1123 invarg("\"pref\" value is invalid\n", *argv); 1124 addattr8(&req.n, sizeof(req), RTA_PREF, pref); 1125 } else if (strcmp(*argv, "encap") == 0) { 1126 char buf[1024]; 1127 struct rtattr *rta = (void*)buf; 1128 1129 rta->rta_type = RTA_ENCAP; 1130 rta->rta_len = RTA_LENGTH(0); 1131 1132 lwt_parse_encap(rta, sizeof(buf), &argc, &argv); 1133 1134 if (rta->rta_len > RTA_LENGTH(0)) 1135 addraw_l(&req.n, 1024, RTA_DATA(rta), RTA_PAYLOAD(rta)); 1136 } else { 1137 int type; 1138 inet_prefix dst; 1139 1140 if (strcmp(*argv, "to") == 0) { 1141 NEXT_ARG(); 1142 } 1143 if ((**argv < '0' || **argv > '9') && 1144 rtnl_rtntype_a2n(&type, *argv) == 0) { 1145 NEXT_ARG(); 1146 req.r.rtm_type = type; 1147 type_ok = 1; 1148 } 1149 1150 if (matches(*argv, "help") == 0) 1151 usage(); 1152 if (dst_ok) 1153 duparg2("to", *argv); 1154 get_prefix(&dst, *argv, req.r.rtm_family); 1155 if (req.r.rtm_family == AF_UNSPEC) 1156 req.r.rtm_family = dst.family; 1157 req.r.rtm_dst_len = dst.bitlen; 1158 dst_ok = 1; 1159 if (dst.bytelen) 1160 addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); 1161 } 1162 argc--; argv++; 1163 } 1164 1165 if (!dst_ok) 1166 usage(); 1167 1168 if (d || nhs_ok) { 1169 int idx; 1170 1171 if (d) { 1172 if ((idx = ll_name_to_index(d)) == 0) { 1173 fprintf(stderr, "Cannot find device \"%s\"\n", d); 1174 return -1; 1175 } 1176 addattr32(&req.n, sizeof(req), RTA_OIF, idx); 1177 } 1178 } 1179 1180 if (mxrta->rta_len > RTA_LENGTH(0)) { 1181 if (mxlock) 1182 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_LOCK, mxlock); 1183 addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta)); 1184 } 1185 1186 if (nhs_ok) 1187 parse_nexthops(&req.n, &req.r, argc, argv); 1188 1189 if (req.r.rtm_family == AF_UNSPEC) 1190 req.r.rtm_family = AF_INET; 1191 1192 if (!table_ok) { 1193 if (req.r.rtm_type == RTN_LOCAL || 1194 req.r.rtm_type == RTN_BROADCAST || 1195 req.r.rtm_type == RTN_NAT || 1196 req.r.rtm_type == RTN_ANYCAST) 1197 req.r.rtm_table = RT_TABLE_LOCAL; 1198 } 1199 if (!scope_ok) { 1200 if (req.r.rtm_family == AF_INET6 || 1201 req.r.rtm_family == AF_MPLS) 1202 req.r.rtm_scope = RT_SCOPE_UNIVERSE; 1203 else if (req.r.rtm_type == RTN_LOCAL || 1204 req.r.rtm_type == RTN_NAT) 1205 req.r.rtm_scope = RT_SCOPE_HOST; 1206 else if (req.r.rtm_type == RTN_BROADCAST || 1207 req.r.rtm_type == RTN_MULTICAST || 1208 req.r.rtm_type == RTN_ANYCAST) 1209 req.r.rtm_scope = RT_SCOPE_LINK; 1210 else if (req.r.rtm_type == RTN_UNICAST || 1211 req.r.rtm_type == RTN_UNSPEC) { 1212 if (cmd == RTM_DELROUTE) 1213 req.r.rtm_scope = RT_SCOPE_NOWHERE; 1214 else if (!gw_ok && !nhs_ok) 1215 req.r.rtm_scope = RT_SCOPE_LINK; 1216 } 1217 } 1218 1219 if (!type_ok && req.r.rtm_family == AF_MPLS) 1220 req.r.rtm_type = RTN_UNICAST; 1221 1222 if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) 1223 return -2; 1224 1225 return 0; 1226 } 1227 1228 static int rtnl_rtcache_request(struct rtnl_handle *rth, int family) 1229 { 1230 struct { 1231 struct nlmsghdr nlh; 1232 struct rtmsg rtm; 1233 } req; 1234 struct sockaddr_nl nladdr; 1235 1236 memset(&nladdr, 0, sizeof(nladdr)); 1237 memset(&req, 0, sizeof(req)); 1238 nladdr.nl_family = AF_NETLINK; 1239 1240 req.nlh.nlmsg_len = sizeof(req); 1241 req.nlh.nlmsg_type = RTM_GETROUTE; 1242 req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST; 1243 req.nlh.nlmsg_pid = 0; 1244 req.nlh.nlmsg_seq = rth->dump = ++rth->seq; 1245 req.rtm.rtm_family = family; 1246 req.rtm.rtm_flags |= RTM_F_CLONED; 1247 1248 return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)); 1249 } 1250 1251 static int iproute_flush_cache(void) 1252 { 1253 #define ROUTE_FLUSH_PATH "/proc/sys/net/ipv4/route/flush" 1254 1255 int len; 1256 int flush_fd = open (ROUTE_FLUSH_PATH, O_WRONLY); 1257 char *buffer = "-1"; 1258 1259 if (flush_fd < 0) { 1260 fprintf (stderr, "Cannot open \"%s\": %s\n", 1261 ROUTE_FLUSH_PATH, strerror(errno)); 1262 return -1; 1263 } 1264 1265 len = strlen (buffer); 1266 1267 if ((write (flush_fd, (void *)buffer, len)) < len) { 1268 fprintf (stderr, "Cannot flush routing cache\n"); 1269 close(flush_fd); 1270 return -1; 1271 } 1272 close(flush_fd); 1273 return 0; 1274 } 1275 1276 static __u32 route_dump_magic = 0x45311224; 1277 1278 static int save_route(const struct sockaddr_nl *who, struct nlmsghdr *n, 1279 void *arg) 1280 { 1281 int ret; 1282 int len = n->nlmsg_len; 1283 struct rtmsg *r = NLMSG_DATA(n); 1284 struct rtattr *tb[RTA_MAX+1]; 1285 int host_len; 1286 1287 host_len = af_bit_len(r->rtm_family); 1288 len -= NLMSG_LENGTH(sizeof(*r)); 1289 parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); 1290 1291 if (!filter_nlmsg(n, tb, host_len)) 1292 return 0; 1293 1294 ret = write(STDOUT_FILENO, n, n->nlmsg_len); 1295 if ((ret > 0) && (ret != n->nlmsg_len)) { 1296 fprintf(stderr, "Short write while saving nlmsg\n"); 1297 ret = -EIO; 1298 } 1299 1300 return ret == n->nlmsg_len ? 0 : ret; 1301 } 1302 1303 static int save_route_prep(void) 1304 { 1305 int ret; 1306 1307 if (isatty(STDOUT_FILENO)) { 1308 fprintf(stderr, "Not sending a binary stream to stdout\n"); 1309 return -1; 1310 } 1311 1312 ret = write(STDOUT_FILENO, &route_dump_magic, sizeof(route_dump_magic)); 1313 if (ret != sizeof(route_dump_magic)) { 1314 fprintf(stderr, "Can't write magic to dump file\n"); 1315 return -1; 1316 } 1317 1318 return 0; 1319 } 1320 1321 static int iproute_list_flush_or_save(int argc, char **argv, int action) 1322 { 1323 int do_ipv6 = preferred_family; 1324 char *id = NULL; 1325 char *od = NULL; 1326 unsigned int mark = 0; 1327 rtnl_filter_t filter_fn; 1328 1329 if (action == IPROUTE_SAVE) { 1330 if (save_route_prep()) 1331 return -1; 1332 1333 filter_fn = save_route; 1334 } else 1335 filter_fn = print_route; 1336 1337 iproute_reset_filter(0); 1338 filter.tb = RT_TABLE_MAIN; 1339 1340 if ((action == IPROUTE_FLUSH) && argc <= 0) { 1341 fprintf(stderr, "\"ip route flush\" requires arguments.\n"); 1342 return -1; 1343 } 1344 1345 while (argc > 0) { 1346 if (matches(*argv, "table") == 0) { 1347 __u32 tid; 1348 NEXT_ARG(); 1349 if (rtnl_rttable_a2n(&tid, *argv)) { 1350 if (strcmp(*argv, "all") == 0) { 1351 filter.tb = 0; 1352 } else if (strcmp(*argv, "cache") == 0) { 1353 filter.cloned = 1; 1354 } else if (strcmp(*argv, "help") == 0) { 1355 usage(); 1356 } else { 1357 invarg("table id value is invalid\n", *argv); 1358 } 1359 } else 1360 filter.tb = tid; 1361 } else if (matches(*argv, "cached") == 0 || 1362 matches(*argv, "cloned") == 0) { 1363 filter.cloned = 1; 1364 } else if (strcmp(*argv, "tos") == 0 || 1365 matches(*argv, "dsfield") == 0) { 1366 __u32 tos; 1367 NEXT_ARG(); 1368 if (rtnl_dsfield_a2n(&tos, *argv)) 1369 invarg("TOS value is invalid\n", *argv); 1370 filter.tos = tos; 1371 filter.tosmask = -1; 1372 } else if (matches(*argv, "protocol") == 0) { 1373 __u32 prot = 0; 1374 NEXT_ARG(); 1375 filter.protocolmask = -1; 1376 if (rtnl_rtprot_a2n(&prot, *argv)) { 1377 if (strcmp(*argv, "all") != 0) 1378 invarg("invalid \"protocol\"\n", *argv); 1379 prot = 0; 1380 filter.protocolmask = 0; 1381 } 1382 filter.protocol = prot; 1383 } else if (matches(*argv, "scope") == 0) { 1384 __u32 scope = 0; 1385 NEXT_ARG(); 1386 filter.scopemask = -1; 1387 if (rtnl_rtscope_a2n(&scope, *argv)) { 1388 if (strcmp(*argv, "all") != 0) 1389 invarg("invalid \"scope\"\n", *argv); 1390 scope = RT_SCOPE_NOWHERE; 1391 filter.scopemask = 0; 1392 } 1393 filter.scope = scope; 1394 } else if (matches(*argv, "type") == 0) { 1395 int type; 1396 NEXT_ARG(); 1397 filter.typemask = -1; 1398 if (rtnl_rtntype_a2n(&type, *argv)) 1399 invarg("node type value is invalid\n", *argv); 1400 filter.type = type; 1401 } else if (strcmp(*argv, "dev") == 0 || 1402 strcmp(*argv, "oif") == 0) { 1403 NEXT_ARG(); 1404 od = *argv; 1405 } else if (strcmp(*argv, "iif") == 0) { 1406 NEXT_ARG(); 1407 id = *argv; 1408 } else if (strcmp(*argv, "mark") == 0) { 1409 NEXT_ARG(); 1410 get_unsigned(&mark, *argv, 0); 1411 filter.markmask = -1; 1412 } else if (strcmp(*argv, "via") == 0) { 1413 int family; 1414 NEXT_ARG(); 1415 family = read_family(*argv); 1416 if (family == AF_UNSPEC) 1417 family = do_ipv6; 1418 else 1419 NEXT_ARG(); 1420 get_prefix(&filter.rvia, *argv, family); 1421 } else if (strcmp(*argv, "src") == 0) { 1422 NEXT_ARG(); 1423 get_prefix(&filter.rprefsrc, *argv, do_ipv6); 1424 } else if (matches(*argv, "realms") == 0) { 1425 __u32 realm; 1426 NEXT_ARG(); 1427 if (get_rt_realms_or_raw(&realm, *argv)) 1428 invarg("invalid realms\n", *argv); 1429 filter.realm = realm; 1430 filter.realmmask = ~0U; 1431 if ((filter.realm&0xFFFF) == 0 && 1432 (*argv)[strlen(*argv) - 1] == '/') 1433 filter.realmmask &= ~0xFFFF; 1434 if ((filter.realm&0xFFFF0000U) == 0 && 1435 (strchr(*argv, '/') == NULL || 1436 (*argv)[0] == '/')) 1437 filter.realmmask &= ~0xFFFF0000U; 1438 } else if (matches(*argv, "from") == 0) { 1439 NEXT_ARG(); 1440 if (matches(*argv, "root") == 0) { 1441 NEXT_ARG(); 1442 get_prefix(&filter.rsrc, *argv, do_ipv6); 1443 } else if (matches(*argv, "match") == 0) { 1444 NEXT_ARG(); 1445 get_prefix(&filter.msrc, *argv, do_ipv6); 1446 } else { 1447 if (matches(*argv, "exact") == 0) { 1448 NEXT_ARG(); 1449 } 1450 get_prefix(&filter.msrc, *argv, do_ipv6); 1451 filter.rsrc = filter.msrc; 1452 } 1453 } else { 1454 if (matches(*argv, "to") == 0) { 1455 NEXT_ARG(); 1456 } 1457 if (matches(*argv, "root") == 0) { 1458 NEXT_ARG(); 1459 get_prefix(&filter.rdst, *argv, do_ipv6); 1460 } else if (matches(*argv, "match") == 0) { 1461 NEXT_ARG(); 1462 get_prefix(&filter.mdst, *argv, do_ipv6); 1463 } else { 1464 if (matches(*argv, "exact") == 0) { 1465 NEXT_ARG(); 1466 } 1467 get_prefix(&filter.mdst, *argv, do_ipv6); 1468 filter.rdst = filter.mdst; 1469 } 1470 } 1471 argc--; argv++; 1472 } 1473 1474 if (do_ipv6 == AF_UNSPEC && filter.tb) 1475 do_ipv6 = AF_INET; 1476 1477 if (id || od) { 1478 int idx; 1479 1480 if (id) { 1481 if ((idx = ll_name_to_index(id)) == 0) { 1482 fprintf(stderr, "Cannot find device \"%s\"\n", id); 1483 return -1; 1484 } 1485 filter.iif = idx; 1486 filter.iifmask = -1; 1487 } 1488 if (od) { 1489 if ((idx = ll_name_to_index(od)) == 0) { 1490 fprintf(stderr, "Cannot find device \"%s\"\n", od); 1491 return -1; 1492 } 1493 filter.oif = idx; 1494 filter.oifmask = -1; 1495 } 1496 } 1497 filter.mark = mark; 1498 1499 if (action == IPROUTE_FLUSH) { 1500 int round = 0; 1501 char flushb[4096-512]; 1502 time_t start = time(0); 1503 1504 if (filter.cloned) { 1505 if (do_ipv6 != AF_INET6) { 1506 iproute_flush_cache(); 1507 if (show_stats) 1508 printf("*** IPv4 routing cache is flushed.\n"); 1509 } 1510 if (do_ipv6 == AF_INET) 1511 return 0; 1512 } 1513 1514 filter.flushb = flushb; 1515 filter.flushp = 0; 1516 filter.flushe = sizeof(flushb); 1517 1518 for (;;) { 1519 if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { 1520 perror("Cannot send dump request"); 1521 exit(1); 1522 } 1523 filter.flushed = 0; 1524 if (rtnl_dump_filter(&rth, filter_fn, stdout) < 0) { 1525 fprintf(stderr, "Flush terminated\n"); 1526 exit(1); 1527 } 1528 if (filter.flushed == 0) { 1529 if (show_stats) { 1530 if (round == 0 && (!filter.cloned || do_ipv6 == AF_INET6)) 1531 printf("Nothing to flush.\n"); 1532 else 1533 printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":""); 1534 } 1535 fflush(stdout); 1536 return 0; 1537 } 1538 round++; 1539 if (flush_update() < 0) 1540 exit(1); 1541 1542 if (time(0) - start > 30) { 1543 printf("\n*** Flush not completed after %ld seconds, %d entries remain ***\n", 1544 (long)(time(0) - start), filter.flushed); 1545 exit(1); 1546 } 1547 1548 if (show_stats) { 1549 printf("\n*** Round %d, deleting %d entries ***\n", round, filter.flushed); 1550 fflush(stdout); 1551 } 1552 } 1553 } 1554 1555 if (!filter.cloned) { 1556 if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { 1557 perror("Cannot send dump request"); 1558 exit(1); 1559 } 1560 } else { 1561 if (rtnl_rtcache_request(&rth, do_ipv6) < 0) { 1562 perror("Cannot send dump request"); 1563 exit(1); 1564 } 1565 } 1566 1567 if (rtnl_dump_filter(&rth, filter_fn, stdout) < 0) { 1568 fprintf(stderr, "Dump terminated\n"); 1569 exit(1); 1570 } 1571 1572 exit(0); 1573 } 1574 1575 1576 static int iproute_get(int argc, char **argv) 1577 { 1578 struct { 1579 struct nlmsghdr n; 1580 struct rtmsg r; 1581 char buf[1024]; 1582 } req; 1583 char *idev = NULL; 1584 char *odev = NULL; 1585 int connected = 0; 1586 int from_ok = 0; 1587 unsigned int mark = 0; 1588 1589 memset(&req, 0, sizeof(req)); 1590 1591 iproute_reset_filter(0); 1592 filter.cloned = 2; 1593 1594 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 1595 req.n.nlmsg_flags = NLM_F_REQUEST; 1596 req.n.nlmsg_type = RTM_GETROUTE; 1597 req.r.rtm_family = preferred_family; 1598 req.r.rtm_table = 0; 1599 req.r.rtm_protocol = 0; 1600 req.r.rtm_scope = 0; 1601 req.r.rtm_type = 0; 1602 req.r.rtm_src_len = 0; 1603 req.r.rtm_dst_len = 0; 1604 req.r.rtm_tos = 0; 1605 1606 while (argc > 0) { 1607 if (strcmp(*argv, "tos") == 0 || 1608 matches(*argv, "dsfield") == 0) { 1609 __u32 tos; 1610 NEXT_ARG(); 1611 if (rtnl_dsfield_a2n(&tos, *argv)) 1612 invarg("TOS value is invalid\n", *argv); 1613 req.r.rtm_tos = tos; 1614 } else if (matches(*argv, "from") == 0) { 1615 inet_prefix addr; 1616 NEXT_ARG(); 1617 if (matches(*argv, "help") == 0) 1618 usage(); 1619 from_ok = 1; 1620 get_prefix(&addr, *argv, req.r.rtm_family); 1621 if (req.r.rtm_family == AF_UNSPEC) 1622 req.r.rtm_family = addr.family; 1623 if (addr.bytelen) 1624 addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen); 1625 req.r.rtm_src_len = addr.bitlen; 1626 } else if (matches(*argv, "iif") == 0) { 1627 NEXT_ARG(); 1628 idev = *argv; 1629 } else if (matches(*argv, "mark") == 0) { 1630 NEXT_ARG(); 1631 get_unsigned(&mark, *argv, 0); 1632 } else if (matches(*argv, "oif") == 0 || 1633 strcmp(*argv, "dev") == 0) { 1634 NEXT_ARG(); 1635 odev = *argv; 1636 } else if (matches(*argv, "uid") == 0) { 1637 uid_t uid; 1638 NEXT_ARG(); 1639 get_unsigned(&uid, *argv, 0); 1640 addattr32(&req.n, sizeof(req), RTA_UID, uid); 1641 } else if (matches(*argv, "notify") == 0) { 1642 req.r.rtm_flags |= RTM_F_NOTIFY; 1643 } else if (matches(*argv, "connected") == 0) { 1644 connected = 1; 1645 } else { 1646 inet_prefix addr; 1647 if (strcmp(*argv, "to") == 0) { 1648 NEXT_ARG(); 1649 } 1650 if (matches(*argv, "help") == 0) 1651 usage(); 1652 get_prefix(&addr, *argv, req.r.rtm_family); 1653 if (req.r.rtm_family == AF_UNSPEC) 1654 req.r.rtm_family = addr.family; 1655 if (addr.bytelen) 1656 addattr_l(&req.n, sizeof(req), RTA_DST, &addr.data, addr.bytelen); 1657 req.r.rtm_dst_len = addr.bitlen; 1658 } 1659 argc--; argv++; 1660 } 1661 1662 if (req.r.rtm_dst_len == 0) { 1663 fprintf(stderr, "need at least a destination address\n"); 1664 exit(1); 1665 } 1666 1667 if (idev || odev) { 1668 int idx; 1669 1670 if (idev) { 1671 if ((idx = ll_name_to_index(idev)) == 0) { 1672 fprintf(stderr, "Cannot find device \"%s\"\n", idev); 1673 return -1; 1674 } 1675 addattr32(&req.n, sizeof(req), RTA_IIF, idx); 1676 } 1677 if (odev) { 1678 if ((idx = ll_name_to_index(odev)) == 0) { 1679 fprintf(stderr, "Cannot find device \"%s\"\n", odev); 1680 return -1; 1681 } 1682 addattr32(&req.n, sizeof(req), RTA_OIF, idx); 1683 } 1684 } 1685 if (mark) 1686 addattr32(&req.n, sizeof(req), RTA_MARK, mark); 1687 1688 if (req.r.rtm_family == AF_UNSPEC) 1689 req.r.rtm_family = AF_INET; 1690 1691 req.r.rtm_flags |= RTM_F_LOOKUP_TABLE; 1692 1693 if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) 1694 return -2; 1695 1696 if (connected && !from_ok) { 1697 struct rtmsg *r = NLMSG_DATA(&req.n); 1698 int len = req.n.nlmsg_len; 1699 struct rtattr * tb[RTA_MAX+1]; 1700 1701 if (print_route(NULL, &req.n, (void*)stdout) < 0) { 1702 fprintf(stderr, "An error :-)\n"); 1703 exit(1); 1704 } 1705 1706 if (req.n.nlmsg_type != RTM_NEWROUTE) { 1707 fprintf(stderr, "Not a route?\n"); 1708 return -1; 1709 } 1710 len -= NLMSG_LENGTH(sizeof(*r)); 1711 if (len < 0) { 1712 fprintf(stderr, "Wrong len %d\n", len); 1713 return -1; 1714 } 1715 1716 parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); 1717 1718 if (tb[RTA_PREFSRC]) { 1719 tb[RTA_PREFSRC]->rta_type = RTA_SRC; 1720 r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]); 1721 } else if (!tb[RTA_SRC]) { 1722 fprintf(stderr, "Failed to connect the route\n"); 1723 return -1; 1724 } 1725 if (!odev && tb[RTA_OIF]) 1726 tb[RTA_OIF]->rta_type = 0; 1727 if (tb[RTA_GATEWAY]) 1728 tb[RTA_GATEWAY]->rta_type = 0; 1729 if (tb[RTA_VIA]) 1730 tb[RTA_VIA]->rta_type = 0; 1731 if (!idev && tb[RTA_IIF]) 1732 tb[RTA_IIF]->rta_type = 0; 1733 req.n.nlmsg_flags = NLM_F_REQUEST; 1734 req.n.nlmsg_type = RTM_GETROUTE; 1735 1736 if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) 1737 return -2; 1738 } 1739 1740 if (print_route(NULL, &req.n, (void*)stdout) < 0) { 1741 fprintf(stderr, "An error :-)\n"); 1742 return -1; 1743 } 1744 1745 return 0; 1746 } 1747 1748 static int restore_handler(const struct sockaddr_nl *nl, 1749 struct rtnl_ctrl_data *ctrl, 1750 struct nlmsghdr *n, void *arg) 1751 { 1752 int ret; 1753 1754 n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK; 1755 1756 ll_init_map(&rth); 1757 1758 ret = rtnl_talk(&rth, n, n, sizeof(*n)); 1759 if ((ret < 0) && (errno == EEXIST)) 1760 ret = 0; 1761 1762 return ret; 1763 } 1764 1765 static int route_dump_check_magic(void) 1766 { 1767 int ret; 1768 __u32 magic = 0; 1769 1770 if (isatty(STDIN_FILENO)) { 1771 fprintf(stderr, "Can't restore route dump from a terminal\n"); 1772 return -1; 1773 } 1774 1775 ret = fread(&magic, sizeof(magic), 1, stdin); 1776 if (magic != route_dump_magic) { 1777 fprintf(stderr, "Magic mismatch (%d elems, %x magic)\n", ret, magic); 1778 return -1; 1779 } 1780 1781 return 0; 1782 } 1783 1784 static int iproute_restore(void) 1785 { 1786 if (route_dump_check_magic()) 1787 exit(-1); 1788 1789 exit(rtnl_from_file(stdin, &restore_handler, NULL)); 1790 } 1791 1792 static int show_handler(const struct sockaddr_nl *nl, 1793 struct rtnl_ctrl_data *ctrl, 1794 struct nlmsghdr *n, void *arg) 1795 { 1796 print_route(nl, n, stdout); 1797 return 0; 1798 } 1799 1800 static int iproute_showdump(void) 1801 { 1802 if (route_dump_check_magic()) 1803 exit(-1); 1804 1805 exit(rtnl_from_file(stdin, &show_handler, NULL)); 1806 } 1807 1808 void iproute_reset_filter(int ifindex) 1809 { 1810 memset(&filter, 0, sizeof(filter)); 1811 filter.mdst.bitlen = -1; 1812 filter.msrc.bitlen = -1; 1813 filter.oif = ifindex; 1814 if (filter.oif > 0) 1815 filter.oifmask = -1; 1816 } 1817 1818 int do_iproute(int argc, char **argv) 1819 { 1820 if (argc < 1) 1821 return iproute_list_flush_or_save(0, NULL, IPROUTE_LIST); 1822 1823 if (matches(*argv, "add") == 0) 1824 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_EXCL, 1825 argc-1, argv+1); 1826 if (matches(*argv, "change") == 0 || strcmp(*argv, "chg") == 0) 1827 return iproute_modify(RTM_NEWROUTE, NLM_F_REPLACE, 1828 argc-1, argv+1); 1829 if (matches(*argv, "replace") == 0) 1830 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_REPLACE, 1831 argc-1, argv+1); 1832 if (matches(*argv, "prepend") == 0) 1833 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE, 1834 argc-1, argv+1); 1835 if (matches(*argv, "append") == 0) 1836 return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_APPEND, 1837 argc-1, argv+1); 1838 if (matches(*argv, "test") == 0) 1839 return iproute_modify(RTM_NEWROUTE, NLM_F_EXCL, 1840 argc-1, argv+1); 1841 if (matches(*argv, "delete") == 0) 1842 return iproute_modify(RTM_DELROUTE, 0, 1843 argc-1, argv+1); 1844 if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0 1845 || matches(*argv, "lst") == 0) 1846 return iproute_list_flush_or_save(argc-1, argv+1, IPROUTE_LIST); 1847 if (matches(*argv, "get") == 0) 1848 return iproute_get(argc-1, argv+1); 1849 if (matches(*argv, "flush") == 0) 1850 return iproute_list_flush_or_save(argc-1, argv+1, IPROUTE_FLUSH); 1851 if (matches(*argv, "save") == 0) 1852 return iproute_list_flush_or_save(argc-1, argv+1, IPROUTE_SAVE); 1853 if (matches(*argv, "restore") == 0) 1854 return iproute_restore(); 1855 if (matches(*argv, "showdump") == 0) 1856 return iproute_showdump(); 1857 if (matches(*argv, "help") == 0) 1858 usage(); 1859 fprintf(stderr, "Command \"%s\" is unknown, try \"ip route help\".\n", *argv); 1860 exit(-1); 1861 } 1862