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