blob: e8708dff3feb37a9a44c30e715563847179b91bc [file] [log] [blame]
adamdunkels1103ef92003-04-02 09:17:18 +00001/*
2 * Copyright (c) 2001, Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * 3. Neither the name of the Institute nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * Author: Adam Dunkels <adam@sics.se>
33 *
oliverschmidt378c23d2005-02-23 22:44:50 +000034 * $Id: tapdev.c,v 1.5 2005/02/23 22:44:50 oliverschmidt Exp $
adamdunkels1103ef92003-04-02 09:17:18 +000035 */
36
37
38#include <fcntl.h>
39#include <stdlib.h>
40#include <stdio.h>
41#include <unistd.h>
42#include <string.h>
43#include <sys/ioctl.h>
44#include <sys/socket.h>
45#include <sys/types.h>
46#include <sys/time.h>
47#include <sys/uio.h>
48#include <sys/socket.h>
49
50#include <gtk/gtk.h>
51
52#ifdef linux
53#include <sys/ioctl.h>
54#include <linux/if.h>
55#include <linux/if_tun.h>
56#define DEVTAP "/dev/net/tun"
57#else /* linux */
58#define DEVTAP "/dev/tap0"
59#endif /* linux */
60
61#include "uip.h"
62#include "uip_arp.h"
63
adamdunkels1e55b752004-06-06 07:07:15 +000064
adamdunkels16a7b262004-07-04 21:15:53 +000065#include "tcpip.h"
adamdunkels1e55b752004-06-06 07:07:15 +000066
adamdunkels1103ef92003-04-02 09:17:18 +000067#define DROP 0
68
69static int drop = 0;
70static int fd;
71
72static unsigned long lasttime;
73static struct timezone tz;
74
75#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
76
adamdunkels1e55b752004-06-06 07:07:15 +000077static void do_send(void);
adamdunkels1103ef92003-04-02 09:17:18 +000078void tapdev_send(void);
79
80
81static void
82read_callback(gpointer data, gint source, GdkInputCondition condition)
83{
84 int ret;
85
adamdunkels16a7b262004-07-04 21:15:53 +000086 ret = read(fd, uip_buf, UIP_BUFSIZE);
87
adamdunkels1103ef92003-04-02 09:17:18 +000088 if(ret == -1) {
89 perror("tap_dev: tapdev_read: read");
90 }
adamdunkels16a7b262004-07-04 21:15:53 +000091
adamdunkels1103ef92003-04-02 09:17:18 +000092 uip_len = ret;
93
94 if(BUF->type == htons(UIP_ETHTYPE_IP)) {
95 uip_arp_ipin();
96 uip_len -= sizeof(struct uip_eth_hdr);
adamdunkels16a7b262004-07-04 21:15:53 +000097 /* uip_input();*/
98 tcpip_input();
adamdunkels1103ef92003-04-02 09:17:18 +000099 /* If the above function invocation resulted in data that
100 should be sent out on the network, the global variable
101 uip_len is set to a value > 0. */
adamdunkels1103ef92003-04-02 09:17:18 +0000102 } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
103 uip_arp_arpin();
104 /* If the above function invocation resulted in data that
105 should be sent out on the network, the global variable
106 uip_len is set to a value > 0. */
107 if(uip_len > 0) {
adamdunkels1e55b752004-06-06 07:07:15 +0000108 do_send();
adamdunkels1103ef92003-04-02 09:17:18 +0000109 }
110 }
111
112
113}
adamdunkels1103ef92003-04-02 09:17:18 +0000114gint
115timeout_callback(gpointer data)
116{
117 static u8_t i, arptimer;
118
119 for(i = 0; i < UIP_CONNS; i++) {
120 uip_periodic(i);
121 /* If the above function invocation resulted in data that
122 should be sent out on the network, the global variable
123 uip_len is set to a value > 0. */
124 if(uip_len > 0) {
adamdunkels16a7b262004-07-04 21:15:53 +0000125 tcpip_output();
126 /* uip_split_output();*/
127 /* tapdev_send();*/
adamdunkels1103ef92003-04-02 09:17:18 +0000128 }
129 }
130
131 for(i = 0; i < UIP_UDP_CONNS; i++) {
132 uip_udp_periodic(i);
133 /* If the above function invocation resulted in data that
134 should be sent out on the network, the global variable
135 uip_len is set to a value > 0. */
136 if(uip_len > 0) {
adamdunkels16a7b262004-07-04 21:15:53 +0000137 /* uip_split_output(); */
138 /* tapdev_send();*/
139 tcpip_output();
adamdunkels1103ef92003-04-02 09:17:18 +0000140 }
141 }
142
143 /* Call the ARP timer function every 10 seconds. */
144 if(++arptimer == 20) {
145 uip_arp_timer();
146 arptimer = 0;
147 }
148
149 return TRUE;
150}
adamdunkelsc8fc2302003-05-28 05:22:39 +0000151
adamdunkels1103ef92003-04-02 09:17:18 +0000152/*-----------------------------------------------------------------------------------*/
153void
154tapdev_init(void)
155{
156 char buf[1024];
157
158 fd = open(DEVTAP, O_RDWR);
159 if(fd == -1) {
160 perror("tapdev: tapdev_init: open");
adamdunkels1e55b752004-06-06 07:07:15 +0000161 return;
adamdunkels1103ef92003-04-02 09:17:18 +0000162 }
163
164#ifdef linux
165 {
166 struct ifreq ifr;
167 memset(&ifr, 0, sizeof(ifr));
168 ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
169 if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
170 perror(buf);
171 exit(1);
172 }
173 }
174#endif /* Linux */
175
adamdunkels1e55b752004-06-06 07:07:15 +0000176 snprintf(buf, sizeof(buf), "ifconfig tap0 inet 192.168.2.1");
adamdunkels1103ef92003-04-02 09:17:18 +0000177 system(buf);
adamdunkels16a7b262004-07-04 21:15:53 +0000178 printf("%s\n", buf);
adamdunkels1103ef92003-04-02 09:17:18 +0000179
180 lasttime = 0;
181
182 gdk_input_add(fd, GDK_INPUT_READ,
183 read_callback, NULL);
184
185 gtk_timeout_add(500, timeout_callback, NULL);
186}
187/*-----------------------------------------------------------------------------------*/
188unsigned int
189tapdev_read(void)
190{
191 fd_set fdset;
192 struct timeval tv, now;
193 int ret;
194
195 if(lasttime >= 500000) {
196 lasttime = 0;
197 return 0;
198 }
199
200 tv.tv_sec = 0;
201 tv.tv_usec = 500000 - lasttime;
202
adamdunkels1e55b752004-06-06 07:07:15 +0000203
adamdunkels1103ef92003-04-02 09:17:18 +0000204 FD_ZERO(&fdset);
adamdunkels1e55b752004-06-06 07:07:15 +0000205 if(fd > 0) {
206 FD_SET(fd, &fdset);
207 }
adamdunkels1103ef92003-04-02 09:17:18 +0000208
209 gettimeofday(&now, &tz);
210 ret = select(fd + 1, &fdset, NULL, NULL, &tv);
211 if(ret == 0) {
212 lasttime = 0;
213 return 0;
214 }
215 ret = read(fd, uip_buf, UIP_BUFSIZE);
216 if(ret == -1) {
217 perror("tap_dev: tapdev_read: read");
218 }
219 gettimeofday(&tv, &tz);
220 lasttime += (tv.tv_sec - now.tv_sec) * 1000000 + (tv.tv_usec - now.tv_usec);
221
222#if DROP
223 drop++;
224 if(drop % 8 == 7) {
225 printf("Dropped an input packet!\n");
226 return 0;
227 }
228#endif /* DROP */
229
230 /* printf("--- tap_dev: tapdev_read: read %d bytes\n", ret);*/
231 /* {
232 int i;
233 for(i = 0; i < 20; i++) {
234 printf("%x ", uip_buf[i]);
235 }
236 printf("\n");
237 }*/
238 /* check_checksum(uip_buf, ret);*/
239 return ret;
240}
241/*-----------------------------------------------------------------------------------*/
adamdunkels1e55b752004-06-06 07:07:15 +0000242static void
243do_send(void)
adamdunkels1103ef92003-04-02 09:17:18 +0000244{
245 int ret;
246 char tmpbuf[UIP_BUFSIZE];
247 int i;
adamdunkels1103ef92003-04-02 09:17:18 +0000248
adamdunkels1e55b752004-06-06 07:07:15 +0000249 if(fd <= 0) {
250 return;
251 }
252
adamdunkels1103ef92003-04-02 09:17:18 +0000253 /* printf("tapdev_send: sending %d bytes\n", size);*/
254 /* check_checksum(uip_buf, size);*/
255#if DROP
256 drop++;
257 if(drop % 8 == 7) {
258 printf("Dropped an output packet!\n");
259 return;
260 }
261#endif /* DROP */
262
oliverschmidt378c23d2005-02-23 22:44:50 +0000263 for(i = 0; i < UIP_TCPIP_HLEN + UIP_LLH_LEN; i++) {
adamdunkels1103ef92003-04-02 09:17:18 +0000264 tmpbuf[i] = uip_buf[i];
265 }
adamdunkels1e55b752004-06-06 07:07:15 +0000266
adamdunkels1103ef92003-04-02 09:17:18 +0000267
268 for(; i < uip_len; i++) {
oliverschmidt378c23d2005-02-23 22:44:50 +0000269 tmpbuf[i] = uip_appdata[i - UIP_TCPIP_HLEN - UIP_LLH_LEN];
adamdunkels1103ef92003-04-02 09:17:18 +0000270 }
271
272 ret = write(fd, tmpbuf, uip_len);
273
274 if(ret == -1) {
275 perror("tap_dev: tapdev_send: writev");
276 exit(1);
277 }
278}
279/*-----------------------------------------------------------------------------------*/
adamdunkels1e55b752004-06-06 07:07:15 +0000280void
281tapdev_send(void)
282{
283
284 uip_arp_out();
285
286 do_send();
287}
288/*-----------------------------------------------------------------------------------*/