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