ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/ether_emu.C
Revision: 1.5
Committed: Thu Mar 3 16:54:34 2005 UTC (19 years, 2 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1_9, rel-1_8
Changes since 1.4: +5 -3 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 ether_emu.C -- ethernet "emulator" library
3 Copyright (C) 2003-2005 Marc Lehmann <gvpe@schmorp.de>
4
5 This file is part of GVPE.
6
7 GVPE is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with gvpe; if not, write to the Free Software
19 Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include "config.h"
23
24 #include <map>
25
26 #include "vpn.h"
27
28 extern struct vpn network;
29
30 struct ether_emu : map<u32, int> {
31 typedef map<u32, int> ipv4map;
32 ipv4map ipv4;
33
34 bool tun_to_tap (tap_packet *pkt);
35 bool tap_to_tun (tap_packet *pkt);
36
37 void set_ipv4 (u32 ip, int dst)
38 {
39 (ipv4.insert (pair<u32, int>(ip, dst)).first)->second = dst;
40 }
41 };
42
43 static struct ether_emu ether_emu;
44
45 bool
46 ether_emu::tun_to_tap (tap_packet *pkt)
47 {
48 int dst;
49
50 if (pkt->is_ipv4 ())
51 {
52 // update arp cache for _local_ hosts
53 set_ipv4 (pkt->ipv4_src (), THISNODE->id);
54
55 ipv4map::iterator i = ipv4.find (pkt->ipv4_dst ());
56
57 if (i == ipv4.end ())
58 {
59 u32 ip_src = pkt->ipv4_src ();
60 u32 ip_dst = pkt->ipv4_dst ();
61
62 // throw away current packet and make it an arp request
63 (*pkt)[12] = 0x08; (*pkt)[13] = 0x06;
64 (*pkt)[14] = 0x00; (*pkt)[15] = 0x01; // hw
65 (*pkt)[16] = 0x08; (*pkt)[17] = 0x00; // prot
66 (*pkt)[18] = 0x06; // hw_len
67 (*pkt)[19] = 0x04; // prot_len
68 (*pkt)[20] = 0x00; (*pkt)[21] = 0x01; // op
69
70 id2mac (THISNODE->id, &(*pkt)[22]);
71 *(u32 *)&(*pkt)[28] = ip_src;
72 id2mac (0, &(*pkt)[32]);
73 *(u32 *)&(*pkt)[38] = ip_dst;
74
75 pkt->len = 42;
76
77 dst = 0;
78 }
79 else
80 dst = i->second;
81 }
82 else
83 dst = 0; // broadcast non-ip
84
85 id2mac (THISNODE->id, pkt->src);
86 id2mac (dst, pkt->dst);
87
88 return true;
89 }
90
91 bool
92 ether_emu::tap_to_tun (tap_packet *pkt)
93 {
94 if (pkt->is_arp ())
95 {
96 u32 ip_src = *(u32 *)&(*pkt)[28];
97
98 // always update with all info we can get. in this case, the arp sender.
99 set_ipv4 (ip_src, mac2id (&(*pkt)[22]));
100
101 //TODO: remove cache dumper
102 //for (ipv4map::iterator i = ipv4.begin (); i != ipv4.end (); ++i) printf ("%08lx => %d\n", i->first, i->second);
103
104 if ((*pkt)[20] == 0x00 && (*pkt)[21] == 0x01) // arp request
105 {
106 // send a reply, if applicable
107 u32 ip_dst = *(u32 *)&(*pkt)[38];
108 ipv4map::iterator i = ipv4.find (ip_dst);
109
110 // TODO: look up list of local networks and answer for them
111 if (i != ipv4.end () && i->second == THISNODE->id)
112 {
113 // create an arp reply
114 tap_packet *rep = new tap_packet;
115
116 id2mac (THISNODE->id, rep->src);
117 memcpy (rep->dst, pkt->src, sizeof (mac));
118
119 (*rep)[12] = 0x08; (*rep)[13] = 0x06;
120 (*rep)[14] = 0x00; (*rep)[15] = 0x01; // hw
121 (*rep)[16] = 0x08; (*rep)[17] = 0x00; // prot
122 (*rep)[18] = 0x06; // hw_len
123 (*rep)[19] = 0x04; // prot_len
124 (*rep)[20] = 0x00; (*rep)[21] = 0x02; // op
125
126 id2mac (THISNODE->id, &(*rep)[22]);
127 *(u32 *)&(*rep)[28] = ip_dst;
128 memcpy (&(*rep)[32], &(*pkt)[22], sizeof (mac));
129 *(u32 *)&(*rep)[38] = ip_src;
130
131 rep->len = 42;
132
133 network.inject_data_packet (rep, mac2id (rep->dst));
134
135 delete rep;
136 }
137 }
138 else if ((*pkt)[20] == 0x00 && (*pkt)[21] == 0x02) // arp reply
139 set_ipv4 (*(u32 *)&(*pkt)[28], mac2id (&(*pkt)[22]));
140
141 return false;
142 }
143 else if (pkt->is_ipv4 ())
144 {
145 // update arp cache
146 set_ipv4 (pkt->ipv4_src (), mac2id (pkt->src));
147 set_ipv4 (pkt->ipv4_dst (), mac2id (pkt->dst));
148 }
149
150 return true;
151 }
152