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

# 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.1 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 pcg 1.3 extern struct vpn network;
29    
30 pcg 1.1 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