⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 my_inet.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
{	struct inet_sock *inet;	/* We may need to bind the socket. */	lock_sock(sk);	inet = inet_sk(sk);	if (!inet->num) {		if (sk->sk_prot->get_port(sk, 0)) {			release_sock(sk);			return -EAGAIN;		}		inet->sport = htons(inet->num);	}	release_sock(sk);	return 0;}int myinet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,				size_t size){	struct sock *sk = sock->sk;	if (!inet_sk(sk)->num && myinet_autobind(sk))		return -EAGAIN;	return sk->sk_prot->sendmsg(iocb, sk, msg, size);}int myinet_dgram_connect(struct socket *sock, struct sockaddr * uaddr,				int addr_len, int flags){	struct sock *sk = sock->sk;	if (uaddr->sa_family == AF_UNSPEC)		return sk->sk_prot->disconnect(sk, flags);	if( !inet_sk(sk)->num && myinet_autobind(sk) )		return -EAGAIN;	return sk->sk_prot->connect(sk, (struct sockaddr *)uaddr, addr_len);}static ssize_t myinet_sendpage(struct socket *sock, struct page *page, 				int offset, size_t size, int flags){	return 0;}struct proto_ops myinet_stream_ops = {	.family =	MY_PF_INET,	.owner =	THIS_MODULE,	.release =	myinet_release,	.bind =		myinet_bind,	.connect =	myinet_stream_connect,	.socketpair =	sock_no_socketpair,	.accept =	myinet_accept,	.getname =	myinet_getname,	.poll =		mytcp_poll,	.ioctl =	myinet_ioctl,	.listen =	myinet_listen,	.shutdown =	myinet_shutdown,	.setsockopt =	sock_common_setsockopt,	.getsockopt =	sock_common_getsockopt,	.sendmsg =	myinet_sendmsg,	.recvmsg =	sock_common_recvmsg,	.mmap =		sock_no_mmap,	.sendpage =	mytcp_sendpage};struct proto_ops myinet_dgram_ops = {	.family =	MY_PF_INET,	.owner =	THIS_MODULE,	.release =	myinet_release,	.bind =		myinet_bind,	.connect =	myinet_dgram_connect,	.socketpair =	sock_no_socketpair,	.accept =	sock_no_accept,	.getname =	myinet_getname,	.poll =		myudp_poll,	.ioctl =	myinet_ioctl,	.listen =	sock_no_listen,	.shutdown =	myinet_shutdown,	.setsockopt =	sock_common_setsockopt,	.getsockopt =	sock_common_getsockopt,	.sendmsg =	myinet_sendmsg,	.recvmsg =	sock_common_recvmsg,	.mmap =		sock_no_mmap,	.sendpage =	myinet_sendpage,};static struct proto_ops myinet_sockraw_ops = {	.family =	MY_PF_INET,	.owner =	THIS_MODULE,	.release =	myinet_release,	.bind =		myinet_bind,	.connect =	myinet_dgram_connect,	.socketpair =	sock_no_socketpair,	.accept =	sock_no_accept,	.getname =	myinet_getname,	.poll =		datagram_poll,	.ioctl =	myinet_ioctl,	.listen =	sock_no_listen,	.shutdown =	myinet_shutdown,	.setsockopt =	sock_common_setsockopt,	.getsockopt =	sock_common_getsockopt,	.sendmsg =	myinet_sendmsg,	.recvmsg =	sock_common_recvmsg,	.mmap =		sock_no_mmap,	.sendpage =	myinet_sendpage,};static struct list_head myinetsw[SOCK_MAX];static DEFINE_SPINLOCK(myinetsw_lock);static struct inet_protosw myinetsw_array[] ={	{		.type =			SOCK_STREAM,		.protocol =		MY_IPPROTO_TCP,		.prot =			&mytcp_prot,		.ops =			&myinet_stream_ops,		.capability =	-1,		.no_check =   	0,		.flags =      	INET_PROTOSW_PERMANENT,	},	{		.type =       SOCK_DGRAM,		.protocol =   MY_IPPROTO_UDP,		.prot =       &myudp_prot,		.ops =        &myinet_dgram_ops,		.capability = -1,		.no_check =   UDP_CSUM_DEFAULT,		.flags =      INET_PROTOSW_PERMANENT,	},	{		.type =       SOCK_RAW,		.protocol =   IPPROTO_IP,	/* wild card */		.prot =       &myraw_prot,		.ops =        &myinet_sockraw_ops,		.capability = CAP_NET_RAW,		.no_check =   UDP_CSUM_DEFAULT,		.flags =      INET_PROTOSW_REUSE,	}};#define MYINETSW_ARRAY_LEN (sizeof(myinetsw_array) / sizeof(struct inet_protosw))static int myinet_create(struct socket *sock, int protocol){	struct sock *sk;	struct inet_protosw *answer;	struct list_head *p;	struct inet_sock *inet;	struct proto *answer_prot;	unsigned char answer_flags;	char answer_no_check;	int err;	sock->state = SS_UNCONNECTED;	answer = NULL;	rcu_read_lock();	list_for_each_rcu(p, &myinetsw[sock->type]) {		answer = list_entry(p, struct inet_protosw, list);		if (protocol == answer->protocol) {			if (protocol != IPPROTO_IP)				break;		}else{			if (IPPROTO_IP == protocol) {				protocol = answer->protocol;				break;			}			if (IPPROTO_IP == answer->protocol)				break;		}		answer = NULL;	}	err = -ESOCKTNOSUPPORT;	if (!answer)		goto out_rcu_unlock;	err = -EPERM;	if (answer->capability > 0 && !capable(answer->capability))		goto out_rcu_unlock;	err = -EPROTONOSUPPORT;	if (!protocol)		goto out_rcu_unlock;		sock->ops = answer->ops;	answer_prot = answer->prot;	answer_no_check = answer->no_check;	answer_flags = answer->flags;	rcu_read_unlock();	BUG_TRAP(answer_prot->slab != NULL);	err = -ENOBUFS;	sk = sk_alloc(MY_PF_INET, GFP_KERNEL, answer_prot, 1);	if (sk == NULL)		goto out;	err = 0;	sk->sk_no_check = answer_no_check;	if (INET_PROTOSW_REUSE & answer_flags)		sk->sk_reuse = 1;	inet = inet_sk(sk);	if (SOCK_RAW == sock->type) {		inet->num = protocol;		if (IPPROTO_RAW == protocol)			inet->hdrincl = 1;	}	if (ipv4_config.no_pmtu_disc)		inet->pmtudisc = IP_PMTUDISC_DONT;	else		inet->pmtudisc = IP_PMTUDISC_WANT;	inet->id = 0;	sock_init_data(sock, sk);	sk->sk_destruct	   = myinet_sock_destruct;	sk->sk_family	   = MY_PF_INET;	sk->sk_protocol	   = protocol;	sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;	inet->uc_ttl	= -1;	inet->mc_loop	= 1;	inet->mc_ttl	= 1;	inet->mc_index	= 0;	inet->mc_list	= NULL;#ifdef INET_REFCNT_DEBUG	atomic_inc(&myinet_sock_nr);#endif	if (inet->num) {		inet->sport = htons(inet->num);		sk->sk_prot->hash(sk);	}	if (sk->sk_prot->init) {		err = sk->sk_prot->init(sk);		if (err)			sk_common_release(sk);	}out:	return err;out_rcu_unlock:	rcu_read_unlock();	goto out;	}static struct net_proto_family myinet_family_ops = {	.family = MY_PF_INET,	.create = myinet_create,	.owner	= THIS_MODULE,};void myinet_register_protosw(struct inet_protosw *p){	struct list_head *lh;	struct inet_protosw *answer;	int protocol = p->protocol;	struct list_head *last_perm;	spin_lock_bh(&myinetsw_lock);	if (p->type >= SOCK_MAX)		goto out_illegal;	answer = NULL;	last_perm = &myinetsw[p->type];	list_for_each(lh, &myinetsw[p->type]) {		answer = list_entry(lh, struct inet_protosw, list);		if (INET_PROTOSW_PERMANENT & answer->flags) {			if( protocol == answer->protocol )				break;			last_perm = lh;		}		answer = NULL;	}	if (answer)		goto out_permanent;	list_add_rcu(&p->list, last_perm);out:	spin_unlock_bh(&myinetsw_lock);	synchronize_net();	return;out_permanent:	printk( KERN_ERR "Attempt to override permanent protocol %d.\n", protocol );	goto out;out_illegal:	printk( KERN_ERR "Ignoring attempt to register invalid socket type %d.\n", p->type );	goto out;}void myinet_unregister_protosw(struct inet_protosw *p){	if (INET_PROTOSW_PERMANENT & p->flags) {		printk(KERN_ERR					"Attempt to unregister permanent protocol %d.\n", p->protocol);	}else{		spin_lock_bh(&myinetsw_lock);		list_del_rcu(&p->list);		spin_unlock_bh(&myinetsw_lock);		synchronize_net();	}}static struct packet_type myip_packet_type = {	.type = __constant_htons(ETH_P_IP),	.func = myip_rcv,};int myinet_sk_rebuild_header(struct sock *sk){	return 0;}static int __init myinet_init(void){	struct list_head *r;	struct inet_protosw *q;	int rc = -EINVAL;	rc = proto_register(&mytcp_prot, 1);	if (rc)			goto out;	rc = proto_register(&myudp_prot, 1);	if (rc)			goto out_unregister_tcp_proto;	rc = proto_register(&myraw_prot, 1);	if (rc)		goto out_unregister_udp_proto;			(void)sock_register( &myinet_family_ops );	if (myinet_add_protocol(&myicmp_protocol, MY_IPPROTO_ICMP) < 0)		printk(KERN_CRIT "myinet_init: Cannot add ICMP protocol\n");	if (myinet_add_protocol(&myudp_protocol, MY_IPPROTO_UDP) < 0)		printk(KERN_CRIT "myinet_init: Cannot add UDP protocol\n");	if (myinet_add_protocol(&mytcp_protocol, MY_IPPROTO_TCP) < 0)		printk(KERN_CRIT "myinet_init: Cannot add TCP protocol\n");#ifdef CONFIG_IP_MULTICAST	if (myinet_add_protocol(&myigmp_protocol, MY_IPPROTO_IGMP) < 0)		printk(KERN_CRIT "myinet_init: Cannot add IGMP protocol\n");#endif	for (r = &myinetsw[0]; r < &myinetsw[SOCK_MAX]; ++r)		INIT_LIST_HEAD(r);	for (q = myinetsw_array; q < &myinetsw_array[MYINETSW_ARRAY_LEN]; ++q)		myinet_register_protosw(q);	myarp_init();	myip_init();	mytcp_v4_init();	mytcp_init();	myicmp_init(&myinet_family_ops);#if defined(CONFIG_IP_MROUTE)	myip_mr_init();#endif	if( myinit_ipv4_mibs() )		printk(KERN_CRIT "myinet_init: Cannot init ipv4 mibs\n"); ;	myipv4_proc_init();	myipfrag_init();	dev_add_pack(&myip_packet_type);	rc = 0;out:	return rc;out_unregister_udp_proto:	proto_unregister(&myudp_prot);out_unregister_tcp_proto:	proto_unregister(&mytcp_prot);	goto out;		}static void __exit myinet_exit(void){	dev_remove_pack( &myip_packet_type );	myipfrag_exit();	myexit_ipv4_mibs();#if defined(CONFIG_IP_MROUTE)    myip_mr_exit();#endif	myicmp_exit();	mytcp_exit();	mytcp_v4_exit();	myip_exit();	myarp_exit();	proto_unregister(&myudp_prot);	proto_unregister(&mytcp_prot);	proto_unregister(&myraw_prot);	myinet_del_protocol(&myicmp_protocol, MY_IPPROTO_ICMP );	myinet_del_protocol(&myudp_protocol, MY_IPPROTO_UDP );	myinet_del_protocol(&mytcp_protocol, MY_IPPROTO_TCP );#ifdef CONFIG_IP_MULTICAST	myinet_del_protocol(&myigmp_protocol, MY_IPPROTO_IGMP);#endif	(void)sock_unregister( MY_PF_INET );}module_init( myinet_init )module_exit( myinet_exit )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -