"INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n"
"NH := [ encap ENCAPTYPE ENCAPHDR ] [ via [ FAMILY ] ADDRESS ]\n"
" [ dev STRING ] [ weight NUMBER ] NHFLAGS\n"
- "FAMILY := [ inet | inet6 | ipx | dnet | mpls | bridge | link ]\n"
+ "FAMILY := [ inet | inet6 | mpls | bridge | link ]\n"
"OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]\n"
" [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n"
" [ window NUMBER ] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n"
if (features)
print_0xhex(PRINT_ANY,
- "features", "0x%x ", of);
+ "features", "%#llx ", of);
}
static void print_rt_flags(FILE *fp, unsigned int flags)
}
if (ci->rta_id)
print_0xhex(PRINT_ANY, "ipid",
- "ipid 0x%04x ", ci->rta_id);
+ "ipid 0x%04llx ", ci->rta_id);
if (ci->rta_ts || ci->rta_tsage) {
print_0xhex(PRINT_ANY, "ts",
- "ts 0x%x", ci->rta_ts);
+ "ts 0x%llx", ci->rta_ts);
print_uint(PRINT_ANY, "tsage",
"tsage %usec ", ci->rta_tsage);
}
}
}
-int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_route(struct nlmsghdr *n, void *arg)
{
FILE *fp = (FILE *)arg;
struct rtmsg *r = NLMSG_DATA(n);
print_uint(PRINT_JSON, "mark", NULL, mark);
else if (mark >= 16)
print_0xhex(PRINT_FP, NULL,
- "mark 0x%x ", mark);
+ "mark 0x%llx ", mark);
else
print_uint(PRINT_FP, NULL,
"mark %u ", mark);
print_rt_pref(fp, rta_getattr_u8(tb[RTA_PREF]));
if (tb[RTA_TTL_PROPAGATE]) {
- bool propogate = rta_getattr_u8(tb[RTA_TTL_PROPAGATE]);
+ bool propagate = rta_getattr_u8(tb[RTA_TTL_PROPAGATE]);
if (is_json_context())
print_bool(PRINT_JSON, "ttl-propogate", NULL,
- propogate);
+ propagate);
else
print_string(PRINT_FP, NULL,
"ttl-propogate %s",
- propogate ? "enabled" : "disabled");
+ propagate ? "enabled" : "disabled");
}
print_string(PRINT_FP, NULL, "\n", NULL);
return 0;
}
-static int rtnl_rtcache_request(struct rtnl_handle *rth, int family)
-{
- struct {
- struct nlmsghdr nlh;
- struct rtmsg rtm;
- } req = {
- .nlh.nlmsg_len = sizeof(req),
- .nlh.nlmsg_type = RTM_GETROUTE,
- .nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST,
- .nlh.nlmsg_seq = rth->dump = ++rth->seq,
- .rtm.rtm_family = family,
- .rtm.rtm_flags = RTM_F_CLONED,
- };
- struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
-
- return sendto(rth->fd, (void *)&req, sizeof(req), 0, (struct sockaddr *)&nladdr, sizeof(nladdr));
-}
-
static int iproute_flush_cache(void)
{
#define ROUTE_FLUSH_PATH "/proc/sys/net/ipv4/route/flush"
static __u32 route_dump_magic = 0x45311224;
-static int save_route(const struct sockaddr_nl *who, struct nlmsghdr *n,
- void *arg)
+static int save_route(struct nlmsghdr *n, void *arg)
{
int ret;
int len = n->nlmsg_len;
return 0;
}
-static int iproute_flush(int do_ipv6, rtnl_filter_t filter_fn)
+static int iproute_flush(int family, rtnl_filter_t filter_fn)
{
time_t start = time(0);
char flushb[4096-512];
int ret;
if (filter.cloned) {
- if (do_ipv6 != AF_INET6) {
+ if (family != AF_INET6) {
iproute_flush_cache();
if (show_stats)
printf("*** IPv4 routing cache is flushed.\n");
}
- if (do_ipv6 == AF_INET)
+ if (family == AF_INET)
return 0;
}
filter.flushe = sizeof(flushb);
for (;;) {
- if (rtnl_routedump_req(&rth, do_ipv6) < 0) {
+ if (rtnl_routedump_req(&rth, family, NULL) < 0) {
perror("Cannot send dump request");
return -2;
}
if (filter.flushed == 0) {
if (show_stats) {
if (round == 0 &&
- (!filter.cloned || do_ipv6 == AF_INET6))
+ (!filter.cloned || family == AF_INET6))
printf("Nothing to flush.\n");
else
printf("*** Flush is complete after %d round%s ***\n",
}
}
+static int iproute_dump_filter(struct nlmsghdr *nlh, int reqlen)
+{
+ struct rtmsg *rtm = NLMSG_DATA(nlh);
+ int err;
+
+ rtm->rtm_protocol = filter.protocol;
+ if (filter.cloned)
+ rtm->rtm_flags |= RTM_F_CLONED;
+
+ if (filter.tb) {
+ err = addattr32(nlh, reqlen, RTA_TABLE, filter.tb);
+ if (err)
+ return err;
+ }
+
+ if (filter.oif) {
+ err = addattr32(nlh, reqlen, RTA_OIF, filter.oif);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static int iproute_list_flush_or_save(int argc, char **argv, int action)
{
- int do_ipv6 = preferred_family;
+ int dump_family = preferred_family;
char *id = NULL;
char *od = NULL;
unsigned int mark = 0;
NEXT_ARG();
family = read_family(*argv);
if (family == AF_UNSPEC)
- family = do_ipv6;
+ family = dump_family;
else
NEXT_ARG();
get_prefix(&filter.rvia, *argv, family);
} else if (strcmp(*argv, "src") == 0) {
NEXT_ARG();
- get_prefix(&filter.rprefsrc, *argv, do_ipv6);
+ get_prefix(&filter.rprefsrc, *argv, dump_family);
} else if (matches(*argv, "realms") == 0) {
__u32 realm;
NEXT_ARG();
if (matches(*argv, "root") == 0) {
NEXT_ARG();
- get_prefix(&filter.rsrc, *argv, do_ipv6);
+ get_prefix(&filter.rsrc, *argv, dump_family);
} else if (matches(*argv, "match") == 0) {
NEXT_ARG();
- get_prefix(&filter.msrc, *argv, do_ipv6);
+ get_prefix(&filter.msrc, *argv, dump_family);
} else {
if (matches(*argv, "exact") == 0) {
NEXT_ARG();
}
- get_prefix(&filter.msrc, *argv, do_ipv6);
+ get_prefix(&filter.msrc, *argv, dump_family);
filter.rsrc = filter.msrc;
}
} else {
}
if (matches(*argv, "root") == 0) {
NEXT_ARG();
- get_prefix(&filter.rdst, *argv, do_ipv6);
+ get_prefix(&filter.rdst, *argv, dump_family);
} else if (matches(*argv, "match") == 0) {
NEXT_ARG();
- get_prefix(&filter.mdst, *argv, do_ipv6);
+ get_prefix(&filter.mdst, *argv, dump_family);
} else {
if (matches(*argv, "exact") == 0) {
NEXT_ARG();
}
- get_prefix(&filter.mdst, *argv, do_ipv6);
+ get_prefix(&filter.mdst, *argv, dump_family);
filter.rdst = filter.mdst;
}
}
argc--; argv++;
}
- if (do_ipv6 == AF_UNSPEC && filter.tb)
- do_ipv6 = AF_INET;
+ if (dump_family == AF_UNSPEC && filter.tb)
+ dump_family = AF_INET;
if (id || od) {
int idx;
filter.mark = mark;
if (action == IPROUTE_FLUSH)
- return iproute_flush(do_ipv6, filter_fn);
+ return iproute_flush(dump_family, filter_fn);
- if (!filter.cloned) {
- if (rtnl_routedump_req(&rth, do_ipv6) < 0) {
- perror("Cannot send dump request");
- return -2;
- }
- } else {
- if (rtnl_rtcache_request(&rth, do_ipv6) < 0) {
- perror("Cannot send dump request");
- return -2;
- }
+ if (rtnl_routedump_req(&rth, dump_family, iproute_dump_filter) < 0) {
+ perror("Cannot send dump request");
+ return -2;
}
new_json_obj(json);
int fib_match = 0;
int from_ok = 0;
unsigned int mark = 0;
+ bool address_found = false;
iproute_reset_filter(0);
filter.cloned = 2;
addattr_l(&req.n, sizeof(req),
RTA_DST, &addr.data, addr.bytelen);
req.r.rtm_dst_len = addr.bitlen;
+ address_found = true;
}
argc--; argv++;
}
- if (req.r.rtm_dst_len == 0) {
+ if (!address_found) {
fprintf(stderr, "need at least a destination address\n");
return -1;
}
if (req.r.rtm_family == AF_UNSPEC)
req.r.rtm_family = AF_INET;
- req.r.rtm_flags |= RTM_F_LOOKUP_TABLE;
+ /* Only IPv4 supports the RTM_F_LOOKUP_TABLE flag */
+ if (req.r.rtm_family == AF_INET)
+ req.r.rtm_flags |= RTM_F_LOOKUP_TABLE;
if (fib_match)
req.r.rtm_flags |= RTM_F_FIB_MATCH;
int len = answer->nlmsg_len;
struct rtattr *tb[RTA_MAX+1];
- if (print_route(NULL, answer, (void *)stdout) < 0) {
+ if (print_route(answer, (void *)stdout) < 0) {
fprintf(stderr, "An error :-)\n");
free(answer);
return -1;
return -2;
}
- if (print_route(NULL, answer, (void *)stdout) < 0) {
+ if (print_route(answer, (void *)stdout) < 0) {
fprintf(stderr, "An error :-)\n");
free(answer);
return -1;
return memcmp(RTA_DATA(rta1), RTA_DATA(rta2), RTA_PAYLOAD(rta1));
}
-static int restore_handler(const struct sockaddr_nl *nl,
- struct rtnl_ctrl_data *ctrl,
+static int restore_handler(struct rtnl_ctrl_data *ctrl,
struct nlmsghdr *n, void *arg)
{
struct rtmsg *r = NLMSG_DATA(n);
return 0;
}
-static int show_handler(const struct sockaddr_nl *nl,
- struct rtnl_ctrl_data *ctrl,
+static int show_handler(struct rtnl_ctrl_data *ctrl,
struct nlmsghdr *n, void *arg)
{
- print_route(nl, n, stdout);
+ print_route(n, stdout);
return 0;
}