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