diff options
Diffstat (limited to 'linux/net/ipsec/ipsec_tunnel.c')
-rw-r--r-- | linux/net/ipsec/ipsec_tunnel.c | 1671 |
1 files changed, 0 insertions, 1671 deletions
diff --git a/linux/net/ipsec/ipsec_tunnel.c b/linux/net/ipsec/ipsec_tunnel.c deleted file mode 100644 index de86843bb..000000000 --- a/linux/net/ipsec/ipsec_tunnel.c +++ /dev/null @@ -1,1671 +0,0 @@ -/* - * IPSEC Tunneling code. Heavily based on drivers/net/new_tunnel.c - * Copyright (C) 1996, 1997 John Ioannidis. - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -char ipsec_tunnel_c_version[] = "RCSID $Id: ipsec_tunnel.c,v 1.4 2005/06/16 21:21:02 as Exp $"; - -#define __NO_VERSION__ -#include <linux/module.h> -#include <linux/config.h> /* for CONFIG_IP_FORWARD */ -#include <linux/version.h> -#include <linux/kernel.h> /* printk() */ - -#include "freeswan/ipsec_param.h" - -#ifdef MALLOC_SLAB -# include <linux/slab.h> /* kmalloc() */ -#else /* MALLOC_SLAB */ -# include <linux/malloc.h> /* kmalloc() */ -#endif /* MALLOC_SLAB */ -#include <linux/errno.h> /* error codes */ -#include <linux/types.h> /* size_t */ -#include <linux/interrupt.h> /* mark_bh */ - -#include <linux/netdevice.h> /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ -#include <linux/etherdevice.h> /* eth_type_trans */ -#include <linux/ip.h> /* struct iphdr */ -#include <linux/tcp.h> /* struct tcphdr */ -#include <linux/udp.h> /* struct udphdr */ -#include <linux/skbuff.h> -#include <freeswan.h> -#ifdef NET_21 -# include <asm/uaccess.h> -# include <linux/in6.h> -# define ip_chk_addr inet_addr_type -# define IS_MYADDR RTN_LOCAL -# include <net/dst.h> -# undef dev_kfree_skb -# define dev_kfree_skb(a,b) kfree_skb(a) -# define PHYSDEV_TYPE -#endif /* NET_21 */ -#include <asm/checksum.h> -#include <net/icmp.h> /* icmp_send() */ -#include <net/ip.h> -#ifdef NETDEV_23 -# include <linux/netfilter_ipv4.h> -#endif /* NETDEV_23 */ - -#include <linux/if_arp.h> - -#include "freeswan/radij.h" -#include "freeswan/ipsec_life.h" -#include "freeswan/ipsec_xform.h" -#include "freeswan/ipsec_eroute.h" -#include "freeswan/ipsec_encap.h" -#include "freeswan/ipsec_radij.h" -#include "freeswan/ipsec_sa.h" -#include "freeswan/ipsec_tunnel.h" -#include "freeswan/ipsec_xmit.h" -#include "freeswan/ipsec_ipe4.h" -#include "freeswan/ipsec_ah.h" -#include "freeswan/ipsec_esp.h" - -#include <pfkeyv2.h> -#include <pfkey.h> - -#include "freeswan/ipsec_proto.h" -#ifdef CONFIG_IPSEC_NAT_TRAVERSAL -#include <linux/udp.h> -#endif - -static __u32 zeroes[64]; - -#ifdef CONFIG_IPSEC_DEBUG -int debug_tunnel = 0; -#endif /* CONFIG_IPSEC_DEBUG */ - -DEBUG_NO_STATIC int -ipsec_tunnel_open(struct device *dev) -{ - struct ipsecpriv *prv = dev->priv; - - /* - * Can't open until attached. - */ - - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_open: " - "dev = %s, prv->dev = %s\n", - dev->name, prv->dev?prv->dev->name:"NONE"); - - if (prv->dev == NULL) - return -ENODEV; - - MOD_INC_USE_COUNT; - return 0; -} - -DEBUG_NO_STATIC int -ipsec_tunnel_close(struct device *dev) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -#ifdef NETDEV_23 -static inline int ipsec_tunnel_xmit2(struct sk_buff *skb) -{ -#ifdef NETDEV_25 /* 2.6 kernels */ - return dst_output(skb); -#else - return ip_send(skb); -#endif -} -#endif /* NETDEV_23 */ - -enum ipsec_xmit_value -ipsec_tunnel_strip_hard_header(struct ipsec_xmit_state *ixs) -{ - /* ixs->physdev->hard_header_len is unreliable and should not be used */ - ixs->hard_header_len = (unsigned char *)(ixs->iph) - ixs->skb->data; - - if(ixs->hard_header_len < 0) { - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_error:ipsec_xmit_strip_hard_header: " - "Negative hard_header_len (%d)?!\n", ixs->hard_header_len); - ixs->stats->tx_dropped++; - return IPSEC_XMIT_BADHHLEN; - } - - /* while ixs->physdev->hard_header_len is unreliable and - * should not be trusted, it accurate and required for ATM, GRE and - * some other interfaces to work. Thanks to Willy Tarreau - * <willy@w.ods.org>. - */ - if(ixs->hard_header_len == 0) { /* no hard header present */ - ixs->hard_header_stripped = 1; - ixs->hard_header_len = ixs->physdev->hard_header_len; - } - -#ifdef CONFIG_IPSEC_DEBUG - if (debug_tunnel & DB_TN_XMIT) { - int i; - char c; - - printk(KERN_INFO "klips_debug:ipsec_xmit_strip_hard_header: " - ">>> skb->len=%ld hard_header_len:%d", - (unsigned long int)ixs->skb->len, ixs->hard_header_len); - c = ' '; - for (i=0; i < ixs->hard_header_len; i++) { - printk("%c%02x", c, ixs->skb->data[i]); - c = ':'; - } - printk(" \n"); - } -#endif /* CONFIG_IPSEC_DEBUG */ - - KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); - - KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, - "klips_debug:ipsec_xmit_strip_hard_header: " - "Original head,tailroom: %d,%d\n", - skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); - - return IPSEC_XMIT_OK; -} - -enum ipsec_xmit_value -ipsec_tunnel_SAlookup(struct ipsec_xmit_state *ixs) -{ - /* - * First things first -- look us up in the erouting tables. - */ - ixs->matcher.sen_len = sizeof (struct sockaddr_encap); - ixs->matcher.sen_family = AF_ENCAP; - ixs->matcher.sen_type = SENT_IP4; - ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr; - ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr; - ixs->matcher.sen_proto = ixs->iph->protocol; - ipsec_extract_ports(ixs->iph, &ixs->matcher); - - /* - * The spinlock is to prevent any other process from accessing or deleting - * the eroute while we are using and updating it. - */ - spin_lock(&eroute_lock); - - ixs->eroute = ipsec_findroute(&ixs->matcher); - - if(ixs->iph->protocol == IPPROTO_UDP) { - if(ixs->skb->sk) { - ixs->sport=ntohs(ixs->skb->sk->sport); - ixs->dport=ntohs(ixs->skb->sk->dport); - } else if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 && - ((ixs->skb->len - ixs->hard_header_len) >= - ((ixs->iph->ihl << 2) + sizeof(struct udphdr)))) { - ixs->sport=ntohs(((struct udphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2)))->source); - ixs->dport=ntohs(((struct udphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl<<2)))->dest); - } else { - ixs->sport=0; ixs->dport=0; - } - } - - /* default to a %drop eroute */ - ixs->outgoing_said.proto = IPPROTO_INT; - ixs->outgoing_said.spi = htonl(SPI_DROP); - ixs->outgoing_said.dst.s_addr = INADDR_ANY; - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_xmit_SAlookup: " - "checking for local udp/500 IKE packet " - "saddr=%x, er=0p%p, daddr=%x, er_dst=%x, proto=%d sport=%d dport=%d\n", - ntohl((unsigned int)ixs->iph->saddr), - ixs->eroute, - ntohl((unsigned int)ixs->iph->daddr), - ixs->eroute ? ntohl((unsigned int)ixs->eroute->er_said.dst.s_addr) : 0, - ixs->iph->protocol, - ixs->sport, - ixs->dport); - - /* - * Quick cheat for now...are we udp/500 or udp/4500? If so, let it through - * without interference since it is most likely an IKE packet. - */ - - if (ip_chk_addr((unsigned long)ixs->iph->saddr) == IS_MYADDR - && (!ixs->eroute - || ixs->iph->daddr == ixs->eroute->er_said.dst.s_addr - || INADDR_ANY == ixs->eroute->er_said.dst.s_addr) - && ((ixs->sport == 500) || (ixs->sport == 4500))) { - /* Whatever the eroute, this is an IKE message - * from us (i.e. not being forwarded). - * Furthermore, if there is a tunnel eroute, - * the destination is the peer for this eroute. - * So %pass the packet: modify the default %drop. - */ - ixs->outgoing_said.spi = htonl(SPI_PASS); - if(!(ixs->skb->sk) && ((ntohs(ixs->iph->frag_off) & IP_MF) != 0)) { - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_xmit_SAlookup: " - "local UDP/500 (probably IKE) passthrough: base fragment, rest of fragments will probably get filtered.\n"); - } - } else if (ixs->eroute) { - ixs->eroute->er_count++; - ixs->eroute->er_lasttime = jiffies/HZ; - if(ixs->eroute->er_said.proto==IPPROTO_INT - && ixs->eroute->er_said.spi==htonl(SPI_HOLD)) { - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_xmit_SAlookup: " - "shunt SA of HOLD: skb stored in HOLD.\n"); - if(ixs->eroute->er_last != NULL) { - kfree_skb(ixs->eroute->er_last); - } - ixs->eroute->er_last = ixs->skb; - ixs->skb = NULL; - ixs->stats->tx_dropped++; - spin_unlock(&eroute_lock); - return IPSEC_XMIT_STOLEN; - } - ixs->outgoing_said = ixs->eroute->er_said; - ixs->eroute_pid = ixs->eroute->er_pid; - /* Copy of the ident for the TRAP/TRAPSUBNET eroutes */ - if(ixs->outgoing_said.proto==IPPROTO_INT - && (ixs->outgoing_said.spi==htonl(SPI_TRAP) - || (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)))) { - int len; - - ixs->ips.ips_ident_s.type = ixs->eroute->er_ident_s.type; - ixs->ips.ips_ident_s.id = ixs->eroute->er_ident_s.id; - ixs->ips.ips_ident_s.len = ixs->eroute->er_ident_s.len; - if (ixs->ips.ips_ident_s.len) { - len = ixs->ips.ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_xmit_SAlookup: " - "allocating %d bytes for ident_s shunt SA of HOLD: skb stored in HOLD.\n", - len); - if ((ixs->ips.ips_ident_s.data = kmalloc(len, GFP_ATOMIC)) == NULL) { - printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: " - "Failed, tried to allocate %d bytes for source ident.\n", - len); - ixs->stats->tx_dropped++; - spin_unlock(&eroute_lock); - return IPSEC_XMIT_ERRMEMALLOC; - } - memcpy(ixs->ips.ips_ident_s.data, ixs->eroute->er_ident_s.data, len); - } - ixs->ips.ips_ident_d.type = ixs->eroute->er_ident_d.type; - ixs->ips.ips_ident_d.id = ixs->eroute->er_ident_d.id; - ixs->ips.ips_ident_d.len = ixs->eroute->er_ident_d.len; - if (ixs->ips.ips_ident_d.len) { - len = ixs->ips.ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_xmit_SAlookup: " - "allocating %d bytes for ident_d shunt SA of HOLD: skb stored in HOLD.\n", - len); - if ((ixs->ips.ips_ident_d.data = kmalloc(len, GFP_ATOMIC)) == NULL) { - printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: " - "Failed, tried to allocate %d bytes for dest ident.\n", - len); - ixs->stats->tx_dropped++; - spin_unlock(&eroute_lock); - return IPSEC_XMIT_ERRMEMALLOC; - } - memcpy(ixs->ips.ips_ident_d.data, ixs->eroute->er_ident_d.data, len); - } - } - } - - spin_unlock(&eroute_lock); - return IPSEC_XMIT_OK; -} - -enum ipsec_xmit_value -ipsec_tunnel_restore_hard_header(struct ipsec_xmit_state*ixs) -{ - KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, - "klips_debug:ipsec_xmit_restore_hard_header: " - "After recursive xforms -- head,tailroom: %d,%d\n", - skb_headroom(ixs->skb), - skb_tailroom(ixs->skb)); - - if(ixs->saved_header) { - if(skb_headroom(ixs->skb) < ixs->hard_header_len) { - printk(KERN_WARNING - "klips_error:ipsec_xmit_restore_hard_header: " - "tried to skb_push hhlen=%d, %d available. This should never happen, please report.\n", - ixs->hard_header_len, - skb_headroom(ixs->skb)); - ixs->stats->tx_errors++; - return IPSEC_XMIT_PUSHPULLERR; - - } - skb_push(ixs->skb, ixs->hard_header_len); - { - int i; - for (i = 0; i < ixs->hard_header_len; i++) { - ixs->skb->data[i] = ixs->saved_header[i]; - } - } - } -#ifdef CONFIG_IPSEC_NAT_TRAVERSAL - if (ixs->natt_type && ixs->natt_head) { - struct iphdr *ipp = ixs->skb->nh.iph; - struct udphdr *udp; - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_tunnel_start_xmit: " - "encapsulating packet into UDP (NAT-Traversal) (%d %d)\n", - ixs->natt_type, ixs->natt_head); - ixs->iphlen = ipp->ihl << 2; - ipp->tot_len = - htons(ntohs(ipp->tot_len) + ixs->natt_head); - if(skb_tailroom(ixs->skb) < ixs->natt_head) { - printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: " - "tried to skb_put %d, %d available. " - "This should never happen, please report.\n", - ixs->natt_head, - skb_tailroom(ixs->skb)); - ixs->stats->tx_errors++; - return IPSEC_XMIT_ESPUDP; - } - skb_put(ixs->skb, ixs->natt_head); - udp = (struct udphdr *)((char *)ipp + ixs->iphlen); - /* move ESP hdr after UDP hdr */ - memmove((void *)((char *)udp + ixs->natt_head), - (void *)(udp), - ntohs(ipp->tot_len) - ixs->iphlen - ixs->natt_head); - /* clear UDP & Non-IKE Markers (if any) */ - memset(udp, 0, ixs->natt_head); - /* fill UDP with usefull informations ;-) */ - udp->source = htons(ixs->natt_sport); - udp->dest = htons(ixs->natt_dport); - udp->len = htons(ntohs(ipp->tot_len) - ixs->iphlen); - /* set protocol */ - ipp->protocol = IPPROTO_UDP; - /* fix IP checksum */ - ipp->check = 0; - ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); - } -#endif - KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, - "klips_debug:ipsec_xmit_restore_hard_header: " - "With hard_header, final head,tailroom: %d,%d\n", - skb_headroom(ixs->skb), - skb_tailroom(ixs->skb)); - - return IPSEC_XMIT_OK; -} - -enum ipsec_xmit_value -ipsec_tunnel_send(struct ipsec_xmit_state*ixs) -{ -#ifdef NETDEV_25 - struct flowi fl; -#endif - -#ifdef NET_21 /* 2.2 and 2.4 kernels */ - /* new route/dst cache code from James Morris */ - ixs->skb->dev = ixs->physdev; -#ifdef NETDEV_25 - fl.oif = ixs->physdev->iflink; - fl.nl_u.ip4_u.daddr = ixs->skb->nh.iph->daddr; - fl.nl_u.ip4_u.saddr = ixs->pass ? 0 : ixs->skb->nh.iph->saddr; - fl.nl_u.ip4_u.tos = RT_TOS(ixs->skb->nh.iph->tos); - fl.proto = ixs->skb->nh.iph->protocol; - if ((ixs->error = ip_route_output_key(&ixs->route, &fl))) { -#else - /*skb_orphan(ixs->skb);*/ - if((ixs->error = ip_route_output(&ixs->route, - ixs->skb->nh.iph->daddr, - ixs->pass ? 0 : ixs->skb->nh.iph->saddr, - RT_TOS(ixs->skb->nh.iph->tos), - /* mcr->rgb: should this be 0 instead? */ - ixs->physdev->iflink))) { -#endif - ixs->stats->tx_errors++; - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_xmit_send: " - "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n", - ixs->error, - ixs->route->u.dst.dev->name); - return IPSEC_XMIT_ROUTEERR; - } - if(ixs->dev == ixs->route->u.dst.dev) { - ip_rt_put(ixs->route); - /* This is recursion, drop it. */ - ixs->stats->tx_errors++; - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_xmit_send: " - "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", - ixs->dev->name); - return IPSEC_XMIT_RECURSDETECT; - } - dst_release(ixs->skb->dst); - ixs->skb->dst = &ixs->route->u.dst; - ixs->stats->tx_bytes += ixs->skb->len; - if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) { - ixs->stats->tx_errors++; - printk(KERN_WARNING - "klips_error:ipsec_xmit_send: " - "tried to __skb_pull nh-data=%ld, %d available. This should never happen, please report.\n", - (unsigned long)(ixs->skb->nh.raw - ixs->skb->data), - ixs->skb->len); - return IPSEC_XMIT_PUSHPULLERR; - } - __skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data); -#ifdef SKB_RESET_NFCT - if(!ixs->pass) { - nf_conntrack_put(ixs->skb->nfct); - ixs->skb->nfct = NULL; - } -#ifdef CONFIG_NETFILTER_DEBUG - ixs->skb->nf_debug = 0; -#endif /* CONFIG_NETFILTER_DEBUG */ -#endif /* SKB_RESET_NFCT */ - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_xmit_send: " - "...done, calling ip_send() on device:%s\n", - ixs->skb->dev ? ixs->skb->dev->name : "NULL"); - KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->skb->nh.iph); -#ifdef NETDEV_23 /* 2.4 kernels */ - { - int err; - - err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev, - ipsec_tunnel_xmit2); - if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) { - if(net_ratelimit()) - printk(KERN_ERR - "klips_error:ipsec_xmit_send: " - "ip_send() failed, err=%d\n", - -err); - ixs->stats->tx_errors++; - ixs->stats->tx_aborted_errors++; - ixs->skb = NULL; - return IPSEC_XMIT_IPSENDFAILURE; - } - } -#else /* NETDEV_23 */ /* 2.2 kernels */ - ip_send(ixs->skb); -#endif /* NETDEV_23 */ -#else /* NET_21 */ /* 2.0 kernels */ - ixs->skb->arp = 1; - /* ISDN/ASYNC PPP from Matjaz Godec. */ - /* skb->protocol = htons(ETH_P_IP); */ - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_xmit_send: " - "...done, calling dev_queue_xmit() or ip_fragment().\n"); - IP_SEND(ixs->skb, ixs->physdev); -#endif /* NET_21 */ - ixs->stats->tx_packets++; - - ixs->skb = NULL; - - return IPSEC_XMIT_OK; -} - -void -ipsec_tunnel_cleanup(struct ipsec_xmit_state*ixs) -{ -#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) - netif_wake_queue(ixs->dev); -#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ - ixs->dev->tbusy = 0; -#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ - if(ixs->saved_header) { - kfree(ixs->saved_header); - } - if(ixs->skb) { - dev_kfree_skb(ixs->skb, FREE_WRITE); - } - if(ixs->oskb) { - dev_kfree_skb(ixs->oskb, FREE_WRITE); - } - if (ixs->ips.ips_ident_s.data) { - kfree(ixs->ips.ips_ident_s.data); - } - if (ixs->ips.ips_ident_d.data) { - kfree(ixs->ips.ips_ident_d.data); - } -} - -/* - * This function assumes it is being called from dev_queue_xmit() - * and that skb is filled properly by that function. - */ -int -ipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev) -{ - struct ipsec_xmit_state ixs_mem; - struct ipsec_xmit_state *ixs = &ixs_mem; - enum ipsec_xmit_value stat; - -#ifdef CONFIG_IPSEC_NAT_TRAVERSAL - ixs->natt_type = 0, ixs->natt_head = 0; - ixs->natt_sport = 0, ixs->natt_dport = 0; -#endif - - memset((caddr_t)ixs, 0, sizeof(*ixs)); - ixs->oskb = NULL; - ixs->saved_header = NULL; /* saved copy of the hard header */ - ixs->route = NULL; - memset((caddr_t)&(ixs->ips), 0, sizeof(ixs->ips)); - ixs->dev = dev; - ixs->skb = skb; - - stat = ipsec_xmit_sanity_check_dev(ixs); - if(stat != IPSEC_XMIT_OK) { - goto cleanup; - } - - stat = ipsec_xmit_sanity_check_skb(ixs); - if(stat != IPSEC_XMIT_OK) { - goto cleanup; - } - - stat = ipsec_tunnel_strip_hard_header(ixs); - if(stat != IPSEC_XMIT_OK) { - goto cleanup; - } - - stat = ipsec_tunnel_SAlookup(ixs); - if(stat != IPSEC_XMIT_OK) { - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_tunnel_start_xmit: SAlookup failed: %d\n", - stat); - goto cleanup; - } - - ixs->innersrc = ixs->iph->saddr; - /* start encapsulation loop here XXX */ - do { - stat = ipsec_xmit_encap_bundle(ixs); - if(stat != IPSEC_XMIT_OK) { - if(stat == IPSEC_XMIT_PASS) { - goto bypass; - } - - KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, - "klips_debug:ipsec_tunnel_start_xmit: encap_bundle failed: %d\n", - stat); - goto cleanup; - } - - ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr; - ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr; - ixs->matcher.sen_proto = ixs->iph->protocol; - ipsec_extract_ports(ixs->iph, &ixs->matcher); - - spin_lock(&eroute_lock); - ixs->eroute = ipsec_findroute(&ixs->matcher); - if(ixs->eroute) { - ixs->outgoing_said = ixs->eroute->er_said; - ixs->eroute_pid = ixs->eroute->er_pid; - ixs->eroute->er_count++; - ixs->eroute->er_lasttime = jiffies/HZ; - } - spin_unlock(&eroute_lock); - - KLIPS_PRINT((debug_tunnel & DB_TN_XMIT) && - /* ((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc)) */ - (ixs->orgedst != ixs->outgoing_said.dst.s_addr) && - ixs->outgoing_said.dst.s_addr && - ixs->eroute, - "klips_debug:ipsec_tunnel_start_xmit: " - "We are recursing here.\n"); - - } while(/*((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc))*/ - (ixs->orgedst != ixs->outgoing_said.dst.s_addr) && - ixs->outgoing_said.dst.s_addr && - ixs->eroute); - - stat = ipsec_tunnel_restore_hard_header(ixs); - if(stat != IPSEC_XMIT_OK) { - goto cleanup; - } - - bypass: - stat = ipsec_tunnel_send(ixs); - - cleanup: - ipsec_tunnel_cleanup(ixs); - - return 0; -} - -DEBUG_NO_STATIC struct net_device_stats * -ipsec_tunnel_get_stats(struct device *dev) -{ - return &(((struct ipsecpriv *)(dev->priv))->mystats); -} - -/* - * Revectored calls. - * For each of these calls, a field exists in our private structure. - */ - -DEBUG_NO_STATIC int -ipsec_tunnel_hard_header(struct sk_buff *skb, struct device *dev, - unsigned short type, void *daddr, void *saddr, unsigned len) -{ - struct ipsecpriv *prv = dev->priv; - struct device *tmp; - int ret; - struct net_device_stats *stats; /* This device's statistics */ - - if(skb == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_hard_header: " - "no skb...\n"); - return -ENODATA; - } - - if(dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_hard_header: " - "no device...\n"); - return -ENODEV; - } - - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_hard_header: " - "skb->dev=%s dev=%s.\n", - skb->dev ? skb->dev->name : "NULL", - dev->name); - - if(prv == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_hard_header: " - "no private space associated with dev=%s\n", - dev->name ? dev->name : "NULL"); - return -ENODEV; - } - - stats = (struct net_device_stats *) &(prv->mystats); - - if(prv->dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_hard_header: " - "no physical device associated with dev=%s\n", - dev->name ? dev->name : "NULL"); - stats->tx_dropped++; - return -ENODEV; - } - - /* check if we have to send a IPv6 packet. It might be a Router - Solicitation, where the building of the packet happens in - reverse order: - 1. ll hdr, - 2. IPv6 hdr, - 3. ICMPv6 hdr - -> skb->nh.raw is still uninitialized when this function is - called!! If this is no IPv6 packet, we can print debugging - messages, otherwise we skip all debugging messages and just - build the ll header */ - if(type != ETH_P_IPV6) { - /* execute this only, if we don't have to build the - header for a IPv6 packet */ - if(!prv->hard_header) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_hard_header: " - "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ", - saddr, - daddr, - len, - type, - dev->name); -#ifdef NET_21 - KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, - "ip=%08x->%08x\n", - (__u32)ntohl(skb->nh.iph->saddr), - (__u32)ntohl(skb->nh.iph->daddr) ); -#else /* NET_21 */ - KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, - "ip=%08x->%08x\n", - (__u32)ntohl(skb->ip_hdr->saddr), - (__u32)ntohl(skb->ip_hdr->daddr) ); -#endif /* NET_21 */ - stats->tx_dropped++; - return -ENODEV; - } - -#define da ((struct device *)(prv->dev))->dev_addr - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_hard_header: " - "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ", - saddr, - daddr, - len, - type, - dev->name, - prv->dev->name, - da[0], da[1], da[2], da[3], da[4], da[5]); -#ifdef NET_21 - KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, - "ip=%08x->%08x\n", - (__u32)ntohl(skb->nh.iph->saddr), - (__u32)ntohl(skb->nh.iph->daddr) ); -#else /* NET_21 */ - KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, - "ip=%08x->%08x\n", - (__u32)ntohl(skb->ip_hdr->saddr), - (__u32)ntohl(skb->ip_hdr->daddr) ); -#endif /* NET_21 */ - } else { - KLIPS_PRINT(debug_tunnel, - "klips_debug:ipsec_tunnel_hard_header: " - "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); - } - tmp = skb->dev; - skb->dev = prv->dev; - ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len); - skb->dev = tmp; - return ret; -} - -DEBUG_NO_STATIC int -#ifdef NET_21 -ipsec_tunnel_rebuild_header(struct sk_buff *skb) -#else /* NET_21 */ -ipsec_tunnel_rebuild_header(void *buff, struct device *dev, - unsigned long raddr, struct sk_buff *skb) -#endif /* NET_21 */ -{ - struct ipsecpriv *prv = skb->dev->priv; - struct device *tmp; - int ret; - struct net_device_stats *stats; /* This device's statistics */ - - if(skb->dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_rebuild_header: " - "no device..."); - return -ENODEV; - } - - if(prv == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_rebuild_header: " - "no private space associated with dev=%s", - skb->dev->name ? skb->dev->name : "NULL"); - return -ENODEV; - } - - stats = (struct net_device_stats *) &(prv->mystats); - - if(prv->dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_rebuild_header: " - "no physical device associated with dev=%s", - skb->dev->name ? skb->dev->name : "NULL"); - stats->tx_dropped++; - return -ENODEV; - } - - if(!prv->rebuild_header) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_rebuild_header: " - "physical device has been detached, packet dropped skb->dev=%s->NULL ", - skb->dev->name); -#ifdef NET_21 - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "ip=%08x->%08x\n", - (__u32)ntohl(skb->nh.iph->saddr), - (__u32)ntohl(skb->nh.iph->daddr) ); -#else /* NET_21 */ - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "ip=%08x->%08x\n", - (__u32)ntohl(skb->ip_hdr->saddr), - (__u32)ntohl(skb->ip_hdr->daddr) ); -#endif /* NET_21 */ - stats->tx_dropped++; - return -ENODEV; - } - - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel: " - "Revectored rebuild_header dev=%s->%s ", - skb->dev->name, prv->dev->name); -#ifdef NET_21 - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "ip=%08x->%08x\n", - (__u32)ntohl(skb->nh.iph->saddr), - (__u32)ntohl(skb->nh.iph->daddr) ); -#else /* NET_21 */ - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "ip=%08x->%08x\n", - (__u32)ntohl(skb->ip_hdr->saddr), - (__u32)ntohl(skb->ip_hdr->daddr) ); -#endif /* NET_21 */ - tmp = skb->dev; - skb->dev = prv->dev; - -#ifdef NET_21 - ret = prv->rebuild_header(skb); -#else /* NET_21 */ - ret = prv->rebuild_header(buff, prv->dev, raddr, skb); -#endif /* NET_21 */ - skb->dev = tmp; - return ret; -} - -DEBUG_NO_STATIC int -ipsec_tunnel_set_mac_address(struct device *dev, void *addr) -{ - struct ipsecpriv *prv = dev->priv; - - struct net_device_stats *stats; /* This device's statistics */ - - if(dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_set_mac_address: " - "no device..."); - return -ENODEV; - } - - if(prv == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_set_mac_address: " - "no private space associated with dev=%s", - dev->name ? dev->name : "NULL"); - return -ENODEV; - } - - stats = (struct net_device_stats *) &(prv->mystats); - - if(prv->dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_set_mac_address: " - "no physical device associated with dev=%s", - dev->name ? dev->name : "NULL"); - stats->tx_dropped++; - return -ENODEV; - } - - if(!prv->set_mac_address) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_set_mac_address: " - "physical device has been detached, cannot set - skb->dev=%s->NULL\n", - dev->name); - return -ENODEV; - } - - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_set_mac_address: " - "Revectored dev=%s->%s addr=0p%p\n", - dev->name, prv->dev->name, addr); - return prv->set_mac_address(prv->dev, addr); - -} - -#ifndef NET_21 -DEBUG_NO_STATIC void -ipsec_tunnel_cache_bind(struct hh_cache **hhp, struct device *dev, - unsigned short htype, __u32 daddr) -{ - struct ipsecpriv *prv = dev->priv; - - struct net_device_stats *stats; /* This device's statistics */ - - if(dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_cache_bind: " - "no device..."); - return; - } - - if(prv == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_cache_bind: " - "no private space associated with dev=%s", - dev->name ? dev->name : "NULL"); - return; - } - - stats = (struct net_device_stats *) &(prv->mystats); - - if(prv->dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_cache_bind: " - "no physical device associated with dev=%s", - dev->name ? dev->name : "NULL"); - stats->tx_dropped++; - return; - } - - if(!prv->header_cache_bind) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_cache_bind: " - "physical device has been detached, cannot set - skb->dev=%s->NULL\n", - dev->name); - stats->tx_dropped++; - return; - } - - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_cache_bind: " - "Revectored \n"); - prv->header_cache_bind(hhp, prv->dev, htype, daddr); - return; -} -#endif /* !NET_21 */ - - -DEBUG_NO_STATIC void -ipsec_tunnel_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr) -{ - struct ipsecpriv *prv = dev->priv; - - struct net_device_stats *stats; /* This device's statistics */ - - if(dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_cache_update: " - "no device..."); - return; - } - - if(prv == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_cache_update: " - "no private space associated with dev=%s", - dev->name ? dev->name : "NULL"); - return; - } - - stats = (struct net_device_stats *) &(prv->mystats); - - if(prv->dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_cache_update: " - "no physical device associated with dev=%s", - dev->name ? dev->name : "NULL"); - stats->tx_dropped++; - return; - } - - if(!prv->header_cache_update) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_cache_update: " - "physical device has been detached, cannot set - skb->dev=%s->NULL\n", - dev->name); - return; - } - - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel: " - "Revectored cache_update\n"); - prv->header_cache_update(hh, prv->dev, haddr); - return; -} - -#ifdef NET_21 -DEBUG_NO_STATIC int -ipsec_tunnel_neigh_setup(struct neighbour *n) -{ - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_neigh_setup:\n"); - - if (n->nud_state == NUD_NONE) { - n->ops = &arp_broken_ops; - n->output = n->ops->output; - } - return 0; -} - -DEBUG_NO_STATIC int -ipsec_tunnel_neigh_setup_dev(struct device *dev, struct neigh_parms *p) -{ - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_neigh_setup_dev: " - "setting up %s\n", - dev ? dev->name : "NULL"); - - if (p->tbl->family == AF_INET) { - p->neigh_setup = ipsec_tunnel_neigh_setup; - p->ucast_probes = 0; - p->mcast_probes = 0; - } - return 0; -} -#endif /* NET_21 */ - -/* - * We call the attach routine to attach another device. - */ - -DEBUG_NO_STATIC int -ipsec_tunnel_attach(struct device *dev, struct device *physdev) -{ - int i; - struct ipsecpriv *prv = dev->priv; - - if(dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_attach: " - "no device..."); - return -ENODEV; - } - - if(prv == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_attach: " - "no private space associated with dev=%s", - dev->name ? dev->name : "NULL"); - return -ENODATA; - } - - prv->dev = physdev; - prv->hard_start_xmit = physdev->hard_start_xmit; - prv->get_stats = physdev->get_stats; - - if (physdev->hard_header) { - prv->hard_header = physdev->hard_header; - dev->hard_header = ipsec_tunnel_hard_header; - } else - dev->hard_header = NULL; - - if (physdev->rebuild_header) { - prv->rebuild_header = physdev->rebuild_header; - dev->rebuild_header = ipsec_tunnel_rebuild_header; - } else - dev->rebuild_header = NULL; - - if (physdev->set_mac_address) { - prv->set_mac_address = physdev->set_mac_address; - dev->set_mac_address = ipsec_tunnel_set_mac_address; - } else - dev->set_mac_address = NULL; - -#ifndef NET_21 - if (physdev->header_cache_bind) { - prv->header_cache_bind = physdev->header_cache_bind; - dev->header_cache_bind = ipsec_tunnel_cache_bind; - } else - dev->header_cache_bind = NULL; -#endif /* !NET_21 */ - - if (physdev->header_cache_update) { - prv->header_cache_update = physdev->header_cache_update; - dev->header_cache_update = ipsec_tunnel_cache_update; - } else - dev->header_cache_update = NULL; - - dev->hard_header_len = physdev->hard_header_len; - -#ifdef NET_21 -/* prv->neigh_setup = physdev->neigh_setup; */ - dev->neigh_setup = ipsec_tunnel_neigh_setup_dev; -#endif /* NET_21 */ - dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */ - prv->mtu = physdev->mtu; - -#ifdef PHYSDEV_TYPE - dev->type = physdev->type; /* ARPHRD_TUNNEL; */ -#endif /* PHYSDEV_TYPE */ - - dev->addr_len = physdev->addr_len; - for (i=0; i<dev->addr_len; i++) { - dev->dev_addr[i] = physdev->dev_addr[i]; - } -#ifdef CONFIG_IPSEC_DEBUG - if(debug_tunnel & DB_TN_INIT) { - printk(KERN_INFO "klips_debug:ipsec_tunnel_attach: " - "physical device %s being attached has HW address: %2x", - physdev->name, physdev->dev_addr[0]); - for (i=1; i < physdev->addr_len; i++) { - printk(":%02x", physdev->dev_addr[i]); - } - printk("\n"); - } -#endif /* CONFIG_IPSEC_DEBUG */ - - return 0; -} - -/* - * We call the detach routine to detach the ipsec tunnel from another device. - */ - -DEBUG_NO_STATIC int -ipsec_tunnel_detach(struct device *dev) -{ - int i; - struct ipsecpriv *prv = dev->priv; - - if(dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_detach: " - "no device..."); - return -ENODEV; - } - - if(prv == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, - "klips_debug:ipsec_tunnel_detach: " - "no private space associated with dev=%s", - dev->name ? dev->name : "NULL"); - return -ENODATA; - } - - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_detach: " - "physical device %s being detached from virtual device %s\n", - prv->dev ? prv->dev->name : "NULL", - dev->name); - - ipsec_dev_put(prv->dev); - prv->dev = NULL; - prv->hard_start_xmit = NULL; - prv->get_stats = NULL; - - prv->hard_header = NULL; -#ifdef DETACH_AND_DOWN - dev->hard_header = NULL; -#endif /* DETACH_AND_DOWN */ - - prv->rebuild_header = NULL; -#ifdef DETACH_AND_DOWN - dev->rebuild_header = NULL; -#endif /* DETACH_AND_DOWN */ - - prv->set_mac_address = NULL; -#ifdef DETACH_AND_DOWN - dev->set_mac_address = NULL; -#endif /* DETACH_AND_DOWN */ - -#ifndef NET_21 - prv->header_cache_bind = NULL; -#ifdef DETACH_AND_DOWN - dev->header_cache_bind = NULL; -#endif /* DETACH_AND_DOWN */ -#endif /* !NET_21 */ - - prv->header_cache_update = NULL; -#ifdef DETACH_AND_DOWN - dev->header_cache_update = NULL; -#endif /* DETACH_AND_DOWN */ - -#ifdef NET_21 -/* prv->neigh_setup = NULL; */ -#ifdef DETACH_AND_DOWN - dev->neigh_setup = NULL; -#endif /* DETACH_AND_DOWN */ -#endif /* NET_21 */ - dev->hard_header_len = 0; -#ifdef DETACH_AND_DOWN - dev->mtu = 0; -#endif /* DETACH_AND_DOWN */ - prv->mtu = 0; - for (i=0; i<MAX_ADDR_LEN; i++) { - dev->dev_addr[i] = 0; - } - dev->addr_len = 0; -#ifdef PHYSDEV_TYPE - dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ -#endif /* PHYSDEV_TYPE */ - - return 0; -} - -/* - * We call the clear routine to detach all ipsec tunnels from other devices. - */ -DEBUG_NO_STATIC int -ipsec_tunnel_clear(void) -{ - int i; - struct device *ipsecdev = NULL, *prvdev; - struct ipsecpriv *prv; - char name[9]; - int ret; - - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_clear: .\n"); - - for(i = 0; i < IPSEC_NUM_IF; i++) { - ipsecdev = ipsecdevices[i]; - if(ipsecdev != NULL) { - if((prv = (struct ipsecpriv *)(ipsecdev->priv))) { - prvdev = (struct device *)(prv->dev); - if(prvdev) { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_clear: " - "physical device for device %s is %s\n", - name, prvdev->name); - if((ret = ipsec_tunnel_detach(ipsecdev))) { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_clear: " - "error %d detatching device %s from device %s.\n", - ret, name, prvdev->name); - return ret; - } - } - } - } - } - return 0; -} - -DEBUG_NO_STATIC int -ipsec_tunnel_ioctl(struct device *dev, struct ifreq *ifr, int cmd) -{ - struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data; - struct ipsecpriv *prv = dev->priv; - struct device *them; /* physical device */ -#ifdef CONFIG_IP_ALIAS - char *colon; - char realphysname[IFNAMSIZ]; -#endif /* CONFIG_IP_ALIAS */ - - if(dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_ioctl: " - "device not supplied.\n"); - return -ENODEV; - } - - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_ioctl: " - "tncfg service call #%d for dev=%s\n", - cmd, - dev->name ? dev->name : "NULL"); - switch (cmd) { - /* attach a virtual ipsec? device to a physical device */ - case IPSEC_SET_DEV: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_ioctl: " - "calling ipsec_tunnel_attatch...\n"); -#ifdef CONFIG_IP_ALIAS - /* If this is an IP alias interface, get its real physical name */ - strncpy(realphysname, cf->cf_name, IFNAMSIZ); - realphysname[IFNAMSIZ-1] = 0; - colon = strchr(realphysname, ':'); - if (colon) *colon = 0; - them = ipsec_dev_get(realphysname); -#else /* CONFIG_IP_ALIAS */ - them = ipsec_dev_get(cf->cf_name); -#endif /* CONFIG_IP_ALIAS */ - - if (them == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_ioctl: " - "physical device %s requested is null\n", - cf->cf_name); - return -ENXIO; - } - -#if 0 - if (them->flags & IFF_UP) { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_ioctl: " - "physical device %s requested is not up.\n", - cf->cf_name); - ipsec_dev_put(them); - return -ENXIO; - } -#endif - - if (prv && prv->dev) { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_ioctl: " - "virtual device is already connected to %s.\n", - prv->dev->name ? prv->dev->name : "NULL"); - ipsec_dev_put(them); - return -EBUSY; - } - return ipsec_tunnel_attach(dev, them); - - case IPSEC_DEL_DEV: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_ioctl: " - "calling ipsec_tunnel_detatch.\n"); - if (! prv->dev) { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_ioctl: " - "physical device not connected.\n"); - return -ENODEV; - } - return ipsec_tunnel_detach(dev); - - case IPSEC_CLR_DEV: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_ioctl: " - "calling ipsec_tunnel_clear.\n"); - return ipsec_tunnel_clear(); - - default: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_ioctl: " - "unknown command %d.\n", - cmd); - return -EOPNOTSUPP; - } -} - -int -ipsec_device_event(struct notifier_block *unused, unsigned long event, void *ptr) -{ - struct device *dev = ptr; - struct device *ipsec_dev; - struct ipsecpriv *priv; - int i; - - if (dev == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "dev=NULL for event type %ld.\n", - event); - return(NOTIFY_DONE); - } - - /* check for loopback devices */ - if (dev && (dev->flags & IFF_LOOPBACK)) { - return(NOTIFY_DONE); - } - - switch (event) { - case NETDEV_DOWN: - /* look very carefully at the scope of these compiler - directives before changing anything... -- RGB */ -#ifdef NET_21 - case NETDEV_UNREGISTER: - switch (event) { - case NETDEV_DOWN: -#endif /* NET_21 */ - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "NETDEV_DOWN dev=%s flags=%x\n", - dev->name, - dev->flags); - if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) { - printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n", - dev->name); - } -#ifdef NET_21 - break; - case NETDEV_UNREGISTER: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "NETDEV_UNREGISTER dev=%s flags=%x\n", - dev->name, - dev->flags); - break; - } -#endif /* NET_21 */ - - /* find the attached physical device and detach it. */ - for(i = 0; i < IPSEC_NUM_IF; i++) { - ipsec_dev = ipsecdevices[i]; - - if(ipsec_dev) { - priv = (struct ipsecpriv *)(ipsec_dev->priv); - if(priv) { - ; - if(((struct device *)(priv->dev)) == dev) { - /* dev_close(ipsec_dev); */ - /* return */ ipsec_tunnel_detach(ipsec_dev); - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "device '%s' has been detached.\n", - ipsec_dev->name); - break; - } - } else { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "device '%s' has no private data space!\n", - ipsec_dev->name); - } - } - } - break; - case NETDEV_UP: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "NETDEV_UP dev=%s\n", - dev->name); - break; -#ifdef NET_21 - case NETDEV_REBOOT: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "NETDEV_REBOOT dev=%s\n", - dev->name); - break; - case NETDEV_CHANGE: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "NETDEV_CHANGE dev=%s flags=%x\n", - dev->name, - dev->flags); - break; - case NETDEV_REGISTER: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "NETDEV_REGISTER dev=%s\n", - dev->name); - break; - case NETDEV_CHANGEMTU: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "NETDEV_CHANGEMTU dev=%s to mtu=%d\n", - dev->name, - dev->mtu); - break; - case NETDEV_CHANGEADDR: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "NETDEV_CHANGEADDR dev=%s\n", - dev->name); - break; - case NETDEV_GOING_DOWN: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "NETDEV_GOING_DOWN dev=%s\n", - dev->name); - break; - case NETDEV_CHANGENAME: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "NETDEV_CHANGENAME dev=%s\n", - dev->name); - break; -#endif /* NET_21 */ - default: - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_device_event: " - "event type %ld unrecognised for dev=%s\n", - event, - dev->name); - break; - } - return NOTIFY_DONE; -} - -/* - * Called when an ipsec tunnel device is initialized. - * The ipsec tunnel device structure is passed to us. - */ - -int -ipsec_tunnel_init(struct device *dev) -{ - int i; - - KLIPS_PRINT(debug_tunnel, - "klips_debug:ipsec_tunnel_init: " - "allocating %lu bytes initialising device: %s\n", - (unsigned long) sizeof(struct ipsecpriv), - dev->name ? dev->name : "NULL"); - - /* Add our tunnel functions to the device */ - dev->open = ipsec_tunnel_open; - dev->stop = ipsec_tunnel_close; - dev->hard_start_xmit = ipsec_tunnel_start_xmit; - dev->get_stats = ipsec_tunnel_get_stats; - - dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); - - for(i = 0; i < sizeof(zeroes); i++) { - ((__u8*)(zeroes))[i] = 0; - } - -#ifndef NET_21 - /* Initialize the tunnel device structure */ - for (i = 0; i < DEV_NUMBUFFS; i++) - skb_queue_head_init(&dev->buffs[i]); -#endif /* !NET_21 */ - - dev->set_multicast_list = NULL; - dev->do_ioctl = ipsec_tunnel_ioctl; - dev->hard_header = NULL; - dev->rebuild_header = NULL; - dev->set_mac_address = NULL; -#ifndef NET_21 - dev->header_cache_bind = NULL; -#endif /* !NET_21 */ - dev->header_cache_update= NULL; - -#ifdef NET_21 -/* prv->neigh_setup = NULL; */ - dev->neigh_setup = ipsec_tunnel_neigh_setup_dev; -#endif /* NET_21 */ - dev->hard_header_len = 0; - dev->mtu = 0; - dev->addr_len = 0; - dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ /* ARPHRD_ETHER; */ - dev->tx_queue_len = 10; /* Small queue */ - memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ - - /* New-style flags. */ - dev->flags = IFF_NOARP /* 0 */ /* Petr Novak */; -#ifdef NET_21 - dev_init_buffers(dev); -#else /* NET_21 */ - dev->family = AF_INET; - dev->pa_addr = 0; - dev->pa_brdaddr = 0; - dev->pa_mask = 0; - dev->pa_alen = 4; -#endif /* NET_21 */ - - /* We're done. Have I forgotten anything? */ - return 0; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Module specific interface (but it links with the rest of IPSEC) */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -int -ipsec_tunnel_probe(struct device *dev) -{ - ipsec_tunnel_init(dev); - return 0; -} - -struct device *ipsecdevices[IPSEC_NUM_IF]; - -int -ipsec_tunnel_init_devices(void) -{ - int i; - char name[IFNAMSIZ]; - struct device *dev_ipsec; - - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_init_devices: " - "creating and registering IPSEC_NUM_IF=%u devices, allocating %lu per device, IFNAMSIZ=%u.\n", - IPSEC_NUM_IF, - (unsigned long) (sizeof(struct device) + IFNAMSIZ), - IFNAMSIZ); - - for(i = 0; i < IPSEC_NUM_IF; i++) { - sprintf(name, IPSEC_DEV_FORMAT, i); - dev_ipsec = (struct device*)kmalloc(sizeof(struct device), GFP_KERNEL); - if (dev_ipsec == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_init_devices: " - "failed to allocate memory for device %s, quitting device init.\n", - name); - return -ENOMEM; - } - memset((caddr_t)dev_ipsec, 0, sizeof(struct device)); -#ifdef NETDEV_23 - strncpy(dev_ipsec->name, name, sizeof(dev_ipsec->name)); -#else /* NETDEV_23 */ - dev_ipsec->name = (char*)kmalloc(IFNAMSIZ, GFP_KERNEL); - if (dev_ipsec->name == NULL) { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_init_devices: " - "failed to allocate memory for device %s name, quitting device init.\n", - name); - return -ENOMEM; - } - memset((caddr_t)dev_ipsec->name, 0, IFNAMSIZ); - strncpy(dev_ipsec->name, name, IFNAMSIZ); -#endif /* NETDEV_23 */ - dev_ipsec->next = NULL; - dev_ipsec->init = &ipsec_tunnel_probe; - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_init_devices: " - "registering device %s\n", - dev_ipsec->name); - - /* reference and hold the device reference */ - dev_hold(dev_ipsec); - ipsecdevices[i]=dev_ipsec; - - if (register_netdev(dev_ipsec) != 0) { - KLIPS_PRINT(1 || debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_init_devices: " - "registering device %s failed, quitting device init.\n", - dev_ipsec->name); - return -EIO; - } else { - KLIPS_PRINT(debug_tunnel & DB_TN_INIT, - "klips_debug:ipsec_tunnel_init_devices: " - "registering device %s succeeded, continuing...\n", - dev_ipsec->name); - } - } - return 0; -} - -/* void */ -int -ipsec_tunnel_cleanup_devices(void) -{ - int error = 0; - int i; - char name[32]; - struct device *dev_ipsec; - - for(i = 0; i < IPSEC_NUM_IF; i++) { - dev_ipsec = ipsecdevices[i]; - if(dev_ipsec == NULL) { - continue; - } - - /* release reference */ - ipsecdevices[i]=NULL; - ipsec_dev_put(dev_ipsec); - - KLIPS_PRINT(debug_tunnel, "Unregistering %s (refcnt=%d)\n", - name, - atomic_read(&dev_ipsec->refcnt)); - unregister_netdev(dev_ipsec); - KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", name); -#ifndef NETDEV_23 - kfree(dev_ipsec->name); - dev_ipsec->name=NULL; -#endif /* !NETDEV_23 */ - kfree(dev_ipsec->priv); - dev_ipsec->priv=NULL; - } - return error; -} |