Commit 93ae2835 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Stephen Hemminger

add support for the RTA_VIA attribute

Add support for the RTA_VIA attribute that specifies an address family
as well as an address for the next hop gateway.

To make it easy to pass this reorder inet_prefix so that it's tail
is a proper RTA_VIA attribute.
Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
parent 8e8f8de4
......@@ -50,10 +50,11 @@ extern void incomplete_command(void) __attribute__((noreturn));
typedef struct
{
__u8 family;
__u8 bytelen;
__u16 flags;
__u16 bytelen;
__s16 bitlen;
__u32 flags;
/* These next two fields match rtvia */
__u16 family;
__u32 data[8];
} inet_prefix;
......
......@@ -75,7 +75,8 @@ static void usage(void)
fprintf(stderr, " [ table TABLE_ID ] [ proto RTPROTO ]\n");
fprintf(stderr, " [ scope SCOPE ] [ metric METRIC ]\n");
fprintf(stderr, "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n");
fprintf(stderr, "NH := [ via ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n");
fprintf(stderr, "NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n");
fprintf(stderr, "FAMILY := [ inet | inet6 | ipx | dnet | bridge | link ]");
fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n");
fprintf(stderr, " [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n");
fprintf(stderr, " [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n");
......@@ -185,8 +186,15 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
(r->rtm_family != filter.msrc.family ||
(filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len)))
return 0;
if (filter.rvia.family && r->rtm_family != filter.rvia.family)
return 0;
if (filter.rvia.family) {
int family = r->rtm_family;
if (tb[RTA_VIA]) {
struct rtvia *via = RTA_DATA(tb[RTA_VIA]);
family = via->rtvia_family;
}
if (family != filter.rvia.family)
return 0;
}
if (filter.rprefsrc.family && r->rtm_family != filter.rprefsrc.family)
return 0;
......@@ -205,6 +213,12 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
via.family = r->rtm_family;
if (tb[RTA_GATEWAY])
memcpy(&via.data, RTA_DATA(tb[RTA_GATEWAY]), host_len/8);
if (tb[RTA_VIA]) {
size_t len = RTA_PAYLOAD(tb[RTA_VIA]) - 2;
struct rtvia *rtvia = RTA_DATA(tb[RTA_VIA]);
via.family = rtvia->rtvia_family;
memcpy(&via.data, rtvia->rtvia_addr, len);
}
}
if (filter.rprefsrc.bitlen>0) {
memset(&prefsrc, 0, sizeof(prefsrc));
......@@ -386,6 +400,14 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
RTA_DATA(tb[RTA_GATEWAY]),
abuf, sizeof(abuf)));
}
if (tb[RTA_VIA]) {
size_t len = RTA_PAYLOAD(tb[RTA_VIA]) - 2;
struct rtvia *via = RTA_DATA(tb[RTA_VIA]);
fprintf(fp, "via %s %s ",
family_name(via->rtvia_family),
format_host(via->rtvia_family, len, via->rtvia_addr,
abuf, sizeof(abuf)));
}
if (tb[RTA_OIF] && filter.oifmask != -1)
fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
......@@ -603,6 +625,14 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
RTA_DATA(tb[RTA_GATEWAY]),
abuf, sizeof(abuf)));
}
if (tb[RTA_VIA]) {
size_t len = RTA_PAYLOAD(tb[RTA_VIA]) - 2;
struct rtvia *via = RTA_DATA(tb[RTA_VIA]);
fprintf(fp, "via %s %s ",
family_name(via->rtvia_family),
format_host(via->rtvia_family, len, via->rtvia_addr,
abuf, sizeof(abuf)));
}
if (tb[RTA_FLOW]) {
__u32 to = rta_getattr_u32(tb[RTA_FLOW]);
__u32 from = to>>16;
......@@ -650,12 +680,23 @@ static int parse_one_nh(struct rtmsg *r, struct rtattr *rta,
while (++argv, --argc > 0) {
if (strcmp(*argv, "via") == 0) {
inet_prefix addr;
int family;
NEXT_ARG();
get_addr(&addr, *argv, r->rtm_family);
family = read_family(*argv);
if (family == AF_UNSPEC)
family = r->rtm_family;
else
NEXT_ARG();
get_addr(&addr, *argv, family);
if (r->rtm_family == AF_UNSPEC)
r->rtm_family = addr.family;
rta_addattr_l(rta, 4096, RTA_GATEWAY, &addr.data, addr.bytelen);
rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen;
if (addr.family == r->rtm_family) {
rta_addattr_l(rta, 4096, RTA_GATEWAY, &addr.data, addr.bytelen);
rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen;
} else {
rta_addattr_l(rta, 4096, RTA_VIA, &addr.family, addr.bytelen+2);
rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen+2;
}
} else if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
if ((rtnh->rtnh_ifindex = ll_name_to_index(*argv)) == 0) {
......@@ -763,12 +804,21 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen);
} else if (strcmp(*argv, "via") == 0) {
inet_prefix addr;
int family;
gw_ok = 1;
NEXT_ARG();
get_addr(&addr, *argv, req.r.rtm_family);
family = read_family(*argv);
if (family == AF_UNSPEC)
family = req.r.rtm_family;
else
NEXT_ARG();
get_addr(&addr, *argv, family);
if (req.r.rtm_family == AF_UNSPEC)
req.r.rtm_family = addr.family;
addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen);
if (addr.family == req.r.rtm_family)
addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen);
else
addattr_l(&req.n, sizeof(req), RTA_VIA, &addr.family, addr.bytelen+2);
} else if (strcmp(*argv, "from") == 0) {
inet_prefix addr;
NEXT_ARG();
......@@ -1253,8 +1303,14 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
get_unsigned(&mark, *argv, 0);
filter.markmask = -1;
} else if (strcmp(*argv, "via") == 0) {
int family;
NEXT_ARG();
get_prefix(&filter.rvia, *argv, do_ipv6);
family = read_family(*argv);
if (family == AF_UNSPEC)
family = do_ipv6;
else
NEXT_ARG();
get_prefix(&filter.rvia, *argv, family);
} else if (strcmp(*argv, "src") == 0) {
NEXT_ARG();
get_prefix(&filter.rprefsrc, *argv, do_ipv6);
......@@ -1556,6 +1612,8 @@ static int iproute_get(int argc, char **argv)
tb[RTA_OIF]->rta_type = 0;
if (tb[RTA_GATEWAY])
tb[RTA_GATEWAY]->rta_type = 0;
if (tb[RTA_VIA])
tb[RTA_VIA]->rta_type = 0;
if (!idev && tb[RTA_IIF])
tb[RTA_IIF]->rta_type = 0;
req.n.nlmsg_flags = NLM_F_REQUEST;
......
......@@ -81,12 +81,17 @@ replace " } "
.ti -8
.IR NH " := [ "
.B via
.IR ADDRESS " ] [ "
[
.IR FAMILY " ] " ADDRESS " ] [ "
.B dev
.IR STRING " ] [ "
.B weight
.IR NUMBER " ] " NHFLAGS
.ti -8
.IR FAMILY " := [ "
.BR inet " | " inet6 " | " ipx " | " dnet " | " bridge " | " link " ]"
.ti -8
.IR OPTIONS " := " FLAGS " [ "
.B mtu
......@@ -333,9 +338,10 @@ table by default.
the output device name.
.TP
.BI via " ADDRESS"
the address of the nexthop router. Actually, the sense of this field
depends on the route type. For normal
.BI via " [ FAMILY ] ADDRESS"
the address of the nexthop router, in the address family FAMILY.
Actually, the sense of this field depends on the route type. For
normal
.B unicast
routes it is either the true next hop router or, if it is a direct
route installed in BSD compatibility mode, it can be a local address
......@@ -472,7 +478,7 @@ is a complex value with its own syntax similar to the top level
argument lists:
.in +8
.BI via " ADDRESS"
.BI via " [ FAMILY ] ADDRESS"
- is the nexthop router.
.sp
......@@ -669,7 +675,7 @@ only list routes of this type.
only list routes going via this device.
.TP
.BI via " PREFIX"
.BI via " [ FAMILY ] PREFIX"
only list routes going via the nexthop routers selected by
.IR PREFIX "."
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment