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