📄 pfkey_v2.c
字号:
/* * RFC2367 PF_KEYv2 Key management API domain socket I/F * Copyright (C) 1999, 2000, 2001 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. * * RCSID $Id: pfkey_v2.c,v 1.60 2001/06/14 19:35:12 rgb Exp $ *//* * Template from /usr/src/linux-2.0.36/net/unix/af_unix.c. * Hints from /usr/src/linux-2.0.36/net/ipv4/udp.c. */#define __NO_VERSION__#include <linux/module.h>#include <linux/version.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/stat.h>#include <linux/socket.h>#include <linux/un.h>#include <linux/fcntl.h>#include <linux/termios.h>#include <linux/socket.h>#include <linux/sockios.h>#include <linux/net.h> /* struct socket */#include <linux/in.h>#include <linux/fs.h>#include <linux/malloc.h>#include <asm/segment.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include <net/sock.h> /* struct sock *//* #include <net/tcp.h> */#include <net/af_unix.h>#ifdef CONFIG_PROC_FS#include <linux/proc_fs.h>#endif /* CONFIG_PROC_FS */#include <linux/types.h> #include <freeswan.h>#ifdef NET_21#include <asm/uaccess.h>#include <linux/in6.h>#endif /* NET_21 */#include <pfkeyv2.h>#include <pfkey.h>#include "radij.h"#include "ipsec_encap.h"#include "ipsec_netlink.h"#ifdef CONFIG_IPSEC_DEBUGint debug_pfkey = 0;extern int sysctl_ipsec_debug_verbose;#endif /* CONFIG_IPSEC_DEBUG */#define min(a,b) (((a)<(b))?(a):(b))#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)#ifndef SOCKOPS_WRAPPED#define SOCKOPS_WRAPPED(name) name#endif /* SOCKOPS_WRAPPED */struct proto_ops SOCKOPS_WRAPPED(pfkey_ops);struct sock *pfkey_sock_list = NULL;struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1];struct socket_list *pfkey_open_sockets = NULL;struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1];int pfkey_msg_interp(struct sock *, struct sadb_msg *, struct sadb_msg **);intpfkey_list_remove_socket(struct socket *socketp, struct socket_list **sockets){ struct socket_list *socket_listp,*prev; if(!socketp) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_socket: " "NULL socketp handed in, failed.\n"); return -EINVAL; } if(!sockets) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_socket: " "NULL sockets list handed in, failed.\n"); return -EINVAL; } socket_listp = *sockets; prev = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_socket: " "removing sock=%p\n", socketp); while(socket_listp != NULL) { if(socket_listp->socketp == socketp) { if(prev != NULL) { prev->next = socket_listp->next; } else { *sockets = socket_listp->next; } kfree((void*)socket_listp); break; } prev = socket_listp; socket_listp = socket_listp->next; } return 0;}intpfkey_list_insert_socket(struct socket *socketp, struct socket_list **sockets){ struct socket_list *socket_listp; if(!socketp) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_socket: " "NULL socketp handed in, failed.\n"); return -EINVAL; } if(!sockets) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_socket: " "NULL sockets list handed in, failed.\n"); return -EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_socket: " "socketp=%p\n",socketp); if((socket_listp = (struct socket_list *)kmalloc(sizeof(struct socket_list), GFP_KERNEL)) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_socket: " "memory allocation error.\n"); return -ENOMEM; } socket_listp->socketp = socketp; socket_listp->next = *sockets; *sockets = socket_listp; return 0;} intpfkey_list_remove_supported(struct supported *supported, struct supported_list **supported_list){ struct supported_list *supported_listp = *supported_list, *prev = NULL; if(!supported) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_supported: " "NULL supported handed in, failed.\n"); return -EINVAL; } if(!supported_list) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_supported: " "NULL supported_list handed in, failed.\n"); return -EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_supported: " "removing supported=%p\n", supported); while(supported_listp != NULL) { if(supported_listp->supportedp == supported) { if(prev != NULL) { prev->next = supported_listp->next; } else { *supported_list = supported_listp->next; } kfree((void*)supported_listp); break; } prev = supported_listp; supported_listp = supported_listp->next; } return 0;}intpfkey_list_insert_supported(struct supported *supported, struct supported_list **supported_list){ struct supported_list *supported_listp; if(!supported) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_supported: " "NULL supported handed in, failed.\n"); return -EINVAL; } if(!supported_list) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_supported: " "NULL supported_list handed in, failed.\n"); return -EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_supported: " "incoming, supported=%p, supported_list=%p\n", supported, supported_list); supported_listp = (struct supported_list *)kmalloc(sizeof(struct supported_list), GFP_KERNEL); if(supported_listp == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_supported: " "memory allocation error.\n"); return -ENOMEM; } supported_listp->supportedp = supported; supported_listp->next = *supported_list; *supported_list = supported_listp; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_supported: " "outgoing, supported=%p, supported_list=%p\n", supported, supported_list); return 0;} #ifndef NET_21DEBUG_NO_STATIC voidpfkey_state_change(struct sock *sk){ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_state_change: .\n"); if(!sk->dead) { wake_up_interruptible(sk->sleep); }}#endif /* !NET_21 */#ifndef NET_21DEBUG_NO_STATIC voidpfkey_data_ready(struct sock *sk, int len){ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_data_ready: " "sk=%p len=%d\n", sk, len); if(!sk->dead) { wake_up_interruptible(sk->sleep); sock_wake_async(sk->socket, 1); }}DEBUG_NO_STATIC voidpfkey_write_space(struct sock *sk){ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_write_space: .\n"); if(!sk->dead) { wake_up_interruptible(sk->sleep); sock_wake_async(sk->socket, 2); }}#endif /* !NET_21 */DEBUG_NO_STATIC voidpfkey_insert_socket(struct sock *sk){ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_insert_socket: " "sk=%p\n", sk); cli(); sk->next=pfkey_sock_list; pfkey_sock_list=sk; sti();}DEBUG_NO_STATIC voidpfkey_remove_socket(struct sock *sk){ struct sock **s; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_remove_socket: .\n"); cli(); s=&pfkey_sock_list; while(*s!=NULL) { if(*s==sk) { *s=sk->next; sk->next=NULL; sti(); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_remove_socket: " "succeeded.\n"); return; } s=&((*s)->next); } sti(); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_remove_socket: " "not found.\n"); return;}DEBUG_NO_STATIC voidpfkey_destroy_socket(struct sock *sk){ struct sk_buff *skb; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: .\n"); pfkey_remove_socket(sk); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "pfkey_remove_socket called.\n"); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "sk(%p)->(&%p)receive_queue.{next=%p,prev=%p}.\n", sk, &(sk->receive_queue), sk->receive_queue.next, sk->receive_queue.prev); while(sk && ((skb=skb_dequeue(&(sk->receive_queue)))!=NULL)) {#ifdef NET_21#ifdef CONFIG_IPSEC_DEBUG if(debug_pfkey && sysctl_ipsec_debug_verbose) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "skb=%p dequeued.\n", skb); printk(KERN_INFO "klips_debug:pfkey_destroy_socket: " "pfkey_skb contents:"); printk(" next:%p", skb->next); printk(" prev:%p", skb->prev); printk(" list:%p", skb->list); printk(" sk:%p", skb->sk); printk(" stamp:%ld.%ld", skb->stamp.tv_sec, skb->stamp.tv_usec); printk(" dev:%p", skb->dev); if(skb->dev) { if(skb->dev->name) { printk(" dev->name:%s", skb->dev->name); } else { printk(" dev->name:NULL?"); } } else { printk(" dev:NULL"); } printk(" h:%p", skb->h.raw); printk(" nh:%p", skb->nh.raw); printk(" mac:%p", skb->mac.raw); printk(" dst:%p", skb->dst); if(sysctl_ipsec_debug_verbose) { int i; printk(" cb"); for(i=0; i<48; i++) { printk(":%2x", skb->cb[i]); } } printk(" len:%d", skb->len); printk(" csum:%d", skb->csum);#ifndef NETDEV_23 printk(" used:%d", skb->used); printk(" is_clone:%d", skb->is_clone);#endif /* NETDEV_23 */ printk(" cloned:%d", skb->cloned); printk(" pkt_type:%d", skb->pkt_type); printk(" ip_summed:%d", skb->ip_summed); printk(" priority:%d", skb->priority); printk(" protocol:%d", skb->protocol); printk(" security:%d", skb->security); printk(" truesize:%d", skb->truesize); printk(" head:%p", skb->head); printk(" data:%p", skb->data); printk(" tail:%p", skb->tail); printk(" end:%p", skb->end); if(sysctl_ipsec_debug_verbose) { unsigned int i; printk(" data"); for(i=(unsigned int)(skb->head); i<(unsigned int)(skb->end); i++) { printk(":%2x", (unsigned char)(*(char*)(i))); } } printk(" destructor:%p", skb->destructor); printk("\n"); }#endif /* CONFIG_IPSEC_DEBUG */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "skb=%p freed.\n", skb); kfree_skb(skb);#else /* NET_21 */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "skb=%p dequeued and freed.\n", skb); kfree_skb(skb, FREE_WRITE);#endif /* NET_21 */ } sk->dead = 1; sk_free(sk); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: destroyed.\n");}intpfkey_upmsg(struct socket *sock, struct sadb_msg *pfkey_msg){ int error = 0; struct sk_buff * skb = NULL; struct sock *sk; if(sock == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "NULL socket passed in.\n"); return -EINVAL; } if(pfkey_msg == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "NULL pfkey_msg passed in.\n"); return -EINVAL; }#ifdef NET_21 sk = sock->sk;#else /* NET_21 */ sk = sock->data;#endif /* NET_21 */ if(sk == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "NULL sock passed in.\n"); return -EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "allocating %d bytes...\n", pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); if(!(skb = alloc_skb(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, GFP_ATOMIC) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "no buffers left to send up a message.\n"); return -ENOBUFS; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "...allocated at %p.\n", skb); skb->dev = NULL; if(skb_tailroom(skb) < pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { printk(KERN_WARNING "klips_error:pfkey_upmsg: " "tried to skb_put %ld, %d available. This should never happen, please report.\n", (unsigned long int)pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, skb_tailroom(skb));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -