#include "ip_common.h"
#include "tunnel.h"
-
-static void usage(void) __attribute__((noreturn));
-static void usage(void)
+static void vti6_print_help(struct link_util *lu, int argc, char **argv,
+ FILE *f)
{
- fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n");
- fprintf(stderr, " type { vti6 } [ remote ADDR ] [ local ADDR ]\n");
- fprintf(stderr, " [ [i|o]key KEY ]\n");
- fprintf(stderr, " [ dev PHYS_DEV ]\n");
- fprintf(stderr, " [ fwmark MARK ]\n");
- fprintf(stderr, "\n");
- fprintf(stderr, "Where: NAME := STRING\n");
- fprintf(stderr, " ADDR := { IPV6_ADDRESS }\n");
- fprintf(stderr, " KEY := { DOTTED_QUAD | NUMBER }\n");
- fprintf(stderr, " MARK := { 0x0..0xffffffff }\n");
- exit(-1);
+ fprintf(f,
+ "Usage: ... %-4s [ remote ADDR ]\n",
+ lu->id
+ );
+ fprintf(f,
+ " [ local ADDR ]\n"
+ " [ [i|o]key KEY ]\n"
+ " [ dev PHYS_DEV ]\n"
+ " [ fwmark MARK ]\n"
+ "\n"
+ );
+ fprintf(f,
+ "Where: ADDR := { IP%s_ADDRESS }\n"
+ " KEY := { DOTTED_QUAD | NUMBER }\n"
+ " MARK := { 0x0..0xffffffff }\n",
+ "V6"
+ );
}
static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
- struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
+ struct ifinfomsg *ifi = NLMSG_DATA(n);
struct {
struct nlmsghdr n;
struct ifinfomsg i;
.i.ifi_family = preferred_family,
.i.ifi_index = ifi->ifi_index,
};
- struct nlmsghdr *answer = NULL;
+ struct nlmsghdr *answer;
struct rtattr *tb[IFLA_MAX + 1];
struct rtattr *linkinfo[IFLA_INFO_MAX+1];
struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
- struct in6_addr saddr = IN6ADDR_ANY_INIT;
- struct in6_addr daddr = IN6ADDR_ANY_INIT;
__be32 ikey = 0;
__be32 okey = 0;
+ inet_prefix saddr, daddr;
unsigned int link = 0;
__u32 fwmark = 0;
int len;
+ inet_prefix_reset(&saddr);
+ inet_prefix_reset(&daddr);
+
if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+ const struct rtattr *rta;
+
if (rtnl_talk(&rth, &req.n, &answer) < 0) {
get_failed:
fprintf(stderr,
"Failed to get existing tunnel info.\n");
- free(answer);
return -1;
}
parse_rtattr_nested(vtiinfo, IFLA_VTI_MAX,
linkinfo[IFLA_INFO_DATA]);
+ rta = vtiinfo[IFLA_VTI_LOCAL];
+ if (rta && get_addr_rta(&saddr, rta, AF_INET6))
+ goto get_failed;
+
+ rta = vtiinfo[IFLA_VTI_REMOTE];
+ if (rta && get_addr_rta(&daddr, rta, AF_INET6))
+ goto get_failed;
+
if (vtiinfo[IFLA_VTI_IKEY])
ikey = rta_getattr_u32(vtiinfo[IFLA_VTI_IKEY]);
if (vtiinfo[IFLA_VTI_OKEY])
okey = rta_getattr_u32(vtiinfo[IFLA_VTI_OKEY]);
- if (vtiinfo[IFLA_VTI_LOCAL])
- memcpy(&saddr, RTA_DATA(vtiinfo[IFLA_VTI_LOCAL]), sizeof(saddr));
-
- if (vtiinfo[IFLA_VTI_REMOTE])
- memcpy(&daddr, RTA_DATA(vtiinfo[IFLA_VTI_REMOTE]), sizeof(daddr));
-
if (vtiinfo[IFLA_VTI_LINK])
link = rta_getattr_u8(vtiinfo[IFLA_VTI_LINK]);
NEXT_ARG();
okey = tnl_parse_key("okey", *argv);
} else if (!matches(*argv, "remote")) {
- inet_prefix addr;
-
NEXT_ARG();
- get_addr(&addr, *argv, AF_INET6);
- memcpy(&daddr, addr.data, sizeof(daddr));
+ get_addr(&daddr, *argv, AF_INET6);
} else if (!matches(*argv, "local")) {
- inet_prefix addr;
-
NEXT_ARG();
- get_addr(&addr, *argv, AF_INET6);
- memcpy(&saddr, addr.data, sizeof(saddr));
+ get_addr(&saddr, *argv, AF_INET6);
} else if (!matches(*argv, "dev")) {
NEXT_ARG();
- link = if_nametoindex(*argv);
- if (link == 0)
- exit(-1);
+ link = ll_name_to_index(*argv);
+ if (!link)
+ exit(nodev(*argv));
} else if (strcmp(*argv, "fwmark") == 0) {
NEXT_ARG();
if (get_u32(&fwmark, *argv, 0))
invarg("invalid fwmark\n", *argv);
- } else
- usage();
+ } else {
+ vti6_print_help(lu, argc, argv, stderr);
+ return -1;
+ }
argc--; argv++;
}
addattr32(n, 1024, IFLA_VTI_IKEY, ikey);
addattr32(n, 1024, IFLA_VTI_OKEY, okey);
-
- if (memcmp(&saddr, &in6addr_any, sizeof(in6addr_any)))
- addattr_l(n, 1024, IFLA_VTI_LOCAL, &saddr, sizeof(saddr));
- if (memcmp(&daddr, &in6addr_any, sizeof(in6addr_any)))
- addattr_l(n, 1024, IFLA_VTI_REMOTE, &daddr, sizeof(daddr));
+ if (is_addrtype_inet_not_unspec(&saddr))
+ addattr_l(n, 1024, IFLA_VTI_LOCAL, saddr.data, saddr.bytelen);
+ if (is_addrtype_inet_not_unspec(&daddr))
+ addattr_l(n, 1024, IFLA_VTI_REMOTE, daddr.data, daddr.bytelen);
addattr32(n, 1024, IFLA_VTI_FWMARK, fwmark);
if (link)
addattr32(n, 1024, IFLA_VTI_LINK, link);
static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
- const char *local = "any";
- const char *remote = "any";
- struct in6_addr saddr;
- struct in6_addr daddr;
- unsigned int link;
char s2[64];
if (!tb)
return;
- if (tb[IFLA_VTI_REMOTE]) {
- memcpy(&daddr, RTA_DATA(tb[IFLA_VTI_REMOTE]), sizeof(daddr));
-
- remote = format_host(AF_INET6, 16, &daddr);
- }
-
- print_string(PRINT_ANY, "remote", "remote %s ", remote);
-
- if (tb[IFLA_VTI_LOCAL]) {
- memcpy(&saddr, RTA_DATA(tb[IFLA_VTI_LOCAL]), sizeof(saddr));
-
- local = format_host(AF_INET6, 16, &saddr);
- }
-
- print_string(PRINT_ANY, "local", "local %s ", local);
+ tnl_print_endpoint("remote", tb[IFLA_VTI_REMOTE], AF_INET6);
+ tnl_print_endpoint("local", tb[IFLA_VTI_LOCAL], AF_INET6);
- if (tb[IFLA_VTI_LINK] && (link = rta_getattr_u32(tb[IFLA_VTI_LINK]))) {
- const char *n = if_indextoname(link, s2);
+ if (tb[IFLA_VTI_LINK]) {
+ __u32 link = rta_getattr_u32(tb[IFLA_VTI_LINK]);
- if (n)
- print_string(PRINT_ANY, "link", "dev %s ", n);
- else
- print_uint(PRINT_ANY, "link_index", "dev %u ", link);
+ if (link) {
+ print_string(PRINT_ANY, "link", "dev %s ",
+ ll_index_to_name(link));
+ }
}
if (tb[IFLA_VTI_IKEY]) {
- inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_IKEY]), s2, sizeof(s2));
- print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
+ struct rtattr *rta = tb[IFLA_VTI_IKEY];
+ __u32 key = rta_getattr_u32(rta);
+
+ if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2)))
+ print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
}
if (tb[IFLA_VTI_OKEY]) {
- inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_OKEY]), s2, sizeof(s2));
- print_string(PRINT_ANY, "okey", "okey %s ", s2);
+ struct rtattr *rta = tb[IFLA_VTI_OKEY];
+ __u32 key = rta_getattr_u32(rta);
+
+ if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2)))
+ print_string(PRINT_ANY, "okey", "okey %s ", s2);
}
if (tb[IFLA_VTI_FWMARK]) {
__u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]);
if (fwmark) {
- snprintf(s2, sizeof(s2), "0x%x", fwmark);
-
- print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
+ print_0xhex(PRINT_ANY,
+ "fwmark", "fwmark %#llx ", fwmark);
}
}
}
.maxattr = IFLA_VTI_MAX,
.parse_opt = vti6_parse_opt,
.print_opt = vti6_print_opt,
+ .print_help = vti6_print_help,
};