📄 mytcp_ipv4.c
字号:
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 + -