ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/ether_emu.C
Revision: 1.7
Committed: Sun Dec 2 00:45:42 2007 UTC (16 years, 5 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.6: +2 -1 lines
Log Message:
*** empty log message ***

File Contents

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