]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/ipila.c
lib/libnetlink: update rtnl_talk to support malloc buff at run time
[mirror_iproute2.git] / ip / ipila.c
CommitLineData
ec71cae0
TH
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
26static 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 */
39static struct rtnl_handle genl_rth = { .fd = -1 };
40static 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
51static 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
75static 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
94static 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
126static 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
149static int ila_parse_opt(int argc, char **argv, struct nlmsghdr *n,
150 bool adding)
151{
2d01b393
TH
152 __u64 locator = 0;
153 __u64 locator_match = 0;
ec71cae0
TH
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
2d01b393
TH
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);
ec71cae0
TH
210
211 if (ifindex_set)
212 addattr32(n, 1024, ILA_ATTR_IFINDEX, ifindex);
213
214 return 0;
215}
216
217static 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
86bf43c7 223 if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
ec71cae0
TH
224 return -2;
225
226 return 0;
227}
228
229static 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
86bf43c7 235 if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
ec71cae0
TH
236 return -2;
237
238 return 0;
239}
240
241int do_ipila(int argc, char **argv)
242{
ec71cae0
TH
243 if (argc < 1)
244 usage();
245
9423a324
SD
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
ec71cae0
TH
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);
ec71cae0
TH
258
259 fprintf(stderr, "Command \"%s\" is unknown, try \"ip ila help\".\n",
260 *argv);
261 exit(-1);
262}