📄 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.97.2.8 2006/07/10 15:56:11 paul 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 "openswan/ipsec_param.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>#ifdef MALLOC_SLAB# include <linux/slab.h> /* kmalloc() */#else /* MALLOC_SLAB */# include <linux/malloc.h> /* kmalloc() */#endif /* MALLOC_SLAB */#include <asm/segment.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include <net/sock.h> /* struct sock */#include <net/protocol.h>/* #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 <openswan.h>#include "openswan/radij.h"#include "openswan/ipsec_encap.h"#include "openswan/ipsec_sa.h"#include <pfkeyv2.h>#include <pfkey.h>#include "openswan/ipsec_proto.h"#include "openswan/ipsec_kern24.h"#ifdef CONFIG_KLIPS_DEBUGint debug_pfkey = 0;extern int sysctl_ipsec_debug_verbose;#endif /* CONFIG_KLIPS_DEBUG */#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)#ifndef SOCKOPS_WRAPPED#define SOCKOPS_WRAPPED(name) name#endif /* SOCKOPS_WRAPPED */#ifdef NET_26static rwlock_t pfkey_sock_lock = RW_LOCK_UNLOCKED;HLIST_HEAD(pfkey_sock_list);static DECLARE_WAIT_QUEUE_HEAD(pfkey_sock_wait);static atomic_t pfkey_sock_users = ATOMIC_INIT(0);#elsestruct sock *pfkey_sock_list = NULL;#endifstruct 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 **);DEBUG_NO_STATIC int pfkey_create(struct socket *sock, int protocol);DEBUG_NO_STATIC int pfkey_shutdown(struct socket *sock, int mode);DEBUG_NO_STATIC int pfkey_release(struct socket *sock);#ifdef NET_26DEBUG_NO_STATIC int pfkey_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len);DEBUG_NO_STATIC int pfkey_recvmsg(struct kiocb *kiocb, struct socket *sock, struct msghdr *msg , size_t size, int flags);#elseDEBUG_NO_STATIC int pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm);DEBUG_NO_STATIC int pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm);#endifstruct net_proto_family pfkey_family_ops = { PF_KEY, pfkey_create};struct proto_ops SOCKOPS_WRAPPED(pfkey_ops) = {#ifdef NETDEV_23 family: PF_KEY, release: pfkey_release, bind: sock_no_bind, connect: sock_no_connect, socketpair: sock_no_socketpair, accept: sock_no_accept, getname: sock_no_getname, poll: datagram_poll, ioctl: sock_no_ioctl, listen: sock_no_listen, shutdown: pfkey_shutdown, setsockopt: sock_no_setsockopt, getsockopt: sock_no_getsockopt, sendmsg: pfkey_sendmsg, recvmsg: pfkey_recvmsg, mmap: sock_no_mmap,#else /* NETDEV_23 */ PF_KEY, sock_no_dup, pfkey_release, sock_no_bind, sock_no_connect, sock_no_socketpair, sock_no_accept, sock_no_getname, datagram_poll, sock_no_ioctl, sock_no_listen, pfkey_shutdown, sock_no_setsockopt, sock_no_getsockopt, sock_no_fcntl, pfkey_sendmsg, pfkey_recvmsg#endif /* NETDEV_23 */};#ifdef NETDEV_23#include <linux/smp_lock.h>SOCKOPS_WRAP(pfkey, PF_KEY);#endif /* NETDEV_23 */#ifdef NET_26static void pfkey_sock_list_grab(void){ write_lock_bh(&pfkey_sock_lock); if (atomic_read(&pfkey_sock_users)) { DECLARE_WAITQUEUE(wait, current); add_wait_queue_exclusive(&pfkey_sock_wait, &wait); for(;;) { set_current_state(TASK_UNINTERRUPTIBLE); if (atomic_read(&pfkey_sock_users) == 0) break; write_unlock_bh(&pfkey_sock_lock); schedule(); write_lock_bh(&pfkey_sock_lock); } __set_current_state(TASK_RUNNING); remove_wait_queue(&pfkey_sock_wait, &wait); }}static __inline__ void pfkey_sock_list_ungrab(void){ write_unlock_bh(&pfkey_sock_lock); wake_up(&pfkey_sock_wait);}static __inline__ void pfkey_lock_sock_list(void){ /* read_lock() synchronizes us to pfkey_table_grab */ read_lock(&pfkey_sock_lock); atomic_inc(&pfkey_sock_users); read_unlock(&pfkey_sock_lock);}static __inline__ void pfkey_unlock_sock_list(void){ if (atomic_dec_and_test(&pfkey_sock_users)) wake_up(&pfkey_sock_wait);}#endifintpfkey_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=0p%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: " "allocating %lu bytes for socketp=0p%p\n", (unsigned long) sizeof(struct socket_list), 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 ipsec_alg_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=0p%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 ipsec_alg_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: " "allocating %lu bytes for incoming, supported=0p%p, supported_list=0p%p\n", (unsigned long) sizeof(struct supported_list), 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=0p%p, supported_list=0p%p\n", supported, supported_list); return 0;} #ifdef NET_26DEBUG_NO_STATIC voidpfkey_insert_socket(struct sock *sk){ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_insert_socket: " "sk=0p%p\n", sk); pfkey_sock_list_grab(); sk_add_node(sk, &pfkey_sock_list); pfkey_sock_list_ungrab();}DEBUG_NO_STATIC voidpfkey_remove_socket(struct sock *sk){ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_remove_socket: 0p%p\n", sk); pfkey_sock_list_grab(); sk_del_node_init(sk); pfkey_sock_list_ungrab(); return;}#elseDEBUG_NO_STATIC voidpfkey_insert_socket(struct sock *sk){ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_insert_socket: " "sk=0p%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; s = NULL; 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;}#endifDEBUG_NO_STATIC voidpfkey_destroy_socket(struct sock *sk){ struct sk_buff *skb; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: 0p%p\n",sk); pfkey_remove_socket(sk); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "pfkey_remove_socket called, sk=0p%p\n",sk); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "sk(0p%p)->(&0p%p)receive_queue.{next=0p%p,prev=0p%p}.\n", sk, &(sk->sk_receive_queue), sk->sk_receive_queue.next, sk->sk_receive_queue.prev); while(sk && ((skb=skb_dequeue(&(sk->sk_receive_queue)))!=NULL)) {#ifdef CONFIG_KLIPS_DEBUG if(debug_pfkey && sysctl_ipsec_debug_verbose) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "skb=0p%p dequeued.\n", skb); printk(KERN_INFO "klips_debug:pfkey_destroy_socket: " "pfkey_skb contents:"); printk(" next:0p%p", skb->next); printk(" prev:0p%p", skb->prev); printk(" sk:0p%p", skb->sk); printk(" dev:0p%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:0p%p", skb->h.raw);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -