]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/link_vti6.c
vti/vti6: Minor improvements
[mirror_iproute2.git] / ip / link_vti6.c
CommitLineData
2f7fbec2
SK
1/*
2 * link_vti6.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 * Steffen Klassert <steffen.klassert@secunet.com> Modified link_vti.c for IPv6
12 */
13
14#include <string.h>
15#include <net/if.h>
16#include <sys/types.h>
17#include <sys/socket.h>
18#include <arpa/inet.h>
19
20#include <linux/ip.h>
21#include <linux/if_tunnel.h>
22#include "rt_names.h"
23#include "utils.h"
24#include "ip_common.h"
25#include "tunnel.h"
26
b8dc6c5b
SP
27static void print_usage(FILE *f)
28{
29 fprintf(f,
30 "Usage: ... vti6 [ remote ADDR ]\n"
31 " [ local ADDR ]\n"
32 " [ [i|o]key KEY ]\n"
33 " [ dev PHYS_DEV ]\n"
34 " [ fwmark MARK ]\n"
35 "\n"
36 "Where: ADDR := { IPV6_ADDRESS }\n"
37 " KEY := { DOTTED_QUAD | NUMBER }\n"
38 " MARK := { 0x0..0xffffffff }\n"
39 );
40}
2f7fbec2
SK
41
42static void usage(void) __attribute__((noreturn));
43static void usage(void)
44{
b8dc6c5b 45 print_usage(stderr);
2f7fbec2
SK
46 exit(-1);
47}
48
49static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
50 struct nlmsghdr *n)
51{
d17b136f 52 struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
2f7fbec2
SK
53 struct {
54 struct nlmsghdr n;
55 struct ifinfomsg i;
d17b136f
PS
56 } req = {
57 .n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
58 .n.nlmsg_flags = NLM_F_REQUEST,
59 .n.nlmsg_type = RTM_GETLINK,
60 .i.ifi_family = preferred_family,
61 .i.ifi_index = ifi->ifi_index,
62 };
08ede25f 63 struct nlmsghdr *answer;
2f7fbec2
SK
64 struct rtattr *tb[IFLA_MAX + 1];
65 struct rtattr *linkinfo[IFLA_INFO_MAX+1];
66 struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
2a80154f
SH
67 struct in6_addr saddr = IN6ADDR_ANY_INIT;
68 struct in6_addr daddr = IN6ADDR_ANY_INIT;
1f44b937
SP
69 __be32 ikey = 0;
70 __be32 okey = 0;
56f5daac 71 unsigned int link = 0;
ad4b1425 72 __u32 fwmark = 0;
2f7fbec2
SK
73 int len;
74
75 if (!(n->nlmsg_flags & NLM_F_CREATE)) {
86bf43c7 76 if (rtnl_talk(&rth, &req.n, &answer) < 0) {
2f7fbec2
SK
77get_failed:
78 fprintf(stderr,
79 "Failed to get existing tunnel info.\n");
80 return -1;
81 }
82
86bf43c7 83 len = answer->nlmsg_len;
2f7fbec2
SK
84 len -= NLMSG_LENGTH(sizeof(*ifi));
85 if (len < 0)
86 goto get_failed;
87
86bf43c7 88 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
2f7fbec2
SK
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])
102 ikey = rta_getattr_u32(vtiinfo[IFLA_VTI_IKEY]);
103
104 if (vtiinfo[IFLA_VTI_OKEY])
105 okey = rta_getattr_u32(vtiinfo[IFLA_VTI_OKEY]);
106
107 if (vtiinfo[IFLA_VTI_LOCAL])
108 memcpy(&saddr, RTA_DATA(vtiinfo[IFLA_VTI_LOCAL]), sizeof(saddr));
109
110 if (vtiinfo[IFLA_VTI_REMOTE])
111 memcpy(&daddr, RTA_DATA(vtiinfo[IFLA_VTI_REMOTE]), sizeof(daddr));
112
113 if (vtiinfo[IFLA_VTI_LINK])
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]);
86bf43c7
HL
118
119 free(answer);
2f7fbec2
SK
120 }
121
122 while (argc > 0) {
123 if (!matches(*argv, "key")) {
2f7fbec2 124 NEXT_ARG();
1f44b937 125 ikey = okey = tnl_parse_key("key", *argv);
2f7fbec2 126 } else if (!matches(*argv, "ikey")) {
2f7fbec2 127 NEXT_ARG();
1f44b937 128 ikey = tnl_parse_key("ikey", *argv);
2f7fbec2 129 } else if (!matches(*argv, "okey")) {
2f7fbec2 130 NEXT_ARG();
1f44b937 131 okey = tnl_parse_key("okey", *argv);
2f7fbec2 132 } else if (!matches(*argv, "remote")) {
57daab1e 133 inet_prefix addr;
56f5daac 134
2f7fbec2 135 NEXT_ARG();
9aceaad7
SP
136 get_addr(&addr, *argv, AF_INET6);
137 memcpy(&daddr, addr.data, sizeof(daddr));
57daab1e
SP
138 } else if (!matches(*argv, "local")) {
139 inet_prefix addr;
56f5daac 140
57daab1e 141 NEXT_ARG();
9aceaad7
SP
142 get_addr(&addr, *argv, AF_INET6);
143 memcpy(&saddr, addr.data, sizeof(saddr));
2f7fbec2
SK
144 } else if (!matches(*argv, "dev")) {
145 NEXT_ARG();
146 link = if_nametoindex(*argv);
9dc04a4f
SP
147 if (link == 0) {
148 fprintf(stderr, "Cannot find device \"%s\"\n",
149 *argv);
2f7fbec2 150 exit(-1);
9dc04a4f 151 }
ad4b1425
CG
152 } else if (strcmp(*argv, "fwmark") == 0) {
153 NEXT_ARG();
154 if (get_u32(&fwmark, *argv, 0))
155 invarg("invalid fwmark\n", *argv);
2f7fbec2
SK
156 } else
157 usage();
158 argc--; argv++;
159 }
160
161 addattr32(n, 1024, IFLA_VTI_IKEY, ikey);
162 addattr32(n, 1024, IFLA_VTI_OKEY, okey);
560cf612
SP
163 addattr_l(n, 1024, IFLA_VTI_LOCAL, &saddr, sizeof(saddr));
164 addattr_l(n, 1024, IFLA_VTI_REMOTE, &daddr, sizeof(daddr));
ad4b1425 165 addattr32(n, 1024, IFLA_VTI_FWMARK, fwmark);
2f7fbec2
SK
166 if (link)
167 addattr32(n, 1024, IFLA_VTI_LINK, link);
168
169 return 0;
170}
171
172static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
173{
2f7fbec2
SK
174 const char *local = "any";
175 const char *remote = "any";
176 struct in6_addr saddr;
177 struct in6_addr daddr;
9f1370c0 178 char s2[64];
2f7fbec2
SK
179
180 if (!tb)
181 return;
182
183 if (tb[IFLA_VTI_REMOTE]) {
184 memcpy(&daddr, RTA_DATA(tb[IFLA_VTI_REMOTE]), sizeof(daddr));
185
a418e451 186 remote = format_host(AF_INET6, 16, &daddr);
2f7fbec2
SK
187 }
188
063dd06c 189 print_string(PRINT_ANY, "remote", "remote %s ", remote);
2f7fbec2
SK
190
191 if (tb[IFLA_VTI_LOCAL]) {
192 memcpy(&saddr, RTA_DATA(tb[IFLA_VTI_LOCAL]), sizeof(saddr));
193
a418e451 194 local = format_host(AF_INET6, 16, &saddr);
2f7fbec2
SK
195 }
196
063dd06c 197 print_string(PRINT_ANY, "local", "local %s ", local);
2f7fbec2 198
45d3a6ef
SP
199 if (tb[IFLA_VTI_LINK]) {
200 unsigned int link = rta_getattr_u32(tb[IFLA_VTI_LINK]);
2f7fbec2 201
45d3a6ef
SP
202 if (link) {
203 print_string(PRINT_ANY, "link", "dev %s ",
204 ll_index_to_name(link));
205 }
2f7fbec2
SK
206 }
207
208 if (tb[IFLA_VTI_IKEY]) {
34a8c54d
SP
209 struct rtattr *rta = tb[IFLA_VTI_IKEY];
210 __u32 key = rta_getattr_u32(rta);
211
212 if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2)))
213 print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
2f7fbec2
SK
214 }
215
216 if (tb[IFLA_VTI_OKEY]) {
34a8c54d
SP
217 struct rtattr *rta = tb[IFLA_VTI_OKEY];
218 __u32 key = rta_getattr_u32(rta);
219
220 if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2)))
221 print_string(PRINT_ANY, "okey", "okey %s ", s2);
2f7fbec2 222 }
ad4b1425 223
063dd06c
JF
224 if (tb[IFLA_VTI_FWMARK]) {
225 __u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]);
226
227 if (fwmark) {
e97ad3d2
SP
228 print_0xhex(PRINT_ANY,
229 "fwmark", "fwmark 0x%x ", fwmark);
063dd06c 230 }
ad4b1425 231 }
2f7fbec2
SK
232}
233
b8dc6c5b
SP
234static void vti6_print_help(struct link_util *lu, int argc, char **argv,
235 FILE *f)
236{
237 print_usage(f);
238}
239
2f7fbec2
SK
240struct link_util vti6_link_util = {
241 .id = "vti6",
242 .maxattr = IFLA_VTI_MAX,
243 .parse_opt = vti6_parse_opt,
244 .print_opt = vti6_print_opt,
b8dc6c5b 245 .print_help = vti6_print_help,
2f7fbec2 246};