1 NOTE: Ethertap is now an obsolete facility, and is scheduled
2 to be removed in the 2.5.x kernel series. Those writing
3 applications using ethertap should convert their code to
4 use the TUN/TAP driver instead, see 'tuntap.txt' in this
5 directory for more details. -DaveM
6
7 Ethertap programming mini-HOWTO
8 -------------------------------
9
10 The ethertap driver was written by Jay Schulist <jschlst@turbolinux.com>,
11 you should contact him for further information. This document was written by
12 bert hubert <bert.hubert@netherlabs.nl>. Updates are welcome.
13
14 What ethertap can do for you
15 ----------------------------
16
17 Ethertap allows you to easily run your own network stack from userspace.
18 Tunnels can benefit greatly from this. You can also use it to do network
19 experiments. The alternative would be to use a raw socket to send data and
20 use libpcap to receive it. Using ethertap saves you this multiplicity and
21 also does ARP for you if you want.
22
23 The more technical blurb:
24
25 Ethertap provides packet reception and transmission for user space programs.
26 It can be viewed as a simple Ethernet device, which instead of receiving
27 packets from a network wire, it receives them from user space.
28
29 Ethertap can be used for anything from AppleTalk to IPX to even building
30 bridging tunnels. It also has many other general purpose uses.
31
32 Configuring your kernel
33 -----------------------
34
35 Firstly, you need this in Networking Options:
36
37 #
38 # Code maturity level options
39 #
40 CONFIG_EXPERIMENTAL=y
41
42 Then you need Netlink support:
43
44 CONFIG_NETLINK=y
45
46 This allows the kernel to exchange data with userspace applications. There
47 are two ways of doing this, the new way works with netlink sockets and I
48 have no experience with that yet. ANK uses it in his excellent iproute2
49 package, see for example rtmon.c. iproute2 can be found on
50 ftp://ftp.inr.ac.ru/ip-routing/iproute2*
51
52 The new way is described, partly in netlink(7), available on
53 http://www.europe.redhat.com/documentation/man-pages/man7/netlink.7.php3
54
55 There is also a Netlink-HOWTO, available on http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html
56 Sadly I know of no code using ethertap with this new interface.
57
58 The older way works by opening character special files with major node 36.
59 Enable this with:
60
61 CONFIG_NETLINK_DEV=m
62
63 Please be advised that this support is going to be dropped somewhere in the
64 future!
65
66 Then finally in the Network Devices section,
67
68 CONFIG_ETHERTAP=m
69
70 You can include it directly in the kernel if you want, of course, no need
71 for modules.
72
73 Setting it all up
74 -----------------
75
76 First we need to create the /dev/tap0 device node:
77
78 # mknod /dev/tap0 c 36 16
79 # mknod /dev/tap1 c 36 17
80 (etc)
81
82 Include the relevant modules (ethertap.o, netlink_dev.o, perhaps netlink.o),
83 and bring up your tap0 device:
84
85 # ifconfig tap0 10.0.0.123 up
86
87 Now your device is up and running, you can ping it as well. This is what
88 confused me to no end, because nothing is connected to our ethertap as yet,
89 how is it that we can ping it?
90
91 It turns out that the ethertap is just like a regular network interface -
92 even when it's down you can ping it. We need to route stuff to it:
93
94 # route add -host 10.0.0.124 gw 10.0.0.123
95
96 Now we can read /dev/tap0 and when we ping 10.0.0.124 from our
97 localhost, output should appear on the screen.
98
99 # cat /dev/tap0
100 :ßVU:9````````````````````````şışET@?'
101
102
103 Getting this to work from other hosts
104 -------------------------------------
105
106 For this to work, you often need proxy ARP.
107
108 # echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
109
110 eth0 here stands for the interface that connects to 'other hosts'.
111
112 Chances are that you are trying this on a non-routing desktop computer, so
113 you need to enable ip forwarding:
114
115 # echo 1 > /proc/sys/net/ipv4/ip_forward
116
117 You should now be able to ping 10.0.0.124 from other hosts on your
118 10.0.0.0/8 subnet. If you are using public ip space, it should work from
119 everywhere.
120
121 ARP
122 ---
123
124 If we were to take things very literally, your tcp/ip pseudo stack would
125 also have to implement ARP and MAC addresses. This is often a bit silly as
126 the ethertap device is a figment of our imagination anyway. However, should
127 you want to go 'all the way', you can add the 'arp' flag to ifconfig:
128
129 # ifconfig tap0 10.0.0.123 up arp
130
131 This may also be useful when implementing a bridge, which needs to bridge
132 ARP packets as well.
133
134 The sample program below will no longer work then, because it does not
135 implement ARP.
136
137 Sample program
138 --------------
139
140 A sample program is included somewhere in the bowels of the netfilter
141 source. I've extracted this program and list it here. It implements a very
142 tiny part of the IP stack and can respond to any pings it receives. It gets
143 confused if it receives ARP, as it tries to parse it by treating it as an IP
144 packet.
145
146 /* Simple program to listen to /dev/tap0 and reply to pings. */
147 #include <fcntl.h>
148 #include <netinet/ip.h>
149 #include <netinet/ip_icmp.h>
150 #if defined(__GLIBC__) && (__GLIBC__ == 2)
151 #include <netinet/tcp.h>
152 #include <netinet/udp.h>
153 #else
154 #include <linux/tcp.h>
155 #include <linux/udp.h>
156 #endif
157 #include <string.h>
158 #include <stdio.h>
159 #include <errno.h>
160 #include <unistd.h>
161
162 u_int16_t csum_partial(void *buffer, unsigned int len, u_int16_t prevsum)
163 {
164 u_int32_t sum = 0;
165 u_int16_t *ptr = buffer;
166
167 while (len > 1) {
168 sum += *ptr++;
169 len -= 2;
170 }
171 if (len) {
172 union {
173 u_int8_t byte;
174 u_int16_t wyde;
175 } odd;
176 odd.wyde = 0;
177 odd.byte = *((u_int8_t *)ptr);
178 sum += odd.wyde;
179 }
180 sum = (sum >> 16) + (sum & 0xFFFF);
181 sum += prevsum;
182 return (sum + (sum >> 16));
183 }
184
185 int main()
186 {
187 int fd, len;
188 union {
189 struct {
190 char etherhdr[16];
191 struct iphdr ip;
192 } fmt;
193 unsigned char raw[65536];
194 } u;
195
196 fd = open("/dev/tap0", O_RDWR);
197 if (fd < 0) {
198 perror("Opening `/dev/tap0'");
199 return 1;
200 }
201
202 /* u.fmt.ip.ihl in host order! Film at 11. */
203 while ((len = read(fd, &u, sizeof(u))) > 0) {
204 u_int32_t tmp;
205 struct icmphdr *icmp
206 = (void *)((u_int32_t *)&u.fmt.ip + u.fmt.ip.ihl );
207 struct tcphdr *tcp = (void *)icmp;
208 struct udphdr *udp = (void *)icmp;
209
210 fprintf(stderr, "SRC = %u.%u.%u.%u DST = %u.%u.%u.%u\n",
211 (ntohl(u.fmt.ip.saddr) >> 24) & 0xFF,
212 (ntohl(u.fmt.ip.saddr) >> 16) & 0xFF,
213 (ntohl(u.fmt.ip.saddr) >> 8) & 0xFF,
214 (ntohl(u.fmt.ip.saddr) >> 0) & 0xFF,
215 (ntohl(u.fmt.ip.daddr) >> 24) & 0xFF,
216 (ntohl(u.fmt.ip.daddr) >> 16) & 0xFF,
217 (ntohl(u.fmt.ip.daddr) >> 8) & 0xFF,
218 (ntohl(u.fmt.ip.daddr) >> 0) & 0xFF);
219
220 switch (u.fmt.ip.protocol) {
221 case IPPROTO_ICMP:
222 if (icmp->type == ICMP_ECHO) {
223 fprintf(stderr, "PONG! (iphdr = %u bytes)\n",
224 (unsigned int)((char *)icmp
225 - (char *)&u.fmt.ip));
226
227 /* Turn it around */
228 tmp = u.fmt.ip.saddr;
229 u.fmt.ip.saddr = u.fmt.ip.daddr;
230 u.fmt.ip.daddr = tmp;
231
232 icmp->type = ICMP_ECHOREPLY;
233 icmp->checksum = 0;
234 icmp->checksum
235 = ~csum_partial(icmp,
236 ntohs(u.fmt.ip.tot_len)
237 - u.fmt.ip.ihl*4, 0);
238
239 {
240 unsigned int i;
241 for (i = 44;
242 i < ntohs(u.fmt.ip.tot_len); i++){
243 printf("%u:0x%02X ", i,
244 ((unsigned char *)
245 &u.fmt.ip)[i]);
246 }
247 printf("\n");
248 }
249 write(fd, &u, len);
250 }
251 break;
252 case IPPROTO_TCP:
253 fprintf(stderr, "TCP: %u -> %u\n", ntohs(tcp->source),
254 ntohs(tcp->dest));
255 break;
256
257 case IPPROTO_UDP:
258 fprintf(stderr, "UDP: %u -> %u\n", ntohs(udp->source),
259 ntohs(udp->dest));
260 break;
261 }
262 }
263 if (len < 0)
264 perror("Reading from `/dev/tap0'");
265 else fprintf(stderr, "Empty read from `/dev/tap0'");
266 return len < 0 ? 1 : 0;
267 }
268
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.