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