]> git.proxmox.com Git - mirror_iproute2.git/blob - ip/link_vti6.c
Merge branch 'unify_tunnel_help' into next
[mirror_iproute2.git] / ip / link_vti6.c
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
27 static void vti6_print_help(struct link_util *lu, int argc, char **argv,
28 FILE *f)
29 {
30 fprintf(f,
31 "Usage: ... %-4s [ remote ADDR ]\n",
32 lu->id
33 );
34 fprintf(f,
35 " [ local ADDR ]\n"
36 " [ [i|o]key KEY ]\n"
37 " [ dev PHYS_DEV ]\n"
38 " [ fwmark MARK ]\n"
39 "\n"
40 );
41 fprintf(f,
42 "Where: ADDR := { IP%s_ADDRESS }\n"
43 " KEY := { DOTTED_QUAD | NUMBER }\n"
44 " MARK := { 0x0..0xffffffff }\n",
45 "V6"
46 );
47 }
48
49 static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
50 struct nlmsghdr *n)
51 {
52 struct ifinfomsg *ifi = NLMSG_DATA(n);
53 struct {
54 struct nlmsghdr n;
55 struct ifinfomsg i;
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 };
63 struct nlmsghdr *answer;
64 struct rtattr *tb[IFLA_MAX + 1];
65 struct rtattr *linkinfo[IFLA_INFO_MAX+1];
66 struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
67 struct in6_addr saddr = IN6ADDR_ANY_INIT;
68 struct in6_addr daddr = IN6ADDR_ANY_INIT;
69 __be32 ikey = 0;
70 __be32 okey = 0;
71 unsigned int link = 0;
72 __u32 fwmark = 0;
73 int len;
74
75 if (!(n->nlmsg_flags & NLM_F_CREATE)) {
76 if (rtnl_talk(&rth, &req.n, &answer) < 0) {
77 get_failed:
78 fprintf(stderr,
79 "Failed to get existing tunnel info.\n");
80 return -1;
81 }
82
83 len = answer->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(NLMSG_DATA(answer)), 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])
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]);
115
116 if (vtiinfo[IFLA_VTI_FWMARK])
117 fwmark = rta_getattr_u32(vtiinfo[IFLA_VTI_FWMARK]);
118
119 free(answer);
120 }
121
122 while (argc > 0) {
123 if (!matches(*argv, "key")) {
124 NEXT_ARG();
125 ikey = okey = tnl_parse_key("key", *argv);
126 } else if (!matches(*argv, "ikey")) {
127 NEXT_ARG();
128 ikey = tnl_parse_key("ikey", *argv);
129 } else if (!matches(*argv, "okey")) {
130 NEXT_ARG();
131 okey = tnl_parse_key("okey", *argv);
132 } else if (!matches(*argv, "remote")) {
133 inet_prefix addr;
134
135 NEXT_ARG();
136 get_addr(&addr, *argv, AF_INET6);
137 memcpy(&daddr, addr.data, sizeof(daddr));
138 } else if (!matches(*argv, "local")) {
139 inet_prefix addr;
140
141 NEXT_ARG();
142 get_addr(&addr, *argv, AF_INET6);
143 memcpy(&saddr, addr.data, sizeof(saddr));
144 } else if (!matches(*argv, "dev")) {
145 NEXT_ARG();
146 link = ll_name_to_index(*argv);
147 if (link == 0) {
148 fprintf(stderr, "Cannot find device \"%s\"\n",
149 *argv);
150 exit(-1);
151 }
152 } else if (strcmp(*argv, "fwmark") == 0) {
153 NEXT_ARG();
154 if (get_u32(&fwmark, *argv, 0))
155 invarg("invalid fwmark\n", *argv);
156 } else {
157 vti6_print_help(lu, argc, argv, stderr);
158 return -1;
159 }
160 argc--; argv++;
161 }
162
163 addattr32(n, 1024, IFLA_VTI_IKEY, ikey);
164 addattr32(n, 1024, IFLA_VTI_OKEY, okey);
165 addattr_l(n, 1024, IFLA_VTI_LOCAL, &saddr, sizeof(saddr));
166 addattr_l(n, 1024, IFLA_VTI_REMOTE, &daddr, sizeof(daddr));
167 addattr32(n, 1024, IFLA_VTI_FWMARK, fwmark);
168 if (link)
169 addattr32(n, 1024, IFLA_VTI_LINK, link);
170
171 return 0;
172 }
173
174 static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
175 {
176 char s2[64];
177
178 if (!tb)
179 return;
180
181 tnl_print_endpoint("remote", tb[IFLA_VTI_REMOTE], AF_INET6);
182 tnl_print_endpoint("local", tb[IFLA_VTI_LOCAL], AF_INET6);
183
184 if (tb[IFLA_VTI_LINK]) {
185 unsigned int link = rta_getattr_u32(tb[IFLA_VTI_LINK]);
186
187 if (link) {
188 print_string(PRINT_ANY, "link", "dev %s ",
189 ll_index_to_name(link));
190 }
191 }
192
193 if (tb[IFLA_VTI_IKEY]) {
194 struct rtattr *rta = tb[IFLA_VTI_IKEY];
195 __u32 key = rta_getattr_u32(rta);
196
197 if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2)))
198 print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
199 }
200
201 if (tb[IFLA_VTI_OKEY]) {
202 struct rtattr *rta = tb[IFLA_VTI_OKEY];
203 __u32 key = rta_getattr_u32(rta);
204
205 if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2)))
206 print_string(PRINT_ANY, "okey", "okey %s ", s2);
207 }
208
209 if (tb[IFLA_VTI_FWMARK]) {
210 __u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]);
211
212 if (fwmark) {
213 print_0xhex(PRINT_ANY,
214 "fwmark", "fwmark 0x%x ", fwmark);
215 }
216 }
217 }
218
219 struct link_util vti6_link_util = {
220 .id = "vti6",
221 .maxattr = IFLA_VTI_MAX,
222 .parse_opt = vti6_parse_opt,
223 .print_opt = vti6_print_opt,
224 .print_help = vti6_print_help,
225 };