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