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