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