Commit 6618e334 authored by Chris Elston's avatar Chris Elston Committed by Stephen Hemminger

iproute2: allow IPv6 addresses for l2tp local and remote parameters

Adds support for parsing IPv6 addresses to the parameters local and
remote in the l2tp commands. Requires netlink attributes L2TP_ATTR_IP6_SADDR
and L2TP_ATTR_IP6_DADDR, added in a required kernel patch already submitted
to netdev.

Also enables printing of IPv6 addresses returned by the L2TP_CMD_TUNNEL_GET
request.
Signed-off-by: default avatarChris Elston <celston@katalix.com>
Signed-off-by: default avatarJames Chapman <jchapman@katalix.com>
parent c3524efc
...@@ -50,8 +50,8 @@ struct l2tp_parm { ...@@ -50,8 +50,8 @@ struct l2tp_parm {
uint8_t cookie[8]; uint8_t cookie[8];
int peer_cookie_len; int peer_cookie_len;
uint8_t peer_cookie[8]; uint8_t peer_cookie[8];
struct in_addr local_ip; inet_prefix local_ip;
struct in_addr peer_ip; inet_prefix peer_ip;
uint16_t pw_type; uint16_t pw_type;
uint16_t mtu; uint16_t mtu;
...@@ -97,6 +97,8 @@ static int create_tunnel(struct l2tp_parm *p) ...@@ -97,6 +97,8 @@ static int create_tunnel(struct l2tp_parm *p)
struct genlmsghdr g; struct genlmsghdr g;
char buf[1024]; char buf[1024];
} req; } req;
uint32_t local_attr = L2TP_ATTR_IP_SADDR;
uint32_t peer_attr = L2TP_ATTR_IP_DADDR;
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
req.n.nlmsg_type = genl_family; req.n.nlmsg_type = genl_family;
...@@ -110,8 +112,14 @@ static int create_tunnel(struct l2tp_parm *p) ...@@ -110,8 +112,14 @@ static int create_tunnel(struct l2tp_parm *p)
addattr8(&req.n, 1024, L2TP_ATTR_PROTO_VERSION, 3); addattr8(&req.n, 1024, L2TP_ATTR_PROTO_VERSION, 3);
addattr16(&req.n, 1024, L2TP_ATTR_ENCAP_TYPE, p->encap); addattr16(&req.n, 1024, L2TP_ATTR_ENCAP_TYPE, p->encap);
addattr32(&req.n, 1024, L2TP_ATTR_IP_SADDR, p->local_ip.s_addr); if (p->local_ip.family == AF_INET6)
addattr32(&req.n, 1024, L2TP_ATTR_IP_DADDR, p->peer_ip.s_addr); local_attr = L2TP_ATTR_IP6_SADDR;
addattr_l(&req.n, 1024, local_attr, &p->local_ip.data, p->local_ip.bytelen);
if (p->peer_ip.family == AF_INET6)
peer_attr = L2TP_ATTR_IP6_DADDR;
addattr_l(&req.n, 1024, peer_attr, &p->peer_ip.data, p->peer_ip.bytelen);
if (p->encap == L2TP_ENCAPTYPE_UDP) { if (p->encap == L2TP_ENCAPTYPE_UDP) {
addattr16(&req.n, 1024, L2TP_ATTR_UDP_SPORT, p->local_udp_port); addattr16(&req.n, 1024, L2TP_ATTR_UDP_SPORT, p->local_udp_port);
addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port); addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port);
...@@ -225,13 +233,14 @@ static void print_cookie(char *name, const uint8_t *cookie, int len) ...@@ -225,13 +233,14 @@ static void print_cookie(char *name, const uint8_t *cookie, int len)
static void print_tunnel(const struct l2tp_data *data) static void print_tunnel(const struct l2tp_data *data)
{ {
const struct l2tp_parm *p = &data->config; const struct l2tp_parm *p = &data->config;
char buf[INET6_ADDRSTRLEN];
printf("Tunnel %u, encap %s\n", printf("Tunnel %u, encap %s\n",
p->tunnel_id, p->tunnel_id,
p->encap == L2TP_ENCAPTYPE_UDP ? "UDP" : p->encap == L2TP_ENCAPTYPE_UDP ? "UDP" :
p->encap == L2TP_ENCAPTYPE_IP ? "IP" : "??"); p->encap == L2TP_ENCAPTYPE_IP ? "IP" : "??");
printf(" From %s ", inet_ntoa(p->local_ip)); printf(" From %s ", inet_ntop(p->local_ip.family, p->local_ip.data, buf, sizeof(buf)));
printf("to %s\n", inet_ntoa(p->peer_ip)); printf("to %s\n", inet_ntop(p->peer_ip.family, p->peer_ip.data, buf, sizeof(buf)));
printf(" Peer tunnel %u\n", printf(" Peer tunnel %u\n",
p->peer_tunnel_id); p->peer_tunnel_id);
...@@ -315,10 +324,30 @@ static int get_response(struct nlmsghdr *n, void *arg) ...@@ -315,10 +324,30 @@ static int get_response(struct nlmsghdr *n, void *arg)
if (attrs[L2TP_ATTR_RECV_TIMEOUT]) if (attrs[L2TP_ATTR_RECV_TIMEOUT])
p->reorder_timeout = rta_getattr_u64(attrs[L2TP_ATTR_RECV_TIMEOUT]); p->reorder_timeout = rta_getattr_u64(attrs[L2TP_ATTR_RECV_TIMEOUT]);
if (attrs[L2TP_ATTR_IP_SADDR]) if (attrs[L2TP_ATTR_IP_SADDR]) {
p->local_ip.s_addr = rta_getattr_u32(attrs[L2TP_ATTR_IP_SADDR]); p->local_ip.family = AF_INET;
if (attrs[L2TP_ATTR_IP_DADDR]) p->local_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_SADDR]);
p->peer_ip.s_addr = rta_getattr_u32(attrs[L2TP_ATTR_IP_DADDR]); p->local_ip.bytelen = 4;
p->local_ip.bitlen = -1;
}
if (attrs[L2TP_ATTR_IP_DADDR]) {
p->peer_ip.family = AF_INET;
p->peer_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_DADDR]);
p->peer_ip.bytelen = 4;
p->peer_ip.bitlen = -1;
}
if (attrs[L2TP_ATTR_IP6_SADDR]) {
p->local_ip.family = AF_INET6;
memcpy(&p->local_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_SADDR]),
p->local_ip.bytelen = 16);
p->local_ip.bitlen = -1;
}
if (attrs[L2TP_ATTR_IP6_DADDR]) {
p->peer_ip.family = AF_INET6;
memcpy(&p->peer_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_DADDR]),
p->peer_ip.bytelen = 16);
p->peer_ip.bitlen = -1;
}
if (attrs[L2TP_ATTR_UDP_SPORT]) if (attrs[L2TP_ATTR_UDP_SPORT])
p->local_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_SPORT]); p->local_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_SPORT]);
if (attrs[L2TP_ATTR_UDP_DPORT]) if (attrs[L2TP_ATTR_UDP_DPORT])
...@@ -529,10 +558,12 @@ static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p) ...@@ -529,10 +558,12 @@ static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
p->ifname = *argv; p->ifname = *argv;
} else if (strcmp(*argv, "remote") == 0) { } else if (strcmp(*argv, "remote") == 0) {
NEXT_ARG(); NEXT_ARG();
p->peer_ip.s_addr = get_addr32(*argv); if (get_addr(&p->peer_ip, *argv, AF_UNSPEC))
invarg("invalid remote address\n", *argv);
} else if (strcmp(*argv, "local") == 0) { } else if (strcmp(*argv, "local") == 0) {
NEXT_ARG(); NEXT_ARG();
p->local_ip.s_addr = get_addr32(*argv); if (get_addr(&p->local_ip, *argv, AF_UNSPEC))
invarg("invalid local address\n", *argv);
} else if ((strcmp(*argv, "tunnel_id") == 0) || } else if ((strcmp(*argv, "tunnel_id") == 0) ||
(strcmp(*argv, "tid") == 0)) { (strcmp(*argv, "tid") == 0)) {
__u32 uval; __u32 uval;
...@@ -648,10 +679,10 @@ static int do_add(int argc, char **argv) ...@@ -648,10 +679,10 @@ static int do_add(int argc, char **argv)
missarg("peer_tunnel_id"); missarg("peer_tunnel_id");
if (p.tunnel) { if (p.tunnel) {
if (p.local_ip.s_addr == 0) if (p.local_ip.family == AF_UNSPEC)
missarg("local"); missarg("local");
if (p.peer_ip.s_addr == 0) if (p.peer_ip.family == AF_UNSPEC)
missarg("remote"); missarg("remote");
if (p.encap == L2TP_ENCAPTYPE_UDP) { if (p.encap == L2TP_ENCAPTYPE_UDP) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment