1548 lines · c
1// SPDX-License-Identifier: GPL-2.02 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_MPTCP23#define IPPROTO_MPTCP 26224#endif25 26static 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 45static 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 63static 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 99static int capture_events(int fd, int event_group)100{101 u_int8_t buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +102 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024];103 struct genlmsghdr *ghdr;104 struct rtattr *attrs;105 struct nlmsghdr *nh;106 int ret = 0;107 int res_len;108 int msg_len;109 fd_set rfds;110 111 if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,112 &event_group, sizeof(event_group)) < 0)113 error(1, errno, "could not join the " MPTCP_PM_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 */202static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)203{204 struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };205 socklen_t addr_len;206 void *data = nh;207 int rem, ret;208 int err = 0;209 210 /* 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 239static 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 308static 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 333int 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 } else388 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 } else411 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 445int 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 } else503 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 } else526 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 579int 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 } else621 error(1, 0, "unknown keyword %s", argv[arg]);622 }623 624 do_nl_req(fd, nh, off, 0);625 return 0;626}627 628int 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 } else670 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 } else728 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 755int 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 } else794 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 else824 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 } else878 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 886int 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 954static 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 else1042 printf("dev unknown/%d", ifindex);1043 }1044 1045 attrs = RTA_NEXT(attrs, len);1046 }1047 printf("\n");1048}1049 1050static 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 1077int 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 1129int 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 1168int 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 1185static 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 1214next:1215 attrs = RTA_NEXT(attrs, len);1216 }1217 }1218}1219 1220int 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 1268int 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 } else1294 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 1316int 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 1502int 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