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