| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581 |
- // SPDX-License-Identifier: GPL-2.0
- #include <errno.h>
- #include <error.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <limits.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <arpa/inet.h>
- #include <net/if.h>
- #include <linux/rtnetlink.h>
- #include <linux/genetlink.h>
- #include "linux/mptcp.h"
- #ifndef IPPROTO_MPTCP
- #define IPPROTO_MPTCP 262
- #endif
- #define MPTCP_PM_ADDR_FLAG_UNKNOWN _BITUL(7)
- static void syntax(char *argv[])
- {
- fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]);
- fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n");
- fprintf(stderr, "\tann <local-ip> id <local-id> token <token> [port <local-port>] [dev <name>]\n");
- fprintf(stderr, "\trem id <local-id> token <token>\n");
- fprintf(stderr, "\tcsf lip <local-ip> lid <local-id> rip <remote-ip> rport <remote-port> token <token>\n");
- fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n");
- fprintf(stderr, "\tdel <id> [<ip>]\n");
- fprintf(stderr, "\tget <id>\n");
- fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>] [token <token>] [rip <ip>] [rport <port>]\n");
- fprintf(stderr, "\tflush\n");
- fprintf(stderr, "\tdump\n");
- fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
- fprintf(stderr, "\tevents\n");
- fprintf(stderr, "\tlisten <local-ip> <local-port>\n");
- exit(0);
- }
- static int init_genl_req(char *data, int family, int cmd, int version)
- {
- struct nlmsghdr *nh = (void *)data;
- struct genlmsghdr *gh;
- int off = 0;
- nh->nlmsg_type = family;
- nh->nlmsg_flags = NLM_F_REQUEST;
- nh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
- off += NLMSG_ALIGN(sizeof(*nh));
- gh = (void *)(data + off);
- gh->cmd = cmd;
- gh->version = version;
- off += NLMSG_ALIGN(sizeof(*gh));
- return off;
- }
- static int nl_error(struct nlmsghdr *nh)
- {
- struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh);
- int len = nh->nlmsg_len - sizeof(*nh);
- uint32_t off;
- if (len < sizeof(struct nlmsgerr)) {
- error(1, 0, "netlink error message truncated %d min %ld", len,
- sizeof(struct nlmsgerr));
- return -1;
- }
- if (err->error) {
- /* check messages from kernel */
- struct rtattr *attrs = (struct rtattr *)NLMSG_DATA(nh);
- fprintf(stderr, "netlink error %d (%s)\n",
- err->error, strerror(-err->error));
- while (RTA_OK(attrs, len)) {
- if (attrs->rta_type == NLMSGERR_ATTR_MSG)
- fprintf(stderr, "netlink ext ack msg: %s\n",
- (char *)RTA_DATA(attrs));
- if (attrs->rta_type == NLMSGERR_ATTR_OFFS) {
- memcpy(&off, RTA_DATA(attrs), 4);
- fprintf(stderr, "netlink err off %d\n",
- (int)off);
- }
- attrs = RTA_NEXT(attrs, len);
- }
- return -1;
- }
- return 0;
- }
- static int capture_events(int fd, int event_group)
- {
- u_int8_t buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024];
- struct genlmsghdr *ghdr;
- struct rtattr *attrs;
- struct nlmsghdr *nh;
- int ret = 0;
- int res_len;
- int msg_len;
- fd_set rfds;
- if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
- &event_group, sizeof(event_group)) < 0)
- error(1, errno, "could not join the " MPTCP_PM_EV_GRP_NAME " mcast group");
- do {
- bool server_side = false;
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
- res_len = NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024;
- ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
- if (ret < 0)
- error(1, ret, "error in select() on NL socket");
- res_len = recv(fd, buffer, res_len, 0);
- if (res_len < 0)
- error(1, res_len, "error on recv() from NL socket");
- nh = (struct nlmsghdr *)buffer;
- for (; NLMSG_OK(nh, res_len); nh = NLMSG_NEXT(nh, res_len)) {
- if (nh->nlmsg_type == NLMSG_ERROR)
- error(1, NLMSG_ERROR, "received invalid NL message");
- ghdr = (struct genlmsghdr *)NLMSG_DATA(nh);
- if (ghdr->cmd == 0)
- continue;
- fprintf(stderr, "type:%d", ghdr->cmd);
- msg_len = nh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
- attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
- while (RTA_OK(attrs, msg_len)) {
- if (attrs->rta_type == MPTCP_ATTR_TOKEN)
- fprintf(stderr, ",token:%u", *(__u32 *)RTA_DATA(attrs));
- else if (attrs->rta_type == MPTCP_ATTR_FAMILY)
- fprintf(stderr, ",family:%u", *(__u16 *)RTA_DATA(attrs));
- else if (attrs->rta_type == MPTCP_ATTR_LOC_ID)
- fprintf(stderr, ",loc_id:%u", *(__u8 *)RTA_DATA(attrs));
- else if (attrs->rta_type == MPTCP_ATTR_REM_ID)
- fprintf(stderr, ",rem_id:%u", *(__u8 *)RTA_DATA(attrs));
- else if (attrs->rta_type == MPTCP_ATTR_SADDR4) {
- u_int32_t saddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
- fprintf(stderr, ",saddr4:%u.%u.%u.%u", saddr4 >> 24,
- (saddr4 >> 16) & 0xFF, (saddr4 >> 8) & 0xFF,
- (saddr4 & 0xFF));
- } else if (attrs->rta_type == MPTCP_ATTR_SADDR6) {
- char buf[INET6_ADDRSTRLEN];
- if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
- sizeof(buf)) != NULL)
- fprintf(stderr, ",saddr6:%s", buf);
- } else if (attrs->rta_type == MPTCP_ATTR_DADDR4) {
- u_int32_t daddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
- fprintf(stderr, ",daddr4:%u.%u.%u.%u", daddr4 >> 24,
- (daddr4 >> 16) & 0xFF, (daddr4 >> 8) & 0xFF,
- (daddr4 & 0xFF));
- } else if (attrs->rta_type == MPTCP_ATTR_DADDR6) {
- char buf[INET6_ADDRSTRLEN];
- if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
- sizeof(buf)) != NULL)
- fprintf(stderr, ",daddr6:%s", buf);
- } else if (attrs->rta_type == MPTCP_ATTR_SPORT)
- fprintf(stderr, ",sport:%u",
- ntohs(*(__u16 *)RTA_DATA(attrs)));
- else if (attrs->rta_type == MPTCP_ATTR_DPORT)
- fprintf(stderr, ",dport:%u",
- ntohs(*(__u16 *)RTA_DATA(attrs)));
- else if (attrs->rta_type == MPTCP_ATTR_BACKUP)
- fprintf(stderr, ",backup:%u", *(__u8 *)RTA_DATA(attrs));
- else if (attrs->rta_type == MPTCP_ATTR_ERROR)
- fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs));
- else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE)
- server_side = !!*(__u8 *)RTA_DATA(attrs);
- else if (attrs->rta_type == MPTCP_ATTR_FLAGS) {
- __u16 flags = *(__u16 *)RTA_DATA(attrs);
- /* only print when present, easier */
- if (flags & MPTCP_PM_EV_FLAG_DENY_JOIN_ID0)
- fprintf(stderr, ",deny_join_id0:1");
- if (flags & MPTCP_PM_EV_FLAG_SERVER_SIDE)
- server_side = true;
- }
- attrs = RTA_NEXT(attrs, msg_len);
- }
- }
- if (server_side)
- fprintf(stderr, ",server_side:1");
- fprintf(stderr, "\n");
- } while (1);
- return 0;
- }
- /* do a netlink command and, if max > 0, fetch the reply ; nh's size >1024B */
- static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
- {
- struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
- socklen_t addr_len;
- void *data = nh;
- int rem, ret;
- int err = 0;
- /* If no expected answer, ask for an ACK to look for errors if any */
- if (max == 0) {
- nh->nlmsg_flags |= NLM_F_ACK;
- max = 1024;
- }
- nh->nlmsg_len = len;
- ret = sendto(fd, data, len, 0, (void *)&nladdr, sizeof(nladdr));
- if (ret != len)
- error(1, errno, "send netlink: %uB != %uB\n", ret, len);
- addr_len = sizeof(nladdr);
- rem = ret = recvfrom(fd, data, max, 0, (void *)&nladdr, &addr_len);
- if (ret < 0)
- error(1, errno, "recv netlink: %uB\n", ret);
- /* Beware: the NLMSG_NEXT macro updates the 'rem' argument */
- for (; NLMSG_OK(nh, rem); nh = NLMSG_NEXT(nh, rem)) {
- if (nh->nlmsg_type == NLMSG_DONE)
- break;
- if (nh->nlmsg_type == NLMSG_ERROR && nl_error(nh))
- err = 1;
- }
- if (err)
- error(1, 0, "bailing out due to netlink error[s]");
- return ret;
- }
- static int genl_parse_getfamily(struct nlmsghdr *nlh, int *pm_family,
- int *events_mcast_grp)
- {
- struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
- int len = nlh->nlmsg_len;
- struct rtattr *attrs;
- struct rtattr *grps;
- struct rtattr *grp;
- int got_events_grp;
- int got_family;
- int grps_len;
- int grp_len;
- if (nlh->nlmsg_type != GENL_ID_CTRL)
- error(1, errno, "Not a controller message, len=%d type=0x%x\n",
- nlh->nlmsg_len, nlh->nlmsg_type);
- len -= NLMSG_LENGTH(GENL_HDRLEN);
- if (len < 0)
- error(1, errno, "wrong controller message len %d\n", len);
- if (ghdr->cmd != CTRL_CMD_NEWFAMILY)
- error(1, errno, "Unknown controller command %d\n", ghdr->cmd);
- attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
- got_family = 0;
- got_events_grp = 0;
- while (RTA_OK(attrs, len)) {
- if (attrs->rta_type == CTRL_ATTR_FAMILY_ID) {
- *pm_family = *(__u16 *)RTA_DATA(attrs);
- got_family = 1;
- } else if (attrs->rta_type == CTRL_ATTR_MCAST_GROUPS) {
- grps = RTA_DATA(attrs);
- grps_len = RTA_PAYLOAD(attrs);
- while (RTA_OK(grps, grps_len)) {
- grp = RTA_DATA(grps);
- grp_len = RTA_PAYLOAD(grps);
- got_events_grp = 0;
- while (RTA_OK(grp, grp_len)) {
- if (grp->rta_type == CTRL_ATTR_MCAST_GRP_ID)
- *events_mcast_grp = *(__u32 *)RTA_DATA(grp);
- else if (grp->rta_type == CTRL_ATTR_MCAST_GRP_NAME &&
- !strcmp(RTA_DATA(grp), MPTCP_PM_EV_GRP_NAME))
- got_events_grp = 1;
- grp = RTA_NEXT(grp, grp_len);
- }
- if (got_events_grp)
- break;
- grps = RTA_NEXT(grps, grps_len);
- }
- }
- if (got_family && got_events_grp)
- return 0;
- attrs = RTA_NEXT(attrs, len);
- }
- error(1, errno, "can't find CTRL_ATTR_FAMILY_ID attr");
- return -1;
- }
- static int resolve_mptcp_pm_netlink(int fd, int *pm_family, int *events_mcast_grp)
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- struct nlmsghdr *nh;
- struct rtattr *rta;
- int namelen;
- int off = 0;
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 0);
- rta = (void *)(data + off);
- namelen = strlen(MPTCP_PM_NAME) + 1;
- rta->rta_type = CTRL_ATTR_FAMILY_NAME;
- rta->rta_len = RTA_LENGTH(namelen);
- memcpy(RTA_DATA(rta), MPTCP_PM_NAME, namelen);
- off += NLMSG_ALIGN(rta->rta_len);
- do_nl_req(fd, nh, off, sizeof(data));
- return genl_parse_getfamily((void *)data, pm_family, events_mcast_grp);
- }
- int dsf(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- struct rtattr *rta, *addr;
- u_int16_t family, port;
- struct nlmsghdr *nh;
- u_int32_t token;
- int addr_start;
- int off = 0;
- int arg;
- const char *params[5];
- memset(params, 0, 5 * sizeof(const char *));
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_DESTROY,
- MPTCP_PM_VER);
- if (argc < 12)
- syntax(argv);
- /* Params recorded in this order:
- * <local-ip>, <local-port>, <remote-ip>, <remote-port>, <token>
- */
- for (arg = 2; arg < argc; arg++) {
- if (!strcmp(argv[arg], "lip")) {
- if (++arg >= argc)
- error(1, 0, " missing local IP");
- params[0] = argv[arg];
- } else if (!strcmp(argv[arg], "lport")) {
- if (++arg >= argc)
- error(1, 0, " missing local port");
- params[1] = argv[arg];
- } else if (!strcmp(argv[arg], "rip")) {
- if (++arg >= argc)
- error(1, 0, " missing remote IP");
- params[2] = argv[arg];
- } else if (!strcmp(argv[arg], "rport")) {
- if (++arg >= argc)
- error(1, 0, " missing remote port");
- params[3] = argv[arg];
- } else if (!strcmp(argv[arg], "token")) {
- if (++arg >= argc)
- error(1, 0, " missing token");
- params[4] = argv[arg];
- } else
- error(1, 0, "unknown keyword %s", argv[arg]);
- }
- for (arg = 0; arg < 4; arg = arg + 2) {
- /* addr header */
- addr_start = off;
- addr = (void *)(data + off);
- addr->rta_type = NLA_F_NESTED |
- ((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
- addr->rta_len = RTA_LENGTH(0);
- off += NLMSG_ALIGN(addr->rta_len);
- /* addr data */
- rta = (void *)(data + off);
- if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
- family = AF_INET;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
- rta->rta_len = RTA_LENGTH(4);
- } else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
- family = AF_INET6;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
- rta->rta_len = RTA_LENGTH(16);
- } else
- error(1, errno, "can't parse ip %s", params[arg]);
- off += NLMSG_ALIGN(rta->rta_len);
- /* family */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &family, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- /* port */
- port = atoi(params[arg + 1]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &port, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- addr->rta_len = off - addr_start;
- }
- /* token */
- token = strtoul(params[4], NULL, 10);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ATTR_TOKEN;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &token, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- do_nl_req(fd, nh, off, 0);
- return 0;
- }
- int csf(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- u_int32_t flags = MPTCP_PM_ADDR_FLAG_SUBFLOW;
- const char *params[5];
- struct nlmsghdr *nh;
- struct rtattr *addr;
- struct rtattr *rta;
- u_int16_t family;
- u_int32_t token;
- u_int16_t port;
- int addr_start;
- u_int8_t id;
- int off = 0;
- int arg;
- memset(params, 0, 5 * sizeof(const char *));
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_CREATE,
- MPTCP_PM_VER);
- if (argc < 12)
- syntax(argv);
- /* Params recorded in this order:
- * <local-ip>, <local-id>, <remote-ip>, <remote-port>, <token>
- */
- for (arg = 2; arg < argc; arg++) {
- if (!strcmp(argv[arg], "lip")) {
- if (++arg >= argc)
- error(1, 0, " missing local IP");
- params[0] = argv[arg];
- } else if (!strcmp(argv[arg], "lid")) {
- if (++arg >= argc)
- error(1, 0, " missing local id");
- params[1] = argv[arg];
- } else if (!strcmp(argv[arg], "rip")) {
- if (++arg >= argc)
- error(1, 0, " missing remote ip");
- params[2] = argv[arg];
- } else if (!strcmp(argv[arg], "rport")) {
- if (++arg >= argc)
- error(1, 0, " missing remote port");
- params[3] = argv[arg];
- } else if (!strcmp(argv[arg], "token")) {
- if (++arg >= argc)
- error(1, 0, " missing token");
- params[4] = argv[arg];
- } else
- error(1, 0, "unknown param %s", argv[arg]);
- }
- for (arg = 0; arg < 4; arg = arg + 2) {
- /* addr header */
- addr_start = off;
- addr = (void *)(data + off);
- addr->rta_type = NLA_F_NESTED |
- ((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
- addr->rta_len = RTA_LENGTH(0);
- off += NLMSG_ALIGN(addr->rta_len);
- /* addr data */
- rta = (void *)(data + off);
- if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
- family = AF_INET;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
- rta->rta_len = RTA_LENGTH(4);
- } else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
- family = AF_INET6;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
- rta->rta_len = RTA_LENGTH(16);
- } else
- error(1, errno, "can't parse ip %s", params[arg]);
- off += NLMSG_ALIGN(rta->rta_len);
- /* family */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &family, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- if (arg == 2) {
- /* port */
- port = atoi(params[arg + 1]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &port, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- }
- if (arg == 0) {
- /* id */
- id = atoi(params[arg + 1]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
- rta->rta_len = RTA_LENGTH(1);
- memcpy(RTA_DATA(rta), &id, 1);
- off += NLMSG_ALIGN(rta->rta_len);
- }
- /* addr flags */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &flags, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- addr->rta_len = off - addr_start;
- }
- /* token */
- token = strtoul(params[4], NULL, 10);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ATTR_TOKEN;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &token, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- do_nl_req(fd, nh, off, 0);
- return 0;
- }
- int remove_addr(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- struct nlmsghdr *nh;
- struct rtattr *rta;
- u_int32_t token;
- u_int8_t id;
- int off = 0;
- int arg;
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, MPTCP_PM_CMD_REMOVE,
- MPTCP_PM_VER);
- if (argc < 6)
- syntax(argv);
- for (arg = 2; arg < argc; arg++) {
- if (!strcmp(argv[arg], "id")) {
- if (++arg >= argc)
- error(1, 0, " missing id value");
- id = atoi(argv[arg]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ATTR_LOC_ID;
- rta->rta_len = RTA_LENGTH(1);
- memcpy(RTA_DATA(rta), &id, 1);
- off += NLMSG_ALIGN(rta->rta_len);
- } else if (!strcmp(argv[arg], "token")) {
- if (++arg >= argc)
- error(1, 0, " missing token value");
- token = strtoul(argv[arg], NULL, 10);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ATTR_TOKEN;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &token, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- } else
- error(1, 0, "unknown keyword %s", argv[arg]);
- }
- do_nl_req(fd, nh, off, 0);
- return 0;
- }
- int announce_addr(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- u_int32_t flags = MPTCP_PM_ADDR_FLAG_SIGNAL;
- u_int32_t token = UINT_MAX;
- struct rtattr *rta, *addr;
- u_int32_t id = UINT_MAX;
- struct nlmsghdr *nh;
- u_int16_t family;
- int addr_start;
- int off = 0;
- int arg;
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ANNOUNCE,
- MPTCP_PM_VER);
- if (argc < 7)
- syntax(argv);
- /* local-ip header */
- addr_start = off;
- addr = (void *)(data + off);
- addr->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
- addr->rta_len = RTA_LENGTH(0);
- off += NLMSG_ALIGN(addr->rta_len);
- /* local-ip data */
- /* record addr type */
- rta = (void *)(data + off);
- if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
- family = AF_INET;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
- rta->rta_len = RTA_LENGTH(4);
- } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
- family = AF_INET6;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
- rta->rta_len = RTA_LENGTH(16);
- } else
- error(1, errno, "can't parse ip %s", argv[2]);
- off += NLMSG_ALIGN(rta->rta_len);
- /* addr family */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &family, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- for (arg = 3; arg < argc; arg++) {
- if (!strcmp(argv[arg], "id")) {
- /* local-id */
- if (++arg >= argc)
- error(1, 0, " missing id value");
- id = atoi(argv[arg]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
- rta->rta_len = RTA_LENGTH(1);
- memcpy(RTA_DATA(rta), &id, 1);
- off += NLMSG_ALIGN(rta->rta_len);
- } else if (!strcmp(argv[arg], "dev")) {
- /* for the if_index */
- int32_t ifindex;
- if (++arg >= argc)
- error(1, 0, " missing dev name");
- ifindex = if_nametoindex(argv[arg]);
- if (!ifindex)
- error(1, errno, "unknown device %s", argv[arg]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &ifindex, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- } else if (!strcmp(argv[arg], "port")) {
- /* local-port (optional) */
- u_int16_t port;
- if (++arg >= argc)
- error(1, 0, " missing port value");
- port = atoi(argv[arg]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &port, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- } else if (!strcmp(argv[arg], "token")) {
- /* MPTCP connection token */
- if (++arg >= argc)
- error(1, 0, " missing token value");
- token = strtoul(argv[arg], NULL, 10);
- } else
- error(1, 0, "unknown keyword %s", argv[arg]);
- }
- /* addr flags */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &flags, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- addr->rta_len = off - addr_start;
- if (id == UINT_MAX || token == UINT_MAX)
- error(1, 0, " missing mandatory inputs");
- /* token */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ATTR_TOKEN;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &token, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- do_nl_req(fd, nh, off, 0);
- return 0;
- }
- int add_addr(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- struct rtattr *rta, *nest;
- struct nlmsghdr *nh;
- u_int32_t flags = 0;
- u_int16_t family;
- int nest_start;
- u_int8_t id;
- int off = 0;
- int arg;
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ADD_ADDR,
- MPTCP_PM_VER);
- if (argc < 3)
- syntax(argv);
- nest_start = off;
- nest = (void *)(data + off);
- nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
- nest->rta_len = RTA_LENGTH(0);
- off += NLMSG_ALIGN(nest->rta_len);
- /* addr data */
- rta = (void *)(data + off);
- if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
- family = AF_INET;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
- rta->rta_len = RTA_LENGTH(4);
- } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
- family = AF_INET6;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
- rta->rta_len = RTA_LENGTH(16);
- } else
- error(1, errno, "can't parse ip %s", argv[2]);
- off += NLMSG_ALIGN(rta->rta_len);
- /* family */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &family, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- for (arg = 3; arg < argc; arg++) {
- if (!strcmp(argv[arg], "flags")) {
- char *tok, *str;
- /* flags */
- if (++arg >= argc)
- error(1, 0, " missing flags value");
- /* do not support flag list yet */
- for (str = argv[arg]; (tok = strtok(str, ","));
- str = NULL) {
- if (!strcmp(tok, "subflow"))
- flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;
- else if (!strcmp(tok, "signal"))
- flags |= MPTCP_PM_ADDR_FLAG_SIGNAL;
- else if (!strcmp(tok, "laminar"))
- flags |= MPTCP_PM_ADDR_FLAG_LAMINAR;
- else if (!strcmp(tok, "backup"))
- flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
- else if (!strcmp(tok, "fullmesh"))
- flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
- else if (!strcmp(tok, "unknown"))
- flags |= MPTCP_PM_ADDR_FLAG_UNKNOWN;
- else
- error(1, errno,
- "unknown flag %s", argv[arg]);
- }
- if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
- flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
- error(1, errno, "error flag fullmesh");
- }
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &flags, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- } else if (!strcmp(argv[arg], "id")) {
- if (++arg >= argc)
- error(1, 0, " missing id value");
- id = atoi(argv[arg]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
- rta->rta_len = RTA_LENGTH(1);
- memcpy(RTA_DATA(rta), &id, 1);
- off += NLMSG_ALIGN(rta->rta_len);
- } else if (!strcmp(argv[arg], "dev")) {
- int32_t ifindex;
- if (++arg >= argc)
- error(1, 0, " missing dev name");
- ifindex = if_nametoindex(argv[arg]);
- if (!ifindex)
- error(1, errno, "unknown device %s", argv[arg]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &ifindex, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- } else if (!strcmp(argv[arg], "port")) {
- u_int16_t port;
- if (++arg >= argc)
- error(1, 0, " missing port value");
- if (!(flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
- error(1, 0, " flags must be signal when using port");
- port = atoi(argv[arg]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &port, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- } else
- error(1, 0, "unknown keyword %s", argv[arg]);
- }
- nest->rta_len = off - nest_start;
- do_nl_req(fd, nh, off, 0);
- return 0;
- }
- int del_addr(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- struct rtattr *rta, *nest;
- struct nlmsghdr *nh;
- u_int16_t family;
- int nest_start;
- u_int8_t id;
- int off = 0;
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, MPTCP_PM_CMD_DEL_ADDR,
- MPTCP_PM_VER);
- /* the only argument is the address id (nonzero) */
- if (argc != 3 && argc != 4)
- syntax(argv);
- id = atoi(argv[2]);
- /* zero id with the IP address */
- if (!id && argc != 4)
- syntax(argv);
- nest_start = off;
- nest = (void *)(data + off);
- nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
- nest->rta_len = RTA_LENGTH(0);
- off += NLMSG_ALIGN(nest->rta_len);
- /* build a dummy addr with only the ID set */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
- rta->rta_len = RTA_LENGTH(1);
- memcpy(RTA_DATA(rta), &id, 1);
- off += NLMSG_ALIGN(rta->rta_len);
- if (!id) {
- /* addr data */
- rta = (void *)(data + off);
- if (inet_pton(AF_INET, argv[3], RTA_DATA(rta))) {
- family = AF_INET;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
- rta->rta_len = RTA_LENGTH(4);
- } else if (inet_pton(AF_INET6, argv[3], RTA_DATA(rta))) {
- family = AF_INET6;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
- rta->rta_len = RTA_LENGTH(16);
- } else {
- error(1, errno, "can't parse ip %s", argv[3]);
- }
- off += NLMSG_ALIGN(rta->rta_len);
- /* family */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &family, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- }
- nest->rta_len = off - nest_start;
- do_nl_req(fd, nh, off, 0);
- return 0;
- }
- static void print_addr(struct rtattr *attrs, int len)
- {
- uint16_t family = 0;
- uint16_t port = 0;
- char str[1024];
- uint32_t flags;
- uint8_t id;
- while (RTA_OK(attrs, len)) {
- if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FAMILY)
- memcpy(&family, RTA_DATA(attrs), 2);
- if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_PORT)
- memcpy(&port, RTA_DATA(attrs), 2);
- if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR4) {
- if (family != AF_INET)
- error(1, errno, "wrong IP (v4) for family %d",
- family);
- inet_ntop(AF_INET, RTA_DATA(attrs), str, sizeof(str));
- printf("%s", str);
- if (port)
- printf(" %d", port);
- }
- if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ADDR6) {
- if (family != AF_INET6)
- error(1, errno, "wrong IP (v6) for family %d",
- family);
- inet_ntop(AF_INET6, RTA_DATA(attrs), str, sizeof(str));
- printf("%s", str);
- if (port)
- printf(" %d", port);
- }
- if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_ID) {
- memcpy(&id, RTA_DATA(attrs), 1);
- printf("id %d ", id);
- }
- if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_FLAGS) {
- memcpy(&flags, RTA_DATA(attrs), 4);
- printf("flags ");
- if (flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
- printf("signal");
- flags &= ~MPTCP_PM_ADDR_FLAG_SIGNAL;
- if (flags)
- printf(",");
- }
- if (flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
- printf("subflow");
- flags &= ~MPTCP_PM_ADDR_FLAG_SUBFLOW;
- if (flags)
- printf(",");
- }
- if (flags & MPTCP_PM_ADDR_FLAG_LAMINAR) {
- printf("laminar");
- flags &= ~MPTCP_PM_ADDR_FLAG_LAMINAR;
- if (flags)
- printf(",");
- }
- if (flags & MPTCP_PM_ADDR_FLAG_BACKUP) {
- printf("backup");
- flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
- if (flags)
- printf(",");
- }
- if (flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
- printf("fullmesh");
- flags &= ~MPTCP_PM_ADDR_FLAG_FULLMESH;
- if (flags)
- printf(",");
- }
- if (flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
- printf("implicit");
- flags &= ~MPTCP_PM_ADDR_FLAG_IMPLICIT;
- if (flags)
- printf(",");
- }
- if (flags & MPTCP_PM_ADDR_FLAG_UNKNOWN) {
- printf("unknown");
- flags &= ~MPTCP_PM_ADDR_FLAG_UNKNOWN;
- if (flags)
- printf(",");
- }
- /* bump unknown flags, if any */
- if (flags)
- printf("0x%x", flags);
- printf(" ");
- }
- if (attrs->rta_type == MPTCP_PM_ADDR_ATTR_IF_IDX) {
- char name[IF_NAMESIZE], *ret;
- int32_t ifindex;
- memcpy(&ifindex, RTA_DATA(attrs), 4);
- ret = if_indextoname(ifindex, name);
- if (ret)
- printf("dev %s ", ret);
- else
- printf("dev unknown/%d", ifindex);
- }
- attrs = RTA_NEXT(attrs, len);
- }
- printf("\n");
- }
- static void print_addrs(struct nlmsghdr *nh, int pm_family, int total_len)
- {
- struct rtattr *attrs;
- for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
- int len = nh->nlmsg_len;
- if (nh->nlmsg_type == NLMSG_DONE)
- break;
- if (nh->nlmsg_type == NLMSG_ERROR)
- nl_error(nh);
- if (nh->nlmsg_type != pm_family)
- continue;
- len -= NLMSG_LENGTH(GENL_HDRLEN);
- attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
- GENL_HDRLEN);
- while (RTA_OK(attrs, len)) {
- if (attrs->rta_type ==
- (MPTCP_PM_ATTR_ADDR | NLA_F_NESTED))
- print_addr((void *)RTA_DATA(attrs),
- attrs->rta_len);
- attrs = RTA_NEXT(attrs, len);
- }
- }
- }
- int get_addr(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- struct rtattr *rta, *nest;
- struct nlmsghdr *nh;
- u_int32_t token = 0;
- int nest_start;
- u_int8_t id;
- int off = 0;
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
- MPTCP_PM_VER);
- /* the only argument is the address id */
- if (argc != 3 && argc != 5)
- syntax(argv);
- id = atoi(argv[2]);
- if (argc == 5 && !strcmp(argv[3], "token"))
- token = strtoul(argv[4], NULL, 10);
- nest_start = off;
- nest = (void *)(data + off);
- nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
- nest->rta_len = RTA_LENGTH(0);
- off += NLMSG_ALIGN(nest->rta_len);
- /* build a dummy addr with only the ID set */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
- rta->rta_len = RTA_LENGTH(1);
- memcpy(RTA_DATA(rta), &id, 1);
- off += NLMSG_ALIGN(rta->rta_len);
- nest->rta_len = off - nest_start;
- /* token */
- if (token) {
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ATTR_TOKEN;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &token, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- }
- print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
- return 0;
- }
- int dump_addrs(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- pid_t pid = getpid();
- struct nlmsghdr *nh;
- u_int32_t token = 0;
- struct rtattr *rta;
- int off = 0;
- if (argc != 2 && argc != 4)
- syntax(argv);
- if (argc == 4 && !strcmp(argv[2], "token"))
- token = strtoul(argv[3], NULL, 10);
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
- MPTCP_PM_VER);
- nh->nlmsg_flags |= NLM_F_DUMP;
- nh->nlmsg_seq = 1;
- nh->nlmsg_pid = pid;
- nh->nlmsg_len = off;
- /* token */
- if (token) {
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ATTR_TOKEN;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &token, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- }
- print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
- return 0;
- }
- int flush_addrs(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- struct nlmsghdr *nh;
- int off = 0;
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, MPTCP_PM_CMD_FLUSH_ADDRS,
- MPTCP_PM_VER);
- do_nl_req(fd, nh, off, 0);
- return 0;
- }
- static void print_limits(struct nlmsghdr *nh, int pm_family, int total_len)
- {
- struct rtattr *attrs;
- uint32_t max;
- for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
- int len = nh->nlmsg_len;
- if (nh->nlmsg_type == NLMSG_DONE)
- break;
- if (nh->nlmsg_type == NLMSG_ERROR)
- nl_error(nh);
- if (nh->nlmsg_type != pm_family)
- continue;
- len -= NLMSG_LENGTH(GENL_HDRLEN);
- attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
- GENL_HDRLEN);
- while (RTA_OK(attrs, len)) {
- int type = attrs->rta_type;
- if (type != MPTCP_PM_ATTR_RCV_ADD_ADDRS &&
- type != MPTCP_PM_ATTR_SUBFLOWS)
- goto next;
- memcpy(&max, RTA_DATA(attrs), 4);
- printf("%s %u\n", type == MPTCP_PM_ATTR_SUBFLOWS ?
- "subflows" : "accept", max);
- next:
- attrs = RTA_NEXT(attrs, len);
- }
- }
- }
- int get_set_limits(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- uint32_t rcv_addr = 0, subflows = 0;
- int cmd, len = sizeof(data);
- struct nlmsghdr *nh;
- int off = 0;
- /* limit */
- if (argc == 4) {
- rcv_addr = atoi(argv[2]);
- subflows = atoi(argv[3]);
- cmd = MPTCP_PM_CMD_SET_LIMITS;
- } else {
- cmd = MPTCP_PM_CMD_GET_LIMITS;
- }
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, cmd, MPTCP_PM_VER);
- /* limit */
- if (cmd == MPTCP_PM_CMD_SET_LIMITS) {
- struct rtattr *rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ATTR_RCV_ADD_ADDRS;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &rcv_addr, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ATTR_SUBFLOWS;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &subflows, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- /* do not expect a reply */
- len = 0;
- }
- len = do_nl_req(fd, nh, off, len);
- if (cmd == MPTCP_PM_CMD_GET_LIMITS)
- print_limits(nh, pm_family, len);
- return 0;
- }
- int add_listener(int argc, char *argv[])
- {
- struct sockaddr_storage addr;
- struct sockaddr_in6 *a6;
- struct sockaddr_in *a4;
- u_int16_t family = AF_UNSPEC;
- int enable = 1;
- int sock;
- int err;
- if (argc < 4)
- syntax(argv);
- memset(&addr, 0, sizeof(struct sockaddr_storage));
- a4 = (struct sockaddr_in *)&addr;
- a6 = (struct sockaddr_in6 *)&addr;
- if (inet_pton(AF_INET, argv[2], &a4->sin_addr)) {
- family = AF_INET;
- a4->sin_family = family;
- a4->sin_port = htons(atoi(argv[3]));
- } else if (inet_pton(AF_INET6, argv[2], &a6->sin6_addr)) {
- family = AF_INET6;
- a6->sin6_family = family;
- a6->sin6_port = htons(atoi(argv[3]));
- } else
- error(1, errno, "can't parse ip %s", argv[2]);
- sock = socket(family, SOCK_STREAM, IPPROTO_MPTCP);
- if (sock < 0)
- error(1, errno, "can't create listener sock\n");
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) {
- close(sock);
- error(1, errno, "can't set SO_REUSEADDR on listener sock\n");
- }
- err = bind(sock, (struct sockaddr *)&addr,
- ((family == AF_INET) ? sizeof(struct sockaddr_in) :
- sizeof(struct sockaddr_in6)));
- if (err == 0 && listen(sock, 30) == 0)
- pause();
- close(sock);
- return 0;
- }
- int set_flags(int fd, int pm_family, int argc, char *argv[])
- {
- char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
- 1024];
- struct rtattr *rta, *nest;
- struct nlmsghdr *nh;
- u_int32_t flags = 0;
- u_int32_t token = 0;
- u_int16_t rport = 0;
- u_int16_t family;
- void *rip = NULL;
- int nest_start;
- int use_id = 0;
- u_int8_t id;
- int off = 0;
- int arg = 2;
- memset(data, 0, sizeof(data));
- nh = (void *)data;
- off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS,
- MPTCP_PM_VER);
- if (argc < 3)
- syntax(argv);
- nest_start = off;
- nest = (void *)(data + off);
- nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
- nest->rta_len = RTA_LENGTH(0);
- off += NLMSG_ALIGN(nest->rta_len);
- if (!strcmp(argv[arg], "id")) {
- if (++arg >= argc)
- error(1, 0, " missing id value");
- use_id = 1;
- id = atoi(argv[arg]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
- rta->rta_len = RTA_LENGTH(1);
- memcpy(RTA_DATA(rta), &id, 1);
- off += NLMSG_ALIGN(rta->rta_len);
- } else {
- /* addr data */
- rta = (void *)(data + off);
- if (inet_pton(AF_INET, argv[arg], RTA_DATA(rta))) {
- family = AF_INET;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
- rta->rta_len = RTA_LENGTH(4);
- } else if (inet_pton(AF_INET6, argv[arg], RTA_DATA(rta))) {
- family = AF_INET6;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
- rta->rta_len = RTA_LENGTH(16);
- } else {
- error(1, errno, "can't parse ip %s", argv[arg]);
- }
- off += NLMSG_ALIGN(rta->rta_len);
- /* family */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &family, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- }
- if (++arg >= argc)
- error(1, 0, " missing flags keyword");
- for (; arg < argc; arg++) {
- if (!strcmp(argv[arg], "token")) {
- if (++arg >= argc)
- error(1, 0, " missing token value");
- /* token */
- token = strtoul(argv[arg], NULL, 10);
- } else if (!strcmp(argv[arg], "flags")) {
- char *tok, *str;
- /* flags */
- if (++arg >= argc)
- error(1, 0, " missing flags value");
- for (str = argv[arg]; (tok = strtok(str, ","));
- str = NULL) {
- if (!strcmp(tok, "backup"))
- flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
- else if (!strcmp(tok, "fullmesh"))
- flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
- else if (strcmp(tok, "nobackup") &&
- strcmp(tok, "nofullmesh"))
- error(1, errno,
- "unknown flag %s", argv[arg]);
- }
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &flags, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- } else if (!strcmp(argv[arg], "port")) {
- u_int16_t port;
- if (use_id)
- error(1, 0, " port can't be used with id");
- if (++arg >= argc)
- error(1, 0, " missing port value");
- port = atoi(argv[arg]);
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &port, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- } else if (!strcmp(argv[arg], "rport")) {
- if (++arg >= argc)
- error(1, 0, " missing remote port");
- rport = atoi(argv[arg]);
- } else if (!strcmp(argv[arg], "rip")) {
- if (++arg >= argc)
- error(1, 0, " missing remote ip");
- rip = argv[arg];
- } else {
- error(1, 0, "unknown keyword %s", argv[arg]);
- }
- }
- nest->rta_len = off - nest_start;
- /* token */
- if (token) {
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ATTR_TOKEN;
- rta->rta_len = RTA_LENGTH(4);
- memcpy(RTA_DATA(rta), &token, 4);
- off += NLMSG_ALIGN(rta->rta_len);
- }
- /* remote addr/port */
- if (rip) {
- nest_start = off;
- nest = (void *)(data + off);
- nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR_REMOTE;
- nest->rta_len = RTA_LENGTH(0);
- off += NLMSG_ALIGN(nest->rta_len);
- /* addr data */
- rta = (void *)(data + off);
- if (inet_pton(AF_INET, rip, RTA_DATA(rta))) {
- family = AF_INET;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
- rta->rta_len = RTA_LENGTH(4);
- } else if (inet_pton(AF_INET6, rip, RTA_DATA(rta))) {
- family = AF_INET6;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
- rta->rta_len = RTA_LENGTH(16);
- } else {
- error(1, errno, "can't parse ip %s", (char *)rip);
- }
- off += NLMSG_ALIGN(rta->rta_len);
- /* family */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &family, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- if (rport) {
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &rport, 2);
- off += NLMSG_ALIGN(rta->rta_len);
- }
- nest->rta_len = off - nest_start;
- }
- do_nl_req(fd, nh, off, 0);
- return 0;
- }
- int main(int argc, char *argv[])
- {
- int events_mcast_grp;
- int pm_family;
- int fd;
- if (argc < 2)
- syntax(argv);
- fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
- if (fd == -1)
- error(1, errno, "socket netlink");
- resolve_mptcp_pm_netlink(fd, &pm_family, &events_mcast_grp);
- if (!strcmp(argv[1], "add"))
- return add_addr(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "ann"))
- return announce_addr(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "rem"))
- return remove_addr(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "csf"))
- return csf(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "dsf"))
- return dsf(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "del"))
- return del_addr(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "flush"))
- return flush_addrs(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "get"))
- return get_addr(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "dump"))
- return dump_addrs(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "limits"))
- return get_set_limits(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "set"))
- return set_flags(fd, pm_family, argc, argv);
- else if (!strcmp(argv[1], "events"))
- return capture_events(fd, events_mcast_grp);
- else if (!strcmp(argv[1], "listen"))
- return add_listener(argc, argv);
- fprintf(stderr, "unknown sub-command: %s", argv[1]);
- syntax(argv);
- return 0;
- }
|