linux/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <errno.h>
   4#include <error.h>
   5#include <stdio.h>
   6#include <stdlib.h>
   7#include <string.h>
   8#include <unistd.h>
   9#include <limits.h>
  10
  11#include <sys/socket.h>
  12#include <sys/types.h>
  13
  14#include <arpa/inet.h>
  15#include <net/if.h>
  16
  17#include <linux/rtnetlink.h>
  18#include <linux/genetlink.h>
  19
  20#include "linux/mptcp.h"
  21
  22#ifndef MPTCP_PM_NAME
  23#define MPTCP_PM_NAME           "mptcp_pm"
  24#endif
  25#ifndef MPTCP_PM_EVENTS
  26#define MPTCP_PM_EVENTS         "mptcp_pm_events"
  27#endif
  28#ifndef IPPROTO_MPTCP
  29#define IPPROTO_MPTCP 262
  30#endif
  31
  32static void syntax(char *argv[])
  33{
  34        fprintf(stderr, "%s add|get|set|del|flush|dump|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");
  48        exit(0);
  49}
  50
  51static int init_genl_req(char *data, int family, int cmd, int version)
  52{
  53        struct nlmsghdr *nh = (void *)data;
  54        struct genlmsghdr *gh;
  55        int off = 0;
  56
  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));
  61
  62        gh = (void *)(data + off);
  63        gh->cmd = cmd;
  64        gh->version = version;
  65        off += NLMSG_ALIGN(sizeof(*gh));
  66        return off;
  67}
  68
  69static void nl_error(struct nlmsghdr *nh)
  70{
  71        struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh);
  72        int len = nh->nlmsg_len - sizeof(*nh);
  73        uint32_t off;
  74
  75        if (len < sizeof(struct nlmsgerr))
  76                error(1, 0, "netlink error message truncated %d min %ld", len,
  77                      sizeof(struct nlmsgerr));
  78
  79        if (!err->error) {
  80                /* check messages from kernel */
  81                struct rtattr *attrs = (struct rtattr *)NLMSG_DATA(nh);
  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        } else {
  95                fprintf(stderr, "netlink error %d", err->error);
  96        }
  97}
  98
  99static int capture_events(int fd, int event_group)
 100{
 101        u_int8_t buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
 102                        NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024];
 103        struct genlmsghdr *ghdr;
 104        struct rtattr *attrs;
 105        struct nlmsghdr *nh;
 106        int ret = 0;
 107        int res_len;
 108        int msg_len;
 109        fd_set rfds;
 110
 111        if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
 112                       &event_group, sizeof(event_group)) < 0)
 113                error(1, errno, "could not join the " MPTCP_PM_EVENTS " mcast group");
 114
 115        do {
 116                FD_ZERO(&rfds);
 117                FD_SET(fd, &rfds);
 118                res_len = NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
 119                  NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024;
 120
 121                ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
 122
 123                if (ret < 0)
 124                        error(1, ret, "error in select() on NL socket");
 125
 126                res_len = recv(fd, buffer, res_len, 0);
 127                if (res_len < 0)
 128                        error(1, res_len, "error on recv() from NL socket");
 129
 130                nh = (struct nlmsghdr *)buffer;
 131
 132                for (; NLMSG_OK(nh, res_len); nh = NLMSG_NEXT(nh, res_len)) {
 133                        if (nh->nlmsg_type == NLMSG_ERROR)
 134                                error(1, NLMSG_ERROR, "received invalid NL message");
 135
 136                        ghdr = (struct genlmsghdr *)NLMSG_DATA(nh);
 137
 138                        if (ghdr->cmd == 0)
 139                                continue;
 140
 141                        fprintf(stderr, "type:%d", ghdr->cmd);
 142
 143                        msg_len = nh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
 144
 145                        attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
 146                        while (RTA_OK(attrs, msg_len)) {
 147                                if (attrs->rta_type == MPTCP_ATTR_TOKEN)
 148                                        fprintf(stderr, ",token:%u", *(__u32 *)RTA_DATA(attrs));
 149                                else if (attrs->rta_type == MPTCP_ATTR_FAMILY)
 150                                        fprintf(stderr, ",family:%u", *(__u16 *)RTA_DATA(attrs));
 151                                else if (attrs->rta_type == MPTCP_ATTR_LOC_ID)
 152                                        fprintf(stderr, ",loc_id:%u", *(__u8 *)RTA_DATA(attrs));
 153                                else if (attrs->rta_type == MPTCP_ATTR_REM_ID)
 154                                        fprintf(stderr, ",rem_id:%u", *(__u8 *)RTA_DATA(attrs));
 155                                else if (attrs->rta_type == MPTCP_ATTR_SADDR4) {
 156                                        u_int32_t saddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
 157
 158                                        fprintf(stderr, ",saddr4:%u.%u.%u.%u", saddr4 >> 24,
 159                                               (saddr4 >> 16) & 0xFF, (saddr4 >> 8) & 0xFF,
 160                                               (saddr4 & 0xFF));
 161                                } else if (attrs->rta_type == MPTCP_ATTR_SADDR6) {
 162                                        char buf[INET6_ADDRSTRLEN];
 163
 164                                        if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
 165                                                      sizeof(buf)) != NULL)
 166                                                fprintf(stderr, ",saddr6:%s", buf);
 167                                } else if (attrs->rta_type == MPTCP_ATTR_DADDR4) {
 168                                        u_int32_t daddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
 169
 170                                        fprintf(stderr, ",daddr4:%u.%u.%u.%u", daddr4 >> 24,
 171                                               (daddr4 >> 16) & 0xFF, (daddr4 >> 8) & 0xFF,
 172                                               (daddr4 & 0xFF));
 173                                } else if (attrs->rta_type == MPTCP_ATTR_DADDR6) {
 174                                        char buf[INET6_ADDRSTRLEN];
 175
 176                                        if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
 177                                                      sizeof(buf)) != NULL)
 178                                                fprintf(stderr, ",daddr6:%s", buf);
 179                                } else if (attrs->rta_type == MPTCP_ATTR_SPORT)
 180                                        fprintf(stderr, ",sport:%u",
 181                                                ntohs(*(__u16 *)RTA_DATA(attrs)));
 182                                else if (attrs->rta_type == MPTCP_ATTR_DPORT)
 183                                        fprintf(stderr, ",dport:%u",
 184                                                ntohs(*(__u16 *)RTA_DATA(attrs)));
 185                                else if (attrs->rta_type == MPTCP_ATTR_BACKUP)
 186                                        fprintf(stderr, ",backup:%u", *(__u8 *)RTA_DATA(attrs));
 187                                else if (attrs->rta_type == MPTCP_ATTR_ERROR)
 188                                        fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs));
 189                                else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE)
 190                                        fprintf(stderr, ",server_side:%u", *(__u8 *)RTA_DATA(attrs));
 191
 192                                attrs = RTA_NEXT(attrs, msg_len);
 193                        }
 194                }
 195                fprintf(stderr, "\n");
 196        } while (1);
 197
 198        return 0;
 199}
 200
 201/* do a netlink command and, if max > 0, fetch the reply  */
 202static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
 203{
 204        struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
 205        socklen_t addr_len;
 206        void *data = nh;
 207        int rem, ret;
 208        int err = 0;
 209
 210        nh->nlmsg_len = len;
 211        ret = sendto(fd, data, len, 0, (void *)&nladdr, sizeof(nladdr));
 212        if (ret != len)
 213                error(1, errno, "send netlink: %uB != %uB\n", ret, len);
 214        if (max == 0)
 215                return 0;
 216
 217        addr_len = sizeof(nladdr);
 218        rem = ret = recvfrom(fd, data, max, 0, (void *)&nladdr, &addr_len);
 219        if (ret < 0)
 220                error(1, errno, "recv netlink: %uB\n", ret);
 221
 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) {
 225                        nl_error(nh);
 226                        err = 1;
 227                }
 228        }
 229        if (err)
 230                error(1, 0, "bailing out due to netlink error[s]");
 231        return ret;
 232}
 233
 234static int genl_parse_getfamily(struct nlmsghdr *nlh, int *pm_family,
 235                                int *events_mcast_grp)
 236{
 237        struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
 238        int len = nlh->nlmsg_len;
 239        struct rtattr *attrs;
 240        struct rtattr *grps;
 241        struct rtattr *grp;
 242        int got_events_grp;
 243        int got_family;
 244        int grps_len;
 245        int grp_len;
 246
 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);
 250
 251        len -= NLMSG_LENGTH(GENL_HDRLEN);
 252
 253        if (len < 0)
 254                error(1, errno, "wrong controller message len %d\n", len);
 255
 256        if (ghdr->cmd != CTRL_CMD_NEWFAMILY)
 257                error(1, errno, "Unknown controller command %d\n", ghdr->cmd);
 258
 259        attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
 260        got_family = 0;
 261        got_events_grp = 0;
 262
 263        while (RTA_OK(attrs, len)) {
 264                if (attrs->rta_type == CTRL_ATTR_FAMILY_ID) {
 265                        *pm_family = *(__u16 *)RTA_DATA(attrs);
 266                        got_family = 1;
 267                } else if (attrs->rta_type == CTRL_ATTR_MCAST_GROUPS) {
 268                        grps = RTA_DATA(attrs);
 269                        grps_len = RTA_PAYLOAD(attrs);
 270
 271                        while (RTA_OK(grps, grps_len)) {
 272                                grp = RTA_DATA(grps);
 273                                grp_len = RTA_PAYLOAD(grps);
 274                                got_events_grp = 0;
 275
 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))
 281                                                got_events_grp = 1;
 282
 283                                        grp = RTA_NEXT(grp, grp_len);
 284                                }
 285
 286                                if (got_events_grp)
 287                                        break;
 288
 289                                grps = RTA_NEXT(grps, grps_len);
 290                        }
 291                }
 292
 293                if (got_family && got_events_grp)
 294                        return 0;
 295
 296                attrs = RTA_NEXT(attrs, len);
 297        }
 298
 299        error(1, errno, "can't find CTRL_ATTR_FAMILY_ID attr");
 300        return -1;
 301}
 302
 303static int resolve_mptcp_pm_netlink(int fd, int *pm_family, int *events_mcast_grp)
 304{
 305        char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
 306                  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
 307                  1024];
 308        struct nlmsghdr *nh;
 309        struct rtattr *rta;
 310        int namelen;
 311        int off = 0;
 312
 313        memset(data, 0, sizeof(data));
 314        nh = (void *)data;
 315        off = init_genl_req(data, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 0);
 316
 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);
 323
 324        do_nl_req(fd, nh, off, sizeof(data));
 325        return genl_parse_getfamily((void *)data, pm_family, events_mcast_grp);
 326}
 327
 328int dsf(int fd, int pm_family, int argc, char *argv[])
 329{
 330        char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
 331                  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
 332                  1024];
 333        struct rtattr *rta, *addr;
 334        u_int16_t family, port;
 335        struct nlmsghdr *nh;
 336        u_int32_t token;
 337        int addr_start;
 338        int off = 0;
 339        int arg;
 340
 341        const char *params[5];
 342
 343        memset(params, 0, 5 * sizeof(const char *));
 344
 345        memset(data, 0, sizeof(data));
 346        nh = (void *)data;
 347        off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_DESTROY,
 348                            MPTCP_PM_VER);
 349
 350        if (argc < 12)
 351                syntax(argv);
 352
 353        /* Params recorded in this order:
 354         * <local-ip>, <local-port>, <remote-ip>, <remote-port>, <token>
 355         */
 356        for (arg = 2; arg < argc; arg++) {
 357                if (!strcmp(argv[arg], "lip")) {
 358                        if (++arg >= argc)
 359                                error(1, 0, " missing local IP");
 360
 361                        params[0] = argv[arg];
 362                } else if (!strcmp(argv[arg], "lport")) {
 363                        if (++arg >= argc)
 364                                error(1, 0, " missing local port");
 365
 366                        params[1] = argv[arg];
 367                } else if (!strcmp(argv[arg], "rip")) {
 368                        if (++arg >= argc)
 369                                error(1, 0, " missing remote IP");
 370
 371                        params[2] = argv[arg];
 372                } else if (!strcmp(argv[arg], "rport")) {
 373                        if (++arg >= argc)
 374                                error(1, 0, " missing remote port");
 375
 376                        params[3] = argv[arg];
 377                } else if (!strcmp(argv[arg], "token")) {
 378                        if (++arg >= argc)
 379                                error(1, 0, " missing token");
 380
 381                        params[4] = argv[arg];
 382                } else
 383                        error(1, 0, "unknown keyword %s", argv[arg]);
 384        }
 385
 386        for (arg = 0; arg < 4; arg = arg + 2) {
 387                /*  addr header */
 388                addr_start = off;
 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);
 394
 395                /*  addr data */
 396                rta = (void *)(data + off);
 397                if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
 398                        family = AF_INET;
 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))) {
 402                        family = AF_INET6;
 403                        rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
 404                        rta->rta_len = RTA_LENGTH(16);
 405                } else
 406                        error(1, errno, "can't parse ip %s", params[arg]);
 407                off += NLMSG_ALIGN(rta->rta_len);
 408
 409                /* family */
 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);
 415
 416                /*  port */
 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);
 423
 424                addr->rta_len = off - addr_start;
 425        }
 426
 427        /* token */
 428        token = atoi(params[4]);
 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);
 434
 435        do_nl_req(fd, nh, off, 0);
 436
 437        return 0;
 438}
 439
 440int csf(int fd, int pm_family, int argc, char *argv[])
 441{
 442        char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
 443                  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
 444                  1024];
 445        const char *params[5];
 446        struct nlmsghdr *nh;
 447        struct rtattr *addr;
 448        struct rtattr *rta;
 449        u_int16_t family;
 450        u_int32_t token;
 451        u_int16_t port;
 452        int addr_start;
 453        u_int8_t id;
 454        int off = 0;
 455        int arg;
 456
 457        memset(params, 0, 5 * sizeof(const char *));
 458
 459        memset(data, 0, sizeof(data));
 460        nh = (void *)data;
 461        off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_CREATE,
 462                            MPTCP_PM_VER);
 463
 464        if (argc < 12)
 465                syntax(argv);
 466
 467        /* Params recorded in this order:
 468         * <local-ip>, <local-id>, <remote-ip>, <remote-port>, <token>
 469         */
 470        for (arg = 2; arg < argc; arg++) {
 471                if (!strcmp(argv[arg], "lip")) {
 472                        if (++arg >= argc)
 473                                error(1, 0, " missing local IP");
 474
 475                        params[0] = argv[arg];
 476                } else if (!strcmp(argv[arg], "lid")) {
 477                        if (++arg >= argc)
 478                                error(1, 0, " missing local id");
 479
 480                        params[1] = argv[arg];
 481                } else if (!strcmp(argv[arg], "rip")) {
 482                        if (++arg >= argc)
 483                                error(1, 0, " missing remote ip");
 484
 485                        params[2] = argv[arg];
 486                } else if (!strcmp(argv[arg], "rport")) {
 487                        if (++arg >= argc)
 488                                error(1, 0, " missing remote port");
 489
 490                        params[3] = argv[arg];
 491                } else if (!strcmp(argv[arg], "token")) {
 492                        if (++arg >= argc)
 493                                error(1, 0, " missing token");
 494
 495                        params[4] = argv[arg];
 496                } else
 497                        error(1, 0, "unknown param %s", argv[arg]);
 498        }
 499
 500        for (arg = 0; arg < 4; arg = arg + 2) {
 501                /*  addr header */
 502                addr_start = off;
 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);
 508
 509                /*  addr data */
 510                rta = (void *)(data + off);
 511                if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
 512                        family = AF_INET;
 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))) {
 516                        family = AF_INET6;
 517                        rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
 518                        rta->rta_len = RTA_LENGTH(16);
 519                } else
 520                        error(1, errno, "can't parse ip %s", params[arg]);
 521                off += NLMSG_ALIGN(rta->rta_len);
 522
 523                /* family */
 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);
 529
 530                if (arg == 2) {
 531                        /*  port */
 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);
 538                }
 539
 540                if (arg == 0) {
 541                        /* id */
 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);
 548                }
 549
 550                addr->rta_len = off - addr_start;
 551        }
 552
 553        /* token */
 554        token = atoi(params[4]);
 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);
 560
 561        do_nl_req(fd, nh, off, 0);
 562
 563        return 0;
 564}
 565
 566int remove_addr(int fd, int pm_family, int argc, char *argv[])
 567{
 568        char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
 569                  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
 570                  1024];
 571        struct nlmsghdr *nh;
 572        struct rtattr *rta;
 573        u_int32_t token;
 574        u_int8_t id;
 575        int off = 0;
 576        int arg;
 577
 578        memset(data, 0, sizeof(data));
 579        nh = (void *)data;
 580        off = init_genl_req(data, pm_family, MPTCP_PM_CMD_REMOVE,
 581                            MPTCP_PM_VER);
 582
 583        if (argc < 6)
 584                syntax(argv);
 585
 586        for (arg = 2; arg < argc; arg++) {
 587                if (!strcmp(argv[arg], "id")) {
 588                        if (++arg >= argc)
 589                                error(1, 0, " missing id value");
 590
 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")) {
 598                        if (++arg >= argc)
 599                                error(1, 0, " missing token value");
 600
 601                        token = atoi(argv[arg]);
 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);
 607                } else
 608                        error(1, 0, "unknown keyword %s", argv[arg]);
 609        }
 610
 611        do_nl_req(fd, nh, off, 0);
 612        return 0;
 613}
 614
 615int announce_addr(int fd, int pm_family, int argc, char *argv[])
 616{
 617        char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
 618                  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
 619                  1024];
 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;
 624        struct nlmsghdr *nh;
 625        u_int16_t family;
 626        int addr_start;
 627        int off = 0;
 628        int arg;
 629
 630        memset(data, 0, sizeof(data));
 631        nh = (void *)data;
 632        off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ANNOUNCE,
 633                            MPTCP_PM_VER);
 634
 635        if (argc < 7)
 636                syntax(argv);
 637
 638        /* local-ip header */
 639        addr_start = off;
 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);
 644
 645        /* local-ip data */
 646        /* record addr type */
 647        rta = (void *)(data + off);
 648        if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
 649                family = AF_INET;
 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))) {
 653                family = AF_INET6;
 654                rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
 655                rta->rta_len = RTA_LENGTH(16);
 656        } else
 657                error(1, errno, "can't parse ip %s", argv[2]);
 658        off += NLMSG_ALIGN(rta->rta_len);
 659
 660        /* addr family */
 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);
 666
 667        for (arg = 3; arg < argc; arg++) {
 668                if (!strcmp(argv[arg], "id")) {
 669                        /* local-id */
 670                        if (++arg >= argc)
 671                                error(1, 0, " missing id value");
 672
 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 */
 681                        int32_t ifindex;
 682
 683                        if (++arg >= argc)
 684                                error(1, 0, " missing dev name");
 685
 686                        ifindex = if_nametoindex(argv[arg]);
 687                        if (!ifindex)
 688                                error(1, errno, "unknown device %s", argv[arg]);
 689
 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) */
 697                        u_int16_t port;
 698
 699                        if (++arg >= argc)
 700                                error(1, 0, " missing port value");
 701
 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 */
 710                        if (++arg >= argc)
 711                                error(1, 0, " missing token value");
 712
 713                        token = atoi(argv[arg]);
 714                } else
 715                        error(1, 0, "unknown keyword %s", argv[arg]);
 716        }
 717
 718        /* addr flags */
 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);
 724
 725        addr->rta_len = off - addr_start;
 726
 727        if (id == UINT_MAX || token == UINT_MAX)
 728                error(1, 0, " missing mandatory inputs");
 729
 730        /* token */
 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);
 736
 737        do_nl_req(fd, nh, off, 0);
 738
 739        return 0;
 740}
 741
 742int add_addr(int fd, int pm_family, int argc, char *argv[])
 743{
 744        char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
 745                  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
 746                  1024];
 747        struct rtattr *rta, *nest;
 748        struct nlmsghdr *nh;
 749        u_int32_t flags = 0;
 750        u_int16_t family;
 751        int nest_start;
 752        u_int8_t id;
 753        int off = 0;
 754        int arg;
 755
 756        memset(data, 0, sizeof(data));
 757        nh = (void *)data;
 758        off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ADD_ADDR,
 759                            MPTCP_PM_VER);
 760
 761        if (argc < 3)
 762                syntax(argv);
 763
 764        nest_start = off;
 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);
 769
 770        /* addr data */
 771        rta = (void *)(data + off);
 772        if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
 773                family = AF_INET;
 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))) {
 777                family = AF_INET6;
 778                rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
 779                rta->rta_len = RTA_LENGTH(16);
 780        } else
 781                error(1, errno, "can't parse ip %s", argv[2]);
 782        off += NLMSG_ALIGN(rta->rta_len);
 783
 784        /* family */
 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);
 790
 791        for (arg = 3; arg < argc; arg++) {
 792                if (!strcmp(argv[arg], "flags")) {
 793                        char *tok, *str;
 794
 795                        /* flags */
 796                        if (++arg >= argc)
 797                                error(1, 0, " missing flags value");
 798
 799                        /* do not support flag list yet */
 800                        for (str = argv[arg]; (tok = strtok(str, ","));
 801                             str = NULL) {
 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;
 810                                else
 811                                        error(1, errno,
 812                                              "unknown flag %s", argv[arg]);
 813                        }
 814
 815                        if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
 816                            flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
 817                                error(1, errno, "error flag fullmesh");
 818                        }
 819
 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")) {
 826                        if (++arg >= argc)
 827                                error(1, 0, " missing id value");
 828
 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")) {
 836                        int32_t ifindex;
 837
 838                        if (++arg >= argc)
 839                                error(1, 0, " missing dev name");
 840
 841                        ifindex = if_nametoindex(argv[arg]);
 842                        if (!ifindex)
 843                                error(1, errno, "unknown device %s", argv[arg]);
 844
 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")) {
 851                        u_int16_t port;
 852
 853                        if (++arg >= argc)
 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");
 857
 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);
 864                } else
 865                        error(1, 0, "unknown keyword %s", argv[arg]);
 866        }
 867        nest->rta_len = off - nest_start;
 868
 869        do_nl_req(fd, nh, off, 0);
 870        return 0;
 871}
 872
 873int del_addr(int fd, int pm_family, int argc, char *argv[])
 874{
 875        char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
 876                  NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
 877                  1024];
 878        struct rtattr *rta, *nest;
 879        struct nlmsghdr *nh;
 880        u_int16_t family;
 881        int nest_start;
 882        u_int8_t id;
 883        int off = 0;
 884
 885        memset(data, 0, sizeof(data));
 886        nh = (void *)data;
 887        off = init_genl_req(data, pm_family, MPTCP_PM_CMD_DEL_ADDR,
 888                            MPTCP_PM_VER);
 889
 890        /* the only argument is the address id (nonzero) */
 891        if (argc != 3 && argc != 4)
 892                syntax(argv);
 893
 894        id = atoi(argv[2]);
 895        /* zero id with the IP address */
 896        if (!id && argc != 4)
 897                syntax(argv);
 898
 899        nest_start = off;
 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);
 904
 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);
 911
 912        if (!id) {
 913                /* addr data */
 914                rta = (void *)(data + off);
 915                if (inet_pton(AF_INET, argv[3], RTA_DATA(rta))) {
 916                        family = AF_INET;
 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))) {
 920                        family = AF_INET6;
 921                        rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
 922                        rta->rta_len = RTA_LENGTH(16);
 923                } else {
 924                        error(1, errno, "can't parse ip %s", argv[3]);
 925                }
 926                off += NLMSG_ALIGN(rta->rta_len);
 927
 928                /* family */
 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);
 934        }
 935        nest->rta_len = off - nest_start;
 936
 937        do_nl_req(fd, nh, off, 0);
 938        return 0;
 939}
 940
 941static void print_addr(struct rtattr *attrs, int len)
 942{
 943        uint16_t family = 0;
 944        uint16_t port = 0;
 945        char str[1024];
 946        uint32_t flags;
 947        uint8_t id;
 948
 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",
 957                                      family);
 958                        inet_ntop(AF_INET, RTA_DATA(attrs), str, sizeof(str));
 959                        printf("%s", str);
 960                        if (port)
 961                                printf(" %d", port);
 962                }
 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",
 966                                      family);
 967                        inet_ntop(AF_INET6, RTA_DATA(attrs), str, sizeof(str));
 968                        printf("%s", str);
 969                        if (port)
 970                                printf(" %d", port);
 971                }
 972                if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ID) {
 973                        memcpy(&id, RTA_DATA(attrs), 1);
 974                        printf("id %d ", id);
 975                }
 976                if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FLAGS) {
 977                        memcpy(&flags, RTA_DATA(attrs), 4);
 978
 979                        printf("flags ");
 980                        if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
 981                                printf("signal");
 982                                flags &= ~MPTCP_PM_ADDR_FLAG_SIGNAL;
 983                                if (flags)
 984                                        printf(",");
 985                        }
 986
 987                        if (flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
 988                                printf("subflow");
 989                                flags &= ~MPTCP_PM_ADDR_FLAG_SUBFLOW;
 990                                if (flags)
 991                                        printf(",");
 992                        }
 993
 994                        if (flags & MPTCP_PM_ADDR_FLAG_BACKUP) {
 995                                printf("backup");
 996                                flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
 997                                if (flags)
 998                                        printf(",");
 999                        }
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
1037static 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
1064int 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
1104int 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
1126int 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
1143static 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
1172next:
1173                        attrs = RTA_NEXT(attrs, len);
1174                }
1175        }
1176}
1177
1178int 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
1226int 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
1274int 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
1460int 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}
1506