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