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

📄 my_inet.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <linux/net.h>#include <linux/init.h>#include <linux/module.h>#include <linux/tcp.h>#include <net/sock.h>#include <net/icmp.h>#include <net/tcp.h>#include <net/request_sock.h>#include <net/protocol.h>#include <linux/in.h>#include <net/udp.h>#include <linux/netdevice.h>#include <linux/bootmem.h>#include <linux/inetdevice.h>#include <linux/proc_fs.h>#include <linux/mroute.h>#include <net/ip_fib.h>#include <net/xfrm.h>#include <net/raw.h>#include <net/neighbour.h>#include <linux/jhash.h>#include <net/ip_mp_alg.h>#include <linux/netlink.h>#include <linux/igmp.h>#include <linux/if_arp.h>#include <linux/netfilter_arp.h>#include <linux/errqueue.h>#include <linux/netfilter_ipv4.h>#include <linux/snmp.h>#include <linux/random.h>#include <asm/unaligned.h>#include "my_inet.h"DEFINE_SNMP_STAT(struct linux_mib, mynet_statistics) __read_mostly;#define MYNET_INC_STATS_USER(field) 	SNMP_INC_STATS_USER(mynet_statistics, field)#define MYNET_INC_STATS_BH(field)       SNMP_INC_STATS_BH(mynet_statistics, field)#define MYNET_INC_STATS(field)			SNMP_INC_STATS(mynet_statistics, field)#define MYTCP_INC_STATS_BH(field)       SNMP_INC_STATS_BH(mytcp_statistics, field)#define MYNET_ADD_STATS_USER(field, adnd)	SNMP_ADD_STATS_USER(mynet_statistics, field, adnd)#include "myinet_hashtables.c"#include "mytcp_output.c"#include "mytcp_cong.c"#include "mytcp_input.c"#include "myinet_connection_sock.c"#include "mytcp_timer.c" #include "my_protocol.c"#include "myip_options.c"#include "myip_forward.c"#include "myfib_lookup.h"#include "myfib_semantics.c"#include "myinet_timewait_sock.c"#include "mytcp_minisocks.c"#include "my_inetpeer.c"#include "myfib_rules.c"#include "myfib_hash.c"#include "myfib_frontend.c"#include "mydevinet.c"#include "my_route.c"#include "myigmp.c"#include "myip_output.c"#include "myip_sockglue.c"#include "mydatagram.c"#include "my_udp.c"#include "my_raw.c"#include "mytcp.c"#include "mytcp_ipv4.c"#include "myicmp.c"#include "myarp.c"#include "myipmr.c"#include "myip_fragment.c"#include "myip_input.c"#include "my_systcl_net_ipv4.c"#ifdef CONFIG_IP_MULTICASTstatic struct net_protocol myigmp_protocol = {	.handler =	myigmp_rcv,};#endifstatic struct net_protocol mytcp_protocol = {	.handler =	mytcp_v4_rcv,	.err_handler =	mytcp_v4_err,	.no_policy =	1,};static struct net_protocol myudp_protocol = {	.handler =	myudp_rcv,	.err_handler =	myudp_err,	.no_policy =	1,};static struct net_protocol myicmp_protocol = {	.handler =	myicmp_rcv,};#ifdef INET_REFCNT_DEBUGatomic_t myinet_sock_nr;#endifvoid myinet_sock_destruct(struct sock *sk){}static int __init myinit_ipv4_mibs(void){	mynet_statistics[0] = alloc_percpu(struct linux_mib);	mynet_statistics[1] = alloc_percpu(struct linux_mib);	myip_statistics[0] = alloc_percpu(struct ipstats_mib);	myip_statistics[1] = alloc_percpu(struct ipstats_mib);	myicmp_statistics[0] = alloc_percpu(struct icmp_mib);	myicmp_statistics[1] = alloc_percpu(struct icmp_mib);	mytcp_statistics[0] = alloc_percpu(struct tcp_mib);	mytcp_statistics[1] = alloc_percpu(struct tcp_mib);	myudp_statistics[0] = alloc_percpu(struct udp_mib);	myudp_statistics[1] = alloc_percpu(struct udp_mib);	if (!(mynet_statistics[0] && mynet_statistics[1] && myip_statistics[0]							&& myip_statistics[1] && mytcp_statistics[0] && mytcp_statistics[1]							&& myudp_statistics[0] && myudp_statistics[1]))			return -ENOMEM;	SNMP_ADD_STATS_USER(mytcp_statistics, TCP_MIB_RTOALGORITHM, 1);	SNMP_ADD_STATS_USER(mytcp_statistics, TCP_MIB_RTOMIN, TCP_RTO_MIN*1000/HZ);	SNMP_ADD_STATS_USER(mytcp_statistics, TCP_MIB_RTOMAX, TCP_RTO_MAX*1000/HZ);	SNMP_ADD_STATS_USER(mytcp_statistics, TCP_MIB_MAXCONN, -1);	return 0;}static void __exit myexit_ipv4_mibs(void){	int i;	for( i = 0; i < 2; i ++ ){		free_percpu( mynet_statistics[i] );		free_percpu( myip_statistics[i] );		free_percpu( myicmp_statistics[i] );		free_percpu( mytcp_statistics[i] );		free_percpu( myudp_statistics[i] );	}}static int myipv4_proc_init(void){	return 0;}int myinet_release(struct socket *sock){	struct sock *sk = sock->sk;	if (sk) {		long timeout;		myip_mc_drop_socket(sk);		timeout = 0;		if (sock_flag(sk, SOCK_LINGER) &&		    !(current->flags & PF_EXITING))			timeout = sk->sk_lingertime;		sock->sk = NULL;		sk->sk_prot->close(sk, timeout);	}	return 0;}int mysysctl_ip_nonlocal_bind;int myinet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){	struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;	struct sock *sk = sock->sk;	struct inet_sock *inet = inet_sk(sk);	unsigned short snum;	int chk_addr_ret;	int err;	if (sk->sk_prot->bind) {		err = sk->sk_prot->bind(sk, uaddr, addr_len);		goto out;	}	err = -EINVAL;	if (addr_len < sizeof(struct sockaddr_in))		goto out;	chk_addr_ret = myinet_addr_type(addr->sin_addr.s_addr);	err = -EADDRNOTAVAIL;	if( !mysysctl_ip_nonlocal_bind && !inet->freebind &&					addr->sin_addr.s_addr != INADDR_ANY && chk_addr_ret != RTN_LOCAL &&					chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST )		goto out;	snum = ntohs(addr->sin_port);	err = -EACCES;	if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))		goto out;		lock_sock(sk);	err = -EINVAL;	if (sk->sk_state != TCP_CLOSE || inet->num)		goto out_release_sock;	inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr;	if( chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST )		inet->saddr = 0;		if( sk->sk_prot->get_port(sk, snum) ){		inet->saddr = inet->rcv_saddr = 0;		err = -EADDRINUSE;		goto out_release_sock;	}	if( inet->rcv_saddr )		sk->sk_userlocks |= SOCK_BINDADDR_LOCK;	if( snum )		sk->sk_userlocks |= SOCK_BINDPORT_LOCK;	inet->sport = htons(inet->num);	inet->daddr = 0;	inet->dport = 0;	sk_dst_reset(sk);	err = 0;out_release_sock:	release_sock(sk);out:	return err;}static long myinet_wait_for_connect(struct sock *sk, long timeo){	DEFINE_WAIT(wait);	prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);	while ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {		release_sock(sk);		timeo = schedule_timeout(timeo);		lock_sock(sk);		if (signal_pending(current) || !timeo)			break;		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);	}	finish_wait(sk->sk_sleep, &wait);	printk(KERN_INFO "the return value: %d\n", timeo);	return timeo;}int myinet_stream_connect(struct socket *sock, struct sockaddr *uaddr,				int addr_len, int flags){	struct sock *sk = sock->sk;	int err;	long timeo;	lock_sock(sk);	if (uaddr->sa_family == AF_UNSPEC) {		err = sk->sk_prot->disconnect(sk, flags);		sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;		goto out;	}		switch (sock->state) {	default:		err = -EINVAL;		goto out;	case SS_CONNECTED:		err = -EISCONN;		goto out;	case SS_CONNECTING:		err = -EALREADY;		break;	case SS_UNCONNECTED:		err = -EISCONN;		if (sk->sk_state != TCP_CLOSE)			goto out;		err = sk->sk_prot->connect(sk, uaddr, addr_len);		if (err < 0)			goto out;  		sock->state = SS_CONNECTING;		err = -EINPROGRESS;		break;	}	timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);	if( (1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV) ){		if (!timeo || !myinet_wait_for_connect(sk, timeo))			goto out;		err = sock_intr_errno(timeo);		printk(KERN_INFO "the err freom sock_intr_errno: %d\n", err );		if (signal_pending(current))			goto out;	}	if (sk->sk_state == TCP_CLOSE){		printk(KERN_INFO "sock state close!\n");		goto sock_error;	}	sock->state = SS_CONNECTED;	err = 0;out:	release_sock(sk);	return err;sock_error:	err = sock_error(sk) ? : -ECONNABORTED;	sock->state = SS_UNCONNECTED;	if (sk->sk_prot->disconnect(sk, flags))		sock->state = SS_DISCONNECTING;	goto out;}int myinet_accept(struct socket *sock, struct socket *newsock, int flags){	struct sock *sk1 = sock->sk;	int err = -EINVAL;	struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err);	if (!sk2)		goto do_err;	lock_sock(sk2);	BUG_TRAP((1 << sk2->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE));	sock_graft(sk2, newsock);	newsock->state = SS_CONNECTED;	err = 0;	release_sock(sk2);do_err:	return err;}int myinet_getname(struct socket *sock, struct sockaddr *uaddr,				int *uaddr_len, int peer){	struct sock *sk		= sock->sk;	struct inet_sock *inet	= inet_sk(sk);	struct sockaddr_in *sin	= (struct sockaddr_in *)uaddr;	sin->sin_family = MY_AF_INET;	if (peer) {		if (!inet->dport ||		    (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) &&		     peer == 1))			return -ENOTCONN;		sin->sin_port = inet->dport;		sin->sin_addr.s_addr = inet->daddr;	} else {		__u32 addr = inet->rcv_saddr;		if (!addr)			addr = inet->saddr;		sin->sin_port = inet->sport;		sin->sin_addr.s_addr = addr;	}	memset(sin->sin_zero, 0, sizeof(sin->sin_zero));	*uaddr_len = sizeof(*sin);	return 0;}int myinet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	struct sock *sk = sock->sk;	int err = 0;	switch(cmd){		case SIOCGIFADDR:		case SIOCSIFADDR:		case SIOCGIFBRDADDR:		case SIOCSIFBRDADDR:		case SIOCGIFNETMASK:		case SIOCSIFNETMASK:		case SIOCGIFDSTADDR:		case SIOCSIFDSTADDR:		case SIOCSIFPFLAGS:		case SIOCGIFPFLAGS:		case SIOCSIFFLAGS:			err = mydevinet_ioctl(cmd, (void __user *)arg);			break;	}	return err;}int myinet_listen(struct socket *sock, int backlog){	struct sock *sk = sock->sk;	unsigned char old_state;	int err;	lock_sock(sk);	err = -EINVAL;	if( sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM )		goto out;	old_state = sk->sk_state;	if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN)))		goto out;	if (old_state != TCP_LISTEN) {		err = myinet_csk_listen_start(sk, TCP_SYNQ_HSIZE);		if (err)			goto out;	}	printk(KERN_INFO "%s:%d: the backlog: %d\n", __FUNCTION__,__LINE__, backlog );	sk->sk_max_ack_backlog = backlog;	err = 0;out:	release_sock(sk);	return err;}int myinet_shutdown(struct socket *sock, int how){	return 0;}static int myinet_autobind(struct sock *sk)

⌨️ 快捷键说明

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