#include <linux/module.h> #include <linux/init.h> #include <linux/net.h> #include <net/sock.h>
#define PF_MYFAMILY 28
static void stream_csk_destroy_sock(struct sock * sk) { skb_queue_purge(&sk->sk_receive_queue); skb_queue_purge(&sk->sk_error_queue); skb_queue_purge(&sk->sk_write_queue); sock_put(sk); } static void my_proto_close(struct sock *sk, long timeout) { lock_sock(sk); sock_hold(sk); /* increment sk_refcnt */ sock_orphan(sk); /* set sk_flag SOCK_DEAD flag */ release_sock(sk);
local_bh_disable(); /* close current cpu softirq */ bh_lock_sock(sk); /* spin_lock */
stream_csk_destroy_sock(sk);
bh_unlock_sock(sk); local_bh_enable(); /* spin_unlock */
sock_put(sk); /* if sk_refcnt = 0, call sk_free(sk) */ printk(KERN_ALERT "my_proto_close ok\n"); }
struct my_priv_struct { struct sock sk; int flag; };
static struct proto my_proto = { .name = "my_proto", .owner = THIS_MODULE, .close = my_proto_close, .obj_size = sizeof(struct my_priv_struct), };
static int my_release(struct socket *sock) { struct sock *sk = sock->sk;
sock->sk = NULL; sk->sk_prot->close(sk, 0);
printk(KERN_ALERT "my_release ok\n");
return 0; }
static struct proto_ops my_ops = { .family = PF_MYFAMILY, .owner = THIS_MODULE, .release = my_release, };
static int family_create(struct socket *sock, int protocol) { struct sock *sk;
sock->state = SS_UNCONNECTED; sock->ops = &my_ops; sk = sk_alloc(PF_MYFAMILY, GFP_KERNEL, &my_proto, 1); if (!sk) { printk(KERN_NOTICE "sk_alloc failure\n"); goto alloc_err; } sock_init_data(sock, sk);
return 0; alloc_err: return -1; }
static struct net_proto_family family = { .family = PF_MYFAMILY, .create = family_create, .owner = THIS_MODULE, };
static int __init private_init(void) { int ret;
ret = proto_register(&my_proto, 1); if (ret < 0) { printk(KERN_ALERT "proto_register failure\n"); goto proto_err; }
ret = sock_register(&family); if (ret < 0) { printk(KERN_NOTICE "sock_register failure\n"); goto sock_err; } printk(KERN_NOTICE "sock_register success\n");
return 0; sock_err: proto_unregister(&my_proto); proto_err: return -1; }
static void __exit private_exit(void) { sock_unregister(PF_MYFAMILY); }
module_init(private_init); module_exit(private_exit); MODULE_LICENSE("GPL");
|