mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-10-19 19:35:21 +00:00
ip fou: Support binding FOU ports
This patch adds support for binding FOU ports using iproute2. Kernel-support was added in 1713cb37bf67 ("fou: Support binding FoU socket"). The parse function now handles new arguments for setting the binding-related attributes, while the print function writes the new attributes if they are set. Also, the man page has been updated. v2->v3: * Remove redundant ll_init_map()-calls (thanks David Ahern). v1->v2 (all changes suggested by David Ahern): * Fix reverse Christmas tree ordering. * Remove redundant peer_port_set-variable, it is enough to check peer_port. * Add proper error handling of invalid local/peer addresses. * Use interface name and not index. * Remove updating fou-header file, it is already done. Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com> Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
parent
90306a1440
commit
112112b8eb
135
ip/ipfou.c
135
ip/ipfou.c
@ -28,11 +28,16 @@ static void usage(void)
|
|||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: ip fou add port PORT { ipproto PROTO | gue } [ -6 ]\n"
|
"Usage: ip fou add port PORT { ipproto PROTO | gue } [ -6 ]\n"
|
||||||
" ip fou del port PORT [ -6 ]\n"
|
" [ local IFADDR ] [ peer IFADDR ]\n"
|
||||||
|
" [ peer_port PORT ] [ dev IFNAME ]\n"
|
||||||
|
" ip fou del port PORT [ -6 ] [ local IFADDR ]\n"
|
||||||
|
" [ peer IFADDR ] [ peer_port PORT ]\n"
|
||||||
|
" [ dev IFNAME ]\n"
|
||||||
" ip fou show\n"
|
" ip fou show\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Where: PROTO { ipproto-name | 1..255 }\n"
|
"Where: PROTO { ipproto-name | 1..255 }\n"
|
||||||
" PORT { 1..65535 }\n");
|
" PORT { 1..65535 }\n"
|
||||||
|
" IFADDR { addr }\n");
|
||||||
|
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
@ -48,12 +53,14 @@ static int genl_family = -1;
|
|||||||
static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n,
|
static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n,
|
||||||
bool adding)
|
bool adding)
|
||||||
{
|
{
|
||||||
__u16 port;
|
const char *local = NULL, *peer = NULL;
|
||||||
int port_set = 0;
|
__u16 port, peer_port = 0;
|
||||||
__u8 ipproto, type;
|
__u8 family = AF_INET;
|
||||||
bool gue_set = false;
|
bool gue_set = false;
|
||||||
int ipproto_set = 0;
|
int ipproto_set = 0;
|
||||||
__u8 family = AF_INET;
|
__u8 ipproto, type;
|
||||||
|
int port_set = 0;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (!matches(*argv, "port")) {
|
if (!matches(*argv, "port")) {
|
||||||
@ -77,6 +84,37 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n,
|
|||||||
gue_set = true;
|
gue_set = true;
|
||||||
} else if (!matches(*argv, "-6")) {
|
} else if (!matches(*argv, "-6")) {
|
||||||
family = AF_INET6;
|
family = AF_INET6;
|
||||||
|
} else if (!matches(*argv, "local")) {
|
||||||
|
NEXT_ARG();
|
||||||
|
|
||||||
|
local = *argv;
|
||||||
|
} else if (!matches(*argv, "peer")) {
|
||||||
|
NEXT_ARG();
|
||||||
|
|
||||||
|
peer = *argv;
|
||||||
|
} else if (!matches(*argv, "peer_port")) {
|
||||||
|
NEXT_ARG();
|
||||||
|
|
||||||
|
if (get_be16(&peer_port, *argv, 0) || peer_port == 0)
|
||||||
|
invarg("invalid peer port", *argv);
|
||||||
|
} else if (!matches(*argv, "dev")) {
|
||||||
|
const char *ifname;
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
|
||||||
|
ifname = *argv;
|
||||||
|
|
||||||
|
if (check_ifname(ifname)) {
|
||||||
|
fprintf(stderr, "fou: invalid device name\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
index = ll_name_to_index(ifname);
|
||||||
|
|
||||||
|
if (!index) {
|
||||||
|
fprintf(stderr, "fou: unknown device name\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr
|
fprintf(stderr
|
||||||
, "fou: unknown command \"%s\"?\n", *argv);
|
, "fou: unknown command \"%s\"?\n", *argv);
|
||||||
@ -101,6 +139,11 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((peer_port && !peer) || (peer && !peer_port)) {
|
||||||
|
fprintf(stderr, "fou: both peer and peer port must be set\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
type = gue_set ? FOU_ENCAP_GUE : FOU_ENCAP_DIRECT;
|
type = gue_set ? FOU_ENCAP_GUE : FOU_ENCAP_DIRECT;
|
||||||
|
|
||||||
addattr16(n, 1024, FOU_ATTR_PORT, port);
|
addattr16(n, 1024, FOU_ATTR_PORT, port);
|
||||||
@ -110,6 +153,38 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n,
|
|||||||
if (ipproto_set)
|
if (ipproto_set)
|
||||||
addattr8(n, 1024, FOU_ATTR_IPPROTO, ipproto);
|
addattr8(n, 1024, FOU_ATTR_IPPROTO, ipproto);
|
||||||
|
|
||||||
|
if (local) {
|
||||||
|
inet_prefix local_addr;
|
||||||
|
__u8 attr_type = family == AF_INET ? FOU_ATTR_LOCAL_V4 :
|
||||||
|
FOU_ATTR_LOCAL_V6;
|
||||||
|
|
||||||
|
if (get_addr(&local_addr, local, family)) {
|
||||||
|
fprintf(stderr, "fou: parsing local address failed\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
addattr_l(n, 1024, attr_type, &local_addr.data,
|
||||||
|
local_addr.bytelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peer) {
|
||||||
|
inet_prefix peer_addr;
|
||||||
|
__u8 attr_type = family == AF_INET ? FOU_ATTR_PEER_V4 :
|
||||||
|
FOU_ATTR_PEER_V6;
|
||||||
|
|
||||||
|
if (get_addr(&peer_addr, peer, family)) {
|
||||||
|
fprintf(stderr, "fou: parsing peer address failed\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
addattr_l(n, 1024, attr_type, &peer_addr.data,
|
||||||
|
peer_addr.bytelen);
|
||||||
|
|
||||||
|
if (peer_port)
|
||||||
|
addattr16(n, 1024, FOU_ATTR_PEER_PORT, peer_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index)
|
||||||
|
addattr32(n, 1024, FOU_ATTR_IFINDEX, index);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,8 +214,10 @@ static int do_del(int argc, char **argv)
|
|||||||
|
|
||||||
static int print_fou_mapping(struct nlmsghdr *n, void *arg)
|
static int print_fou_mapping(struct nlmsghdr *n, void *arg)
|
||||||
{
|
{
|
||||||
struct genlmsghdr *ghdr;
|
__u8 family = AF_INET, local_attr_type, peer_attr_type, byte_len;
|
||||||
struct rtattr *tb[FOU_ATTR_MAX + 1];
|
struct rtattr *tb[FOU_ATTR_MAX + 1];
|
||||||
|
__u8 empty_buf[16] = {0};
|
||||||
|
struct genlmsghdr *ghdr;
|
||||||
int len = n->nlmsg_len;
|
int len = n->nlmsg_len;
|
||||||
|
|
||||||
if (n->nlmsg_type != genl_family)
|
if (n->nlmsg_type != genl_family)
|
||||||
@ -166,7 +243,7 @@ static int print_fou_mapping(struct nlmsghdr *n, void *arg)
|
|||||||
" ipproto %u", rta_getattr_u8(tb[FOU_ATTR_IPPROTO]));
|
" ipproto %u", rta_getattr_u8(tb[FOU_ATTR_IPPROTO]));
|
||||||
|
|
||||||
if (tb[FOU_ATTR_AF]) {
|
if (tb[FOU_ATTR_AF]) {
|
||||||
__u8 family = rta_getattr_u8(tb[FOU_ATTR_AF]);
|
family = rta_getattr_u8(tb[FOU_ATTR_AF]);
|
||||||
|
|
||||||
print_string(PRINT_JSON, "family", NULL,
|
print_string(PRINT_JSON, "family", NULL,
|
||||||
family_name(family));
|
family_name(family));
|
||||||
@ -175,6 +252,48 @@ static int print_fou_mapping(struct nlmsghdr *n, void *arg)
|
|||||||
print_string(PRINT_FP, NULL,
|
print_string(PRINT_FP, NULL,
|
||||||
" -6", NULL);
|
" -6", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local_attr_type = family == AF_INET ? FOU_ATTR_LOCAL_V4 :
|
||||||
|
FOU_ATTR_LOCAL_V6;
|
||||||
|
peer_attr_type = family == AF_INET ? FOU_ATTR_PEER_V4 :
|
||||||
|
FOU_ATTR_PEER_V6;
|
||||||
|
byte_len = af_bit_len(family) / 8;
|
||||||
|
|
||||||
|
if (tb[local_attr_type] && memcmp(RTA_DATA(tb[local_attr_type]),
|
||||||
|
empty_buf, byte_len)) {
|
||||||
|
print_string(PRINT_ANY, "local", " local %s",
|
||||||
|
format_host_rta(family, tb[local_attr_type]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[peer_attr_type] && memcmp(RTA_DATA(tb[peer_attr_type]),
|
||||||
|
empty_buf, byte_len)) {
|
||||||
|
print_string(PRINT_ANY, "peer", " peer %s",
|
||||||
|
format_host_rta(family, tb[peer_attr_type]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[FOU_ATTR_PEER_PORT]) {
|
||||||
|
__u16 p_port = ntohs(rta_getattr_u16(tb[FOU_ATTR_PEER_PORT]));
|
||||||
|
|
||||||
|
if (p_port)
|
||||||
|
print_uint(PRINT_ANY, "peer_port", " peer_port %u",
|
||||||
|
p_port);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[FOU_ATTR_IFINDEX]) {
|
||||||
|
int index = rta_getattr_s32(tb[FOU_ATTR_IFINDEX]);
|
||||||
|
|
||||||
|
if (index) {
|
||||||
|
const char *ifname;
|
||||||
|
|
||||||
|
ifname = ll_index_to_name(index);
|
||||||
|
|
||||||
|
if (ifname)
|
||||||
|
print_string(PRINT_ANY, "dev", " dev %s",
|
||||||
|
ifname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
print_string(PRINT_FP, NULL, "\n", NULL);
|
print_string(PRINT_FP, NULL, "\n", NULL);
|
||||||
close_json_object();
|
close_json_object();
|
||||||
|
|
||||||
|
@ -24,11 +24,43 @@ ip-gue \- Generic UDP Encapsulation receive port configuration
|
|||||||
.B ipproto
|
.B ipproto
|
||||||
.IR PROTO
|
.IR PROTO
|
||||||
.RB " }"
|
.RB " }"
|
||||||
|
.RB "[ "
|
||||||
|
.B local
|
||||||
|
.IR IFADDR
|
||||||
|
.RB " ]"
|
||||||
|
.RB "[ "
|
||||||
|
.B peer
|
||||||
|
.IR IFADDR
|
||||||
|
.RB " ]"
|
||||||
|
.RB "[ "
|
||||||
|
.B peer_port
|
||||||
|
.IR PORT
|
||||||
|
.RB " ]"
|
||||||
|
.RB "[ "
|
||||||
|
.B dev
|
||||||
|
.IR IFNAME
|
||||||
|
.RB " ]"
|
||||||
.br
|
.br
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "ip fou del"
|
.BR "ip fou del"
|
||||||
.B port
|
.B port
|
||||||
.IR PORT
|
.IR PORT
|
||||||
|
.RB "[ "
|
||||||
|
.B local
|
||||||
|
.IR IFADDR
|
||||||
|
.RB " ]"
|
||||||
|
.RB "[ "
|
||||||
|
.B peer
|
||||||
|
.IR IFADDR
|
||||||
|
.RB " ]"
|
||||||
|
.RB "[ "
|
||||||
|
.B peer_port
|
||||||
|
.IR PORT
|
||||||
|
.RB " ]"
|
||||||
|
.RB "[ "
|
||||||
|
.B dev
|
||||||
|
.IR IFNAME
|
||||||
|
.RB " ]"
|
||||||
.br
|
.br
|
||||||
.ti -8
|
.ti -8
|
||||||
.B ip fou show
|
.B ip fou show
|
||||||
@ -50,11 +82,22 @@ When creating a FOU or GUE receive port, the port number is specified in
|
|||||||
.I PORT
|
.I PORT
|
||||||
argument. If FOU is used, the IP protocol number associated with the port is specified in
|
argument. If FOU is used, the IP protocol number associated with the port is specified in
|
||||||
.I PROTO
|
.I PROTO
|
||||||
|
argument. You can bind a port to a local address/interface, by specifying the
|
||||||
|
address in the local
|
||||||
|
.I IFADDR
|
||||||
|
argument or the device in the
|
||||||
|
.I IFNAME
|
||||||
|
argument. If you would like to connect the port, you can specify the peer
|
||||||
|
address in the peer
|
||||||
|
.I IFADDR
|
||||||
|
argument and peer port in the peer_port
|
||||||
|
.I PORT
|
||||||
argument.
|
argument.
|
||||||
.PP
|
.PP
|
||||||
A FOU or GUE receive port is deleted by specifying
|
A FOU or GUE receive port is deleted by specifying
|
||||||
.I PORT
|
.I PORT
|
||||||
in the delete command.
|
in the delete command, as well as local address/interface or peer address/port
|
||||||
|
(if set).
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
.PP
|
.PP
|
||||||
.SS Configure a FOU receive port for GRE bound to 7777
|
.SS Configure a FOU receive port for GRE bound to 7777
|
||||||
@ -72,6 +115,10 @@ in the delete command.
|
|||||||
.SS Delete the GUE receive port bound to 9999
|
.SS Delete the GUE receive port bound to 9999
|
||||||
.nf
|
.nf
|
||||||
# ip fou del port 9999
|
# ip fou del port 9999
|
||||||
|
.SS Configure a FOU receive port for GRE bound to 1.2.3.4:7777
|
||||||
|
.nf
|
||||||
|
# ip fou add port 7777 ipproto 47 local 1.2.3.4
|
||||||
|
.PP
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.br
|
.br
|
||||||
.BR ip (8)
|
.BR ip (8)
|
||||||
|
Loading…
Reference in New Issue
Block a user