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 static void syntax(char *argv[]) 28 { 29 fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]); 30 fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n"); 31 fprintf(stderr, "\tann <local-ip> id <local-id> token <token> [port <local-port>] [dev <name>]\n"); 32 fprintf(stderr, "\trem id <local-id> token <token>\n"); 33 fprintf(stderr, "\tcsf lip <local-ip> lid <local-id> rip <remote-ip> rport <remote-port> token <token>\n"); 34 fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n"); 35 fprintf(stderr, "\tdel <id> [<ip>]\n"); 36 fprintf(stderr, "\tget <id>\n"); 37 fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>] [token <token>] [rip <ip>] [rport <port>]\n"); 38 fprintf(stderr, "\tflush\n"); 39 fprintf(stderr, "\tdump\n"); 40 fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n"); 41 fprintf(stderr, "\tevents\n"); 42 fprintf(stderr, "\tlisten <local-ip> <local-port>\n"); 43 exit(0); 44 } 45 46 static int init_genl_req(char *data, int family, int cmd, int version) 47 { 48 struct nlmsghdr *nh = (void *)data; 49 struct genlmsghdr *gh; 50 int off = 0; 51 52 nh->nlmsg_type = family; 53 nh->nlmsg_flags = NLM_F_REQUEST; 54 nh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); 55 off += NLMSG_ALIGN(sizeof(*nh)); 56 57 gh = (void *)(data + off); 58 gh->cmd = cmd; 59 gh->version = version; 60 off += NLMSG_ALIGN(sizeof(*gh)); 61 return off; 62 } 63 64 static int nl_error(struct nlmsghdr *nh) 65 { 66 struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh); 67 int len = nh->nlmsg_len - sizeof(*nh); 68 uint32_t off; 69 70 if (len < sizeof(struct nlmsgerr)) { 71 error(1, 0, "netlink error message truncated %d min %ld", len, 72 sizeof(struct nlmsgerr)); 73 return -1; 74 } 75 76 if (err->error) { 77 /* check messages from kernel */ 78 struct rtattr *attrs = (struct rtattr *)NLMSG_DATA(nh); 79 80 fprintf(stderr, "netlink error %d (%s)\n", 81 err->error, strerror(-err->error)); 82 83 while (RTA_OK(attrs, len)) { 84 if (attrs->rta_type == NLMSGERR_ATTR_MSG) 85 fprintf(stderr, "netlink ext ack msg: %s\n", 86 (char *)RTA_DATA(attrs)); 87 if (attrs->rta_type == NLMSGERR_ATTR_OFFS) { 88 memcpy(&off, RTA_DATA(attrs), 4); 89 fprintf(stderr, "netlink err off %d\n", 90 (int)off); 91 } 92 attrs = RTA_NEXT(attrs, len); 93 } 94 return -1; 95 } 96 97 return 0; 98 } 99 100 static int capture_events(int fd, int event_group) 101 { 102 u_int8_t buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 103 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024]; 104 struct genlmsghdr *ghdr; 105 struct rtattr *attrs; 106 struct nlmsghdr *nh; 107 int ret = 0; 108 int res_len; 109 int msg_len; 110 fd_set rfds; 111 112 if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, 113 &event_group, sizeof(event_group)) < 0) 114 error(1, errno, "could not join the " MPTCP_PM_EV_GRP_NAME " mcast group"); 115 116 do { 117 bool server_side = false; 118 119 FD_ZERO(&rfds); 120 FD_SET(fd, &rfds); 121 res_len = NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 122 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024; 123 124 ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL); 125 126 if (ret < 0) 127 error(1, ret, "error in select() on NL socket"); 128 129 res_len = recv(fd, buffer, res_len, 0); 130 if (res_len < 0) 131 error(1, res_len, "error on recv() from NL socket"); 132 133 nh = (struct nlmsghdr *)buffer; 134 135 for (; NLMSG_OK(nh, res_len); nh = NLMSG_NEXT(nh, res_len)) { 136 if (nh->nlmsg_type == NLMSG_ERROR) 137 error(1, NLMSG_ERROR, "received invalid NL message"); 138 139 ghdr = (struct genlmsghdr *)NLMSG_DATA(nh); 140 141 if (ghdr->cmd == 0) 142 continue; 143 144 fprintf(stderr, "type:%d", ghdr->cmd); 145 146 msg_len = nh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN); 147 148 attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN); 149 while (RTA_OK(attrs, msg_len)) { 150 if (attrs->rta_type == MPTCP_ATTR_TOKEN) 151 fprintf(stderr, ",token:%u", *(__u32 *)RTA_DATA(attrs)); 152 else if (attrs->rta_type == MPTCP_ATTR_FAMILY) 153 fprintf(stderr, ",family:%u", *(__u16 *)RTA_DATA(attrs)); 154 else if (attrs->rta_type == MPTCP_ATTR_LOC_ID) 155 fprintf(stderr, ",loc_id:%u", *(__u8 *)RTA_DATA(attrs)); 156 else if (attrs->rta_type == MPTCP_ATTR_REM_ID) 157 fprintf(stderr, ",rem_id:%u", *(__u8 *)RTA_DATA(attrs)); 158 else if (attrs->rta_type == MPTCP_ATTR_SADDR4) { 159 u_int32_t saddr4 = ntohl(*(__u32 *)RTA_DATA(attrs)); 160 161 fprintf(stderr, ",saddr4:%u.%u.%u.%u", saddr4 >> 24, 162 (saddr4 >> 16) & 0xFF, (saddr4 >> 8) & 0xFF, 163 (saddr4 & 0xFF)); 164 } else if (attrs->rta_type == MPTCP_ATTR_SADDR6) { 165 char buf[INET6_ADDRSTRLEN]; 166 167 if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf, 168 sizeof(buf)) != NULL) 169 fprintf(stderr, ",saddr6:%s", buf); 170 } else if (attrs->rta_type == MPTCP_ATTR_DADDR4) { 171 u_int32_t daddr4 = ntohl(*(__u32 *)RTA_DATA(attrs)); 172 173 fprintf(stderr, ",daddr4:%u.%u.%u.%u", daddr4 >> 24, 174 (daddr4 >> 16) & 0xFF, (daddr4 >> 8) & 0xFF, 175 (daddr4 & 0xFF)); 176 } else if (attrs->rta_type == MPTCP_ATTR_DADDR6) { 177 char buf[INET6_ADDRSTRLEN]; 178 179 if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf, 180 sizeof(buf)) != NULL) 181 fprintf(stderr, ",daddr6:%s", buf); 182 } else if (attrs->rta_type == MPTCP_ATTR_SPORT) 183 fprintf(stderr, ",sport:%u", 184 ntohs(*(__u16 *)RTA_DATA(attrs))); 185 else if (attrs->rta_type == MPTCP_ATTR_DPORT) 186 fprintf(stderr, ",dport:%u", 187 ntohs(*(__u16 *)RTA_DATA(attrs))); 188 else if (attrs->rta_type == MPTCP_ATTR_BACKUP) 189 fprintf(stderr, ",backup:%u", *(__u8 *)RTA_DATA(attrs)); 190 else if (attrs->rta_type == MPTCP_ATTR_ERROR) 191 fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs)); 192 else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE) 193 server_side = !!*(__u8 *)RTA_DATA(attrs); 194 else if (attrs->rta_type == MPTCP_ATTR_FLAGS) { 195 __u16 flags = *(__u16 *)RTA_DATA(attrs); 196 197 /* only print when present, easier */ 198 if (flags & MPTCP_PM_EV_FLAG_DENY_JOIN_ID0) 199 fprintf(stderr, ",deny_join_id0:1"); 200 if (flags & MPTCP_PM_EV_FLAG_SERVER_SIDE) 201 server_side = true; 202 } 203 204 attrs = RTA_NEXT(attrs, msg_len); 205 } 206 } 207 if (server_side) 208 fprintf(stderr, ",server_side:1"); 209 fprintf(stderr, "\n"); 210 } while (1); 211 212 return 0; 213 } 214 215 /* do a netlink command and, if max > 0, fetch the reply ; nh's size >1024B */ 216 static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max) 217 { 218 struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK }; 219 socklen_t addr_len; 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 = sendto(fd, data, len, 0, (void *)&nladdr, sizeof(nladdr)); 232 if (ret != len) 233 error(1, errno, "send netlink: %uB != %uB\n", ret, len); 234 235 addr_len = sizeof(nladdr); 236 rem = ret = recvfrom(fd, data, max, 0, (void *)&nladdr, &addr_len); 237 if (ret < 0) 238 error(1, errno, "recv netlink: %uB\n", ret); 239 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, "backup")) 834 flags |= MPTCP_PM_ADDR_FLAG_BACKUP; 835 else if (!strcmp(tok, "fullmesh")) 836 flags |= MPTCP_PM_ADDR_FLAG_FULLMESH; 837 else 838 error(1, errno, 839 "unknown flag %s", argv[arg]); 840 } 841 842 if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL && 843 flags & MPTCP_PM_ADDR_FLAG_FULLMESH) { 844 error(1, errno, "error flag fullmesh"); 845 } 846 847 rta = (void *)(data + off); 848 rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS; 849 rta->rta_len = RTA_LENGTH(4); 850 memcpy(RTA_DATA(rta), &flags, 4); 851 off += NLMSG_ALIGN(rta->rta_len); 852 } else if (!strcmp(argv[arg], "id")) { 853 if (++arg >= argc) 854 error(1, 0, " missing id value"); 855 856 id = atoi(argv[arg]); 857 rta = (void *)(data + off); 858 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID; 859 rta->rta_len = RTA_LENGTH(1); 860 memcpy(RTA_DATA(rta), &id, 1); 861 off += NLMSG_ALIGN(rta->rta_len); 862 } else if (!strcmp(argv[arg], "dev")) { 863 int32_t ifindex; 864 865 if (++arg >= argc) 866 error(1, 0, " missing dev name"); 867 868 ifindex = if_nametoindex(argv[arg]); 869 if (!ifindex) 870 error(1, errno, "unknown device %s", argv[arg]); 871 872 rta = (void *)(data + off); 873 rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX; 874 rta->rta_len = RTA_LENGTH(4); 875 memcpy(RTA_DATA(rta), &ifindex, 4); 876 off += NLMSG_ALIGN(rta->rta_len); 877 } else if (!strcmp(argv[arg], "port")) { 878 u_int16_t port; 879 880 if (++arg >= argc) 881 error(1, 0, " missing port value"); 882 if (!(flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) 883 error(1, 0, " flags must be signal when using port"); 884 885 port = atoi(argv[arg]); 886 rta = (void *)(data + off); 887 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT; 888 rta->rta_len = RTA_LENGTH(2); 889 memcpy(RTA_DATA(rta), &port, 2); 890 off += NLMSG_ALIGN(rta->rta_len); 891 } else 892 error(1, 0, "unknown keyword %s", argv[arg]); 893 } 894 nest->rta_len = off - nest_start; 895 896 do_nl_req(fd, nh, off, 0); 897 return 0; 898 } 899 900 int del_addr(int fd, int pm_family, int argc, char *argv[]) 901 { 902 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 903 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 904 1024]; 905 struct rtattr *rta, *nest; 906 struct nlmsghdr *nh; 907 u_int16_t family; 908 int nest_start; 909 u_int8_t id; 910 int off = 0; 911 912 memset(data, 0, sizeof(data)); 913 nh = (void *)data; 914 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_DEL_ADDR, 915 MPTCP_PM_VER); 916 917 /* the only argument is the address id (nonzero) */ 918 if (argc != 3 && argc != 4) 919 syntax(argv); 920 921 id = atoi(argv[2]); 922 /* zero id with the IP address */ 923 if (!id && argc != 4) 924 syntax(argv); 925 926 nest_start = off; 927 nest = (void *)(data + off); 928 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR; 929 nest->rta_len = RTA_LENGTH(0); 930 off += NLMSG_ALIGN(nest->rta_len); 931 932 /* build a dummy addr with only the ID set */ 933 rta = (void *)(data + off); 934 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID; 935 rta->rta_len = RTA_LENGTH(1); 936 memcpy(RTA_DATA(rta), &id, 1); 937 off += NLMSG_ALIGN(rta->rta_len); 938 939 if (!id) { 940 /* addr data */ 941 rta = (void *)(data + off); 942 if (inet_pton(AF_INET, argv[3], RTA_DATA(rta))) { 943 family = AF_INET; 944 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4; 945 rta->rta_len = RTA_LENGTH(4); 946 } else if (inet_pton(AF_INET6, argv[3], RTA_DATA(rta))) { 947 family = AF_INET6; 948 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6; 949 rta->rta_len = RTA_LENGTH(16); 950 } else { 951 error(1, errno, "can't parse ip %s", argv[3]); 952 } 953 off += NLMSG_ALIGN(rta->rta_len); 954 955 /* family */ 956 rta = (void *)(data + off); 957 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY; 958 rta->rta_len = RTA_LENGTH(2); 959 memcpy(RTA_DATA(rta), &family, 2); 960 off += NLMSG_ALIGN(rta->rta_len); 961 } 962 nest->rta_len = off - nest_start; 963 964 do_nl_req(fd, nh, off, 0); 965 return 0; 966 } 967 968 static void print_addr(struct rtattr *attrs, int len) 969 { 970 uint16_t family = 0; 971 uint16_t port = 0; 972 char str[1024]; 973 uint32_t flags; 974 uint8_t id; 975 976 while (RTA_OK(attrs, len)) { 977 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FAMILY) 978 memcpy(&family, RTA_DATA(attrs), 2); 979 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_PORT) 980 memcpy(&port, RTA_DATA(attrs), 2); 981 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR4) { 982 if (family != AF_INET) 983 error(1, errno, "wrong IP (v4) for family %d", 984 family); 985 inet_ntop(AF_INET, RTA_DATA(attrs), str, sizeof(str)); 986 printf("%s", str); 987 if (port) 988 printf(" %d", port); 989 } 990 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR6) { 991 if (family != AF_INET6) 992 error(1, errno, "wrong IP (v6) for family %d", 993 family); 994 inet_ntop(AF_INET6, RTA_DATA(attrs), str, sizeof(str)); 995 printf("%s", str); 996 if (port) 997 printf(" %d", port); 998 } 999 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ID) { 1000 memcpy(&id, RTA_DATA(attrs), 1); 1001 printf("id %d ", id); 1002 } 1003 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FLAGS) { 1004 memcpy(&flags, RTA_DATA(attrs), 4); 1005 1006 printf("flags "); 1007 if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL) { 1008 printf("signal"); 1009 flags &= ~MPTCP_PM_ADDR_FLAG_SIGNAL; 1010 if (flags) 1011 printf(","); 1012 } 1013 1014 if (flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) { 1015 printf("subflow"); 1016 flags &= ~MPTCP_PM_ADDR_FLAG_SUBFLOW; 1017 if (flags) 1018 printf(","); 1019 } 1020 1021 if (flags & MPTCP_PM_ADDR_FLAG_BACKUP) { 1022 printf("backup"); 1023 flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP; 1024 if (flags) 1025 printf(","); 1026 } 1027 1028 if (flags & MPTCP_PM_ADDR_FLAG_FULLMESH) { 1029 printf("fullmesh"); 1030 flags &= ~MPTCP_PM_ADDR_FLAG_FULLMESH; 1031 if (flags) 1032 printf(","); 1033 } 1034 1035 if (flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) { 1036 printf("implicit"); 1037 flags &= ~MPTCP_PM_ADDR_FLAG_IMPLICIT; 1038 if (flags) 1039 printf(","); 1040 } 1041 1042 /* bump unknown flags, if any */ 1043 if (flags) 1044 printf("0x%x", flags); 1045 printf(" "); 1046 } 1047 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_IF_IDX) { 1048 char name[IF_NAMESIZE], *ret; 1049 int32_t ifindex; 1050 1051 memcpy(&ifindex, RTA_DATA(attrs), 4); 1052 ret = if_indextoname(ifindex, name); 1053 if (ret) 1054 printf("dev %s ", ret); 1055 else 1056 printf("dev unknown/%d", ifindex); 1057 } 1058 1059 attrs = RTA_NEXT(attrs, len); 1060 } 1061 printf("\n"); 1062 } 1063 1064 static void print_addrs(struct nlmsghdr *nh, int pm_family, int total_len) 1065 { 1066 struct rtattr *attrs; 1067 1068 for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) { 1069 int len = nh->nlmsg_len; 1070 1071 if (nh->nlmsg_type == NLMSG_DONE) 1072 break; 1073 if (nh->nlmsg_type == NLMSG_ERROR) 1074 nl_error(nh); 1075 if (nh->nlmsg_type != pm_family) 1076 continue; 1077 1078 len -= NLMSG_LENGTH(GENL_HDRLEN); 1079 attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) + 1080 GENL_HDRLEN); 1081 while (RTA_OK(attrs, len)) { 1082 if (attrs->rta_type == 1083 (MPTCP_PM_ATTR_ADDR | NLA_F_NESTED)) 1084 print_addr((void *)RTA_DATA(attrs), 1085 attrs->rta_len); 1086 attrs = RTA_NEXT(attrs, len); 1087 } 1088 } 1089 } 1090 1091 int get_addr(int fd, int pm_family, int argc, char *argv[]) 1092 { 1093 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 1094 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1095 1024]; 1096 struct rtattr *rta, *nest; 1097 struct nlmsghdr *nh; 1098 u_int32_t token = 0; 1099 int nest_start; 1100 u_int8_t id; 1101 int off = 0; 1102 1103 memset(data, 0, sizeof(data)); 1104 nh = (void *)data; 1105 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR, 1106 MPTCP_PM_VER); 1107 1108 /* the only argument is the address id */ 1109 if (argc != 3 && argc != 5) 1110 syntax(argv); 1111 1112 id = atoi(argv[2]); 1113 if (argc == 5 && !strcmp(argv[3], "token")) 1114 token = strtoul(argv[4], NULL, 10); 1115 1116 nest_start = off; 1117 nest = (void *)(data + off); 1118 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR; 1119 nest->rta_len = RTA_LENGTH(0); 1120 off += NLMSG_ALIGN(nest->rta_len); 1121 1122 /* build a dummy addr with only the ID set */ 1123 rta = (void *)(data + off); 1124 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID; 1125 rta->rta_len = RTA_LENGTH(1); 1126 memcpy(RTA_DATA(rta), &id, 1); 1127 off += NLMSG_ALIGN(rta->rta_len); 1128 nest->rta_len = off - nest_start; 1129 1130 /* token */ 1131 if (token) { 1132 rta = (void *)(data + off); 1133 rta->rta_type = MPTCP_PM_ATTR_TOKEN; 1134 rta->rta_len = RTA_LENGTH(4); 1135 memcpy(RTA_DATA(rta), &token, 4); 1136 off += NLMSG_ALIGN(rta->rta_len); 1137 } 1138 1139 print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data))); 1140 return 0; 1141 } 1142 1143 int dump_addrs(int fd, int pm_family, int argc, char *argv[]) 1144 { 1145 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 1146 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1147 1024]; 1148 pid_t pid = getpid(); 1149 struct nlmsghdr *nh; 1150 u_int32_t token = 0; 1151 struct rtattr *rta; 1152 int off = 0; 1153 1154 if (argc != 2 && argc != 4) 1155 syntax(argv); 1156 1157 if (argc == 4 && !strcmp(argv[2], "token")) 1158 token = strtoul(argv[3], NULL, 10); 1159 1160 memset(data, 0, sizeof(data)); 1161 nh = (void *)data; 1162 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR, 1163 MPTCP_PM_VER); 1164 nh->nlmsg_flags |= NLM_F_DUMP; 1165 nh->nlmsg_seq = 1; 1166 nh->nlmsg_pid = pid; 1167 nh->nlmsg_len = off; 1168 1169 /* token */ 1170 if (token) { 1171 rta = (void *)(data + off); 1172 rta->rta_type = MPTCP_PM_ATTR_TOKEN; 1173 rta->rta_len = RTA_LENGTH(4); 1174 memcpy(RTA_DATA(rta), &token, 4); 1175 off += NLMSG_ALIGN(rta->rta_len); 1176 } 1177 1178 print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data))); 1179 return 0; 1180 } 1181 1182 int flush_addrs(int fd, int pm_family, int argc, char *argv[]) 1183 { 1184 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 1185 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1186 1024]; 1187 struct nlmsghdr *nh; 1188 int off = 0; 1189 1190 memset(data, 0, sizeof(data)); 1191 nh = (void *)data; 1192 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_FLUSH_ADDRS, 1193 MPTCP_PM_VER); 1194 1195 do_nl_req(fd, nh, off, 0); 1196 return 0; 1197 } 1198 1199 static void print_limits(struct nlmsghdr *nh, int pm_family, int total_len) 1200 { 1201 struct rtattr *attrs; 1202 uint32_t max; 1203 1204 for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) { 1205 int len = nh->nlmsg_len; 1206 1207 if (nh->nlmsg_type == NLMSG_DONE) 1208 break; 1209 if (nh->nlmsg_type == NLMSG_ERROR) 1210 nl_error(nh); 1211 if (nh->nlmsg_type != pm_family) 1212 continue; 1213 1214 len -= NLMSG_LENGTH(GENL_HDRLEN); 1215 attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) + 1216 GENL_HDRLEN); 1217 while (RTA_OK(attrs, len)) { 1218 int type = attrs->rta_type; 1219 1220 if (type != MPTCP_PM_ATTR_RCV_ADD_ADDRS && 1221 type != MPTCP_PM_ATTR_SUBFLOWS) 1222 goto next; 1223 1224 memcpy(&max, RTA_DATA(attrs), 4); 1225 printf("%s %u\n", type == MPTCP_PM_ATTR_SUBFLOWS ? 1226 "subflows" : "accept", max); 1227 1228 next: 1229 attrs = RTA_NEXT(attrs, len); 1230 } 1231 } 1232 } 1233 1234 int get_set_limits(int fd, int pm_family, int argc, char *argv[]) 1235 { 1236 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 1237 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1238 1024]; 1239 uint32_t rcv_addr = 0, subflows = 0; 1240 int cmd, len = sizeof(data); 1241 struct nlmsghdr *nh; 1242 int off = 0; 1243 1244 /* limit */ 1245 if (argc == 4) { 1246 rcv_addr = atoi(argv[2]); 1247 subflows = atoi(argv[3]); 1248 cmd = MPTCP_PM_CMD_SET_LIMITS; 1249 } else { 1250 cmd = MPTCP_PM_CMD_GET_LIMITS; 1251 } 1252 1253 memset(data, 0, sizeof(data)); 1254 nh = (void *)data; 1255 off = init_genl_req(data, pm_family, cmd, MPTCP_PM_VER); 1256 1257 /* limit */ 1258 if (cmd == MPTCP_PM_CMD_SET_LIMITS) { 1259 struct rtattr *rta = (void *)(data + off); 1260 1261 rta->rta_type = MPTCP_PM_ATTR_RCV_ADD_ADDRS; 1262 rta->rta_len = RTA_LENGTH(4); 1263 memcpy(RTA_DATA(rta), &rcv_addr, 4); 1264 off += NLMSG_ALIGN(rta->rta_len); 1265 1266 rta = (void *)(data + off); 1267 rta->rta_type = MPTCP_PM_ATTR_SUBFLOWS; 1268 rta->rta_len = RTA_LENGTH(4); 1269 memcpy(RTA_DATA(rta), &subflows, 4); 1270 off += NLMSG_ALIGN(rta->rta_len); 1271 1272 /* do not expect a reply */ 1273 len = 0; 1274 } 1275 1276 len = do_nl_req(fd, nh, off, len); 1277 if (cmd == MPTCP_PM_CMD_GET_LIMITS) 1278 print_limits(nh, pm_family, len); 1279 return 0; 1280 } 1281 1282 int add_listener(int argc, char *argv[]) 1283 { 1284 struct sockaddr_storage addr; 1285 struct sockaddr_in6 *a6; 1286 struct sockaddr_in *a4; 1287 u_int16_t family = AF_UNSPEC; 1288 int enable = 1; 1289 int sock; 1290 int err; 1291 1292 if (argc < 4) 1293 syntax(argv); 1294 1295 memset(&addr, 0, sizeof(struct sockaddr_storage)); 1296 a4 = (struct sockaddr_in *)&addr; 1297 a6 = (struct sockaddr_in6 *)&addr; 1298 1299 if (inet_pton(AF_INET, argv[2], &a4->sin_addr)) { 1300 family = AF_INET; 1301 a4->sin_family = family; 1302 a4->sin_port = htons(atoi(argv[3])); 1303 } else if (inet_pton(AF_INET6, argv[2], &a6->sin6_addr)) { 1304 family = AF_INET6; 1305 a6->sin6_family = family; 1306 a6->sin6_port = htons(atoi(argv[3])); 1307 } else 1308 error(1, errno, "can't parse ip %s", argv[2]); 1309 1310 sock = socket(family, SOCK_STREAM, IPPROTO_MPTCP); 1311 if (sock < 0) 1312 error(1, errno, "can't create listener sock\n"); 1313 1314 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) { 1315 close(sock); 1316 error(1, errno, "can't set SO_REUSEADDR on listener sock\n"); 1317 } 1318 1319 err = bind(sock, (struct sockaddr *)&addr, 1320 ((family == AF_INET) ? sizeof(struct sockaddr_in) : 1321 sizeof(struct sockaddr_in6))); 1322 1323 if (err == 0 && listen(sock, 30) == 0) 1324 pause(); 1325 1326 close(sock); 1327 return 0; 1328 } 1329 1330 int set_flags(int fd, int pm_family, int argc, char *argv[]) 1331 { 1332 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 1333 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1334 1024]; 1335 struct rtattr *rta, *nest; 1336 struct nlmsghdr *nh; 1337 u_int32_t flags = 0; 1338 u_int32_t token = 0; 1339 u_int16_t rport = 0; 1340 u_int16_t family; 1341 void *rip = NULL; 1342 int nest_start; 1343 int use_id = 0; 1344 u_int8_t id; 1345 int off = 0; 1346 int arg = 2; 1347 1348 memset(data, 0, sizeof(data)); 1349 nh = (void *)data; 1350 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS, 1351 MPTCP_PM_VER); 1352 1353 if (argc < 3) 1354 syntax(argv); 1355 1356 nest_start = off; 1357 nest = (void *)(data + off); 1358 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR; 1359 nest->rta_len = RTA_LENGTH(0); 1360 off += NLMSG_ALIGN(nest->rta_len); 1361 1362 if (!strcmp(argv[arg], "id")) { 1363 if (++arg >= argc) 1364 error(1, 0, " missing id value"); 1365 1366 use_id = 1; 1367 id = atoi(argv[arg]); 1368 rta = (void *)(data + off); 1369 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID; 1370 rta->rta_len = RTA_LENGTH(1); 1371 memcpy(RTA_DATA(rta), &id, 1); 1372 off += NLMSG_ALIGN(rta->rta_len); 1373 } else { 1374 /* addr data */ 1375 rta = (void *)(data + off); 1376 if (inet_pton(AF_INET, argv[arg], RTA_DATA(rta))) { 1377 family = AF_INET; 1378 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4; 1379 rta->rta_len = RTA_LENGTH(4); 1380 } else if (inet_pton(AF_INET6, argv[arg], RTA_DATA(rta))) { 1381 family = AF_INET6; 1382 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6; 1383 rta->rta_len = RTA_LENGTH(16); 1384 } else { 1385 error(1, errno, "can't parse ip %s", argv[arg]); 1386 } 1387 off += NLMSG_ALIGN(rta->rta_len); 1388 1389 /* family */ 1390 rta = (void *)(data + off); 1391 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY; 1392 rta->rta_len = RTA_LENGTH(2); 1393 memcpy(RTA_DATA(rta), &family, 2); 1394 off += NLMSG_ALIGN(rta->rta_len); 1395 } 1396 1397 if (++arg >= argc) 1398 error(1, 0, " missing flags keyword"); 1399 1400 for (; arg < argc; arg++) { 1401 if (!strcmp(argv[arg], "token")) { 1402 if (++arg >= argc) 1403 error(1, 0, " missing token value"); 1404 1405 /* token */ 1406 token = strtoul(argv[arg], NULL, 10); 1407 } else if (!strcmp(argv[arg], "flags")) { 1408 char *tok, *str; 1409 1410 /* flags */ 1411 if (++arg >= argc) 1412 error(1, 0, " missing flags value"); 1413 1414 for (str = argv[arg]; (tok = strtok(str, ",")); 1415 str = NULL) { 1416 if (!strcmp(tok, "backup")) 1417 flags |= MPTCP_PM_ADDR_FLAG_BACKUP; 1418 else if (!strcmp(tok, "fullmesh")) 1419 flags |= MPTCP_PM_ADDR_FLAG_FULLMESH; 1420 else if (strcmp(tok, "nobackup") && 1421 strcmp(tok, "nofullmesh")) 1422 error(1, errno, 1423 "unknown flag %s", argv[arg]); 1424 } 1425 1426 rta = (void *)(data + off); 1427 rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS; 1428 rta->rta_len = RTA_LENGTH(4); 1429 memcpy(RTA_DATA(rta), &flags, 4); 1430 off += NLMSG_ALIGN(rta->rta_len); 1431 } else if (!strcmp(argv[arg], "port")) { 1432 u_int16_t port; 1433 1434 if (use_id) 1435 error(1, 0, " port can't be used with id"); 1436 1437 if (++arg >= argc) 1438 error(1, 0, " missing port value"); 1439 1440 port = atoi(argv[arg]); 1441 rta = (void *)(data + off); 1442 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT; 1443 rta->rta_len = RTA_LENGTH(2); 1444 memcpy(RTA_DATA(rta), &port, 2); 1445 off += NLMSG_ALIGN(rta->rta_len); 1446 } else if (!strcmp(argv[arg], "rport")) { 1447 if (++arg >= argc) 1448 error(1, 0, " missing remote port"); 1449 1450 rport = atoi(argv[arg]); 1451 } else if (!strcmp(argv[arg], "rip")) { 1452 if (++arg >= argc) 1453 error(1, 0, " missing remote ip"); 1454 1455 rip = argv[arg]; 1456 } else { 1457 error(1, 0, "unknown keyword %s", argv[arg]); 1458 } 1459 } 1460 nest->rta_len = off - nest_start; 1461 1462 /* token */ 1463 if (token) { 1464 rta = (void *)(data + off); 1465 rta->rta_type = MPTCP_PM_ATTR_TOKEN; 1466 rta->rta_len = RTA_LENGTH(4); 1467 memcpy(RTA_DATA(rta), &token, 4); 1468 off += NLMSG_ALIGN(rta->rta_len); 1469 } 1470 1471 /* remote addr/port */ 1472 if (rip) { 1473 nest_start = off; 1474 nest = (void *)(data + off); 1475 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR_REMOTE; 1476 nest->rta_len = RTA_LENGTH(0); 1477 off += NLMSG_ALIGN(nest->rta_len); 1478 1479 /* addr data */ 1480 rta = (void *)(data + off); 1481 if (inet_pton(AF_INET, rip, RTA_DATA(rta))) { 1482 family = AF_INET; 1483 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4; 1484 rta->rta_len = RTA_LENGTH(4); 1485 } else if (inet_pton(AF_INET6, rip, RTA_DATA(rta))) { 1486 family = AF_INET6; 1487 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6; 1488 rta->rta_len = RTA_LENGTH(16); 1489 } else { 1490 error(1, errno, "can't parse ip %s", (char *)rip); 1491 } 1492 off += NLMSG_ALIGN(rta->rta_len); 1493 1494 /* family */ 1495 rta = (void *)(data + off); 1496 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY; 1497 rta->rta_len = RTA_LENGTH(2); 1498 memcpy(RTA_DATA(rta), &family, 2); 1499 off += NLMSG_ALIGN(rta->rta_len); 1500 1501 if (rport) { 1502 rta = (void *)(data + off); 1503 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT; 1504 rta->rta_len = RTA_LENGTH(2); 1505 memcpy(RTA_DATA(rta), &rport, 2); 1506 off += NLMSG_ALIGN(rta->rta_len); 1507 } 1508 1509 nest->rta_len = off - nest_start; 1510 } 1511 1512 do_nl_req(fd, nh, off, 0); 1513 return 0; 1514 } 1515 1516 int main(int argc, char *argv[]) 1517 { 1518 int events_mcast_grp; 1519 int pm_family; 1520 int fd; 1521 1522 if (argc < 2) 1523 syntax(argv); 1524 1525 fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); 1526 if (fd == -1) 1527 error(1, errno, "socket netlink"); 1528 1529 resolve_mptcp_pm_netlink(fd, &pm_family, &events_mcast_grp); 1530 1531 if (!strcmp(argv[1], "add")) 1532 return add_addr(fd, pm_family, argc, argv); 1533 else if (!strcmp(argv[1], "ann")) 1534 return announce_addr(fd, pm_family, argc, argv); 1535 else if (!strcmp(argv[1], "rem")) 1536 return remove_addr(fd, pm_family, argc, argv); 1537 else if (!strcmp(argv[1], "csf")) 1538 return csf(fd, pm_family, argc, argv); 1539 else if (!strcmp(argv[1], "dsf")) 1540 return dsf(fd, pm_family, argc, argv); 1541 else if (!strcmp(argv[1], "del")) 1542 return del_addr(fd, pm_family, argc, argv); 1543 else if (!strcmp(argv[1], "flush")) 1544 return flush_addrs(fd, pm_family, argc, argv); 1545 else if (!strcmp(argv[1], "get")) 1546 return get_addr(fd, pm_family, argc, argv); 1547 else if (!strcmp(argv[1], "dump")) 1548 return dump_addrs(fd, pm_family, argc, argv); 1549 else if (!strcmp(argv[1], "limits")) 1550 return get_set_limits(fd, pm_family, argc, argv); 1551 else if (!strcmp(argv[1], "set")) 1552 return set_flags(fd, pm_family, argc, argv); 1553 else if (!strcmp(argv[1], "events")) 1554 return capture_events(fd, events_mcast_grp); 1555 else if (!strcmp(argv[1], "listen")) 1556 return add_listener(argc, argv); 1557 1558 fprintf(stderr, "unknown sub-command: %s", argv[1]); 1559 syntax(argv); 1560 return 0; 1561 } 1562