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 
26 static void syntax(char *argv[])
27 {
28 	fprintf(stderr, "%s add|get|set|del|flush|dump|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, "\tdel <id> [<ip>]\n");
33 	fprintf(stderr, "\tget <id>\n");
34 	fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>]\n");
35 	fprintf(stderr, "\tflush\n");
36 	fprintf(stderr, "\tdump\n");
37 	fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
38 	exit(0);
39 }
40 
41 static int init_genl_req(char *data, int family, int cmd, int version)
42 {
43 	struct nlmsghdr *nh = (void *)data;
44 	struct genlmsghdr *gh;
45 	int off = 0;
46 
47 	nh->nlmsg_type = family;
48 	nh->nlmsg_flags = NLM_F_REQUEST;
49 	nh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
50 	off += NLMSG_ALIGN(sizeof(*nh));
51 
52 	gh = (void *)(data + off);
53 	gh->cmd = cmd;
54 	gh->version = version;
55 	off += NLMSG_ALIGN(sizeof(*gh));
56 	return off;
57 }
58 
59 static void nl_error(struct nlmsghdr *nh)
60 {
61 	struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh);
62 	int len = nh->nlmsg_len - sizeof(*nh);
63 	uint32_t off;
64 
65 	if (len < sizeof(struct nlmsgerr))
66 		error(1, 0, "netlink error message truncated %d min %ld", len,
67 		      sizeof(struct nlmsgerr));
68 
69 	if (!err->error) {
70 		/* check messages from kernel */
71 		struct rtattr *attrs = (struct rtattr *)NLMSG_DATA(nh);
72 
73 		while (RTA_OK(attrs, len)) {
74 			if (attrs->rta_type == NLMSGERR_ATTR_MSG)
75 				fprintf(stderr, "netlink ext ack msg: %s\n",
76 					(char *)RTA_DATA(attrs));
77 			if (attrs->rta_type == NLMSGERR_ATTR_OFFS) {
78 				memcpy(&off, RTA_DATA(attrs), 4);
79 				fprintf(stderr, "netlink err off %d\n",
80 					(int)off);
81 			}
82 			attrs = RTA_NEXT(attrs, len);
83 		}
84 	} else {
85 		fprintf(stderr, "netlink error %d", err->error);
86 	}
87 }
88 
89 /* do a netlink command and, if max > 0, fetch the reply  */
90 static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
91 {
92 	struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
93 	socklen_t addr_len;
94 	void *data = nh;
95 	int rem, ret;
96 	int err = 0;
97 
98 	nh->nlmsg_len = len;
99 	ret = sendto(fd, data, len, 0, (void *)&nladdr, sizeof(nladdr));
100 	if (ret != len)
101 		error(1, errno, "send netlink: %uB != %uB\n", ret, len);
102 	if (max == 0)
103 		return 0;
104 
105 	addr_len = sizeof(nladdr);
106 	rem = ret = recvfrom(fd, data, max, 0, (void *)&nladdr, &addr_len);
107 	if (ret < 0)
108 		error(1, errno, "recv netlink: %uB\n", ret);
109 
110 	/* Beware: the NLMSG_NEXT macro updates the 'rem' argument */
111 	for (; NLMSG_OK(nh, rem); nh = NLMSG_NEXT(nh, rem)) {
112 		if (nh->nlmsg_type == NLMSG_ERROR) {
113 			nl_error(nh);
114 			err = 1;
115 		}
116 	}
117 	if (err)
118 		error(1, 0, "bailing out due to netlink error[s]");
119 	return ret;
120 }
121 
122 static int genl_parse_getfamily(struct nlmsghdr *nlh)
123 {
124 	struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
125 	int len = nlh->nlmsg_len;
126 	struct rtattr *attrs;
127 
128 	if (nlh->nlmsg_type != GENL_ID_CTRL)
129 		error(1, errno, "Not a controller message, len=%d type=0x%x\n",
130 		      nlh->nlmsg_len, nlh->nlmsg_type);
131 
132 	len -= NLMSG_LENGTH(GENL_HDRLEN);
133 
134 	if (len < 0)
135 		error(1, errno, "wrong controller message len %d\n", len);
136 
137 	if (ghdr->cmd != CTRL_CMD_NEWFAMILY)
138 		error(1, errno, "Unknown controller command %d\n", ghdr->cmd);
139 
140 	attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
141 	while (RTA_OK(attrs, len)) {
142 		if (attrs->rta_type == CTRL_ATTR_FAMILY_ID)
143 			return *(__u16 *)RTA_DATA(attrs);
144 		attrs = RTA_NEXT(attrs, len);
145 	}
146 
147 	error(1, errno, "can't find CTRL_ATTR_FAMILY_ID attr");
148 	return -1;
149 }
150 
151 static int resolve_mptcp_pm_netlink(int fd)
152 {
153 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
154 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
155 		  1024];
156 	struct nlmsghdr *nh;
157 	struct rtattr *rta;
158 	int namelen;
159 	int off = 0;
160 
161 	memset(data, 0, sizeof(data));
162 	nh = (void *)data;
163 	off = init_genl_req(data, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 0);
164 
165 	rta = (void *)(data + off);
166 	namelen = strlen(MPTCP_PM_NAME) + 1;
167 	rta->rta_type = CTRL_ATTR_FAMILY_NAME;
168 	rta->rta_len = RTA_LENGTH(namelen);
169 	memcpy(RTA_DATA(rta), MPTCP_PM_NAME, namelen);
170 	off += NLMSG_ALIGN(rta->rta_len);
171 
172 	do_nl_req(fd, nh, off, sizeof(data));
173 	return genl_parse_getfamily((void *)data);
174 }
175 
176 int remove_addr(int fd, int pm_family, int argc, char *argv[])
177 {
178 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
179 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
180 		  1024];
181 	struct nlmsghdr *nh;
182 	struct rtattr *rta;
183 	u_int32_t token;
184 	u_int8_t id;
185 	int off = 0;
186 	int arg;
187 
188 	memset(data, 0, sizeof(data));
189 	nh = (void *)data;
190 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_REMOVE,
191 			    MPTCP_PM_VER);
192 
193 	if (argc < 6)
194 		syntax(argv);
195 
196 	for (arg = 2; arg < argc; arg++) {
197 		if (!strcmp(argv[arg], "id")) {
198 			if (++arg >= argc)
199 				error(1, 0, " missing id value");
200 
201 			id = atoi(argv[arg]);
202 			rta = (void *)(data + off);
203 			rta->rta_type = MPTCP_PM_ATTR_LOC_ID;
204 			rta->rta_len = RTA_LENGTH(1);
205 			memcpy(RTA_DATA(rta), &id, 1);
206 			off += NLMSG_ALIGN(rta->rta_len);
207 		} else if (!strcmp(argv[arg], "token")) {
208 			if (++arg >= argc)
209 				error(1, 0, " missing token value");
210 
211 			token = atoi(argv[arg]);
212 			rta = (void *)(data + off);
213 			rta->rta_type = MPTCP_PM_ATTR_TOKEN;
214 			rta->rta_len = RTA_LENGTH(4);
215 			memcpy(RTA_DATA(rta), &token, 4);
216 			off += NLMSG_ALIGN(rta->rta_len);
217 		} else
218 			error(1, 0, "unknown keyword %s", argv[arg]);
219 	}
220 
221 	do_nl_req(fd, nh, off, 0);
222 	return 0;
223 }
224 
225 int announce_addr(int fd, int pm_family, int argc, char *argv[])
226 {
227 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
228 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
229 		  1024];
230 	u_int32_t flags = MPTCP_PM_ADDR_FLAG_SIGNAL;
231 	u_int32_t token = UINT_MAX;
232 	struct rtattr *rta, *addr;
233 	u_int32_t id = UINT_MAX;
234 	struct nlmsghdr *nh;
235 	u_int16_t family;
236 	int addr_start;
237 	int off = 0;
238 	int arg;
239 
240 	memset(data, 0, sizeof(data));
241 	nh = (void *)data;
242 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ANNOUNCE,
243 			    MPTCP_PM_VER);
244 
245 	if (argc < 7)
246 		syntax(argv);
247 
248 	/* local-ip header */
249 	addr_start = off;
250 	addr = (void *)(data + off);
251 	addr->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
252 	addr->rta_len = RTA_LENGTH(0);
253 	off += NLMSG_ALIGN(addr->rta_len);
254 
255 	/* local-ip data */
256 	/* record addr type */
257 	rta = (void *)(data + off);
258 	if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
259 		family = AF_INET;
260 		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
261 		rta->rta_len = RTA_LENGTH(4);
262 	} else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
263 		family = AF_INET6;
264 		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
265 		rta->rta_len = RTA_LENGTH(16);
266 	} else
267 		error(1, errno, "can't parse ip %s", argv[2]);
268 	off += NLMSG_ALIGN(rta->rta_len);
269 
270 	/* addr family */
271 	rta = (void *)(data + off);
272 	rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
273 	rta->rta_len = RTA_LENGTH(2);
274 	memcpy(RTA_DATA(rta), &family, 2);
275 	off += NLMSG_ALIGN(rta->rta_len);
276 
277 	for (arg = 3; arg < argc; arg++) {
278 		if (!strcmp(argv[arg], "id")) {
279 			/* local-id */
280 			if (++arg >= argc)
281 				error(1, 0, " missing id value");
282 
283 			id = atoi(argv[arg]);
284 			rta = (void *)(data + off);
285 			rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
286 			rta->rta_len = RTA_LENGTH(1);
287 			memcpy(RTA_DATA(rta), &id, 1);
288 			off += NLMSG_ALIGN(rta->rta_len);
289 		} else if (!strcmp(argv[arg], "dev")) {
290 			/* for the if_index */
291 			int32_t ifindex;
292 
293 			if (++arg >= argc)
294 				error(1, 0, " missing dev name");
295 
296 			ifindex = if_nametoindex(argv[arg]);
297 			if (!ifindex)
298 				error(1, errno, "unknown device %s", argv[arg]);
299 
300 			rta = (void *)(data + off);
301 			rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
302 			rta->rta_len = RTA_LENGTH(4);
303 			memcpy(RTA_DATA(rta), &ifindex, 4);
304 			off += NLMSG_ALIGN(rta->rta_len);
305 		} else if (!strcmp(argv[arg], "port")) {
306 			/* local-port (optional) */
307 			u_int16_t port;
308 
309 			if (++arg >= argc)
310 				error(1, 0, " missing port value");
311 
312 			port = atoi(argv[arg]);
313 			rta = (void *)(data + off);
314 			rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
315 			rta->rta_len = RTA_LENGTH(2);
316 			memcpy(RTA_DATA(rta), &port, 2);
317 			off += NLMSG_ALIGN(rta->rta_len);
318 		} else if (!strcmp(argv[arg], "token")) {
319 			/* MPTCP connection token */
320 			if (++arg >= argc)
321 				error(1, 0, " missing token value");
322 
323 			token = atoi(argv[arg]);
324 		} else
325 			error(1, 0, "unknown keyword %s", argv[arg]);
326 	}
327 
328 	/* addr flags */
329 	rta = (void *)(data + off);
330 	rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
331 	rta->rta_len = RTA_LENGTH(4);
332 	memcpy(RTA_DATA(rta), &flags, 4);
333 	off += NLMSG_ALIGN(rta->rta_len);
334 
335 	addr->rta_len = off - addr_start;
336 
337 	if (id == UINT_MAX || token == UINT_MAX)
338 		error(1, 0, " missing mandatory inputs");
339 
340 	/* token */
341 	rta = (void *)(data + off);
342 	rta->rta_type = MPTCP_PM_ATTR_TOKEN;
343 	rta->rta_len = RTA_LENGTH(4);
344 	memcpy(RTA_DATA(rta), &token, 4);
345 	off += NLMSG_ALIGN(rta->rta_len);
346 
347 	do_nl_req(fd, nh, off, 0);
348 
349 	return 0;
350 }
351 
352 int add_addr(int fd, int pm_family, int argc, char *argv[])
353 {
354 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
355 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
356 		  1024];
357 	struct rtattr *rta, *nest;
358 	struct nlmsghdr *nh;
359 	u_int32_t flags = 0;
360 	u_int16_t family;
361 	int nest_start;
362 	u_int8_t id;
363 	int off = 0;
364 	int arg;
365 
366 	memset(data, 0, sizeof(data));
367 	nh = (void *)data;
368 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ADD_ADDR,
369 			    MPTCP_PM_VER);
370 
371 	if (argc < 3)
372 		syntax(argv);
373 
374 	nest_start = off;
375 	nest = (void *)(data + off);
376 	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
377 	nest->rta_len = RTA_LENGTH(0);
378 	off += NLMSG_ALIGN(nest->rta_len);
379 
380 	/* addr data */
381 	rta = (void *)(data + off);
382 	if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
383 		family = AF_INET;
384 		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
385 		rta->rta_len = RTA_LENGTH(4);
386 	} else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
387 		family = AF_INET6;
388 		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
389 		rta->rta_len = RTA_LENGTH(16);
390 	} else
391 		error(1, errno, "can't parse ip %s", argv[2]);
392 	off += NLMSG_ALIGN(rta->rta_len);
393 
394 	/* family */
395 	rta = (void *)(data + off);
396 	rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
397 	rta->rta_len = RTA_LENGTH(2);
398 	memcpy(RTA_DATA(rta), &family, 2);
399 	off += NLMSG_ALIGN(rta->rta_len);
400 
401 	for (arg = 3; arg < argc; arg++) {
402 		if (!strcmp(argv[arg], "flags")) {
403 			char *tok, *str;
404 
405 			/* flags */
406 			if (++arg >= argc)
407 				error(1, 0, " missing flags value");
408 
409 			/* do not support flag list yet */
410 			for (str = argv[arg]; (tok = strtok(str, ","));
411 			     str = NULL) {
412 				if (!strcmp(tok, "subflow"))
413 					flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;
414 				else if (!strcmp(tok, "signal"))
415 					flags |= MPTCP_PM_ADDR_FLAG_SIGNAL;
416 				else if (!strcmp(tok, "backup"))
417 					flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
418 				else if (!strcmp(tok, "fullmesh"))
419 					flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
420 				else
421 					error(1, errno,
422 					      "unknown flag %s", argv[arg]);
423 			}
424 
425 			if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
426 			    flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
427 				error(1, errno, "error flag fullmesh");
428 			}
429 
430 			rta = (void *)(data + off);
431 			rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
432 			rta->rta_len = RTA_LENGTH(4);
433 			memcpy(RTA_DATA(rta), &flags, 4);
434 			off += NLMSG_ALIGN(rta->rta_len);
435 		} else if (!strcmp(argv[arg], "id")) {
436 			if (++arg >= argc)
437 				error(1, 0, " missing id value");
438 
439 			id = atoi(argv[arg]);
440 			rta = (void *)(data + off);
441 			rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
442 			rta->rta_len = RTA_LENGTH(1);
443 			memcpy(RTA_DATA(rta), &id, 1);
444 			off += NLMSG_ALIGN(rta->rta_len);
445 		} else if (!strcmp(argv[arg], "dev")) {
446 			int32_t ifindex;
447 
448 			if (++arg >= argc)
449 				error(1, 0, " missing dev name");
450 
451 			ifindex = if_nametoindex(argv[arg]);
452 			if (!ifindex)
453 				error(1, errno, "unknown device %s", argv[arg]);
454 
455 			rta = (void *)(data + off);
456 			rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
457 			rta->rta_len = RTA_LENGTH(4);
458 			memcpy(RTA_DATA(rta), &ifindex, 4);
459 			off += NLMSG_ALIGN(rta->rta_len);
460 		} else if (!strcmp(argv[arg], "port")) {
461 			u_int16_t port;
462 
463 			if (++arg >= argc)
464 				error(1, 0, " missing port value");
465 			if (!(flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
466 				error(1, 0, " flags must be signal when using port");
467 
468 			port = atoi(argv[arg]);
469 			rta = (void *)(data + off);
470 			rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
471 			rta->rta_len = RTA_LENGTH(2);
472 			memcpy(RTA_DATA(rta), &port, 2);
473 			off += NLMSG_ALIGN(rta->rta_len);
474 		} else
475 			error(1, 0, "unknown keyword %s", argv[arg]);
476 	}
477 	nest->rta_len = off - nest_start;
478 
479 	do_nl_req(fd, nh, off, 0);
480 	return 0;
481 }
482 
483 int del_addr(int fd, int pm_family, int argc, char *argv[])
484 {
485 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
486 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
487 		  1024];
488 	struct rtattr *rta, *nest;
489 	struct nlmsghdr *nh;
490 	u_int16_t family;
491 	int nest_start;
492 	u_int8_t id;
493 	int off = 0;
494 
495 	memset(data, 0, sizeof(data));
496 	nh = (void *)data;
497 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_DEL_ADDR,
498 			    MPTCP_PM_VER);
499 
500 	/* the only argument is the address id (nonzero) */
501 	if (argc != 3 && argc != 4)
502 		syntax(argv);
503 
504 	id = atoi(argv[2]);
505 	/* zero id with the IP address */
506 	if (!id && argc != 4)
507 		syntax(argv);
508 
509 	nest_start = off;
510 	nest = (void *)(data + off);
511 	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
512 	nest->rta_len =  RTA_LENGTH(0);
513 	off += NLMSG_ALIGN(nest->rta_len);
514 
515 	/* build a dummy addr with only the ID set */
516 	rta = (void *)(data + off);
517 	rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
518 	rta->rta_len = RTA_LENGTH(1);
519 	memcpy(RTA_DATA(rta), &id, 1);
520 	off += NLMSG_ALIGN(rta->rta_len);
521 
522 	if (!id) {
523 		/* addr data */
524 		rta = (void *)(data + off);
525 		if (inet_pton(AF_INET, argv[3], RTA_DATA(rta))) {
526 			family = AF_INET;
527 			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
528 			rta->rta_len = RTA_LENGTH(4);
529 		} else if (inet_pton(AF_INET6, argv[3], RTA_DATA(rta))) {
530 			family = AF_INET6;
531 			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
532 			rta->rta_len = RTA_LENGTH(16);
533 		} else {
534 			error(1, errno, "can't parse ip %s", argv[3]);
535 		}
536 		off += NLMSG_ALIGN(rta->rta_len);
537 
538 		/* family */
539 		rta = (void *)(data + off);
540 		rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
541 		rta->rta_len = RTA_LENGTH(2);
542 		memcpy(RTA_DATA(rta), &family, 2);
543 		off += NLMSG_ALIGN(rta->rta_len);
544 	}
545 	nest->rta_len = off - nest_start;
546 
547 	do_nl_req(fd, nh, off, 0);
548 	return 0;
549 }
550 
551 static void print_addr(struct rtattr *attrs, int len)
552 {
553 	uint16_t family = 0;
554 	uint16_t port = 0;
555 	char str[1024];
556 	uint32_t flags;
557 	uint8_t id;
558 
559 	while (RTA_OK(attrs, len)) {
560 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FAMILY)
561 			memcpy(&family, RTA_DATA(attrs), 2);
562 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_PORT)
563 			memcpy(&port, RTA_DATA(attrs), 2);
564 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR4) {
565 			if (family != AF_INET)
566 				error(1, errno, "wrong IP (v4) for family %d",
567 				      family);
568 			inet_ntop(AF_INET, RTA_DATA(attrs), str, sizeof(str));
569 			printf("%s", str);
570 			if (port)
571 				printf(" %d", port);
572 		}
573 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR6) {
574 			if (family != AF_INET6)
575 				error(1, errno, "wrong IP (v6) for family %d",
576 				      family);
577 			inet_ntop(AF_INET6, RTA_DATA(attrs), str, sizeof(str));
578 			printf("%s", str);
579 			if (port)
580 				printf(" %d", port);
581 		}
582 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ID) {
583 			memcpy(&id, RTA_DATA(attrs), 1);
584 			printf("id %d ", id);
585 		}
586 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FLAGS) {
587 			memcpy(&flags, RTA_DATA(attrs), 4);
588 
589 			printf("flags ");
590 			if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
591 				printf("signal");
592 				flags &= ~MPTCP_PM_ADDR_FLAG_SIGNAL;
593 				if (flags)
594 					printf(",");
595 			}
596 
597 			if (flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
598 				printf("subflow");
599 				flags &= ~MPTCP_PM_ADDR_FLAG_SUBFLOW;
600 				if (flags)
601 					printf(",");
602 			}
603 
604 			if (flags & MPTCP_PM_ADDR_FLAG_BACKUP) {
605 				printf("backup");
606 				flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
607 				if (flags)
608 					printf(",");
609 			}
610 
611 			if (flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
612 				printf("fullmesh");
613 				flags &= ~MPTCP_PM_ADDR_FLAG_FULLMESH;
614 				if (flags)
615 					printf(",");
616 			}
617 
618 			if (flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
619 				printf("implicit");
620 				flags &= ~MPTCP_PM_ADDR_FLAG_IMPLICIT;
621 				if (flags)
622 					printf(",");
623 			}
624 
625 			/* bump unknown flags, if any */
626 			if (flags)
627 				printf("0x%x", flags);
628 			printf(" ");
629 		}
630 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_IF_IDX) {
631 			char name[IF_NAMESIZE], *ret;
632 			int32_t ifindex;
633 
634 			memcpy(&ifindex, RTA_DATA(attrs), 4);
635 			ret = if_indextoname(ifindex, name);
636 			if (ret)
637 				printf("dev %s ", ret);
638 			else
639 				printf("dev unknown/%d", ifindex);
640 		}
641 
642 		attrs = RTA_NEXT(attrs, len);
643 	}
644 	printf("\n");
645 }
646 
647 static void print_addrs(struct nlmsghdr *nh, int pm_family, int total_len)
648 {
649 	struct rtattr *attrs;
650 
651 	for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
652 		int len = nh->nlmsg_len;
653 
654 		if (nh->nlmsg_type == NLMSG_DONE)
655 			break;
656 		if (nh->nlmsg_type == NLMSG_ERROR)
657 			nl_error(nh);
658 		if (nh->nlmsg_type != pm_family)
659 			continue;
660 
661 		len -= NLMSG_LENGTH(GENL_HDRLEN);
662 		attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
663 					   GENL_HDRLEN);
664 		while (RTA_OK(attrs, len)) {
665 			if (attrs->rta_type ==
666 			    (MPTCP_PM_ATTR_ADDR | NLA_F_NESTED))
667 				print_addr((void *)RTA_DATA(attrs),
668 					   attrs->rta_len);
669 			attrs = RTA_NEXT(attrs, len);
670 		}
671 	}
672 }
673 
674 int get_addr(int fd, int pm_family, int argc, char *argv[])
675 {
676 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
677 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
678 		  1024];
679 	struct rtattr *rta, *nest;
680 	struct nlmsghdr *nh;
681 	int nest_start;
682 	u_int8_t id;
683 	int off = 0;
684 
685 	memset(data, 0, sizeof(data));
686 	nh = (void *)data;
687 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
688 			    MPTCP_PM_VER);
689 
690 	/* the only argument is the address id */
691 	if (argc != 3)
692 		syntax(argv);
693 
694 	id = atoi(argv[2]);
695 
696 	nest_start = off;
697 	nest = (void *)(data + off);
698 	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
699 	nest->rta_len =  RTA_LENGTH(0);
700 	off += NLMSG_ALIGN(nest->rta_len);
701 
702 	/* build a dummy addr with only the ID set */
703 	rta = (void *)(data + off);
704 	rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
705 	rta->rta_len = RTA_LENGTH(1);
706 	memcpy(RTA_DATA(rta), &id, 1);
707 	off += NLMSG_ALIGN(rta->rta_len);
708 	nest->rta_len = off - nest_start;
709 
710 	print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
711 	return 0;
712 }
713 
714 int dump_addrs(int fd, int pm_family, int argc, char *argv[])
715 {
716 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
717 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
718 		  1024];
719 	pid_t pid = getpid();
720 	struct nlmsghdr *nh;
721 	int off = 0;
722 
723 	memset(data, 0, sizeof(data));
724 	nh = (void *)data;
725 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
726 			    MPTCP_PM_VER);
727 	nh->nlmsg_flags |= NLM_F_DUMP;
728 	nh->nlmsg_seq = 1;
729 	nh->nlmsg_pid = pid;
730 	nh->nlmsg_len = off;
731 
732 	print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
733 	return 0;
734 }
735 
736 int flush_addrs(int fd, int pm_family, int argc, char *argv[])
737 {
738 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
739 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
740 		  1024];
741 	struct nlmsghdr *nh;
742 	int off = 0;
743 
744 	memset(data, 0, sizeof(data));
745 	nh = (void *)data;
746 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_FLUSH_ADDRS,
747 			    MPTCP_PM_VER);
748 
749 	do_nl_req(fd, nh, off, 0);
750 	return 0;
751 }
752 
753 static void print_limits(struct nlmsghdr *nh, int pm_family, int total_len)
754 {
755 	struct rtattr *attrs;
756 	uint32_t max;
757 
758 	for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
759 		int len = nh->nlmsg_len;
760 
761 		if (nh->nlmsg_type == NLMSG_DONE)
762 			break;
763 		if (nh->nlmsg_type == NLMSG_ERROR)
764 			nl_error(nh);
765 		if (nh->nlmsg_type != pm_family)
766 			continue;
767 
768 		len -= NLMSG_LENGTH(GENL_HDRLEN);
769 		attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
770 					   GENL_HDRLEN);
771 		while (RTA_OK(attrs, len)) {
772 			int type = attrs->rta_type;
773 
774 			if (type != MPTCP_PM_ATTR_RCV_ADD_ADDRS &&
775 			    type != MPTCP_PM_ATTR_SUBFLOWS)
776 				goto next;
777 
778 			memcpy(&max, RTA_DATA(attrs), 4);
779 			printf("%s %u\n", type == MPTCP_PM_ATTR_SUBFLOWS ?
780 					  "subflows" : "accept", max);
781 
782 next:
783 			attrs = RTA_NEXT(attrs, len);
784 		}
785 	}
786 }
787 
788 int get_set_limits(int fd, int pm_family, int argc, char *argv[])
789 {
790 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
791 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
792 		  1024];
793 	uint32_t rcv_addr = 0, subflows = 0;
794 	int cmd, len = sizeof(data);
795 	struct nlmsghdr *nh;
796 	int off = 0;
797 
798 	/* limit */
799 	if (argc == 4) {
800 		rcv_addr = atoi(argv[2]);
801 		subflows = atoi(argv[3]);
802 		cmd = MPTCP_PM_CMD_SET_LIMITS;
803 	} else {
804 		cmd = MPTCP_PM_CMD_GET_LIMITS;
805 	}
806 
807 	memset(data, 0, sizeof(data));
808 	nh = (void *)data;
809 	off = init_genl_req(data, pm_family, cmd, MPTCP_PM_VER);
810 
811 	/* limit */
812 	if (cmd == MPTCP_PM_CMD_SET_LIMITS) {
813 		struct rtattr *rta = (void *)(data + off);
814 
815 		rta->rta_type = MPTCP_PM_ATTR_RCV_ADD_ADDRS;
816 		rta->rta_len = RTA_LENGTH(4);
817 		memcpy(RTA_DATA(rta), &rcv_addr, 4);
818 		off += NLMSG_ALIGN(rta->rta_len);
819 
820 		rta = (void *)(data + off);
821 		rta->rta_type = MPTCP_PM_ATTR_SUBFLOWS;
822 		rta->rta_len = RTA_LENGTH(4);
823 		memcpy(RTA_DATA(rta), &subflows, 4);
824 		off += NLMSG_ALIGN(rta->rta_len);
825 
826 		/* do not expect a reply */
827 		len = 0;
828 	}
829 
830 	len = do_nl_req(fd, nh, off, len);
831 	if (cmd == MPTCP_PM_CMD_GET_LIMITS)
832 		print_limits(nh, pm_family, len);
833 	return 0;
834 }
835 
836 int set_flags(int fd, int pm_family, int argc, char *argv[])
837 {
838 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
839 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
840 		  1024];
841 	struct rtattr *rta, *nest;
842 	struct nlmsghdr *nh;
843 	u_int32_t flags = 0;
844 	u_int16_t family;
845 	int nest_start;
846 	int use_id = 0;
847 	u_int8_t id;
848 	int off = 0;
849 	int arg = 2;
850 
851 	memset(data, 0, sizeof(data));
852 	nh = (void *)data;
853 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS,
854 			    MPTCP_PM_VER);
855 
856 	if (argc < 3)
857 		syntax(argv);
858 
859 	nest_start = off;
860 	nest = (void *)(data + off);
861 	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
862 	nest->rta_len = RTA_LENGTH(0);
863 	off += NLMSG_ALIGN(nest->rta_len);
864 
865 	if (!strcmp(argv[arg], "id")) {
866 		if (++arg >= argc)
867 			error(1, 0, " missing id value");
868 
869 		use_id = 1;
870 		id = atoi(argv[arg]);
871 		rta = (void *)(data + off);
872 		rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
873 		rta->rta_len = RTA_LENGTH(1);
874 		memcpy(RTA_DATA(rta), &id, 1);
875 		off += NLMSG_ALIGN(rta->rta_len);
876 	} else {
877 		/* addr data */
878 		rta = (void *)(data + off);
879 		if (inet_pton(AF_INET, argv[arg], RTA_DATA(rta))) {
880 			family = AF_INET;
881 			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
882 			rta->rta_len = RTA_LENGTH(4);
883 		} else if (inet_pton(AF_INET6, argv[arg], RTA_DATA(rta))) {
884 			family = AF_INET6;
885 			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
886 			rta->rta_len = RTA_LENGTH(16);
887 		} else {
888 			error(1, errno, "can't parse ip %s", argv[arg]);
889 		}
890 		off += NLMSG_ALIGN(rta->rta_len);
891 
892 		/* family */
893 		rta = (void *)(data + off);
894 		rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
895 		rta->rta_len = RTA_LENGTH(2);
896 		memcpy(RTA_DATA(rta), &family, 2);
897 		off += NLMSG_ALIGN(rta->rta_len);
898 	}
899 
900 	if (++arg >= argc)
901 		error(1, 0, " missing flags keyword");
902 
903 	for (; arg < argc; arg++) {
904 		if (!strcmp(argv[arg], "flags")) {
905 			char *tok, *str;
906 
907 			/* flags */
908 			if (++arg >= argc)
909 				error(1, 0, " missing flags value");
910 
911 			for (str = argv[arg]; (tok = strtok(str, ","));
912 			     str = NULL) {
913 				if (!strcmp(tok, "backup"))
914 					flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
915 				else if (!strcmp(tok, "fullmesh"))
916 					flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
917 				else if (strcmp(tok, "nobackup") &&
918 					 strcmp(tok, "nofullmesh"))
919 					error(1, errno,
920 					      "unknown flag %s", argv[arg]);
921 			}
922 
923 			rta = (void *)(data + off);
924 			rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
925 			rta->rta_len = RTA_LENGTH(4);
926 			memcpy(RTA_DATA(rta), &flags, 4);
927 			off += NLMSG_ALIGN(rta->rta_len);
928 		} else if (!strcmp(argv[arg], "port")) {
929 			u_int16_t port;
930 
931 			if (use_id)
932 				error(1, 0, " port can't be used with id");
933 
934 			if (++arg >= argc)
935 				error(1, 0, " missing port value");
936 
937 			port = atoi(argv[arg]);
938 			rta = (void *)(data + off);
939 			rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
940 			rta->rta_len = RTA_LENGTH(2);
941 			memcpy(RTA_DATA(rta), &port, 2);
942 			off += NLMSG_ALIGN(rta->rta_len);
943 		} else {
944 			error(1, 0, "unknown keyword %s", argv[arg]);
945 		}
946 	}
947 	nest->rta_len = off - nest_start;
948 
949 	do_nl_req(fd, nh, off, 0);
950 	return 0;
951 }
952 
953 int main(int argc, char *argv[])
954 {
955 	int fd, pm_family;
956 
957 	if (argc < 2)
958 		syntax(argv);
959 
960 	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
961 	if (fd == -1)
962 		error(1, errno, "socket netlink");
963 
964 	pm_family = resolve_mptcp_pm_netlink(fd);
965 
966 	if (!strcmp(argv[1], "add"))
967 		return add_addr(fd, pm_family, argc, argv);
968 	else if (!strcmp(argv[1], "ann"))
969 		return announce_addr(fd, pm_family, argc, argv);
970 	else if (!strcmp(argv[1], "rem"))
971 		return remove_addr(fd, pm_family, argc, argv);
972 	else if (!strcmp(argv[1], "del"))
973 		return del_addr(fd, pm_family, argc, argv);
974 	else if (!strcmp(argv[1], "flush"))
975 		return flush_addrs(fd, pm_family, argc, argv);
976 	else if (!strcmp(argv[1], "get"))
977 		return get_addr(fd, pm_family, argc, argv);
978 	else if (!strcmp(argv[1], "dump"))
979 		return dump_addrs(fd, pm_family, argc, argv);
980 	else if (!strcmp(argv[1], "limits"))
981 		return get_set_limits(fd, pm_family, argc, argv);
982 	else if (!strcmp(argv[1], "set"))
983 		return set_flags(fd, pm_family, argc, argv);
984 
985 	fprintf(stderr, "unknown sub-command: %s", argv[1]);
986 	syntax(argv);
987 	return 0;
988 }
989