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