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

📄 mytcp_ipv4.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
static struct socket *mytcp_socket;int mysysctl_local_port_range[2] = { 1024, 4999 };extern atomic_t mytcp_memory_allocated;extern atomic_t mytcp_sockets_allocated;int mysysctl_tcp_tw_reuse;int mysysctl_tcp_low_latency;struct inet_hashinfo __cacheline_aligned mytcp_hashinfo = {	.lhash_lock = RW_LOCK_UNLOCKED,	.lhash_users    = ATOMIC_INIT(0),	.lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER( mytcp_hashinfo.lhash_wait ),};int mytcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw){	struct inet_peer *peer = myinet_getpeer(tw->tw_daddr, 1);	if (peer) {		const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);		if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||						(peer->tcp_ts_stamp + TCP_PAWS_MSL < xtime.tv_sec &&						 peer->tcp_ts_stamp <= tcptw->tw_ts_recent_stamp)) {			peer->tcp_ts_stamp = tcptw->tw_ts_recent_stamp;			peer->tcp_ts	   = tcptw->tw_ts_recent;		}		myinet_putpeer(peer);		return 1;	}	return 0;}static int mytcp_v4_checksum_init(struct sk_buff *skb){	if( skb->ip_summed == CHECKSUM_HW ){		if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr,								skb->nh.iph->daddr, skb->csum)) {			skb->ip_summed = CHECKSUM_UNNECESSARY;			return 0;		}	}	skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr, skb->nh.iph->daddr,					skb->len, IPPROTO_TCP, 0);	if (skb->len <= 76) {		return __skb_checksum_complete(skb);	}	return 0;}struct sock *__myinet_lookup_listener(const struct hlist_head *head, const u32 daddr,				const unsigned short hnum, const int dif){	struct sock *result = NULL, *sk;	const struct hlist_node *node;	int hiscore = -1;	sk_for_each(sk, node, head) {		const struct inet_sock *inet = inet_sk(sk);		if (inet->num == hnum && !ipv6_only_sock(sk)) {			const __u32 rcv_saddr = inet->rcv_saddr;			int score = sk->sk_family == MY_PF_INET ? 1 : 0;			if (rcv_saddr) {				if (rcv_saddr != daddr)					continue;				score += 2;			}			if (sk->sk_bound_dev_if) {				if (sk->sk_bound_dev_if != dif)					continue;				score += 2;			}			if (score == 5)				return sk;			if (score > hiscore) {				hiscore	= score;				result	= sk;			}		}	}	return result;}static inline struct sock *myinet_lookup_listener(struct inet_hashinfo *hashinfo,				     const u32 daddr, const unsigned short hnum, const int dif){	struct sock *sk = NULL;	const struct hlist_head *head;	read_lock(&hashinfo->lhash_lock);	head = &hashinfo->listening_hash[inet_lhashfn(hnum)];	if (!hlist_empty(head)) {		const struct inet_sock *inet = inet_sk((sk = __sk_head(head)));		if (inet->num == hnum && !sk->sk_node.next &&		    (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&		    (sk->sk_family == MY_PF_INET || !ipv6_only_sock(sk)) &&		    !sk->sk_bound_dev_if)			goto sherry_cache;		sk = __myinet_lookup_listener(head, daddr, hnum, dif);	}	if (sk) {sherry_cache:		sock_hold(sk);	}	read_unlock(&hashinfo->lhash_lock);	return sk;}static struct sock *mytcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb){	struct tcphdr *th = skb->h.th;	struct iphdr *iph = skb->nh.iph;	struct sock *nsk;	struct request_sock **prev;	struct request_sock *req = myinet_csk_search_req(sk, &prev, th->source,					iph->saddr, iph->daddr);	if (req){		printk(KERN_INFO "%s:%d: cat find the req in search req\n", __FUNCTION__, __LINE__ );		return mytcp_check_req(sk, skb, req, prev);	}	nsk = __inet_lookup_established( &mytcp_hashinfo, skb->nh.iph->saddr,					th->source, skb->nh.iph->daddr,					ntohs(th->dest), inet_iif(skb));	if (nsk) {		printk(KERN_INFO "%s:%d: can find the nsk in establish\n", __FUNCTION__, __LINE__ );		if (nsk->sk_state != TCP_TIME_WAIT) {			bh_lock_sock(nsk);			return nsk;		}		myinet_twsk_put((struct inet_timewait_sock *)nsk);		return NULL;	}#ifdef CONFIG_SYN_COOKIES	//if (!th->rst && !th->syn && th->ack)	//	sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));#endif	printk(KERN_INFO "%s:%d: return here!\n", __FUNCTION__, __LINE__ );	return sk;}static void mytcp_v4_send_reset(struct sk_buff *skb){	struct tcphdr *th = skb->h.th;	struct tcphdr rth;	struct ip_reply_arg arg;	if (th->rst)		return;	if (((struct rtable *)skb->dst)->rt_type != RTN_LOCAL)		return;	memset(&rth, 0, sizeof(struct tcphdr));	rth.dest   = th->source;	rth.source = th->dest;	rth.doff   = sizeof(struct tcphdr) / 4;	rth.rst    = 1;	if (th->ack) {		rth.seq = th->ack_seq;	} else {		rth.ack = 1;		rth.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin +				    skb->len - (th->doff << 2));	}	memset(&arg, 0, sizeof arg);	arg.iov[0].iov_base = (unsigned char *)&rth;	arg.iov[0].iov_len  = sizeof rth;	arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,				      skb->nh.iph->saddr,				      sizeof(struct tcphdr), IPPROTO_TCP, 0);	arg.csumoffset = offsetof(struct tcphdr, check) / 2;	myip_send_reply( mytcp_socket->sk, skb, &arg, sizeof rth);	MYTCP_INC_STATS_BH(TCP_MIB_OUTSEGS);	MYTCP_INC_STATS_BH(TCP_MIB_OUTRSTS);}int mytcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb){	if( sk->sk_state == TCP_ESTABLISHED ){		TCP_CHECK_TIMER(sk);		if( mytcp_rcv_established(sk, skb, skb->h.th, skb->len) )			goto reset;		TCP_CHECK_TIMER(sk);		return 0;	}	if (skb->len < (skb->h.th->doff << 2) || tcp_checksum_complete(skb))		goto csum_err;	if( sk->sk_state == TCP_LISTEN ){		struct sock *nsk = mytcp_v4_hnd_req(sk, skb);		printk(KERN_INFO "%s:%d: get the nsk: %p\n", __FUNCTION__, __LINE__, nsk );		if (!nsk)			goto discard;		if (nsk != sk) {			if( mytcp_child_process(sk, nsk, skb) )				goto reset;			return 0;		}	}	TCP_CHECK_TIMER(sk);	if( mytcp_rcv_state_process(sk, skb, skb->h.th, skb->len) )		goto reset;	TCP_CHECK_TIMER(sk);	return 0;reset:	mytcp_v4_send_reset(skb);discard:	kfree_skb(skb);	return 0;csum_err:	MYTCP_INC_STATS_BH(TCP_MIB_INERRS);	goto discard;}static void mytcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,				u32 win, u32 ts){	struct tcphdr *th = skb->h.th;	struct {		struct tcphdr th;		u32 tsopt[3];	} rep;	struct ip_reply_arg arg;	memset(&rep.th, 0, sizeof(struct tcphdr));	memset(&arg, 0, sizeof arg);	arg.iov[0].iov_base = (unsigned char *)&rep;	arg.iov[0].iov_len  = sizeof(rep.th);	if (ts) {		rep.tsopt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |				     (TCPOPT_TIMESTAMP << 8) |				     TCPOLEN_TIMESTAMP);		rep.tsopt[1] = htonl(tcp_time_stamp);		rep.tsopt[2] = htonl(ts);		arg.iov[0].iov_len = sizeof(rep);	}	rep.th.dest    = th->source;	rep.th.source  = th->dest;	rep.th.doff    = arg.iov[0].iov_len / 4;	rep.th.seq     = htonl(seq);	rep.th.ack_seq = htonl(ack);	rep.th.ack     = 1;	rep.th.window  = htons(win);	arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,skb->nh.iph->saddr,				      arg.iov[0].iov_len, IPPROTO_TCP, 0);	arg.csumoffset = offsetof(struct tcphdr, check) / 2;	myip_send_reply( mytcp_socket->sk, skb, &arg, arg.iov[0].iov_len);	MYTCP_INC_STATS_BH(TCP_MIB_OUTSEGS);}static void mytcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb){	struct inet_timewait_sock *tw = inet_twsk(sk);	const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);	mytcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,					tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent);	printk(KERN_INFO "call in ipv4 224!\n");	myinet_twsk_put(tw);}static inline struct sock *__myinet_lookup(struct inet_hashinfo *hashinfo,					 const u32 saddr, const u16 sport, const u32 daddr, const u16 hnum,					 const int dif){	struct sock *sk = __inet_lookup_established( hashinfo, saddr, sport, daddr, hnum, dif );	return sk ? : myinet_lookup_listener( hashinfo, daddr, hnum, dif );}int mytcp_v4_rcv(struct sk_buff *skb){	struct tcphdr *th;	struct sock *sk;	int ret;	if (skb->pkt_type != PACKET_HOST)		goto discard_it;	MYTCP_INC_STATS_BH(TCP_MIB_INSEGS);	if( !pskb_may_pull(skb, sizeof(struct tcphdr)) )		goto discard_it;	th = skb->h.th;	if (th->doff < sizeof(struct tcphdr) / 4)		goto bad_packet;	if (!pskb_may_pull(skb, th->doff * 4))		goto discard_it;	if( (skb->ip_summed != CHECKSUM_UNNECESSARY && mytcp_v4_checksum_init(skb)) )		goto bad_packet;	th = skb->h.th;	TCP_SKB_CB(skb)->seq = ntohl(th->seq);	TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +				    skb->len - th->doff * 4);	TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);	TCP_SKB_CB(skb)->when	 = 0;	TCP_SKB_CB(skb)->flags	 = skb->nh.iph->tos;	TCP_SKB_CB(skb)->sacked	 = 0;	sk = __myinet_lookup( &mytcp_hashinfo, skb->nh.iph->saddr, th->source,					skb->nh.iph->daddr, ntohs(th->dest), inet_iif(skb) );	if( sk == NULL )		goto no_tcp_socket;process:	if (sk->sk_state == TCP_TIME_WAIT)		goto do_time_wait;	//if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))	//	goto discard_and_relse;	nf_reset(skb);	if (sk_filter(sk, skb, 0))		goto discard_and_relse;	skb->dev = NULL;	bh_lock_sock(sk);	ret = 0;	if( !sock_owned_by_user(sk) ){		if (!tcp_prequeue(sk, skb))			ret = mytcp_v4_do_rcv(sk, skb);	}else		sk_add_backlog(sk, skb);	bh_unlock_sock(sk);	sock_put(sk);	return ret;no_tcp_socket:	//TEMP CODE! FIXME!!!!	if( skb->nh.iph->daddr == 0x023010AC )      //filter the ssh packet.		goto discard_it;	//if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))	//	goto discard_it;	if( skb->len < (th->doff << 2) || tcp_checksum_complete(skb) ){bad_packet:		MYTCP_INC_STATS_BH(TCP_MIB_INERRS);	}else{		mytcp_v4_send_reset(skb);	}discard_it:	kfree_skb(skb);  	return 0;discard_and_relse:	sock_put(sk);	goto discard_it;do_time_wait:	//if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {	//	inet_twsk_put((struct inet_timewait_sock *) sk);	//	goto discard_it;	//}	if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {		MYTCP_INC_STATS_BH(TCP_MIB_INERRS);		printk(KERN_INFO "call in ipv4 315!\n");		myinet_twsk_put((struct inet_timewait_sock *) sk);		goto discard_it;	}	switch ( mytcp_timewait_state_process((struct inet_timewait_sock *)sk, skb, th)) {	case TCP_TW_SYN: {		struct sock *sk2 = myinet_lookup_listener( &mytcp_hashinfo, skb->nh.iph->daddr,							ntohs(th->dest), inet_iif(skb));		if (sk2) {			myinet_twsk_deschedule((struct inet_timewait_sock *)sk, &mytcp_death_row);			myinet_twsk_put((struct inet_timewait_sock *)sk);			sk = sk2;			goto process;		}	}	case TCP_TW_ACK:		mytcp_v4_timewait_ack(sk, skb);		break;	case TCP_TW_RST:		goto no_tcp_socket;	case TCP_TW_SUCCESS:;	}	goto discard_it;}void mytcp_v4_err(struct sk_buff *skb, u32 info){	printk(KERN_INFO "mytcp_v4_err\n");}static inline int myip_route_newports(struct rtable **rp, u8 protocol,				u16 sport, u16 dport, struct sock *sk){	if (sport != (*rp)->fl.fl_ip_sport || dport != (*rp)->fl.fl_ip_dport) {		struct flowi fl;		memcpy(&fl, &(*rp)->fl, sizeof(fl));		fl.fl_ip_sport = sport;		fl.fl_ip_dport = dport;		fl.proto = protocol;		ip_rt_put(*rp);		*rp = NULL;		return myip_route_output_flow(rp, &fl, sk, 0);	}	return 0;}int mytcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len){	struct inet_sock *inet = inet_sk(sk);	struct tcp_sock *tp = tcp_sk(sk);	struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;	struct rtable *rt;	u32 daddr, nexthop;	int tmp;	int err;	if (addr_len < sizeof(struct sockaddr_in))		return -EINVAL;	nexthop = daddr = usin->sin_addr.s_addr;	if( inet->opt && inet->opt->srr ){		if (!daddr)			return -EINVAL;		nexthop = inet->opt->faddr;	}		tmp = myip_route_connect(&rt, nexthop, inet->saddr, RT_CONN_FLAGS(sk), 					sk->sk_bound_dev_if, MY_IPPROTO_TCP, inet->sport, usin->sin_port, sk);	if( tmp < 0 ){		return tmp;	}	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {		ip_rt_put(rt);		return -ENETUNREACH;	}	if( !inet->opt || !inet->opt->srr )		daddr = rt->rt_dst;	if( !inet->saddr )		inet->saddr = rt->rt_src;	inet->rcv_saddr = inet->saddr;	if (tp->rx_opt.ts_recent_stamp && inet->daddr != daddr) {		tp->rx_opt.ts_recent	   = 0;		tp->rx_opt.ts_recent_stamp = 0;		tp->write_seq		   = 0;	}	if( mytcp_death_row.sysctl_tw_recycle &&					!tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) {		struct inet_peer *peer = myrt_get_peer(rt);		if (peer && peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) {			tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;			tp->rx_opt.ts_recent = peer->tcp_ts;		}	}	inet->dport = usin->sin_port;	inet->daddr = daddr;	inet_csk(sk)->icsk_ext_hdr_len = 0;	if (inet->opt)		inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen;	tp->rx_opt.mss_clamp = 536;	tcp_set_state(sk, TCP_SYN_SENT);	err = myinet_hash_connect(&mytcp_death_row, sk);	err = myip_route_newports( &rt, MY_IPPROTO_TCP, inet->sport, inet->dport, sk );	if (err)		goto failure;	printk(KERN_INFO "%s:%d: the features: %x\n", __FUNCTION__, __LINE__, rt->u.dst.dev->features );	sk_setup_caps(sk, &rt->u.dst);	if (!tp->write_seq)		//tp->write_seq = secure_tcp_sequence_number(inet->saddr,		//					   inet->daddr, inet->sport, usin->sin_port );		tp->write_seq = 1980;	inet->id = tp->write_seq ^ jiffies;

⌨️ 快捷键说明

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