1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * ipila.c ILA (Identifier Locator Addressing) support
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Authors: Tom Herbert <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker */
11*de1e4e89SAndroid Build Coastguard Worker
12*de1e4e89SAndroid Build Coastguard Worker #include <netdb.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <net/if.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <linux/ila.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <linux/genetlink.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <linux/ip.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
21*de1e4e89SAndroid Build Coastguard Worker
22*de1e4e89SAndroid Build Coastguard Worker #include "libgenl.h"
23*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
24*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
25*de1e4e89SAndroid Build Coastguard Worker
usage(void)26*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
27*de1e4e89SAndroid Build Coastguard Worker {
28*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ip ila add loc_match LOCATOR_MATCH "
29*de1e4e89SAndroid Build Coastguard Worker "loc LOCATOR [ dev DEV ]\n");
30*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip ila del loc_match LOCATOR_MATCH "
31*de1e4e89SAndroid Build Coastguard Worker "[ loc LOCATOR ] [ dev DEV ]\n");
32*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip ila list\n");
33*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\n");
34*de1e4e89SAndroid Build Coastguard Worker
35*de1e4e89SAndroid Build Coastguard Worker exit(-1);
36*de1e4e89SAndroid Build Coastguard Worker }
37*de1e4e89SAndroid Build Coastguard Worker
38*de1e4e89SAndroid Build Coastguard Worker /* netlink socket */
39*de1e4e89SAndroid Build Coastguard Worker static struct rtnl_handle genl_rth = { .fd = -1 };
40*de1e4e89SAndroid Build Coastguard Worker static int genl_family = -1;
41*de1e4e89SAndroid Build Coastguard Worker
42*de1e4e89SAndroid Build Coastguard Worker #define ILA_REQUEST(_req, _bufsiz, _cmd, _flags) \
43*de1e4e89SAndroid Build Coastguard Worker GENL_REQUEST(_req, _bufsiz, genl_family, 0, \
44*de1e4e89SAndroid Build Coastguard Worker ILA_GENL_VERSION, _cmd, _flags)
45*de1e4e89SAndroid Build Coastguard Worker
46*de1e4e89SAndroid Build Coastguard Worker #define ILA_RTA(g) ((struct rtattr *)(((char *)(g)) + \
47*de1e4e89SAndroid Build Coastguard Worker NLMSG_ALIGN(sizeof(struct genlmsghdr))))
48*de1e4e89SAndroid Build Coastguard Worker
49*de1e4e89SAndroid Build Coastguard Worker #define ADDR_BUF_SIZE sizeof("xxxx:xxxx:xxxx:xxxx")
50*de1e4e89SAndroid Build Coastguard Worker
print_addr64(__u64 addr,char * buff,size_t len)51*de1e4e89SAndroid Build Coastguard Worker static int print_addr64(__u64 addr, char *buff, size_t len)
52*de1e4e89SAndroid Build Coastguard Worker {
53*de1e4e89SAndroid Build Coastguard Worker __u16 *words = (__u16 *)&addr;
54*de1e4e89SAndroid Build Coastguard Worker __u16 v;
55*de1e4e89SAndroid Build Coastguard Worker int i, ret;
56*de1e4e89SAndroid Build Coastguard Worker size_t written = 0;
57*de1e4e89SAndroid Build Coastguard Worker char *sep = ":";
58*de1e4e89SAndroid Build Coastguard Worker
59*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < 4; i++) {
60*de1e4e89SAndroid Build Coastguard Worker v = ntohs(words[i]);
61*de1e4e89SAndroid Build Coastguard Worker
62*de1e4e89SAndroid Build Coastguard Worker if (i == 3)
63*de1e4e89SAndroid Build Coastguard Worker sep = "";
64*de1e4e89SAndroid Build Coastguard Worker
65*de1e4e89SAndroid Build Coastguard Worker ret = snprintf(&buff[written], len - written, "%x%s", v, sep);
66*de1e4e89SAndroid Build Coastguard Worker if (ret < 0)
67*de1e4e89SAndroid Build Coastguard Worker return ret;
68*de1e4e89SAndroid Build Coastguard Worker
69*de1e4e89SAndroid Build Coastguard Worker written += ret;
70*de1e4e89SAndroid Build Coastguard Worker }
71*de1e4e89SAndroid Build Coastguard Worker
72*de1e4e89SAndroid Build Coastguard Worker return written;
73*de1e4e89SAndroid Build Coastguard Worker }
74*de1e4e89SAndroid Build Coastguard Worker
print_ila_locid(FILE * fp,int attr,struct rtattr * tb[],int space)75*de1e4e89SAndroid Build Coastguard Worker static void print_ila_locid(FILE *fp, int attr, struct rtattr *tb[], int space)
76*de1e4e89SAndroid Build Coastguard Worker {
77*de1e4e89SAndroid Build Coastguard Worker char abuf[256];
78*de1e4e89SAndroid Build Coastguard Worker size_t blen;
79*de1e4e89SAndroid Build Coastguard Worker int i;
80*de1e4e89SAndroid Build Coastguard Worker
81*de1e4e89SAndroid Build Coastguard Worker if (tb[attr]) {
82*de1e4e89SAndroid Build Coastguard Worker blen = print_addr64(rta_getattr_u32(tb[attr]),
83*de1e4e89SAndroid Build Coastguard Worker abuf, sizeof(abuf));
84*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%s", abuf);
85*de1e4e89SAndroid Build Coastguard Worker } else {
86*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "-");
87*de1e4e89SAndroid Build Coastguard Worker blen = 1;
88*de1e4e89SAndroid Build Coastguard Worker }
89*de1e4e89SAndroid Build Coastguard Worker
90*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < space - blen; i++)
91*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, " ");
92*de1e4e89SAndroid Build Coastguard Worker }
93*de1e4e89SAndroid Build Coastguard Worker
print_ila_mapping(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)94*de1e4e89SAndroid Build Coastguard Worker static int print_ila_mapping(const struct sockaddr_nl *who,
95*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *n, void *arg)
96*de1e4e89SAndroid Build Coastguard Worker {
97*de1e4e89SAndroid Build Coastguard Worker FILE *fp = (FILE *)arg;
98*de1e4e89SAndroid Build Coastguard Worker struct genlmsghdr *ghdr;
99*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[ILA_ATTR_MAX + 1];
100*de1e4e89SAndroid Build Coastguard Worker int len = n->nlmsg_len;
101*de1e4e89SAndroid Build Coastguard Worker
102*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type != genl_family)
103*de1e4e89SAndroid Build Coastguard Worker return 0;
104*de1e4e89SAndroid Build Coastguard Worker
105*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_LENGTH(GENL_HDRLEN);
106*de1e4e89SAndroid Build Coastguard Worker if (len < 0)
107*de1e4e89SAndroid Build Coastguard Worker return -1;
108*de1e4e89SAndroid Build Coastguard Worker
109*de1e4e89SAndroid Build Coastguard Worker ghdr = NLMSG_DATA(n);
110*de1e4e89SAndroid Build Coastguard Worker parse_rtattr(tb, ILA_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len);
111*de1e4e89SAndroid Build Coastguard Worker
112*de1e4e89SAndroid Build Coastguard Worker print_ila_locid(fp, ILA_ATTR_LOCATOR_MATCH, tb, ADDR_BUF_SIZE);
113*de1e4e89SAndroid Build Coastguard Worker print_ila_locid(fp, ILA_ATTR_LOCATOR, tb, ADDR_BUF_SIZE);
114*de1e4e89SAndroid Build Coastguard Worker
115*de1e4e89SAndroid Build Coastguard Worker if (tb[ILA_ATTR_IFINDEX])
116*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%s", ll_index_to_name(rta_getattr_u32(tb[ILA_ATTR_IFINDEX])));
117*de1e4e89SAndroid Build Coastguard Worker else
118*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "-");
119*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
120*de1e4e89SAndroid Build Coastguard Worker
121*de1e4e89SAndroid Build Coastguard Worker return 0;
122*de1e4e89SAndroid Build Coastguard Worker }
123*de1e4e89SAndroid Build Coastguard Worker
124*de1e4e89SAndroid Build Coastguard Worker #define NLMSG_BUF_SIZE 4096
125*de1e4e89SAndroid Build Coastguard Worker
do_list(int argc,char ** argv)126*de1e4e89SAndroid Build Coastguard Worker static int do_list(int argc, char **argv)
127*de1e4e89SAndroid Build Coastguard Worker {
128*de1e4e89SAndroid Build Coastguard Worker ILA_REQUEST(req, 1024, ILA_CMD_GET, NLM_F_REQUEST | NLM_F_DUMP);
129*de1e4e89SAndroid Build Coastguard Worker
130*de1e4e89SAndroid Build Coastguard Worker if (argc > 0) {
131*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"ip ila show\" does not take "
132*de1e4e89SAndroid Build Coastguard Worker "any arguments.\n");
133*de1e4e89SAndroid Build Coastguard Worker return -1;
134*de1e4e89SAndroid Build Coastguard Worker }
135*de1e4e89SAndroid Build Coastguard Worker
136*de1e4e89SAndroid Build Coastguard Worker if (rtnl_send(&genl_rth, (void *)&req, req.n.nlmsg_len) < 0) {
137*de1e4e89SAndroid Build Coastguard Worker perror("Cannot send dump request");
138*de1e4e89SAndroid Build Coastguard Worker exit(1);
139*de1e4e89SAndroid Build Coastguard Worker }
140*de1e4e89SAndroid Build Coastguard Worker
141*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dump_filter(&genl_rth, print_ila_mapping, stdout) < 0) {
142*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Dump terminated\n");
143*de1e4e89SAndroid Build Coastguard Worker return 1;
144*de1e4e89SAndroid Build Coastguard Worker }
145*de1e4e89SAndroid Build Coastguard Worker
146*de1e4e89SAndroid Build Coastguard Worker return 0;
147*de1e4e89SAndroid Build Coastguard Worker }
148*de1e4e89SAndroid Build Coastguard Worker
ila_parse_opt(int argc,char ** argv,struct nlmsghdr * n,bool adding)149*de1e4e89SAndroid Build Coastguard Worker static int ila_parse_opt(int argc, char **argv, struct nlmsghdr *n,
150*de1e4e89SAndroid Build Coastguard Worker bool adding)
151*de1e4e89SAndroid Build Coastguard Worker {
152*de1e4e89SAndroid Build Coastguard Worker __u64 locator = 0;
153*de1e4e89SAndroid Build Coastguard Worker __u64 locator_match = 0;
154*de1e4e89SAndroid Build Coastguard Worker int ifindex = 0;
155*de1e4e89SAndroid Build Coastguard Worker bool loc_set = false;
156*de1e4e89SAndroid Build Coastguard Worker bool loc_match_set = false;
157*de1e4e89SAndroid Build Coastguard Worker bool ifindex_set = false;
158*de1e4e89SAndroid Build Coastguard Worker
159*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
160*de1e4e89SAndroid Build Coastguard Worker if (!matches(*argv, "loc")) {
161*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
162*de1e4e89SAndroid Build Coastguard Worker
163*de1e4e89SAndroid Build Coastguard Worker if (get_addr64(&locator, *argv) < 0) {
164*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Bad locator: %s\n", *argv);
165*de1e4e89SAndroid Build Coastguard Worker return -1;
166*de1e4e89SAndroid Build Coastguard Worker }
167*de1e4e89SAndroid Build Coastguard Worker loc_set = true;
168*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "loc_match")) {
169*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
170*de1e4e89SAndroid Build Coastguard Worker
171*de1e4e89SAndroid Build Coastguard Worker if (get_addr64(&locator_match, *argv) < 0) {
172*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Bad locator to match: %s\n",
173*de1e4e89SAndroid Build Coastguard Worker *argv);
174*de1e4e89SAndroid Build Coastguard Worker return -1;
175*de1e4e89SAndroid Build Coastguard Worker }
176*de1e4e89SAndroid Build Coastguard Worker loc_match_set = true;
177*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "dev")) {
178*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
179*de1e4e89SAndroid Build Coastguard Worker
180*de1e4e89SAndroid Build Coastguard Worker ifindex = ll_name_to_index(*argv);
181*de1e4e89SAndroid Build Coastguard Worker if (ifindex == 0) {
182*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "No such interface: %s\n",
183*de1e4e89SAndroid Build Coastguard Worker *argv);
184*de1e4e89SAndroid Build Coastguard Worker return -1;
185*de1e4e89SAndroid Build Coastguard Worker }
186*de1e4e89SAndroid Build Coastguard Worker ifindex_set = true;
187*de1e4e89SAndroid Build Coastguard Worker } else {
188*de1e4e89SAndroid Build Coastguard Worker usage();
189*de1e4e89SAndroid Build Coastguard Worker return -1;
190*de1e4e89SAndroid Build Coastguard Worker }
191*de1e4e89SAndroid Build Coastguard Worker argc--, argv++;
192*de1e4e89SAndroid Build Coastguard Worker }
193*de1e4e89SAndroid Build Coastguard Worker
194*de1e4e89SAndroid Build Coastguard Worker if (adding) {
195*de1e4e89SAndroid Build Coastguard Worker if (!loc_set) {
196*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ila: missing locator\n");
197*de1e4e89SAndroid Build Coastguard Worker return -1;
198*de1e4e89SAndroid Build Coastguard Worker }
199*de1e4e89SAndroid Build Coastguard Worker if (!loc_match_set) {
200*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ila: missing locator0match\n");
201*de1e4e89SAndroid Build Coastguard Worker return -1;
202*de1e4e89SAndroid Build Coastguard Worker }
203*de1e4e89SAndroid Build Coastguard Worker }
204*de1e4e89SAndroid Build Coastguard Worker
205*de1e4e89SAndroid Build Coastguard Worker if (loc_match_set)
206*de1e4e89SAndroid Build Coastguard Worker addattr64(n, 1024, ILA_ATTR_LOCATOR_MATCH, locator_match);
207*de1e4e89SAndroid Build Coastguard Worker
208*de1e4e89SAndroid Build Coastguard Worker if (loc_set)
209*de1e4e89SAndroid Build Coastguard Worker addattr64(n, 1024, ILA_ATTR_LOCATOR, locator);
210*de1e4e89SAndroid Build Coastguard Worker
211*de1e4e89SAndroid Build Coastguard Worker if (ifindex_set)
212*de1e4e89SAndroid Build Coastguard Worker addattr32(n, 1024, ILA_ATTR_IFINDEX, ifindex);
213*de1e4e89SAndroid Build Coastguard Worker
214*de1e4e89SAndroid Build Coastguard Worker return 0;
215*de1e4e89SAndroid Build Coastguard Worker }
216*de1e4e89SAndroid Build Coastguard Worker
do_add(int argc,char ** argv)217*de1e4e89SAndroid Build Coastguard Worker static int do_add(int argc, char **argv)
218*de1e4e89SAndroid Build Coastguard Worker {
219*de1e4e89SAndroid Build Coastguard Worker ILA_REQUEST(req, 1024, ILA_CMD_ADD, NLM_F_REQUEST);
220*de1e4e89SAndroid Build Coastguard Worker
221*de1e4e89SAndroid Build Coastguard Worker ila_parse_opt(argc, argv, &req.n, true);
222*de1e4e89SAndroid Build Coastguard Worker
223*de1e4e89SAndroid Build Coastguard Worker if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
224*de1e4e89SAndroid Build Coastguard Worker return -2;
225*de1e4e89SAndroid Build Coastguard Worker
226*de1e4e89SAndroid Build Coastguard Worker return 0;
227*de1e4e89SAndroid Build Coastguard Worker }
228*de1e4e89SAndroid Build Coastguard Worker
do_del(int argc,char ** argv)229*de1e4e89SAndroid Build Coastguard Worker static int do_del(int argc, char **argv)
230*de1e4e89SAndroid Build Coastguard Worker {
231*de1e4e89SAndroid Build Coastguard Worker ILA_REQUEST(req, 1024, ILA_CMD_DEL, NLM_F_REQUEST);
232*de1e4e89SAndroid Build Coastguard Worker
233*de1e4e89SAndroid Build Coastguard Worker ila_parse_opt(argc, argv, &req.n, false);
234*de1e4e89SAndroid Build Coastguard Worker
235*de1e4e89SAndroid Build Coastguard Worker if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
236*de1e4e89SAndroid Build Coastguard Worker return -2;
237*de1e4e89SAndroid Build Coastguard Worker
238*de1e4e89SAndroid Build Coastguard Worker return 0;
239*de1e4e89SAndroid Build Coastguard Worker }
240*de1e4e89SAndroid Build Coastguard Worker
do_ipila(int argc,char ** argv)241*de1e4e89SAndroid Build Coastguard Worker int do_ipila(int argc, char **argv)
242*de1e4e89SAndroid Build Coastguard Worker {
243*de1e4e89SAndroid Build Coastguard Worker if (argc < 1)
244*de1e4e89SAndroid Build Coastguard Worker usage();
245*de1e4e89SAndroid Build Coastguard Worker
246*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "help") == 0)
247*de1e4e89SAndroid Build Coastguard Worker usage();
248*de1e4e89SAndroid Build Coastguard Worker
249*de1e4e89SAndroid Build Coastguard Worker if (genl_init_handle(&genl_rth, ILA_GENL_NAME, &genl_family))
250*de1e4e89SAndroid Build Coastguard Worker exit(1);
251*de1e4e89SAndroid Build Coastguard Worker
252*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "add") == 0)
253*de1e4e89SAndroid Build Coastguard Worker return do_add(argc-1, argv+1);
254*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "delete") == 0)
255*de1e4e89SAndroid Build Coastguard Worker return do_del(argc-1, argv+1);
256*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "list") == 0)
257*de1e4e89SAndroid Build Coastguard Worker return do_list(argc-1, argv+1);
258*de1e4e89SAndroid Build Coastguard Worker
259*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Command \"%s\" is unknown, try \"ip ila help\".\n",
260*de1e4e89SAndroid Build Coastguard Worker *argv);
261*de1e4e89SAndroid Build Coastguard Worker exit(-1);
262*de1e4e89SAndroid Build Coastguard Worker }
263