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