xref: /linux/tools/testing/selftests/net/mptcp/pm_nl_ctl.c (revision ae22a94997b8a03dcb3c922857c203246711f9d4)
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 
32 static 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 
51 static 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 
69 static 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 
105 static 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 */
208 static 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 
245 static 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 
314 static 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 
339 int 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 
451 int 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 
585 int 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 
634 int 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 
761 int 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 
892 int 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 
960 static 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 
1056 static 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 
1083 int 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 
1135 int 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 
1174 int 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 
1191 static 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 
1220 next:
1221 			attrs = RTA_NEXT(attrs, len);
1222 		}
1223 	}
1224 }
1225 
1226 int 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 
1274 int 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 
1322 int 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 
1508 int 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