156483Ssklower /* 256484Ssklower * Copyright (c) 1992 Regents of the University of California. 356483Ssklower * All rights reserved. 456483Ssklower * 556483Ssklower * %sccs.include.redist.c% 656483Ssklower * 7*56901Ssklower * @(#)tuba_subr.c 7.9 (Berkeley) 11/19/92 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 69*56901Ssklower struct addr_arg { 70*56901Ssklower int error; 71*56901Ssklower int offset; 72*56901Ssklower u_long sum; 73*56901Ssklower }; 74*56901Ssklower 7556485Ssklower static void 76*56901Ssklower tuba_getaddr(arg, siso, index) 77*56901Ssklower register struct addr_arg *arg; 7856704Ssklower struct sockaddr_iso **siso; 7956485Ssklower u_long index; 8056485Ssklower { 8156485Ssklower register struct tuba_cache *tc; 8256681Ssklower if (index <= tuba_table_size && (tc = tuba_table[index])) { 8356704Ssklower if (siso) 8456704Ssklower *siso = &tc->tc_siso; 85*56901Ssklower arg->sum += (arg->offset & 1 ? tc->tc_ssum_d : tc->tc_sum_d); 86*56901Ssklower arg->offset += tc->tc_siso.siso_nlen + 1; 8756485Ssklower } else 88*56901Ssklower arg->error = 1; 8956485Ssklower } 9056485Ssklower 9156485Ssklower tuba_output(m, tp) 9256485Ssklower register struct mbuf *m; 9356483Ssklower struct tcpcb *tp; 9456483Ssklower { 9556690Ssklower register struct tcpiphdr *n; 96*56901Ssklower struct isopcb *isop; 97*56901Ssklower struct addr_arg arg; 9856483Ssklower 9956681Ssklower if (tp == 0 || (n = tp->t_template) == 0 || 10056681Ssklower (isop = (struct isopcb *)tp->t_tuba_pcb) == 0) { 10156485Ssklower isop = &tuba_isopcb; 10256681Ssklower n = mtod(m, struct tcpiphdr *); 103*56901Ssklower arg.error = arg.sum = arg.offset = 0; 104*56901Ssklower tuba_getaddr(&arg, &tuba_isopcb.isop_faddr, n->ti_dst.s_addr); 105*56901Ssklower tuba_getaddr(&arg, &tuba_isopcb.isop_laddr, n->ti_src.s_addr); 106*56901Ssklower REDUCE(arg.sum, arg.sum); 10756485Ssklower goto adjust; 10856485Ssklower } 10956565Ssklower if (n->ti_sum == 0) { 110*56901Ssklower arg.error = arg.sum = arg.offset = 0; 111*56901Ssklower tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_dst.s_addr); 112*56901Ssklower tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_src.s_addr); 113*56901Ssklower REDUCE(arg.sum, arg.sum); 114*56901Ssklower n->ti_sum = arg.sum; 11556485Ssklower n = mtod(m, struct tcpiphdr *); 11656485Ssklower adjust: 117*56901Ssklower if (arg.error) { 11856485Ssklower m_freem(m); 11956681Ssklower return (EADDRNOTAVAIL); 12056485Ssklower } 121*56901Ssklower REDUCE(n->ti_sum, n->ti_sum + (0xffff ^ arg.sum)); 12256483Ssklower } 12356483Ssklower m->m_len -= sizeof (struct ip); 12456483Ssklower m->m_pkthdr.len -= sizeof (struct ip); 12556483Ssklower m->m_data += sizeof (struct ip); 126*56901Ssklower return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 12756483Ssklower } 12856483Ssklower 12956483Ssklower tuba_refcnt(isop, delta) 13056483Ssklower struct isopcb *isop; 13156483Ssklower { 13256483Ssklower register struct tuba_cache *tc; 13356485Ssklower unsigned index, sum; 13456483Ssklower 13556483Ssklower if (delta != 1) 13656483Ssklower delta = -1; 13756483Ssklower if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 13856483Ssklower (delta == -1 && isop->isop_tuba_cached == 0) || 13956483Ssklower (delta == 1 && isop->isop_tuba_cached != 0)) 14056483Ssklower return; 14156483Ssklower isop->isop_tuba_cached = (delta == 1); 14256681Ssklower if ((index = tuba_lookup(&isop->isop_sfaddr.siso_addr, M_DONTWAIT)) != 0 && 14356565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 14456483Ssklower tc->tc_refcnt += delta; 14556681Ssklower if ((index = tuba_lookup(&isop->isop_sladdr.siso_addr, M_DONTWAIT)) != 0 && 14656565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 14756483Ssklower tc->tc_refcnt += delta; 14856483Ssklower } 14956483Ssklower 15056483Ssklower tuba_pcbdetach(isop) 15156483Ssklower struct isopcb *isop; 15256483Ssklower { 15356483Ssklower if (isop == 0) 15456483Ssklower return; 15556483Ssklower tuba_refcnt(isop, -1); 15656483Ssklower isop->isop_socket = 0; 15756483Ssklower iso_pcbdetach(isop); 15856483Ssklower } 15956483Ssklower 16056483Ssklower /* 16156483Ssklower * Avoid in_pcbconnect in faked out tcp_input() 16256483Ssklower */ 16356483Ssklower tuba_pcbconnect(inp, nam) 16456483Ssklower register struct inpcb *inp; 16556483Ssklower struct mbuf *nam; 16656483Ssklower { 16756565Ssklower register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 16856565Ssklower struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 16956483Ssklower struct tcpcb *tp = intotcpcb(inp); 17056483Ssklower unsigned index = sin->sin_addr.s_addr; 17156483Ssklower struct tuba_cache *tc = tuba_table[index]; 17256565Ssklower struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; 17356483Ssklower int error; 17456483Ssklower 17556483Ssklower inp->inp_faddr.s_addr = index; 17656483Ssklower inp->inp_fport = sin->sin_port; 17756704Ssklower *siso = tc->tc_siso; 17856483Ssklower siso->siso_tlen = sizeof(inp->inp_fport); 17956483Ssklower bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 18056483Ssklower nam->m_len = sizeof(*siso); 18156483Ssklower if ((error = iso_pcbconnect(isop, nam)) == 0) 18256483Ssklower tuba_refcnt(isop, 1); 18356483Ssklower return (error); 18456483Ssklower } 18556483Ssklower 18656483Ssklower /* 18756483Ssklower * CALLED FROM: 18856483Ssklower * clnp's input routine, indirectly through the protosw. 18956483Ssklower * FUNCTION and ARGUMENTS: 19056565Ssklower * Take a packet (m) from clnp, strip off the clnp header 19156565Ssklower * and do tcp input processing. 19256483Ssklower * No return value. 19356483Ssklower */ 19456565Ssklower tuba_tcpinput(m, src, dst, clnp_len, ce_bit) 19556483Ssklower register struct mbuf *m; 19656483Ssklower struct sockaddr_iso *src, *dst; 19756483Ssklower int clnp_len, ce_bit; 19856483Ssklower { 19956681Ssklower unsigned long sum, lindex, findex; 20056483Ssklower register struct tcpiphdr *ti; 20156483Ssklower register struct inpcb *inp; 20256681Ssklower struct mbuf *om; 20356483Ssklower int len, tlen, off; 20456483Ssklower register struct tcpcb *tp = 0; 20556483Ssklower int tiflags; 20656483Ssklower struct socket *so; 20756483Ssklower int todrop, acked, ourfinisacked, needoutput = 0; 20856483Ssklower short ostate; 20956483Ssklower struct in_addr laddr; 21056483Ssklower int dropsocket = 0, iss = 0; 21156483Ssklower 21256681Ssklower if ((m->m_flags & M_PKTHDR) == 0) { 21356681Ssklower om = m_gethdr(M_DONTWAIT, MT_DATA); 21456681Ssklower if (om == 0) 21556681Ssklower goto drop; 21656681Ssklower om->m_next = m; 21756685Ssklower for (len = 0; m; m = m->m_next) 21856685Ssklower len += m->m_len; 21956685Ssklower m = om; 22056685Ssklower m->m_pkthdr.len = len; 22156685Ssklower } 22256681Ssklower om = 0; 22356483Ssklower /* 22456483Ssklower * Do some housekeeping looking up CLNP addresses. 22556483Ssklower * If we are out of space might as well drop the packet now. 22656483Ssklower */ 22756483Ssklower tcpstat.tcps_rcvtotal++; 22856681Ssklower lindex = tuba_lookup(&dst->siso_addr, M_DONTWAIT); 229*56901Ssklower findex = tuba_lookup(&src->siso_addr, M_DONTWAIT); 23056681Ssklower if (lindex == 0 || findex == 0) 23156483Ssklower goto drop; 23256483Ssklower /* 23356483Ssklower * Get CLNP and TCP header together in first mbuf. 23456483Ssklower * CLNP gave us an mbuf chain WITH the clnp header pulled up, 23556483Ssklower * and the length of the clnp header. 23656483Ssklower */ 23756483Ssklower len = clnp_len + sizeof(struct tcphdr); 23856483Ssklower if (m->m_len < len) { 23956483Ssklower if ((m = m_pullup(m, len)) == 0) { 24056483Ssklower tcpstat.tcps_rcvshort++; 24156483Ssklower return; 24256483Ssklower } 24356483Ssklower } 24456483Ssklower /* 24556483Ssklower * Calculate checksum of extended TCP header and data, 24656483Ssklower * by adjusting the checksum for missing parts of the header. 24756483Ssklower */ 24856483Ssklower m->m_data += clnp_len; 24956483Ssklower m->m_len -= clnp_len; 25056483Ssklower tlen = m->m_pkthdr.len -= clnp_len; 25156483Ssklower m->m_data -= sizeof(struct ip); 25256483Ssklower m->m_len += sizeof(struct ip); 25356483Ssklower m->m_pkthdr.len += sizeof(struct ip); 25456483Ssklower /* 25556483Ssklower * The reassembly code assumes it will be overwriting a useless 25656681Ssklower * part of the packet, which is why we need to have it point 25756483Ssklower * into the packet itself. 25856483Ssklower * 25956483Ssklower * Check to see if the data is properly alligned 26056483Ssklower * so that we can save copying the tcp header. 26156483Ssklower * This code knows way too much about the structure of mbufs! 26256483Ssklower */ 26356565Ssklower off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ? 26456565Ssklower (m->m_data - m->m_ext.ext_buf) : (m->m_data - m->m_pktdat))); 26556483Ssklower if (off) { 26656565Ssklower struct mbuf *m0 = m_gethdr(M_DONTWAIT, MT_DATA); 26756483Ssklower if (m0 == 0) { 26856483Ssklower goto drop; 26956483Ssklower } 27056685Ssklower m0->m_data += max_linkhdr; 27156483Ssklower bcopy(mtod(m, caddr_t) + sizeof(struct ip), 27256483Ssklower mtod(m0, caddr_t) + sizeof(struct ip), 27356483Ssklower sizeof(struct tcphdr)); 27456483Ssklower m->m_data += sizeof(struct tcpiphdr); 27556704Ssklower m->m_len -= sizeof(struct tcpiphdr); 27656483Ssklower m0->m_next = m; 27756483Ssklower m0->m_pkthdr = m->m_pkthdr; 27856565Ssklower m0->m_flags = m->m_flags & M_COPYFLAGS; 27956483Ssklower m0->m_len = sizeof(struct tcpiphdr); 28056483Ssklower m = m0; 28156483Ssklower } 28256483Ssklower ti = mtod(m, struct tcpiphdr *); 283*56901Ssklower ti->ti_dst.s_addr = tuba_table[lindex]->tc_sum; 284*56901Ssklower if (dst->siso_nlen & 1) 285*56901Ssklower ti->ti_src.s_addr = tuba_table[findex]->tc_sum; 286*56901Ssklower else 287*56901Ssklower ti->ti_src.s_addr = tuba_table[findex]->tc_ssum; 28856685Ssklower ti->ti_prev = ti->ti_next = 0; 28956685Ssklower ti->ti_x1 = 0; ti->ti_pr = ISOPROTO_TCP; 29056685Ssklower ti->ti_len = htons((u_short)tlen); 29156685Ssklower if (ti->ti_sum = in_cksum(m, m->m_pkthdr.len)) { 29256685Ssklower tcpstat.tcps_rcvbadsum++; 29356685Ssklower goto drop; 29456685Ssklower } 29556483Ssklower ti->ti_src.s_addr = findex; 29656483Ssklower ti->ti_dst.s_addr = lindex; 29756483Ssklower /* 29856483Ssklower * Now include the rest of TCP input 29956483Ssklower */ 30056565Ssklower #define TUBA_INCLUDE 30156690Ssklower #define in_pcbconnect tuba_pcbconnect 30256690Ssklower #define tcb tuba_inpcb 30356690Ssklower #define tcp_last_inpcb tuba_last_inpcb 30456483Ssklower 30556565Ssklower #include <netinet/tcp_input.c> 30656483Ssklower } 30756704Ssklower 30856704Ssklower #define tcp_slowtimo tuba_slowtimo 30956704Ssklower #define tcp_fasttimo tuba_fasttimo 31056704Ssklower #include <netinet/tcp_timer.c> 311