Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #include <errno.h>
0004 #include <error.h>
0005 #include <stdio.h>
0006 #include <stdlib.h>
0007 #include <string.h>
0008 #include <unistd.h>
0009 #include <limits.h>
0010 
0011 #include <sys/socket.h>
0012 #include <sys/types.h>
0013 
0014 #include <arpa/inet.h>
0015 #include <net/if.h>
0016 
0017 #include <linux/rtnetlink.h>
0018 #include <linux/genetlink.h>
0019 
0020 #include "linux/mptcp.h"
0021 
0022 #ifndef MPTCP_PM_NAME
0023 #define MPTCP_PM_NAME       "mptcp_pm"
0024 #endif
0025 #ifndef MPTCP_PM_EVENTS
0026 #define MPTCP_PM_EVENTS     "mptcp_pm_events"
0027 #endif
0028 #ifndef IPPROTO_MPTCP
0029 #define IPPROTO_MPTCP 262
0030 #endif
0031 
0032 static void syntax(char *argv[])
0033 {
0034     fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]);
0035     fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n");
0036     fprintf(stderr, "\tann <local-ip> id <local-id> token <token> [port <local-port>] [dev <name>]\n");
0037     fprintf(stderr, "\trem id <local-id> token <token>\n");
0038     fprintf(stderr, "\tcsf lip <local-ip> lid <local-id> rip <remote-ip> rport <remote-port> token <token>\n");
0039     fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n");
0040     fprintf(stderr, "\tdel <id> [<ip>]\n");
0041     fprintf(stderr, "\tget <id>\n");
0042     fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>] [token <token>] [rip <ip>] [rport <port>]\n");
0043     fprintf(stderr, "\tflush\n");
0044     fprintf(stderr, "\tdump\n");
0045     fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
0046     fprintf(stderr, "\tevents\n");
0047     fprintf(stderr, "\tlisten <local-ip> <local-port>\n");
0048     exit(0);
0049 }
0050 
0051 static int init_genl_req(char *data, int family, int cmd, int version)
0052 {
0053     struct nlmsghdr *nh = (void *)data;
0054     struct genlmsghdr *gh;
0055     int off = 0;
0056 
0057     nh->nlmsg_type = family;
0058     nh->nlmsg_flags = NLM_F_REQUEST;
0059     nh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
0060     off += NLMSG_ALIGN(sizeof(*nh));
0061 
0062     gh = (void *)(data + off);
0063     gh->cmd = cmd;
0064     gh->version = version;
0065     off += NLMSG_ALIGN(sizeof(*gh));
0066     return off;
0067 }
0068 
0069 static void nl_error(struct nlmsghdr *nh)
0070 {
0071     struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh);
0072     int len = nh->nlmsg_len - sizeof(*nh);
0073     uint32_t off;
0074 
0075     if (len < sizeof(struct nlmsgerr))
0076         error(1, 0, "netlink error message truncated %d min %ld", len,
0077               sizeof(struct nlmsgerr));
0078 
0079     if (!err->error) {
0080         /* check messages from kernel */
0081         struct rtattr *attrs = (struct rtattr *)NLMSG_DATA(nh);
0082 
0083         while (RTA_OK(attrs, len)) {
0084             if (attrs->rta_type == NLMSGERR_ATTR_MSG)
0085                 fprintf(stderr, "netlink ext ack msg: %s\n",
0086                     (char *)RTA_DATA(attrs));
0087             if (attrs->rta_type == NLMSGERR_ATTR_OFFS) {
0088                 memcpy(&off, RTA_DATA(attrs), 4);
0089                 fprintf(stderr, "netlink err off %d\n",
0090                     (int)off);
0091             }
0092             attrs = RTA_NEXT(attrs, len);
0093         }
0094     } else {
0095         fprintf(stderr, "netlink error %d", err->error);
0096     }
0097 }
0098 
0099 static int capture_events(int fd, int event_group)
0100 {
0101     u_int8_t buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0102             NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024];
0103     struct genlmsghdr *ghdr;
0104     struct rtattr *attrs;
0105     struct nlmsghdr *nh;
0106     int ret = 0;
0107     int res_len;
0108     int msg_len;
0109     fd_set rfds;
0110 
0111     if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
0112                &event_group, sizeof(event_group)) < 0)
0113         error(1, errno, "could not join the " MPTCP_PM_EVENTS " mcast group");
0114 
0115     do {
0116         FD_ZERO(&rfds);
0117         FD_SET(fd, &rfds);
0118         res_len = NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0119           NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024;
0120 
0121         ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
0122 
0123         if (ret < 0)
0124             error(1, ret, "error in select() on NL socket");
0125 
0126         res_len = recv(fd, buffer, res_len, 0);
0127         if (res_len < 0)
0128             error(1, res_len, "error on recv() from NL socket");
0129 
0130         nh = (struct nlmsghdr *)buffer;
0131 
0132         for (; NLMSG_OK(nh, res_len); nh = NLMSG_NEXT(nh, res_len)) {
0133             if (nh->nlmsg_type == NLMSG_ERROR)
0134                 error(1, NLMSG_ERROR, "received invalid NL message");
0135 
0136             ghdr = (struct genlmsghdr *)NLMSG_DATA(nh);
0137 
0138             if (ghdr->cmd == 0)
0139                 continue;
0140 
0141             fprintf(stderr, "type:%d", ghdr->cmd);
0142 
0143             msg_len = nh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
0144 
0145             attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
0146             while (RTA_OK(attrs, msg_len)) {
0147                 if (attrs->rta_type == MPTCP_ATTR_TOKEN)
0148                     fprintf(stderr, ",token:%u", *(__u32 *)RTA_DATA(attrs));
0149                 else if (attrs->rta_type == MPTCP_ATTR_FAMILY)
0150                     fprintf(stderr, ",family:%u", *(__u16 *)RTA_DATA(attrs));
0151                 else if (attrs->rta_type == MPTCP_ATTR_LOC_ID)
0152                     fprintf(stderr, ",loc_id:%u", *(__u8 *)RTA_DATA(attrs));
0153                 else if (attrs->rta_type == MPTCP_ATTR_REM_ID)
0154                     fprintf(stderr, ",rem_id:%u", *(__u8 *)RTA_DATA(attrs));
0155                 else if (attrs->rta_type == MPTCP_ATTR_SADDR4) {
0156                     u_int32_t saddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
0157 
0158                     fprintf(stderr, ",saddr4:%u.%u.%u.%u", saddr4 >> 24,
0159                            (saddr4 >> 16) & 0xFF, (saddr4 >> 8) & 0xFF,
0160                            (saddr4 & 0xFF));
0161                 } else if (attrs->rta_type == MPTCP_ATTR_SADDR6) {
0162                     char buf[INET6_ADDRSTRLEN];
0163 
0164                     if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
0165                               sizeof(buf)) != NULL)
0166                         fprintf(stderr, ",saddr6:%s", buf);
0167                 } else if (attrs->rta_type == MPTCP_ATTR_DADDR4) {
0168                     u_int32_t daddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
0169 
0170                     fprintf(stderr, ",daddr4:%u.%u.%u.%u", daddr4 >> 24,
0171                            (daddr4 >> 16) & 0xFF, (daddr4 >> 8) & 0xFF,
0172                            (daddr4 & 0xFF));
0173                 } else if (attrs->rta_type == MPTCP_ATTR_DADDR6) {
0174                     char buf[INET6_ADDRSTRLEN];
0175 
0176                     if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
0177                               sizeof(buf)) != NULL)
0178                         fprintf(stderr, ",daddr6:%s", buf);
0179                 } else if (attrs->rta_type == MPTCP_ATTR_SPORT)
0180                     fprintf(stderr, ",sport:%u",
0181                         ntohs(*(__u16 *)RTA_DATA(attrs)));
0182                 else if (attrs->rta_type == MPTCP_ATTR_DPORT)
0183                     fprintf(stderr, ",dport:%u",
0184                         ntohs(*(__u16 *)RTA_DATA(attrs)));
0185                 else if (attrs->rta_type == MPTCP_ATTR_BACKUP)
0186                     fprintf(stderr, ",backup:%u", *(__u8 *)RTA_DATA(attrs));
0187                 else if (attrs->rta_type == MPTCP_ATTR_ERROR)
0188                     fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs));
0189                 else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE)
0190                     fprintf(stderr, ",server_side:%u", *(__u8 *)RTA_DATA(attrs));
0191 
0192                 attrs = RTA_NEXT(attrs, msg_len);
0193             }
0194         }
0195         fprintf(stderr, "\n");
0196     } while (1);
0197 
0198     return 0;
0199 }
0200 
0201 /* do a netlink command and, if max > 0, fetch the reply  */
0202 static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
0203 {
0204     struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
0205     socklen_t addr_len;
0206     void *data = nh;
0207     int rem, ret;
0208     int err = 0;
0209 
0210     nh->nlmsg_len = len;
0211     ret = sendto(fd, data, len, 0, (void *)&nladdr, sizeof(nladdr));
0212     if (ret != len)
0213         error(1, errno, "send netlink: %uB != %uB\n", ret, len);
0214     if (max == 0)
0215         return 0;
0216 
0217     addr_len = sizeof(nladdr);
0218     rem = ret = recvfrom(fd, data, max, 0, (void *)&nladdr, &addr_len);
0219     if (ret < 0)
0220         error(1, errno, "recv netlink: %uB\n", ret);
0221 
0222     /* Beware: the NLMSG_NEXT macro updates the 'rem' argument */
0223     for (; NLMSG_OK(nh, rem); nh = NLMSG_NEXT(nh, rem)) {
0224         if (nh->nlmsg_type == NLMSG_ERROR) {
0225             nl_error(nh);
0226             err = 1;
0227         }
0228     }
0229     if (err)
0230         error(1, 0, "bailing out due to netlink error[s]");
0231     return ret;
0232 }
0233 
0234 static int genl_parse_getfamily(struct nlmsghdr *nlh, int *pm_family,
0235                 int *events_mcast_grp)
0236 {
0237     struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
0238     int len = nlh->nlmsg_len;
0239     struct rtattr *attrs;
0240     struct rtattr *grps;
0241     struct rtattr *grp;
0242     int got_events_grp;
0243     int got_family;
0244     int grps_len;
0245     int grp_len;
0246 
0247     if (nlh->nlmsg_type != GENL_ID_CTRL)
0248         error(1, errno, "Not a controller message, len=%d type=0x%x\n",
0249               nlh->nlmsg_len, nlh->nlmsg_type);
0250 
0251     len -= NLMSG_LENGTH(GENL_HDRLEN);
0252 
0253     if (len < 0)
0254         error(1, errno, "wrong controller message len %d\n", len);
0255 
0256     if (ghdr->cmd != CTRL_CMD_NEWFAMILY)
0257         error(1, errno, "Unknown controller command %d\n", ghdr->cmd);
0258 
0259     attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
0260     got_family = 0;
0261     got_events_grp = 0;
0262 
0263     while (RTA_OK(attrs, len)) {
0264         if (attrs->rta_type == CTRL_ATTR_FAMILY_ID) {
0265             *pm_family = *(__u16 *)RTA_DATA(attrs);
0266             got_family = 1;
0267         } else if (attrs->rta_type == CTRL_ATTR_MCAST_GROUPS) {
0268             grps = RTA_DATA(attrs);
0269             grps_len = RTA_PAYLOAD(attrs);
0270 
0271             while (RTA_OK(grps, grps_len)) {
0272                 grp = RTA_DATA(grps);
0273                 grp_len = RTA_PAYLOAD(grps);
0274                 got_events_grp = 0;
0275 
0276                 while (RTA_OK(grp, grp_len)) {
0277                     if (grp->rta_type == CTRL_ATTR_MCAST_GRP_ID)
0278                         *events_mcast_grp = *(__u32 *)RTA_DATA(grp);
0279                     else if (grp->rta_type == CTRL_ATTR_MCAST_GRP_NAME &&
0280                          !strcmp(RTA_DATA(grp), MPTCP_PM_EVENTS))
0281                         got_events_grp = 1;
0282 
0283                     grp = RTA_NEXT(grp, grp_len);
0284                 }
0285 
0286                 if (got_events_grp)
0287                     break;
0288 
0289                 grps = RTA_NEXT(grps, grps_len);
0290             }
0291         }
0292 
0293         if (got_family && got_events_grp)
0294             return 0;
0295 
0296         attrs = RTA_NEXT(attrs, len);
0297     }
0298 
0299     error(1, errno, "can't find CTRL_ATTR_FAMILY_ID attr");
0300     return -1;
0301 }
0302 
0303 static int resolve_mptcp_pm_netlink(int fd, int *pm_family, int *events_mcast_grp)
0304 {
0305     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0306           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0307           1024];
0308     struct nlmsghdr *nh;
0309     struct rtattr *rta;
0310     int namelen;
0311     int off = 0;
0312 
0313     memset(data, 0, sizeof(data));
0314     nh = (void *)data;
0315     off = init_genl_req(data, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 0);
0316 
0317     rta = (void *)(data + off);
0318     namelen = strlen(MPTCP_PM_NAME) + 1;
0319     rta->rta_type = CTRL_ATTR_FAMILY_NAME;
0320     rta->rta_len = RTA_LENGTH(namelen);
0321     memcpy(RTA_DATA(rta), MPTCP_PM_NAME, namelen);
0322     off += NLMSG_ALIGN(rta->rta_len);
0323 
0324     do_nl_req(fd, nh, off, sizeof(data));
0325     return genl_parse_getfamily((void *)data, pm_family, events_mcast_grp);
0326 }
0327 
0328 int dsf(int fd, int pm_family, int argc, char *argv[])
0329 {
0330     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0331           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0332           1024];
0333     struct rtattr *rta, *addr;
0334     u_int16_t family, port;
0335     struct nlmsghdr *nh;
0336     u_int32_t token;
0337     int addr_start;
0338     int off = 0;
0339     int arg;
0340 
0341     const char *params[5];
0342 
0343     memset(params, 0, 5 * sizeof(const char *));
0344 
0345     memset(data, 0, sizeof(data));
0346     nh = (void *)data;
0347     off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_DESTROY,
0348                 MPTCP_PM_VER);
0349 
0350     if (argc < 12)
0351         syntax(argv);
0352 
0353     /* Params recorded in this order:
0354      * <local-ip>, <local-port>, <remote-ip>, <remote-port>, <token>
0355      */
0356     for (arg = 2; arg < argc; arg++) {
0357         if (!strcmp(argv[arg], "lip")) {
0358             if (++arg >= argc)
0359                 error(1, 0, " missing local IP");
0360 
0361             params[0] = argv[arg];
0362         } else if (!strcmp(argv[arg], "lport")) {
0363             if (++arg >= argc)
0364                 error(1, 0, " missing local port");
0365 
0366             params[1] = argv[arg];
0367         } else if (!strcmp(argv[arg], "rip")) {
0368             if (++arg >= argc)
0369                 error(1, 0, " missing remote IP");
0370 
0371             params[2] = argv[arg];
0372         } else if (!strcmp(argv[arg], "rport")) {
0373             if (++arg >= argc)
0374                 error(1, 0, " missing remote port");
0375 
0376             params[3] = argv[arg];
0377         } else if (!strcmp(argv[arg], "token")) {
0378             if (++arg >= argc)
0379                 error(1, 0, " missing token");
0380 
0381             params[4] = argv[arg];
0382         } else
0383             error(1, 0, "unknown keyword %s", argv[arg]);
0384     }
0385 
0386     for (arg = 0; arg < 4; arg = arg + 2) {
0387         /*  addr header */
0388         addr_start = off;
0389         addr = (void *)(data + off);
0390         addr->rta_type = NLA_F_NESTED |
0391             ((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
0392         addr->rta_len = RTA_LENGTH(0);
0393         off += NLMSG_ALIGN(addr->rta_len);
0394 
0395         /*  addr data */
0396         rta = (void *)(data + off);
0397         if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
0398             family = AF_INET;
0399             rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
0400             rta->rta_len = RTA_LENGTH(4);
0401         } else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
0402             family = AF_INET6;
0403             rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
0404             rta->rta_len = RTA_LENGTH(16);
0405         } else
0406             error(1, errno, "can't parse ip %s", params[arg]);
0407         off += NLMSG_ALIGN(rta->rta_len);
0408 
0409         /* family */
0410         rta = (void *)(data + off);
0411         rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
0412         rta->rta_len = RTA_LENGTH(2);
0413         memcpy(RTA_DATA(rta), &family, 2);
0414         off += NLMSG_ALIGN(rta->rta_len);
0415 
0416         /*  port */
0417         port = atoi(params[arg + 1]);
0418         rta = (void *)(data + off);
0419         rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
0420         rta->rta_len = RTA_LENGTH(2);
0421         memcpy(RTA_DATA(rta), &port, 2);
0422         off += NLMSG_ALIGN(rta->rta_len);
0423 
0424         addr->rta_len = off - addr_start;
0425     }
0426 
0427     /* token */
0428     token = atoi(params[4]);
0429     rta = (void *)(data + off);
0430     rta->rta_type = MPTCP_PM_ATTR_TOKEN;
0431     rta->rta_len = RTA_LENGTH(4);
0432     memcpy(RTA_DATA(rta), &token, 4);
0433     off += NLMSG_ALIGN(rta->rta_len);
0434 
0435     do_nl_req(fd, nh, off, 0);
0436 
0437     return 0;
0438 }
0439 
0440 int csf(int fd, int pm_family, int argc, char *argv[])
0441 {
0442     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0443           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0444           1024];
0445     const char *params[5];
0446     struct nlmsghdr *nh;
0447     struct rtattr *addr;
0448     struct rtattr *rta;
0449     u_int16_t family;
0450     u_int32_t token;
0451     u_int16_t port;
0452     int addr_start;
0453     u_int8_t id;
0454     int off = 0;
0455     int arg;
0456 
0457     memset(params, 0, 5 * sizeof(const char *));
0458 
0459     memset(data, 0, sizeof(data));
0460     nh = (void *)data;
0461     off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_CREATE,
0462                 MPTCP_PM_VER);
0463 
0464     if (argc < 12)
0465         syntax(argv);
0466 
0467     /* Params recorded in this order:
0468      * <local-ip>, <local-id>, <remote-ip>, <remote-port>, <token>
0469      */
0470     for (arg = 2; arg < argc; arg++) {
0471         if (!strcmp(argv[arg], "lip")) {
0472             if (++arg >= argc)
0473                 error(1, 0, " missing local IP");
0474 
0475             params[0] = argv[arg];
0476         } else if (!strcmp(argv[arg], "lid")) {
0477             if (++arg >= argc)
0478                 error(1, 0, " missing local id");
0479 
0480             params[1] = argv[arg];
0481         } else if (!strcmp(argv[arg], "rip")) {
0482             if (++arg >= argc)
0483                 error(1, 0, " missing remote ip");
0484 
0485             params[2] = argv[arg];
0486         } else if (!strcmp(argv[arg], "rport")) {
0487             if (++arg >= argc)
0488                 error(1, 0, " missing remote port");
0489 
0490             params[3] = argv[arg];
0491         } else if (!strcmp(argv[arg], "token")) {
0492             if (++arg >= argc)
0493                 error(1, 0, " missing token");
0494 
0495             params[4] = argv[arg];
0496         } else
0497             error(1, 0, "unknown param %s", argv[arg]);
0498     }
0499 
0500     for (arg = 0; arg < 4; arg = arg + 2) {
0501         /*  addr header */
0502         addr_start = off;
0503         addr = (void *)(data + off);
0504         addr->rta_type = NLA_F_NESTED |
0505             ((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
0506         addr->rta_len = RTA_LENGTH(0);
0507         off += NLMSG_ALIGN(addr->rta_len);
0508 
0509         /*  addr data */
0510         rta = (void *)(data + off);
0511         if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
0512             family = AF_INET;
0513             rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
0514             rta->rta_len = RTA_LENGTH(4);
0515         } else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
0516             family = AF_INET6;
0517             rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
0518             rta->rta_len = RTA_LENGTH(16);
0519         } else
0520             error(1, errno, "can't parse ip %s", params[arg]);
0521         off += NLMSG_ALIGN(rta->rta_len);
0522 
0523         /* family */
0524         rta = (void *)(data + off);
0525         rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
0526         rta->rta_len = RTA_LENGTH(2);
0527         memcpy(RTA_DATA(rta), &family, 2);
0528         off += NLMSG_ALIGN(rta->rta_len);
0529 
0530         if (arg == 2) {
0531             /*  port */
0532             port = atoi(params[arg + 1]);
0533             rta = (void *)(data + off);
0534             rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
0535             rta->rta_len = RTA_LENGTH(2);
0536             memcpy(RTA_DATA(rta), &port, 2);
0537             off += NLMSG_ALIGN(rta->rta_len);
0538         }
0539 
0540         if (arg == 0) {
0541             /* id */
0542             id = atoi(params[arg + 1]);
0543             rta = (void *)(data + off);
0544             rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
0545             rta->rta_len = RTA_LENGTH(1);
0546             memcpy(RTA_DATA(rta), &id, 1);
0547             off += NLMSG_ALIGN(rta->rta_len);
0548         }
0549 
0550         addr->rta_len = off - addr_start;
0551     }
0552 
0553     /* token */
0554     token = atoi(params[4]);
0555     rta = (void *)(data + off);
0556     rta->rta_type = MPTCP_PM_ATTR_TOKEN;
0557     rta->rta_len = RTA_LENGTH(4);
0558     memcpy(RTA_DATA(rta), &token, 4);
0559     off += NLMSG_ALIGN(rta->rta_len);
0560 
0561     do_nl_req(fd, nh, off, 0);
0562 
0563     return 0;
0564 }
0565 
0566 int remove_addr(int fd, int pm_family, int argc, char *argv[])
0567 {
0568     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0569           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0570           1024];
0571     struct nlmsghdr *nh;
0572     struct rtattr *rta;
0573     u_int32_t token;
0574     u_int8_t id;
0575     int off = 0;
0576     int arg;
0577 
0578     memset(data, 0, sizeof(data));
0579     nh = (void *)data;
0580     off = init_genl_req(data, pm_family, MPTCP_PM_CMD_REMOVE,
0581                 MPTCP_PM_VER);
0582 
0583     if (argc < 6)
0584         syntax(argv);
0585 
0586     for (arg = 2; arg < argc; arg++) {
0587         if (!strcmp(argv[arg], "id")) {
0588             if (++arg >= argc)
0589                 error(1, 0, " missing id value");
0590 
0591             id = atoi(argv[arg]);
0592             rta = (void *)(data + off);
0593             rta->rta_type = MPTCP_PM_ATTR_LOC_ID;
0594             rta->rta_len = RTA_LENGTH(1);
0595             memcpy(RTA_DATA(rta), &id, 1);
0596             off += NLMSG_ALIGN(rta->rta_len);
0597         } else if (!strcmp(argv[arg], "token")) {
0598             if (++arg >= argc)
0599                 error(1, 0, " missing token value");
0600 
0601             token = atoi(argv[arg]);
0602             rta = (void *)(data + off);
0603             rta->rta_type = MPTCP_PM_ATTR_TOKEN;
0604             rta->rta_len = RTA_LENGTH(4);
0605             memcpy(RTA_DATA(rta), &token, 4);
0606             off += NLMSG_ALIGN(rta->rta_len);
0607         } else
0608             error(1, 0, "unknown keyword %s", argv[arg]);
0609     }
0610 
0611     do_nl_req(fd, nh, off, 0);
0612     return 0;
0613 }
0614 
0615 int announce_addr(int fd, int pm_family, int argc, char *argv[])
0616 {
0617     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0618           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0619           1024];
0620     u_int32_t flags = MPTCP_PM_ADDR_FLAG_SIGNAL;
0621     u_int32_t token = UINT_MAX;
0622     struct rtattr *rta, *addr;
0623     u_int32_t id = UINT_MAX;
0624     struct nlmsghdr *nh;
0625     u_int16_t family;
0626     int addr_start;
0627     int off = 0;
0628     int arg;
0629 
0630     memset(data, 0, sizeof(data));
0631     nh = (void *)data;
0632     off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ANNOUNCE,
0633                 MPTCP_PM_VER);
0634 
0635     if (argc < 7)
0636         syntax(argv);
0637 
0638     /* local-ip header */
0639     addr_start = off;
0640     addr = (void *)(data + off);
0641     addr->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
0642     addr->rta_len = RTA_LENGTH(0);
0643     off += NLMSG_ALIGN(addr->rta_len);
0644 
0645     /* local-ip data */
0646     /* record addr type */
0647     rta = (void *)(data + off);
0648     if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
0649         family = AF_INET;
0650         rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
0651         rta->rta_len = RTA_LENGTH(4);
0652     } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
0653         family = AF_INET6;
0654         rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
0655         rta->rta_len = RTA_LENGTH(16);
0656     } else
0657         error(1, errno, "can't parse ip %s", argv[2]);
0658     off += NLMSG_ALIGN(rta->rta_len);
0659 
0660     /* addr family */
0661     rta = (void *)(data + off);
0662     rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
0663     rta->rta_len = RTA_LENGTH(2);
0664     memcpy(RTA_DATA(rta), &family, 2);
0665     off += NLMSG_ALIGN(rta->rta_len);
0666 
0667     for (arg = 3; arg < argc; arg++) {
0668         if (!strcmp(argv[arg], "id")) {
0669             /* local-id */
0670             if (++arg >= argc)
0671                 error(1, 0, " missing id value");
0672 
0673             id = atoi(argv[arg]);
0674             rta = (void *)(data + off);
0675             rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
0676             rta->rta_len = RTA_LENGTH(1);
0677             memcpy(RTA_DATA(rta), &id, 1);
0678             off += NLMSG_ALIGN(rta->rta_len);
0679         } else if (!strcmp(argv[arg], "dev")) {
0680             /* for the if_index */
0681             int32_t ifindex;
0682 
0683             if (++arg >= argc)
0684                 error(1, 0, " missing dev name");
0685 
0686             ifindex = if_nametoindex(argv[arg]);
0687             if (!ifindex)
0688                 error(1, errno, "unknown device %s", argv[arg]);
0689 
0690             rta = (void *)(data + off);
0691             rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
0692             rta->rta_len = RTA_LENGTH(4);
0693             memcpy(RTA_DATA(rta), &ifindex, 4);
0694             off += NLMSG_ALIGN(rta->rta_len);
0695         } else if (!strcmp(argv[arg], "port")) {
0696             /* local-port (optional) */
0697             u_int16_t port;
0698 
0699             if (++arg >= argc)
0700                 error(1, 0, " missing port value");
0701 
0702             port = atoi(argv[arg]);
0703             rta = (void *)(data + off);
0704             rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
0705             rta->rta_len = RTA_LENGTH(2);
0706             memcpy(RTA_DATA(rta), &port, 2);
0707             off += NLMSG_ALIGN(rta->rta_len);
0708         } else if (!strcmp(argv[arg], "token")) {
0709             /* MPTCP connection token */
0710             if (++arg >= argc)
0711                 error(1, 0, " missing token value");
0712 
0713             token = atoi(argv[arg]);
0714         } else
0715             error(1, 0, "unknown keyword %s", argv[arg]);
0716     }
0717 
0718     /* addr flags */
0719     rta = (void *)(data + off);
0720     rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
0721     rta->rta_len = RTA_LENGTH(4);
0722     memcpy(RTA_DATA(rta), &flags, 4);
0723     off += NLMSG_ALIGN(rta->rta_len);
0724 
0725     addr->rta_len = off - addr_start;
0726 
0727     if (id == UINT_MAX || token == UINT_MAX)
0728         error(1, 0, " missing mandatory inputs");
0729 
0730     /* token */
0731     rta = (void *)(data + off);
0732     rta->rta_type = MPTCP_PM_ATTR_TOKEN;
0733     rta->rta_len = RTA_LENGTH(4);
0734     memcpy(RTA_DATA(rta), &token, 4);
0735     off += NLMSG_ALIGN(rta->rta_len);
0736 
0737     do_nl_req(fd, nh, off, 0);
0738 
0739     return 0;
0740 }
0741 
0742 int add_addr(int fd, int pm_family, int argc, char *argv[])
0743 {
0744     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0745           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0746           1024];
0747     struct rtattr *rta, *nest;
0748     struct nlmsghdr *nh;
0749     u_int32_t flags = 0;
0750     u_int16_t family;
0751     int nest_start;
0752     u_int8_t id;
0753     int off = 0;
0754     int arg;
0755 
0756     memset(data, 0, sizeof(data));
0757     nh = (void *)data;
0758     off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ADD_ADDR,
0759                 MPTCP_PM_VER);
0760 
0761     if (argc < 3)
0762         syntax(argv);
0763 
0764     nest_start = off;
0765     nest = (void *)(data + off);
0766     nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
0767     nest->rta_len = RTA_LENGTH(0);
0768     off += NLMSG_ALIGN(nest->rta_len);
0769 
0770     /* addr data */
0771     rta = (void *)(data + off);
0772     if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
0773         family = AF_INET;
0774         rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
0775         rta->rta_len = RTA_LENGTH(4);
0776     } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
0777         family = AF_INET6;
0778         rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
0779         rta->rta_len = RTA_LENGTH(16);
0780     } else
0781         error(1, errno, "can't parse ip %s", argv[2]);
0782     off += NLMSG_ALIGN(rta->rta_len);
0783 
0784     /* family */
0785     rta = (void *)(data + off);
0786     rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
0787     rta->rta_len = RTA_LENGTH(2);
0788     memcpy(RTA_DATA(rta), &family, 2);
0789     off += NLMSG_ALIGN(rta->rta_len);
0790 
0791     for (arg = 3; arg < argc; arg++) {
0792         if (!strcmp(argv[arg], "flags")) {
0793             char *tok, *str;
0794 
0795             /* flags */
0796             if (++arg >= argc)
0797                 error(1, 0, " missing flags value");
0798 
0799             /* do not support flag list yet */
0800             for (str = argv[arg]; (tok = strtok(str, ","));
0801                  str = NULL) {
0802                 if (!strcmp(tok, "subflow"))
0803                     flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;
0804                 else if (!strcmp(tok, "signal"))
0805                     flags |= MPTCP_PM_ADDR_FLAG_SIGNAL;
0806                 else if (!strcmp(tok, "backup"))
0807                     flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
0808                 else if (!strcmp(tok, "fullmesh"))
0809                     flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
0810                 else
0811                     error(1, errno,
0812                           "unknown flag %s", argv[arg]);
0813             }
0814 
0815             if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
0816                 flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
0817                 error(1, errno, "error flag fullmesh");
0818             }
0819 
0820             rta = (void *)(data + off);
0821             rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
0822             rta->rta_len = RTA_LENGTH(4);
0823             memcpy(RTA_DATA(rta), &flags, 4);
0824             off += NLMSG_ALIGN(rta->rta_len);
0825         } else if (!strcmp(argv[arg], "id")) {
0826             if (++arg >= argc)
0827                 error(1, 0, " missing id value");
0828 
0829             id = atoi(argv[arg]);
0830             rta = (void *)(data + off);
0831             rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
0832             rta->rta_len = RTA_LENGTH(1);
0833             memcpy(RTA_DATA(rta), &id, 1);
0834             off += NLMSG_ALIGN(rta->rta_len);
0835         } else if (!strcmp(argv[arg], "dev")) {
0836             int32_t ifindex;
0837 
0838             if (++arg >= argc)
0839                 error(1, 0, " missing dev name");
0840 
0841             ifindex = if_nametoindex(argv[arg]);
0842             if (!ifindex)
0843                 error(1, errno, "unknown device %s", argv[arg]);
0844 
0845             rta = (void *)(data + off);
0846             rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
0847             rta->rta_len = RTA_LENGTH(4);
0848             memcpy(RTA_DATA(rta), &ifindex, 4);
0849             off += NLMSG_ALIGN(rta->rta_len);
0850         } else if (!strcmp(argv[arg], "port")) {
0851             u_int16_t port;
0852 
0853             if (++arg >= argc)
0854                 error(1, 0, " missing port value");
0855             if (!(flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
0856                 error(1, 0, " flags must be signal when using port");
0857 
0858             port = atoi(argv[arg]);
0859             rta = (void *)(data + off);
0860             rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
0861             rta->rta_len = RTA_LENGTH(2);
0862             memcpy(RTA_DATA(rta), &port, 2);
0863             off += NLMSG_ALIGN(rta->rta_len);
0864         } else
0865             error(1, 0, "unknown keyword %s", argv[arg]);
0866     }
0867     nest->rta_len = off - nest_start;
0868 
0869     do_nl_req(fd, nh, off, 0);
0870     return 0;
0871 }
0872 
0873 int del_addr(int fd, int pm_family, int argc, char *argv[])
0874 {
0875     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
0876           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
0877           1024];
0878     struct rtattr *rta, *nest;
0879     struct nlmsghdr *nh;
0880     u_int16_t family;
0881     int nest_start;
0882     u_int8_t id;
0883     int off = 0;
0884 
0885     memset(data, 0, sizeof(data));
0886     nh = (void *)data;
0887     off = init_genl_req(data, pm_family, MPTCP_PM_CMD_DEL_ADDR,
0888                 MPTCP_PM_VER);
0889 
0890     /* the only argument is the address id (nonzero) */
0891     if (argc != 3 && argc != 4)
0892         syntax(argv);
0893 
0894     id = atoi(argv[2]);
0895     /* zero id with the IP address */
0896     if (!id && argc != 4)
0897         syntax(argv);
0898 
0899     nest_start = off;
0900     nest = (void *)(data + off);
0901     nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
0902     nest->rta_len =  RTA_LENGTH(0);
0903     off += NLMSG_ALIGN(nest->rta_len);
0904 
0905     /* build a dummy addr with only the ID set */
0906     rta = (void *)(data + off);
0907     rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
0908     rta->rta_len = RTA_LENGTH(1);
0909     memcpy(RTA_DATA(rta), &id, 1);
0910     off += NLMSG_ALIGN(rta->rta_len);
0911 
0912     if (!id) {
0913         /* addr data */
0914         rta = (void *)(data + off);
0915         if (inet_pton(AF_INET, argv[3], RTA_DATA(rta))) {
0916             family = AF_INET;
0917             rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
0918             rta->rta_len = RTA_LENGTH(4);
0919         } else if (inet_pton(AF_INET6, argv[3], RTA_DATA(rta))) {
0920             family = AF_INET6;
0921             rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
0922             rta->rta_len = RTA_LENGTH(16);
0923         } else {
0924             error(1, errno, "can't parse ip %s", argv[3]);
0925         }
0926         off += NLMSG_ALIGN(rta->rta_len);
0927 
0928         /* family */
0929         rta = (void *)(data + off);
0930         rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
0931         rta->rta_len = RTA_LENGTH(2);
0932         memcpy(RTA_DATA(rta), &family, 2);
0933         off += NLMSG_ALIGN(rta->rta_len);
0934     }
0935     nest->rta_len = off - nest_start;
0936 
0937     do_nl_req(fd, nh, off, 0);
0938     return 0;
0939 }
0940 
0941 static void print_addr(struct rtattr *attrs, int len)
0942 {
0943     uint16_t family = 0;
0944     uint16_t port = 0;
0945     char str[1024];
0946     uint32_t flags;
0947     uint8_t id;
0948 
0949     while (RTA_OK(attrs, len)) {
0950         if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FAMILY)
0951             memcpy(&family, RTA_DATA(attrs), 2);
0952         if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_PORT)
0953             memcpy(&port, RTA_DATA(attrs), 2);
0954         if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR4) {
0955             if (family != AF_INET)
0956                 error(1, errno, "wrong IP (v4) for family %d",
0957                       family);
0958             inet_ntop(AF_INET, RTA_DATA(attrs), str, sizeof(str));
0959             printf("%s", str);
0960             if (port)
0961                 printf(" %d", port);
0962         }
0963         if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR6) {
0964             if (family != AF_INET6)
0965                 error(1, errno, "wrong IP (v6) for family %d",
0966                       family);
0967             inet_ntop(AF_INET6, RTA_DATA(attrs), str, sizeof(str));
0968             printf("%s", str);
0969             if (port)
0970                 printf(" %d", port);
0971         }
0972         if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ID) {
0973             memcpy(&id, RTA_DATA(attrs), 1);
0974             printf("id %d ", id);
0975         }
0976         if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FLAGS) {
0977             memcpy(&flags, RTA_DATA(attrs), 4);
0978 
0979             printf("flags ");
0980             if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
0981                 printf("signal");
0982                 flags &= ~MPTCP_PM_ADDR_FLAG_SIGNAL;
0983                 if (flags)
0984                     printf(",");
0985             }
0986 
0987             if (flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
0988                 printf("subflow");
0989                 flags &= ~MPTCP_PM_ADDR_FLAG_SUBFLOW;
0990                 if (flags)
0991                     printf(",");
0992             }
0993 
0994             if (flags & MPTCP_PM_ADDR_FLAG_BACKUP) {
0995                 printf("backup");
0996                 flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
0997                 if (flags)
0998                     printf(",");
0999             }
1000 
1001             if (flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
1002                 printf("fullmesh");
1003                 flags &= ~MPTCP_PM_ADDR_FLAG_FULLMESH;
1004                 if (flags)
1005                     printf(",");
1006             }
1007 
1008             if (flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
1009                 printf("implicit");
1010                 flags &= ~MPTCP_PM_ADDR_FLAG_IMPLICIT;
1011                 if (flags)
1012                     printf(",");
1013             }
1014 
1015             /* bump unknown flags, if any */
1016             if (flags)
1017                 printf("0x%x", flags);
1018             printf(" ");
1019         }
1020         if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_IF_IDX) {
1021             char name[IF_NAMESIZE], *ret;
1022             int32_t ifindex;
1023 
1024             memcpy(&ifindex, RTA_DATA(attrs), 4);
1025             ret = if_indextoname(ifindex, name);
1026             if (ret)
1027                 printf("dev %s ", ret);
1028             else
1029                 printf("dev unknown/%d", ifindex);
1030         }
1031 
1032         attrs = RTA_NEXT(attrs, len);
1033     }
1034     printf("\n");
1035 }
1036 
1037 static void print_addrs(struct nlmsghdr *nh, int pm_family, int total_len)
1038 {
1039     struct rtattr *attrs;
1040 
1041     for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
1042         int len = nh->nlmsg_len;
1043 
1044         if (nh->nlmsg_type == NLMSG_DONE)
1045             break;
1046         if (nh->nlmsg_type == NLMSG_ERROR)
1047             nl_error(nh);
1048         if (nh->nlmsg_type != pm_family)
1049             continue;
1050 
1051         len -= NLMSG_LENGTH(GENL_HDRLEN);
1052         attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
1053                        GENL_HDRLEN);
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),
1058                        attrs->rta_len);
1059             attrs = RTA_NEXT(attrs, len);
1060         }
1061     }
1062 }
1063 
1064 int get_addr(int fd, int pm_family, int argc, char *argv[])
1065 {
1066     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1067           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1068           1024];
1069     struct rtattr *rta, *nest;
1070     struct nlmsghdr *nh;
1071     int nest_start;
1072     u_int8_t id;
1073     int off = 0;
1074 
1075     memset(data, 0, sizeof(data));
1076     nh = (void *)data;
1077     off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
1078                 MPTCP_PM_VER);
1079 
1080     /* the only argument is the address id */
1081     if (argc != 3)
1082         syntax(argv);
1083 
1084     id = atoi(argv[2]);
1085 
1086     nest_start = off;
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);
1091 
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;
1099 
1100     print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
1101     return 0;
1102 }
1103 
1104 int dump_addrs(int fd, int pm_family, int argc, char *argv[])
1105 {
1106     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1107           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1108           1024];
1109     pid_t pid = getpid();
1110     struct nlmsghdr *nh;
1111     int off = 0;
1112 
1113     memset(data, 0, sizeof(data));
1114     nh = (void *)data;
1115     off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
1116                 MPTCP_PM_VER);
1117     nh->nlmsg_flags |= NLM_F_DUMP;
1118     nh->nlmsg_seq = 1;
1119     nh->nlmsg_pid = pid;
1120     nh->nlmsg_len = off;
1121 
1122     print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
1123     return 0;
1124 }
1125 
1126 int flush_addrs(int fd, int pm_family, int argc, char *argv[])
1127 {
1128     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1129           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1130           1024];
1131     struct nlmsghdr *nh;
1132     int off = 0;
1133 
1134     memset(data, 0, sizeof(data));
1135     nh = (void *)data;
1136     off = init_genl_req(data, pm_family, MPTCP_PM_CMD_FLUSH_ADDRS,
1137                 MPTCP_PM_VER);
1138 
1139     do_nl_req(fd, nh, off, 0);
1140     return 0;
1141 }
1142 
1143 static void print_limits(struct nlmsghdr *nh, int pm_family, int total_len)
1144 {
1145     struct rtattr *attrs;
1146     uint32_t max;
1147 
1148     for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
1149         int len = nh->nlmsg_len;
1150 
1151         if (nh->nlmsg_type == NLMSG_DONE)
1152             break;
1153         if (nh->nlmsg_type == NLMSG_ERROR)
1154             nl_error(nh);
1155         if (nh->nlmsg_type != pm_family)
1156             continue;
1157 
1158         len -= NLMSG_LENGTH(GENL_HDRLEN);
1159         attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
1160                        GENL_HDRLEN);
1161         while (RTA_OK(attrs, len)) {
1162             int type = attrs->rta_type;
1163 
1164             if (type != MPTCP_PM_ATTR_RCV_ADD_ADDRS &&
1165                 type != MPTCP_PM_ATTR_SUBFLOWS)
1166                 goto next;
1167 
1168             memcpy(&max, RTA_DATA(attrs), 4);
1169             printf("%s %u\n", type == MPTCP_PM_ATTR_SUBFLOWS ?
1170                       "subflows" : "accept", max);
1171 
1172 next:
1173             attrs = RTA_NEXT(attrs, len);
1174         }
1175     }
1176 }
1177 
1178 int get_set_limits(int fd, int pm_family, int argc, char *argv[])
1179 {
1180     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1181           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1182           1024];
1183     uint32_t rcv_addr = 0, subflows = 0;
1184     int cmd, len = sizeof(data);
1185     struct nlmsghdr *nh;
1186     int off = 0;
1187 
1188     /* limit */
1189     if (argc == 4) {
1190         rcv_addr = atoi(argv[2]);
1191         subflows = atoi(argv[3]);
1192         cmd = MPTCP_PM_CMD_SET_LIMITS;
1193     } else {
1194         cmd = MPTCP_PM_CMD_GET_LIMITS;
1195     }
1196 
1197     memset(data, 0, sizeof(data));
1198     nh = (void *)data;
1199     off = init_genl_req(data, pm_family, cmd, MPTCP_PM_VER);
1200 
1201     /* limit */
1202     if (cmd == MPTCP_PM_CMD_SET_LIMITS) {
1203         struct rtattr *rta = (void *)(data + off);
1204 
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);
1209 
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);
1215 
1216         /* do not expect a reply */
1217         len = 0;
1218     }
1219 
1220     len = do_nl_req(fd, nh, off, len);
1221     if (cmd == MPTCP_PM_CMD_GET_LIMITS)
1222         print_limits(nh, pm_family, len);
1223     return 0;
1224 }
1225 
1226 int add_listener(int argc, char *argv[])
1227 {
1228     struct sockaddr_storage addr;
1229     struct sockaddr_in6 *a6;
1230     struct sockaddr_in *a4;
1231     u_int16_t family;
1232     int enable = 1;
1233     int sock;
1234     int err;
1235 
1236     if (argc < 4)
1237         syntax(argv);
1238 
1239     memset(&addr, 0, sizeof(struct sockaddr_storage));
1240     a4 = (struct sockaddr_in *)&addr;
1241     a6 = (struct sockaddr_in6 *)&addr;
1242 
1243     if (inet_pton(AF_INET, argv[2], &a4->sin_addr)) {
1244         family = AF_INET;
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)) {
1248         family = AF_INET6;
1249         a6->sin6_family = family;
1250         a6->sin6_port = htons(atoi(argv[3]));
1251     } else
1252         error(1, errno, "can't parse ip %s", argv[2]);
1253 
1254     sock = socket(family, SOCK_STREAM, IPPROTO_MPTCP);
1255     if (sock < 0)
1256         error(1, errno, "can't create listener sock\n");
1257 
1258     if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) {
1259         close(sock);
1260         error(1, errno, "can't set SO_REUSEADDR on listener sock\n");
1261     }
1262 
1263     err = bind(sock, (struct sockaddr *)&addr,
1264            ((family == AF_INET) ? sizeof(struct sockaddr_in) :
1265             sizeof(struct sockaddr_in6)));
1266 
1267     if (err == 0 && listen(sock, 30) == 0)
1268         pause();
1269 
1270     close(sock);
1271     return 0;
1272 }
1273 
1274 int set_flags(int fd, int pm_family, int argc, char *argv[])
1275 {
1276     char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1277           NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1278           1024];
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;
1284     u_int16_t family;
1285     void *rip = NULL;
1286     int nest_start;
1287     int use_id = 0;
1288     u_int8_t id;
1289     int off = 0;
1290     int arg = 2;
1291 
1292     memset(data, 0, sizeof(data));
1293     nh = (void *)data;
1294     off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS,
1295                 MPTCP_PM_VER);
1296 
1297     if (argc < 3)
1298         syntax(argv);
1299 
1300     nest_start = off;
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);
1305 
1306     if (!strcmp(argv[arg], "id")) {
1307         if (++arg >= argc)
1308             error(1, 0, " missing id value");
1309 
1310         use_id = 1;
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);
1317     } else {
1318         /* addr data */
1319         rta = (void *)(data + off);
1320         if (inet_pton(AF_INET, argv[arg], RTA_DATA(rta))) {
1321             family = AF_INET;
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))) {
1325             family = AF_INET6;
1326             rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
1327             rta->rta_len = RTA_LENGTH(16);
1328         } else {
1329             error(1, errno, "can't parse ip %s", argv[arg]);
1330         }
1331         off += NLMSG_ALIGN(rta->rta_len);
1332 
1333         /* family */
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);
1339     }
1340 
1341     if (++arg >= argc)
1342         error(1, 0, " missing flags keyword");
1343 
1344     for (; arg < argc; arg++) {
1345         if (!strcmp(argv[arg], "token")) {
1346             if (++arg >= argc)
1347                 error(1, 0, " missing token value");
1348 
1349             /* token */
1350             token = atoi(argv[arg]);
1351         } else if (!strcmp(argv[arg], "flags")) {
1352             char *tok, *str;
1353 
1354             /* flags */
1355             if (++arg >= argc)
1356                 error(1, 0, " missing flags value");
1357 
1358             for (str = argv[arg]; (tok = strtok(str, ","));
1359                  str = NULL) {
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"))
1366                     error(1, errno,
1367                           "unknown flag %s", argv[arg]);
1368             }
1369 
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")) {
1376             u_int16_t port;
1377 
1378             if (use_id)
1379                 error(1, 0, " port can't be used with id");
1380 
1381             if (++arg >= argc)
1382                 error(1, 0, " missing port value");
1383 
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")) {
1391             if (++arg >= argc)
1392                 error(1, 0, " missing remote port");
1393 
1394             rport = atoi(argv[arg]);
1395         } else if (!strcmp(argv[arg], "rip")) {
1396             if (++arg >= argc)
1397                 error(1, 0, " missing remote ip");
1398 
1399             rip = argv[arg];
1400         } else {
1401             error(1, 0, "unknown keyword %s", argv[arg]);
1402         }
1403     }
1404     nest->rta_len = off - nest_start;
1405 
1406     /* token */
1407     if (token) {
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);
1413     }
1414 
1415     /* remote addr/port */
1416     if (rip) {
1417         nest_start = off;
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);
1422 
1423         /* addr data */
1424         rta = (void *)(data + off);
1425         if (inet_pton(AF_INET, rip, RTA_DATA(rta))) {
1426             family = AF_INET;
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))) {
1430             family = AF_INET6;
1431             rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
1432             rta->rta_len = RTA_LENGTH(16);
1433         } else {
1434             error(1, errno, "can't parse ip %s", (char *)rip);
1435         }
1436         off += NLMSG_ALIGN(rta->rta_len);
1437 
1438         /* family */
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);
1444 
1445         if (rport) {
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);
1451         }
1452 
1453         nest->rta_len = off - nest_start;
1454     }
1455 
1456     do_nl_req(fd, nh, off, 0);
1457     return 0;
1458 }
1459 
1460 int main(int argc, char *argv[])
1461 {
1462     int events_mcast_grp;
1463     int pm_family;
1464     int fd;
1465 
1466     if (argc < 2)
1467         syntax(argv);
1468 
1469     fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
1470     if (fd == -1)
1471         error(1, errno, "socket netlink");
1472 
1473     resolve_mptcp_pm_netlink(fd, &pm_family, &events_mcast_grp);
1474 
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);
1501 
1502     fprintf(stderr, "unknown sub-command: %s", argv[1]);
1503     syntax(argv);
1504     return 0;
1505 }