1 // SPDX-License-Identifier: GPL-2.0
11 #include <sys/socket.h>
12 #include <sys/types.h>
14 #include <arpa/inet.h>
17 #include <linux/rtnetlink.h>
18 #include <linux/genetlink.h>
20 #include "linux/mptcp.h"
23 #define MPTCP_PM_NAME "mptcp_pm"
25 #ifndef MPTCP_PM_EVENTS
26 #define MPTCP_PM_EVENTS "mptcp_pm_events"
29 #define IPPROTO_MPTCP 262
32 static void syntax(char *argv[])
34 fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]);
35 fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n");
36 fprintf(stderr, "\tann <local-ip> id <local-id> token <token> [port <local-port>] [dev <name>]\n");
37 fprintf(stderr, "\trem id <local-id> token <token>\n");
38 fprintf(stderr, "\tcsf lip <local-ip> lid <local-id> rip <remote-ip> rport <remote-port> token <token>\n");
39 fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n");
40 fprintf(stderr, "\tdel <id> [<ip>]\n");
41 fprintf(stderr, "\tget <id>\n");
42 fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>] [token <token>] [rip <ip>] [rport <port>]\n");
43 fprintf(stderr, "\tflush\n");
44 fprintf(stderr, "\tdump\n");
45 fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
46 fprintf(stderr, "\tevents\n");
47 fprintf(stderr, "\tlisten <local-ip> <local-port>\n");
51 static int init_genl_req(char *data, int family, int cmd, int version)
53 struct nlmsghdr *nh = (void *)data;
54 struct genlmsghdr *gh;
57 nh->nlmsg_type = family;
58 nh->nlmsg_flags = NLM_F_REQUEST;
59 nh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
60 off += NLMSG_ALIGN(sizeof(*nh));
62 gh = (void *)(data + off);
64 gh->version = version;
65 off += NLMSG_ALIGN(sizeof(*gh));
69 static void nl_error(struct nlmsghdr *nh)
71 struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh);
72 int len = nh->nlmsg_len - sizeof(*nh);
75 if (len < sizeof(struct nlmsgerr))
76 error(1, 0, "netlink error message truncated %d min %ld", len,
77 sizeof(struct nlmsgerr));
80 /* check messages from kernel */
81 struct rtattr *attrs = (struct rtattr *)NLMSG_DATA(nh);
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",
92 attrs = RTA_NEXT(attrs, len);
95 fprintf(stderr, "netlink error %d", err->error);
99 static int capture_events(int fd, int event_group)
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;
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_EVENTS " mcast group");
118 res_len = NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
119 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024;
121 ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
124 error(1, ret, "error in select() on NL socket");
126 res_len = recv(fd, buffer, res_len, 0);
128 error(1, res_len, "error on recv() from NL socket");
130 nh = (struct nlmsghdr *)buffer;
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");
136 ghdr = (struct genlmsghdr *)NLMSG_DATA(nh);
141 fprintf(stderr, "type:%d", ghdr->cmd);
143 msg_len = nh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
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));
158 fprintf(stderr, ",saddr4:%u.%u.%u.%u", saddr4 >> 24,
159 (saddr4 >> 16) & 0xFF, (saddr4 >> 8) & 0xFF,
161 } else if (attrs->rta_type == MPTCP_ATTR_SADDR6) {
162 char buf[INET6_ADDRSTRLEN];
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));
170 fprintf(stderr, ",daddr4:%u.%u.%u.%u", daddr4 >> 24,
171 (daddr4 >> 16) & 0xFF, (daddr4 >> 8) & 0xFF,
173 } else if (attrs->rta_type == MPTCP_ATTR_DADDR6) {
174 char buf[INET6_ADDRSTRLEN];
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));
192 attrs = RTA_NEXT(attrs, msg_len);
195 fprintf(stderr, "\n");
201 /* do a netlink command and, if max > 0, fetch the reply */
202 static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
204 struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
211 ret = sendto(fd, data, len, 0, (void *)&nladdr, sizeof(nladdr));
213 error(1, errno, "send netlink: %uB != %uB\n", ret, len);
217 addr_len = sizeof(nladdr);
218 rem = ret = recvfrom(fd, data, max, 0, (void *)&nladdr, &addr_len);
220 error(1, errno, "recv netlink: %uB\n", ret);
222 /* Beware: the NLMSG_NEXT macro updates the 'rem' argument */
223 for (; NLMSG_OK(nh, rem); nh = NLMSG_NEXT(nh, rem)) {
224 if (nh->nlmsg_type == NLMSG_ERROR) {
230 error(1, 0, "bailing out due to netlink error[s]");
234 static int genl_parse_getfamily(struct nlmsghdr *nlh, int *pm_family,
235 int *events_mcast_grp)
237 struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
238 int len = nlh->nlmsg_len;
239 struct rtattr *attrs;
247 if (nlh->nlmsg_type != GENL_ID_CTRL)
248 error(1, errno, "Not a controller message, len=%d type=0x%x\n",
249 nlh->nlmsg_len, nlh->nlmsg_type);
251 len -= NLMSG_LENGTH(GENL_HDRLEN);
254 error(1, errno, "wrong controller message len %d\n", len);
256 if (ghdr->cmd != CTRL_CMD_NEWFAMILY)
257 error(1, errno, "Unknown controller command %d\n", ghdr->cmd);
259 attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
263 while (RTA_OK(attrs, len)) {
264 if (attrs->rta_type == CTRL_ATTR_FAMILY_ID) {
265 *pm_family = *(__u16 *)RTA_DATA(attrs);
267 } else if (attrs->rta_type == CTRL_ATTR_MCAST_GROUPS) {
268 grps = RTA_DATA(attrs);
269 grps_len = RTA_PAYLOAD(attrs);
271 while (RTA_OK(grps, grps_len)) {
272 grp = RTA_DATA(grps);
273 grp_len = RTA_PAYLOAD(grps);
276 while (RTA_OK(grp, grp_len)) {
277 if (grp->rta_type == CTRL_ATTR_MCAST_GRP_ID)
278 *events_mcast_grp = *(__u32 *)RTA_DATA(grp);
279 else if (grp->rta_type == CTRL_ATTR_MCAST_GRP_NAME &&
280 !strcmp(RTA_DATA(grp), MPTCP_PM_EVENTS))
283 grp = RTA_NEXT(grp, grp_len);
289 grps = RTA_NEXT(grps, grps_len);
293 if (got_family && got_events_grp)
296 attrs = RTA_NEXT(attrs, len);
299 error(1, errno, "can't find CTRL_ATTR_FAMILY_ID attr");
303 static int resolve_mptcp_pm_netlink(int fd, int *pm_family, int *events_mcast_grp)
305 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
306 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
313 memset(data, 0, sizeof(data));
315 off = init_genl_req(data, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 0);
317 rta = (void *)(data + off);
318 namelen = strlen(MPTCP_PM_NAME) + 1;
319 rta->rta_type = CTRL_ATTR_FAMILY_NAME;
320 rta->rta_len = RTA_LENGTH(namelen);
321 memcpy(RTA_DATA(rta), MPTCP_PM_NAME, namelen);
322 off += NLMSG_ALIGN(rta->rta_len);
324 do_nl_req(fd, nh, off, sizeof(data));
325 return genl_parse_getfamily((void *)data, pm_family, events_mcast_grp);
328 int dsf(int fd, int pm_family, int argc, char *argv[])
330 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
331 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
333 struct rtattr *rta, *addr;
334 u_int16_t family, port;
341 const char *params[5];
343 memset(params, 0, 5 * sizeof(const char *));
345 memset(data, 0, sizeof(data));
347 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_DESTROY,
353 /* Params recorded in this order:
354 * <local-ip>, <local-port>, <remote-ip>, <remote-port>, <token>
356 for (arg = 2; arg < argc; arg++) {
357 if (!strcmp(argv[arg], "lip")) {
359 error(1, 0, " missing local IP");
361 params[0] = argv[arg];
362 } else if (!strcmp(argv[arg], "lport")) {
364 error(1, 0, " missing local port");
366 params[1] = argv[arg];
367 } else if (!strcmp(argv[arg], "rip")) {
369 error(1, 0, " missing remote IP");
371 params[2] = argv[arg];
372 } else if (!strcmp(argv[arg], "rport")) {
374 error(1, 0, " missing remote port");
376 params[3] = argv[arg];
377 } else if (!strcmp(argv[arg], "token")) {
379 error(1, 0, " missing token");
381 params[4] = argv[arg];
383 error(1, 0, "unknown keyword %s", argv[arg]);
386 for (arg = 0; arg < 4; arg = arg + 2) {
389 addr = (void *)(data + off);
390 addr->rta_type = NLA_F_NESTED |
391 ((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
392 addr->rta_len = RTA_LENGTH(0);
393 off += NLMSG_ALIGN(addr->rta_len);
396 rta = (void *)(data + off);
397 if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
399 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
400 rta->rta_len = RTA_LENGTH(4);
401 } else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
403 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
404 rta->rta_len = RTA_LENGTH(16);
406 error(1, errno, "can't parse ip %s", params[arg]);
407 off += NLMSG_ALIGN(rta->rta_len);
410 rta = (void *)(data + off);
411 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
412 rta->rta_len = RTA_LENGTH(2);
413 memcpy(RTA_DATA(rta), &family, 2);
414 off += NLMSG_ALIGN(rta->rta_len);
417 port = atoi(params[arg + 1]);
418 rta = (void *)(data + off);
419 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
420 rta->rta_len = RTA_LENGTH(2);
421 memcpy(RTA_DATA(rta), &port, 2);
422 off += NLMSG_ALIGN(rta->rta_len);
424 addr->rta_len = off - addr_start;
428 token = strtoul(params[4], NULL, 10);
429 rta = (void *)(data + off);
430 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
431 rta->rta_len = RTA_LENGTH(4);
432 memcpy(RTA_DATA(rta), &token, 4);
433 off += NLMSG_ALIGN(rta->rta_len);
435 do_nl_req(fd, nh, off, 0);
440 int csf(int fd, int pm_family, int argc, char *argv[])
442 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
443 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
445 const char *params[5];
457 memset(params, 0, 5 * sizeof(const char *));
459 memset(data, 0, sizeof(data));
461 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_CREATE,
467 /* Params recorded in this order:
468 * <local-ip>, <local-id>, <remote-ip>, <remote-port>, <token>
470 for (arg = 2; arg < argc; arg++) {
471 if (!strcmp(argv[arg], "lip")) {
473 error(1, 0, " missing local IP");
475 params[0] = argv[arg];
476 } else if (!strcmp(argv[arg], "lid")) {
478 error(1, 0, " missing local id");
480 params[1] = argv[arg];
481 } else if (!strcmp(argv[arg], "rip")) {
483 error(1, 0, " missing remote ip");
485 params[2] = argv[arg];
486 } else if (!strcmp(argv[arg], "rport")) {
488 error(1, 0, " missing remote port");
490 params[3] = argv[arg];
491 } else if (!strcmp(argv[arg], "token")) {
493 error(1, 0, " missing token");
495 params[4] = argv[arg];
497 error(1, 0, "unknown param %s", argv[arg]);
500 for (arg = 0; arg < 4; arg = arg + 2) {
503 addr = (void *)(data + off);
504 addr->rta_type = NLA_F_NESTED |
505 ((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
506 addr->rta_len = RTA_LENGTH(0);
507 off += NLMSG_ALIGN(addr->rta_len);
510 rta = (void *)(data + off);
511 if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
513 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
514 rta->rta_len = RTA_LENGTH(4);
515 } else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
517 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
518 rta->rta_len = RTA_LENGTH(16);
520 error(1, errno, "can't parse ip %s", params[arg]);
521 off += NLMSG_ALIGN(rta->rta_len);
524 rta = (void *)(data + off);
525 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
526 rta->rta_len = RTA_LENGTH(2);
527 memcpy(RTA_DATA(rta), &family, 2);
528 off += NLMSG_ALIGN(rta->rta_len);
532 port = atoi(params[arg + 1]);
533 rta = (void *)(data + off);
534 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
535 rta->rta_len = RTA_LENGTH(2);
536 memcpy(RTA_DATA(rta), &port, 2);
537 off += NLMSG_ALIGN(rta->rta_len);
542 id = atoi(params[arg + 1]);
543 rta = (void *)(data + off);
544 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
545 rta->rta_len = RTA_LENGTH(1);
546 memcpy(RTA_DATA(rta), &id, 1);
547 off += NLMSG_ALIGN(rta->rta_len);
550 addr->rta_len = off - addr_start;
554 token = strtoul(params[4], NULL, 10);
555 rta = (void *)(data + off);
556 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
557 rta->rta_len = RTA_LENGTH(4);
558 memcpy(RTA_DATA(rta), &token, 4);
559 off += NLMSG_ALIGN(rta->rta_len);
561 do_nl_req(fd, nh, off, 0);
566 int remove_addr(int fd, int pm_family, int argc, char *argv[])
568 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
569 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
578 memset(data, 0, sizeof(data));
580 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_REMOVE,
586 for (arg = 2; arg < argc; arg++) {
587 if (!strcmp(argv[arg], "id")) {
589 error(1, 0, " missing id value");
591 id = atoi(argv[arg]);
592 rta = (void *)(data + off);
593 rta->rta_type = MPTCP_PM_ATTR_LOC_ID;
594 rta->rta_len = RTA_LENGTH(1);
595 memcpy(RTA_DATA(rta), &id, 1);
596 off += NLMSG_ALIGN(rta->rta_len);
597 } else if (!strcmp(argv[arg], "token")) {
599 error(1, 0, " missing token value");
601 token = strtoul(argv[arg], NULL, 10);
602 rta = (void *)(data + off);
603 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
604 rta->rta_len = RTA_LENGTH(4);
605 memcpy(RTA_DATA(rta), &token, 4);
606 off += NLMSG_ALIGN(rta->rta_len);
608 error(1, 0, "unknown keyword %s", argv[arg]);
611 do_nl_req(fd, nh, off, 0);
615 int announce_addr(int fd, int pm_family, int argc, char *argv[])
617 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
618 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
620 u_int32_t flags = MPTCP_PM_ADDR_FLAG_SIGNAL;
621 u_int32_t token = UINT_MAX;
622 struct rtattr *rta, *addr;
623 u_int32_t id = UINT_MAX;
630 memset(data, 0, sizeof(data));
632 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ANNOUNCE,
638 /* local-ip header */
640 addr = (void *)(data + off);
641 addr->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
642 addr->rta_len = RTA_LENGTH(0);
643 off += NLMSG_ALIGN(addr->rta_len);
646 /* record addr type */
647 rta = (void *)(data + off);
648 if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
650 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
651 rta->rta_len = RTA_LENGTH(4);
652 } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
654 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
655 rta->rta_len = RTA_LENGTH(16);
657 error(1, errno, "can't parse ip %s", argv[2]);
658 off += NLMSG_ALIGN(rta->rta_len);
661 rta = (void *)(data + off);
662 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
663 rta->rta_len = RTA_LENGTH(2);
664 memcpy(RTA_DATA(rta), &family, 2);
665 off += NLMSG_ALIGN(rta->rta_len);
667 for (arg = 3; arg < argc; arg++) {
668 if (!strcmp(argv[arg], "id")) {
671 error(1, 0, " missing id value");
673 id = atoi(argv[arg]);
674 rta = (void *)(data + off);
675 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
676 rta->rta_len = RTA_LENGTH(1);
677 memcpy(RTA_DATA(rta), &id, 1);
678 off += NLMSG_ALIGN(rta->rta_len);
679 } else if (!strcmp(argv[arg], "dev")) {
680 /* for the if_index */
684 error(1, 0, " missing dev name");
686 ifindex = if_nametoindex(argv[arg]);
688 error(1, errno, "unknown device %s", argv[arg]);
690 rta = (void *)(data + off);
691 rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
692 rta->rta_len = RTA_LENGTH(4);
693 memcpy(RTA_DATA(rta), &ifindex, 4);
694 off += NLMSG_ALIGN(rta->rta_len);
695 } else if (!strcmp(argv[arg], "port")) {
696 /* local-port (optional) */
700 error(1, 0, " missing port value");
702 port = atoi(argv[arg]);
703 rta = (void *)(data + off);
704 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
705 rta->rta_len = RTA_LENGTH(2);
706 memcpy(RTA_DATA(rta), &port, 2);
707 off += NLMSG_ALIGN(rta->rta_len);
708 } else if (!strcmp(argv[arg], "token")) {
709 /* MPTCP connection token */
711 error(1, 0, " missing token value");
713 token = strtoul(argv[arg], NULL, 10);
715 error(1, 0, "unknown keyword %s", argv[arg]);
719 rta = (void *)(data + off);
720 rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
721 rta->rta_len = RTA_LENGTH(4);
722 memcpy(RTA_DATA(rta), &flags, 4);
723 off += NLMSG_ALIGN(rta->rta_len);
725 addr->rta_len = off - addr_start;
727 if (id == UINT_MAX || token == UINT_MAX)
728 error(1, 0, " missing mandatory inputs");
731 rta = (void *)(data + off);
732 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
733 rta->rta_len = RTA_LENGTH(4);
734 memcpy(RTA_DATA(rta), &token, 4);
735 off += NLMSG_ALIGN(rta->rta_len);
737 do_nl_req(fd, nh, off, 0);
742 int add_addr(int fd, int pm_family, int argc, char *argv[])
744 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
745 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
747 struct rtattr *rta, *nest;
756 memset(data, 0, sizeof(data));
758 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ADD_ADDR,
765 nest = (void *)(data + off);
766 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
767 nest->rta_len = RTA_LENGTH(0);
768 off += NLMSG_ALIGN(nest->rta_len);
771 rta = (void *)(data + off);
772 if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
774 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
775 rta->rta_len = RTA_LENGTH(4);
776 } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
778 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
779 rta->rta_len = RTA_LENGTH(16);
781 error(1, errno, "can't parse ip %s", argv[2]);
782 off += NLMSG_ALIGN(rta->rta_len);
785 rta = (void *)(data + off);
786 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
787 rta->rta_len = RTA_LENGTH(2);
788 memcpy(RTA_DATA(rta), &family, 2);
789 off += NLMSG_ALIGN(rta->rta_len);
791 for (arg = 3; arg < argc; arg++) {
792 if (!strcmp(argv[arg], "flags")) {
797 error(1, 0, " missing flags value");
799 /* do not support flag list yet */
800 for (str = argv[arg]; (tok = strtok(str, ","));
802 if (!strcmp(tok, "subflow"))
803 flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;
804 else if (!strcmp(tok, "signal"))
805 flags |= MPTCP_PM_ADDR_FLAG_SIGNAL;
806 else if (!strcmp(tok, "backup"))
807 flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
808 else if (!strcmp(tok, "fullmesh"))
809 flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
812 "unknown flag %s", argv[arg]);
815 if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
816 flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
817 error(1, errno, "error flag fullmesh");
820 rta = (void *)(data + off);
821 rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
822 rta->rta_len = RTA_LENGTH(4);
823 memcpy(RTA_DATA(rta), &flags, 4);
824 off += NLMSG_ALIGN(rta->rta_len);
825 } else if (!strcmp(argv[arg], "id")) {
827 error(1, 0, " missing id value");
829 id = atoi(argv[arg]);
830 rta = (void *)(data + off);
831 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
832 rta->rta_len = RTA_LENGTH(1);
833 memcpy(RTA_DATA(rta), &id, 1);
834 off += NLMSG_ALIGN(rta->rta_len);
835 } else if (!strcmp(argv[arg], "dev")) {
839 error(1, 0, " missing dev name");
841 ifindex = if_nametoindex(argv[arg]);
843 error(1, errno, "unknown device %s", argv[arg]);
845 rta = (void *)(data + off);
846 rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
847 rta->rta_len = RTA_LENGTH(4);
848 memcpy(RTA_DATA(rta), &ifindex, 4);
849 off += NLMSG_ALIGN(rta->rta_len);
850 } else if (!strcmp(argv[arg], "port")) {
854 error(1, 0, " missing port value");
855 if (!(flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
856 error(1, 0, " flags must be signal when using port");
858 port = atoi(argv[arg]);
859 rta = (void *)(data + off);
860 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
861 rta->rta_len = RTA_LENGTH(2);
862 memcpy(RTA_DATA(rta), &port, 2);
863 off += NLMSG_ALIGN(rta->rta_len);
865 error(1, 0, "unknown keyword %s", argv[arg]);
867 nest->rta_len = off - nest_start;
869 do_nl_req(fd, nh, off, 0);
873 int del_addr(int fd, int pm_family, int argc, char *argv[])
875 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
876 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
878 struct rtattr *rta, *nest;
885 memset(data, 0, sizeof(data));
887 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_DEL_ADDR,
890 /* the only argument is the address id (nonzero) */
891 if (argc != 3 && argc != 4)
895 /* zero id with the IP address */
896 if (!id && argc != 4)
900 nest = (void *)(data + off);
901 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
902 nest->rta_len = RTA_LENGTH(0);
903 off += NLMSG_ALIGN(nest->rta_len);
905 /* build a dummy addr with only the ID set */
906 rta = (void *)(data + off);
907 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
908 rta->rta_len = RTA_LENGTH(1);
909 memcpy(RTA_DATA(rta), &id, 1);
910 off += NLMSG_ALIGN(rta->rta_len);
914 rta = (void *)(data + off);
915 if (inet_pton(AF_INET, argv[3], RTA_DATA(rta))) {
917 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
918 rta->rta_len = RTA_LENGTH(4);
919 } else if (inet_pton(AF_INET6, argv[3], RTA_DATA(rta))) {
921 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
922 rta->rta_len = RTA_LENGTH(16);
924 error(1, errno, "can't parse ip %s", argv[3]);
926 off += NLMSG_ALIGN(rta->rta_len);
929 rta = (void *)(data + off);
930 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
931 rta->rta_len = RTA_LENGTH(2);
932 memcpy(RTA_DATA(rta), &family, 2);
933 off += NLMSG_ALIGN(rta->rta_len);
935 nest->rta_len = off - nest_start;
937 do_nl_req(fd, nh, off, 0);
941 static void print_addr(struct rtattr *attrs, int len)
949 while (RTA_OK(attrs, len)) {
950 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FAMILY)
951 memcpy(&family, RTA_DATA(attrs), 2);
952 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_PORT)
953 memcpy(&port, RTA_DATA(attrs), 2);
954 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR4) {
955 if (family != AF_INET)
956 error(1, errno, "wrong IP (v4) for family %d",
958 inet_ntop(AF_INET, RTA_DATA(attrs), str, sizeof(str));
963 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR6) {
964 if (family != AF_INET6)
965 error(1, errno, "wrong IP (v6) for family %d",
967 inet_ntop(AF_INET6, RTA_DATA(attrs), str, sizeof(str));
972 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ID) {
973 memcpy(&id, RTA_DATA(attrs), 1);
974 printf("id %d ", id);
976 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FLAGS) {
977 memcpy(&flags, RTA_DATA(attrs), 4);
980 if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
982 flags &= ~MPTCP_PM_ADDR_FLAG_SIGNAL;
987 if (flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
989 flags &= ~MPTCP_PM_ADDR_FLAG_SUBFLOW;
994 if (flags & MPTCP_PM_ADDR_FLAG_BACKUP) {
996 flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
1001 if (flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
1003 flags &= ~MPTCP_PM_ADDR_FLAG_FULLMESH;
1008 if (flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
1010 flags &= ~MPTCP_PM_ADDR_FLAG_IMPLICIT;
1015 /* bump unknown flags, if any */
1017 printf("0x%x", flags);
1020 if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_IF_IDX) {
1021 char name[IF_NAMESIZE], *ret;
1024 memcpy(&ifindex, RTA_DATA(attrs), 4);
1025 ret = if_indextoname(ifindex, name);
1027 printf("dev %s ", ret);
1029 printf("dev unknown/%d", ifindex);
1032 attrs = RTA_NEXT(attrs, len);
1037 static void print_addrs(struct nlmsghdr *nh, int pm_family, int total_len)
1039 struct rtattr *attrs;
1041 for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
1042 int len = nh->nlmsg_len;
1044 if (nh->nlmsg_type == NLMSG_DONE)
1046 if (nh->nlmsg_type == NLMSG_ERROR)
1048 if (nh->nlmsg_type != pm_family)
1051 len -= NLMSG_LENGTH(GENL_HDRLEN);
1052 attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
1054 while (RTA_OK(attrs, len)) {
1055 if (attrs->rta_type ==
1056 (MPTCP_PM_ATTR_ADDR | NLA_F_NESTED))
1057 print_addr((void *)RTA_DATA(attrs),
1059 attrs = RTA_NEXT(attrs, len);
1064 int get_addr(int fd, int pm_family, int argc, char *argv[])
1066 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1067 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1069 struct rtattr *rta, *nest;
1070 struct nlmsghdr *nh;
1075 memset(data, 0, sizeof(data));
1077 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
1080 /* the only argument is the address id */
1087 nest = (void *)(data + off);
1088 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
1089 nest->rta_len = RTA_LENGTH(0);
1090 off += NLMSG_ALIGN(nest->rta_len);
1092 /* build a dummy addr with only the ID set */
1093 rta = (void *)(data + off);
1094 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
1095 rta->rta_len = RTA_LENGTH(1);
1096 memcpy(RTA_DATA(rta), &id, 1);
1097 off += NLMSG_ALIGN(rta->rta_len);
1098 nest->rta_len = off - nest_start;
1100 print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
1104 int dump_addrs(int fd, int pm_family, int argc, char *argv[])
1106 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1107 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1109 pid_t pid = getpid();
1110 struct nlmsghdr *nh;
1113 memset(data, 0, sizeof(data));
1115 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
1117 nh->nlmsg_flags |= NLM_F_DUMP;
1119 nh->nlmsg_pid = pid;
1120 nh->nlmsg_len = off;
1122 print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
1126 int flush_addrs(int fd, int pm_family, int argc, char *argv[])
1128 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1129 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1131 struct nlmsghdr *nh;
1134 memset(data, 0, sizeof(data));
1136 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_FLUSH_ADDRS,
1139 do_nl_req(fd, nh, off, 0);
1143 static void print_limits(struct nlmsghdr *nh, int pm_family, int total_len)
1145 struct rtattr *attrs;
1148 for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
1149 int len = nh->nlmsg_len;
1151 if (nh->nlmsg_type == NLMSG_DONE)
1153 if (nh->nlmsg_type == NLMSG_ERROR)
1155 if (nh->nlmsg_type != pm_family)
1158 len -= NLMSG_LENGTH(GENL_HDRLEN);
1159 attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
1161 while (RTA_OK(attrs, len)) {
1162 int type = attrs->rta_type;
1164 if (type != MPTCP_PM_ATTR_RCV_ADD_ADDRS &&
1165 type != MPTCP_PM_ATTR_SUBFLOWS)
1168 memcpy(&max, RTA_DATA(attrs), 4);
1169 printf("%s %u\n", type == MPTCP_PM_ATTR_SUBFLOWS ?
1170 "subflows" : "accept", max);
1173 attrs = RTA_NEXT(attrs, len);
1178 int get_set_limits(int fd, int pm_family, int argc, char *argv[])
1180 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1181 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1183 uint32_t rcv_addr = 0, subflows = 0;
1184 int cmd, len = sizeof(data);
1185 struct nlmsghdr *nh;
1190 rcv_addr = atoi(argv[2]);
1191 subflows = atoi(argv[3]);
1192 cmd = MPTCP_PM_CMD_SET_LIMITS;
1194 cmd = MPTCP_PM_CMD_GET_LIMITS;
1197 memset(data, 0, sizeof(data));
1199 off = init_genl_req(data, pm_family, cmd, MPTCP_PM_VER);
1202 if (cmd == MPTCP_PM_CMD_SET_LIMITS) {
1203 struct rtattr *rta = (void *)(data + off);
1205 rta->rta_type = MPTCP_PM_ATTR_RCV_ADD_ADDRS;
1206 rta->rta_len = RTA_LENGTH(4);
1207 memcpy(RTA_DATA(rta), &rcv_addr, 4);
1208 off += NLMSG_ALIGN(rta->rta_len);
1210 rta = (void *)(data + off);
1211 rta->rta_type = MPTCP_PM_ATTR_SUBFLOWS;
1212 rta->rta_len = RTA_LENGTH(4);
1213 memcpy(RTA_DATA(rta), &subflows, 4);
1214 off += NLMSG_ALIGN(rta->rta_len);
1216 /* do not expect a reply */
1220 len = do_nl_req(fd, nh, off, len);
1221 if (cmd == MPTCP_PM_CMD_GET_LIMITS)
1222 print_limits(nh, pm_family, len);
1226 int add_listener(int argc, char *argv[])
1228 struct sockaddr_storage addr;
1229 struct sockaddr_in6 *a6;
1230 struct sockaddr_in *a4;
1239 memset(&addr, 0, sizeof(struct sockaddr_storage));
1240 a4 = (struct sockaddr_in *)&addr;
1241 a6 = (struct sockaddr_in6 *)&addr;
1243 if (inet_pton(AF_INET, argv[2], &a4->sin_addr)) {
1245 a4->sin_family = family;
1246 a4->sin_port = htons(atoi(argv[3]));
1247 } else if (inet_pton(AF_INET6, argv[2], &a6->sin6_addr)) {
1249 a6->sin6_family = family;
1250 a6->sin6_port = htons(atoi(argv[3]));
1252 error(1, errno, "can't parse ip %s", argv[2]);
1254 sock = socket(family, SOCK_STREAM, IPPROTO_MPTCP);
1256 error(1, errno, "can't create listener sock\n");
1258 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) {
1260 error(1, errno, "can't set SO_REUSEADDR on listener sock\n");
1263 err = bind(sock, (struct sockaddr *)&addr,
1264 ((family == AF_INET) ? sizeof(struct sockaddr_in) :
1265 sizeof(struct sockaddr_in6)));
1267 if (err == 0 && listen(sock, 30) == 0)
1274 int set_flags(int fd, int pm_family, int argc, char *argv[])
1276 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1277 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1279 struct rtattr *rta, *nest;
1280 struct nlmsghdr *nh;
1281 u_int32_t flags = 0;
1282 u_int32_t token = 0;
1283 u_int16_t rport = 0;
1292 memset(data, 0, sizeof(data));
1294 off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS,
1301 nest = (void *)(data + off);
1302 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
1303 nest->rta_len = RTA_LENGTH(0);
1304 off += NLMSG_ALIGN(nest->rta_len);
1306 if (!strcmp(argv[arg], "id")) {
1308 error(1, 0, " missing id value");
1311 id = atoi(argv[arg]);
1312 rta = (void *)(data + off);
1313 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
1314 rta->rta_len = RTA_LENGTH(1);
1315 memcpy(RTA_DATA(rta), &id, 1);
1316 off += NLMSG_ALIGN(rta->rta_len);
1319 rta = (void *)(data + off);
1320 if (inet_pton(AF_INET, argv[arg], RTA_DATA(rta))) {
1322 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
1323 rta->rta_len = RTA_LENGTH(4);
1324 } else if (inet_pton(AF_INET6, argv[arg], RTA_DATA(rta))) {
1326 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
1327 rta->rta_len = RTA_LENGTH(16);
1329 error(1, errno, "can't parse ip %s", argv[arg]);
1331 off += NLMSG_ALIGN(rta->rta_len);
1334 rta = (void *)(data + off);
1335 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
1336 rta->rta_len = RTA_LENGTH(2);
1337 memcpy(RTA_DATA(rta), &family, 2);
1338 off += NLMSG_ALIGN(rta->rta_len);
1342 error(1, 0, " missing flags keyword");
1344 for (; arg < argc; arg++) {
1345 if (!strcmp(argv[arg], "token")) {
1347 error(1, 0, " missing token value");
1350 token = strtoul(argv[arg], NULL, 10);
1351 } else if (!strcmp(argv[arg], "flags")) {
1356 error(1, 0, " missing flags value");
1358 for (str = argv[arg]; (tok = strtok(str, ","));
1360 if (!strcmp(tok, "backup"))
1361 flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
1362 else if (!strcmp(tok, "fullmesh"))
1363 flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
1364 else if (strcmp(tok, "nobackup") &&
1365 strcmp(tok, "nofullmesh"))
1367 "unknown flag %s", argv[arg]);
1370 rta = (void *)(data + off);
1371 rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
1372 rta->rta_len = RTA_LENGTH(4);
1373 memcpy(RTA_DATA(rta), &flags, 4);
1374 off += NLMSG_ALIGN(rta->rta_len);
1375 } else if (!strcmp(argv[arg], "port")) {
1379 error(1, 0, " port can't be used with id");
1382 error(1, 0, " missing port value");
1384 port = atoi(argv[arg]);
1385 rta = (void *)(data + off);
1386 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
1387 rta->rta_len = RTA_LENGTH(2);
1388 memcpy(RTA_DATA(rta), &port, 2);
1389 off += NLMSG_ALIGN(rta->rta_len);
1390 } else if (!strcmp(argv[arg], "rport")) {
1392 error(1, 0, " missing remote port");
1394 rport = atoi(argv[arg]);
1395 } else if (!strcmp(argv[arg], "rip")) {
1397 error(1, 0, " missing remote ip");
1401 error(1, 0, "unknown keyword %s", argv[arg]);
1404 nest->rta_len = off - nest_start;
1408 rta = (void *)(data + off);
1409 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
1410 rta->rta_len = RTA_LENGTH(4);
1411 memcpy(RTA_DATA(rta), &token, 4);
1412 off += NLMSG_ALIGN(rta->rta_len);
1415 /* remote addr/port */
1418 nest = (void *)(data + off);
1419 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR_REMOTE;
1420 nest->rta_len = RTA_LENGTH(0);
1421 off += NLMSG_ALIGN(nest->rta_len);
1424 rta = (void *)(data + off);
1425 if (inet_pton(AF_INET, rip, RTA_DATA(rta))) {
1427 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
1428 rta->rta_len = RTA_LENGTH(4);
1429 } else if (inet_pton(AF_INET6, rip, RTA_DATA(rta))) {
1431 rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
1432 rta->rta_len = RTA_LENGTH(16);
1434 error(1, errno, "can't parse ip %s", (char *)rip);
1436 off += NLMSG_ALIGN(rta->rta_len);
1439 rta = (void *)(data + off);
1440 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
1441 rta->rta_len = RTA_LENGTH(2);
1442 memcpy(RTA_DATA(rta), &family, 2);
1443 off += NLMSG_ALIGN(rta->rta_len);
1446 rta = (void *)(data + off);
1447 rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
1448 rta->rta_len = RTA_LENGTH(2);
1449 memcpy(RTA_DATA(rta), &rport, 2);
1450 off += NLMSG_ALIGN(rta->rta_len);
1453 nest->rta_len = off - nest_start;
1456 do_nl_req(fd, nh, off, 0);
1460 int main(int argc, char *argv[])
1462 int events_mcast_grp;
1469 fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
1471 error(1, errno, "socket netlink");
1473 resolve_mptcp_pm_netlink(fd, &pm_family, &events_mcast_grp);
1475 if (!strcmp(argv[1], "add"))
1476 return add_addr(fd, pm_family, argc, argv);
1477 else if (!strcmp(argv[1], "ann"))
1478 return announce_addr(fd, pm_family, argc, argv);
1479 else if (!strcmp(argv[1], "rem"))
1480 return remove_addr(fd, pm_family, argc, argv);
1481 else if (!strcmp(argv[1], "csf"))
1482 return csf(fd, pm_family, argc, argv);
1483 else if (!strcmp(argv[1], "dsf"))
1484 return dsf(fd, pm_family, argc, argv);
1485 else if (!strcmp(argv[1], "del"))
1486 return del_addr(fd, pm_family, argc, argv);
1487 else if (!strcmp(argv[1], "flush"))
1488 return flush_addrs(fd, pm_family, argc, argv);
1489 else if (!strcmp(argv[1], "get"))
1490 return get_addr(fd, pm_family, argc, argv);
1491 else if (!strcmp(argv[1], "dump"))
1492 return dump_addrs(fd, pm_family, argc, argv);
1493 else if (!strcmp(argv[1], "limits"))
1494 return get_set_limits(fd, pm_family, argc, argv);
1495 else if (!strcmp(argv[1], "set"))
1496 return set_flags(fd, pm_family, argc, argv);
1497 else if (!strcmp(argv[1], "events"))
1498 return capture_events(fd, events_mcast_grp);
1499 else if (!strcmp(argv[1], "listen"))
1500 return add_listener(argc, argv);
1502 fprintf(stderr, "unknown sub-command: %s", argv[1]);