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