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