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