blob: 72ea2640609549736c0b63f5009201d66ba34cbe [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
2 * OpenGGSN - Gateway GPRS Support Node
3 * Copyright (C) 2002 Mondru AB.
4 *
5 * The contents of this file may be used under the terms of the GNU
6 * General Public License Version 2, provided that the above copyright
7 * notice and this permission notice is included in all copies or
8 * substantial portions of the software.
9 *
10 * The initial developer of the original code is
11 * Jens Jakobsen <jj@openggsn.org>
12 *
13 * Contributor(s):
14 *
15 */
16
17/*
18 * tun.c: Contains all TUN functionality. Should be able to handle multiple
19 * tunnels in the same program. Each tunnel is identified by the socket.
20 * I suppose that no other state information than the socket is needed.
21 *
22 * - tun_newtun: Initialise TUN tunnel.
23 * - tun_freetun: Free a device previously created with tun_newtun.
24 * - tun_encaps: Encapsulate packet in TUN tunnel and send off
25 * - tun_decaps: Extract packet from TUN tunnel and call function to
26 * ship it off as GTP encapsulated packet.
27 *
28 * TODO:
29 * - Do we need to handle fragmentation?
30 */
31
32
33#include <syslog.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
40#include <sys/stat.h>
41#include <sys/time.h>
42#include <unistd.h>
43#include <string.h>
44#include <errno.h>
45#include <fcntl.h>
46
47#include <stdio.h>
48#include <fcntl.h>
49#include <unistd.h>
50#include <sys/time.h>
51#include <sys/types.h>
52#include <sys/ioctl.h>
53#include <sys/socket.h>
54#include <linux/if.h>
55#include <errno.h>
56#include <linux/if_tun.h>
57
58
59#include "tun.h"
60
61
62int tun_newtun(struct tun_t **tun)
63{
64 struct ifreq ifr;
65
66 if (!(*tun = calloc(1, sizeof(struct tun_t)))) {
67 syslog(LOG_ERR, "%s %d. calloc(nmemb=%d, size=%d) failed: Error = %s(%d)",
68 __FILE__, __LINE__, 1, sizeof(struct tun_t),
69 strerror(errno), errno);
70 return EOF;
71 }
72
73 if (((*tun)->fd = open("/dev/net/tun", O_RDWR)) < 0) {
74 syslog(LOG_ERR, "TUN: open() failed");
75 return -1;
76 }
77
78 memset(&ifr, 0, sizeof(ifr));
79 ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Tun device, no packet info */
80 strncpy(ifr.ifr_name, (*tun)->devname, IFNAMSIZ);
81
82 if (ioctl((*tun)->fd, TUNSETIFF, (void *) &ifr) < 0) {
83 syslog(LOG_ERR, "TUN: ioctl() failed");
84 close((*tun)->fd);
85 return -1;
86 }
87
88 ioctl((*tun)->fd, TUNSETNOCSUM, 1); /* Disable checksums */
89
90 strncpy((*tun)->devname, ifr.ifr_name, IFNAMSIZ);
91
92 return (*tun)->fd;
93}
94
95int tun_freetun(struct tun_t *tun)
96{
97 if (close(tun->fd)) {
98 syslog(LOG_ERR, "%s %d. close(fd=%d) failed: Error = %s",
99 __FILE__, __LINE__, tun->fd, strerror(errno));
100 return EOF;
101 }
102 free(tun);
103 return 0;
104}
105
106
107int tun_decaps(struct tun_t *tun,
108 int (*cb) (void *cl, struct tun_t*, void *pack, unsigned len),
109 void *cl)
110{
111 unsigned char buffer[PACKET_MAX + 64 /*TODO: ip header */ ];
112 int status;
113
114
115 if ((status = read(tun->fd, buffer, sizeof(buffer))) <= 0) {
116 syslog(LOG_ERR, "TUN: read(fd=%d,buffer=%lx,len=%d) from network failed: status = %d error = %s",
117 tun->fd, (unsigned long) buffer, sizeof(buffer), status, status ? strerror(errno) : "No error");
118 return -1;
119 }
120
121 /* Need to include code to verify packet src and dest addresses */
122 return cb(cl, tun, buffer, status);
123}
124
125int tun_encaps(struct tun_t *tun, void *pack, unsigned len)
126{
127 return write(tun->fd, pack, len);
128}