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