0001
0002
0003 #include <errno.h>
0004 #include <error.h>
0005 #include <stdio.h>
0006 #include <stdlib.h>
0007 #include <string.h>
0008 #include <unistd.h>
0009 #include <limits.h>
0010
0011 #include <sys/socket.h>
0012 #include <sys/types.h>
0013
0014 #include <arpa/inet.h>
0015 #include <net/if.h>
0016
0017 #include <linux/rtnetlink.h>
0018 #include <linux/genetlink.h>
0019
0020 #include "linux/mptcp.h"
0021
0022 #ifndef MPTCP_PM_NAME
0023 #define MPTCP_PM_NAME "mptcp_pm"
0024 #endif
0025 #ifndef MPTCP_PM_EVENTS
0026 #define MPTCP_PM_EVENTS "mptcp_pm_events"
0027 #endif
0028 #ifndef IPPROTO_MPTCP
0029 #define IPPROTO_MPTCP 262
0030 #endif
0031
0032 static void syntax(char *argv[])
0033 {
0034 fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]);
0035 fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n");
0036 fprintf(stderr, "\tann <local-ip> id <local-id> token <token> [port <local-port>] [dev <name>]\n");
0037 fprintf(stderr, "\trem id <local-id> token <token>\n");
0038 fprintf(stderr, "\tcsf lip <local-ip> lid <local-id> rip <remote-ip> rport <remote-port> token <token>\n");
0039 fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n");
0040 fprintf(stderr, "\tdel <id> [<ip>]\n");
0041 fprintf(stderr, "\tget <id>\n");
0042 fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>] [token <token>] [rip <ip>] [rport <port>]\n");
0043 fprintf(stderr, "\tflush\n");
0044 fprintf(stderr, "\tdump\n");
0045 fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
0046 fprintf(stderr, "\tevents\n");
0047 fprintf(stderr, "\tlisten <local-ip> <local-port>\n");
0048 exit(0);
0049 }
0050
0051 static int init_genl_req(char *data, int family, int cmd, int version)
0052 {
0053 struct nlmsghdr *nh = (void *)data;
0054 struct genlmsghdr *gh;
0055 int off = 0;
0056
0057 nh->nlmsg_type = family;
0058 nh->nlmsg_flags = NLM_F_REQUEST;
0059 nh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
0060 off += NLMSG_ALIGN(sizeof(*nh));
0061
0062 gh = (void *)(data + off);
0063 gh->cmd = cmd;
0064 gh->version = version;
0065 off += NLMSG_ALIGN(sizeof(*gh));
0066 return off;
0067 }
0068
0069 static void nl_error(struct nlmsghdr *nh)
0070 {
0071 struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh);
0072 int len = nh->nlmsg_len - sizeof(*nh);
0073 uint32_t off;
0074
0075 if (len < sizeof(struct nlmsgerr))
0076 error(1, 0, "netlink error message truncated %d min %ld", len,
0077 sizeof(struct nlmsgerr));
0078
0079 if (!err->error) {
0080
0081 struct rtattr *attrs = (struct rtattr *)NLMSG_DATA(nh);
0082
0083 while (RTA_OK(attrs, len)) {
0084 if (attrs->rta_type == NLMSGERR_ATTR_MSG)
0085 fprintf(stderr, "netlink ext ack msg: %s\n",
0086 (char *)RTA_DATA(attrs));
0087 if (attrs->rta_type == NLMSGERR_ATTR_OFFS) {
0088 memcpy(&off, RTA_DATA(attrs), 4);
0089 fprintf(stderr, "netlink err off %d\n",
0090 (int)off);
0091 }
0092 attrs = RTA_NEXT(attrs, len);
0093 }
0094 } else {
0095 fprintf(stderr, "netlink error %d", err->error);
0096 }
0097 }
0098
0099 static int capture_events(int fd, int event_group)
0100 {
0101 u_int8_t buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0102 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024];
0103 struct genlmsghdr *ghdr;
0104 struct rtattr *attrs;
0105 struct nlmsghdr *nh;
0106 int ret = 0;
0107 int res_len;
0108 int msg_len;
0109 fd_set rfds;
0110
0111 if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
0112 &event_group, sizeof(event_group)) < 0)
0113 error(1, errno, "could not join the " MPTCP_PM_EVENTS " mcast group");
0114
0115 do {
0116 FD_ZERO(&rfds);
0117 FD_SET(fd, &rfds);
0118 res_len = NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0119 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024;
0120
0121 ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
0122
0123 if (ret < 0)
0124 error(1, ret, "error in select() on NL socket");
0125
0126 res_len = recv(fd, buffer, res_len, 0);
0127 if (res_len < 0)
0128 error(1, res_len, "error on recv() from NL socket");
0129
0130 nh = (struct nlmsghdr *)buffer;
0131
0132 for (; NLMSG_OK(nh, res_len); nh = NLMSG_NEXT(nh, res_len)) {
0133 if (nh->nlmsg_type == NLMSG_ERROR)
0134 error(1, NLMSG_ERROR, "received invalid NL message");
0135
0136 ghdr = (struct genlmsghdr *)NLMSG_DATA(nh);
0137
0138 if (ghdr->cmd == 0)
0139 continue;
0140
0141 fprintf(stderr, "type:%d", ghdr->cmd);
0142
0143 msg_len = nh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
0144
0145 attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
0146 while (RTA_OK(attrs, msg_len)) {
0147 if (attrs->rta_type == MPTCP_ATTR_TOKEN)
0148 fprintf(stderr, ",token:%u", *(__u32 *)RTA_DATA(attrs));
0149 else if (attrs->rta_type == MPTCP_ATTR_FAMILY)
0150 fprintf(stderr, ",family:%u", *(__u16 *)RTA_DATA(attrs));
0151 else if (attrs->rta_type == MPTCP_ATTR_LOC_ID)
0152 fprintf(stderr, ",loc_id:%u", *(__u8 *)RTA_DATA(attrs));
0153 else if (attrs->rta_type == MPTCP_ATTR_REM_ID)
0154 fprintf(stderr, ",rem_id:%u", *(__u8 *)RTA_DATA(attrs));
0155 else if (attrs->rta_type == MPTCP_ATTR_SADDR4) {
0156 u_int32_t saddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
0157
0158 fprintf(stderr, ",saddr4:%u.%u.%u.%u", saddr4 >> 24,
0159 (saddr4 >> 16) & 0xFF, (saddr4 >> 8) & 0xFF,
0160 (saddr4 & 0xFF));
0161 } else if (attrs->rta_type == MPTCP_ATTR_SADDR6) {
0162 char buf[INET6_ADDRSTRLEN];
0163
0164 if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
0165 sizeof(buf)) != NULL)
0166 fprintf(stderr, ",saddr6:%s", buf);
0167 } else if (attrs->rta_type == MPTCP_ATTR_DADDR4) {
0168 u_int32_t daddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
0169
0170 fprintf(stderr, ",daddr4:%u.%u.%u.%u", daddr4 >> 24,
0171 (daddr4 >> 16) & 0xFF, (daddr4 >> 8) & 0xFF,
0172 (daddr4 & 0xFF));
0173 } else if (attrs->rta_type == MPTCP_ATTR_DADDR6) {
0174 char buf[INET6_ADDRSTRLEN];
0175
0176 if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
0177 sizeof(buf)) != NULL)
0178 fprintf(stderr, ",daddr6:%s", buf);
0179 } else if (attrs->rta_type == MPTCP_ATTR_SPORT)
0180 fprintf(stderr, ",sport:%u",
0181 ntohs(*(__u16 *)RTA_DATA(attrs)));
0182 else if (attrs->rta_type == MPTCP_ATTR_DPORT)
0183 fprintf(stderr, ",dport:%u",
0184 ntohs(*(__u16 *)RTA_DATA(attrs)));
0185 else if (attrs->rta_type == MPTCP_ATTR_BACKUP)
0186 fprintf(stderr, ",backup:%u", *(__u8 *)RTA_DATA(attrs));
0187 else if (attrs->rta_type == MPTCP_ATTR_ERROR)
0188 fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs));
0189 else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE)
0190 fprintf(stderr, ",server_side:%u", *(__u8 *)RTA_DATA(attrs));
0191
0192 attrs = RTA_NEXT(attrs, msg_len);
0193 }
0194 }
0195 fprintf(stderr, "\n");
0196 } while (1);
0197
0198 return 0;
0199 }
0200
0201
0202 static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
0203 {
0204 struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
0205 socklen_t addr_len;
0206 void *data = nh;
0207 int rem, ret;
0208 int err = 0;
0209
0210 nh->nlmsg_len = len;
0211 ret = sendto(fd, data, len, 0, (void *)&nladdr, sizeof(nladdr));
0212 if (ret != len)
0213 error(1, errno, "send netlink: %uB != %uB\n", ret, len);
0214 if (max == 0)
0215 return 0;
0216
0217 addr_len = sizeof(nladdr);
0218 rem = ret = recvfrom(fd, data, max, 0, (void *)&nladdr, &addr_len);
0219 if (ret < 0)
0220 error(1, errno, "recv netlink: %uB\n", ret);
0221
0222
0223 for (; NLMSG_OK(nh, rem); nh = NLMSG_NEXT(nh, rem)) {
0224 if (nh->nlmsg_type == NLMSG_ERROR) {
0225 nl_error(nh);
0226 err = 1;
0227 }
0228 }
0229 if (err)
0230 error(1, 0, "bailing out due to netlink error[s]");
0231 return ret;
0232 }
0233
0234 static int genl_parse_getfamily(struct nlmsghdr *nlh, int *pm_family,
0235 int *events_mcast_grp)
0236 {
0237 struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
0238 int len = nlh->nlmsg_len;
0239 struct rtattr *attrs;
0240 struct rtattr *grps;
0241 struct rtattr *grp;
0242 int got_events_grp;
0243 int got_family;
0244 int grps_len;
0245 int grp_len;
0246
0247 if (nlh->nlmsg_type != GENL_ID_CTRL)
0248 error(1, errno, "Not a controller message, len=%d type=0x%x\n",
0249 nlh->nlmsg_len, nlh->nlmsg_type);
0250
0251 len -= NLMSG_LENGTH(GENL_HDRLEN);
0252
0253 if (len < 0)
0254 error(1, errno, "wrong controller message len %d\n", len);
0255
0256 if (ghdr->cmd != CTRL_CMD_NEWFAMILY)
0257 error(1, errno, "Unknown controller command %d\n", ghdr->cmd);
0258
0259 attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
0260 got_family = 0;
0261 got_events_grp = 0;
0262
0263 while (RTA_OK(attrs, len)) {
0264 if (attrs->rta_type == CTRL_ATTR_FAMILY_ID) {
0265 *pm_family = *(__u16 *)RTA_DATA(attrs);
0266 got_family = 1;
0267 } else if (attrs->rta_type == CTRL_ATTR_MCAST_GROUPS) {
0268 grps = RTA_DATA(attrs);
0269 grps_len = RTA_PAYLOAD(attrs);
0270
0271 while (RTA_OK(grps, grps_len)) {
0272 grp = RTA_DATA(grps);
0273 grp_len = RTA_PAYLOAD(grps);
0274 got_events_grp = 0;
0275
0276 while (RTA_OK(grp, grp_len)) {
0277 if (grp->rta_type == CTRL_ATTR_MCAST_GRP_ID)
0278 *events_mcast_grp = *(__u32 *)RTA_DATA(grp);
0279 else if (grp->rta_type == CTRL_ATTR_MCAST_GRP_NAME &&
0280 !strcmp(RTA_DATA(grp), MPTCP_PM_EVENTS))
0281 got_events_grp = 1;
0282
0283 grp = RTA_NEXT(grp, grp_len);
0284 }
0285
0286 if (got_events_grp)
0287 break;
0288
0289 grps = RTA_NEXT(grps, grps_len);
0290 }
0291 }
0292
0293 if (got_family && got_events_grp)
0294 return 0;
0295
0296 attrs = RTA_NEXT(attrs, len);
0297 }
0298
0299 error(1, errno, "can't find CTRL_ATTR_FAMILY_ID attr");
0300 return -1;
0301 }
0302
0303 static int resolve_mptcp_pm_netlink(int fd, int *pm_family, int *events_mcast_grp)
0304 {
0305 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0306 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0307 1024];
0308 struct nlmsghdr *nh;
0309 struct rtattr *rta;
0310 int namelen;
0311 int off = 0;
0312
0313 memset(data, 0, sizeof(data));
0314 nh = (void *)data;
0315 off = init_genl_req(data, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 0);
0316
0317 rta = (void *)(data + off);
0318 namelen = strlen(MPTCP_PM_NAME) + 1;
0319 rta->rta_type = CTRL_ATTR_FAMILY_NAME;
0320 rta->rta_len = RTA_LENGTH(namelen);
0321 memcpy(RTA_DATA(rta), MPTCP_PM_NAME, namelen);
0322 off += NLMSG_ALIGN(rta->rta_len);
0323
0324 do_nl_req(fd, nh, off, sizeof(data));
0325 return genl_parse_getfamily((void *)data, pm_family, events_mcast_grp);
0326 }
0327
0328 int dsf(int fd, int pm_family, int argc, char *argv[])
0329 {
0330 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0331 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0332 1024];
0333 struct rtattr *rta, *addr;
0334 u_int16_t family, port;
0335 struct nlmsghdr *nh;
0336 u_int32_t token;
0337 int addr_start;
0338 int off = 0;
0339 int arg;
0340
0341 const char *params[5];
0342
0343 memset(params, 0, 5 * sizeof(const char *));
0344
0345 memset(data, 0, sizeof(data));
0346 nh = (void *)data;
0347 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_DESTROY,
0348 MPTCP_PM_VER);
0349
0350 if (argc < 12)
0351 syntax(argv);
0352
0353
0354
0355
0356 for (arg = 2; arg < argc; arg++) {
0357 if (!strcmp(argv[arg], "lip")) {
0358 if (++arg >= argc)
0359 error(1, 0, " missing local IP");
0360
0361 params[0] = argv[arg];
0362 } else if (!strcmp(argv[arg], "lport")) {
0363 if (++arg >= argc)
0364 error(1, 0, " missing local port");
0365
0366 params[1] = argv[arg];
0367 } else if (!strcmp(argv[arg], "rip")) {
0368 if (++arg >= argc)
0369 error(1, 0, " missing remote IP");
0370
0371 params[2] = argv[arg];
0372 } else if (!strcmp(argv[arg], "rport")) {
0373 if (++arg >= argc)
0374 error(1, 0, " missing remote port");
0375
0376 params[3] = argv[arg];
0377 } else if (!strcmp(argv[arg], "token")) {
0378 if (++arg >= argc)
0379 error(1, 0, " missing token");
0380
0381 params[4] = argv[arg];
0382 } else
0383 error(1, 0, "unknown keyword %s", argv[arg]);
0384 }
0385
0386 for (arg = 0; arg < 4; arg = arg + 2) {
0387
0388 addr_start = off;
0389 addr = (void *)(data + off);
0390 addr->rta_type = NLA_F_NESTED |
0391 ((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
0392 addr->rta_len = RTA_LENGTH(0);
0393 off += NLMSG_ALIGN(addr->rta_len);
0394
0395
0396 rta = (void *)(data + off);
0397 if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
0398 family = AF_INET;
0399 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
0400 rta->rta_len = RTA_LENGTH(4);
0401 } else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
0402 family = AF_INET6;
0403 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
0404 rta->rta_len = RTA_LENGTH(16);
0405 } else
0406 error(1, errno, "can't parse ip %s", params[arg]);
0407 off += NLMSG_ALIGN(rta->rta_len);
0408
0409
0410 rta = (void *)(data + off);
0411 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
0412 rta->rta_len = RTA_LENGTH(2);
0413 memcpy(RTA_DATA(rta), &family, 2);
0414 off += NLMSG_ALIGN(rta->rta_len);
0415
0416
0417 port = atoi(params[arg + 1]);
0418 rta = (void *)(data + off);
0419 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
0420 rta->rta_len = RTA_LENGTH(2);
0421 memcpy(RTA_DATA(rta), &port, 2);
0422 off += NLMSG_ALIGN(rta->rta_len);
0423
0424 addr->rta_len = off - addr_start;
0425 }
0426
0427
0428 token = atoi(params[4]);
0429 rta = (void *)(data + off);
0430 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
0431 rta->rta_len = RTA_LENGTH(4);
0432 memcpy(RTA_DATA(rta), &token, 4);
0433 off += NLMSG_ALIGN(rta->rta_len);
0434
0435 do_nl_req(fd, nh, off, 0);
0436
0437 return 0;
0438 }
0439
0440 int csf(int fd, int pm_family, int argc, char *argv[])
0441 {
0442 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0443 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0444 1024];
0445 const char *params[5];
0446 struct nlmsghdr *nh;
0447 struct rtattr *addr;
0448 struct rtattr *rta;
0449 u_int16_t family;
0450 u_int32_t token;
0451 u_int16_t port;
0452 int addr_start;
0453 u_int8_t id;
0454 int off = 0;
0455 int arg;
0456
0457 memset(params, 0, 5 * sizeof(const char *));
0458
0459 memset(data, 0, sizeof(data));
0460 nh = (void *)data;
0461 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_CREATE,
0462 MPTCP_PM_VER);
0463
0464 if (argc < 12)
0465 syntax(argv);
0466
0467
0468
0469
0470 for (arg = 2; arg < argc; arg++) {
0471 if (!strcmp(argv[arg], "lip")) {
0472 if (++arg >= argc)
0473 error(1, 0, " missing local IP");
0474
0475 params[0] = argv[arg];
0476 } else if (!strcmp(argv[arg], "lid")) {
0477 if (++arg >= argc)
0478 error(1, 0, " missing local id");
0479
0480 params[1] = argv[arg];
0481 } else if (!strcmp(argv[arg], "rip")) {
0482 if (++arg >= argc)
0483 error(1, 0, " missing remote ip");
0484
0485 params[2] = argv[arg];
0486 } else if (!strcmp(argv[arg], "rport")) {
0487 if (++arg >= argc)
0488 error(1, 0, " missing remote port");
0489
0490 params[3] = argv[arg];
0491 } else if (!strcmp(argv[arg], "token")) {
0492 if (++arg >= argc)
0493 error(1, 0, " missing token");
0494
0495 params[4] = argv[arg];
0496 } else
0497 error(1, 0, "unknown param %s", argv[arg]);
0498 }
0499
0500 for (arg = 0; arg < 4; arg = arg + 2) {
0501
0502 addr_start = off;
0503 addr = (void *)(data + off);
0504 addr->rta_type = NLA_F_NESTED |
0505 ((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
0506 addr->rta_len = RTA_LENGTH(0);
0507 off += NLMSG_ALIGN(addr->rta_len);
0508
0509
0510 rta = (void *)(data + off);
0511 if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
0512 family = AF_INET;
0513 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
0514 rta->rta_len = RTA_LENGTH(4);
0515 } else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
0516 family = AF_INET6;
0517 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
0518 rta->rta_len = RTA_LENGTH(16);
0519 } else
0520 error(1, errno, "can't parse ip %s", params[arg]);
0521 off += NLMSG_ALIGN(rta->rta_len);
0522
0523
0524 rta = (void *)(data + off);
0525 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
0526 rta->rta_len = RTA_LENGTH(2);
0527 memcpy(RTA_DATA(rta), &family, 2);
0528 off += NLMSG_ALIGN(rta->rta_len);
0529
0530 if (arg == 2) {
0531
0532 port = atoi(params[arg + 1]);
0533 rta = (void *)(data + off);
0534 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
0535 rta->rta_len = RTA_LENGTH(2);
0536 memcpy(RTA_DATA(rta), &port, 2);
0537 off += NLMSG_ALIGN(rta->rta_len);
0538 }
0539
0540 if (arg == 0) {
0541
0542 id = atoi(params[arg + 1]);
0543 rta = (void *)(data + off);
0544 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
0545 rta->rta_len = RTA_LENGTH(1);
0546 memcpy(RTA_DATA(rta), &id, 1);
0547 off += NLMSG_ALIGN(rta->rta_len);
0548 }
0549
0550 addr->rta_len = off - addr_start;
0551 }
0552
0553
0554 token = atoi(params[4]);
0555 rta = (void *)(data + off);
0556 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
0557 rta->rta_len = RTA_LENGTH(4);
0558 memcpy(RTA_DATA(rta), &token, 4);
0559 off += NLMSG_ALIGN(rta->rta_len);
0560
0561 do_nl_req(fd, nh, off, 0);
0562
0563 return 0;
0564 }
0565
0566 int remove_addr(int fd, int pm_family, int argc, char *argv[])
0567 {
0568 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0569 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0570 1024];
0571 struct nlmsghdr *nh;
0572 struct rtattr *rta;
0573 u_int32_t token;
0574 u_int8_t id;
0575 int off = 0;
0576 int arg;
0577
0578 memset(data, 0, sizeof(data));
0579 nh = (void *)data;
0580 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_REMOVE,
0581 MPTCP_PM_VER);
0582
0583 if (argc < 6)
0584 syntax(argv);
0585
0586 for (arg = 2; arg < argc; arg++) {
0587 if (!strcmp(argv[arg], "id")) {
0588 if (++arg >= argc)
0589 error(1, 0, " missing id value");
0590
0591 id = atoi(argv[arg]);
0592 rta = (void *)(data + off);
0593 rta->rta_type = MPTCP_PM_ATTR_LOC_ID;
0594 rta->rta_len = RTA_LENGTH(1);
0595 memcpy(RTA_DATA(rta), &id, 1);
0596 off += NLMSG_ALIGN(rta->rta_len);
0597 } else if (!strcmp(argv[arg], "token")) {
0598 if (++arg >= argc)
0599 error(1, 0, " missing token value");
0600
0601 token = atoi(argv[arg]);
0602 rta = (void *)(data + off);
0603 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
0604 rta->rta_len = RTA_LENGTH(4);
0605 memcpy(RTA_DATA(rta), &token, 4);
0606 off += NLMSG_ALIGN(rta->rta_len);
0607 } else
0608 error(1, 0, "unknown keyword %s", argv[arg]);
0609 }
0610
0611 do_nl_req(fd, nh, off, 0);
0612 return 0;
0613 }
0614
0615 int announce_addr(int fd, int pm_family, int argc, char *argv[])
0616 {
0617 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0618 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0619 1024];
0620 u_int32_t flags = MPTCP_PM_ADDR_FLAG_SIGNAL;
0621 u_int32_t token = UINT_MAX;
0622 struct rtattr *rta, *addr;
0623 u_int32_t id = UINT_MAX;
0624 struct nlmsghdr *nh;
0625 u_int16_t family;
0626 int addr_start;
0627 int off = 0;
0628 int arg;
0629
0630 memset(data, 0, sizeof(data));
0631 nh = (void *)data;
0632 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ANNOUNCE,
0633 MPTCP_PM_VER);
0634
0635 if (argc < 7)
0636 syntax(argv);
0637
0638
0639 addr_start = off;
0640 addr = (void *)(data + off);
0641 addr->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
0642 addr->rta_len = RTA_LENGTH(0);
0643 off += NLMSG_ALIGN(addr->rta_len);
0644
0645
0646
0647 rta = (void *)(data + off);
0648 if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
0649 family = AF_INET;
0650 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
0651 rta->rta_len = RTA_LENGTH(4);
0652 } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
0653 family = AF_INET6;
0654 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
0655 rta->rta_len = RTA_LENGTH(16);
0656 } else
0657 error(1, errno, "can't parse ip %s", argv[2]);
0658 off += NLMSG_ALIGN(rta->rta_len);
0659
0660
0661 rta = (void *)(data + off);
0662 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
0663 rta->rta_len = RTA_LENGTH(2);
0664 memcpy(RTA_DATA(rta), &family, 2);
0665 off += NLMSG_ALIGN(rta->rta_len);
0666
0667 for (arg = 3; arg < argc; arg++) {
0668 if (!strcmp(argv[arg], "id")) {
0669
0670 if (++arg >= argc)
0671 error(1, 0, " missing id value");
0672
0673 id = atoi(argv[arg]);
0674 rta = (void *)(data + off);
0675 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
0676 rta->rta_len = RTA_LENGTH(1);
0677 memcpy(RTA_DATA(rta), &id, 1);
0678 off += NLMSG_ALIGN(rta->rta_len);
0679 } else if (!strcmp(argv[arg], "dev")) {
0680
0681 int32_t ifindex;
0682
0683 if (++arg >= argc)
0684 error(1, 0, " missing dev name");
0685
0686 ifindex = if_nametoindex(argv[arg]);
0687 if (!ifindex)
0688 error(1, errno, "unknown device %s", argv[arg]);
0689
0690 rta = (void *)(data + off);
0691 rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
0692 rta->rta_len = RTA_LENGTH(4);
0693 memcpy(RTA_DATA(rta), &ifindex, 4);
0694 off += NLMSG_ALIGN(rta->rta_len);
0695 } else if (!strcmp(argv[arg], "port")) {
0696
0697 u_int16_t port;
0698
0699 if (++arg >= argc)
0700 error(1, 0, " missing port value");
0701
0702 port = atoi(argv[arg]);
0703 rta = (void *)(data + off);
0704 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
0705 rta->rta_len = RTA_LENGTH(2);
0706 memcpy(RTA_DATA(rta), &port, 2);
0707 off += NLMSG_ALIGN(rta->rta_len);
0708 } else if (!strcmp(argv[arg], "token")) {
0709
0710 if (++arg >= argc)
0711 error(1, 0, " missing token value");
0712
0713 token = atoi(argv[arg]);
0714 } else
0715 error(1, 0, "unknown keyword %s", argv[arg]);
0716 }
0717
0718
0719 rta = (void *)(data + off);
0720 rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
0721 rta->rta_len = RTA_LENGTH(4);
0722 memcpy(RTA_DATA(rta), &flags, 4);
0723 off += NLMSG_ALIGN(rta->rta_len);
0724
0725 addr->rta_len = off - addr_start;
0726
0727 if (id == UINT_MAX || token == UINT_MAX)
0728 error(1, 0, " missing mandatory inputs");
0729
0730
0731 rta = (void *)(data + off);
0732 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
0733 rta->rta_len = RTA_LENGTH(4);
0734 memcpy(RTA_DATA(rta), &token, 4);
0735 off += NLMSG_ALIGN(rta->rta_len);
0736
0737 do_nl_req(fd, nh, off, 0);
0738
0739 return 0;
0740 }
0741
0742 int add_addr(int fd, int pm_family, int argc, char *argv[])
0743 {
0744 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0745 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0746 1024];
0747 struct rtattr *rta, *nest;
0748 struct nlmsghdr *nh;
0749 u_int32_t flags = 0;
0750 u_int16_t family;
0751 int nest_start;
0752 u_int8_t id;
0753 int off = 0;
0754 int arg;
0755
0756 memset(data, 0, sizeof(data));
0757 nh = (void *)data;
0758 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ADD_ADDR,
0759 MPTCP_PM_VER);
0760
0761 if (argc < 3)
0762 syntax(argv);
0763
0764 nest_start = off;
0765 nest = (void *)(data + off);
0766 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
0767 nest->rta_len = RTA_LENGTH(0);
0768 off += NLMSG_ALIGN(nest->rta_len);
0769
0770
0771 rta = (void *)(data + off);
0772 if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
0773 family = AF_INET;
0774 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
0775 rta->rta_len = RTA_LENGTH(4);
0776 } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
0777 family = AF_INET6;
0778 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
0779 rta->rta_len = RTA_LENGTH(16);
0780 } else
0781 error(1, errno, "can't parse ip %s", argv[2]);
0782 off += NLMSG_ALIGN(rta->rta_len);
0783
0784
0785 rta = (void *)(data + off);
0786 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
0787 rta->rta_len = RTA_LENGTH(2);
0788 memcpy(RTA_DATA(rta), &family, 2);
0789 off += NLMSG_ALIGN(rta->rta_len);
0790
0791 for (arg = 3; arg < argc; arg++) {
0792 if (!strcmp(argv[arg], "flags")) {
0793 char *tok, *str;
0794
0795
0796 if (++arg >= argc)
0797 error(1, 0, " missing flags value");
0798
0799
0800 for (str = argv[arg]; (tok = strtok(str, ","));
0801 str = NULL) {
0802 if (!strcmp(tok, "subflow"))
0803 flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;
0804 else if (!strcmp(tok, "signal"))
0805 flags |= MPTCP_PM_ADDR_FLAG_SIGNAL;
0806 else if (!strcmp(tok, "backup"))
0807 flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
0808 else if (!strcmp(tok, "fullmesh"))
0809 flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
0810 else
0811 error(1, errno,
0812 "unknown flag %s", argv[arg]);
0813 }
0814
0815 if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
0816 flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
0817 error(1, errno, "error flag fullmesh");
0818 }
0819
0820 rta = (void *)(data + off);
0821 rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
0822 rta->rta_len = RTA_LENGTH(4);
0823 memcpy(RTA_DATA(rta), &flags, 4);
0824 off += NLMSG_ALIGN(rta->rta_len);
0825 } else if (!strcmp(argv[arg], "id")) {
0826 if (++arg >= argc)
0827 error(1, 0, " missing id value");
0828
0829 id = atoi(argv[arg]);
0830 rta = (void *)(data + off);
0831 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
0832 rta->rta_len = RTA_LENGTH(1);
0833 memcpy(RTA_DATA(rta), &id, 1);
0834 off += NLMSG_ALIGN(rta->rta_len);
0835 } else if (!strcmp(argv[arg], "dev")) {
0836 int32_t ifindex;
0837
0838 if (++arg >= argc)
0839 error(1, 0, " missing dev name");
0840
0841 ifindex = if_nametoindex(argv[arg]);
0842 if (!ifindex)
0843 error(1, errno, "unknown device %s", argv[arg]);
0844
0845 rta = (void *)(data + off);
0846 rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
0847 rta->rta_len = RTA_LENGTH(4);
0848 memcpy(RTA_DATA(rta), &ifindex, 4);
0849 off += NLMSG_ALIGN(rta->rta_len);
0850 } else if (!strcmp(argv[arg], "port")) {
0851 u_int16_t port;
0852
0853 if (++arg >= argc)
0854 error(1, 0, " missing port value");
0855 if (!(flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
0856 error(1, 0, " flags must be signal when using port");
0857
0858 port = atoi(argv[arg]);
0859 rta = (void *)(data + off);
0860 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
0861 rta->rta_len = RTA_LENGTH(2);
0862 memcpy(RTA_DATA(rta), &port, 2);
0863 off += NLMSG_ALIGN(rta->rta_len);
0864 } else
0865 error(1, 0, "unknown keyword %s", argv[arg]);
0866 }
0867 nest->rta_len = off - nest_start;
0868
0869 do_nl_req(fd, nh, off, 0);
0870 return 0;
0871 }
0872
0873 int del_addr(int fd, int pm_family, int argc, char *argv[])
0874 {
0875 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0876 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0877 1024];
0878 struct rtattr *rta, *nest;
0879 struct nlmsghdr *nh;
0880 u_int16_t family;
0881 int nest_start;
0882 u_int8_t id;
0883 int off = 0;
0884
0885 memset(data, 0, sizeof(data));
0886 nh = (void *)data;
0887 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_DEL_ADDR,
0888 MPTCP_PM_VER);
0889
0890
0891 if (argc != 3 && argc != 4)
0892 syntax(argv);
0893
0894 id = atoi(argv[2]);
0895
0896 if (!id && argc != 4)
0897 syntax(argv);
0898
0899 nest_start = off;
0900 nest = (void *)(data + off);
0901 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
0902 nest->rta_len = RTA_LENGTH(0);
0903 off += NLMSG_ALIGN(nest->rta_len);
0904
0905
0906 rta = (void *)(data + off);
0907 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
0908 rta->rta_len = RTA_LENGTH(1);
0909 memcpy(RTA_DATA(rta), &id, 1);
0910 off += NLMSG_ALIGN(rta->rta_len);
0911
0912 if (!id) {
0913
0914 rta = (void *)(data + off);
0915 if (inet_pton(AF_INET, argv[3], RTA_DATA(rta))) {
0916 family = AF_INET;
0917 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
0918 rta->rta_len = RTA_LENGTH(4);
0919 } else if (inet_pton(AF_INET6, argv[3], RTA_DATA(rta))) {
0920 family = AF_INET6;
0921 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
0922 rta->rta_len = RTA_LENGTH(16);
0923 } else {
0924 error(1, errno, "can't parse ip %s", argv[3]);
0925 }
0926 off += NLMSG_ALIGN(rta->rta_len);
0927
0928
0929 rta = (void *)(data + off);
0930 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
0931 rta->rta_len = RTA_LENGTH(2);
0932 memcpy(RTA_DATA(rta), &family, 2);
0933 off += NLMSG_ALIGN(rta->rta_len);
0934 }
0935 nest->rta_len = off - nest_start;
0936
0937 do_nl_req(fd, nh, off, 0);
0938 return 0;
0939 }
0940
0941 static void print_addr(struct rtattr *attrs, int len)
0942 {
0943 uint16_t family = 0;
0944 uint16_t port = 0;
0945 char str[1024];
0946 uint32_t flags;
0947 uint8_t id;
0948
0949 while (RTA_OK(attrs, len)) {
0950 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FAMILY)
0951 memcpy(&family, RTA_DATA(attrs), 2);
0952 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_PORT)
0953 memcpy(&port, RTA_DATA(attrs), 2);
0954 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR4) {
0955 if (family != AF_INET)
0956 error(1, errno, "wrong IP (v4) for family %d",
0957 family);
0958 inet_ntop(AF_INET, RTA_DATA(attrs), str, sizeof(str));
0959 printf("%s", str);
0960 if (port)
0961 printf(" %d", port);
0962 }
0963 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR6) {
0964 if (family != AF_INET6)
0965 error(1, errno, "wrong IP (v6) for family %d",
0966 family);
0967 inet_ntop(AF_INET6, RTA_DATA(attrs), str, sizeof(str));
0968 printf("%s", str);
0969 if (port)
0970 printf(" %d", port);
0971 }
0972 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ID) {
0973 memcpy(&id, RTA_DATA(attrs), 1);
0974 printf("id %d ", id);
0975 }
0976 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FLAGS) {
0977 memcpy(&flags, RTA_DATA(attrs), 4);
0978
0979 printf("flags ");
0980 if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
0981 printf("signal");
0982 flags &= ~MPTCP_PM_ADDR_FLAG_SIGNAL;
0983 if (flags)
0984 printf(",");
0985 }
0986
0987 if (flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
0988 printf("subflow");
0989 flags &= ~MPTCP_PM_ADDR_FLAG_SUBFLOW;
0990 if (flags)
0991 printf(",");
0992 }
0993
0994 if (flags & MPTCP_PM_ADDR_FLAG_BACKUP) {
0995 printf("backup");
0996 flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
0997 if (flags)
0998 printf(",");
0999 }
1000
1001 if (flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
1002 printf("fullmesh");
1003 flags &= ~MPTCP_PM_ADDR_FLAG_FULLMESH;
1004 if (flags)
1005 printf(",");
1006 }
1007
1008 if (flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
1009 printf("implicit");
1010 flags &= ~MPTCP_PM_ADDR_FLAG_IMPLICIT;
1011 if (flags)
1012 printf(",");
1013 }
1014
1015
1016 if (flags)
1017 printf("0x%x", flags);
1018 printf(" ");
1019 }
1020 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_IF_IDX) {
1021 char name[IF_NAMESIZE], *ret;
1022 int32_t ifindex;
1023
1024 memcpy(&ifindex, RTA_DATA(attrs), 4);
1025 ret = if_indextoname(ifindex, name);
1026 if (ret)
1027 printf("dev %s ", ret);
1028 else
1029 printf("dev unknown/%d", ifindex);
1030 }
1031
1032 attrs = RTA_NEXT(attrs, len);
1033 }
1034 printf("\n");
1035 }
1036
1037 static void print_addrs(struct nlmsghdr *nh, int pm_family, int total_len)
1038 {
1039 struct rtattr *attrs;
1040
1041 for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
1042 int len = nh->nlmsg_len;
1043
1044 if (nh->nlmsg_type == NLMSG_DONE)
1045 break;
1046 if (nh->nlmsg_type == NLMSG_ERROR)
1047 nl_error(nh);
1048 if (nh->nlmsg_type != pm_family)
1049 continue;
1050
1051 len -= NLMSG_LENGTH(GENL_HDRLEN);
1052 attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
1053 GENL_HDRLEN);
1054 while (RTA_OK(attrs, len)) {
1055 if (attrs->rta_type ==
1056 (MPTCP_PM_ATTR_ADDR | NLA_F_NESTED))
1057 print_addr((void *)RTA_DATA(attrs),
1058 attrs->rta_len);
1059 attrs = RTA_NEXT(attrs, len);
1060 }
1061 }
1062 }
1063
1064 int get_addr(int fd, int pm_family, int argc, char *argv[])
1065 {
1066 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1067 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1068 1024];
1069 struct rtattr *rta, *nest;
1070 struct nlmsghdr *nh;
1071 int nest_start;
1072 u_int8_t id;
1073 int off = 0;
1074
1075 memset(data, 0, sizeof(data));
1076 nh = (void *)data;
1077 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
1078 MPTCP_PM_VER);
1079
1080
1081 if (argc != 3)
1082 syntax(argv);
1083
1084 id = atoi(argv[2]);
1085
1086 nest_start = off;
1087 nest = (void *)(data + off);
1088 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
1089 nest->rta_len = RTA_LENGTH(0);
1090 off += NLMSG_ALIGN(nest->rta_len);
1091
1092
1093 rta = (void *)(data + off);
1094 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
1095 rta->rta_len = RTA_LENGTH(1);
1096 memcpy(RTA_DATA(rta), &id, 1);
1097 off += NLMSG_ALIGN(rta->rta_len);
1098 nest->rta_len = off - nest_start;
1099
1100 print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
1101 return 0;
1102 }
1103
1104 int dump_addrs(int fd, int pm_family, int argc, char *argv[])
1105 {
1106 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1107 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1108 1024];
1109 pid_t pid = getpid();
1110 struct nlmsghdr *nh;
1111 int off = 0;
1112
1113 memset(data, 0, sizeof(data));
1114 nh = (void *)data;
1115 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
1116 MPTCP_PM_VER);
1117 nh->nlmsg_flags |= NLM_F_DUMP;
1118 nh->nlmsg_seq = 1;
1119 nh->nlmsg_pid = pid;
1120 nh->nlmsg_len = off;
1121
1122 print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
1123 return 0;
1124 }
1125
1126 int flush_addrs(int fd, int pm_family, int argc, char *argv[])
1127 {
1128 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1129 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1130 1024];
1131 struct nlmsghdr *nh;
1132 int off = 0;
1133
1134 memset(data, 0, sizeof(data));
1135 nh = (void *)data;
1136 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_FLUSH_ADDRS,
1137 MPTCP_PM_VER);
1138
1139 do_nl_req(fd, nh, off, 0);
1140 return 0;
1141 }
1142
1143 static void print_limits(struct nlmsghdr *nh, int pm_family, int total_len)
1144 {
1145 struct rtattr *attrs;
1146 uint32_t max;
1147
1148 for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
1149 int len = nh->nlmsg_len;
1150
1151 if (nh->nlmsg_type == NLMSG_DONE)
1152 break;
1153 if (nh->nlmsg_type == NLMSG_ERROR)
1154 nl_error(nh);
1155 if (nh->nlmsg_type != pm_family)
1156 continue;
1157
1158 len -= NLMSG_LENGTH(GENL_HDRLEN);
1159 attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
1160 GENL_HDRLEN);
1161 while (RTA_OK(attrs, len)) {
1162 int type = attrs->rta_type;
1163
1164 if (type != MPTCP_PM_ATTR_RCV_ADD_ADDRS &&
1165 type != MPTCP_PM_ATTR_SUBFLOWS)
1166 goto next;
1167
1168 memcpy(&max, RTA_DATA(attrs), 4);
1169 printf("%s %u\n", type == MPTCP_PM_ATTR_SUBFLOWS ?
1170 "subflows" : "accept", max);
1171
1172 next:
1173 attrs = RTA_NEXT(attrs, len);
1174 }
1175 }
1176 }
1177
1178 int get_set_limits(int fd, int pm_family, int argc, char *argv[])
1179 {
1180 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1181 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1182 1024];
1183 uint32_t rcv_addr = 0, subflows = 0;
1184 int cmd, len = sizeof(data);
1185 struct nlmsghdr *nh;
1186 int off = 0;
1187
1188
1189 if (argc == 4) {
1190 rcv_addr = atoi(argv[2]);
1191 subflows = atoi(argv[3]);
1192 cmd = MPTCP_PM_CMD_SET_LIMITS;
1193 } else {
1194 cmd = MPTCP_PM_CMD_GET_LIMITS;
1195 }
1196
1197 memset(data, 0, sizeof(data));
1198 nh = (void *)data;
1199 off = init_genl_req(data, pm_family, cmd, MPTCP_PM_VER);
1200
1201
1202 if (cmd == MPTCP_PM_CMD_SET_LIMITS) {
1203 struct rtattr *rta = (void *)(data + off);
1204
1205 rta->rta_type = MPTCP_PM_ATTR_RCV_ADD_ADDRS;
1206 rta->rta_len = RTA_LENGTH(4);
1207 memcpy(RTA_DATA(rta), &rcv_addr, 4);
1208 off += NLMSG_ALIGN(rta->rta_len);
1209
1210 rta = (void *)(data + off);
1211 rta->rta_type = MPTCP_PM_ATTR_SUBFLOWS;
1212 rta->rta_len = RTA_LENGTH(4);
1213 memcpy(RTA_DATA(rta), &subflows, 4);
1214 off += NLMSG_ALIGN(rta->rta_len);
1215
1216
1217 len = 0;
1218 }
1219
1220 len = do_nl_req(fd, nh, off, len);
1221 if (cmd == MPTCP_PM_CMD_GET_LIMITS)
1222 print_limits(nh, pm_family, len);
1223 return 0;
1224 }
1225
1226 int add_listener(int argc, char *argv[])
1227 {
1228 struct sockaddr_storage addr;
1229 struct sockaddr_in6 *a6;
1230 struct sockaddr_in *a4;
1231 u_int16_t family;
1232 int enable = 1;
1233 int sock;
1234 int err;
1235
1236 if (argc < 4)
1237 syntax(argv);
1238
1239 memset(&addr, 0, sizeof(struct sockaddr_storage));
1240 a4 = (struct sockaddr_in *)&addr;
1241 a6 = (struct sockaddr_in6 *)&addr;
1242
1243 if (inet_pton(AF_INET, argv[2], &a4->sin_addr)) {
1244 family = AF_INET;
1245 a4->sin_family = family;
1246 a4->sin_port = htons(atoi(argv[3]));
1247 } else if (inet_pton(AF_INET6, argv[2], &a6->sin6_addr)) {
1248 family = AF_INET6;
1249 a6->sin6_family = family;
1250 a6->sin6_port = htons(atoi(argv[3]));
1251 } else
1252 error(1, errno, "can't parse ip %s", argv[2]);
1253
1254 sock = socket(family, SOCK_STREAM, IPPROTO_MPTCP);
1255 if (sock < 0)
1256 error(1, errno, "can't create listener sock\n");
1257
1258 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) {
1259 close(sock);
1260 error(1, errno, "can't set SO_REUSEADDR on listener sock\n");
1261 }
1262
1263 err = bind(sock, (struct sockaddr *)&addr,
1264 ((family == AF_INET) ? sizeof(struct sockaddr_in) :
1265 sizeof(struct sockaddr_in6)));
1266
1267 if (err == 0 && listen(sock, 30) == 0)
1268 pause();
1269
1270 close(sock);
1271 return 0;
1272 }
1273
1274 int set_flags(int fd, int pm_family, int argc, char *argv[])
1275 {
1276 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1277 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1278 1024];
1279 struct rtattr *rta, *nest;
1280 struct nlmsghdr *nh;
1281 u_int32_t flags = 0;
1282 u_int32_t token = 0;
1283 u_int16_t rport = 0;
1284 u_int16_t family;
1285 void *rip = NULL;
1286 int nest_start;
1287 int use_id = 0;
1288 u_int8_t id;
1289 int off = 0;
1290 int arg = 2;
1291
1292 memset(data, 0, sizeof(data));
1293 nh = (void *)data;
1294 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS,
1295 MPTCP_PM_VER);
1296
1297 if (argc < 3)
1298 syntax(argv);
1299
1300 nest_start = off;
1301 nest = (void *)(data + off);
1302 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
1303 nest->rta_len = RTA_LENGTH(0);
1304 off += NLMSG_ALIGN(nest->rta_len);
1305
1306 if (!strcmp(argv[arg], "id")) {
1307 if (++arg >= argc)
1308 error(1, 0, " missing id value");
1309
1310 use_id = 1;
1311 id = atoi(argv[arg]);
1312 rta = (void *)(data + off);
1313 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
1314 rta->rta_len = RTA_LENGTH(1);
1315 memcpy(RTA_DATA(rta), &id, 1);
1316 off += NLMSG_ALIGN(rta->rta_len);
1317 } else {
1318
1319 rta = (void *)(data + off);
1320 if (inet_pton(AF_INET, argv[arg], RTA_DATA(rta))) {
1321 family = AF_INET;
1322 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
1323 rta->rta_len = RTA_LENGTH(4);
1324 } else if (inet_pton(AF_INET6, argv[arg], RTA_DATA(rta))) {
1325 family = AF_INET6;
1326 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
1327 rta->rta_len = RTA_LENGTH(16);
1328 } else {
1329 error(1, errno, "can't parse ip %s", argv[arg]);
1330 }
1331 off += NLMSG_ALIGN(rta->rta_len);
1332
1333
1334 rta = (void *)(data + off);
1335 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
1336 rta->rta_len = RTA_LENGTH(2);
1337 memcpy(RTA_DATA(rta), &family, 2);
1338 off += NLMSG_ALIGN(rta->rta_len);
1339 }
1340
1341 if (++arg >= argc)
1342 error(1, 0, " missing flags keyword");
1343
1344 for (; arg < argc; arg++) {
1345 if (!strcmp(argv[arg], "token")) {
1346 if (++arg >= argc)
1347 error(1, 0, " missing token value");
1348
1349
1350 token = atoi(argv[arg]);
1351 } else if (!strcmp(argv[arg], "flags")) {
1352 char *tok, *str;
1353
1354
1355 if (++arg >= argc)
1356 error(1, 0, " missing flags value");
1357
1358 for (str = argv[arg]; (tok = strtok(str, ","));
1359 str = NULL) {
1360 if (!strcmp(tok, "backup"))
1361 flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
1362 else if (!strcmp(tok, "fullmesh"))
1363 flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
1364 else if (strcmp(tok, "nobackup") &&
1365 strcmp(tok, "nofullmesh"))
1366 error(1, errno,
1367 "unknown flag %s", argv[arg]);
1368 }
1369
1370 rta = (void *)(data + off);
1371 rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
1372 rta->rta_len = RTA_LENGTH(4);
1373 memcpy(RTA_DATA(rta), &flags, 4);
1374 off += NLMSG_ALIGN(rta->rta_len);
1375 } else if (!strcmp(argv[arg], "port")) {
1376 u_int16_t port;
1377
1378 if (use_id)
1379 error(1, 0, " port can't be used with id");
1380
1381 if (++arg >= argc)
1382 error(1, 0, " missing port value");
1383
1384 port = atoi(argv[arg]);
1385 rta = (void *)(data + off);
1386 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
1387 rta->rta_len = RTA_LENGTH(2);
1388 memcpy(RTA_DATA(rta), &port, 2);
1389 off += NLMSG_ALIGN(rta->rta_len);
1390 } else if (!strcmp(argv[arg], "rport")) {
1391 if (++arg >= argc)
1392 error(1, 0, " missing remote port");
1393
1394 rport = atoi(argv[arg]);
1395 } else if (!strcmp(argv[arg], "rip")) {
1396 if (++arg >= argc)
1397 error(1, 0, " missing remote ip");
1398
1399 rip = argv[arg];
1400 } else {
1401 error(1, 0, "unknown keyword %s", argv[arg]);
1402 }
1403 }
1404 nest->rta_len = off - nest_start;
1405
1406
1407 if (token) {
1408 rta = (void *)(data + off);
1409 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
1410 rta->rta_len = RTA_LENGTH(4);
1411 memcpy(RTA_DATA(rta), &token, 4);
1412 off += NLMSG_ALIGN(rta->rta_len);
1413 }
1414
1415
1416 if (rip) {
1417 nest_start = off;
1418 nest = (void *)(data + off);
1419 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR_REMOTE;
1420 nest->rta_len = RTA_LENGTH(0);
1421 off += NLMSG_ALIGN(nest->rta_len);
1422
1423
1424 rta = (void *)(data + off);
1425 if (inet_pton(AF_INET, rip, RTA_DATA(rta))) {
1426 family = AF_INET;
1427 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
1428 rta->rta_len = RTA_LENGTH(4);
1429 } else if (inet_pton(AF_INET6, rip, RTA_DATA(rta))) {
1430 family = AF_INET6;
1431 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
1432 rta->rta_len = RTA_LENGTH(16);
1433 } else {
1434 error(1, errno, "can't parse ip %s", (char *)rip);
1435 }
1436 off += NLMSG_ALIGN(rta->rta_len);
1437
1438
1439 rta = (void *)(data + off);
1440 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
1441 rta->rta_len = RTA_LENGTH(2);
1442 memcpy(RTA_DATA(rta), &family, 2);
1443 off += NLMSG_ALIGN(rta->rta_len);
1444
1445 if (rport) {
1446 rta = (void *)(data + off);
1447 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
1448 rta->rta_len = RTA_LENGTH(2);
1449 memcpy(RTA_DATA(rta), &rport, 2);
1450 off += NLMSG_ALIGN(rta->rta_len);
1451 }
1452
1453 nest->rta_len = off - nest_start;
1454 }
1455
1456 do_nl_req(fd, nh, off, 0);
1457 return 0;
1458 }
1459
1460 int main(int argc, char *argv[])
1461 {
1462 int events_mcast_grp;
1463 int pm_family;
1464 int fd;
1465
1466 if (argc < 2)
1467 syntax(argv);
1468
1469 fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
1470 if (fd == -1)
1471 error(1, errno, "socket netlink");
1472
1473 resolve_mptcp_pm_netlink(fd, &pm_family, &events_mcast_grp);
1474
1475 if (!strcmp(argv[1], "add"))
1476 return add_addr(fd, pm_family, argc, argv);
1477 else if (!strcmp(argv[1], "ann"))
1478 return announce_addr(fd, pm_family, argc, argv);
1479 else if (!strcmp(argv[1], "rem"))
1480 return remove_addr(fd, pm_family, argc, argv);
1481 else if (!strcmp(argv[1], "csf"))
1482 return csf(fd, pm_family, argc, argv);
1483 else if (!strcmp(argv[1], "dsf"))
1484 return dsf(fd, pm_family, argc, argv);
1485 else if (!strcmp(argv[1], "del"))
1486 return del_addr(fd, pm_family, argc, argv);
1487 else if (!strcmp(argv[1], "flush"))
1488 return flush_addrs(fd, pm_family, argc, argv);
1489 else if (!strcmp(argv[1], "get"))
1490 return get_addr(fd, pm_family, argc, argv);
1491 else if (!strcmp(argv[1], "dump"))
1492 return dump_addrs(fd, pm_family, argc, argv);
1493 else if (!strcmp(argv[1], "limits"))
1494 return get_set_limits(fd, pm_family, argc, argv);
1495 else if (!strcmp(argv[1], "set"))
1496 return set_flags(fd, pm_family, argc, argv);
1497 else if (!strcmp(argv[1], "events"))
1498 return capture_events(fd, events_mcast_grp);
1499 else if (!strcmp(argv[1], "listen"))
1500 return add_listener(argc, argv);
1501
1502 fprintf(stderr, "unknown sub-command: %s", argv[1]);
1503 syntax(argv);
1504 return 0;
1505 }