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: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
parent
8e8f8de42f
commit
93ae283594
|
|
@ -50,10 +50,11 @@ extern void incomplete_command(void) __attribute__((noreturn));
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
__u8 family;
|
__u16 flags;
|
||||||
__u8 bytelen;
|
__u16 bytelen;
|
||||||
__s16 bitlen;
|
__s16 bitlen;
|
||||||
__u32 flags;
|
/* These next two fields match rtvia */
|
||||||
|
__u16 family;
|
||||||
__u32 data[8];
|
__u32 data[8];
|
||||||
} inet_prefix;
|
} inet_prefix;
|
||||||
|
|
||||||
|
|
|
||||||
76
ip/iproute.c
76
ip/iproute.c
|
|
@ -75,7 +75,8 @@ static void usage(void)
|
||||||
fprintf(stderr, " [ table TABLE_ID ] [ proto RTPROTO ]\n");
|
fprintf(stderr, " [ table TABLE_ID ] [ proto RTPROTO ]\n");
|
||||||
fprintf(stderr, " [ scope SCOPE ] [ metric METRIC ]\n");
|
fprintf(stderr, " [ scope SCOPE ] [ metric METRIC ]\n");
|
||||||
fprintf(stderr, "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\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, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n");
|
||||||
fprintf(stderr, " [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n");
|
fprintf(stderr, " [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n");
|
||||||
fprintf(stderr, " [ window NUMBER] [ cwnd NUMBER ] [ initcwnd 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 ||
|
(r->rtm_family != filter.msrc.family ||
|
||||||
(filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len)))
|
(filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len)))
|
||||||
return 0;
|
return 0;
|
||||||
if (filter.rvia.family && r->rtm_family != filter.rvia.family)
|
if (filter.rvia.family) {
|
||||||
return 0;
|
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)
|
if (filter.rprefsrc.family && r->rtm_family != filter.rprefsrc.family)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -205,6 +213,12 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
|
||||||
via.family = r->rtm_family;
|
via.family = r->rtm_family;
|
||||||
if (tb[RTA_GATEWAY])
|
if (tb[RTA_GATEWAY])
|
||||||
memcpy(&via.data, RTA_DATA(tb[RTA_GATEWAY]), host_len/8);
|
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) {
|
if (filter.rprefsrc.bitlen>0) {
|
||||||
memset(&prefsrc, 0, sizeof(prefsrc));
|
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]),
|
RTA_DATA(tb[RTA_GATEWAY]),
|
||||||
abuf, sizeof(abuf)));
|
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)
|
if (tb[RTA_OIF] && filter.oifmask != -1)
|
||||||
fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
|
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]),
|
RTA_DATA(tb[RTA_GATEWAY]),
|
||||||
abuf, sizeof(abuf)));
|
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]) {
|
if (tb[RTA_FLOW]) {
|
||||||
__u32 to = rta_getattr_u32(tb[RTA_FLOW]);
|
__u32 to = rta_getattr_u32(tb[RTA_FLOW]);
|
||||||
__u32 from = to>>16;
|
__u32 from = to>>16;
|
||||||
|
|
@ -650,12 +680,23 @@ static int parse_one_nh(struct rtmsg *r, struct rtattr *rta,
|
||||||
while (++argv, --argc > 0) {
|
while (++argv, --argc > 0) {
|
||||||
if (strcmp(*argv, "via") == 0) {
|
if (strcmp(*argv, "via") == 0) {
|
||||||
inet_prefix addr;
|
inet_prefix addr;
|
||||||
|
int family;
|
||||||
NEXT_ARG();
|
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)
|
if (r->rtm_family == AF_UNSPEC)
|
||||||
r->rtm_family = addr.family;
|
r->rtm_family = addr.family;
|
||||||
rta_addattr_l(rta, 4096, RTA_GATEWAY, &addr.data, addr.bytelen);
|
if (addr.family == r->rtm_family) {
|
||||||
rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen;
|
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) {
|
} else if (strcmp(*argv, "dev") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if ((rtnh->rtnh_ifindex = ll_name_to_index(*argv)) == 0) {
|
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);
|
addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen);
|
||||||
} else if (strcmp(*argv, "via") == 0) {
|
} else if (strcmp(*argv, "via") == 0) {
|
||||||
inet_prefix addr;
|
inet_prefix addr;
|
||||||
|
int family;
|
||||||
gw_ok = 1;
|
gw_ok = 1;
|
||||||
NEXT_ARG();
|
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)
|
if (req.r.rtm_family == AF_UNSPEC)
|
||||||
req.r.rtm_family = addr.family;
|
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) {
|
} else if (strcmp(*argv, "from") == 0) {
|
||||||
inet_prefix addr;
|
inet_prefix addr;
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
@ -1253,8 +1303,14 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
|
||||||
get_unsigned(&mark, *argv, 0);
|
get_unsigned(&mark, *argv, 0);
|
||||||
filter.markmask = -1;
|
filter.markmask = -1;
|
||||||
} else if (strcmp(*argv, "via") == 0) {
|
} else if (strcmp(*argv, "via") == 0) {
|
||||||
|
int family;
|
||||||
NEXT_ARG();
|
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) {
|
} else if (strcmp(*argv, "src") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
get_prefix(&filter.rprefsrc, *argv, do_ipv6);
|
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;
|
tb[RTA_OIF]->rta_type = 0;
|
||||||
if (tb[RTA_GATEWAY])
|
if (tb[RTA_GATEWAY])
|
||||||
tb[RTA_GATEWAY]->rta_type = 0;
|
tb[RTA_GATEWAY]->rta_type = 0;
|
||||||
|
if (tb[RTA_VIA])
|
||||||
|
tb[RTA_VIA]->rta_type = 0;
|
||||||
if (!idev && tb[RTA_IIF])
|
if (!idev && tb[RTA_IIF])
|
||||||
tb[RTA_IIF]->rta_type = 0;
|
tb[RTA_IIF]->rta_type = 0;
|
||||||
req.n.nlmsg_flags = NLM_F_REQUEST;
|
req.n.nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,17 @@ replace " } "
|
||||||
.ti -8
|
.ti -8
|
||||||
.IR NH " := [ "
|
.IR NH " := [ "
|
||||||
.B via
|
.B via
|
||||||
.IR ADDRESS " ] [ "
|
[
|
||||||
|
.IR FAMILY " ] " ADDRESS " ] [ "
|
||||||
.B dev
|
.B dev
|
||||||
.IR STRING " ] [ "
|
.IR STRING " ] [ "
|
||||||
.B weight
|
.B weight
|
||||||
.IR NUMBER " ] " NHFLAGS
|
.IR NUMBER " ] " NHFLAGS
|
||||||
|
|
||||||
|
.ti -8
|
||||||
|
.IR FAMILY " := [ "
|
||||||
|
.BR inet " | " inet6 " | " ipx " | " dnet " | " bridge " | " link " ]"
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.IR OPTIONS " := " FLAGS " [ "
|
.IR OPTIONS " := " FLAGS " [ "
|
||||||
.B mtu
|
.B mtu
|
||||||
|
|
@ -333,9 +338,10 @@ table by default.
|
||||||
the output device name.
|
the output device name.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI via " ADDRESS"
|
.BI via " [ FAMILY ] ADDRESS"
|
||||||
the address of the nexthop router. Actually, the sense of this field
|
the address of the nexthop router, in the address family FAMILY.
|
||||||
depends on the route type. For normal
|
Actually, the sense of this field depends on the route type. For
|
||||||
|
normal
|
||||||
.B unicast
|
.B unicast
|
||||||
routes it is either the true next hop router or, if it is a direct
|
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
|
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:
|
argument lists:
|
||||||
|
|
||||||
.in +8
|
.in +8
|
||||||
.BI via " ADDRESS"
|
.BI via " [ FAMILY ] ADDRESS"
|
||||||
- is the nexthop router.
|
- is the nexthop router.
|
||||||
.sp
|
.sp
|
||||||
|
|
||||||
|
|
@ -669,7 +675,7 @@ only list routes of this type.
|
||||||
only list routes going via this device.
|
only list routes going via this device.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI via " PREFIX"
|
.BI via " [ FAMILY ] PREFIX"
|
||||||
only list routes going via the nexthop routers selected by
|
only list routes going via the nexthop routers selected by
|
||||||
.IR PREFIX "."
|
.IR PREFIX "."
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue