Index: sys/conf/options =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/conf/options,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/conf/options 5 Aug 2004 22:31:17 -0000 1.1.1.1 +++ sys/conf/options 9 Aug 2004 18:26:17 -0000 1.2 @@ -357,6 +357,8 @@ TCP_DROP_SYNFIN opt_tcp_input.h XBONEHACK +LATEBINDING opt_latebinding.h + # Netgraph(4). Use option NETGRAPH to enable the base netgraph code. # Each netgraph node type can be either be compiled into the kernel # or loaded dynamically. To get the former, include the corresponding Index: sys/kern/uipc_socket.c =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/kern/uipc_socket.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/kern/uipc_socket.c 5 Aug 2004 22:32:13 -0000 1.1.1.1 +++ sys/kern/uipc_socket.c 9 Aug 2004 18:26:06 -0000 1.2 @@ -37,6 +37,7 @@ #include "opt_inet.h" #include "opt_mac.h" #include "opt_zero.h" +#include "opt_latebinding.h" #include #include @@ -1304,6 +1305,9 @@ case SO_OOBINLINE: case SO_TIMESTAMP: case SO_NOSIGPIPE: +#ifdef LATEBINDING + case SO_LATEBINDING: +#endif error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval); if (error) @@ -1507,6 +1511,9 @@ case SO_OOBINLINE: case SO_TIMESTAMP: case SO_NOSIGPIPE: +#ifdef LATEBINDING + case SO_LATEBINDING: +#endif optval = so->so_options & sopt->sopt_name; integer: error = sooptcopyout(sopt, &optval, sizeof optval); Index: sys/netinet/in_pcb.c =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/in_pcb.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- sys/netinet/in_pcb.c 5 Aug 2004 22:32:33 -0000 1.1.1.1 +++ sys/netinet/in_pcb.c 28 Aug 2004 05:02:19 -0000 1.3 @@ -36,6 +36,7 @@ #include "opt_ipsec.h" #include "opt_inet6.h" +#include "opt_latebinding.h" #include #include @@ -49,6 +50,7 @@ #include #include #include +#include #include @@ -164,6 +166,7 @@ inp->inp_gencnt = ++pcbinfo->ipi_gencnt; inp->inp_pcbinfo = pcbinfo; inp->inp_socket = so; + inp->inp_nonce = arc4random(); /* assume host byte order */ #ifdef IPSEC error = ipsec_init_policy(so, &inp->inp_sp); if (error != 0) { @@ -977,17 +980,38 @@ struct inpcbhead *head; register struct inpcb *inp; u_short fport = fport_arg, lport = lport_arg; + u_int32_t dst; /* * First look for an exact match. */ head = &pcbinfo->hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, pcbinfo->hashmask)]; LIST_FOREACH(inp, head, inp_hash) { + +#ifdef LATEBINDING + if ((lport == htons(4660)) || (fport == htons(4660))){ + log(LOG_INFO, + "pcblookup_hash: use_nonce? %s nonce = %x (host order = %x) \n", + inp->inp_vflag & INP_USE_NONCE ? "yes":"no", htonl(inp->inp_nonce), inp->inp_nonce); + log(LOG_INFO, + "pcblookup_hash: saddr = %x sport = %x daddr = %x dport = %x\n", + ntohl(laddr.s_addr), ntohs(lport), + ntohl(faddr.s_addr), ntohs(fport)); + } +#endif + #ifdef INET6 if ((inp->inp_vflag & INP_IPV4) == 0) continue; #endif - if (inp->inp_faddr.s_addr == faddr.s_addr && + dst = inp->inp_faddr.s_addr; +#ifdef LATEBINDING + if (inp->inp_vflag & INP_USE_NONCE) { + dst = htonl(inp->inp_nonce); + } +#endif + + if (dst == faddr.s_addr && inp->inp_laddr.s_addr == laddr.s_addr && inp->inp_fport == fport && inp->inp_lport == lport) { @@ -1060,6 +1084,25 @@ #endif /* INET6 */ hashkey_faddr = inp->inp_faddr.s_addr; +#ifdef LATEBINDING + if (inp->inp_lport == htons(4660) || inp->inp_fport == htons(4660)){ + log(LOG_INFO, + "pcbinshash: use_nonce? %s nonce = %x \n", + (inp->inp_vflag & INP_USE_NONCE)? "yes":"no", + htonl(inp->inp_nonce)); + log(LOG_INFO, + "pcbinshash: saddr = %x sport = %x daddr = %x dport = %x\n", + ntohl(inp->inp_laddr.s_addr), ntohs(inp->inp_lport), + ntohl(inp->inp_faddr.s_addr), ntohs(inp->inp_fport)); + } +#endif +#ifdef LATEBINDING + if (inp->inp_vflag & INP_USE_NONCE){ + /* have to ensure that nonce is non null */ + hashkey_faddr = htonl(inp->inp_nonce); + } +#endif + pcbhash = &pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr, inp->inp_lport, inp->inp_fport, pcbinfo->hashmask)]; @@ -1111,6 +1154,24 @@ #endif /* INET6 */ hashkey_faddr = inp->inp_faddr.s_addr; +#ifdef LATEBINDING + if (inp->inp_lport == htons(4660) || inp->inp_fport == htons(4660)){ + log(LOG_INFO, + "pcbrehash: use_nonce? %s nonce = %x \n", + (inp->inp_vflag & INP_USE_NONCE)? "yes":"no", + ntohl(inp->inp_nonce)); + log(LOG_INFO, + "pcbrehash: saddr = %x sport = %x daddr = %x dport = %x\n", + ntohl(inp->inp_laddr.s_addr), ntohs(inp->inp_lport), + ntohl(inp->inp_faddr.s_addr), ntohs(inp->inp_fport)); + } +#endif +#ifdef LATEBINDING + if (inp->inp_vflag & INP_USE_NONCE){ + /* have to ensure that nonce is non null */ + hashkey_faddr = htonl(inp->inp_nonce); + } +#endif head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr, inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)]; Index: sys/netinet/in_pcb.h =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/in_pcb.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/in_pcb.h 5 Aug 2004 22:32:33 -0000 1.1.1.1 +++ sys/netinet/in_pcb.h 9 Aug 2004 18:26:12 -0000 1.2 @@ -130,6 +130,8 @@ /* local and foreign ports, local and foreign addr */ struct in_conninfo inp_inc; + u_int32_t inp_nonce; /* for latebinding */ + caddr_t inp_ppcb; /* pointer to per-protocol pcb */ struct inpcbinfo *inp_pcbinfo; /* PCB list info */ struct socket *inp_socket; /* back pointer to socket */ @@ -140,6 +142,7 @@ u_char inp_vflag; /* IP version flag (v4/v6) */ #define INP_IPV4 0x1 #define INP_IPV6 0x2 +#define INP_USE_NONCE 0x20 /* nonce */ u_char inp_ip_ttl; /* time to live proto */ u_char inp_ip_p; /* protocol proto */ Index: sys/netinet/ip_output.c =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/ip_output.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/ip_output.c 5 Aug 2004 22:32:33 -0000 1.1.1.1 +++ sys/netinet/ip_output.c 9 Aug 2004 18:26:12 -0000 1.2 @@ -42,6 +42,7 @@ #include "opt_mac.h" #include "opt_pfil_hooks.h" #include "opt_random_ip_id.h" +#include "opt_latebinding.h" #include #include @@ -52,6 +53,7 @@ #include #include #include +#include #include #include @@ -198,6 +200,13 @@ mtod(m, struct ip *)->ip_p)); #endif +#ifdef LATEBINDING + if (inp && inp->inp_socket && + (inp->inp_socket->so_options & SO_LATEBINDING)){ + log(LOG_INFO, "ip_output latebinding enabled on this socket \n"); + } +#endif + if (args.rule != NULL) { /* dummynet already saw us */ ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2 ; @@ -975,12 +984,49 @@ m->m_pkthdr.csum_flags |= CSUM_IP; sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_hwassist; + +#ifdef LATEBINDING + if (inp && inp->inp_socket && + (inp->inp_socket->so_options & SO_LATEBINDING)){ + log(LOG_INFO, "ip_output latebinding enabled 2 \n"); + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA){ + log(LOG_INFO, " CSUM_DELAY_DATA = %x sw_csum = %x \n", CSUM_DELAY_DATA, sw_csum); + } + } +#endif + +#ifdef LATEBINDING + /* the problem seems to be that in case of source routes, + although the pseudo header specified in fill headers is + different from that of the first hop, the checksum computed + seems to be using the first step. the speculation here is + that it is the hardware which is doing the trick i.e., it + is ignoring the pseudoheader and computing one by itself. A + change in the first hop (keeping the destination of the + source route same) required the new firsthop IP address to + be put into IP header as destination before for the + checksum to go through. The idea is to force the checksum + computation in software. */ + if ((inp) && + (inp->inp_socket->so_options & SO_LATEBINDING) && + (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)){ + log(LOG_INFO, "delayed checksum\n"); + in_delayed_cksum(m); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + } +#endif if (sw_csum & CSUM_DELAY_DATA) { in_delayed_cksum(m); sw_csum &= ~CSUM_DELAY_DATA; } m->m_pkthdr.csum_flags &= ifp->if_hwassist; +#ifdef LATEBINDING + if (inp && inp->inp_socket && + (inp->inp_socket->so_options & SO_LATEBINDING)){ + log(LOG_INFO, "csum next step csum_flags = %x !\n", m->m_pkthdr.csum_flags ); + } +#endif /* * If small enough for interface, or the interface will take * care of the fragmentation for us, can just send directly. @@ -1208,6 +1254,12 @@ #endif /* FAST_IPSEC */ return (error); bad: +#ifdef LATEBINDING + if (inp && inp->inp_socket && + (inp->inp_socket->so_options & SO_LATEBINDING)){ + log(LOG_INFO, "packet dropped error = %u \n", error); + } +#endif m_freem(m); goto done; } Index: sys/netinet/tcp.h =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/tcp.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/tcp.h 5 Aug 2004 22:32:33 -0000 1.1.1.1 +++ sys/netinet/tcp.h 9 Aug 2004 18:26:12 -0000 1.2 @@ -103,6 +103,9 @@ #define TCPOPT_CC_HDR(ccopt) \ (TCPOPT_NOP<<24|TCPOPT_NOP<<16|(ccopt)<<8|TCPOLEN_CC) +#define TCPOPT_NONCE 28 +#define TCPOLEN_NONCE 6 + /* * Default maximum segment size for TCP. * With an IP MSS of 576, this is 536, Index: sys/netinet/tcp_input.c =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/tcp_input.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- sys/netinet/tcp_input.c 5 Aug 2004 22:32:34 -0000 1.1.1.1 +++ sys/netinet/tcp_input.c 28 Aug 2004 05:02:19 -0000 1.3 @@ -40,6 +40,7 @@ #include "opt_mac.h" #include "opt_tcpdebug.h" #include "opt_tcp_input.h" +#include "opt_latebinding.h" #include #include @@ -54,6 +55,7 @@ #include #include #include +#include #include /* before tcp_seq.h, for tcp_random18() */ @@ -326,6 +328,67 @@ } #endif +#ifdef LATEBINDING +/* process the TCP header to see if there is a TCP Nonce + * option is present. It is necessary for computation of + * the checksum + */ +static u_int extract_nonce_fromopt(u_char *cp, int cnt) { + + unsigned int nonce = 0; + unsigned int optlen = 0; + + for (; cnt > 0; cnt -= optlen, cp += optlen) { + u_char opt = cp[0]; + if (opt == TCPOPT_EOL) + break; + if (opt == TCPOPT_NOP) + optlen = 1; + else { + if (cnt < 2) break; + optlen = cp[1]; + if (optlen < 2 || optlen > cnt) break; + if (opt == TCPOPT_NONCE){ + nonce = *(unsigned int *) (cp + 2); + log(LOG_INFO, + "extract_nonce: found nonce = %x \n", nonce); + break; + } + } + } + + return nonce; + +}; + +static u_int extract_nonce(register struct mbuf *m){ + + register struct ip *ip = NULL; + unsigned tcpdataoff = 0; + unsigned char *tcpopt = 0; + register struct tcphdr *th; + + ip = mtod(m, struct ip *); + th = (struct tcphdr *)((caddr_t)ip + sizeof(struct ip)); + + /* look at the tcp options to compute the checksum */ + tcpdataoff = th->th_off << 2; /* includes the TCP header */ + if (tcpdataoff > sizeof (struct tcphdr)) { + /* look at the options only if necessary */ + if (m->m_len < (sizeof(struct ip) + tcpdataoff)) { + if ((m = m_pullup(m, sizeof (struct ip) + tcpdataoff)) == 0) { + return 0; + } + } + tcpopt = (u_char *)th + sizeof(struct tcphdr); + return /* nonce in network long format */ + extract_nonce_fromopt(tcpopt, + tcpdataoff - sizeof(struct tcphdr)); + } + return 0; +} /* finish computing the nonce */ +#endif + void tcp_input(m, off0) register struct mbuf *m; @@ -357,6 +420,10 @@ #else const int isipv6 = 0; #endif +#ifdef LATEBINDING + unsigned int nonce = 0; + unsigned int mypkt = 0; +#endif #ifdef TCPDEBUG /* @@ -426,6 +493,27 @@ th = (struct tcphdr *)((caddr_t)ip + off0); tlen = ip->ip_len; +#ifdef LATEBINDING + nonce = extract_nonce(m); + if (((ip->ip_src.s_addr == htonl(0x8009a83a))|| + (ip->ip_dst.s_addr == htonl(0x8009a83a))) && + ((ip->ip_src.s_addr == htonl(0x8009a838))|| + (ip->ip_dst.s_addr == htonl(0x8009a838)))){ + mypkt = 1; + log(LOG_INFO, "pkt received: src = %x dst = %x \n", + ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr)); + log(LOG_INFO, "Came here valid = %x hdr = %x \n", + m->m_pkthdr.csum_flags & CSUM_DATA_VALID, + m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR); + } + if (nonce){ + /* ignore the setting from the hardware and + the driver. force computation of the + checksum in software */ + mypkt = 1; + m->m_pkthdr.csum_flags &= ~CSUM_DATA_VALID; + } +#endif if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) th->th_sum = m->m_pkthdr.csum_data; @@ -444,8 +532,40 @@ bzero(ipov->ih_x1, sizeof(ipov->ih_x1)); ipov->ih_len = (u_short)tlen; ipov->ih_len = htons(ipov->ih_len); - th->th_sum = in_cksum(m, len); +#ifdef LATEBINDING + if (mypkt) + log(LOG_INFO, "Computing checksum\n"); + + if (nonce && (th->th_flags & TH_SYN)){ + if (!(th->th_flags & TH_ACK)){ + unsigned int dst = ipov->ih_dst.s_addr; + log(LOG_INFO, "using the nonce %x for checksum as the dst \n", nonce); + log(LOG_INFO, "src = %x dst = %x \n", + ntohl(ipov->ih_src.s_addr), ntohl(ipov->ih_dst.s_addr)); + ipov->ih_dst.s_addr = nonce; + th->th_sum = in_cksum(m, len); /* make it official */ + ipov->ih_dst.s_addr = dst; /* undo the change */ + } else { + unsigned int src = ipov->ih_src.s_addr; + log(LOG_INFO, "using the nonce %x for checksum as the src \n", nonce); + log(LOG_INFO, "src = %x dst = %x \n", + ntohl(ipov->ih_src.s_addr), ntohl(ipov->ih_dst.s_addr)); + ipov->ih_src.s_addr = nonce; + th->th_sum = in_cksum(m, len); /* make it official */ + ipov->ih_src.s_addr = src; /* undo the change */ + } + } else { +#endif + th->th_sum = in_cksum(m, len); +#ifdef LATEBINDING + } +#endif } +#ifdef LATEBINDING + if (mypkt){ + log(LOG_INFO, "th_sum = %x \n", th->th_sum); + } +#endif if (th->th_sum) { tcpstat.tcps_rcvbadsum++; goto drop; @@ -455,7 +575,6 @@ ip->ip_v = IPVERSION; #endif } - /* * Check that TCP offset makes sense, * pull out TCP options and adjust length. XXX @@ -552,10 +671,36 @@ &ip6->ip6_dst, th->th_dport, 1, m->m_pkthdr.rcvif); else +#ifdef LATEBINDING + if (!nonce){ +#endif inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, th->th_sport, ip->ip_dst, th->th_dport, 1, m->m_pkthdr.rcvif); +#ifdef LATEBINDING + } else { + /* Have to check for PCBs with the correct + destination address. + */ + + struct in_addr faddr; + faddr.s_addr = nonce; /* nonce is already in network long format */ + + log(LOG_INFO, "looking up hash with src_addr = %x source port = %x dst addr = %x dst port = %x \n", + ntohl(ip->ip_dst.s_addr), ntohs(th->th_dport), + ntohl(faddr.s_addr), ntohs(th->th_sport)); + + /* lookup to see if the connection has been + indexed using the nonce */ + inp = in_pcblookup_hash(&tcbinfo, + faddr, th->th_sport, + ip->ip_dst, th->th_dport, + 1, m->m_pkthdr.rcvif); + + log(LOG_INFO, "inp = %x \n", (uint32_t)inp); + } +#endif } #ifdef IPSEC @@ -642,6 +787,26 @@ rstreason = BANDLIM_RST_CLOSEDPORT; goto dropwithreset; } +#ifdef LATEBINDING + /* We cannot come here if the inp lookup has not occured + properly using the nonce. If the nonce is used and the inp + still carries the USE_NONCE flag that means that this is + the initiator of the connection and that this end should be + now correctly indexed using the destination address instead + of the nonce + + There should be a check here for whether the nonce will be + used permanently or used only for the bootstrapping + + before anything happens, index the connection back. + */ + + if (inp->inp_vflag & INP_USE_NONCE){ + inp->inp_vflag &= ~INP_USE_NONCE; + in_pcbrehash(inp); + } +#endif + INP_LOCK(inp); tp = intotcpcb(inp); if (tp == 0) { @@ -2264,6 +2429,12 @@ return; dropwithreset: +#ifdef LATEBINDING + if (mypkt){ + log(LOG_INFO, "dropping with reset rstreason = %x \n", + rstreason); + } +#endif /* * Generate a RST, dropping incoming segment. * Make ACK acceptable to originator of segment. @@ -2315,6 +2486,11 @@ return; drop: +#ifdef LATEBINDING + if (mypkt){ + log(LOG_INFO, "dropping packet\n"); + } +#endif /* * Drop space held by incoming segment and return. */ @@ -2343,6 +2519,9 @@ int opt, optlen; to->to_flags = 0; +#ifdef LATEBINDING + to->to_nonce = 0; +#endif for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[0]; if (opt == TCPOPT_EOL) @@ -2414,6 +2593,18 @@ (char *)&to->to_ccecho, sizeof(to->to_ccecho)); to->to_ccecho = ntohl(to->to_ccecho); break; +#ifdef LATEBINDING + case TCPOPT_NONCE: + if (optlen != TCPOLEN_NONCE) + continue; + if (!is_syn) + continue; + bcopy((char *)cp + 2, + (char *)&to->to_nonce, sizeof(to->to_nonce)); + /* to->to_nonce = ntohl(to->to_nonce); */ + log(LOG_INFO, "incoming packet has nonce = %x \n", to->to_nonce); + break; +#endif default: continue; } Index: sys/netinet/tcp_output.c =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/tcp_output.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- sys/netinet/tcp_output.c 5 Aug 2004 22:32:34 -0000 1.1.1.1 +++ sys/netinet/tcp_output.c 28 Aug 2004 05:02:20 -0000 1.3 @@ -38,6 +38,7 @@ #include "opt_ipsec.h" #include "opt_mac.h" #include "opt_tcpdebug.h" +#include "opt_latebinding.h" #include #include @@ -51,6 +52,7 @@ #include #include #include +#include #include @@ -137,6 +139,12 @@ mtx_assert(&tp->t_inpcb->inp_mtx, MA_OWNED); #endif +#ifdef LATEBINDING + if (so->so_options & SO_LATEBINDING){ + log(LOG_INFO, "looking at socket %x with latebinding enabled %x \n", + (uint32_t)so, so->so_options); + } +#endif /* * Determine length of data that should be transmitted, * and flags that will be used. @@ -411,6 +419,12 @@ return (0); send: +#ifdef LATEBINDING + if (so->so_options & SO_LATEBINDING){ + log(LOG_INFO, "about to send the packet from socket %x \n", + (uint32_t)so); + } +#endif /* * Before ESTABLISHED, force sending of initial options * unless TCP set not to do any options. @@ -447,6 +461,24 @@ tp->request_r_scale); optlen += 4; } +#ifdef LATEBINDING + /* insert the nonce */ + if (so->so_options & SO_LATEBINDING){ + unsigned char *opt1 = &opt[optlen]; + + log(LOG_INFO, " latebinding adding the nonce option %x socket %x \n", + (uint32_t) tp->t_inpcb->inp_nonce, (uint32_t)so); + opt1[0] = TCPOPT_NOP; + opt1[1] = TCPOPT_NOP; + opt1[2] = TCPOPT_NONCE; + opt1[3] = TCPOLEN_NONCE; + + /* nonce is already allocated during initialization */ + *(unsigned int *)(opt1 + 4) = htonl(tp->t_inpcb->inp_nonce); + optlen += 8; + } +#endif + } } @@ -774,9 +806,22 @@ { m->m_pkthdr.csum_flags = CSUM_TCP; m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); - if (len + optlen) +#ifdef LATEBINDING + if ((flags & TH_SYN) && !(flags & TH_ACK) && + (so->so_options & SO_LATEBINDING)){ + log(LOG_INFO, "checksum using the nonce\n"); + th->th_sum = in_pseudo(ip->ip_src.s_addr, htonl(tp->t_inpcb->inp_nonce), + htons(sizeof(struct tcphdr) + IPPROTO_TCP + len + optlen)); + } else { + if (so->so_options & SO_LATEBINDING) + log(LOG_INFO, "checksum without using the nonce\n"); +#endif + if (len + optlen) th->th_sum = in_addword(th->th_sum, htons((u_short)(optlen + len))); +#ifdef LATEBINDING + } +#endif /* IP version must be set here for ipv4/ipv6 checking later */ KASSERT(ip->ip_v == IPVERSION, Index: sys/netinet/tcp_subr.c =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/tcp_subr.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- sys/netinet/tcp_subr.c 5 Aug 2004 22:32:34 -0000 1.1.1.1 +++ sys/netinet/tcp_subr.c 28 Aug 2004 05:02:20 -0000 1.3 @@ -39,6 +39,7 @@ #include "opt_ipsec.h" #include "opt_mac.h" #include "opt_tcpdebug.h" +#include "opt_latebinding.h" #include #include @@ -594,6 +595,7 @@ tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->t_rcvtime = ticks; tp->t_bw_rtttime = ticks; + /* * IPv4 TTL initialization is necessary for an IPv6 socket as well, * because the socket may be bound to an IPv6 wildcard address, Index: sys/netinet/tcp_syncache.c =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/tcp_syncache.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- sys/netinet/tcp_syncache.c 5 Aug 2004 22:32:34 -0000 1.1.1.1 +++ sys/netinet/tcp_syncache.c 28 Aug 2004 05:02:20 -0000 1.3 @@ -37,6 +37,7 @@ #include "opt_inet6.h" #include "opt_ipsec.h" #include "opt_mac.h" +#include "opt_latebinding.h" #include #include @@ -50,6 +51,7 @@ #include #include #include +#include #include #include @@ -692,6 +694,15 @@ tp->rcv_wnd = sc->sc_wnd; tp->rcv_adv += tp->rcv_wnd; +#ifdef LATEBINDING + inp->inp_nonce = sc->sc_nonce; + if (inp->inp_nonce){ + log(LOG_INFO, "nonce stored in tcpcb %x \n", + (uint32_t)inp->inp_nonce); + inp->inp_socket->so_options |= SO_LATEBINDING; + } +#endif + tp->t_flags = sototcpcb(lso)->t_flags & (TF_NOPUSH|TF_NODELAY); if (sc->sc_flags & SCF_NOOPT) tp->t_flags |= TF_NOOPT; @@ -936,6 +947,15 @@ else sc->sc_iss = arc4random(); +#ifdef LATEBINDING + if (to->to_nonce){ + log(LOG_INFO, "copying the nonce %x to the sc\n", to->to_nonce); + log(LOG_INFO, "faddr = %x laddr = %x \n", + sc->sc_inc.inc_faddr.s_addr, sc->sc_inc.inc_laddr.s_addr); + } + sc->sc_nonce = to->to_nonce; +#endif + /* Initial receive window: clip sbspace to [0 .. TCP_MAXWIN] */ win = sbspace(&so->so_rcv); win = imax(win, 0); @@ -1083,6 +1103,9 @@ ((sc->sc_flags & SCF_WINSCALE) ? 4 : 0) + ((sc->sc_flags & SCF_TIMESTAMP) ? TCPOLEN_TSTAMP_APPA : 0) + ((sc->sc_flags & SCF_CC) ? TCPOLEN_CC_APPA * 2 : 0); +#ifdef LATEBINDING + if (sc->sc_nonce) optlen += 8; +#endif } tlen = hlen + sizeof(struct tcphdr) + optlen; @@ -1201,6 +1224,20 @@ *lp = htonl(sc->sc_cc_recv); optp += TCPOLEN_CC_APPA * 2; } + +#ifdef LATEBINDING + if (sc->sc_nonce){ + log(LOG_INFO, "inserting the nonce %x into the synack\n", + sc->sc_nonce); + *optp++ = TCPOPT_NOP; + *optp++ = TCPOPT_NOP; + optp[0] = TCPOPT_NONCE; + optp[1] = TCPOLEN_NONCE; + *((u_int32_t *)(optp+2)) = sc->sc_nonce; + optp += TCPOLEN_NONCE; + } +#endif + no_options: #ifdef INET6 @@ -1216,8 +1253,20 @@ } else #endif { +#ifdef LATEBINDING + if (sc->sc_nonce) { + log(LOG_INFO, + "computing the checksum with nonce = %x instead of src = %x and dst = %x\n", + sc->sc_nonce, ip->ip_src.s_addr, ip->ip_dst.s_addr); + th->th_sum = in_pseudo(sc->sc_nonce, ip->ip_dst.s_addr, + htons(tlen - hlen + IPPROTO_TCP)); + } else { +#endif th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htons(tlen - hlen + IPPROTO_TCP)); +#ifdef LATEBINDING + } +#endif m->m_pkthdr.csum_flags = CSUM_TCP; m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); error = ip_output(m, sc->sc_ipopts, &sc->sc_route, 0, NULL, Index: sys/netinet/tcp_usrreq.c =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/tcp_usrreq.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- sys/netinet/tcp_usrreq.c 5 Aug 2004 22:32:34 -0000 1.1.1.1 +++ sys/netinet/tcp_usrreq.c 28 Aug 2004 05:02:20 -0000 1.3 @@ -37,6 +37,7 @@ #include "opt_ipsec.h" #include "opt_inet6.h" #include "opt_tcpdebug.h" +#include "opt_latebinding.h" #include #include @@ -44,6 +45,7 @@ #include #include #include +#include #ifdef INET6 #include #endif /* INET6 */ @@ -497,6 +499,14 @@ port = inp->inp_fport; addr = inp->inp_faddr; +#ifdef LATEBINDING + if (inp->inp_vflag & INP_USE_NONCE){ + inp->inp_vflag &= ~INP_USE_NONCE; + in_pcbrehash(inp); + log(LOG_INFO, "tcp_accept: resetting the INP_USE_NONCE flag \n"); + } +#endif + out: TCPDEBUG2(PRU_ACCEPT); if (tp) INP_UNLOCK(inp); @@ -852,7 +862,7 @@ struct rmxp_tao tao_noncached; struct in_addr laddr; u_short lport; - int error; + int error = 0; if (inp->inp_lport == 0) { error = in_pcbbind(inp, (struct sockaddr *)0, td); @@ -867,6 +877,14 @@ */ laddr = inp->inp_laddr; lport = inp->inp_lport; + +#ifdef LATEBINDING + if (inp->inp_socket->so_options & SO_LATEBINDING){ + log(LOG_INFO, " setting the use_nonce flag\n"); + inp->inp_vflag |= INP_USE_NONCE; + } +#endif + error = in_pcbconnect_setup(inp, nam, &laddr.s_addr, &lport, &inp->inp_faddr.s_addr, &inp->inp_fport, &oinp, td); if (error && oinp == NULL) Index: sys/netinet/tcp_var.h =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/tcp_var.h,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- sys/netinet/tcp_var.h 5 Aug 2004 22:32:34 -0000 1.1.1.1 +++ sys/netinet/tcp_var.h 28 Aug 2004 05:02:20 -0000 1.3 @@ -175,6 +175,7 @@ u_long snd_cwnd_prev; /* cwnd prior to retransmit */ u_long snd_ssthresh_prev; /* ssthresh prior to retransmit */ u_long t_badrxtwin; /* window for retransmit recovery */ + }; /* @@ -198,6 +199,7 @@ u_int16_t to_mss; u_int8_t to_requested_s_scale; u_int8_t to_pad; + u_int32_t to_nonce; /* for latebinding */ }; struct syncache { @@ -225,6 +227,7 @@ #define SCF_CC 0x08 /* negotiated CC */ #define SCF_UNREACH 0x10 /* icmp unreachable received */ #define SCF_KEEPROUTE 0x20 /* keep cloned route */ + u_int32_t sc_nonce; TAILQ_ENTRY(syncache) sc_hash; TAILQ_ENTRY(syncache) sc_timerq; }; Index: sys/netinet/udp_usrreq.c =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/netinet/udp_usrreq.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/udp_usrreq.c 5 Aug 2004 22:32:34 -0000 1.1.1.1 +++ sys/netinet/udp_usrreq.c 28 Aug 2004 05:02:20 -0000 1.2 @@ -37,6 +37,7 @@ #include "opt_ipsec.h" #include "opt_inet6.h" #include "opt_mac.h" +#include "opt_latebinding.h" #include #include Index: sys/sys/socket.h =================================================================== RCS file: /home/xbone/CVSROOT/latebinding/sys/sys/socket.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/sys/socket.h 5 Aug 2004 22:32:49 -0000 1.1.1.1 +++ sys/sys/socket.h 9 Aug 2004 18:28:39 -0000 1.2 @@ -124,6 +124,7 @@ #define SO_TIMESTAMP 0x0400 /* timestamp received dgram traffic */ #define SO_NOSIGPIPE 0x0800 /* no SIGPIPE from EPIPE */ #define SO_ACCEPTFILTER 0x1000 /* there is an accept filter */ +#define SO_LATEBINDING 0x2000 /* latebinding option */ #endif /*