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