156483Ssklower /* 2*57949Ssklower * Copyright (c) 1992, 1993 Regents of the University of California. 356483Ssklower * All rights reserved. 456483Ssklower * 556483Ssklower * %sccs.include.redist.c% 656483Ssklower * 7*57949Ssklower * @(#)tuba_subr.c 7.12 (Berkeley) 02/12/93 856483Ssklower */ 956483Ssklower 1056565Ssklower #include <sys/param.h> 1156565Ssklower #include <sys/proc.h> 1256565Ssklower #include <sys/systm.h> 1356565Ssklower #include <sys/malloc.h> 1456565Ssklower #include <sys/mbuf.h> 1556565Ssklower #include <sys/socket.h> 1656565Ssklower #include <sys/socketvar.h> 1756565Ssklower #include <sys/protosw.h> 1856565Ssklower #include <sys/errno.h> 1956483Ssklower 2056565Ssklower #include <net/route.h> 2156565Ssklower #include <net/if.h> 2256483Ssklower 2356565Ssklower #include <netinet/in.h> 2456565Ssklower #include <netinet/in_systm.h> 2556565Ssklower #include <netinet/ip.h> 2656565Ssklower #include <netinet/in_pcb.h> 2756565Ssklower #include <netinet/ip_var.h> 2856565Ssklower #include <netinet/ip_icmp.h> 2956565Ssklower #include <netinet/tcp.h> 3056565Ssklower #include <netinet/tcp_fsm.h> 3156565Ssklower #include <netinet/tcp_seq.h> 3256565Ssklower #include <netinet/tcp_timer.h> 3356565Ssklower #include <netinet/tcp_var.h> 3456565Ssklower #include <netinet/tcpip.h> 3556565Ssklower #include <netinet/tcp_debug.h> 3656483Ssklower 3756565Ssklower #include <netiso/argo_debug.h> 3856565Ssklower #include <netiso/iso.h> 3956565Ssklower #include <netiso/clnp.h> 4056565Ssklower #include <netiso/iso_pcb.h> 4156565Ssklower #include <netiso/iso_var.h> 4256681Ssklower #include <netiso/tuba_table.h> 4356483Ssklower 4456690Ssklower static struct sockaddr_iso null_siso = { sizeof(null_siso), AF_ISO, }; 4556704Ssklower extern int tuba_table_size, tcp_keepidle, tcp_keepintvl, tcp_maxidle; 4656690Ssklower extern int tcppcbcachemiss, tcppredack, tcppreddat, tcprexmtthresh; 4756690Ssklower extern struct tcpiphdr tcp_saveti; 4856690Ssklower struct inpcb tuba_inpcb; 4956704Ssklower struct inpcb *tuba_last_inpcb = &tuba_inpcb; 5056690Ssklower struct isopcb tuba_isopcb; 5156483Ssklower /* 5256483Ssklower * Tuba initialization 5356483Ssklower */ 5456483Ssklower tuba_init() 5556483Ssklower { 5656484Ssklower #define TUBAHDRSIZE (3 /*LLC*/ + 9 /*CLNP Fixed*/ + 42 /*Addresses*/ \ 5756484Ssklower + 6 /*CLNP Segment*/ + 20 /*TCP*/) 5856483Ssklower 5956690Ssklower tuba_inpcb.inp_next = tuba_inpcb.inp_prev = &tuba_inpcb; 6056483Ssklower tuba_isopcb.isop_next = tuba_isopcb.isop_prev = &tuba_isopcb; 6156565Ssklower tuba_isopcb.isop_faddr = &tuba_isopcb.isop_sfaddr; 6256565Ssklower tuba_isopcb.isop_laddr = &tuba_isopcb.isop_sladdr; 6356483Ssklower if (max_protohdr < TUBAHDRSIZE) 6456483Ssklower max_protohdr = TUBAHDRSIZE; 6556483Ssklower if (max_linkhdr + TUBAHDRSIZE > MHLEN) 6656483Ssklower panic("tuba_init"); 6756483Ssklower } 6856483Ssklower 6956901Ssklower struct addr_arg { 7056901Ssklower int error; 7156901Ssklower int offset; 7256901Ssklower u_long sum; 7356901Ssklower }; 7456901Ssklower 7556903Ssklower /* 7656903Ssklower * Calculate contribution to fudge factor for TCP checksum, 7756903Ssklower * and coincidentally set pointer for convenience of clnp_output 7856903Ssklower * if we are are responding when there is no isopcb around. 7956903Ssklower */ 8056485Ssklower static void 8156901Ssklower tuba_getaddr(arg, siso, index) 8256901Ssklower register struct addr_arg *arg; 8356704Ssklower struct sockaddr_iso **siso; 8456485Ssklower u_long index; 8556485Ssklower { 8656485Ssklower register struct tuba_cache *tc; 8756681Ssklower if (index <= tuba_table_size && (tc = tuba_table[index])) { 8856704Ssklower if (siso) 8956704Ssklower *siso = &tc->tc_siso; 9056903Ssklower arg->sum += (arg->offset & 1 ? tc->tc_ssum : tc->tc_sum) 9156903Ssklower + (0xffff ^ index); 9256901Ssklower arg->offset += tc->tc_siso.siso_nlen + 1; 9356485Ssklower } else 9456901Ssklower arg->error = 1; 9556485Ssklower } 9656485Ssklower 9756485Ssklower tuba_output(m, tp) 9856485Ssklower register struct mbuf *m; 9956483Ssklower struct tcpcb *tp; 10056483Ssklower { 10156690Ssklower register struct tcpiphdr *n; 10256901Ssklower struct isopcb *isop; 10356901Ssklower struct addr_arg arg; 10456483Ssklower 10556681Ssklower if (tp == 0 || (n = tp->t_template) == 0 || 10656681Ssklower (isop = (struct isopcb *)tp->t_tuba_pcb) == 0) { 10756485Ssklower isop = &tuba_isopcb; 10856681Ssklower n = mtod(m, struct tcpiphdr *); 10956901Ssklower arg.error = arg.sum = arg.offset = 0; 11056901Ssklower tuba_getaddr(&arg, &tuba_isopcb.isop_faddr, n->ti_dst.s_addr); 11156901Ssklower tuba_getaddr(&arg, &tuba_isopcb.isop_laddr, n->ti_src.s_addr); 11256901Ssklower REDUCE(arg.sum, arg.sum); 11356485Ssklower goto adjust; 11456485Ssklower } 11556565Ssklower if (n->ti_sum == 0) { 11656901Ssklower arg.error = arg.sum = arg.offset = 0; 11756901Ssklower tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_dst.s_addr); 11856901Ssklower tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_src.s_addr); 11956901Ssklower REDUCE(arg.sum, arg.sum); 12056901Ssklower n->ti_sum = arg.sum; 12156485Ssklower n = mtod(m, struct tcpiphdr *); 12256485Ssklower adjust: 12356901Ssklower if (arg.error) { 12456485Ssklower m_freem(m); 12556681Ssklower return (EADDRNOTAVAIL); 12656485Ssklower } 12756901Ssklower REDUCE(n->ti_sum, n->ti_sum + (0xffff ^ arg.sum)); 12856483Ssklower } 12956483Ssklower m->m_len -= sizeof (struct ip); 13056483Ssklower m->m_pkthdr.len -= sizeof (struct ip); 13156483Ssklower m->m_data += sizeof (struct ip); 13256901Ssklower return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 13356483Ssklower } 13456483Ssklower 13556483Ssklower tuba_refcnt(isop, delta) 13656483Ssklower struct isopcb *isop; 13756483Ssklower { 13856483Ssklower register struct tuba_cache *tc; 13956485Ssklower unsigned index, sum; 14056483Ssklower 14156483Ssklower if (delta != 1) 14256483Ssklower delta = -1; 14356483Ssklower if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 14456483Ssklower (delta == -1 && isop->isop_tuba_cached == 0) || 14556483Ssklower (delta == 1 && isop->isop_tuba_cached != 0)) 14656483Ssklower return; 14756483Ssklower isop->isop_tuba_cached = (delta == 1); 14856912Ssklower if ((index = tuba_lookup(isop->isop_faddr, M_DONTWAIT)) != 0 && 14956565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 15056483Ssklower tc->tc_refcnt += delta; 15156912Ssklower if ((index = tuba_lookup(isop->isop_laddr, M_DONTWAIT)) != 0 && 15256565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 15356483Ssklower tc->tc_refcnt += delta; 15456483Ssklower } 15556483Ssklower 15656483Ssklower tuba_pcbdetach(isop) 15756483Ssklower struct isopcb *isop; 15856483Ssklower { 15956483Ssklower if (isop == 0) 16056483Ssklower return; 16156483Ssklower tuba_refcnt(isop, -1); 16256483Ssklower isop->isop_socket = 0; 16356483Ssklower iso_pcbdetach(isop); 16456483Ssklower } 16556483Ssklower 16656483Ssklower /* 16756483Ssklower * Avoid in_pcbconnect in faked out tcp_input() 16856483Ssklower */ 16956483Ssklower tuba_pcbconnect(inp, nam) 17056483Ssklower register struct inpcb *inp; 17156483Ssklower struct mbuf *nam; 17256483Ssklower { 17356912Ssklower register struct sockaddr_iso *siso; 17456565Ssklower struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 17556483Ssklower struct tcpcb *tp = intotcpcb(inp); 17656565Ssklower struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; 17756483Ssklower int error; 17856483Ssklower 17956912Ssklower /* hardwire iso_pcbbind() here */ 18056912Ssklower siso = isop->isop_laddr = &isop->isop_sladdr; 18156912Ssklower *siso = tuba_table[inp->inp_laddr.s_addr]->tc_siso; 18256912Ssklower siso->siso_tlen = sizeof(inp->inp_lport); 18356912Ssklower bcopy((caddr_t)&inp->inp_lport, TSEL(siso), sizeof(inp->inp_lport)); 18456912Ssklower 18556912Ssklower /* hardwire in_pcbconnect() here without assigning route */ 18656483Ssklower inp->inp_fport = sin->sin_port; 18756912Ssklower inp->inp_faddr = sin->sin_addr; 18856912Ssklower 18956912Ssklower /* reuse nam argument to call iso_pcbconnect() */ 19056912Ssklower nam->m_len = sizeof(*siso); 19156912Ssklower siso = mtod(nam, struct sockaddr_iso *); 19256912Ssklower *siso = tuba_table[inp->inp_faddr.s_addr]->tc_siso; 19356483Ssklower siso->siso_tlen = sizeof(inp->inp_fport); 19456483Ssklower bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 19556912Ssklower 19656483Ssklower if ((error = iso_pcbconnect(isop, nam)) == 0) 19756483Ssklower tuba_refcnt(isop, 1); 19856483Ssklower return (error); 19956483Ssklower } 20056483Ssklower 20156483Ssklower /* 20256483Ssklower * CALLED FROM: 20356483Ssklower * clnp's input routine, indirectly through the protosw. 20456483Ssklower * FUNCTION and ARGUMENTS: 20556565Ssklower * Take a packet (m) from clnp, strip off the clnp header 20656565Ssklower * and do tcp input processing. 20756483Ssklower * No return value. 20856483Ssklower */ 20956903Ssklower tuba_tcpinput(m, src, dst) 21056483Ssklower register struct mbuf *m; 21156483Ssklower struct sockaddr_iso *src, *dst; 21256483Ssklower { 21356681Ssklower unsigned long sum, lindex, findex; 21456483Ssklower register struct tcpiphdr *ti; 21556483Ssklower register struct inpcb *inp; 216*57949Ssklower caddr_t optp = NULL; 217*57949Ssklower int optlen; 21856483Ssklower int len, tlen, off; 21956483Ssklower register struct tcpcb *tp = 0; 22056483Ssklower int tiflags; 22156483Ssklower struct socket *so; 22256483Ssklower int todrop, acked, ourfinisacked, needoutput = 0; 22356483Ssklower short ostate; 22456483Ssklower struct in_addr laddr; 22556483Ssklower int dropsocket = 0, iss = 0; 226*57949Ssklower u_long tiwin, ts_val, ts_ecr; 227*57949Ssklower int ts_present = 0; 22856483Ssklower 22956903Ssklower if ((m->m_flags & M_PKTHDR) == 0) 23056903Ssklower panic("tuba_tcpinput"); 23156483Ssklower /* 23256483Ssklower * Do some housekeeping looking up CLNP addresses. 23356483Ssklower * If we are out of space might as well drop the packet now. 23456483Ssklower */ 23556483Ssklower tcpstat.tcps_rcvtotal++; 23656912Ssklower lindex = tuba_lookup(dst, M_DONTWAIT); 23756912Ssklower findex = tuba_lookup(src, M_DONTWAIT); 23856681Ssklower if (lindex == 0 || findex == 0) 23956483Ssklower goto drop; 24056483Ssklower /* 24156483Ssklower * CLNP gave us an mbuf chain WITH the clnp header pulled up, 24256903Ssklower * but the data pointer pushed past it. 24356483Ssklower */ 24456903Ssklower len = m->m_len; 24556903Ssklower tlen = m->m_pkthdr.len; 24656483Ssklower m->m_data -= sizeof(struct ip); 24756483Ssklower m->m_len += sizeof(struct ip); 24856483Ssklower m->m_pkthdr.len += sizeof(struct ip); 24956912Ssklower m->m_flags &= ~(M_MCAST|M_BCAST); /* XXX should do this in clnp_input */ 25056483Ssklower /* 25156483Ssklower * The reassembly code assumes it will be overwriting a useless 25256681Ssklower * part of the packet, which is why we need to have it point 25356483Ssklower * into the packet itself. 25456483Ssklower * 25556483Ssklower * Check to see if the data is properly alligned 25656483Ssklower * so that we can save copying the tcp header. 25756483Ssklower * This code knows way too much about the structure of mbufs! 25856483Ssklower */ 25956565Ssklower off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ? 26056565Ssklower (m->m_data - m->m_ext.ext_buf) : (m->m_data - m->m_pktdat))); 26156903Ssklower if (off || len < sizeof(struct tcphdr)) { 26256903Ssklower struct mbuf *m0 = m; 26356903Ssklower 26456903Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 26556903Ssklower if (m == 0) { 26656903Ssklower m = m0; 26756483Ssklower goto drop; 26856483Ssklower } 26956903Ssklower m->m_next = m0; 27056903Ssklower m->m_data += max_linkhdr; 27156912Ssklower m->m_pkthdr = m0->m_pkthdr; 27256912Ssklower m->m_flags = m0->m_flags & M_COPYFLAGS; 27356903Ssklower if (len < sizeof(struct tcphdr)) { 27456912Ssklower m->m_len = 0; 27556903Ssklower if ((m = m_pullup(m, sizeof(struct tcpiphdr))) == 0) { 27656903Ssklower tcpstat.tcps_rcvshort++; 27756903Ssklower return; 27856903Ssklower } 27956903Ssklower } else { 28056912Ssklower bcopy(mtod(m0, caddr_t) + sizeof(struct ip), 28156912Ssklower mtod(m, caddr_t) + sizeof(struct ip), 28256903Ssklower sizeof(struct tcphdr)); 28356903Ssklower m0->m_len -= sizeof(struct tcpiphdr); 28456903Ssklower m0->m_data += sizeof(struct tcpiphdr); 28556903Ssklower m->m_len = sizeof(struct tcpiphdr); 28656903Ssklower } 28756483Ssklower } 28856903Ssklower /* 28956903Ssklower * Calculate checksum of extended TCP header and data, 29056903Ssklower * replacing what would have been IP addresses by 29156903Ssklower * the IP checksum of the CLNP addresses. 29256903Ssklower */ 29356483Ssklower ti = mtod(m, struct tcpiphdr *); 29456901Ssklower ti->ti_dst.s_addr = tuba_table[lindex]->tc_sum; 29556901Ssklower if (dst->siso_nlen & 1) 29656901Ssklower ti->ti_src.s_addr = tuba_table[findex]->tc_sum; 29756901Ssklower else 29856901Ssklower ti->ti_src.s_addr = tuba_table[findex]->tc_ssum; 29956685Ssklower ti->ti_prev = ti->ti_next = 0; 30056685Ssklower ti->ti_x1 = 0; ti->ti_pr = ISOPROTO_TCP; 30156685Ssklower ti->ti_len = htons((u_short)tlen); 30256685Ssklower if (ti->ti_sum = in_cksum(m, m->m_pkthdr.len)) { 30356685Ssklower tcpstat.tcps_rcvbadsum++; 30456685Ssklower goto drop; 30556685Ssklower } 30656483Ssklower ti->ti_src.s_addr = findex; 30756483Ssklower ti->ti_dst.s_addr = lindex; 30856483Ssklower /* 30956483Ssklower * Now include the rest of TCP input 31056483Ssklower */ 31156565Ssklower #define TUBA_INCLUDE 31256690Ssklower #define in_pcbconnect tuba_pcbconnect 31356690Ssklower #define tcb tuba_inpcb 31456690Ssklower #define tcp_last_inpcb tuba_last_inpcb 31556483Ssklower 31656565Ssklower #include <netinet/tcp_input.c> 31756483Ssklower } 31856704Ssklower 31956704Ssklower #define tcp_slowtimo tuba_slowtimo 32056704Ssklower #define tcp_fasttimo tuba_fasttimo 32156903Ssklower 32256704Ssklower #include <netinet/tcp_timer.c> 323