📄 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.85 2004/12/03 21:25:57 mcr 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/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>#ifdef NET_21# include <asm/uaccess.h># include <linux/in6.h>#endif /* NET_21 */#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 */extern struct proto_ops pfkey_ops;#ifdef NET_26HLIST_HEAD(pfkey_sock_list);static DECLARE_WAIT_QUEUE_HEAD(pfkey_sock_wait);static rwlock_t pfkey_sock_lock = RW_LOCK_UNLOCKED;static atomic_t pfkey_sock_users = ATOMIC_INIT(0);#elseextern struct proto_ops pfkey_ops;struct 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 **);#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 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 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;} #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=0p%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=0p%p\n", sk);#ifdef NET_26 pfkey_sock_list_grab(); sk_add_node(sk, &pfkey_sock_list); pfkey_sock_list_ungrab();#else cli(); sk->next=pfkey_sock_list; pfkey_sock_list=sk; sti();#endif}DEBUG_NO_STATIC voidpfkey_remove_socket(struct sock *sk){ struct sock **s; s = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_remove_socket: .\n");#ifdef NET_26 pfkey_sock_list_grab(); sk_del_node_init(sk); pfkey_sock_list_ungrab();#else 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();#endif 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(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 NET_21#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(" list:0p%p", skb->list); printk(" sk:0p%p", skb->sk); printk(" stamp:%ld.%ld", skb->stamp.tv_sec, skb->stamp.tv_usec); 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); printk(" nh:0p%p", skb->nh.raw); printk(" mac:0p%p", skb->mac.raw); printk(" dst:0p%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:0p%p", skb->head); printk(" data:0p%p", skb->data); printk(" tail:0p%p", skb->tail); printk(" end:0p%p", skb->end); if(sysctl_ipsec_debug_verbose) { unsigned char* i; printk(" data"); for(i = skb->head; i < skb->end; i++) { printk(":%2x", (unsigned char)(*(i))); } } printk(" destructor:0p%p", skb->destructor); printk("\n"); }#endif /* CONFIG_KLIPS_DEBUG */#endif /* NET_21 */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "skb=0p%p freed.\n", skb); ipsec_kfree_skb(skb); }#ifdef NET_26 sock_set_flag(sk, SOCK_DEAD);#else sk->dead = 1;#endif 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -