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