@@ -303,6 +303,10 @@ enum rtattr_type_t {
RTA_TABLE,
RTA_MARK,
RTA_MFC_STATS,
+ RTA_VIA,
+ RTA_NEWDST,
+ RTA_PREF,
+ RTA_GATEWAY6,
__RTA_MAX
};
@@ -384,6 +384,15 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
RTA_DATA(tb[RTA_GATEWAY]),
abuf, sizeof(abuf)));
}
+
+ if (tb[RTA_GATEWAY6] && filter.rvia.bitlen != host_len) {
+ fprintf(fp, "via %s ",
+ format_host(AF_INET6,
+ RTA_PAYLOAD(tb[RTA_GATEWAY6]),
+ RTA_DATA(tb[RTA_GATEWAY6]),
+ abuf, sizeof(abuf)));
+ }
+
if (tb[RTA_OIF] && filter.oifmask != -1)
fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
@@ -647,7 +656,7 @@ static int parse_one_nh(struct rtmsg *r, struct rtattr *rta,
inet_prefix addr;
NEXT_ARG();
get_addr(&addr, *argv, r->rtm_family);
- if (r->rtm_family == AF_UNSPEC)
+ if (addr.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;
@@ -761,9 +770,12 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
gw_ok = 1;
NEXT_ARG();
get_addr(&addr, *argv, req.r.rtm_family);
- if (req.r.rtm_family == AF_UNSPEC)
+ if (addr.family == AF_UNSPEC)
req.r.rtm_family = addr.family;
- addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen);
+ if (addr.family == AF_INET)
+ addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen);
+ else if (addr.family == AF_INET6)
+ addattr_l(&req.n, sizeof(req), RTA_GATEWAY6, &addr.data, addr.bytelen);
} else if (strcmp(*argv, "from") == 0) {
inet_prefix addr;
NEXT_ARG();
@@ -399,7 +399,7 @@ int get_addr_1(inet_prefix *addr, const char *name, int family)
if (strchr(name, ':')) {
addr->family = AF_INET6;
- if (family != AF_UNSPEC && family != AF_INET6)
+ if (family != AF_UNSPEC && family != AF_INET6 && family != AF_INET)
return -1;
if (inet_pton(AF_INET6, name, addr->data) <= 0)
return -1;
@@ -712,6 +712,8 @@ static const char *resolve_address(const void *addr, int len, int af)
const char *format_host(int af, int len, const void *addr,
char *buf, int buflen)
{
+ if (af == AF_INET && len == 16)
+ af = AF_INET6;
#ifdef RESOLVE_HOSTNAMES
if (resolve_hosts) {
const char *n;
This will allow a user to run a command like this: $ ip route add 20.0.0.0/24 via 2100::2 dev p7p1 so that an IPv6 network can be used as a carrier for IPv4 traffic. This is extremely useful in many datecenter environments especially where autoconfiguration of IPv6 helps minimize the need to configure invdividual addresses on each interface. This feature does not encompass all that is needed to support RFC-5549, but this demonstrates the netlink infrastructure needed to correctly enable the kernel infrastructure. For more informtion the full RFC is here: http://www.ietf.org/rfc/rfc5549.txt. Signed-off-by: Andy Gospodarek <gospo@cumulusnetworks.com> --- include/linux/rtnetlink.h | 4 ++++ ip/iproute.c | 18 +++++++++++++++--- lib/utils.c | 4 +++- 3 files changed, 22 insertions(+), 4 deletions(-)