]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - ip/ipfou.c
iproute: Set ip/ip6 lwtunnel flags
[mirror_iproute2.git] / ip / ipfou.c
index 0b83c277c86086ab1d7dc6057fece3bd6b49ef23..346522ddb7f7fa19d58d3cc69e047cd5f4ccdfc3 100644 (file)
 #include "libgenl.h"
 #include "utils.h"
 #include "ip_common.h"
+#include "json_print.h"
 
 static void usage(void)
 {
-       fprintf(stderr, "Usage: ip fou add port PORT { ipproto PROTO  | gue }\n");
-       fprintf(stderr, "       ip fou del port PORT\n");
-       fprintf(stderr, "\n");
-       fprintf(stderr, "Where: PROTO { ipproto-name | 1..255 }\n");
-       fprintf(stderr, "       PORT { 1..65535 }\n");
+       fprintf(stderr,
+               "Usage: ip fou add port PORT { ipproto PROTO  | gue } [ -6 ]\n"
+               "       ip fou del port PORT [ -6 ]\n"
+               "       ip fou show\n"
+               "\n"
+               "Where: PROTO { ipproto-name | 1..255 }\n"
+               "       PORT { 1..65535 }\n");
 
        exit(-1);
 }
@@ -50,14 +53,14 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n,
        __u8 ipproto, type;
        bool gue_set = false;
        int ipproto_set = 0;
+       __u8 family = AF_INET;
 
        while (argc > 0) {
                if (!matches(*argv, "port")) {
                        NEXT_ARG();
 
-                       if (get_u16(&port, *argv, 0) || port == 0)
+                       if (get_be16(&port, *argv, 0) || port == 0)
                                invarg("invalid port", *argv);
-                       port = htons(port);
                        port_set = 1;
                } else if (!matches(*argv, "ipproto")) {
                        struct protoent *servptr;
@@ -72,8 +75,11 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n,
                        ipproto_set = 1;
                } else if (!matches(*argv, "gue")) {
                        gue_set = true;
+               } else if (!matches(*argv, "-6")) {
+                       family = AF_INET6;
                } else {
-                       fprintf(stderr, "fou: unknown command \"%s\"?\n", *argv);
+                       fprintf(stderr
+                               , "fou: unknown command \"%s\"?\n", *argv);
                        usage();
                        return -1;
                }
@@ -99,6 +105,7 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n,
 
        addattr16(n, 1024, FOU_ATTR_PORT, port);
        addattr8(n, 1024, FOU_ATTR_TYPE, type);
+       addattr8(n, 1024, FOU_ATTR_AF, family);
 
        if (ipproto_set)
                addattr8(n, 1024, FOU_ATTR_IPPROTO, ipproto);
@@ -112,7 +119,7 @@ static int do_add(int argc, char **argv)
 
        fou_parse_opt(argc, argv, &req.n, true);
 
-       if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
+       if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
                return -2;
 
        return 0;
@@ -124,36 +131,101 @@ static int do_del(int argc, char **argv)
 
        fou_parse_opt(argc, argv, &req.n, false);
 
-       if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
+       if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
                return -2;
 
        return 0;
 }
 
-int do_ipfou(int argc, char **argv)
+static int print_fou_mapping(struct nlmsghdr *n, void *arg)
 {
-       if (genl_family < 0) {
-               if (rtnl_open_byproto(&genl_rth, 0, NETLINK_GENERIC) < 0) {
-                       fprintf(stderr, "Cannot open generic netlink socket\n");
-                       exit(1);
-               }
+       struct genlmsghdr *ghdr;
+       struct rtattr *tb[FOU_ATTR_MAX + 1];
+       int len = n->nlmsg_len;
+
+       if (n->nlmsg_type != genl_family)
+               return 0;
+
+       len -= NLMSG_LENGTH(GENL_HDRLEN);
+       if (len < 0)
+               return -1;
+
+       ghdr = NLMSG_DATA(n);
+       parse_rtattr(tb, FOU_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len);
+
+       open_json_object(NULL);
+       if (tb[FOU_ATTR_PORT])
+               print_uint(PRINT_ANY, "port", "port %u",
+                          ntohs(rta_getattr_u16(tb[FOU_ATTR_PORT])));
+
+       if (tb[FOU_ATTR_TYPE] &&
+           rta_getattr_u8(tb[FOU_ATTR_TYPE]) == FOU_ENCAP_GUE)
+               print_null(PRINT_ANY, "gue", " gue", NULL);
+       else if (tb[FOU_ATTR_IPPROTO])
+               print_uint(PRINT_ANY, "ipproto",
+                          " ipproto %u", rta_getattr_u8(tb[FOU_ATTR_IPPROTO]));
+
+       if (tb[FOU_ATTR_AF]) {
+               __u8 family = rta_getattr_u8(tb[FOU_ATTR_AF]);
+
+               print_string(PRINT_JSON, "family", NULL,
+                            family_name(family));
+
+               if (family == AF_INET6)
+                       print_string(PRINT_FP, NULL,
+                                    " -6", NULL);
+       }
+       print_string(PRINT_FP, NULL, "\n", NULL);
+       close_json_object();
+
+       return 0;
+}
+
+static int do_show(int argc, char **argv)
+{
+       FOU_REQUEST(req, 4096, FOU_CMD_GET, NLM_F_REQUEST | NLM_F_DUMP);
 
-               genl_family = genl_resolve_family(&genl_rth, FOU_GENL_NAME);
-               if (genl_family < 0)
-                       exit(1);
+       if (argc > 0) {
+               fprintf(stderr,
+                       "\"ip fou show\" does not take any arguments.\n");
+               return -1;
+       }
+
+       if (rtnl_send(&genl_rth, &req.n, req.n.nlmsg_len) < 0) {
+               perror("Cannot send show request");
+               exit(1);
+       }
+
+       new_json_obj(json);
+       if (rtnl_dump_filter(&genl_rth, print_fou_mapping, stdout) < 0) {
+               fprintf(stderr, "Dump terminated\n");
+               return 1;
        }
+       delete_json_obj();
+       fflush(stdout);
 
+       return 0;
+}
+
+int do_ipfou(int argc, char **argv)
+{
        if (argc < 1)
                usage();
 
+       if (matches(*argv, "help") == 0)
+               usage();
+
+       if (genl_init_handle(&genl_rth, FOU_GENL_NAME, &genl_family))
+               exit(1);
+
        if (matches(*argv, "add") == 0)
                return do_add(argc-1, argv+1);
        if (matches(*argv, "delete") == 0)
                return do_del(argc-1, argv+1);
-       if (matches(*argv, "help") == 0)
-               usage();
+       if (matches(*argv, "show") == 0)
+               return do_show(argc-1, argv+1);
 
-       fprintf(stderr, "Command \"%s\" is unknown, try \"ip fou help\".\n", *argv);
+       fprintf(stderr,
+               "Command \"%s\" is unknown, try \"ip fou help\".\n", *argv);
        exit(-1);
 }
-