ia64/xen-unstable

view tools/vnet/vnet-module/etherip.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 3233e7ecfa9f
children 06d84bf87159
line source
1 /*
2 * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
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 the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free software Foundation, Inc.,
16 * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19 #include <linux/config.h>
20 #include <linux/module.h>
21 #include <linux/types.h>
22 #include <linux/kernel.h>
23 #include <linux/init.h>
25 #include <linux/version.h>
27 #include <linux/skbuff.h>
28 #include <linux/net.h>
29 #include <linux/netdevice.h>
30 #include <linux/in.h>
31 #include <linux/inet.h>
32 #include <linux/netfilter_ipv4.h>
33 #include <linux/icmp.h>
35 #include <net/ip.h>
36 #include <net/protocol.h>
37 #include <net/route.h>
38 #include <net/checksum.h>
40 #include <etherip.h>
41 #include <tunnel.h>
42 #include <vnet.h>
43 #include <varp.h>
44 #include <if_varp.h>
45 #include <varp.h>
46 #include <skb_util.h>
48 #define MODULE_NAME "VNET"
49 //#define DEBUG 1
50 #undef DEBUG
51 #include "debug.h"
53 /** @file Etherip implementation.
54 * The etherip protocol is used to transport Ethernet frames in IP packets.
55 */
57 /** Get the vnet label from an etherip header.
58 *
59 * @param hdr header
60 * @@param vnet (in net order)
61 */
62 void etheriphdr_get_vnet(struct etheriphdr *hdr, VnetId *vnet){
63 #ifdef CONFIG_ETHERIP_EXT
64 *vnet = *(VnetId*)hdr->vnet;
65 #else
66 *vnet = (VnetId){};
67 vnet->u.vnet16[7] = (unsigned short)hdr->reserved;
69 #endif
70 }
72 /** Set the vnet label in an etherip header.
73 * Also sets the etherip version.
74 *
75 * @param hdr header
76 * @param vnet vnet label (in net order)
77 */
78 void etheriphdr_set_vnet(struct etheriphdr *hdr, VnetId *vnet){
79 #ifdef CONFIG_ETHERIP_EXT
80 hdr->version = ETHERIP_VERSION;
81 *(VnetId*)hdr->vnet = *vnet;
82 #else
83 hdr->version = ETHERIP_VERSION;
84 hdr->reserved = (vnet->u.vnet16[7] & 0x0fff);
85 #endif
86 }
88 /** Open an etherip tunnel.
89 *
90 * @param tunnel to open
91 * @return 0 on success, error code otherwise
92 */
93 static int etherip_tunnel_open(Tunnel *tunnel){
94 return 0;
95 }
97 /** Close an etherip tunnel.
98 *
99 * @param tunnel to close
100 */
101 static void etherip_tunnel_close(Tunnel *tunnel){
102 }
105 /** Send a packet via an etherip tunnel.
106 * Adds etherip header, new ip header, new ethernet header around
107 * ethernet frame.
108 *
109 * @param tunnel tunnel
110 * @param skb packet
111 * @return 0 on success, error code otherwise
112 */
113 static int etherip_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
114 int err = 0;
115 const int etherip_n = sizeof(struct etheriphdr);
116 const int ip_n = sizeof(struct iphdr);
117 const int eth_n = ETH_HLEN;
118 int head_n = 0;
119 VnetId *vnet = &tunnel->key.vnet;
120 struct etheriphdr *etheriph;
121 struct ethhdr *ethh;
122 u32 saddr = 0;
124 //dprintf("> skb=%p vnet=%d\n", skb, vnet);
125 head_n = etherip_n + ip_n + eth_n;
126 err = skb_make_room(&skb, skb, head_n, 0);
127 if(err) goto exit;
129 //err = vnet_get_device_address(skb->dev, &saddr);
130 //if(err) goto exit;
132 // The original ethernet header.
133 ethh = eth_hdr(skb);
134 //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len);
135 // Null the pointer as we are pushing a new IP header.
136 skb->mac.raw = NULL;
138 // Setup the etherip header.
139 //dprintf("> push etherip header...\n");
140 etheriph = (struct etheriphdr *)skb_push(skb, etherip_n);
141 etheriphdr_set_vnet(etheriph, vnet);
143 // Setup the IP header.
144 //dprintf("> push IP header...\n");
145 skb->nh.raw = skb_push(skb, ip_n);
146 skb->nh.iph->version = 4; // Standard version.
147 skb->nh.iph->ihl = ip_n / 4; // IP header length (32-bit words).
148 skb->nh.iph->tos = 0; // No special type-of-service.
149 skb->nh.iph->tot_len = htons(skb->len); // Total packet length (bytes).
150 skb->nh.iph->id = 0; // No flow id (since no frags).
151 skb->nh.iph->frag_off = htons(IP_DF); // Don't fragment - can't handle frags.
152 skb->nh.iph->ttl = 64; // Linux default time-to-live.
153 skb->nh.iph->protocol = IPPROTO_ETHERIP; // IP protocol number.
154 skb->nh.iph->saddr = saddr; // Source address.
155 skb->nh.iph->daddr = tunnel->key.addr.u.ip4.s_addr; // Destination address.
156 skb->nh.iph->check = 0;
158 // Ethernet header will be filled-in by device.
159 err = Tunnel_send(tunnel->base, skb);
160 skb = NULL;
161 exit:
162 if(err && skb) dev_kfree_skb(skb);
163 //dprintf("< err=%d\n", err);
164 return err;
165 }
167 /** Tunnel type for etherip.
168 */
169 static TunnelType _etherip_tunnel_type = {
170 .name = "ETHERIP",
171 .open = etherip_tunnel_open,
172 .close = etherip_tunnel_close,
173 .send = etherip_tunnel_send
174 };
176 TunnelType *etherip_tunnel_type = &_etherip_tunnel_type;
178 /* Defeat compiler warnings about unused functions. */
179 static void print_str(char *s, int n) __attribute__((unused));
181 static void print_str(char *s, int n) {
182 int i;
184 for(i=0; i<n; s++, i++){
185 if(i && i % 40 == 0) printk("\n");
186 if(('a'<= *s && *s <= 'z') ||
187 ('A'<= *s && *s <= 'Z') ||
188 ('0'<= *s && *s <= '9')){
189 printk("%c", *s);
190 } else {
191 printk("<%x>", (unsigned)(0xff & *s));
192 }
193 }
194 printk("\n");
195 }
197 /** Do etherip receive processing.
198 * Strips etherip header to extract the ethernet frame, sets
199 * the vnet from the header and re-receives the frame.
200 *
201 * @param skb packet
202 * @return 0 on success, error code otherwise
203 */
204 static int etherip_protocol_recv(struct sk_buff *skb){
205 int err = 0;
206 int mine = 0;
207 const int eth_n = ETH_HLEN;
208 int ip_n;
209 const int etherip_n = sizeof(struct etheriphdr);
210 struct etheriphdr *etheriph;
211 struct ethhdr *ethhdr;
212 Vnet *vinfo = NULL;
213 VnetId vnet = {};
214 u32 saddr, daddr;
215 char vnetbuf[VNET_ID_BUF];
217 saddr = skb->nh.iph->saddr;
218 daddr = skb->nh.iph->daddr;
219 ethhdr = eth_hdr(skb);
220 if(MULTICAST(daddr) && (daddr != varp_mcast_addr)){
221 // Ignore multicast packets not addressed to us.
222 dprintf("> Ignoring mcast skb: src=%u.%u.%u.%u dst=%u.%u.%u.%u"
223 " varp_mcast_addr=%u.%u.%u.%u\n",
224 NIPQUAD(saddr), NIPQUAD(daddr), NIPQUAD(varp_mcast_addr));
225 goto exit;
226 }
227 ip_n = (skb->nh.iph->ihl << 2);
228 if(skb->data == skb->mac.raw){
229 // skb->data points at ethernet header.
230 //dprintf("> len=%d\n", skb->len);
231 if (!pskb_may_pull(skb, eth_n + ip_n)){
232 wprintf("> Malformed skb (eth+ip) src=%u.%u.%u.%u\n",
233 NIPQUAD(saddr));
234 err = -EINVAL;
235 goto exit;
236 }
237 skb_pull(skb, eth_n + ip_n);
238 }
239 // Assume skb->data points at etherip header.
240 etheriph = (void*)skb->data;
241 if(etheriph->version != ETHERIP_VERSION){
242 wprintf("> Bad etherip version=%d src=%u.%u.%u.%u\n",
243 etheriph->version,
244 NIPQUAD(saddr));
245 err = -EINVAL;
246 goto exit;
247 }
248 if(!pskb_may_pull(skb, etherip_n)){
249 wprintf("> Malformed skb (etherip) src=%u.%u.%u.%u\n",
250 NIPQUAD(saddr));
251 err = -EINVAL;
252 goto exit;
253 }
254 etheriphdr_get_vnet(etheriph, &vnet);
255 dprintf("> Rcvd skb vnet=%s src=%u.%u.%u.%u\n",
256 VnetId_ntoa(&vnet, vnetbuf),
257 NIPQUAD(saddr));
258 // If vnet is secure, context must include IPSEC ESP.
259 err = vnet_check_context(&vnet, SKB_CONTEXT(skb), &vinfo);
260 Vnet_decref(vinfo);
261 if(err){
262 wprintf("> Failed security check vnet=%s src=%u.%u.%u.%u\n",
263 VnetId_ntoa(&vnet, vnetbuf),
264 NIPQUAD(saddr));
265 goto exit;
266 }
267 mine = 1;
268 // Point at the headers in the contained ethernet frame.
269 skb->mac.raw = skb_pull(skb, etherip_n);
271 // Know source ip, vnet, vmac, so could update varp cache.
272 // But if traffic comes to us over a vnetd tunnel this points the coa
273 // at the vnetd rather than the endpoint. So don't do it.
274 //varp_update(vnet, eth_hdr(skb)->h_source, skb->nh.iph->saddr);
276 // Assuming a standard Ethernet frame.
277 // Should check for protocol? Support ETH_P_8021Q too.
278 skb->nh.raw = skb_pull(skb, ETH_HLEN);
280 dprintf("> Unpacked vnet=%s srcmac=" MACFMT " dstmac=" MACFMT "\n",
281 VnetId_ntoa(&vnet, vnetbuf),
282 MAC6TUPLE(eth_hdr(skb)->h_source),
283 MAC6TUPLE(eth_hdr(skb)->h_dest));
285 #ifdef CONFIG_NETFILTER
286 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
287 // This stops our new pkt header being clobbered by a subsequent
288 // call to nf_bridge_maybe_copy_header.
289 // Code from nf_bridge_save_header() modidifed to use h_proto
290 // instead of skb->protocol.
291 if(skb->nf_bridge){
292 // Hmm. Standard ethernet header is ETH_HLEN (14),
293 // VLAN header (802.1q) is VLAN_ETH_HLEN (18).
294 // Where does 16 come from?
295 int header_size = 16;
296 if(eth_hdr(skb)->h_proto == __constant_htons(ETH_P_8021Q)) {
297 header_size = 18;
298 }
299 memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
300 }
301 #endif
302 #endif
304 if(1){
305 struct ethhdr *eth = eth_hdr(skb);
306 // Devices use eth_type_trans() to set skb->pkt_type and skb->protocol.
307 // Set them from contained ethhdr, or leave as received?
308 // 'Ware use of hard_header_len in eth_type_trans().
310 //skb->protocol = htons(ETH_P_IP);
312 if(ntohs(eth->h_proto) >= 1536){
313 skb->protocol = eth->h_proto;
314 } else {
315 skb->protocol = htons(ETH_P_802_2);
316 }
318 if(mac_is_multicast(eth->h_dest)){
319 if(mac_is_broadcast(eth->h_dest)){
320 skb->pkt_type = PACKET_BROADCAST;
321 } else {
322 skb->pkt_type = PACKET_MULTICAST;
323 }
324 } else {
325 skb->pkt_type = PACKET_HOST;
326 }
328 memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
329 if (skb->ip_summed == CHECKSUM_HW){
330 skb->ip_summed = CHECKSUM_NONE;
331 //skb->csum = csum_sub(skb->csum,
332 // csum_partial(skb->mac.raw, skb->nh.raw - skb->mac.raw, 0));
333 }
334 dst_release(skb->dst);
335 skb->dst = NULL;
337 #ifdef CONFIG_NETFILTER
338 nf_conntrack_put(skb->nfct);
339 skb->nfct = NULL;
340 #ifdef CONFIG_NETFILTER_DEBUG
341 skb->nf_debug = 0;
342 #endif
343 #endif
344 }
346 //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len + ETH_HLEN);
348 err = vnet_skb_recv(skb, &vnet, (Vmac*)eth_hdr(skb)->h_dest);
349 exit:
350 if(mine) err = 1;
351 dprintf("< skb=%p err=%d\n", skb, err);
352 return err;
353 }
355 /** Handle an ICMP error related to etherip.
356 *
357 * @param skb ICMP error packet
358 * @param info
359 */
360 static void etherip_protocol_icmp_err(struct sk_buff *skb, u32 info){
361 struct iphdr *iph = (struct iphdr*)skb->data;
363 wprintf("> ICMP error type=%d code=%d addr=" IPFMT "\n",
364 skb->h.icmph->type, skb->h.icmph->code, NIPQUAD(iph->daddr));
366 if (skb->h.icmph->type != ICMP_DEST_UNREACH ||
367 skb->h.icmph->code != ICMP_FRAG_NEEDED){
368 return;
369 }
370 wprintf("> MTU too big addr= " IPFMT "\n", NIPQUAD(iph->daddr));
371 }
373 //============================================================================
374 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
375 // Code for 2.6 kernel.
377 /** Etherip protocol. */
378 static struct net_protocol etherip_protocol = {
379 .handler = etherip_protocol_recv,
380 .err_handler = etherip_protocol_icmp_err,
381 };
383 static int etherip_protocol_add(void){
384 return inet_add_protocol(&etherip_protocol, IPPROTO_ETHERIP);
385 }
387 static int etherip_protocol_del(void){
388 return inet_del_protocol(&etherip_protocol, IPPROTO_ETHERIP);
389 }
391 //============================================================================
392 #else
393 //============================================================================
394 // Code for 2.4 kernel.
396 /** Etherip protocol. */
397 static struct inet_protocol etherip_protocol = {
398 .name = "ETHERIP",
399 .protocol = IPPROTO_ETHERIP,
400 .handler = etherip_protocol_recv,
401 .err_handler = etherip_protocol_icmp_err,
402 };
404 static int etherip_protocol_add(void){
405 inet_add_protocol(&etherip_protocol);
406 return 0;
407 }
409 static int etherip_protocol_del(void){
410 return inet_del_protocol(&etherip_protocol);
411 }
413 #endif
414 //============================================================================
417 /** Initialize the etherip module.
418 * Registers the etherip protocol.
419 *
420 * @return 0 on success, error code otherwise
421 */
422 int __init etherip_module_init(void) {
423 int err = 0;
424 etherip_protocol_add();
425 return err;
426 }
428 /** Finalize the etherip module.
429 * Deregisters the etherip protocol.
430 */
431 void __exit etherip_module_exit(void) {
432 if(etherip_protocol_del() < 0){
433 printk(KERN_INFO "%s: can't remove etherip protocol\n", __FUNCTION__);
434 }
435 }