1// SPDX-License-Identifier: GPL-2.0
2
3#include <errno.h>
4#include <error.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <unistd.h>
9#include <limits.h>
10
11#include <sys/socket.h>
12#include <sys/types.h>
13
14#include <arpa/inet.h>
15#include <net/if.h>
16
17#include <linux/rtnetlink.h>
18#include <linux/genetlink.h>
19
20#include "linux/mptcp.h"
21
22#ifndef MPTCP_PM_NAME
23#define MPTCP_PM_NAME		"mptcp_pm"
24#endif
25#ifndef MPTCP_PM_EVENTS
26#define MPTCP_PM_EVENTS		"mptcp_pm_events"
27#endif
28#ifndef IPPROTO_MPTCP
29#define IPPROTO_MPTCP 262
30#endif
31
32static void syntax(char *argv[])
33{
34	fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]);
35	fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n");
36	fprintf(stderr, "\tann <local-ip> id <local-id> token <token> [port <local-port>] [dev <name>]\n");
37	fprintf(stderr, "\trem id <local-id> token <token>\n");
38	fprintf(stderr, "\tcsf lip <local-ip> lid <local-id> rip <remote-ip> rport <remote-port> token <token>\n");
39	fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n");
40	fprintf(stderr, "\tdel <id> [<ip>]\n");
41	fprintf(stderr, "\tget <id>\n");
42	fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>] [token <token>] [rip <ip>] [rport <port>]\n");
43	fprintf(stderr, "\tflush\n");
44	fprintf(stderr, "\tdump\n");
45	fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
46	fprintf(stderr, "\tevents\n");
47	fprintf(stderr, "\tlisten <local-ip> <local-port>\n");
48	exit(0);
49}
50
51static int init_genl_req(char *data, int family, int cmd, int version)
52{
53	struct nlmsghdr *nh = (void *)data;
54	struct genlmsghdr *gh;
55	int off = 0;
56
57	nh->nlmsg_type = family;
58	nh->nlmsg_flags = NLM_F_REQUEST;
59	nh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
60	off += NLMSG_ALIGN(sizeof(*nh));
61
62	gh = (void *)(data + off);
63	gh->cmd = cmd;
64	gh->version = version;
65	off += NLMSG_ALIGN(sizeof(*gh));
66	return off;
67}
68
69static int nl_error(struct nlmsghdr *nh)
70{
71	struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh);
72	int len = nh->nlmsg_len - sizeof(*nh);
73	uint32_t off;
74
75	if (len < sizeof(struct nlmsgerr)) {
76		error(1, 0, "netlink error message truncated %d min %ld", len,
77		      sizeof(struct nlmsgerr));
78		return -1;
79	}
80
81	if (err->error) {
82		/* check messages from kernel */
83		struct rtattr *attrs = (struct rtattr *)NLMSG_DATA(nh);
84
85		fprintf(stderr, "netlink error %d (%s)\n",
86			err->error, strerror(-err->error));
87
88		while (RTA_OK(attrs, len)) {
89			if (attrs->rta_type == NLMSGERR_ATTR_MSG)
90				fprintf(stderr, "netlink ext ack msg: %s\n",
91					(char *)RTA_DATA(attrs));
92			if (attrs->rta_type == NLMSGERR_ATTR_OFFS) {
93				memcpy(&off, RTA_DATA(attrs), 4);
94				fprintf(stderr, "netlink err off %d\n",
95					(int)off);
96			}
97			attrs = RTA_NEXT(attrs, len);
98		}
99		return -1;
100	}
101
102	return 0;
103}
104
105static int capture_events(int fd, int event_group)
106{
107	u_int8_t buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
108			NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024];
109	struct genlmsghdr *ghdr;
110	struct rtattr *attrs;
111	struct nlmsghdr *nh;
112	int ret = 0;
113	int res_len;
114	int msg_len;
115	fd_set rfds;
116
117	if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
118		       &event_group, sizeof(event_group)) < 0)
119		error(1, errno, "could not join the " MPTCP_PM_EVENTS " mcast group");
120
121	do {
122		FD_ZERO(&rfds);
123		FD_SET(fd, &rfds);
124		res_len = NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
125		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024;
126
127		ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
128
129		if (ret < 0)
130			error(1, ret, "error in select() on NL socket");
131
132		res_len = recv(fd, buffer, res_len, 0);
133		if (res_len < 0)
134			error(1, res_len, "error on recv() from NL socket");
135
136		nh = (struct nlmsghdr *)buffer;
137
138		for (; NLMSG_OK(nh, res_len); nh = NLMSG_NEXT(nh, res_len)) {
139			if (nh->nlmsg_type == NLMSG_ERROR)
140				error(1, NLMSG_ERROR, "received invalid NL message");
141
142			ghdr = (struct genlmsghdr *)NLMSG_DATA(nh);
143
144			if (ghdr->cmd == 0)
145				continue;
146
147			fprintf(stderr, "type:%d", ghdr->cmd);
148
149			msg_len = nh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
150
151			attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
152			while (RTA_OK(attrs, msg_len)) {
153				if (attrs->rta_type == MPTCP_ATTR_TOKEN)
154					fprintf(stderr, ",token:%u", *(__u32 *)RTA_DATA(attrs));
155				else if (attrs->rta_type == MPTCP_ATTR_FAMILY)
156					fprintf(stderr, ",family:%u", *(__u16 *)RTA_DATA(attrs));
157				else if (attrs->rta_type == MPTCP_ATTR_LOC_ID)
158					fprintf(stderr, ",loc_id:%u", *(__u8 *)RTA_DATA(attrs));
159				else if (attrs->rta_type == MPTCP_ATTR_REM_ID)
160					fprintf(stderr, ",rem_id:%u", *(__u8 *)RTA_DATA(attrs));
161				else if (attrs->rta_type == MPTCP_ATTR_SADDR4) {
162					u_int32_t saddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
163
164					fprintf(stderr, ",saddr4:%u.%u.%u.%u", saddr4 >> 24,
165					       (saddr4 >> 16) & 0xFF, (saddr4 >> 8) & 0xFF,
166					       (saddr4 & 0xFF));
167				} else if (attrs->rta_type == MPTCP_ATTR_SADDR6) {
168					char buf[INET6_ADDRSTRLEN];
169
170					if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
171						      sizeof(buf)) != NULL)
172						fprintf(stderr, ",saddr6:%s", buf);
173				} else if (attrs->rta_type == MPTCP_ATTR_DADDR4) {
174					u_int32_t daddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
175
176					fprintf(stderr, ",daddr4:%u.%u.%u.%u", daddr4 >> 24,
177					       (daddr4 >> 16) & 0xFF, (daddr4 >> 8) & 0xFF,
178					       (daddr4 & 0xFF));
179				} else if (attrs->rta_type == MPTCP_ATTR_DADDR6) {
180					char buf[INET6_ADDRSTRLEN];
181
182					if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
183						      sizeof(buf)) != NULL)
184						fprintf(stderr, ",daddr6:%s", buf);
185				} else if (attrs->rta_type == MPTCP_ATTR_SPORT)
186					fprintf(stderr, ",sport:%u",
187						ntohs(*(__u16 *)RTA_DATA(attrs)));
188				else if (attrs->rta_type == MPTCP_ATTR_DPORT)
189					fprintf(stderr, ",dport:%u",
190						ntohs(*(__u16 *)RTA_DATA(attrs)));
191				else if (attrs->rta_type == MPTCP_ATTR_BACKUP)
192					fprintf(stderr, ",backup:%u", *(__u8 *)RTA_DATA(attrs));
193				else if (attrs->rta_type == MPTCP_ATTR_ERROR)
194					fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs));
195				else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE)
196					fprintf(stderr, ",server_side:%u", *(__u8 *)RTA_DATA(attrs));
197
198				attrs = RTA_NEXT(attrs, msg_len);
199			}
200		}
201		fprintf(stderr, "\n");
202	} while (1);
203
204	return 0;
205}
206
207/* do a netlink command and, if max > 0, fetch the reply ; nh's size >1024B */
208static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
209{
210	struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
211	socklen_t addr_len;
212	void *data = nh;
213	int rem, ret;
214	int err = 0;
215
216	/* If no expected answer, ask for an ACK to look for errors if any */
217	if (max == 0) {
218		nh->nlmsg_flags |= NLM_F_ACK;
219		max = 1024;
220	}
221
222	nh->nlmsg_len = len;
223	ret = sendto(fd, data, len, 0, (void *)&nladdr, sizeof(nladdr));
224	if (ret != len)
225		error(1, errno, "send netlink: %uB != %uB\n", ret, len);
226
227	addr_len = sizeof(nladdr);
228	rem = ret = recvfrom(fd, data, max, 0, (void *)&nladdr, &addr_len);
229	if (ret < 0)
230		error(1, errno, "recv netlink: %uB\n", ret);
231
232	/* Beware: the NLMSG_NEXT macro updates the 'rem' argument */
233	for (; NLMSG_OK(nh, rem); nh = NLMSG_NEXT(nh, rem)) {
234		if (nh->nlmsg_type == NLMSG_DONE)
235			break;
236
237		if (nh->nlmsg_type == NLMSG_ERROR && nl_error(nh))
238			err = 1;
239	}
240	if (err)
241		error(1, 0, "bailing out due to netlink error[s]");
242	return ret;
243}
244
245static int genl_parse_getfamily(struct nlmsghdr *nlh, int *pm_family,
246				int *events_mcast_grp)
247{
248	struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
249	int len = nlh->nlmsg_len;
250	struct rtattr *attrs;
251	struct rtattr *grps;
252	struct rtattr *grp;
253	int got_events_grp;
254	int got_family;
255	int grps_len;
256	int grp_len;
257
258	if (nlh->nlmsg_type != GENL_ID_CTRL)
259		error(1, errno, "Not a controller message, len=%d type=0x%x\n",
260		      nlh->nlmsg_len, nlh->nlmsg_type);
261
262	len -= NLMSG_LENGTH(GENL_HDRLEN);
263
264	if (len < 0)
265		error(1, errno, "wrong controller message len %d\n", len);
266
267	if (ghdr->cmd != CTRL_CMD_NEWFAMILY)
268		error(1, errno, "Unknown controller command %d\n", ghdr->cmd);
269
270	attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
271	got_family = 0;
272	got_events_grp = 0;
273
274	while (RTA_OK(attrs, len)) {
275		if (attrs->rta_type == CTRL_ATTR_FAMILY_ID) {
276			*pm_family = *(__u16 *)RTA_DATA(attrs);
277			got_family = 1;
278		} else if (attrs->rta_type == CTRL_ATTR_MCAST_GROUPS) {
279			grps = RTA_DATA(attrs);
280			grps_len = RTA_PAYLOAD(attrs);
281
282			while (RTA_OK(grps, grps_len)) {
283				grp = RTA_DATA(grps);
284				grp_len = RTA_PAYLOAD(grps);
285				got_events_grp = 0;
286
287				while (RTA_OK(grp, grp_len)) {
288					if (grp->rta_type == CTRL_ATTR_MCAST_GRP_ID)
289						*events_mcast_grp = *(__u32 *)RTA_DATA(grp);
290					else if (grp->rta_type == CTRL_ATTR_MCAST_GRP_NAME &&
291						 !strcmp(RTA_DATA(grp), MPTCP_PM_EVENTS))
292						got_events_grp = 1;
293
294					grp = RTA_NEXT(grp, grp_len);
295				}
296
297				if (got_events_grp)
298					break;
299
300				grps = RTA_NEXT(grps, grps_len);
301			}
302		}
303
304		if (got_family && got_events_grp)
305			return 0;
306
307		attrs = RTA_NEXT(attrs, len);
308	}
309
310	error(1, errno, "can't find CTRL_ATTR_FAMILY_ID attr");
311	return -1;
312}
313
314static int resolve_mptcp_pm_netlink(int fd, int *pm_family, int *events_mcast_grp)
315{
316	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
317		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
318		  1024];
319	struct nlmsghdr *nh;
320	struct rtattr *rta;
321	int namelen;
322	int off = 0;
323
324	memset(data, 0, sizeof(data));
325	nh = (void *)data;
326	off = init_genl_req(data, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 0);
327
328	rta = (void *)(data + off);
329	namelen = strlen(MPTCP_PM_NAME) + 1;
330	rta->rta_type = CTRL_ATTR_FAMILY_NAME;
331	rta->rta_len = RTA_LENGTH(namelen);
332	memcpy(RTA_DATA(rta), MPTCP_PM_NAME, namelen);
333	off += NLMSG_ALIGN(rta->rta_len);
334
335	do_nl_req(fd, nh, off, sizeof(data));
336	return genl_parse_getfamily((void *)data, pm_family, events_mcast_grp);
337}
338
339int dsf(int fd, int pm_family, int argc, char *argv[])
340{
341	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
342		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
343		  1024];
344	struct rtattr *rta, *addr;
345	u_int16_t family, port;
346	struct nlmsghdr *nh;
347	u_int32_t token;
348	int addr_start;
349	int off = 0;
350	int arg;
351
352	const char *params[5];
353
354	memset(params, 0, 5 * sizeof(const char *));
355
356	memset(data, 0, sizeof(data));
357	nh = (void *)data;
358	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_DESTROY,
359			    MPTCP_PM_VER);
360
361	if (argc < 12)
362		syntax(argv);
363
364	/* Params recorded in this order:
365	 * <local-ip>, <local-port>, <remote-ip>, <remote-port>, <token>
366	 */
367	for (arg = 2; arg < argc; arg++) {
368		if (!strcmp(argv[arg], "lip")) {
369			if (++arg >= argc)
370				error(1, 0, " missing local IP");
371
372			params[0] = argv[arg];
373		} else if (!strcmp(argv[arg], "lport")) {
374			if (++arg >= argc)
375				error(1, 0, " missing local port");
376
377			params[1] = argv[arg];
378		} else if (!strcmp(argv[arg], "rip")) {
379			if (++arg >= argc)
380				error(1, 0, " missing remote IP");
381
382			params[2] = argv[arg];
383		} else if (!strcmp(argv[arg], "rport")) {
384			if (++arg >= argc)
385				error(1, 0, " missing remote port");
386
387			params[3] = argv[arg];
388		} else if (!strcmp(argv[arg], "token")) {
389			if (++arg >= argc)
390				error(1, 0, " missing token");
391
392			params[4] = argv[arg];
393		} else
394			error(1, 0, "unknown keyword %s", argv[arg]);
395	}
396
397	for (arg = 0; arg < 4; arg = arg + 2) {
398		/*  addr header */
399		addr_start = off;
400		addr = (void *)(data + off);
401		addr->rta_type = NLA_F_NESTED |
402			((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
403		addr->rta_len = RTA_LENGTH(0);
404		off += NLMSG_ALIGN(addr->rta_len);
405
406		/*  addr data */
407		rta = (void *)(data + off);
408		if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
409			family = AF_INET;
410			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
411			rta->rta_len = RTA_LENGTH(4);
412		} else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
413			family = AF_INET6;
414			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
415			rta->rta_len = RTA_LENGTH(16);
416		} else
417			error(1, errno, "can't parse ip %s", params[arg]);
418		off += NLMSG_ALIGN(rta->rta_len);
419
420		/* family */
421		rta = (void *)(data + off);
422		rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
423		rta->rta_len = RTA_LENGTH(2);
424		memcpy(RTA_DATA(rta), &family, 2);
425		off += NLMSG_ALIGN(rta->rta_len);
426
427		/*  port */
428		port = atoi(params[arg + 1]);
429		rta = (void *)(data + off);
430		rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
431		rta->rta_len = RTA_LENGTH(2);
432		memcpy(RTA_DATA(rta), &port, 2);
433		off += NLMSG_ALIGN(rta->rta_len);
434
435		addr->rta_len = off - addr_start;
436	}
437
438	/* token */
439	token = strtoul(params[4], NULL, 10);
440	rta = (void *)(data + off);
441	rta->rta_type = MPTCP_PM_ATTR_TOKEN;
442	rta->rta_len = RTA_LENGTH(4);
443	memcpy(RTA_DATA(rta), &token, 4);
444	off += NLMSG_ALIGN(rta->rta_len);
445
446	do_nl_req(fd, nh, off, 0);
447
448	return 0;
449}
450
451int csf(int fd, int pm_family, int argc, char *argv[])
452{
453	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
454		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
455		  1024];
456	u_int32_t flags = MPTCP_PM_ADDR_FLAG_SUBFLOW;
457	const char *params[5];
458	struct nlmsghdr *nh;
459	struct rtattr *addr;
460	struct rtattr *rta;
461	u_int16_t family;
462	u_int32_t token;
463	u_int16_t port;
464	int addr_start;
465	u_int8_t id;
466	int off = 0;
467	int arg;
468
469	memset(params, 0, 5 * sizeof(const char *));
470
471	memset(data, 0, sizeof(data));
472	nh = (void *)data;
473	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_CREATE,
474			    MPTCP_PM_VER);
475
476	if (argc < 12)
477		syntax(argv);
478
479	/* Params recorded in this order:
480	 * <local-ip>, <local-id>, <remote-ip>, <remote-port>, <token>
481	 */
482	for (arg = 2; arg < argc; arg++) {
483		if (!strcmp(argv[arg], "lip")) {
484			if (++arg >= argc)
485				error(1, 0, " missing local IP");
486
487			params[0] = argv[arg];
488		} else if (!strcmp(argv[arg], "lid")) {
489			if (++arg >= argc)
490				error(1, 0, " missing local id");
491
492			params[1] = argv[arg];
493		} else if (!strcmp(argv[arg], "rip")) {
494			if (++arg >= argc)
495				error(1, 0, " missing remote ip");
496
497			params[2] = argv[arg];
498		} else if (!strcmp(argv[arg], "rport")) {
499			if (++arg >= argc)
500				error(1, 0, " missing remote port");
501
502			params[3] = argv[arg];
503		} else if (!strcmp(argv[arg], "token")) {
504			if (++arg >= argc)
505				error(1, 0, " missing token");
506
507			params[4] = argv[arg];
508		} else
509			error(1, 0, "unknown param %s", argv[arg]);
510	}
511
512	for (arg = 0; arg < 4; arg = arg + 2) {
513		/*  addr header */
514		addr_start = off;
515		addr = (void *)(data + off);
516		addr->rta_type = NLA_F_NESTED |
517			((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
518		addr->rta_len = RTA_LENGTH(0);
519		off += NLMSG_ALIGN(addr->rta_len);
520
521		/*  addr data */
522		rta = (void *)(data + off);
523		if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
524			family = AF_INET;
525			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
526			rta->rta_len = RTA_LENGTH(4);
527		} else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
528			family = AF_INET6;
529			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
530			rta->rta_len = RTA_LENGTH(16);
531		} else
532			error(1, errno, "can't parse ip %s", params[arg]);
533		off += NLMSG_ALIGN(rta->rta_len);
534
535		/* family */
536		rta = (void *)(data + off);
537		rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
538		rta->rta_len = RTA_LENGTH(2);
539		memcpy(RTA_DATA(rta), &family, 2);
540		off += NLMSG_ALIGN(rta->rta_len);
541
542		if (arg == 2) {
543			/*  port */
544			port = atoi(params[arg + 1]);
545			rta = (void *)(data + off);
546			rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
547			rta->rta_len = RTA_LENGTH(2);
548			memcpy(RTA_DATA(rta), &port, 2);
549			off += NLMSG_ALIGN(rta->rta_len);
550		}
551
552		if (arg == 0) {
553			/* id */
554			id = atoi(params[arg + 1]);
555			rta = (void *)(data + off);
556			rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
557			rta->rta_len = RTA_LENGTH(1);
558			memcpy(RTA_DATA(rta), &id, 1);
559			off += NLMSG_ALIGN(rta->rta_len);
560		}
561
562		/* addr flags */
563		rta = (void *)(data + off);
564		rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
565		rta->rta_len = RTA_LENGTH(4);
566		memcpy(RTA_DATA(rta), &flags, 4);
567		off += NLMSG_ALIGN(rta->rta_len);
568
569		addr->rta_len = off - addr_start;
570	}
571
572	/* token */
573	token = strtoul(params[4], NULL, 10);
574	rta = (void *)(data + off);
575	rta->rta_type = MPTCP_PM_ATTR_TOKEN;
576	rta->rta_len = RTA_LENGTH(4);
577	memcpy(RTA_DATA(rta), &token, 4);
578	off += NLMSG_ALIGN(rta->rta_len);
579
580	do_nl_req(fd, nh, off, 0);
581
582	return 0;
583}
584
585int remove_addr(int fd, int pm_family, int argc, char *argv[])
586{
587	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
588		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
589		  1024];
590	struct nlmsghdr *nh;
591	struct rtattr *rta;
592	u_int32_t token;
593	u_int8_t id;
594	int off = 0;
595	int arg;
596
597	memset(data, 0, sizeof(data));
598	nh = (void *)data;
599	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_REMOVE,
600			    MPTCP_PM_VER);
601
602	if (argc < 6)
603		syntax(argv);
604
605	for (arg = 2; arg < argc; arg++) {
606		if (!strcmp(argv[arg], "id")) {
607			if (++arg >= argc)
608				error(1, 0, " missing id value");
609
610			id = atoi(argv[arg]);
611			rta = (void *)(data + off);
612			rta->rta_type = MPTCP_PM_ATTR_LOC_ID;
613			rta->rta_len = RTA_LENGTH(1);
614			memcpy(RTA_DATA(rta), &id, 1);
615			off += NLMSG_ALIGN(rta->rta_len);
616		} else if (!strcmp(argv[arg], "token")) {
617			if (++arg >= argc)
618				error(1, 0, " missing token value");
619
620			token = strtoul(argv[arg], NULL, 10);
621			rta = (void *)(data + off);
622			rta->rta_type = MPTCP_PM_ATTR_TOKEN;
623			rta->rta_len = RTA_LENGTH(4);
624			memcpy(RTA_DATA(rta), &token, 4);
625			off += NLMSG_ALIGN(rta->rta_len);
626		} else
627			error(1, 0, "unknown keyword %s", argv[arg]);
628	}
629
630	do_nl_req(fd, nh, off, 0);
631	return 0;
632}
633
634int announce_addr(int fd, int pm_family, int argc, char *argv[])
635{
636	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
637		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
638		  1024];
639	u_int32_t flags = MPTCP_PM_ADDR_FLAG_SIGNAL;
640	u_int32_t token = UINT_MAX;
641	struct rtattr *rta, *addr;
642	u_int32_t id = UINT_MAX;
643	struct nlmsghdr *nh;
644	u_int16_t family;
645	int addr_start;
646	int off = 0;
647	int arg;
648
649	memset(data, 0, sizeof(data));
650	nh = (void *)data;
651	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ANNOUNCE,
652			    MPTCP_PM_VER);
653
654	if (argc < 7)
655		syntax(argv);
656
657	/* local-ip header */
658	addr_start = off;
659	addr = (void *)(data + off);
660	addr->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
661	addr->rta_len = RTA_LENGTH(0);
662	off += NLMSG_ALIGN(addr->rta_len);
663
664	/* local-ip data */
665	/* record addr type */
666	rta = (void *)(data + off);
667	if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
668		family = AF_INET;
669		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
670		rta->rta_len = RTA_LENGTH(4);
671	} else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
672		family = AF_INET6;
673		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
674		rta->rta_len = RTA_LENGTH(16);
675	} else
676		error(1, errno, "can't parse ip %s", argv[2]);
677	off += NLMSG_ALIGN(rta->rta_len);
678
679	/* addr family */
680	rta = (void *)(data + off);
681	rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
682	rta->rta_len = RTA_LENGTH(2);
683	memcpy(RTA_DATA(rta), &family, 2);
684	off += NLMSG_ALIGN(rta->rta_len);
685
686	for (arg = 3; arg < argc; arg++) {
687		if (!strcmp(argv[arg], "id")) {
688			/* local-id */
689			if (++arg >= argc)
690				error(1, 0, " missing id value");
691
692			id = atoi(argv[arg]);
693			rta = (void *)(data + off);
694			rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
695			rta->rta_len = RTA_LENGTH(1);
696			memcpy(RTA_DATA(rta), &id, 1);
697			off += NLMSG_ALIGN(rta->rta_len);
698		} else if (!strcmp(argv[arg], "dev")) {
699			/* for the if_index */
700			int32_t ifindex;
701
702			if (++arg >= argc)
703				error(1, 0, " missing dev name");
704
705			ifindex = if_nametoindex(argv[arg]);
706			if (!ifindex)
707				error(1, errno, "unknown device %s", argv[arg]);
708
709			rta = (void *)(data + off);
710			rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
711			rta->rta_len = RTA_LENGTH(4);
712			memcpy(RTA_DATA(rta), &ifindex, 4);
713			off += NLMSG_ALIGN(rta->rta_len);
714		} else if (!strcmp(argv[arg], "port")) {
715			/* local-port (optional) */
716			u_int16_t port;
717
718			if (++arg >= argc)
719				error(1, 0, " missing port value");
720
721			port = atoi(argv[arg]);
722			rta = (void *)(data + off);
723			rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
724			rta->rta_len = RTA_LENGTH(2);
725			memcpy(RTA_DATA(rta), &port, 2);
726			off += NLMSG_ALIGN(rta->rta_len);
727		} else if (!strcmp(argv[arg], "token")) {
728			/* MPTCP connection token */
729			if (++arg >= argc)
730				error(1, 0, " missing token value");
731
732			token = strtoul(argv[arg], NULL, 10);
733		} else
734			error(1, 0, "unknown keyword %s", argv[arg]);
735	}
736
737	/* addr flags */
738	rta = (void *)(data + off);
739	rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
740	rta->rta_len = RTA_LENGTH(4);
741	memcpy(RTA_DATA(rta), &flags, 4);
742	off += NLMSG_ALIGN(rta->rta_len);
743
744	addr->rta_len = off - addr_start;
745
746	if (id == UINT_MAX || token == UINT_MAX)
747		error(1, 0, " missing mandatory inputs");
748
749	/* token */
750	rta = (void *)(data + off);
751	rta->rta_type = MPTCP_PM_ATTR_TOKEN;
752	rta->rta_len = RTA_LENGTH(4);
753	memcpy(RTA_DATA(rta), &token, 4);
754	off += NLMSG_ALIGN(rta->rta_len);
755
756	do_nl_req(fd, nh, off, 0);
757
758	return 0;
759}
760
761int add_addr(int fd, int pm_family, int argc, char *argv[])
762{
763	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
764		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
765		  1024];
766	struct rtattr *rta, *nest;
767	struct nlmsghdr *nh;
768	u_int32_t flags = 0;
769	u_int16_t family;
770	int nest_start;
771	u_int8_t id;
772	int off = 0;
773	int arg;
774
775	memset(data, 0, sizeof(data));
776	nh = (void *)data;
777	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ADD_ADDR,
778			    MPTCP_PM_VER);
779
780	if (argc < 3)
781		syntax(argv);
782
783	nest_start = off;
784	nest = (void *)(data + off);
785	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
786	nest->rta_len = RTA_LENGTH(0);
787	off += NLMSG_ALIGN(nest->rta_len);
788
789	/* addr data */
790	rta = (void *)(data + off);
791	if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
792		family = AF_INET;
793		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
794		rta->rta_len = RTA_LENGTH(4);
795	} else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
796		family = AF_INET6;
797		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
798		rta->rta_len = RTA_LENGTH(16);
799	} else
800		error(1, errno, "can't parse ip %s", argv[2]);
801	off += NLMSG_ALIGN(rta->rta_len);
802
803	/* family */
804	rta = (void *)(data + off);
805	rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
806	rta->rta_len = RTA_LENGTH(2);
807	memcpy(RTA_DATA(rta), &family, 2);
808	off += NLMSG_ALIGN(rta->rta_len);
809
810	for (arg = 3; arg < argc; arg++) {
811		if (!strcmp(argv[arg], "flags")) {
812			char *tok, *str;
813
814			/* flags */
815			if (++arg >= argc)
816				error(1, 0, " missing flags value");
817
818			/* do not support flag list yet */
819			for (str = argv[arg]; (tok = strtok(str, ","));
820			     str = NULL) {
821				if (!strcmp(tok, "subflow"))
822					flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;
823				else if (!strcmp(tok, "signal"))
824					flags |= MPTCP_PM_ADDR_FLAG_SIGNAL;
825				else if (!strcmp(tok, "backup"))
826					flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
827				else if (!strcmp(tok, "fullmesh"))
828					flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
829				else
830					error(1, errno,
831					      "unknown flag %s", argv[arg]);
832			}
833
834			if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
835			    flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
836				error(1, errno, "error flag fullmesh");
837			}
838
839			rta = (void *)(data + off);
840			rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
841			rta->rta_len = RTA_LENGTH(4);
842			memcpy(RTA_DATA(rta), &flags, 4);
843			off += NLMSG_ALIGN(rta->rta_len);
844		} else if (!strcmp(argv[arg], "id")) {
845			if (++arg >= argc)
846				error(1, 0, " missing id value");
847
848			id = atoi(argv[arg]);
849			rta = (void *)(data + off);
850			rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
851			rta->rta_len = RTA_LENGTH(1);
852			memcpy(RTA_DATA(rta), &id, 1);
853			off += NLMSG_ALIGN(rta->rta_len);
854		} else if (!strcmp(argv[arg], "dev")) {
855			int32_t ifindex;
856
857			if (++arg >= argc)
858				error(1, 0, " missing dev name");
859
860			ifindex = if_nametoindex(argv[arg]);
861			if (!ifindex)
862				error(1, errno, "unknown device %s", argv[arg]);
863
864			rta = (void *)(data + off);
865			rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
866			rta->rta_len = RTA_LENGTH(4);
867			memcpy(RTA_DATA(rta), &ifindex, 4);
868			off += NLMSG_ALIGN(rta->rta_len);
869		} else if (!strcmp(argv[arg], "port")) {
870			u_int16_t port;
871
872			if (++arg >= argc)
873				error(1, 0, " missing port value");
874			if (!(flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
875				error(1, 0, " flags must be signal when using port");
876
877			port = atoi(argv[arg]);
878			rta = (void *)(data + off);
879			rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
880			rta->rta_len = RTA_LENGTH(2);
881			memcpy(RTA_DATA(rta), &port, 2);
882			off += NLMSG_ALIGN(rta->rta_len);
883		} else
884			error(1, 0, "unknown keyword %s", argv[arg]);
885	}
886	nest->rta_len = off - nest_start;
887
888	do_nl_req(fd, nh, off, 0);
889	return 0;
890}
891
892int del_addr(int fd, int pm_family, int argc, char *argv[])
893{
894	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
895		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
896		  1024];
897	struct rtattr *rta, *nest;
898	struct nlmsghdr *nh;
899	u_int16_t family;
900	int nest_start;
901	u_int8_t id;
902	int off = 0;
903
904	memset(data, 0, sizeof(data));
905	nh = (void *)data;
906	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_DEL_ADDR,
907			    MPTCP_PM_VER);
908
909	/* the only argument is the address id (nonzero) */
910	if (argc != 3 && argc != 4)
911		syntax(argv);
912
913	id = atoi(argv[2]);
914	/* zero id with the IP address */
915	if (!id && argc != 4)
916		syntax(argv);
917
918	nest_start = off;
919	nest = (void *)(data + off);
920	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
921	nest->rta_len =  RTA_LENGTH(0);
922	off += NLMSG_ALIGN(nest->rta_len);
923
924	/* build a dummy addr with only the ID set */
925	rta = (void *)(data + off);
926	rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
927	rta->rta_len = RTA_LENGTH(1);
928	memcpy(RTA_DATA(rta), &id, 1);
929	off += NLMSG_ALIGN(rta->rta_len);
930
931	if (!id) {
932		/* addr data */
933		rta = (void *)(data + off);
934		if (inet_pton(AF_INET, argv[3], RTA_DATA(rta))) {
935			family = AF_INET;
936			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
937			rta->rta_len = RTA_LENGTH(4);
938		} else if (inet_pton(AF_INET6, argv[3], RTA_DATA(rta))) {
939			family = AF_INET6;
940			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
941			rta->rta_len = RTA_LENGTH(16);
942		} else {
943			error(1, errno, "can't parse ip %s", argv[3]);
944		}
945		off += NLMSG_ALIGN(rta->rta_len);
946
947		/* family */
948		rta = (void *)(data + off);
949		rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
950		rta->rta_len = RTA_LENGTH(2);
951		memcpy(RTA_DATA(rta), &family, 2);
952		off += NLMSG_ALIGN(rta->rta_len);
953	}
954	nest->rta_len = off - nest_start;
955
956	do_nl_req(fd, nh, off, 0);
957	return 0;
958}
959
960static void print_addr(struct rtattr *attrs, int len)
961{
962	uint16_t family = 0;
963	uint16_t port = 0;
964	char str[1024];
965	uint32_t flags;
966	uint8_t id;
967
968	while (RTA_OK(attrs, len)) {
969		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FAMILY)
970			memcpy(&family, RTA_DATA(attrs), 2);
971		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_PORT)
972			memcpy(&port, RTA_DATA(attrs), 2);
973		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR4) {
974			if (family != AF_INET)
975				error(1, errno, "wrong IP (v4) for family %d",
976				      family);
977			inet_ntop(AF_INET, RTA_DATA(attrs), str, sizeof(str));
978			printf("%s", str);
979			if (port)
980				printf(" %d", port);
981		}
982		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR6) {
983			if (family != AF_INET6)
984				error(1, errno, "wrong IP (v6) for family %d",
985				      family);
986			inet_ntop(AF_INET6, RTA_DATA(attrs), str, sizeof(str));
987			printf("%s", str);
988			if (port)
989				printf(" %d", port);
990		}
991		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ID) {
992			memcpy(&id, RTA_DATA(attrs), 1);
993			printf("id %d ", id);
994		}
995		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FLAGS) {
996			memcpy(&flags, RTA_DATA(attrs), 4);
997
998			printf("flags ");
999			if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
1000				printf("signal");
1001				flags &= ~MPTCP_PM_ADDR_FLAG_SIGNAL;
1002				if (flags)
1003					printf(",");
1004			}
1005
1006			if (flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
1007				printf("subflow");
1008				flags &= ~MPTCP_PM_ADDR_FLAG_SUBFLOW;
1009				if (flags)
1010					printf(",");
1011			}
1012
1013			if (flags & MPTCP_PM_ADDR_FLAG_BACKUP) {
1014				printf("backup");
1015				flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
1016				if (flags)
1017					printf(",");
1018			}
1019
1020			if (flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
1021				printf("fullmesh");
1022				flags &= ~MPTCP_PM_ADDR_FLAG_FULLMESH;
1023				if (flags)
1024					printf(",");
1025			}
1026
1027			if (flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
1028				printf("implicit");
1029				flags &= ~MPTCP_PM_ADDR_FLAG_IMPLICIT;
1030				if (flags)
1031					printf(",");
1032			}
1033
1034			/* bump unknown flags, if any */
1035			if (flags)
1036				printf("0x%x", flags);
1037			printf(" ");
1038		}
1039		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_IF_IDX) {
1040			char name[IF_NAMESIZE], *ret;
1041			int32_t ifindex;
1042
1043			memcpy(&ifindex, RTA_DATA(attrs), 4);
1044			ret = if_indextoname(ifindex, name);
1045			if (ret)
1046				printf("dev %s ", ret);
1047			else
1048				printf("dev unknown/%d", ifindex);
1049		}
1050
1051		attrs = RTA_NEXT(attrs, len);
1052	}
1053	printf("\n");
1054}
1055
1056static void print_addrs(struct nlmsghdr *nh, int pm_family, int total_len)
1057{
1058	struct rtattr *attrs;
1059
1060	for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
1061		int len = nh->nlmsg_len;
1062
1063		if (nh->nlmsg_type == NLMSG_DONE)
1064			break;
1065		if (nh->nlmsg_type == NLMSG_ERROR)
1066			nl_error(nh);
1067		if (nh->nlmsg_type != pm_family)
1068			continue;
1069
1070		len -= NLMSG_LENGTH(GENL_HDRLEN);
1071		attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
1072					   GENL_HDRLEN);
1073		while (RTA_OK(attrs, len)) {
1074			if (attrs->rta_type ==
1075			    (MPTCP_PM_ATTR_ADDR | NLA_F_NESTED))
1076				print_addr((void *)RTA_DATA(attrs),
1077					   attrs->rta_len);
1078			attrs = RTA_NEXT(attrs, len);
1079		}
1080	}
1081}
1082
1083int get_addr(int fd, int pm_family, int argc, char *argv[])
1084{
1085	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1086		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1087		  1024];
1088	struct rtattr *rta, *nest;
1089	struct nlmsghdr *nh;
1090	u_int32_t token = 0;
1091	int nest_start;
1092	u_int8_t id;
1093	int off = 0;
1094
1095	memset(data, 0, sizeof(data));
1096	nh = (void *)data;
1097	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
1098			    MPTCP_PM_VER);
1099
1100	/* the only argument is the address id */
1101	if (argc != 3 && argc != 5)
1102		syntax(argv);
1103
1104	id = atoi(argv[2]);
1105	if (argc == 5 && !strcmp(argv[3], "token"))
1106		token = strtoul(argv[4], NULL, 10);
1107
1108	nest_start = off;
1109	nest = (void *)(data + off);
1110	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
1111	nest->rta_len =  RTA_LENGTH(0);
1112	off += NLMSG_ALIGN(nest->rta_len);
1113
1114	/* build a dummy addr with only the ID set */
1115	rta = (void *)(data + off);
1116	rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
1117	rta->rta_len = RTA_LENGTH(1);
1118	memcpy(RTA_DATA(rta), &id, 1);
1119	off += NLMSG_ALIGN(rta->rta_len);
1120	nest->rta_len = off - nest_start;
1121
1122	/* token */
1123	if (token) {
1124		rta = (void *)(data + off);
1125		rta->rta_type = MPTCP_PM_ATTR_TOKEN;
1126		rta->rta_len = RTA_LENGTH(4);
1127		memcpy(RTA_DATA(rta), &token, 4);
1128		off += NLMSG_ALIGN(rta->rta_len);
1129	}
1130
1131	print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
1132	return 0;
1133}
1134
1135int dump_addrs(int fd, int pm_family, int argc, char *argv[])
1136{
1137	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1138		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1139		  1024];
1140	pid_t pid = getpid();
1141	struct nlmsghdr *nh;
1142	u_int32_t token = 0;
1143	struct rtattr *rta;
1144	int off = 0;
1145
1146	if (argc != 2 && argc != 4)
1147		syntax(argv);
1148
1149	if (argc == 4 && !strcmp(argv[2], "token"))
1150		token = strtoul(argv[3], NULL, 10);
1151
1152	memset(data, 0, sizeof(data));
1153	nh = (void *)data;
1154	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
1155			    MPTCP_PM_VER);
1156	nh->nlmsg_flags |= NLM_F_DUMP;
1157	nh->nlmsg_seq = 1;
1158	nh->nlmsg_pid = pid;
1159	nh->nlmsg_len = off;
1160
1161	/* token */
1162	if (token) {
1163		rta = (void *)(data + off);
1164		rta->rta_type = MPTCP_PM_ATTR_TOKEN;
1165		rta->rta_len = RTA_LENGTH(4);
1166		memcpy(RTA_DATA(rta), &token, 4);
1167		off += NLMSG_ALIGN(rta->rta_len);
1168	}
1169
1170	print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
1171	return 0;
1172}
1173
1174int flush_addrs(int fd, int pm_family, int argc, char *argv[])
1175{
1176	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1177		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1178		  1024];
1179	struct nlmsghdr *nh;
1180	int off = 0;
1181
1182	memset(data, 0, sizeof(data));
1183	nh = (void *)data;
1184	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_FLUSH_ADDRS,
1185			    MPTCP_PM_VER);
1186
1187	do_nl_req(fd, nh, off, 0);
1188	return 0;
1189}
1190
1191static void print_limits(struct nlmsghdr *nh, int pm_family, int total_len)
1192{
1193	struct rtattr *attrs;
1194	uint32_t max;
1195
1196	for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
1197		int len = nh->nlmsg_len;
1198
1199		if (nh->nlmsg_type == NLMSG_DONE)
1200			break;
1201		if (nh->nlmsg_type == NLMSG_ERROR)
1202			nl_error(nh);
1203		if (nh->nlmsg_type != pm_family)
1204			continue;
1205
1206		len -= NLMSG_LENGTH(GENL_HDRLEN);
1207		attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
1208					   GENL_HDRLEN);
1209		while (RTA_OK(attrs, len)) {
1210			int type = attrs->rta_type;
1211
1212			if (type != MPTCP_PM_ATTR_RCV_ADD_ADDRS &&
1213			    type != MPTCP_PM_ATTR_SUBFLOWS)
1214				goto next;
1215
1216			memcpy(&max, RTA_DATA(attrs), 4);
1217			printf("%s %u\n", type == MPTCP_PM_ATTR_SUBFLOWS ?
1218					  "subflows" : "accept", max);
1219
1220next:
1221			attrs = RTA_NEXT(attrs, len);
1222		}
1223	}
1224}
1225
1226int get_set_limits(int fd, int pm_family, int argc, char *argv[])
1227{
1228	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1229		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1230		  1024];
1231	uint32_t rcv_addr = 0, subflows = 0;
1232	int cmd, len = sizeof(data);
1233	struct nlmsghdr *nh;
1234	int off = 0;
1235
1236	/* limit */
1237	if (argc == 4) {
1238		rcv_addr = atoi(argv[2]);
1239		subflows = atoi(argv[3]);
1240		cmd = MPTCP_PM_CMD_SET_LIMITS;
1241	} else {
1242		cmd = MPTCP_PM_CMD_GET_LIMITS;
1243	}
1244
1245	memset(data, 0, sizeof(data));
1246	nh = (void *)data;
1247	off = init_genl_req(data, pm_family, cmd, MPTCP_PM_VER);
1248
1249	/* limit */
1250	if (cmd == MPTCP_PM_CMD_SET_LIMITS) {
1251		struct rtattr *rta = (void *)(data + off);
1252
1253		rta->rta_type = MPTCP_PM_ATTR_RCV_ADD_ADDRS;
1254		rta->rta_len = RTA_LENGTH(4);
1255		memcpy(RTA_DATA(rta), &rcv_addr, 4);
1256		off += NLMSG_ALIGN(rta->rta_len);
1257
1258		rta = (void *)(data + off);
1259		rta->rta_type = MPTCP_PM_ATTR_SUBFLOWS;
1260		rta->rta_len = RTA_LENGTH(4);
1261		memcpy(RTA_DATA(rta), &subflows, 4);
1262		off += NLMSG_ALIGN(rta->rta_len);
1263
1264		/* do not expect a reply */
1265		len = 0;
1266	}
1267
1268	len = do_nl_req(fd, nh, off, len);
1269	if (cmd == MPTCP_PM_CMD_GET_LIMITS)
1270		print_limits(nh, pm_family, len);
1271	return 0;
1272}
1273
1274int add_listener(int argc, char *argv[])
1275{
1276	struct sockaddr_storage addr;
1277	struct sockaddr_in6 *a6;
1278	struct sockaddr_in *a4;
1279	u_int16_t family;
1280	int enable = 1;
1281	int sock;
1282	int err;
1283
1284	if (argc < 4)
1285		syntax(argv);
1286
1287	memset(&addr, 0, sizeof(struct sockaddr_storage));
1288	a4 = (struct sockaddr_in *)&addr;
1289	a6 = (struct sockaddr_in6 *)&addr;
1290
1291	if (inet_pton(AF_INET, argv[2], &a4->sin_addr)) {
1292		family = AF_INET;
1293		a4->sin_family = family;
1294		a4->sin_port = htons(atoi(argv[3]));
1295	} else if (inet_pton(AF_INET6, argv[2], &a6->sin6_addr)) {
1296		family = AF_INET6;
1297		a6->sin6_family = family;
1298		a6->sin6_port = htons(atoi(argv[3]));
1299	} else
1300		error(1, errno, "can't parse ip %s", argv[2]);
1301
1302	sock = socket(family, SOCK_STREAM, IPPROTO_MPTCP);
1303	if (sock < 0)
1304		error(1, errno, "can't create listener sock\n");
1305
1306	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) {
1307		close(sock);
1308		error(1, errno, "can't set SO_REUSEADDR on listener sock\n");
1309	}
1310
1311	err = bind(sock, (struct sockaddr *)&addr,
1312		   ((family == AF_INET) ? sizeof(struct sockaddr_in) :
1313		    sizeof(struct sockaddr_in6)));
1314
1315	if (err == 0 && listen(sock, 30) == 0)
1316		pause();
1317
1318	close(sock);
1319	return 0;
1320}
1321
1322int set_flags(int fd, int pm_family, int argc, char *argv[])
1323{
1324	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1325		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1326		  1024];
1327	struct rtattr *rta, *nest;
1328	struct nlmsghdr *nh;
1329	u_int32_t flags = 0;
1330	u_int32_t token = 0;
1331	u_int16_t rport = 0;
1332	u_int16_t family;
1333	void *rip = NULL;
1334	int nest_start;
1335	int use_id = 0;
1336	u_int8_t id;
1337	int off = 0;
1338	int arg = 2;
1339
1340	memset(data, 0, sizeof(data));
1341	nh = (void *)data;
1342	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS,
1343			    MPTCP_PM_VER);
1344
1345	if (argc < 3)
1346		syntax(argv);
1347
1348	nest_start = off;
1349	nest = (void *)(data + off);
1350	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
1351	nest->rta_len = RTA_LENGTH(0);
1352	off += NLMSG_ALIGN(nest->rta_len);
1353
1354	if (!strcmp(argv[arg], "id")) {
1355		if (++arg >= argc)
1356			error(1, 0, " missing id value");
1357
1358		use_id = 1;
1359		id = atoi(argv[arg]);
1360		rta = (void *)(data + off);
1361		rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
1362		rta->rta_len = RTA_LENGTH(1);
1363		memcpy(RTA_DATA(rta), &id, 1);
1364		off += NLMSG_ALIGN(rta->rta_len);
1365	} else {
1366		/* addr data */
1367		rta = (void *)(data + off);
1368		if (inet_pton(AF_INET, argv[arg], RTA_DATA(rta))) {
1369			family = AF_INET;
1370			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
1371			rta->rta_len = RTA_LENGTH(4);
1372		} else if (inet_pton(AF_INET6, argv[arg], RTA_DATA(rta))) {
1373			family = AF_INET6;
1374			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
1375			rta->rta_len = RTA_LENGTH(16);
1376		} else {
1377			error(1, errno, "can't parse ip %s", argv[arg]);
1378		}
1379		off += NLMSG_ALIGN(rta->rta_len);
1380
1381		/* family */
1382		rta = (void *)(data + off);
1383		rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
1384		rta->rta_len = RTA_LENGTH(2);
1385		memcpy(RTA_DATA(rta), &family, 2);
1386		off += NLMSG_ALIGN(rta->rta_len);
1387	}
1388
1389	if (++arg >= argc)
1390		error(1, 0, " missing flags keyword");
1391
1392	for (; arg < argc; arg++) {
1393		if (!strcmp(argv[arg], "token")) {
1394			if (++arg >= argc)
1395				error(1, 0, " missing token value");
1396
1397			/* token */
1398			token = strtoul(argv[arg], NULL, 10);
1399		} else if (!strcmp(argv[arg], "flags")) {
1400			char *tok, *str;
1401
1402			/* flags */
1403			if (++arg >= argc)
1404				error(1, 0, " missing flags value");
1405
1406			for (str = argv[arg]; (tok = strtok(str, ","));
1407			     str = NULL) {
1408				if (!strcmp(tok, "backup"))
1409					flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
1410				else if (!strcmp(tok, "fullmesh"))
1411					flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
1412				else if (strcmp(tok, "nobackup") &&
1413					 strcmp(tok, "nofullmesh"))
1414					error(1, errno,
1415					      "unknown flag %s", argv[arg]);
1416			}
1417
1418			rta = (void *)(data + off);
1419			rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
1420			rta->rta_len = RTA_LENGTH(4);
1421			memcpy(RTA_DATA(rta), &flags, 4);
1422			off += NLMSG_ALIGN(rta->rta_len);
1423		} else if (!strcmp(argv[arg], "port")) {
1424			u_int16_t port;
1425
1426			if (use_id)
1427				error(1, 0, " port can't be used with id");
1428
1429			if (++arg >= argc)
1430				error(1, 0, " missing port value");
1431
1432			port = atoi(argv[arg]);
1433			rta = (void *)(data + off);
1434			rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
1435			rta->rta_len = RTA_LENGTH(2);
1436			memcpy(RTA_DATA(rta), &port, 2);
1437			off += NLMSG_ALIGN(rta->rta_len);
1438		} else if (!strcmp(argv[arg], "rport")) {
1439			if (++arg >= argc)
1440				error(1, 0, " missing remote port");
1441
1442			rport = atoi(argv[arg]);
1443		} else if (!strcmp(argv[arg], "rip")) {
1444			if (++arg >= argc)
1445				error(1, 0, " missing remote ip");
1446
1447			rip = argv[arg];
1448		} else {
1449			error(1, 0, "unknown keyword %s", argv[arg]);
1450		}
1451	}
1452	nest->rta_len = off - nest_start;
1453
1454	/* token */
1455	if (token) {
1456		rta = (void *)(data + off);
1457		rta->rta_type = MPTCP_PM_ATTR_TOKEN;
1458		rta->rta_len = RTA_LENGTH(4);
1459		memcpy(RTA_DATA(rta), &token, 4);
1460		off += NLMSG_ALIGN(rta->rta_len);
1461	}
1462
1463	/* remote addr/port */
1464	if (rip) {
1465		nest_start = off;
1466		nest = (void *)(data + off);
1467		nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR_REMOTE;
1468		nest->rta_len = RTA_LENGTH(0);
1469		off += NLMSG_ALIGN(nest->rta_len);
1470
1471		/* addr data */
1472		rta = (void *)(data + off);
1473		if (inet_pton(AF_INET, rip, RTA_DATA(rta))) {
1474			family = AF_INET;
1475			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
1476			rta->rta_len = RTA_LENGTH(4);
1477		} else if (inet_pton(AF_INET6, rip, RTA_DATA(rta))) {
1478			family = AF_INET6;
1479			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
1480			rta->rta_len = RTA_LENGTH(16);
1481		} else {
1482			error(1, errno, "can't parse ip %s", (char *)rip);
1483		}
1484		off += NLMSG_ALIGN(rta->rta_len);
1485
1486		/* family */
1487		rta = (void *)(data + off);
1488		rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
1489		rta->rta_len = RTA_LENGTH(2);
1490		memcpy(RTA_DATA(rta), &family, 2);
1491		off += NLMSG_ALIGN(rta->rta_len);
1492
1493		if (rport) {
1494			rta = (void *)(data + off);
1495			rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
1496			rta->rta_len = RTA_LENGTH(2);
1497			memcpy(RTA_DATA(rta), &rport, 2);
1498			off += NLMSG_ALIGN(rta->rta_len);
1499		}
1500
1501		nest->rta_len = off - nest_start;
1502	}
1503
1504	do_nl_req(fd, nh, off, 0);
1505	return 0;
1506}
1507
1508int main(int argc, char *argv[])
1509{
1510	int events_mcast_grp;
1511	int pm_family;
1512	int fd;
1513
1514	if (argc < 2)
1515		syntax(argv);
1516
1517	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
1518	if (fd == -1)
1519		error(1, errno, "socket netlink");
1520
1521	resolve_mptcp_pm_netlink(fd, &pm_family, &events_mcast_grp);
1522
1523	if (!strcmp(argv[1], "add"))
1524		return add_addr(fd, pm_family, argc, argv);
1525	else if (!strcmp(argv[1], "ann"))
1526		return announce_addr(fd, pm_family, argc, argv);
1527	else if (!strcmp(argv[1], "rem"))
1528		return remove_addr(fd, pm_family, argc, argv);
1529	else if (!strcmp(argv[1], "csf"))
1530		return csf(fd, pm_family, argc, argv);
1531	else if (!strcmp(argv[1], "dsf"))
1532		return dsf(fd, pm_family, argc, argv);
1533	else if (!strcmp(argv[1], "del"))
1534		return del_addr(fd, pm_family, argc, argv);
1535	else if (!strcmp(argv[1], "flush"))
1536		return flush_addrs(fd, pm_family, argc, argv);
1537	else if (!strcmp(argv[1], "get"))
1538		return get_addr(fd, pm_family, argc, argv);
1539	else if (!strcmp(argv[1], "dump"))
1540		return dump_addrs(fd, pm_family, argc, argv);
1541	else if (!strcmp(argv[1], "limits"))
1542		return get_set_limits(fd, pm_family, argc, argv);
1543	else if (!strcmp(argv[1], "set"))
1544		return set_flags(fd, pm_family, argc, argv);
1545	else if (!strcmp(argv[1], "events"))
1546		return capture_events(fd, events_mcast_grp);
1547	else if (!strcmp(argv[1], "listen"))
1548		return add_listener(argc, argv);
1549
1550	fprintf(stderr, "unknown sub-command: %s", argv[1]);
1551	syntax(argv);
1552	return 0;
1553}
1554