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