• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/gctwimax-0.0.3rc4/src/
1/*
2 * This is a reverse-engineered driver for mobile WiMAX (802.16e) devices
3 * based on GCT Semiconductor GDM7213 & GDM7205 chip.
4 * Copyright (���) 2010 Yaroslav Levandovsky <leyarx@gmail.com>
5 *
6 * Based on  madWiMAX driver writed by Alexander Gordeev
7 * Copyright (C) 2008-2009 Alexander Gordeev <lasaine@lvk.cs.msu.su>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <unistd.h>
25#include <fcntl.h>
26#include <stdlib.h>
27#include <stdio.h>
28#include <string.h>
29#include <errno.h>
30
31#include <sys/ioctl.h>
32#include <sys/socket.h>
33#include <linux/if.h>
34#include <linux/if_arp.h>
35#include <linux/if_ether.h>
36#include <linux/if_tun.h>
37
38#include "wimax.h"
39
40
41/*
42 * Allocate TUN device, returns opened fd.
43 * Stores dev name in the first arg(must be large enough).
44 */
45static int tun_open_common0(char *dev, int istun)
46{
47	char tunname[14];
48	int i, fd, err;
49
50	if( *dev ) {
51		sprintf(tunname, "/dev/%s", dev);
52		return open(tunname, O_RDWR);
53	}
54
55	sprintf(tunname, "/dev/%s", istun ? "tun" : "tap");
56	err = 0;
57	for(i=0; i < 255; i++){
58		sprintf(tunname + 8, "%d", i);
59		/* Open device */
60		if( (fd=open(tunname, O_RDWR)) > 0 ) {
61			strcpy(dev, tunname + 5);
62			return fd;
63		}
64		else if (errno != ENOENT)
65			err = errno;
66		else if (i)	/* don't try all 256 devices */
67			break;
68	}
69	if (err)
70	errno = err;
71	return -1;
72}
73
74#ifndef OTUNSETNOCSUM
75/* pre 2.4.6 compatibility */
76#define OTUNSETNOCSUM	(('T'<< 8) | 200)
77#define OTUNSETDEBUG	(('T'<< 8) | 201)
78#define OTUNSETIFF	(('T'<< 8) | 202)
79#define OTUNSETPERSIST	(('T'<< 8) | 203)
80#define OTUNSETOWNER	(('T'<< 8) | 204)
81#endif
82
83static int tun_open_common(char *dev, int istun)
84{
85	struct ifreq ifr;
86	int fd;
87
88	if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
89		return tun_open_common0(dev, istun);
90
91	memset(&ifr, 0, sizeof(ifr));
92	ifr.ifr_flags = (istun ? IFF_TUN : IFF_TAP) | IFF_NO_PI;
93	if (*dev)
94		strncpy(ifr.ifr_name, dev, IFNAMSIZ);
95	if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
96		if (errno == EBADFD) {
97			/* Try old ioctl */
98 			if (ioctl(fd, OTUNSETIFF, (void *) &ifr) < 0)
99				goto failed;
100		} else
101			goto failed;
102	}
103
104	strcpy(dev, ifr.ifr_name);
105	return fd;
106
107failed:
108	close(fd);
109	return -1;
110}
111
112
113int tap_open(char *dev) { return tun_open_common(dev, 0); }
114
115int tap_close(int fd, char *dev) { return close(fd); }
116
117/* Read/write frames from TAP device */
118int tap_write(int fd, const void *buf, int len) { return write(fd, buf, len); }
119
120int tap_read(int fd, void *buf, int len) { return read(fd, buf, len); }
121
122
123/* Like strncpy but make sure the resulting string is always 0 terminated. */
124static char *safe_strncpy(char *dst, const char *src, int size)
125{
126	dst[size-1] = '\0';
127	return strncpy(dst,src,size-1);
128}
129
130/* Set interface hw adress */
131int tap_set_hwaddr(int fd, const char *dev, unsigned char *hwaddr)
132{
133	struct ifreq ifr;
134
135	fd = socket(PF_INET, SOCK_DGRAM, 0);
136
137	/* Fill in the structure */
138	safe_strncpy(ifr.ifr_name, dev, IFNAMSIZ);
139	ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
140	memcpy(&ifr.ifr_hwaddr.sa_data, hwaddr, ETH_ALEN);
141
142	/* call the IOCTL */
143	if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) {
144		perror("SIOCSIFHWADDR");
145		return -1;
146	}
147
148	close(fd);
149	return 0;
150}
151
152/* Set interface mtu */
153int tap_set_mtu(int fd, const char *dev, int mtu)
154{
155	struct ifreq ifr;
156
157	fd = socket(PF_INET, SOCK_DGRAM, 0);
158
159	/* Fill in the structure */
160	safe_strncpy(ifr.ifr_name, dev, IFNAMSIZ);
161	ifr.ifr_mtu = mtu;
162
163	/* call the IOCTL */
164	if ((ioctl(fd, SIOCSIFMTU, &ifr)) < 0) {
165		perror("SIOCSIFMTU");
166		return -1;
167	}
168
169	close(fd);
170	return 0;
171}
172
173/* Set a certain interface flags. */
174static int tap_set_flags(const char *dev, short flags)
175{
176	struct ifreq ifr;
177	int fd;
178
179	fd = socket(PF_INET, SOCK_DGRAM, 0);
180
181	safe_strncpy(ifr.ifr_name, dev, IFNAMSIZ);
182	if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
183		fprintf(stderr, "%s: ERROR while getting interface flags: %s\n",
184			dev, strerror(errno));
185		return (-1);
186	}
187
188	safe_strncpy(ifr.ifr_name, dev, IFNAMSIZ);
189	ifr.ifr_flags |= flags;
190	if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
191		perror("SIOCSIFFLAGS");
192		return -1;
193	}
194
195	close(fd);
196	return (0);
197}
198
199/* Clear a certain interface flags. */
200static int tap_clr_flags(const char *dev, short flags)
201{
202	struct ifreq ifr;
203	int fd;
204
205	fd = socket(PF_INET, SOCK_DGRAM, 0);
206
207	safe_strncpy(ifr.ifr_name, dev, IFNAMSIZ);
208	if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
209		fprintf(stderr, "%s: ERROR while getting interface flags: %s\n",
210			dev, strerror(errno));
211		return -1;
212	}
213
214	safe_strncpy(ifr.ifr_name, dev, IFNAMSIZ);
215	ifr.ifr_flags &= ~flags;
216	if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
217		perror("SIOCSIFFLAGS");
218		return -1;
219	}
220
221	close(fd);
222	return (0);
223}
224
225/* Test if a specified flags is set *//*
226static int tap_test_flag(const char *dev, short flags)
227{
228	struct ifreq ifr;
229	int fd;
230
231	fd = socket(PF_INET, SOCK_DGRAM, 0);
232
233	safe_strncpy(ifr.ifr_name, dev, IFNAMSIZ);
234	if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
235		fprintf(stderr, "%s: ERROR while testing interface flags: %s\n",
236			dev, strerror(errno));
237		return -1;
238	}
239
240	close(fd);
241	return (ifr.ifr_flags & flags);
242}*/
243
244int tap_bring_up(int fd, const char *dev)
245{
246	return tap_set_flags(dev, IFF_UP);
247}
248
249int tap_bring_down(int fd, const char *dev)
250{
251	return tap_clr_flags(dev, IFF_UP);
252}
253
254