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 
10 #include <sys/socket.h>
11 #include <sys/types.h>
12 
13 #include <arpa/inet.h>
14 #include <net/if.h>
15 
16 #include <linux/rtnetlink.h>
17 #include <linux/genetlink.h>
18 
19 #include "linux/mptcp.h"
20 
21 #ifndef MPTCP_PM_NAME
22 #define MPTCP_PM_NAME		"mptcp_pm"
23 #endif
24 
25 static void syntax(char *argv[])
26 {
27 	fprintf(stderr, "%s add|get|set|del|flush|dump|accept [<args>]\n", argv[0]);
28 	fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n");
29 	fprintf(stderr, "\tdel <id> [<ip>]\n");
30 	fprintf(stderr, "\tget <id>\n");
31 	fprintf(stderr, "\tset <ip> [flags backup|nobackup]\n");
32 	fprintf(stderr, "\tflush\n");
33 	fprintf(stderr, "\tdump\n");
34 	fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
35 	exit(0);
36 }
37 
38 static int init_genl_req(char *data, int family, int cmd, int version)
39 {
40 	struct nlmsghdr *nh = (void *)data;
41 	struct genlmsghdr *gh;
42 	int off = 0;
43 
44 	nh->nlmsg_type = family;
45 	nh->nlmsg_flags = NLM_F_REQUEST;
46 	nh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
47 	off += NLMSG_ALIGN(sizeof(*nh));
48 
49 	gh = (void *)(data + off);
50 	gh->cmd = cmd;
51 	gh->version = version;
52 	off += NLMSG_ALIGN(sizeof(*gh));
53 	return off;
54 }
55 
56 static void nl_error(struct nlmsghdr *nh)
57 {
58 	struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh);
59 	int len = nh->nlmsg_len - sizeof(*nh);
60 	uint32_t off;
61 
62 	if (len < sizeof(struct nlmsgerr))
63 		error(1, 0, "netlink error message truncated %d min %ld", len,
64 		      sizeof(struct nlmsgerr));
65 
66 	if (!err->error) {
67 		/* check messages from kernel */
68 		struct rtattr *attrs = (struct rtattr *)NLMSG_DATA(nh);
69 
70 		while (RTA_OK(attrs, len)) {
71 			if (attrs->rta_type == NLMSGERR_ATTR_MSG)
72 				fprintf(stderr, "netlink ext ack msg: %s\n",
73 					(char *)RTA_DATA(attrs));
74 			if (attrs->rta_type == NLMSGERR_ATTR_OFFS) {
75 				memcpy(&off, RTA_DATA(attrs), 4);
76 				fprintf(stderr, "netlink err off %d\n",
77 					(int)off);
78 			}
79 			attrs = RTA_NEXT(attrs, len);
80 		}
81 	} else {
82 		fprintf(stderr, "netlink error %d", err->error);
83 	}
84 }
85 
86 /* do a netlink command and, if max > 0, fetch the reply  */
87 static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
88 {
89 	struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
90 	socklen_t addr_len;
91 	void *data = nh;
92 	int rem, ret;
93 	int err = 0;
94 
95 	nh->nlmsg_len = len;
96 	ret = sendto(fd, data, len, 0, (void *)&nladdr, sizeof(nladdr));
97 	if (ret != len)
98 		error(1, errno, "send netlink: %uB != %uB\n", ret, len);
99 	if (max == 0)
100 		return 0;
101 
102 	addr_len = sizeof(nladdr);
103 	rem = ret = recvfrom(fd, data, max, 0, (void *)&nladdr, &addr_len);
104 	if (ret < 0)
105 		error(1, errno, "recv netlink: %uB\n", ret);
106 
107 	/* Beware: the NLMSG_NEXT macro updates the 'rem' argument */
108 	for (; NLMSG_OK(nh, rem); nh = NLMSG_NEXT(nh, rem)) {
109 		if (nh->nlmsg_type == NLMSG_ERROR) {
110 			nl_error(nh);
111 			err = 1;
112 		}
113 	}
114 	if (err)
115 		error(1, 0, "bailing out due to netlink error[s]");
116 	return ret;
117 }
118 
119 static int genl_parse_getfamily(struct nlmsghdr *nlh)
120 {
121 	struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
122 	int len = nlh->nlmsg_len;
123 	struct rtattr *attrs;
124 
125 	if (nlh->nlmsg_type != GENL_ID_CTRL)
126 		error(1, errno, "Not a controller message, len=%d type=0x%x\n",
127 		      nlh->nlmsg_len, nlh->nlmsg_type);
128 
129 	len -= NLMSG_LENGTH(GENL_HDRLEN);
130 
131 	if (len < 0)
132 		error(1, errno, "wrong controller message len %d\n", len);
133 
134 	if (ghdr->cmd != CTRL_CMD_NEWFAMILY)
135 		error(1, errno, "Unknown controller command %d\n", ghdr->cmd);
136 
137 	attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
138 	while (RTA_OK(attrs, len)) {
139 		if (attrs->rta_type == CTRL_ATTR_FAMILY_ID)
140 			return *(__u16 *)RTA_DATA(attrs);
141 		attrs = RTA_NEXT(attrs, len);
142 	}
143 
144 	error(1, errno, "can't find CTRL_ATTR_FAMILY_ID attr");
145 	return -1;
146 }
147 
148 static int resolve_mptcp_pm_netlink(int fd)
149 {
150 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
151 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
152 		  1024];
153 	struct nlmsghdr *nh;
154 	struct rtattr *rta;
155 	int namelen;
156 	int off = 0;
157 
158 	memset(data, 0, sizeof(data));
159 	nh = (void *)data;
160 	off = init_genl_req(data, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 0);
161 
162 	rta = (void *)(data + off);
163 	namelen = strlen(MPTCP_PM_NAME) + 1;
164 	rta->rta_type = CTRL_ATTR_FAMILY_NAME;
165 	rta->rta_len = RTA_LENGTH(namelen);
166 	memcpy(RTA_DATA(rta), MPTCP_PM_NAME, namelen);
167 	off += NLMSG_ALIGN(rta->rta_len);
168 
169 	do_nl_req(fd, nh, off, sizeof(data));
170 	return genl_parse_getfamily((void *)data);
171 }
172 
173 int add_addr(int fd, int pm_family, int argc, char *argv[])
174 {
175 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
176 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
177 		  1024];
178 	struct rtattr *rta, *nest;
179 	struct nlmsghdr *nh;
180 	u_int32_t flags = 0;
181 	u_int16_t family;
182 	int nest_start;
183 	u_int8_t id;
184 	int off = 0;
185 	int arg;
186 
187 	memset(data, 0, sizeof(data));
188 	nh = (void *)data;
189 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ADD_ADDR,
190 			    MPTCP_PM_VER);
191 
192 	if (argc < 3)
193 		syntax(argv);
194 
195 	nest_start = off;
196 	nest = (void *)(data + off);
197 	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
198 	nest->rta_len = RTA_LENGTH(0);
199 	off += NLMSG_ALIGN(nest->rta_len);
200 
201 	/* addr data */
202 	rta = (void *)(data + off);
203 	if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
204 		family = AF_INET;
205 		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
206 		rta->rta_len = RTA_LENGTH(4);
207 	} else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
208 		family = AF_INET6;
209 		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
210 		rta->rta_len = RTA_LENGTH(16);
211 	} else
212 		error(1, errno, "can't parse ip %s", argv[2]);
213 	off += NLMSG_ALIGN(rta->rta_len);
214 
215 	/* family */
216 	rta = (void *)(data + off);
217 	rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
218 	rta->rta_len = RTA_LENGTH(2);
219 	memcpy(RTA_DATA(rta), &family, 2);
220 	off += NLMSG_ALIGN(rta->rta_len);
221 
222 	for (arg = 3; arg < argc; arg++) {
223 		if (!strcmp(argv[arg], "flags")) {
224 			char *tok, *str;
225 
226 			/* flags */
227 			if (++arg >= argc)
228 				error(1, 0, " missing flags value");
229 
230 			/* do not support flag list yet */
231 			for (str = argv[arg]; (tok = strtok(str, ","));
232 			     str = NULL) {
233 				if (!strcmp(tok, "subflow"))
234 					flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;
235 				else if (!strcmp(tok, "signal"))
236 					flags |= MPTCP_PM_ADDR_FLAG_SIGNAL;
237 				else if (!strcmp(tok, "backup"))
238 					flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
239 				else if (!strcmp(tok, "fullmesh"))
240 					flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
241 				else
242 					error(1, errno,
243 					      "unknown flag %s", argv[arg]);
244 			}
245 
246 			if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
247 			    flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
248 				error(1, errno, "error flag fullmesh");
249 			}
250 
251 			rta = (void *)(data + off);
252 			rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
253 			rta->rta_len = RTA_LENGTH(4);
254 			memcpy(RTA_DATA(rta), &flags, 4);
255 			off += NLMSG_ALIGN(rta->rta_len);
256 		} else if (!strcmp(argv[arg], "id")) {
257 			if (++arg >= argc)
258 				error(1, 0, " missing id value");
259 
260 			id = atoi(argv[arg]);
261 			rta = (void *)(data + off);
262 			rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
263 			rta->rta_len = RTA_LENGTH(1);
264 			memcpy(RTA_DATA(rta), &id, 1);
265 			off += NLMSG_ALIGN(rta->rta_len);
266 		} else if (!strcmp(argv[arg], "dev")) {
267 			int32_t ifindex;
268 
269 			if (++arg >= argc)
270 				error(1, 0, " missing dev name");
271 
272 			ifindex = if_nametoindex(argv[arg]);
273 			if (!ifindex)
274 				error(1, errno, "unknown device %s", argv[arg]);
275 
276 			rta = (void *)(data + off);
277 			rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
278 			rta->rta_len = RTA_LENGTH(4);
279 			memcpy(RTA_DATA(rta), &ifindex, 4);
280 			off += NLMSG_ALIGN(rta->rta_len);
281 		} else if (!strcmp(argv[arg], "port")) {
282 			u_int16_t port;
283 
284 			if (++arg >= argc)
285 				error(1, 0, " missing port value");
286 			if (!(flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
287 				error(1, 0, " flags must be signal when using port");
288 
289 			port = atoi(argv[arg]);
290 			rta = (void *)(data + off);
291 			rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
292 			rta->rta_len = RTA_LENGTH(2);
293 			memcpy(RTA_DATA(rta), &port, 2);
294 			off += NLMSG_ALIGN(rta->rta_len);
295 		} else
296 			error(1, 0, "unknown keyword %s", argv[arg]);
297 	}
298 	nest->rta_len = off - nest_start;
299 
300 	do_nl_req(fd, nh, off, 0);
301 	return 0;
302 }
303 
304 int del_addr(int fd, int pm_family, int argc, char *argv[])
305 {
306 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
307 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
308 		  1024];
309 	struct rtattr *rta, *nest;
310 	struct nlmsghdr *nh;
311 	u_int16_t family;
312 	int nest_start;
313 	u_int8_t id;
314 	int off = 0;
315 
316 	memset(data, 0, sizeof(data));
317 	nh = (void *)data;
318 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_DEL_ADDR,
319 			    MPTCP_PM_VER);
320 
321 	/* the only argument is the address id (nonzero) */
322 	if (argc != 3 && argc != 4)
323 		syntax(argv);
324 
325 	id = atoi(argv[2]);
326 	/* zero id with the IP address */
327 	if (!id && argc != 4)
328 		syntax(argv);
329 
330 	nest_start = off;
331 	nest = (void *)(data + off);
332 	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
333 	nest->rta_len =  RTA_LENGTH(0);
334 	off += NLMSG_ALIGN(nest->rta_len);
335 
336 	/* build a dummy addr with only the ID set */
337 	rta = (void *)(data + off);
338 	rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
339 	rta->rta_len = RTA_LENGTH(1);
340 	memcpy(RTA_DATA(rta), &id, 1);
341 	off += NLMSG_ALIGN(rta->rta_len);
342 
343 	if (!id) {
344 		/* addr data */
345 		rta = (void *)(data + off);
346 		if (inet_pton(AF_INET, argv[3], RTA_DATA(rta))) {
347 			family = AF_INET;
348 			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
349 			rta->rta_len = RTA_LENGTH(4);
350 		} else if (inet_pton(AF_INET6, argv[3], RTA_DATA(rta))) {
351 			family = AF_INET6;
352 			rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
353 			rta->rta_len = RTA_LENGTH(16);
354 		} else {
355 			error(1, errno, "can't parse ip %s", argv[3]);
356 		}
357 		off += NLMSG_ALIGN(rta->rta_len);
358 
359 		/* family */
360 		rta = (void *)(data + off);
361 		rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
362 		rta->rta_len = RTA_LENGTH(2);
363 		memcpy(RTA_DATA(rta), &family, 2);
364 		off += NLMSG_ALIGN(rta->rta_len);
365 	}
366 	nest->rta_len = off - nest_start;
367 
368 	do_nl_req(fd, nh, off, 0);
369 	return 0;
370 }
371 
372 static void print_addr(struct rtattr *attrs, int len)
373 {
374 	uint16_t family = 0;
375 	uint16_t port = 0;
376 	char str[1024];
377 	uint32_t flags;
378 	uint8_t id;
379 
380 	while (RTA_OK(attrs, len)) {
381 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FAMILY)
382 			memcpy(&family, RTA_DATA(attrs), 2);
383 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_PORT)
384 			memcpy(&port, RTA_DATA(attrs), 2);
385 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR4) {
386 			if (family != AF_INET)
387 				error(1, errno, "wrong IP (v4) for family %d",
388 				      family);
389 			inet_ntop(AF_INET, RTA_DATA(attrs), str, sizeof(str));
390 			printf("%s", str);
391 			if (port)
392 				printf(" %d", port);
393 		}
394 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR6) {
395 			if (family != AF_INET6)
396 				error(1, errno, "wrong IP (v6) for family %d",
397 				      family);
398 			inet_ntop(AF_INET6, RTA_DATA(attrs), str, sizeof(str));
399 			printf("%s", str);
400 			if (port)
401 				printf(" %d", port);
402 		}
403 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ID) {
404 			memcpy(&id, RTA_DATA(attrs), 1);
405 			printf("id %d ", id);
406 		}
407 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FLAGS) {
408 			memcpy(&flags, RTA_DATA(attrs), 4);
409 
410 			printf("flags ");
411 			if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
412 				printf("signal");
413 				flags &= ~MPTCP_PM_ADDR_FLAG_SIGNAL;
414 				if (flags)
415 					printf(",");
416 			}
417 
418 			if (flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
419 				printf("subflow");
420 				flags &= ~MPTCP_PM_ADDR_FLAG_SUBFLOW;
421 				if (flags)
422 					printf(",");
423 			}
424 
425 			if (flags & MPTCP_PM_ADDR_FLAG_BACKUP) {
426 				printf("backup");
427 				flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
428 				if (flags)
429 					printf(",");
430 			}
431 
432 			if (flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
433 				printf("fullmesh");
434 				flags &= ~MPTCP_PM_ADDR_FLAG_FULLMESH;
435 				if (flags)
436 					printf(",");
437 			}
438 
439 			/* bump unknown flags, if any */
440 			if (flags)
441 				printf("0x%x", flags);
442 			printf(" ");
443 		}
444 		if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_IF_IDX) {
445 			char name[IF_NAMESIZE], *ret;
446 			int32_t ifindex;
447 
448 			memcpy(&ifindex, RTA_DATA(attrs), 4);
449 			ret = if_indextoname(ifindex, name);
450 			if (ret)
451 				printf("dev %s ", ret);
452 			else
453 				printf("dev unknown/%d", ifindex);
454 		}
455 
456 		attrs = RTA_NEXT(attrs, len);
457 	}
458 	printf("\n");
459 }
460 
461 static void print_addrs(struct nlmsghdr *nh, int pm_family, int total_len)
462 {
463 	struct rtattr *attrs;
464 
465 	for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
466 		int len = nh->nlmsg_len;
467 
468 		if (nh->nlmsg_type == NLMSG_DONE)
469 			break;
470 		if (nh->nlmsg_type == NLMSG_ERROR)
471 			nl_error(nh);
472 		if (nh->nlmsg_type != pm_family)
473 			continue;
474 
475 		len -= NLMSG_LENGTH(GENL_HDRLEN);
476 		attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
477 					   GENL_HDRLEN);
478 		while (RTA_OK(attrs, len)) {
479 			if (attrs->rta_type ==
480 			    (MPTCP_PM_ATTR_ADDR | NLA_F_NESTED))
481 				print_addr((void *)RTA_DATA(attrs),
482 					   attrs->rta_len);
483 			attrs = RTA_NEXT(attrs, len);
484 		}
485 	}
486 }
487 
488 int get_addr(int fd, int pm_family, int argc, char *argv[])
489 {
490 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
491 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
492 		  1024];
493 	struct rtattr *rta, *nest;
494 	struct nlmsghdr *nh;
495 	int nest_start;
496 	u_int8_t id;
497 	int off = 0;
498 
499 	memset(data, 0, sizeof(data));
500 	nh = (void *)data;
501 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
502 			    MPTCP_PM_VER);
503 
504 	/* the only argument is the address id */
505 	if (argc != 3)
506 		syntax(argv);
507 
508 	id = atoi(argv[2]);
509 
510 	nest_start = off;
511 	nest = (void *)(data + off);
512 	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
513 	nest->rta_len =  RTA_LENGTH(0);
514 	off += NLMSG_ALIGN(nest->rta_len);
515 
516 	/* build a dummy addr with only the ID set */
517 	rta = (void *)(data + off);
518 	rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
519 	rta->rta_len = RTA_LENGTH(1);
520 	memcpy(RTA_DATA(rta), &id, 1);
521 	off += NLMSG_ALIGN(rta->rta_len);
522 	nest->rta_len = off - nest_start;
523 
524 	print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
525 	return 0;
526 }
527 
528 int dump_addrs(int fd, int pm_family, int argc, char *argv[])
529 {
530 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
531 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
532 		  1024];
533 	pid_t pid = getpid();
534 	struct nlmsghdr *nh;
535 	int off = 0;
536 
537 	memset(data, 0, sizeof(data));
538 	nh = (void *)data;
539 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
540 			    MPTCP_PM_VER);
541 	nh->nlmsg_flags |= NLM_F_DUMP;
542 	nh->nlmsg_seq = 1;
543 	nh->nlmsg_pid = pid;
544 	nh->nlmsg_len = off;
545 
546 	print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
547 	return 0;
548 }
549 
550 int flush_addrs(int fd, int pm_family, int argc, char *argv[])
551 {
552 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
553 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
554 		  1024];
555 	struct nlmsghdr *nh;
556 	int off = 0;
557 
558 	memset(data, 0, sizeof(data));
559 	nh = (void *)data;
560 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_FLUSH_ADDRS,
561 			    MPTCP_PM_VER);
562 
563 	do_nl_req(fd, nh, off, 0);
564 	return 0;
565 }
566 
567 static void print_limits(struct nlmsghdr *nh, int pm_family, int total_len)
568 {
569 	struct rtattr *attrs;
570 	uint32_t max;
571 
572 	for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
573 		int len = nh->nlmsg_len;
574 
575 		if (nh->nlmsg_type == NLMSG_DONE)
576 			break;
577 		if (nh->nlmsg_type == NLMSG_ERROR)
578 			nl_error(nh);
579 		if (nh->nlmsg_type != pm_family)
580 			continue;
581 
582 		len -= NLMSG_LENGTH(GENL_HDRLEN);
583 		attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
584 					   GENL_HDRLEN);
585 		while (RTA_OK(attrs, len)) {
586 			int type = attrs->rta_type;
587 
588 			if (type != MPTCP_PM_ATTR_RCV_ADD_ADDRS &&
589 			    type != MPTCP_PM_ATTR_SUBFLOWS)
590 				goto next;
591 
592 			memcpy(&max, RTA_DATA(attrs), 4);
593 			printf("%s %u\n", type == MPTCP_PM_ATTR_SUBFLOWS ?
594 					  "subflows" : "accept", max);
595 
596 next:
597 			attrs = RTA_NEXT(attrs, len);
598 		}
599 	}
600 }
601 
602 int get_set_limits(int fd, int pm_family, int argc, char *argv[])
603 {
604 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
605 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
606 		  1024];
607 	uint32_t rcv_addr = 0, subflows = 0;
608 	int cmd, len = sizeof(data);
609 	struct nlmsghdr *nh;
610 	int off = 0;
611 
612 	/* limit */
613 	if (argc == 4) {
614 		rcv_addr = atoi(argv[2]);
615 		subflows = atoi(argv[3]);
616 		cmd = MPTCP_PM_CMD_SET_LIMITS;
617 	} else {
618 		cmd = MPTCP_PM_CMD_GET_LIMITS;
619 	}
620 
621 	memset(data, 0, sizeof(data));
622 	nh = (void *)data;
623 	off = init_genl_req(data, pm_family, cmd, MPTCP_PM_VER);
624 
625 	/* limit */
626 	if (cmd == MPTCP_PM_CMD_SET_LIMITS) {
627 		struct rtattr *rta = (void *)(data + off);
628 
629 		rta->rta_type = MPTCP_PM_ATTR_RCV_ADD_ADDRS;
630 		rta->rta_len = RTA_LENGTH(4);
631 		memcpy(RTA_DATA(rta), &rcv_addr, 4);
632 		off += NLMSG_ALIGN(rta->rta_len);
633 
634 		rta = (void *)(data + off);
635 		rta->rta_type = MPTCP_PM_ATTR_SUBFLOWS;
636 		rta->rta_len = RTA_LENGTH(4);
637 		memcpy(RTA_DATA(rta), &subflows, 4);
638 		off += NLMSG_ALIGN(rta->rta_len);
639 
640 		/* do not expect a reply */
641 		len = 0;
642 	}
643 
644 	len = do_nl_req(fd, nh, off, len);
645 	if (cmd == MPTCP_PM_CMD_GET_LIMITS)
646 		print_limits(nh, pm_family, len);
647 	return 0;
648 }
649 
650 int set_flags(int fd, int pm_family, int argc, char *argv[])
651 {
652 	char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
653 		  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
654 		  1024];
655 	struct rtattr *rta, *nest;
656 	struct nlmsghdr *nh;
657 	u_int32_t flags = 0;
658 	u_int16_t family;
659 	int nest_start;
660 	int off = 0;
661 	int arg;
662 
663 	memset(data, 0, sizeof(data));
664 	nh = (void *)data;
665 	off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS,
666 			    MPTCP_PM_VER);
667 
668 	if (argc < 3)
669 		syntax(argv);
670 
671 	nest_start = off;
672 	nest = (void *)(data + off);
673 	nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
674 	nest->rta_len = RTA_LENGTH(0);
675 	off += NLMSG_ALIGN(nest->rta_len);
676 
677 	/* addr data */
678 	rta = (void *)(data + off);
679 	if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
680 		family = AF_INET;
681 		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
682 		rta->rta_len = RTA_LENGTH(4);
683 	} else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
684 		family = AF_INET6;
685 		rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
686 		rta->rta_len = RTA_LENGTH(16);
687 	} else {
688 		error(1, errno, "can't parse ip %s", argv[2]);
689 	}
690 	off += NLMSG_ALIGN(rta->rta_len);
691 
692 	/* family */
693 	rta = (void *)(data + off);
694 	rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
695 	rta->rta_len = RTA_LENGTH(2);
696 	memcpy(RTA_DATA(rta), &family, 2);
697 	off += NLMSG_ALIGN(rta->rta_len);
698 
699 	for (arg = 3; arg < argc; arg++) {
700 		if (!strcmp(argv[arg], "flags")) {
701 			char *tok, *str;
702 
703 			/* flags */
704 			if (++arg >= argc)
705 				error(1, 0, " missing flags value");
706 
707 			/* do not support flag list yet */
708 			for (str = argv[arg]; (tok = strtok(str, ","));
709 			     str = NULL) {
710 				if (!strcmp(tok, "backup"))
711 					flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
712 				else if (strcmp(tok, "nobackup"))
713 					error(1, errno,
714 					      "unknown flag %s", argv[arg]);
715 			}
716 
717 			rta = (void *)(data + off);
718 			rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
719 			rta->rta_len = RTA_LENGTH(4);
720 			memcpy(RTA_DATA(rta), &flags, 4);
721 			off += NLMSG_ALIGN(rta->rta_len);
722 		} else {
723 			error(1, 0, "unknown keyword %s", argv[arg]);
724 		}
725 	}
726 	nest->rta_len = off - nest_start;
727 
728 	do_nl_req(fd, nh, off, 0);
729 	return 0;
730 }
731 
732 int main(int argc, char *argv[])
733 {
734 	int fd, pm_family;
735 
736 	if (argc < 2)
737 		syntax(argv);
738 
739 	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
740 	if (fd == -1)
741 		error(1, errno, "socket netlink");
742 
743 	pm_family = resolve_mptcp_pm_netlink(fd);
744 
745 	if (!strcmp(argv[1], "add"))
746 		return add_addr(fd, pm_family, argc, argv);
747 	else if (!strcmp(argv[1], "del"))
748 		return del_addr(fd, pm_family, argc, argv);
749 	else if (!strcmp(argv[1], "flush"))
750 		return flush_addrs(fd, pm_family, argc, argv);
751 	else if (!strcmp(argv[1], "get"))
752 		return get_addr(fd, pm_family, argc, argv);
753 	else if (!strcmp(argv[1], "dump"))
754 		return dump_addrs(fd, pm_family, argc, argv);
755 	else if (!strcmp(argv[1], "limits"))
756 		return get_set_limits(fd, pm_family, argc, argv);
757 	else if (!strcmp(argv[1], "set"))
758 		return set_flags(fd, pm_family, argc, argv);
759 
760 	fprintf(stderr, "unknown sub-command: %s", argv[1]);
761 	syntax(argv);
762 	return 0;
763 }
764