]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/link_vti.c
lib/libnetlink: re malloc buff if size is not enough
[mirror_iproute2.git] / ip / link_vti.c
CommitLineData
73579339
S
1/*
2 * link_vti.c VTI driver module
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: Herbert Xu <herbert@gondor.apana.org.au>
10 * Saurabh Mohan <saurabh.mohan@vyatta.com> Modified link_gre.c for VTI
11 */
12
13#include <string.h>
14#include <net/if.h>
15#include <sys/types.h>
16#include <sys/socket.h>
17#include <arpa/inet.h>
18
19#include <linux/ip.h>
20#include <linux/if_tunnel.h>
21#include "rt_names.h"
22#include "utils.h"
23#include "ip_common.h"
24#include "tunnel.h"
25
26
561e650e 27static void print_usage(FILE *f)
28{
8b471354
PS
29 fprintf(f,
30 "Usage: ... vti [ remote ADDR ]\n"
31 " [ local ADDR ]\n"
32 " [ [i|o]key KEY ]\n"
33 " [ dev PHYS_DEV ]\n"
ad4b1425 34 " [ fwmark MARK ]\n"
8b471354
PS
35 "\n"
36 "Where: ADDR := { IP_ADDRESS }\n"
37 " KEY := { DOTTED_QUAD | NUMBER }\n"
ad4b1425 38 " MARK := { 0x0..0xffffffff }\n"
8b471354 39 );
561e650e 40}
41
73579339
S
42static void usage(void) __attribute__((noreturn));
43static void usage(void)
44{
561e650e 45 print_usage(stderr);
73579339
S
46 exit(-1);
47}
48
49static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
50 struct nlmsghdr *n)
51{
d17b136f 52 struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
73579339
S
53 struct {
54 struct nlmsghdr n;
55 struct ifinfomsg i;
56 char buf[1024];
d17b136f
PS
57 } req = {
58 .n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
59 .n.nlmsg_flags = NLM_F_REQUEST,
60 .n.nlmsg_type = RTM_GETLINK,
61 .i.ifi_family = preferred_family,
62 .i.ifi_index = ifi->ifi_index,
63 };
73579339
S
64 struct rtattr *tb[IFLA_MAX + 1];
65 struct rtattr *linkinfo[IFLA_INFO_MAX+1];
66 struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
56f5daac
SH
67 unsigned int ikey = 0;
68 unsigned int okey = 0;
69 unsigned int saddr = 0;
70 unsigned int daddr = 0;
71 unsigned int link = 0;
ad4b1425 72 unsigned int fwmark = 0;
73579339
S
73 int len;
74
75 if (!(n->nlmsg_flags & NLM_F_CREATE)) {
c079e121 76 if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
73579339
S
77get_failed:
78 fprintf(stderr,
79 "Failed to get existing tunnel info.\n");
80 return -1;
81 }
82
83 len = req.n.nlmsg_len;
84 len -= NLMSG_LENGTH(sizeof(*ifi));
85 if (len < 0)
86 goto get_failed;
87
88 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
89
90 if (!tb[IFLA_LINKINFO])
91 goto get_failed;
92
93 parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
94
95 if (!linkinfo[IFLA_INFO_DATA])
96 goto get_failed;
97
98 parse_rtattr_nested(vtiinfo, IFLA_VTI_MAX,
99 linkinfo[IFLA_INFO_DATA]);
100
101 if (vtiinfo[IFLA_VTI_IKEY])
9f1370c0 102 ikey = rta_getattr_u32(vtiinfo[IFLA_VTI_IKEY]);
73579339
S
103
104 if (vtiinfo[IFLA_VTI_OKEY])
9f1370c0 105 okey = rta_getattr_u32(vtiinfo[IFLA_VTI_OKEY]);
73579339
S
106
107 if (vtiinfo[IFLA_VTI_LOCAL])
9f1370c0 108 saddr = rta_getattr_u32(vtiinfo[IFLA_VTI_LOCAL]);
73579339
S
109
110 if (vtiinfo[IFLA_VTI_REMOTE])
9f1370c0 111 daddr = rta_getattr_u32(vtiinfo[IFLA_VTI_REMOTE]);
73579339
S
112
113 if (vtiinfo[IFLA_VTI_LINK])
9f1370c0 114 link = rta_getattr_u8(vtiinfo[IFLA_VTI_LINK]);
ad4b1425
CG
115
116 if (vtiinfo[IFLA_VTI_FWMARK])
117 fwmark = rta_getattr_u32(vtiinfo[IFLA_VTI_FWMARK]);
73579339
S
118 }
119
120 while (argc > 0) {
121 if (!matches(*argv, "key")) {
56f5daac 122 unsigned int uval;
73579339
S
123
124 NEXT_ARG();
125 if (strchr(*argv, '.'))
126 uval = get_addr32(*argv);
127 else {
128 if (get_unsigned(&uval, *argv, 0) < 0) {
129 fprintf(stderr,
14645ec2 130 "Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv);
73579339
S
131 exit(-1);
132 }
133 uval = htonl(uval);
134 }
135
136 ikey = okey = uval;
137 } else if (!matches(*argv, "ikey")) {
56f5daac 138 unsigned int uval;
73579339
S
139
140 NEXT_ARG();
141 if (strchr(*argv, '.'))
142 uval = get_addr32(*argv);
143 else {
144 if (get_unsigned(&uval, *argv, 0) < 0) {
14645ec2 145 fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv);
73579339
S
146 exit(-1);
147 }
148 uval = htonl(uval);
149 }
150 ikey = uval;
151 } else if (!matches(*argv, "okey")) {
56f5daac 152 unsigned int uval;
73579339
S
153
154 NEXT_ARG();
155 if (strchr(*argv, '.'))
156 uval = get_addr32(*argv);
157 else {
158 if (get_unsigned(&uval, *argv, 0) < 0) {
14645ec2 159 fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv);
73579339
S
160 exit(-1);
161 }
162 uval = htonl(uval);
163 }
164 okey = uval;
165 } else if (!matches(*argv, "remote")) {
166 NEXT_ARG();
167 if (!strcmp(*argv, "any")) {
14645ec2 168 fprintf(stderr, "invalid value for \"remote\": \"%s\"\n", *argv);
73579339
S
169 exit(-1);
170 } else {
171 daddr = get_addr32(*argv);
172 }
173 } else if (!matches(*argv, "local")) {
174 NEXT_ARG();
175 if (!strcmp(*argv, "any")) {
14645ec2 176 fprintf(stderr, "invalid value for \"local\": \"%s\"\n", *argv);
73579339
S
177 exit(-1);
178 } else {
179 saddr = get_addr32(*argv);
180 }
181 } else if (!matches(*argv, "dev")) {
182 NEXT_ARG();
183 link = if_nametoindex(*argv);
0cb6bb51
CW
184 if (link == 0) {
185 fprintf(stderr, "Cannot find device \"%s\"\n",
186 *argv);
73579339 187 exit(-1);
0cb6bb51 188 }
ad4b1425
CG
189 } else if (strcmp(*argv, "fwmark") == 0) {
190 NEXT_ARG();
191 if (get_u32(&fwmark, *argv, 0))
192 invarg("invalid fwmark\n", *argv);
73579339
S
193 } else
194 usage();
195 argc--; argv++;
196 }
197
198 addattr32(n, 1024, IFLA_VTI_IKEY, ikey);
199 addattr32(n, 1024, IFLA_VTI_OKEY, okey);
200 addattr_l(n, 1024, IFLA_VTI_LOCAL, &saddr, 4);
201 addattr_l(n, 1024, IFLA_VTI_REMOTE, &daddr, 4);
ad4b1425 202 addattr32(n, 1024, IFLA_VTI_FWMARK, fwmark);
73579339
S
203 if (link)
204 addattr32(n, 1024, IFLA_VTI_LINK, link);
205
206 return 0;
207}
208
209static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
210{
73579339
S
211 const char *local = "any";
212 const char *remote = "any";
fcfcc40b 213 __u32 key;
9f1370c0 214 unsigned int link;
fcfcc40b 215 char s2[IFNAMSIZ];
73579339
S
216
217 if (!tb)
218 return;
219
220 if (tb[IFLA_VTI_REMOTE]) {
9f1370c0 221 unsigned int addr = rta_getattr_u32(tb[IFLA_VTI_REMOTE]);
73579339
S
222
223 if (addr)
a418e451 224 remote = format_host(AF_INET, 4, &addr);
73579339
S
225 }
226
4c42a1c1 227 print_string(PRINT_ANY, "remote", "remote %s ", remote);
73579339
S
228
229 if (tb[IFLA_VTI_LOCAL]) {
9f1370c0 230 unsigned int addr = rta_getattr_u32(tb[IFLA_VTI_LOCAL]);
73579339
S
231
232 if (addr)
a418e451 233 local = format_host(AF_INET, 4, &addr);
73579339
S
234 }
235
4c42a1c1 236 print_string(PRINT_ANY, "local", "local %s ", local);
73579339 237
9f1370c0
SH
238 if (tb[IFLA_VTI_LINK] &&
239 (link = rta_getattr_u32(tb[IFLA_VTI_LINK]))) {
73579339
S
240 const char *n = if_indextoname(link, s2);
241
242 if (n)
4c42a1c1 243 print_string(PRINT_ANY, "link", "dev %s ", n);
73579339 244 else
4c42a1c1 245 print_uint(PRINT_ANY, "link_index", "dev %u ", link);
73579339
S
246 }
247
fcfcc40b
SH
248 if (tb[IFLA_VTI_IKEY] &&
249 (key = rta_getattr_u32(tb[IFLA_VTI_IKEY])))
4c42a1c1 250 print_0xhex(PRINT_ANY, "ikey", "ikey %#x ", ntohl(key));
73579339 251
fcfcc40b
SH
252
253 if (tb[IFLA_VTI_OKEY] &&
254 (key = rta_getattr_u32(tb[IFLA_VTI_OKEY])))
4c42a1c1 255 print_0xhex(PRINT_ANY, "okey", "okey %#x ", ntohl(key));
ad4b1425 256
4c42a1c1
JF
257 if (tb[IFLA_VTI_FWMARK]) {
258 __u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]);
259
260 if (fwmark) {
261 SPRINT_BUF(b1);
262
263 snprintf(b1, sizeof(b1), "0x%x", fwmark);
264 print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
265 }
ad4b1425 266 }
73579339
S
267}
268
561e650e 269static void vti_print_help(struct link_util *lu, int argc, char **argv,
270 FILE *f)
271{
272 print_usage(f);
273}
274
73579339
S
275struct link_util vti_link_util = {
276 .id = "vti",
277 .maxattr = IFLA_VTI_MAX,
278 .parse_opt = vti_parse_opt,
279 .print_opt = vti_print_opt,
561e650e 280 .print_help = vti_print_help,
73579339 281};