1887bd61bd9a5f5818a7e06e47ecb627bac35205
[platform/kernel/linux-rpi.git] / tools / testing / selftests / net / mptcp / pm_nl_ctl.c
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
32 static void syntax(char *argv[])
33 {
34         fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]);
35         fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n");
36         fprintf(stderr, "\tann <local-ip> id <local-id> token <token> [port <local-port>] [dev <name>]\n");
37         fprintf(stderr, "\trem id <local-id> token <token>\n");
38         fprintf(stderr, "\tcsf lip <local-ip> lid <local-id> rip <remote-ip> rport <remote-port> token <token>\n");
39         fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n");
40         fprintf(stderr, "\tdel <id> [<ip>]\n");
41         fprintf(stderr, "\tget <id>\n");
42         fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>] [token <token>] [rip <ip>] [rport <port>]\n");
43         fprintf(stderr, "\tflush\n");
44         fprintf(stderr, "\tdump\n");
45         fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
46         fprintf(stderr, "\tevents\n");
47         fprintf(stderr, "\tlisten <local-ip> <local-port>\n");
48         exit(0);
49 }
50
51 static 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
69 static 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
99 static 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  */
202 static 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
234 static 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
303 static 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
328 int 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 = strtoul(params[4], NULL, 10);
429         rta = (void *)(data + off);
430         rta->rta_type = MPTCP_PM_ATTR_TOKEN;
431         rta->rta_len = RTA_LENGTH(4);
432         memcpy(RTA_DATA(rta), &token, 4);
433         off += NLMSG_ALIGN(rta->rta_len);
434
435         do_nl_req(fd, nh, off, 0);
436
437         return 0;
438 }
439
440 int 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 = strtoul(params[4], NULL, 10);
555         rta = (void *)(data + off);
556         rta->rta_type = MPTCP_PM_ATTR_TOKEN;
557         rta->rta_len = RTA_LENGTH(4);
558         memcpy(RTA_DATA(rta), &token, 4);
559         off += NLMSG_ALIGN(rta->rta_len);
560
561         do_nl_req(fd, nh, off, 0);
562
563         return 0;
564 }
565
566 int 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 = strtoul(argv[arg], NULL, 10);
602                         rta = (void *)(data + off);
603                         rta->rta_type = MPTCP_PM_ATTR_TOKEN;
604                         rta->rta_len = RTA_LENGTH(4);
605                         memcpy(RTA_DATA(rta), &token, 4);
606                         off += NLMSG_ALIGN(rta->rta_len);
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
615 int 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 = strtoul(argv[arg], NULL, 10);
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
742 int 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
873 int 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
941 static 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
1037 static void print_addrs(struct nlmsghdr *nh, int pm_family, int total_len)
1038 {
1039         struct rtattr *attrs;
1040
1041         for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
1042                 int len = nh->nlmsg_len;
1043
1044                 if (nh->nlmsg_type == NLMSG_DONE)
1045                         break;
1046                 if (nh->nlmsg_type == NLMSG_ERROR)
1047                         nl_error(nh);
1048                 if (nh->nlmsg_type != pm_family)
1049                         continue;
1050
1051                 len -= NLMSG_LENGTH(GENL_HDRLEN);
1052                 attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
1053                                            GENL_HDRLEN);
1054                 while (RTA_OK(attrs, len)) {
1055                         if (attrs->rta_type ==
1056                             (MPTCP_PM_ATTR_ADDR | NLA_F_NESTED))
1057                                 print_addr((void *)RTA_DATA(attrs),
1058                                            attrs->rta_len);
1059                         attrs = RTA_NEXT(attrs, len);
1060                 }
1061         }
1062 }
1063
1064 int get_addr(int fd, int pm_family, int argc, char *argv[])
1065 {
1066         char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1067                   NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1068                   1024];
1069         struct rtattr *rta, *nest;
1070         struct nlmsghdr *nh;
1071         int nest_start;
1072         u_int8_t id;
1073         int off = 0;
1074
1075         memset(data, 0, sizeof(data));
1076         nh = (void *)data;
1077         off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
1078                             MPTCP_PM_VER);
1079
1080         /* the only argument is the address id */
1081         if (argc != 3)
1082                 syntax(argv);
1083
1084         id = atoi(argv[2]);
1085
1086         nest_start = off;
1087         nest = (void *)(data + off);
1088         nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
1089         nest->rta_len =  RTA_LENGTH(0);
1090         off += NLMSG_ALIGN(nest->rta_len);
1091
1092         /* build a dummy addr with only the ID set */
1093         rta = (void *)(data + off);
1094         rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
1095         rta->rta_len = RTA_LENGTH(1);
1096         memcpy(RTA_DATA(rta), &id, 1);
1097         off += NLMSG_ALIGN(rta->rta_len);
1098         nest->rta_len = off - nest_start;
1099
1100         print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
1101         return 0;
1102 }
1103
1104 int dump_addrs(int fd, int pm_family, int argc, char *argv[])
1105 {
1106         char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1107                   NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1108                   1024];
1109         pid_t pid = getpid();
1110         struct nlmsghdr *nh;
1111         int off = 0;
1112
1113         memset(data, 0, sizeof(data));
1114         nh = (void *)data;
1115         off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
1116                             MPTCP_PM_VER);
1117         nh->nlmsg_flags |= NLM_F_DUMP;
1118         nh->nlmsg_seq = 1;
1119         nh->nlmsg_pid = pid;
1120         nh->nlmsg_len = off;
1121
1122         print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
1123         return 0;
1124 }
1125
1126 int flush_addrs(int fd, int pm_family, int argc, char *argv[])
1127 {
1128         char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1129                   NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1130                   1024];
1131         struct nlmsghdr *nh;
1132         int off = 0;
1133
1134         memset(data, 0, sizeof(data));
1135         nh = (void *)data;
1136         off = init_genl_req(data, pm_family, MPTCP_PM_CMD_FLUSH_ADDRS,
1137                             MPTCP_PM_VER);
1138
1139         do_nl_req(fd, nh, off, 0);
1140         return 0;
1141 }
1142
1143 static void print_limits(struct nlmsghdr *nh, int pm_family, int total_len)
1144 {
1145         struct rtattr *attrs;
1146         uint32_t max;
1147
1148         for (; NLMSG_OK(nh, total_len); nh = NLMSG_NEXT(nh, total_len)) {
1149                 int len = nh->nlmsg_len;
1150
1151                 if (nh->nlmsg_type == NLMSG_DONE)
1152                         break;
1153                 if (nh->nlmsg_type == NLMSG_ERROR)
1154                         nl_error(nh);
1155                 if (nh->nlmsg_type != pm_family)
1156                         continue;
1157
1158                 len -= NLMSG_LENGTH(GENL_HDRLEN);
1159                 attrs = (struct rtattr *) ((char *) NLMSG_DATA(nh) +
1160                                            GENL_HDRLEN);
1161                 while (RTA_OK(attrs, len)) {
1162                         int type = attrs->rta_type;
1163
1164                         if (type != MPTCP_PM_ATTR_RCV_ADD_ADDRS &&
1165                             type != MPTCP_PM_ATTR_SUBFLOWS)
1166                                 goto next;
1167
1168                         memcpy(&max, RTA_DATA(attrs), 4);
1169                         printf("%s %u\n", type == MPTCP_PM_ATTR_SUBFLOWS ?
1170                                           "subflows" : "accept", max);
1171
1172 next:
1173                         attrs = RTA_NEXT(attrs, len);
1174                 }
1175         }
1176 }
1177
1178 int get_set_limits(int fd, int pm_family, int argc, char *argv[])
1179 {
1180         char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1181                   NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1182                   1024];
1183         uint32_t rcv_addr = 0, subflows = 0;
1184         int cmd, len = sizeof(data);
1185         struct nlmsghdr *nh;
1186         int off = 0;
1187
1188         /* limit */
1189         if (argc == 4) {
1190                 rcv_addr = atoi(argv[2]);
1191                 subflows = atoi(argv[3]);
1192                 cmd = MPTCP_PM_CMD_SET_LIMITS;
1193         } else {
1194                 cmd = MPTCP_PM_CMD_GET_LIMITS;
1195         }
1196
1197         memset(data, 0, sizeof(data));
1198         nh = (void *)data;
1199         off = init_genl_req(data, pm_family, cmd, MPTCP_PM_VER);
1200
1201         /* limit */
1202         if (cmd == MPTCP_PM_CMD_SET_LIMITS) {
1203                 struct rtattr *rta = (void *)(data + off);
1204
1205                 rta->rta_type = MPTCP_PM_ATTR_RCV_ADD_ADDRS;
1206                 rta->rta_len = RTA_LENGTH(4);
1207                 memcpy(RTA_DATA(rta), &rcv_addr, 4);
1208                 off += NLMSG_ALIGN(rta->rta_len);
1209
1210                 rta = (void *)(data + off);
1211                 rta->rta_type = MPTCP_PM_ATTR_SUBFLOWS;
1212                 rta->rta_len = RTA_LENGTH(4);
1213                 memcpy(RTA_DATA(rta), &subflows, 4);
1214                 off += NLMSG_ALIGN(rta->rta_len);
1215
1216                 /* do not expect a reply */
1217                 len = 0;
1218         }
1219
1220         len = do_nl_req(fd, nh, off, len);
1221         if (cmd == MPTCP_PM_CMD_GET_LIMITS)
1222                 print_limits(nh, pm_family, len);
1223         return 0;
1224 }
1225
1226 int add_listener(int argc, char *argv[])
1227 {
1228         struct sockaddr_storage addr;
1229         struct sockaddr_in6 *a6;
1230         struct sockaddr_in *a4;
1231         u_int16_t family;
1232         int enable = 1;
1233         int sock;
1234         int err;
1235
1236         if (argc < 4)
1237                 syntax(argv);
1238
1239         memset(&addr, 0, sizeof(struct sockaddr_storage));
1240         a4 = (struct sockaddr_in *)&addr;
1241         a6 = (struct sockaddr_in6 *)&addr;
1242
1243         if (inet_pton(AF_INET, argv[2], &a4->sin_addr)) {
1244                 family = AF_INET;
1245                 a4->sin_family = family;
1246                 a4->sin_port = htons(atoi(argv[3]));
1247         } else if (inet_pton(AF_INET6, argv[2], &a6->sin6_addr)) {
1248                 family = AF_INET6;
1249                 a6->sin6_family = family;
1250                 a6->sin6_port = htons(atoi(argv[3]));
1251         } else
1252                 error(1, errno, "can't parse ip %s", argv[2]);
1253
1254         sock = socket(family, SOCK_STREAM, IPPROTO_MPTCP);
1255         if (sock < 0)
1256                 error(1, errno, "can't create listener sock\n");
1257
1258         if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) {
1259                 close(sock);
1260                 error(1, errno, "can't set SO_REUSEADDR on listener sock\n");
1261         }
1262
1263         err = bind(sock, (struct sockaddr *)&addr,
1264                    ((family == AF_INET) ? sizeof(struct sockaddr_in) :
1265                     sizeof(struct sockaddr_in6)));
1266
1267         if (err == 0 && listen(sock, 30) == 0)
1268                 pause();
1269
1270         close(sock);
1271         return 0;
1272 }
1273
1274 int set_flags(int fd, int pm_family, int argc, char *argv[])
1275 {
1276         char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1277                   NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1278                   1024];
1279         struct rtattr *rta, *nest;
1280         struct nlmsghdr *nh;
1281         u_int32_t flags = 0;
1282         u_int32_t token = 0;
1283         u_int16_t rport = 0;
1284         u_int16_t family;
1285         void *rip = NULL;
1286         int nest_start;
1287         int use_id = 0;
1288         u_int8_t id;
1289         int off = 0;
1290         int arg = 2;
1291
1292         memset(data, 0, sizeof(data));
1293         nh = (void *)data;
1294         off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS,
1295                             MPTCP_PM_VER);
1296
1297         if (argc < 3)
1298                 syntax(argv);
1299
1300         nest_start = off;
1301         nest = (void *)(data + off);
1302         nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
1303         nest->rta_len = RTA_LENGTH(0);
1304         off += NLMSG_ALIGN(nest->rta_len);
1305
1306         if (!strcmp(argv[arg], "id")) {
1307                 if (++arg >= argc)
1308                         error(1, 0, " missing id value");
1309
1310                 use_id = 1;
1311                 id = atoi(argv[arg]);
1312                 rta = (void *)(data + off);
1313                 rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
1314                 rta->rta_len = RTA_LENGTH(1);
1315                 memcpy(RTA_DATA(rta), &id, 1);
1316                 off += NLMSG_ALIGN(rta->rta_len);
1317         } else {
1318                 /* addr data */
1319                 rta = (void *)(data + off);
1320                 if (inet_pton(AF_INET, argv[arg], RTA_DATA(rta))) {
1321                         family = AF_INET;
1322                         rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
1323                         rta->rta_len = RTA_LENGTH(4);
1324                 } else if (inet_pton(AF_INET6, argv[arg], RTA_DATA(rta))) {
1325                         family = AF_INET6;
1326                         rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
1327                         rta->rta_len = RTA_LENGTH(16);
1328                 } else {
1329                         error(1, errno, "can't parse ip %s", argv[arg]);
1330                 }
1331                 off += NLMSG_ALIGN(rta->rta_len);
1332
1333                 /* family */
1334                 rta = (void *)(data + off);
1335                 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
1336                 rta->rta_len = RTA_LENGTH(2);
1337                 memcpy(RTA_DATA(rta), &family, 2);
1338                 off += NLMSG_ALIGN(rta->rta_len);
1339         }
1340
1341         if (++arg >= argc)
1342                 error(1, 0, " missing flags keyword");
1343
1344         for (; arg < argc; arg++) {
1345                 if (!strcmp(argv[arg], "token")) {
1346                         if (++arg >= argc)
1347                                 error(1, 0, " missing token value");
1348
1349                         /* token */
1350                         token = strtoul(argv[arg], NULL, 10);
1351                 } else if (!strcmp(argv[arg], "flags")) {
1352                         char *tok, *str;
1353
1354                         /* flags */
1355                         if (++arg >= argc)
1356                                 error(1, 0, " missing flags value");
1357
1358                         for (str = argv[arg]; (tok = strtok(str, ","));
1359                              str = NULL) {
1360                                 if (!strcmp(tok, "backup"))
1361                                         flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
1362                                 else if (!strcmp(tok, "fullmesh"))
1363                                         flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
1364                                 else if (strcmp(tok, "nobackup") &&
1365                                          strcmp(tok, "nofullmesh"))
1366                                         error(1, errno,
1367                                               "unknown flag %s", argv[arg]);
1368                         }
1369
1370                         rta = (void *)(data + off);
1371                         rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
1372                         rta->rta_len = RTA_LENGTH(4);
1373                         memcpy(RTA_DATA(rta), &flags, 4);
1374                         off += NLMSG_ALIGN(rta->rta_len);
1375                 } else if (!strcmp(argv[arg], "port")) {
1376                         u_int16_t port;
1377
1378                         if (use_id)
1379                                 error(1, 0, " port can't be used with id");
1380
1381                         if (++arg >= argc)
1382                                 error(1, 0, " missing port value");
1383
1384                         port = atoi(argv[arg]);
1385                         rta = (void *)(data + off);
1386                         rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
1387                         rta->rta_len = RTA_LENGTH(2);
1388                         memcpy(RTA_DATA(rta), &port, 2);
1389                         off += NLMSG_ALIGN(rta->rta_len);
1390                 } else if (!strcmp(argv[arg], "rport")) {
1391                         if (++arg >= argc)
1392                                 error(1, 0, " missing remote port");
1393
1394                         rport = atoi(argv[arg]);
1395                 } else if (!strcmp(argv[arg], "rip")) {
1396                         if (++arg >= argc)
1397                                 error(1, 0, " missing remote ip");
1398
1399                         rip = argv[arg];
1400                 } else {
1401                         error(1, 0, "unknown keyword %s", argv[arg]);
1402                 }
1403         }
1404         nest->rta_len = off - nest_start;
1405
1406         /* token */
1407         if (token) {
1408                 rta = (void *)(data + off);
1409                 rta->rta_type = MPTCP_PM_ATTR_TOKEN;
1410                 rta->rta_len = RTA_LENGTH(4);
1411                 memcpy(RTA_DATA(rta), &token, 4);
1412                 off += NLMSG_ALIGN(rta->rta_len);
1413         }
1414
1415         /* remote addr/port */
1416         if (rip) {
1417                 nest_start = off;
1418                 nest = (void *)(data + off);
1419                 nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR_REMOTE;
1420                 nest->rta_len = RTA_LENGTH(0);
1421                 off += NLMSG_ALIGN(nest->rta_len);
1422
1423                 /* addr data */
1424                 rta = (void *)(data + off);
1425                 if (inet_pton(AF_INET, rip, RTA_DATA(rta))) {
1426                         family = AF_INET;
1427                         rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
1428                         rta->rta_len = RTA_LENGTH(4);
1429                 } else if (inet_pton(AF_INET6, rip, RTA_DATA(rta))) {
1430                         family = AF_INET6;
1431                         rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
1432                         rta->rta_len = RTA_LENGTH(16);
1433                 } else {
1434                         error(1, errno, "can't parse ip %s", (char *)rip);
1435                 }
1436                 off += NLMSG_ALIGN(rta->rta_len);
1437
1438                 /* family */
1439                 rta = (void *)(data + off);
1440                 rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
1441                 rta->rta_len = RTA_LENGTH(2);
1442                 memcpy(RTA_DATA(rta), &family, 2);
1443                 off += NLMSG_ALIGN(rta->rta_len);
1444
1445                 if (rport) {
1446                         rta = (void *)(data + off);
1447                         rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
1448                         rta->rta_len = RTA_LENGTH(2);
1449                         memcpy(RTA_DATA(rta), &rport, 2);
1450                         off += NLMSG_ALIGN(rta->rta_len);
1451                 }
1452
1453                 nest->rta_len = off - nest_start;
1454         }
1455
1456         do_nl_req(fd, nh, off, 0);
1457         return 0;
1458 }
1459
1460 int main(int argc, char *argv[])
1461 {
1462         int events_mcast_grp;
1463         int pm_family;
1464         int fd;
1465
1466         if (argc < 2)
1467                 syntax(argv);
1468
1469         fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
1470         if (fd == -1)
1471                 error(1, errno, "socket netlink");
1472
1473         resolve_mptcp_pm_netlink(fd, &pm_family, &events_mcast_grp);
1474
1475         if (!strcmp(argv[1], "add"))
1476                 return add_addr(fd, pm_family, argc, argv);
1477         else if (!strcmp(argv[1], "ann"))
1478                 return announce_addr(fd, pm_family, argc, argv);
1479         else if (!strcmp(argv[1], "rem"))
1480                 return remove_addr(fd, pm_family, argc, argv);
1481         else if (!strcmp(argv[1], "csf"))
1482                 return csf(fd, pm_family, argc, argv);
1483         else if (!strcmp(argv[1], "dsf"))
1484                 return dsf(fd, pm_family, argc, argv);
1485         else if (!strcmp(argv[1], "del"))
1486                 return del_addr(fd, pm_family, argc, argv);
1487         else if (!strcmp(argv[1], "flush"))
1488                 return flush_addrs(fd, pm_family, argc, argv);
1489         else if (!strcmp(argv[1], "get"))
1490                 return get_addr(fd, pm_family, argc, argv);
1491         else if (!strcmp(argv[1], "dump"))
1492                 return dump_addrs(fd, pm_family, argc, argv);
1493         else if (!strcmp(argv[1], "limits"))
1494                 return get_set_limits(fd, pm_family, argc, argv);
1495         else if (!strcmp(argv[1], "set"))
1496                 return set_flags(fd, pm_family, argc, argv);
1497         else if (!strcmp(argv[1], "events"))
1498                 return capture_events(fd, events_mcast_grp);
1499         else if (!strcmp(argv[1], "listen"))
1500                 return add_listener(argc, argv);
1501
1502         fprintf(stderr, "unknown sub-command: %s", argv[1]);
1503         syntax(argv);
1504         return 0;
1505 }