156483Ssklower /* 256484Ssklower * Copyright (c) 1992 Regents of the University of California. 356483Ssklower * All rights reserved. 456483Ssklower * 556483Ssklower * %sccs.include.redist.c% 656483Ssklower * 7*56565Ssklower * @(#)tuba_subr.c 7.4 (Berkeley) 10/15/92 856483Ssklower */ 956483Ssklower 10*56565Ssklower #include <sys/param.h> 11*56565Ssklower #include <sys/proc.h> 12*56565Ssklower #include <sys/systm.h> 13*56565Ssklower #include <sys/malloc.h> 14*56565Ssklower #include <sys/mbuf.h> 15*56565Ssklower #include <sys/socket.h> 16*56565Ssklower #include <sys/socketvar.h> 17*56565Ssklower #include <sys/protosw.h> 18*56565Ssklower #include <sys/errno.h> 1956483Ssklower 20*56565Ssklower #include <net/route.h> 21*56565Ssklower #include <net/if.h> 2256483Ssklower 23*56565Ssklower #include <netinet/in.h> 24*56565Ssklower #include <netinet/in_systm.h> 25*56565Ssklower #include <netinet/ip.h> 26*56565Ssklower #include <netinet/in_pcb.h> 27*56565Ssklower #include <netinet/ip_var.h> 28*56565Ssklower #include <netinet/ip_icmp.h> 29*56565Ssklower #include <netinet/tcp.h> 30*56565Ssklower #include <netinet/tcp_fsm.h> 31*56565Ssklower #include <netinet/tcp_seq.h> 32*56565Ssklower #include <netinet/tcp_timer.h> 33*56565Ssklower #include <netinet/tcp_var.h> 34*56565Ssklower #include <netinet/tcpip.h> 35*56565Ssklower #include <netinet/tcp_debug.h> 3656483Ssklower 37*56565Ssklower #include <netiso/argo_debug.h> 38*56565Ssklower #include <netiso/iso.h> 39*56565Ssklower #include <netiso/clnp.h> 40*56565Ssklower #include <netiso/iso_pcb.h> 41*56565Ssklower #include <netiso/iso_var.h> 42*56565Ssklower #include <netiso/tuba_addr.h> 4356483Ssklower 44*56565Ssklower static struct sockaddr_iso null_siso = { sizeof(null_siso), AF_ISO, }; 45*56565Ssklower extern struct isopcb tuba_isopcb; 46*56565Ssklower extern int tuba_table_size; 47*56565Ssklower extern int tcppcbcachemiss, tcppredack, tcppreddat, tcprexmtthresh; 48*56565Ssklower extern struct inpcb *tcp_last_inpcb; 49*56565Ssklower extern struct tcpiphdr tcp_saveti; 5056483Ssklower /* 5156483Ssklower * Tuba initialization 5256483Ssklower */ 5356483Ssklower tuba_init() 5456483Ssklower { 5556484Ssklower #define TUBAHDRSIZE (3 /*LLC*/ + 9 /*CLNP Fixed*/ + 42 /*Addresses*/ \ 5656484Ssklower + 6 /*CLNP Segment*/ + 20 /*TCP*/) 5756483Ssklower 5856483Ssklower tuba_isopcb.isop_next = tuba_isopcb.isop_prev = &tuba_isopcb; 59*56565Ssklower tuba_isopcb.isop_faddr = &tuba_isopcb.isop_sfaddr; 60*56565Ssklower tuba_isopcb.isop_laddr = &tuba_isopcb.isop_sladdr; 6156483Ssklower if (max_protohdr < TUBAHDRSIZE) 6256483Ssklower max_protohdr = TUBAHDRSIZE; 6356483Ssklower if (max_linkhdr + TUBAHDRSIZE > MHLEN) 6456483Ssklower panic("tuba_init"); 65*56565Ssklower tuba_table_init(); 6656483Ssklower } 6756483Ssklower 6856485Ssklower static void 6956485Ssklower tuba_getaddr(error, sum, siso, index) 7056485Ssklower int *error; 7156485Ssklower u_long *sum; 7256485Ssklower struct sockaddr_iso *siso; 7356485Ssklower u_long index; 7456485Ssklower { 7556485Ssklower register struct tuba_cache *tc; 7656485Ssklower if (index < tuba_table_size && (tc = tuba_table[index])) { 7756485Ssklower if (siso) { 7856485Ssklower *siso = null_siso; 7956485Ssklower siso->siso_addr = tc->tc_addr; 8056485Ssklower } 81*56565Ssklower sum += tc->tc_sum_out; 8256485Ssklower } else 8356485Ssklower *error = 1; 8456485Ssklower } 8556485Ssklower 8656485Ssklower tuba_output(m, tp) 8756485Ssklower register struct mbuf *m; 8856483Ssklower struct tcpcb *tp; 8956483Ssklower { 9056485Ssklower struct isopcb *isop; 9156485Ssklower register struct tcpiphdr *n; 9256485Ssklower u_long sum, i; 9356483Ssklower 94*56565Ssklower if (tp == 0 || (n = tp->t_template) == 0) { 9556485Ssklower isop = &tuba_isopcb; 9656485Ssklower i = sum = 0; 9756485Ssklower n = mtod(m, struct tcpiphdr *); 98*56565Ssklower tuba_getaddr(&i, &sum, tuba_isopcb.isop_faddr, 99*56565Ssklower n->ti_dst.s_addr); 100*56565Ssklower tuba_getaddr(&i, &sum, tuba_isopcb.isop_laddr, 101*56565Ssklower n->ti_src.s_addr); 10256485Ssklower goto adjust; 10356485Ssklower } 10456485Ssklower isop = (struct isopcb *)tp->t_tuba_pcb; 105*56565Ssklower if (n->ti_sum == 0) { 10656485Ssklower i = sum = 0; 10756485Ssklower tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, 10856485Ssklower n->ti_dst.s_addr); 10956485Ssklower tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, 11056485Ssklower n->ti_src.s_addr); 11156485Ssklower ICKSUM(sum, sum); 11256485Ssklower n->ti_sum = sum; 11356485Ssklower n = mtod(m, struct tcpiphdr *); 11456485Ssklower adjust: 11556485Ssklower if (i) { 11656485Ssklower m_freem(m); 11756483Ssklower return (ENOBUFS); 11856485Ssklower } 11956485Ssklower ICKSUM(n->ti_sum, sum + n->ti_sum); 12056483Ssklower } 12156483Ssklower m->m_len -= sizeof (struct ip); 12256483Ssklower m->m_pkthdr.len -= sizeof (struct ip); 12356483Ssklower m->m_data += sizeof (struct ip); 12456483Ssklower return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 12556483Ssklower } 12656483Ssklower 12756483Ssklower tuba_refcnt(isop, delta) 12856483Ssklower struct isopcb *isop; 12956483Ssklower { 13056483Ssklower register struct tuba_cache *tc; 13156485Ssklower unsigned index, sum; 13256483Ssklower 13356483Ssklower if (delta != 1) 13456483Ssklower delta = -1; 13556483Ssklower if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 13656483Ssklower (delta == -1 && isop->isop_tuba_cached == 0) || 13756483Ssklower (delta == 1 && isop->isop_tuba_cached != 0)) 13856483Ssklower return; 13956483Ssklower isop->isop_tuba_cached = (delta == 1); 140*56565Ssklower if ((index = tuba_lookup(&isop->isop_sfaddr.siso_addr)) != 0 && 141*56565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 14256483Ssklower tc->tc_refcnt += delta; 143*56565Ssklower if ((index = tuba_lookup(&isop->isop_sladdr.siso_addr)) != 0 && 144*56565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 14556483Ssklower tc->tc_refcnt += delta; 14656483Ssklower } 14756483Ssklower 14856483Ssklower tuba_pcbdetach(isop) 14956483Ssklower struct isopcb *isop; 15056483Ssklower { 15156483Ssklower if (isop == 0) 15256483Ssklower return; 15356483Ssklower tuba_refcnt(isop, -1); 15456483Ssklower isop->isop_socket = 0; 15556483Ssklower iso_pcbdetach(isop); 15656483Ssklower } 15756483Ssklower 15856483Ssklower /* 15956483Ssklower * Avoid in_pcbconnect in faked out tcp_input() 16056483Ssklower */ 16156483Ssklower tuba_pcbconnect(inp, nam) 16256483Ssklower register struct inpcb *inp; 16356483Ssklower struct mbuf *nam; 16456483Ssklower { 165*56565Ssklower register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 166*56565Ssklower struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 16756483Ssklower struct tcpcb *tp = intotcpcb(inp); 16856483Ssklower unsigned index = sin->sin_addr.s_addr; 16956483Ssklower struct tuba_cache *tc = tuba_table[index]; 170*56565Ssklower struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; 17156483Ssklower int error; 17256483Ssklower 17356483Ssklower inp->inp_faddr.s_addr = index; 17456483Ssklower inp->inp_fport = sin->sin_port; 17556483Ssklower *siso = null_siso; 17656483Ssklower siso->siso_addr = tc->tc_addr; 17756483Ssklower siso->siso_tlen = sizeof(inp->inp_fport); 17856483Ssklower bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 17956483Ssklower nam->m_len = sizeof(*siso); 18056483Ssklower if ((error = iso_pcbconnect(isop, nam)) == 0) 18156483Ssklower tuba_refcnt(isop, 1); 18256483Ssklower return (error); 18356483Ssklower } 18456483Ssklower 18556483Ssklower /* 18656483Ssklower * CALLED FROM: 18756483Ssklower * clnp's input routine, indirectly through the protosw. 18856483Ssklower * FUNCTION and ARGUMENTS: 189*56565Ssklower * Take a packet (m) from clnp, strip off the clnp header 190*56565Ssklower * and do tcp input processing. 19156483Ssklower * No return value. 19256483Ssklower */ 193*56565Ssklower tuba_tcpinput(m, src, dst, clnp_len, ce_bit) 19456483Ssklower register struct mbuf *m; 19556483Ssklower struct sockaddr_iso *src, *dst; 19656483Ssklower int clnp_len, ce_bit; 19756483Ssklower { 19856483Ssklower int s = splnet(); 199*56565Ssklower unsigned long fix_cksum, lindex, findex; 20056483Ssklower register struct tcpiphdr *ti; 20156483Ssklower register struct inpcb *inp; 20256483Ssklower struct mbuf *om = 0; 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 21256483Ssklower if ((m->m_flags & M_PKTHDR) == 0) 21356483Ssklower panic("tuba_input"); 21456483Ssklower /* 21556483Ssklower * Do some housekeeping looking up CLNP addresses. 21656483Ssklower * If we are out of space might as well drop the packet now. 21756483Ssklower */ 21856483Ssklower tcpstat.tcps_rcvtotal++; 219*56565Ssklower if ((lindex = tuba_lookup(&dst->siso_addr) == 0) || 22056483Ssklower (findex = tuba_lookup(&dst->siso_addr) == 0)) 22156483Ssklower goto drop; 22256483Ssklower /* 22356483Ssklower * Get CLNP and TCP header together in first mbuf. 22456483Ssklower * CLNP gave us an mbuf chain WITH the clnp header pulled up, 22556483Ssklower * and the length of the clnp header. 22656483Ssklower */ 22756483Ssklower len = clnp_len + sizeof(struct tcphdr); 22856483Ssklower if (m->m_len < len) { 22956483Ssklower if ((m = m_pullup(m, len)) == 0) { 23056483Ssklower tcpstat.tcps_rcvshort++; 23156483Ssklower return; 23256483Ssklower } 23356483Ssklower } 23456483Ssklower /* 23556483Ssklower * Calculate checksum of extended TCP header and data, 23656483Ssklower * by adjusting the checksum for missing parts of the header. 23756483Ssklower */ 23856483Ssklower m->m_data += clnp_len; 23956483Ssklower m->m_len -= clnp_len; 24056483Ssklower tlen = m->m_pkthdr.len -= clnp_len; 24156483Ssklower ICKSUM(fix_cksum, tuba_table[findex]->tc_sum_in + htons((u_short)tlen) 24256483Ssklower + tuba_table[lindex]->tc_sum_in + in_cksum(m, tlen)); 24356483Ssklower if (fix_cksum != 0xffff) { 24456483Ssklower tcpstat.tcps_rcvbadsum++; 24556483Ssklower goto drop; 24656483Ssklower } 24756483Ssklower m->m_data -= sizeof(struct ip); 24856483Ssklower m->m_len += sizeof(struct ip); 24956483Ssklower m->m_pkthdr.len += sizeof(struct ip); 25056483Ssklower /* 25156483Ssklower * The reassembly code assumes it will be overwriting a useless 25256483Ssklower * part of the packet, which is why we need to have ti 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 */ 259*56565Ssklower off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ? 260*56565Ssklower (m->m_data - m->m_ext.ext_buf) : (m->m_data - m->m_pktdat))); 26156483Ssklower if (off) { 262*56565Ssklower struct mbuf *m0 = m_gethdr(M_DONTWAIT, MT_DATA); 26356483Ssklower if (m0 == 0) { 26456483Ssklower goto drop; 26556483Ssklower } 26656483Ssklower bcopy(mtod(m, caddr_t) + sizeof(struct ip), 26756483Ssklower mtod(m0, caddr_t) + sizeof(struct ip), 26856483Ssklower sizeof(struct tcphdr)); 26956483Ssklower m->m_data += sizeof(struct tcpiphdr); 27056483Ssklower m0->m_next = m; 27156483Ssklower m0->m_pkthdr = m->m_pkthdr; 272*56565Ssklower m0->m_flags = m->m_flags & M_COPYFLAGS; 27356483Ssklower m0->m_len = sizeof(struct tcpiphdr); 27456483Ssklower m = m0; 27556483Ssklower } 27656483Ssklower ti = mtod(m, struct tcpiphdr *); 27756483Ssklower ti->ti_src.s_addr = findex; 27856483Ssklower ti->ti_dst.s_addr = lindex; 27956483Ssklower ti->ti_len = tlen; 28056483Ssklower /* 28156483Ssklower * Now include the rest of TCP input 28256483Ssklower */ 283*56565Ssklower #define TUBA_INCLUDE 28456483Ssklower #define in_pcbconnect tuba_pcbconnect 28556483Ssklower 286*56565Ssklower #include <netinet/tcp_input.c> 28756483Ssklower } 288