ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/ether_emu.C
Revision: 1.1
Committed: Thu Oct 16 02:29:25 2003 UTC (20 years, 7 months ago) by pcg
Content type: text/plain
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

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