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

source code of linux/tools/testing/selftests/net/mptcp/pm_nl_ctl.c