• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C)2006 USAGI/WIDE Project
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 /*
19  * split from ip_tunnel.c
20  */
21 /*
22  * Author:
23  *	Masahide NAKAMURA @USAGI
24  */
25 
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/ioctl.h>
33 #include <netinet/in.h>
34 #include <linux/if.h>
35 #include <linux/ip.h>
36 #include <linux/if_tunnel.h>
37 
38 #include "utils.h"
39 #include "tunnel.h"
40 
tnl_strproto(__u8 proto)41 const char *tnl_strproto(__u8 proto)
42 {
43 	static char buf[16];
44 
45 	switch (proto) {
46 	case IPPROTO_IPIP:
47 		strcpy(buf, "ip");
48 		break;
49 	case IPPROTO_GRE:
50 		strcpy(buf, "gre");
51 		break;
52 	case IPPROTO_IPV6:
53 		strcpy(buf, "ipv6");
54 		break;
55 	case 0:
56 		strcpy(buf, "any");
57 		break;
58 	default:
59 		strcpy(buf, "unknown");
60 		break;
61 	}
62 
63 	return buf;
64 }
65 
tnl_ioctl_get_ifindex(const char * dev)66 int tnl_ioctl_get_ifindex(const char *dev)
67 {
68 	struct ifreq ifr;
69 	int fd;
70 	int err;
71 
72 	strncpy(ifr.ifr_name, dev, IFNAMSIZ);
73 	fd = socket(preferred_family, SOCK_DGRAM, 0);
74 	err = ioctl(fd, SIOCGIFINDEX, &ifr);
75 	if (err) {
76 		perror("ioctl");
77 		return 0;
78 	}
79 	close(fd);
80 	return ifr.ifr_ifindex;
81 }
82 
tnl_ioctl_get_iftype(const char * dev)83 int tnl_ioctl_get_iftype(const char *dev)
84 {
85 	struct ifreq ifr;
86 	int fd;
87 	int err;
88 
89 	strncpy(ifr.ifr_name, dev, IFNAMSIZ);
90 	fd = socket(preferred_family, SOCK_DGRAM, 0);
91 	err = ioctl(fd, SIOCGIFHWADDR, &ifr);
92 	if (err) {
93 		perror("ioctl");
94 		return -1;
95 	}
96 	close(fd);
97 	return ifr.ifr_addr.sa_family;
98 }
99 
100 
tnl_ioctl_get_ifname(int idx)101 char * tnl_ioctl_get_ifname(int idx)
102 {
103 	static struct ifreq ifr;
104 	int fd;
105 	int err;
106 
107 	ifr.ifr_ifindex = idx;
108 	fd = socket(preferred_family, SOCK_DGRAM, 0);
109 	err = ioctl(fd, SIOCGIFNAME, &ifr);
110 	if (err) {
111 		perror("ioctl");
112 		return NULL;
113 	}
114 	close(fd);
115 	return ifr.ifr_name;
116 }
117 
tnl_get_ioctl(const char * basedev,void * p)118 int tnl_get_ioctl(const char *basedev, void *p)
119 {
120 	struct ifreq ifr;
121 	int fd;
122 	int err;
123 
124 	strncpy(ifr.ifr_name, basedev, IFNAMSIZ);
125 	ifr.ifr_ifru.ifru_data = (void*)p;
126 	fd = socket(preferred_family, SOCK_DGRAM, 0);
127 	err = ioctl(fd, SIOCGETTUNNEL, &ifr);
128 	if (err)
129 		perror("ioctl");
130 	close(fd);
131 	return err;
132 }
133 
tnl_add_ioctl(int cmd,const char * basedev,const char * name,void * p)134 int tnl_add_ioctl(int cmd, const char *basedev, const char *name, void *p)
135 {
136 	struct ifreq ifr;
137 	int fd;
138 	int err;
139 
140 	if (cmd == SIOCCHGTUNNEL && name[0])
141 		strncpy(ifr.ifr_name, name, IFNAMSIZ);
142 	else
143 		strncpy(ifr.ifr_name, basedev, IFNAMSIZ);
144 	ifr.ifr_ifru.ifru_data = p;
145 	fd = socket(preferred_family, SOCK_DGRAM, 0);
146 	err = ioctl(fd, cmd, &ifr);
147 	if (err)
148 		perror("ioctl");
149 	close(fd);
150 	return err;
151 }
152 
tnl_del_ioctl(const char * basedev,const char * name,void * p)153 int tnl_del_ioctl(const char *basedev, const char *name, void *p)
154 {
155 	struct ifreq ifr;
156 	int fd;
157 	int err;
158 
159 	if (name[0])
160 		strncpy(ifr.ifr_name, name, IFNAMSIZ);
161 	else
162 		strncpy(ifr.ifr_name, basedev, IFNAMSIZ);
163 	ifr.ifr_ifru.ifru_data = p;
164 	fd = socket(preferred_family, SOCK_DGRAM, 0);
165 	err = ioctl(fd, SIOCDELTUNNEL, &ifr);
166 	if (err)
167 		perror("ioctl");
168 	close(fd);
169 	return err;
170 }
171 
tnl_gen_ioctl(int cmd,const char * name,void * p,int skiperr)172 static int tnl_gen_ioctl(int cmd, const char *name, void *p, int skiperr)
173 {
174 	struct ifreq ifr;
175 	int fd;
176 	int err;
177 
178 	strncpy(ifr.ifr_name, name, IFNAMSIZ);
179 	ifr.ifr_ifru.ifru_data = p;
180 	fd = socket(preferred_family, SOCK_DGRAM, 0);
181 	err = ioctl(fd, cmd, &ifr);
182 	if (err && errno != skiperr)
183 		perror("ioctl");
184 	close(fd);
185 	return err;
186 }
187 
tnl_prl_ioctl(int cmd,const char * name,void * p)188 int tnl_prl_ioctl(int cmd, const char *name, void *p)
189 {
190 	return tnl_gen_ioctl(cmd, name, p, -1);
191 }
192 
tnl_6rd_ioctl(int cmd,const char * name,void * p)193 int tnl_6rd_ioctl(int cmd, const char *name, void *p)
194 {
195 	return tnl_gen_ioctl(cmd, name, p, -1);
196 }
197 
tnl_ioctl_get_6rd(const char * name,void * p)198 int tnl_ioctl_get_6rd(const char *name, void *p)
199 {
200 	return tnl_gen_ioctl(SIOCGET6RD, name, p, EINVAL);
201 }
202