#include "ip_common.h"
#include "tunnel.h"
-
-static void print_usage(FILE *f)
-{
- fprintf(f, "Usage: ip link { add | set | change | replace | del } NAME\n");
- fprintf(f, " type { vti } [ remote ADDR ] [ local ADDR ]\n");
- fprintf(f, " [ [i|o]key KEY ]\n");
- fprintf(f, " [ dev PHYS_DEV ]\n");
- fprintf(f, "\n");
- fprintf(f, "Where: NAME := STRING\n");
- fprintf(f, " ADDR := { IP_ADDRESS }\n");
- fprintf(f, " KEY := { DOTTED_QUAD | NUMBER }\n");
-}
-
-static void usage(void) __attribute__((noreturn));
-static void usage(void)
+static void vti_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
{
- print_usage(stderr);
- 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",
+ ""
+ );
}
static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
+ struct ifinfomsg *ifi = NLMSG_DATA(n);
struct {
struct nlmsghdr n;
struct ifinfomsg i;
- char buf[1024];
- } req;
- struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
+ } req = {
+ .n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
+ .n.nlmsg_flags = NLM_F_REQUEST,
+ .n.nlmsg_type = RTM_GETLINK,
+ .i.ifi_family = preferred_family,
+ .i.ifi_index = ifi->ifi_index,
+ };
+ struct nlmsghdr *answer;
struct rtattr *tb[IFLA_MAX + 1];
struct rtattr *linkinfo[IFLA_INFO_MAX+1];
struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
- unsigned ikey = 0;
- unsigned okey = 0;
- unsigned saddr = 0;
- unsigned daddr = 0;
- unsigned link = 0;
+ __be32 ikey = 0;
+ __be32 okey = 0;
+ inet_prefix saddr, daddr;
+ unsigned int link = 0;
+ __u32 fwmark = 0;
int len;
- if (!(n->nlmsg_flags & NLM_F_CREATE)) {
- memset(&req, 0, sizeof(req));
+ inet_prefix_reset(&saddr);
+ inet_prefix_reset(&daddr);
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- req.n.nlmsg_type = RTM_GETLINK;
- req.i.ifi_family = preferred_family;
- req.i.ifi_index = ifi->ifi_index;
+ if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+ const struct rtattr *rta;
- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
+ if (rtnl_talk(&rth, &req.n, &answer) < 0) {
get_failed:
fprintf(stderr,
"Failed to get existing tunnel info.\n");
return -1;
}
- len = req.n.nlmsg_len;
+ len = answer->nlmsg_len;
len -= NLMSG_LENGTH(sizeof(*ifi));
if (len < 0)
goto get_failed;
- parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
if (!tb[IFLA_LINKINFO])
goto get_failed;
parse_rtattr_nested(vtiinfo, IFLA_VTI_MAX,
linkinfo[IFLA_INFO_DATA]);
+ rta = vtiinfo[IFLA_VTI_LOCAL];
+ if (rta && get_addr_rta(&saddr, rta, AF_INET))
+ goto get_failed;
+
+ rta = vtiinfo[IFLA_VTI_REMOTE];
+ if (rta && get_addr_rta(&daddr, rta, AF_INET))
+ goto get_failed;
+
if (vtiinfo[IFLA_VTI_IKEY])
- ikey = *(__u32 *)RTA_DATA(vtiinfo[IFLA_VTI_IKEY]);
+ ikey = rta_getattr_u32(vtiinfo[IFLA_VTI_IKEY]);
if (vtiinfo[IFLA_VTI_OKEY])
- okey = *(__u32 *)RTA_DATA(vtiinfo[IFLA_VTI_OKEY]);
+ okey = rta_getattr_u32(vtiinfo[IFLA_VTI_OKEY]);
- if (vtiinfo[IFLA_VTI_LOCAL])
- saddr = *(__u32 *)RTA_DATA(vtiinfo[IFLA_VTI_LOCAL]);
+ if (vtiinfo[IFLA_VTI_LINK])
+ link = rta_getattr_u8(vtiinfo[IFLA_VTI_LINK]);
- if (vtiinfo[IFLA_VTI_REMOTE])
- daddr = *(__u32 *)RTA_DATA(vtiinfo[IFLA_VTI_REMOTE]);
+ if (vtiinfo[IFLA_VTI_FWMARK])
+ fwmark = rta_getattr_u32(vtiinfo[IFLA_VTI_FWMARK]);
- if (vtiinfo[IFLA_VTI_LINK])
- link = *(__u8 *)RTA_DATA(vtiinfo[IFLA_VTI_LINK]);
+ free(answer);
}
while (argc > 0) {
if (!matches(*argv, "key")) {
- unsigned uval;
-
NEXT_ARG();
- if (strchr(*argv, '.'))
- uval = get_addr32(*argv);
- else {
- if (get_unsigned(&uval, *argv, 0) < 0) {
- fprintf(stderr,
- "Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv);
- exit(-1);
- }
- uval = htonl(uval);
- }
-
- ikey = okey = uval;
+ ikey = okey = tnl_parse_key("key", *argv);
} else if (!matches(*argv, "ikey")) {
- unsigned uval;
-
NEXT_ARG();
- if (strchr(*argv, '.'))
- uval = get_addr32(*argv);
- else {
- if (get_unsigned(&uval, *argv, 0) < 0) {
- fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv);
- exit(-1);
- }
- uval = htonl(uval);
- }
- ikey = uval;
+ ikey = tnl_parse_key("ikey", *argv);
} else if (!matches(*argv, "okey")) {
- unsigned uval;
-
NEXT_ARG();
- if (strchr(*argv, '.'))
- uval = get_addr32(*argv);
- else {
- if (get_unsigned(&uval, *argv, 0) < 0) {
- fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv);
- exit(-1);
- }
- uval = htonl(uval);
- }
- okey = uval;
+ okey = tnl_parse_key("okey", *argv);
} else if (!matches(*argv, "remote")) {
NEXT_ARG();
- if (!strcmp(*argv, "any")) {
- fprintf(stderr, "invalid value for \"remote\": \"%s\"\n", *argv);
- exit(-1);
- } else {
- daddr = get_addr32(*argv);
- }
+ get_addr(&daddr, *argv, AF_INET);
} else if (!matches(*argv, "local")) {
NEXT_ARG();
- if (!strcmp(*argv, "any")) {
- fprintf(stderr, "invalid value for \"local\": \"%s\"\n", *argv);
- exit(-1);
- } else {
- saddr = get_addr32(*argv);
- }
+ get_addr(&saddr, *argv, AF_INET);
} else if (!matches(*argv, "dev")) {
NEXT_ARG();
- link = if_nametoindex(*argv);
- if (link == 0) {
- fprintf(stderr, "Cannot find device \"%s\"\n",
- *argv);
- exit(-1);
- }
- } else
- usage();
+ 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 {
+ vti_print_help(lu, argc, argv, stderr);
+ return -1;
+ }
argc--; argv++;
}
addattr32(n, 1024, IFLA_VTI_IKEY, ikey);
addattr32(n, 1024, IFLA_VTI_OKEY, okey);
- addattr_l(n, 1024, IFLA_VTI_LOCAL, &saddr, 4);
- addattr_l(n, 1024, IFLA_VTI_REMOTE, &daddr, 4);
+ 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 vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
- char s1[1024];
char s2[64];
- const char *local = "any";
- const char *remote = "any";
if (!tb)
return;
- if (tb[IFLA_VTI_REMOTE]) {
- unsigned addr = *(__u32 *)RTA_DATA(tb[IFLA_VTI_REMOTE]);
+ tnl_print_endpoint("remote", tb[IFLA_VTI_REMOTE], AF_INET);
+ tnl_print_endpoint("local", tb[IFLA_VTI_LOCAL], AF_INET);
- if (addr)
- remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
- }
+ if (tb[IFLA_VTI_LINK]) {
+ __u32 link = rta_getattr_u32(tb[IFLA_VTI_LINK]);
- fprintf(f, "remote %s ", remote);
+ if (link) {
+ print_string(PRINT_ANY, "link", "dev %s ",
+ ll_index_to_name(link));
+ }
+ }
- if (tb[IFLA_VTI_LOCAL]) {
- unsigned addr = *(__u32 *)RTA_DATA(tb[IFLA_VTI_LOCAL]);
+ if (tb[IFLA_VTI_IKEY]) {
+ struct rtattr *rta = tb[IFLA_VTI_IKEY];
+ __u32 key = rta_getattr_u32(rta);
- if (addr)
- local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
+ if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2)))
+ print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
}
- fprintf(f, "local %s ", local);
-
- if (tb[IFLA_VTI_LINK] && *(__u32 *)RTA_DATA(tb[IFLA_VTI_LINK])) {
- unsigned link = *(__u32 *)RTA_DATA(tb[IFLA_VTI_LINK]);
- const char *n = if_indextoname(link, s2);
+ if (tb[IFLA_VTI_OKEY]) {
+ struct rtattr *rta = tb[IFLA_VTI_OKEY];
+ __u32 key = rta_getattr_u32(rta);
- if (n)
- fprintf(f, "dev %s ", n);
- else
- fprintf(f, "dev %u ", link);
+ if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2)))
+ print_string(PRINT_ANY, "okey", "okey %s ", s2);
}
- if (tb[IFLA_VTI_IKEY]) {
- inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_IKEY]), s2, sizeof(s2));
- fprintf(f, "ikey %s ", s2);
- }
+ if (tb[IFLA_VTI_FWMARK]) {
+ __u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]);
- if (tb[IFLA_VTI_OKEY]) {
- inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_OKEY]), s2, sizeof(s2));
- fprintf(f, "okey %s ", s2);
+ if (fwmark) {
+ print_0xhex(PRINT_ANY,
+ "fwmark", "fwmark 0x%x ", fwmark);
+ }
}
}
-static void vti_print_help(struct link_util *lu, int argc, char **argv,
- FILE *f)
-{
- print_usage(f);
-}
-
struct link_util vti_link_util = {
.id = "vti",
.maxattr = IFLA_VTI_MAX,