Home | History | Annotate | Download | only in ip
      1 /*
      2  * ipl2tp.c	       "ip l2tp"
      3  *
      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.
      8  *
      9  * Original Author:	James Chapman <jchapman (at) katalix.com>
     10  *
     11  */
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 #include <unistd.h>
     17 #include <errno.h>
     18 #include <sys/types.h>
     19 #include <sys/socket.h>
     20 #include <arpa/inet.h>
     21 #include <sys/ioctl.h>
     22 #include <linux/if.h>
     23 #include <linux/if_arp.h>
     24 #include <linux/ip.h>
     25 
     26 #include <linux/genetlink.h>
     27 #include <linux/l2tp.h>
     28 #include "libgenl.h"
     29 
     30 #include "utils.h"
     31 #include "ip_common.h"
     32 
     33 enum {
     34 	L2TP_ADD,
     35 	L2TP_CHG,
     36 	L2TP_DEL,
     37 	L2TP_GET
     38 };
     39 
     40 struct l2tp_parm {
     41 	uint32_t tunnel_id;
     42 	uint32_t peer_tunnel_id;
     43 	uint32_t session_id;
     44 	uint32_t peer_session_id;
     45 	uint32_t offset;
     46 	uint32_t peer_offset;
     47 	enum l2tp_encap_type encap;
     48 	uint16_t local_udp_port;
     49 	uint16_t peer_udp_port;
     50 	int cookie_len;
     51 	uint8_t cookie[8];
     52 	int peer_cookie_len;
     53 	uint8_t peer_cookie[8];
     54 	inet_prefix local_ip;
     55 	inet_prefix peer_ip;
     56 
     57 	uint16_t pw_type;
     58 	uint16_t mtu;
     59 	unsigned int udp6_csum_tx:1;
     60 	unsigned int udp6_csum_rx:1;
     61 	unsigned int udp_csum:1;
     62 	unsigned int recv_seq:1;
     63 	unsigned int send_seq:1;
     64 	unsigned int lns_mode:1;
     65 	unsigned int data_seq:2;
     66 	unsigned int tunnel:1;
     67 	unsigned int session:1;
     68 	int reorder_timeout;
     69 	const char *ifname;
     70 	uint8_t l2spec_type;
     71 	uint8_t l2spec_len;
     72 };
     73 
     74 struct l2tp_stats {
     75 	uint64_t data_rx_packets;
     76 	uint64_t data_rx_bytes;
     77 	uint64_t data_rx_errors;
     78 	uint64_t data_rx_oos_packets;
     79 	uint64_t data_rx_oos_discards;
     80 	uint64_t data_tx_packets;
     81 	uint64_t data_tx_bytes;
     82 	uint64_t data_tx_errors;
     83 };
     84 
     85 struct l2tp_data {
     86 	struct l2tp_parm config;
     87 	struct l2tp_stats stats;
     88 };
     89 
     90 /* netlink socket */
     91 static struct rtnl_handle genl_rth;
     92 static int genl_family = -1;
     93 
     94 /*****************************************************************************
     95  * Netlink actions
     96  *****************************************************************************/
     97 
     98 static int create_tunnel(struct l2tp_parm *p)
     99 {
    100 	uint32_t local_attr = L2TP_ATTR_IP_SADDR;
    101 	uint32_t peer_attr = L2TP_ATTR_IP_DADDR;
    102 
    103 	GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
    104 		     L2TP_CMD_TUNNEL_CREATE, NLM_F_REQUEST | NLM_F_ACK);
    105 
    106 	addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
    107 	addattr32(&req.n, 1024, L2TP_ATTR_PEER_CONN_ID, p->peer_tunnel_id);
    108 	addattr8(&req.n, 1024, L2TP_ATTR_PROTO_VERSION, 3);
    109 	addattr16(&req.n, 1024, L2TP_ATTR_ENCAP_TYPE, p->encap);
    110 
    111 	if (p->local_ip.family == AF_INET6)
    112 		local_attr = L2TP_ATTR_IP6_SADDR;
    113 	addattr_l(&req.n, 1024, local_attr, &p->local_ip.data,
    114 		  p->local_ip.bytelen);
    115 
    116 	if (p->peer_ip.family == AF_INET6)
    117 		peer_attr = L2TP_ATTR_IP6_DADDR;
    118 	addattr_l(&req.n, 1024, peer_attr, &p->peer_ip.data,
    119 		  p->peer_ip.bytelen);
    120 
    121 	if (p->encap == L2TP_ENCAPTYPE_UDP) {
    122 		addattr16(&req.n, 1024, L2TP_ATTR_UDP_SPORT, p->local_udp_port);
    123 		addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port);
    124 		if (p->udp_csum)
    125 			addattr8(&req.n, 1024, L2TP_ATTR_UDP_CSUM, 1);
    126 		if (!p->udp6_csum_tx)
    127 			addattr(&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_TX);
    128 		if (!p->udp6_csum_rx)
    129 			addattr(&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_RX);
    130 	}
    131 
    132 	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
    133 		return -2;
    134 
    135 	return 0;
    136 }
    137 
    138 static int delete_tunnel(struct l2tp_parm *p)
    139 {
    140 	GENL_REQUEST(req, 128, genl_family, 0, L2TP_GENL_VERSION,
    141 		     L2TP_CMD_TUNNEL_DELETE, NLM_F_REQUEST | NLM_F_ACK);
    142 
    143 	addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id);
    144 
    145 	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
    146 		return -2;
    147 
    148 	return 0;
    149 }
    150 
    151 static int create_session(struct l2tp_parm *p)
    152 {
    153 	GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
    154 		     L2TP_CMD_SESSION_CREATE, NLM_F_REQUEST | NLM_F_ACK);
    155 
    156 	addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
    157 	addattr32(&req.n, 1024, L2TP_ATTR_PEER_CONN_ID, p->peer_tunnel_id);
    158 	addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
    159 	addattr32(&req.n, 1024, L2TP_ATTR_PEER_SESSION_ID, p->peer_session_id);
    160 	addattr16(&req.n, 1024, L2TP_ATTR_PW_TYPE, p->pw_type);
    161 	addattr8(&req.n, 1024, L2TP_ATTR_L2SPEC_TYPE, p->l2spec_type);
    162 	addattr8(&req.n, 1024, L2TP_ATTR_L2SPEC_LEN, p->l2spec_len);
    163 
    164 	if (p->mtu)
    165 		addattr16(&req.n, 1024, L2TP_ATTR_MTU, p->mtu);
    166 	if (p->recv_seq)
    167 		addattr8(&req.n, 1024, L2TP_ATTR_RECV_SEQ, 1);
    168 	if (p->send_seq)
    169 		addattr8(&req.n, 1024, L2TP_ATTR_SEND_SEQ, 1);
    170 	if (p->lns_mode)
    171 		addattr(&req.n, 1024, L2TP_ATTR_LNS_MODE);
    172 	if (p->data_seq)
    173 		addattr8(&req.n, 1024, L2TP_ATTR_DATA_SEQ, p->data_seq);
    174 	if (p->reorder_timeout)
    175 		addattr64(&req.n, 1024, L2TP_ATTR_RECV_TIMEOUT,
    176 					  p->reorder_timeout);
    177 	if (p->offset)
    178 		addattr16(&req.n, 1024, L2TP_ATTR_OFFSET, p->offset);
    179 	if (p->cookie_len)
    180 		addattr_l(&req.n, 1024, L2TP_ATTR_COOKIE,
    181 			  p->cookie, p->cookie_len);
    182 	if (p->peer_cookie_len)
    183 		addattr_l(&req.n, 1024, L2TP_ATTR_PEER_COOKIE,
    184 			  p->peer_cookie,  p->peer_cookie_len);
    185 	if (p->ifname)
    186 		addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname);
    187 
    188 	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
    189 		return -2;
    190 
    191 	return 0;
    192 }
    193 
    194 static int delete_session(struct l2tp_parm *p)
    195 {
    196 	GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
    197 		     L2TP_CMD_SESSION_DELETE, NLM_F_REQUEST | NLM_F_ACK);
    198 
    199 	addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
    200 	addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
    201 	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
    202 		return -2;
    203 
    204 	return 0;
    205 }
    206 
    207 static void print_cookie(char *name, const uint8_t *cookie, int len)
    208 {
    209 	printf("  %s %02x%02x%02x%02x", name,
    210 	       cookie[0], cookie[1],
    211 	       cookie[2], cookie[3]);
    212 	if (len == 8)
    213 		printf("%02x%02x%02x%02x",
    214 		       cookie[4], cookie[5],
    215 		       cookie[6], cookie[7]);
    216 }
    217 
    218 static void print_tunnel(const struct l2tp_data *data)
    219 {
    220 	const struct l2tp_parm *p = &data->config;
    221 	char buf[INET6_ADDRSTRLEN];
    222 
    223 	printf("Tunnel %u, encap %s\n",
    224 	       p->tunnel_id,
    225 	       p->encap == L2TP_ENCAPTYPE_UDP ? "UDP" :
    226 	       p->encap == L2TP_ENCAPTYPE_IP ? "IP" : "??");
    227 	printf("  From %s ",
    228 	       inet_ntop(p->local_ip.family, p->local_ip.data,
    229 			 buf, sizeof(buf)));
    230 	printf("to %s\n",
    231 	       inet_ntop(p->peer_ip.family, p->peer_ip.data,
    232 			 buf, sizeof(buf)));
    233 	printf("  Peer tunnel %u\n",
    234 	       p->peer_tunnel_id);
    235 
    236 	if (p->encap == L2TP_ENCAPTYPE_UDP) {
    237 		printf("  UDP source / dest ports: %hu/%hu\n",
    238 		       p->local_udp_port, p->peer_udp_port);
    239 
    240 		switch (p->local_ip.family) {
    241 		case AF_INET:
    242 			printf("  UDP checksum: %s\n",
    243 			       p->udp_csum ? "enabled" : "disabled");
    244 			break;
    245 		case AF_INET6:
    246 			printf("  UDP checksum: %s%s%s%s\n",
    247 			       p->udp6_csum_tx && p->udp6_csum_rx
    248 			       ? "enabled" : "",
    249 			       p->udp6_csum_tx && !p->udp6_csum_rx
    250 			       ? "tx" : "",
    251 			       !p->udp6_csum_tx && p->udp6_csum_rx
    252 			       ? "rx" : "",
    253 			       !p->udp6_csum_tx && !p->udp6_csum_rx
    254 			       ? "disabled" : "");
    255 			break;
    256 		}
    257 	}
    258 }
    259 
    260 static void print_session(struct l2tp_data *data)
    261 {
    262 	struct l2tp_parm *p = &data->config;
    263 
    264 	printf("Session %u in tunnel %u\n",
    265 	       p->session_id, p->tunnel_id);
    266 	printf("  Peer session %u, tunnel %u\n",
    267 	       p->peer_session_id, p->peer_tunnel_id);
    268 
    269 	if (p->ifname != NULL)
    270 		printf("  interface name: %s\n", p->ifname);
    271 
    272 	printf("  offset %u, peer offset %u\n",
    273 	       p->offset, p->peer_offset);
    274 	if (p->cookie_len > 0)
    275 		print_cookie("cookie", p->cookie, p->cookie_len);
    276 	if (p->peer_cookie_len > 0)
    277 		print_cookie("peer cookie", p->peer_cookie, p->peer_cookie_len);
    278 
    279 	if (p->reorder_timeout != 0)
    280 		printf("  reorder timeout: %u\n", p->reorder_timeout);
    281 	else
    282 		printf("\n");
    283 	if (p->send_seq || p->recv_seq) {
    284 		printf("  sequence numbering:");
    285 		if (p->send_seq)
    286 			printf(" send");
    287 		if (p->recv_seq)
    288 			printf(" recv");
    289 		printf("\n");
    290 	}
    291 }
    292 
    293 static int get_response(struct nlmsghdr *n, void *arg)
    294 {
    295 	struct genlmsghdr *ghdr;
    296 	struct l2tp_data *data = arg;
    297 	struct l2tp_parm *p = &data->config;
    298 	struct rtattr *attrs[L2TP_ATTR_MAX + 1];
    299 	struct rtattr *nla_stats;
    300 	int len;
    301 
    302 	/* Validate message and parse attributes */
    303 	if (n->nlmsg_type == NLMSG_ERROR)
    304 		return -EBADMSG;
    305 
    306 	ghdr = NLMSG_DATA(n);
    307 	len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ghdr));
    308 	if (len < 0)
    309 		return -1;
    310 
    311 	parse_rtattr(attrs, L2TP_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
    312 
    313 	if (attrs[L2TP_ATTR_PW_TYPE])
    314 		p->pw_type = rta_getattr_u16(attrs[L2TP_ATTR_PW_TYPE]);
    315 	if (attrs[L2TP_ATTR_ENCAP_TYPE])
    316 		p->encap = rta_getattr_u16(attrs[L2TP_ATTR_ENCAP_TYPE]);
    317 	if (attrs[L2TP_ATTR_OFFSET])
    318 		p->offset = rta_getattr_u16(attrs[L2TP_ATTR_OFFSET]);
    319 	if (attrs[L2TP_ATTR_DATA_SEQ])
    320 		p->data_seq = rta_getattr_u16(attrs[L2TP_ATTR_DATA_SEQ]);
    321 	if (attrs[L2TP_ATTR_CONN_ID])
    322 		p->tunnel_id = rta_getattr_u32(attrs[L2TP_ATTR_CONN_ID]);
    323 	if (attrs[L2TP_ATTR_PEER_CONN_ID])
    324 		p->peer_tunnel_id = rta_getattr_u32(attrs[L2TP_ATTR_PEER_CONN_ID]);
    325 	if (attrs[L2TP_ATTR_SESSION_ID])
    326 		p->session_id = rta_getattr_u32(attrs[L2TP_ATTR_SESSION_ID]);
    327 	if (attrs[L2TP_ATTR_PEER_SESSION_ID])
    328 		p->peer_session_id = rta_getattr_u32(attrs[L2TP_ATTR_PEER_SESSION_ID]);
    329 	if (attrs[L2TP_ATTR_L2SPEC_TYPE])
    330 		p->l2spec_type = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_TYPE]);
    331 	if (attrs[L2TP_ATTR_L2SPEC_LEN])
    332 		p->l2spec_len = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_LEN]);
    333 
    334 	if (attrs[L2TP_ATTR_UDP_CSUM])
    335 		p->udp_csum = !!rta_getattr_u8(attrs[L2TP_ATTR_UDP_CSUM]);
    336 
    337 	p->udp6_csum_tx = !attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX];
    338 	p->udp6_csum_rx = !attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX];
    339 
    340 	if (attrs[L2TP_ATTR_COOKIE])
    341 		memcpy(p->cookie, RTA_DATA(attrs[L2TP_ATTR_COOKIE]),
    342 		       p->cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_COOKIE]));
    343 
    344 	if (attrs[L2TP_ATTR_PEER_COOKIE])
    345 		memcpy(p->peer_cookie, RTA_DATA(attrs[L2TP_ATTR_PEER_COOKIE]),
    346 		       p->peer_cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_PEER_COOKIE]));
    347 
    348 	if (attrs[L2TP_ATTR_RECV_SEQ])
    349 		p->recv_seq = !!rta_getattr_u8(attrs[L2TP_ATTR_RECV_SEQ]);
    350 	if (attrs[L2TP_ATTR_SEND_SEQ])
    351 		p->send_seq = !!rta_getattr_u8(attrs[L2TP_ATTR_SEND_SEQ]);
    352 
    353 	if (attrs[L2TP_ATTR_RECV_TIMEOUT])
    354 		p->reorder_timeout = rta_getattr_u64(attrs[L2TP_ATTR_RECV_TIMEOUT]);
    355 	if (attrs[L2TP_ATTR_IP_SADDR]) {
    356 		p->local_ip.family = AF_INET;
    357 		p->local_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_SADDR]);
    358 		p->local_ip.bytelen = 4;
    359 		p->local_ip.bitlen = -1;
    360 	}
    361 	if (attrs[L2TP_ATTR_IP_DADDR]) {
    362 		p->peer_ip.family = AF_INET;
    363 		p->peer_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_DADDR]);
    364 		p->peer_ip.bytelen = 4;
    365 		p->peer_ip.bitlen = -1;
    366 	}
    367 	if (attrs[L2TP_ATTR_IP6_SADDR]) {
    368 		p->local_ip.family = AF_INET6;
    369 		memcpy(&p->local_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_SADDR]),
    370 			p->local_ip.bytelen = 16);
    371 		p->local_ip.bitlen = -1;
    372 	}
    373 	if (attrs[L2TP_ATTR_IP6_DADDR]) {
    374 		p->peer_ip.family = AF_INET6;
    375 		memcpy(&p->peer_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_DADDR]),
    376 			p->peer_ip.bytelen = 16);
    377 		p->peer_ip.bitlen = -1;
    378 	}
    379 	if (attrs[L2TP_ATTR_UDP_SPORT])
    380 		p->local_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_SPORT]);
    381 	if (attrs[L2TP_ATTR_UDP_DPORT])
    382 		p->peer_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_DPORT]);
    383 	if (attrs[L2TP_ATTR_MTU])
    384 		p->mtu = rta_getattr_u16(attrs[L2TP_ATTR_MTU]);
    385 	if (attrs[L2TP_ATTR_IFNAME])
    386 		p->ifname = rta_getattr_str(attrs[L2TP_ATTR_IFNAME]);
    387 
    388 	nla_stats = attrs[L2TP_ATTR_STATS];
    389 	if (nla_stats) {
    390 		struct rtattr *tb[L2TP_ATTR_STATS_MAX + 1];
    391 
    392 		parse_rtattr_nested(tb, L2TP_ATTR_STATS_MAX, nla_stats);
    393 
    394 		if (tb[L2TP_ATTR_TX_PACKETS])
    395 			data->stats.data_tx_packets = rta_getattr_u64(tb[L2TP_ATTR_TX_PACKETS]);
    396 		if (tb[L2TP_ATTR_TX_BYTES])
    397 			data->stats.data_tx_bytes = rta_getattr_u64(tb[L2TP_ATTR_TX_BYTES]);
    398 		if (tb[L2TP_ATTR_TX_ERRORS])
    399 			data->stats.data_tx_errors = rta_getattr_u64(tb[L2TP_ATTR_TX_ERRORS]);
    400 		if (tb[L2TP_ATTR_RX_PACKETS])
    401 			data->stats.data_rx_packets = rta_getattr_u64(tb[L2TP_ATTR_RX_PACKETS]);
    402 		if (tb[L2TP_ATTR_RX_BYTES])
    403 			data->stats.data_rx_bytes = rta_getattr_u64(tb[L2TP_ATTR_RX_BYTES]);
    404 		if (tb[L2TP_ATTR_RX_ERRORS])
    405 			data->stats.data_rx_errors = rta_getattr_u64(tb[L2TP_ATTR_RX_ERRORS]);
    406 		if (tb[L2TP_ATTR_RX_SEQ_DISCARDS])
    407 			data->stats.data_rx_oos_discards = rta_getattr_u64(tb[L2TP_ATTR_RX_SEQ_DISCARDS]);
    408 		if (tb[L2TP_ATTR_RX_OOS_PACKETS])
    409 			data->stats.data_rx_oos_packets = rta_getattr_u64(tb[L2TP_ATTR_RX_OOS_PACKETS]);
    410 	}
    411 
    412 	return 0;
    413 }
    414 
    415 static int session_nlmsg(const struct sockaddr_nl *who,
    416 			 struct nlmsghdr *n, void *arg)
    417 {
    418 	int ret = get_response(n, arg);
    419 
    420 	if (ret == 0)
    421 		print_session(arg);
    422 
    423 	return ret;
    424 }
    425 
    426 static int get_session(struct l2tp_data *p)
    427 {
    428 	GENL_REQUEST(req, 128, genl_family, 0, L2TP_GENL_VERSION,
    429 		     L2TP_CMD_SESSION_GET,
    430 		     NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST);
    431 
    432 	req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
    433 
    434 	if (p->config.tunnel_id && p->config.session_id) {
    435 		addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
    436 		addattr32(&req.n, 128, L2TP_ATTR_SESSION_ID,
    437 			  p->config.session_id);
    438 	}
    439 
    440 	if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
    441 		return -2;
    442 
    443 	if (rtnl_dump_filter(&genl_rth, session_nlmsg, p) < 0) {
    444 		fprintf(stderr, "Dump terminated\n");
    445 		exit(1);
    446 	}
    447 
    448 	return 0;
    449 }
    450 
    451 static int tunnel_nlmsg(const struct sockaddr_nl *who,
    452 			struct nlmsghdr *n, void *arg)
    453 {
    454 	int ret = get_response(n, arg);
    455 
    456 	if (ret == 0)
    457 		print_tunnel(arg);
    458 
    459 	return ret;
    460 }
    461 
    462 static int get_tunnel(struct l2tp_data *p)
    463 {
    464 	GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
    465 		     L2TP_CMD_TUNNEL_GET,
    466 		     NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST);
    467 
    468 	req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
    469 
    470 	if (p->config.tunnel_id)
    471 		addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
    472 
    473 	if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
    474 		return -2;
    475 
    476 	if (rtnl_dump_filter(&genl_rth, tunnel_nlmsg, p) < 0) {
    477 		fprintf(stderr, "Dump terminated\n");
    478 		exit(1);
    479 	}
    480 
    481 	return 0;
    482 }
    483 
    484 /*****************************************************************************
    485  * Command parser
    486  *****************************************************************************/
    487 
    488 static void usage(void) __attribute__((noreturn));
    489 
    490 static void usage(void)
    491 {
    492 	fprintf(stderr, "Usage: ip l2tp add tunnel\n"
    493 		"          remote ADDR local ADDR\n"
    494 		"          tunnel_id ID peer_tunnel_id ID\n"
    495 		"          [ encap { ip | udp } ]\n"
    496 		"          [ udp_sport PORT ] [ udp_dport PORT ]\n"
    497 		"          [ udp_csum { on | off } ]\n"
    498 		"          [ udp6_csum_tx { on | off } ]\n"
    499 		"          [ udp6_csum_rx { on | off } ]\n"
    500 		"Usage: ip l2tp add session [ name NAME ]\n"
    501 		"          tunnel_id ID\n"
    502 		"          session_id ID peer_session_id ID\n"
    503 		"          [ cookie HEXSTR ] [ peer_cookie HEXSTR ]\n"
    504 		"          [ offset OFFSET ] [ peer_offset OFFSET ]\n"
    505 		"          [ seq { none | send | recv | both } ]\n"
    506 		"          [ l2spec_type L2SPEC ]\n"
    507 		"       ip l2tp del tunnel tunnel_id ID\n"
    508 		"       ip l2tp del session tunnel_id ID session_id ID\n"
    509 		"       ip l2tp show tunnel [ tunnel_id ID ]\n"
    510 		"       ip l2tp show session [ tunnel_id ID ] [ session_id ID ]\n"
    511 		"\n"
    512 		"Where: NAME   := STRING\n"
    513 		"       ADDR   := { IP_ADDRESS | any }\n"
    514 		"       PORT   := { 0..65535 }\n"
    515 		"       ID     := { 1..4294967295 }\n"
    516 		"       HEXSTR := { 8 or 16 hex digits (4 / 8 bytes) }\n"
    517 		"       L2SPEC := { none | default }\n");
    518 
    519 	exit(-1);
    520 }
    521 
    522 static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
    523 {
    524 	memset(p, 0, sizeof(*p));
    525 
    526 	if (argc == 0)
    527 		usage();
    528 
    529 	/* Defaults */
    530 	p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT;
    531 	p->l2spec_len = 4;
    532 	p->udp6_csum_rx = 1;
    533 	p->udp6_csum_tx = 1;
    534 
    535 	while (argc > 0) {
    536 		if (strcmp(*argv, "encap") == 0) {
    537 			NEXT_ARG();
    538 			if (strcmp(*argv, "ip") == 0) {
    539 				p->encap = L2TP_ENCAPTYPE_IP;
    540 			} else if (strcmp(*argv, "udp") == 0) {
    541 				p->encap = L2TP_ENCAPTYPE_UDP;
    542 			} else {
    543 				fprintf(stderr, "Unknown tunnel encapsulation \"%s\"\n", *argv);
    544 				exit(-1);
    545 			}
    546 		} else if (strcmp(*argv, "name") == 0) {
    547 			NEXT_ARG();
    548 			if (check_ifname(*argv))
    549 				invarg("\"name\" not a valid ifname", *argv);
    550 			p->ifname = *argv;
    551 		} else if (strcmp(*argv, "remote") == 0) {
    552 			NEXT_ARG();
    553 			if (get_addr(&p->peer_ip, *argv, AF_UNSPEC))
    554 				invarg("invalid remote address\n", *argv);
    555 		} else if (strcmp(*argv, "local") == 0) {
    556 			NEXT_ARG();
    557 			if (get_addr(&p->local_ip, *argv, AF_UNSPEC))
    558 				invarg("invalid local address\n", *argv);
    559 		} else if ((strcmp(*argv, "tunnel_id") == 0) ||
    560 			   (strcmp(*argv, "tid") == 0)) {
    561 			__u32 uval;
    562 
    563 			NEXT_ARG();
    564 			if (get_u32(&uval, *argv, 0))
    565 				invarg("invalid ID\n", *argv);
    566 			p->tunnel_id = uval;
    567 		} else if ((strcmp(*argv, "peer_tunnel_id") == 0) ||
    568 			   (strcmp(*argv, "ptid") == 0)) {
    569 			__u32 uval;
    570 
    571 			NEXT_ARG();
    572 			if (get_u32(&uval, *argv, 0))
    573 				invarg("invalid ID\n", *argv);
    574 			p->peer_tunnel_id = uval;
    575 		} else if ((strcmp(*argv, "session_id") == 0) ||
    576 			   (strcmp(*argv, "sid") == 0)) {
    577 			__u32 uval;
    578 
    579 			NEXT_ARG();
    580 			if (get_u32(&uval, *argv, 0))
    581 				invarg("invalid ID\n", *argv);
    582 			p->session_id = uval;
    583 		} else if ((strcmp(*argv, "peer_session_id") == 0) ||
    584 			   (strcmp(*argv, "psid") == 0)) {
    585 			__u32 uval;
    586 
    587 			NEXT_ARG();
    588 			if (get_u32(&uval, *argv, 0))
    589 				invarg("invalid ID\n", *argv);
    590 			p->peer_session_id = uval;
    591 		} else if (strcmp(*argv, "udp_sport") == 0) {
    592 			__u16 uval;
    593 
    594 			NEXT_ARG();
    595 			if (get_u16(&uval, *argv, 0))
    596 				invarg("invalid port\n", *argv);
    597 			p->local_udp_port = uval;
    598 		} else if (strcmp(*argv, "udp_dport") == 0) {
    599 			__u16 uval;
    600 
    601 			NEXT_ARG();
    602 			if (get_u16(&uval, *argv, 0))
    603 				invarg("invalid port\n", *argv);
    604 			p->peer_udp_port = uval;
    605 		} else if (strcmp(*argv, "udp_csum") == 0) {
    606 			NEXT_ARG();
    607 			if (strcmp(*argv, "on") == 0)
    608 				p->udp_csum = 1;
    609 			else if (strcmp(*argv, "off") == 0)
    610 				p->udp_csum = 0;
    611 			else
    612 				invarg("invalid option for udp_csum\n", *argv);
    613 		} else if (strcmp(*argv, "udp6_csum_rx") == 0) {
    614 			NEXT_ARG();
    615 			if (strcmp(*argv, "on") == 0)
    616 				p->udp6_csum_rx = 1;
    617 			else if (strcmp(*argv, "off") == 0)
    618 				p->udp6_csum_rx = 0;
    619 			else
    620 				invarg("invalid option for udp6_csum_rx\n"
    621 						, *argv);
    622 		} else if (strcmp(*argv, "udp6_csum_tx") == 0) {
    623 			NEXT_ARG();
    624 			if (strcmp(*argv, "on") == 0)
    625 				p->udp6_csum_tx = 1;
    626 			else if (strcmp(*argv, "off") == 0)
    627 				p->udp6_csum_tx = 0;
    628 			else
    629 				invarg("invalid option for udp6_csum_tx\n"
    630 						, *argv);
    631 		} else if (strcmp(*argv, "offset") == 0) {
    632 			__u8 uval;
    633 
    634 			NEXT_ARG();
    635 			if (get_u8(&uval, *argv, 0))
    636 				invarg("invalid offset\n", *argv);
    637 			p->offset = uval;
    638 		} else if (strcmp(*argv, "peer_offset") == 0) {
    639 			__u8 uval;
    640 
    641 			NEXT_ARG();
    642 			if (get_u8(&uval, *argv, 0))
    643 				invarg("invalid offset\n", *argv);
    644 			p->peer_offset = uval;
    645 		} else if (strcmp(*argv, "cookie") == 0) {
    646 			int slen;
    647 
    648 			NEXT_ARG();
    649 			slen = strlen(*argv);
    650 			if ((slen != 8) && (slen != 16))
    651 				invarg("cookie must be either 8 or 16 hex digits\n", *argv);
    652 
    653 			p->cookie_len = slen / 2;
    654 			if (hex2mem(*argv, p->cookie, p->cookie_len) < 0)
    655 				invarg("cookie must be a hex string\n", *argv);
    656 		} else if (strcmp(*argv, "peer_cookie") == 0) {
    657 			int slen;
    658 
    659 			NEXT_ARG();
    660 			slen = strlen(*argv);
    661 			if ((slen != 8) && (slen != 16))
    662 				invarg("cookie must be either 8 or 16 hex digits\n", *argv);
    663 
    664 			p->peer_cookie_len = slen / 2;
    665 			if (hex2mem(*argv, p->peer_cookie, p->peer_cookie_len) < 0)
    666 				invarg("cookie must be a hex string\n", *argv);
    667 		} else if (strcmp(*argv, "l2spec_type") == 0) {
    668 			NEXT_ARG();
    669 			if (strcasecmp(*argv, "default") == 0) {
    670 				p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT;
    671 				p->l2spec_len = 4;
    672 			} else if (strcasecmp(*argv, "none") == 0) {
    673 				p->l2spec_type = L2TP_L2SPECTYPE_NONE;
    674 				p->l2spec_len = 0;
    675 			} else {
    676 				fprintf(stderr,
    677 					"Unknown layer2specific header type \"%s\"\n",
    678 					*argv);
    679 				exit(-1);
    680 			}
    681 		} else if (strcmp(*argv, "seq") == 0) {
    682 			NEXT_ARG();
    683 			if (strcasecmp(*argv, "both") == 0) {
    684 				p->recv_seq = 1;
    685 				p->send_seq = 1;
    686 			} else if (strcasecmp(*argv, "recv") == 0) {
    687 				p->recv_seq = 1;
    688 			} else if (strcasecmp(*argv, "send") == 0) {
    689 				p->send_seq = 1;
    690 			} else if (strcasecmp(*argv, "none") == 0) {
    691 				p->recv_seq = 0;
    692 				p->send_seq = 0;
    693 			} else {
    694 				fprintf(stderr,
    695 					"Unknown seq value \"%s\"\n", *argv);
    696 				exit(-1);
    697 			}
    698 		} else if (strcmp(*argv, "tunnel") == 0) {
    699 			p->tunnel = 1;
    700 		} else if (strcmp(*argv, "session") == 0) {
    701 			p->session = 1;
    702 		} else if (matches(*argv, "help") == 0) {
    703 			usage();
    704 		} else {
    705 			fprintf(stderr, "Unknown command: %s\n", *argv);
    706 			usage();
    707 		}
    708 
    709 		argc--; argv++;
    710 	}
    711 
    712 	return 0;
    713 }
    714 
    715 
    716 static int do_add(int argc, char **argv)
    717 {
    718 	struct l2tp_parm p;
    719 	int ret = 0;
    720 
    721 	if (parse_args(argc, argv, L2TP_ADD, &p) < 0)
    722 		return -1;
    723 
    724 	if (!p.tunnel && !p.session)
    725 		missarg("tunnel or session");
    726 
    727 	if (p.tunnel_id == 0)
    728 		missarg("tunnel_id");
    729 
    730 	/* session_id and peer_session_id must be provided for sessions */
    731 	if ((p.session) && (p.peer_session_id == 0))
    732 		missarg("peer_session_id");
    733 	if ((p.session) && (p.session_id == 0))
    734 		missarg("session_id");
    735 
    736 	/* peer_tunnel_id is needed for tunnels */
    737 	if ((p.tunnel) && (p.peer_tunnel_id == 0))
    738 		missarg("peer_tunnel_id");
    739 
    740 	if (p.tunnel) {
    741 		if (p.local_ip.family == AF_UNSPEC)
    742 			missarg("local");
    743 
    744 		if (p.peer_ip.family == AF_UNSPEC)
    745 			missarg("remote");
    746 
    747 		if (p.encap == L2TP_ENCAPTYPE_UDP) {
    748 			if (p.local_udp_port == 0)
    749 				missarg("udp_sport");
    750 			if (p.peer_udp_port == 0)
    751 				missarg("udp_dport");
    752 		}
    753 
    754 		ret = create_tunnel(&p);
    755 	}
    756 
    757 	if (p.session) {
    758 		/* Only ethernet pseudowires supported */
    759 		p.pw_type = L2TP_PWTYPE_ETH;
    760 
    761 		ret = create_session(&p);
    762 	}
    763 
    764 	return ret;
    765 }
    766 
    767 static int do_del(int argc, char **argv)
    768 {
    769 	struct l2tp_parm p;
    770 
    771 	if (parse_args(argc, argv, L2TP_DEL, &p) < 0)
    772 		return -1;
    773 
    774 	if (!p.tunnel && !p.session)
    775 		missarg("tunnel or session");
    776 
    777 	if ((p.tunnel) && (p.tunnel_id == 0))
    778 		missarg("tunnel_id");
    779 	if ((p.session) && (p.session_id == 0))
    780 		missarg("session_id");
    781 
    782 	if (p.session_id)
    783 		return delete_session(&p);
    784 	else
    785 		return delete_tunnel(&p);
    786 
    787 	return -1;
    788 }
    789 
    790 static int do_show(int argc, char **argv)
    791 {
    792 	struct l2tp_data data;
    793 	struct l2tp_parm *p = &data.config;
    794 
    795 	if (parse_args(argc, argv, L2TP_GET, p) < 0)
    796 		return -1;
    797 
    798 	if (!p->tunnel && !p->session)
    799 		missarg("tunnel or session");
    800 
    801 	if (p->session)
    802 		get_session(&data);
    803 	else
    804 		get_tunnel(&data);
    805 
    806 	return 0;
    807 }
    808 
    809 int do_ipl2tp(int argc, char **argv)
    810 {
    811 	if (argc < 1 || !matches(*argv, "help"))
    812 		usage();
    813 
    814 	if (genl_init_handle(&genl_rth, L2TP_GENL_NAME, &genl_family))
    815 		exit(1);
    816 
    817 	if (matches(*argv, "add") == 0)
    818 		return do_add(argc-1, argv+1);
    819 	if (matches(*argv, "delete") == 0)
    820 		return do_del(argc-1, argv+1);
    821 	if (matches(*argv, "show") == 0 ||
    822 	    matches(*argv, "lst") == 0 ||
    823 	    matches(*argv, "list") == 0)
    824 		return do_show(argc-1, argv+1);
    825 
    826 	fprintf(stderr,
    827 		"Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv);
    828 	exit(-1);
    829 }
    830