cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pm_nl_ctl.c (39675B)


      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}