]>
git.proxmox.com Git - mirror_iproute2.git/blob - ip/ipfou.c
2 * ipfou.c FOU (foo over UDP) support
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Tom Herbert <therbert@google.com>
17 #include <linux/fou.h>
18 #include <linux/genetlink.h>
20 #include <arpa/inet.h>
24 #include "ip_common.h"
25 #include "json_print.h"
27 static void usage(void)
30 "Usage: ip fou add port PORT { ipproto PROTO | gue } [ -6 ]\n"
31 " ip fou del port PORT [ -6 ]\n"
34 "Where: PROTO { ipproto-name | 1..255 }\n"
35 " PORT { 1..65535 }\n");
41 static struct rtnl_handle genl_rth
= { .fd
= -1 };
42 static int genl_family
= -1;
44 #define FOU_REQUEST(_req, _bufsiz, _cmd, _flags) \
45 GENL_REQUEST(_req, _bufsiz, genl_family, 0, \
46 FOU_GENL_VERSION, _cmd, _flags)
48 static int fou_parse_opt(int argc
, char **argv
, struct nlmsghdr
*n
,
56 __u8 family
= AF_INET
;
59 if (!matches(*argv
, "port")) {
62 if (get_be16(&port
, *argv
, 0) || port
== 0)
63 invarg("invalid port", *argv
);
65 } else if (!matches(*argv
, "ipproto")) {
66 struct protoent
*servptr
;
70 servptr
= getprotobyname(*argv
);
72 ipproto
= servptr
->p_proto
;
73 else if (get_u8(&ipproto
, *argv
, 0) || ipproto
== 0)
74 invarg("invalid ipproto", *argv
);
76 } else if (!matches(*argv
, "gue")) {
78 } else if (!matches(*argv
, "-6")) {
82 , "fou: unknown command \"%s\"?\n", *argv
);
90 fprintf(stderr
, "fou: missing port\n");
94 if (!ipproto_set
&& !gue_set
&& adding
) {
95 fprintf(stderr
, "fou: must set ipproto or gue\n");
99 if (ipproto_set
&& gue_set
) {
100 fprintf(stderr
, "fou: cannot set ipproto and gue\n");
104 type
= gue_set
? FOU_ENCAP_GUE
: FOU_ENCAP_DIRECT
;
106 addattr16(n
, 1024, FOU_ATTR_PORT
, port
);
107 addattr8(n
, 1024, FOU_ATTR_TYPE
, type
);
108 addattr8(n
, 1024, FOU_ATTR_AF
, family
);
111 addattr8(n
, 1024, FOU_ATTR_IPPROTO
, ipproto
);
116 static int do_add(int argc
, char **argv
)
118 FOU_REQUEST(req
, 1024, FOU_CMD_ADD
, NLM_F_REQUEST
);
120 fou_parse_opt(argc
, argv
, &req
.n
, true);
122 if (rtnl_talk(&genl_rth
, &req
.n
, NULL
) < 0)
128 static int do_del(int argc
, char **argv
)
130 FOU_REQUEST(req
, 1024, FOU_CMD_DEL
, NLM_F_REQUEST
);
132 fou_parse_opt(argc
, argv
, &req
.n
, false);
134 if (rtnl_talk(&genl_rth
, &req
.n
, NULL
) < 0)
140 static int print_fou_mapping(const struct sockaddr_nl
*who
,
141 struct nlmsghdr
*n
, void *arg
)
143 struct genlmsghdr
*ghdr
;
144 struct rtattr
*tb
[FOU_ATTR_MAX
+ 1];
145 int len
= n
->nlmsg_len
;
147 if (n
->nlmsg_type
!= genl_family
)
150 len
-= NLMSG_LENGTH(GENL_HDRLEN
);
154 ghdr
= NLMSG_DATA(n
);
155 parse_rtattr(tb
, FOU_ATTR_MAX
, (void *) ghdr
+ GENL_HDRLEN
, len
);
157 open_json_object(NULL
);
158 if (tb
[FOU_ATTR_PORT
])
159 print_uint(PRINT_ANY
, "port", "port %u",
160 ntohs(rta_getattr_u16(tb
[FOU_ATTR_PORT
])));
162 if (tb
[FOU_ATTR_TYPE
] &&
163 rta_getattr_u8(tb
[FOU_ATTR_TYPE
]) == FOU_ENCAP_GUE
)
164 print_null(PRINT_ANY
, "gue", " gue", NULL
);
165 else if (tb
[FOU_ATTR_IPPROTO
])
166 print_uint(PRINT_ANY
, "ipproto",
167 " ipproto %u", rta_getattr_u8(tb
[FOU_ATTR_IPPROTO
]));
169 if (tb
[FOU_ATTR_AF
]) {
170 __u8 family
= rta_getattr_u8(tb
[FOU_ATTR_AF
]);
172 print_string(PRINT_JSON
, "family", NULL
,
173 family_name(family
));
175 if (family
== AF_INET6
)
176 print_string(PRINT_FP
, NULL
,
179 print_string(PRINT_FP
, NULL
, "\n", NULL
);
185 static int do_show(int argc
, char **argv
)
187 FOU_REQUEST(req
, 4096, FOU_CMD_GET
, NLM_F_REQUEST
| NLM_F_DUMP
);
191 "\"ip fou show\" does not take any arguments.\n");
195 if (rtnl_send(&genl_rth
, &req
.n
, req
.n
.nlmsg_len
) < 0) {
196 perror("Cannot send show request");
201 if (rtnl_dump_filter(&genl_rth
, print_fou_mapping
, stdout
) < 0) {
202 fprintf(stderr
, "Dump terminated\n");
211 int do_ipfou(int argc
, char **argv
)
216 if (matches(*argv
, "help") == 0)
219 if (genl_init_handle(&genl_rth
, FOU_GENL_NAME
, &genl_family
))
222 if (matches(*argv
, "add") == 0)
223 return do_add(argc
-1, argv
+1);
224 if (matches(*argv
, "delete") == 0)
225 return do_del(argc
-1, argv
+1);
226 if (matches(*argv
, "show") == 0)
227 return do_show(argc
-1, argv
+1);
230 "Command \"%s\" is unknown, try \"ip fou help\".\n", *argv
);