156483Ssklower /* 256484Ssklower * Copyright (c) 1992 Regents of the University of California. 356483Ssklower * All rights reserved. 456483Ssklower * 556483Ssklower * %sccs.include.redist.c% 656483Ssklower * 7*56681Ssklower * @(#)tuba_subr.c 7.5 (Berkeley) 11/05/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> 42*56681Ssklower #include <netiso/tuba_table.h> 4356483Ssklower 4456565Ssklower static struct sockaddr_iso null_siso = { sizeof(null_siso), AF_ISO, }; 4556565Ssklower extern struct isopcb tuba_isopcb; 4656565Ssklower extern int tuba_table_size; 4756565Ssklower extern int tcppcbcachemiss, tcppredack, tcppreddat, tcprexmtthresh; 4856565Ssklower extern struct inpcb *tcp_last_inpcb; 4956565Ssklower 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; 5956565Ssklower tuba_isopcb.isop_faddr = &tuba_isopcb.isop_sfaddr; 6056565Ssklower 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"); 6556483Ssklower } 6656483Ssklower 6756485Ssklower static void 6856485Ssklower tuba_getaddr(error, sum, siso, index) 6956485Ssklower int *error; 70*56681Ssklower register u_long *sum; 7156485Ssklower struct sockaddr_iso *siso; 7256485Ssklower u_long index; 7356485Ssklower { 7456485Ssklower register struct tuba_cache *tc; 75*56681Ssklower if (index <= tuba_table_size && (tc = tuba_table[index])) { 7656485Ssklower if (siso) { 7756485Ssklower *siso = null_siso; 7856485Ssklower siso->siso_addr = tc->tc_addr; 7956485Ssklower } 80*56681Ssklower REDUCE(*sum, *sum + tc->tc_sum_out); 8156485Ssklower } else 8256485Ssklower *error = 1; 8356485Ssklower } 8456485Ssklower 8556485Ssklower tuba_output(m, tp) 8656485Ssklower register struct mbuf *m; 8756483Ssklower struct tcpcb *tp; 8856483Ssklower { 8956485Ssklower struct isopcb *isop; 9056485Ssklower register struct tcpiphdr *n; 9156485Ssklower u_long sum, i; 9256483Ssklower 93*56681Ssklower if (tp == 0 || (n = tp->t_template) == 0 || 94*56681Ssklower (isop = (struct isopcb *)tp->t_tuba_pcb) == 0) { 9556485Ssklower isop = &tuba_isopcb; 96*56681Ssklower n = mtod(m, struct tcpiphdr *); 9756485Ssklower i = sum = 0; 9856565Ssklower tuba_getaddr(&i, &sum, tuba_isopcb.isop_faddr, 9956565Ssklower n->ti_dst.s_addr); 10056565Ssklower tuba_getaddr(&i, &sum, tuba_isopcb.isop_laddr, 10156565Ssklower n->ti_src.s_addr); 10256485Ssklower goto adjust; 10356485Ssklower } 10456565Ssklower if (n->ti_sum == 0) { 10556485Ssklower i = sum = 0; 10656485Ssklower tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, 10756485Ssklower n->ti_dst.s_addr); 10856485Ssklower tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, 10956485Ssklower n->ti_src.s_addr); 11056485Ssklower n->ti_sum = sum; 11156485Ssklower n = mtod(m, struct tcpiphdr *); 11256485Ssklower adjust: 11356485Ssklower if (i) { 11456485Ssklower m_freem(m); 115*56681Ssklower return (EADDRNOTAVAIL); 11656485Ssklower } 117*56681Ssklower REDUCE(n->ti_sum, n->ti_sum + (0xffff ^ sum)); 11856483Ssklower } 11956483Ssklower m->m_len -= sizeof (struct ip); 12056483Ssklower m->m_pkthdr.len -= sizeof (struct ip); 12156483Ssklower m->m_data += sizeof (struct ip); 12256483Ssklower return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 12356483Ssklower } 12456483Ssklower 12556483Ssklower tuba_refcnt(isop, delta) 12656483Ssklower struct isopcb *isop; 12756483Ssklower { 12856483Ssklower register struct tuba_cache *tc; 12956485Ssklower unsigned index, sum; 13056483Ssklower 13156483Ssklower if (delta != 1) 13256483Ssklower delta = -1; 13356483Ssklower if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 13456483Ssklower (delta == -1 && isop->isop_tuba_cached == 0) || 13556483Ssklower (delta == 1 && isop->isop_tuba_cached != 0)) 13656483Ssklower return; 13756483Ssklower isop->isop_tuba_cached = (delta == 1); 138*56681Ssklower if ((index = tuba_lookup(&isop->isop_sfaddr.siso_addr, M_DONTWAIT)) != 0 && 13956565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 14056483Ssklower tc->tc_refcnt += delta; 141*56681Ssklower if ((index = tuba_lookup(&isop->isop_sladdr.siso_addr, M_DONTWAIT)) != 0 && 14256565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 14356483Ssklower tc->tc_refcnt += delta; 14456483Ssklower } 14556483Ssklower 14656483Ssklower tuba_pcbdetach(isop) 14756483Ssklower struct isopcb *isop; 14856483Ssklower { 14956483Ssklower if (isop == 0) 15056483Ssklower return; 15156483Ssklower tuba_refcnt(isop, -1); 15256483Ssklower isop->isop_socket = 0; 15356483Ssklower iso_pcbdetach(isop); 15456483Ssklower } 15556483Ssklower 15656483Ssklower /* 15756483Ssklower * Avoid in_pcbconnect in faked out tcp_input() 15856483Ssklower */ 15956483Ssklower tuba_pcbconnect(inp, nam) 16056483Ssklower register struct inpcb *inp; 16156483Ssklower struct mbuf *nam; 16256483Ssklower { 16356565Ssklower register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 16456565Ssklower struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 16556483Ssklower struct tcpcb *tp = intotcpcb(inp); 16656483Ssklower unsigned index = sin->sin_addr.s_addr; 16756483Ssklower struct tuba_cache *tc = tuba_table[index]; 16856565Ssklower struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; 16956483Ssklower int error; 17056483Ssklower 17156483Ssklower inp->inp_faddr.s_addr = index; 17256483Ssklower inp->inp_fport = sin->sin_port; 17356483Ssklower *siso = null_siso; 17456483Ssklower siso->siso_addr = tc->tc_addr; 17556483Ssklower siso->siso_tlen = sizeof(inp->inp_fport); 17656483Ssklower bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 17756483Ssklower nam->m_len = sizeof(*siso); 17856483Ssklower if ((error = iso_pcbconnect(isop, nam)) == 0) 17956483Ssklower tuba_refcnt(isop, 1); 18056483Ssklower return (error); 18156483Ssklower } 18256483Ssklower 183*56681Ssklower tuba_badcksum() {} /* XXX - to set breakpoints */ 184*56681Ssklower 18556483Ssklower /* 18656483Ssklower * CALLED FROM: 18756483Ssklower * clnp's input routine, indirectly through the protosw. 18856483Ssklower * FUNCTION and ARGUMENTS: 18956565Ssklower * Take a packet (m) from clnp, strip off the clnp header 19056565Ssklower * and do tcp input processing. 19156483Ssklower * No return value. 19256483Ssklower */ 19356565Ssklower 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*56681Ssklower unsigned long sum, lindex, findex; 20056483Ssklower register struct tcpiphdr *ti; 20156483Ssklower register struct inpcb *inp; 202*56681Ssklower 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 212*56681Ssklower if ((m->m_flags & M_PKTHDR) == 0) { 213*56681Ssklower om = m_gethdr(M_DONTWAIT, MT_DATA); 214*56681Ssklower if (om == 0) 215*56681Ssklower goto drop; 216*56681Ssklower om->m_next = m; 217*56681Ssklower } else 218*56681Ssklower om = m; 219*56681Ssklower for (len = 0; m; m = m->m_next) 220*56681Ssklower len += m->m_len; 221*56681Ssklower m = om; 222*56681Ssklower om = 0; 223*56681Ssklower m->m_pkthdr.len = len; 22456483Ssklower /* 22556483Ssklower * Do some housekeeping looking up CLNP addresses. 22656483Ssklower * If we are out of space might as well drop the packet now. 22756483Ssklower */ 22856483Ssklower tcpstat.tcps_rcvtotal++; 229*56681Ssklower lindex = tuba_lookup(&dst->siso_addr, M_DONTWAIT); 230*56681Ssklower findex = tuba_lookup(&dst->siso_addr, M_DONTWAIT); 231*56681Ssklower if (lindex == 0 || findex == 0) 23256483Ssklower goto drop; 23356483Ssklower /* 23456483Ssklower * Get CLNP and TCP header together in first mbuf. 23556483Ssklower * CLNP gave us an mbuf chain WITH the clnp header pulled up, 23656483Ssklower * and the length of the clnp header. 23756483Ssklower */ 23856483Ssklower len = clnp_len + sizeof(struct tcphdr); 23956483Ssklower if (m->m_len < len) { 24056483Ssklower if ((m = m_pullup(m, len)) == 0) { 24156483Ssklower tcpstat.tcps_rcvshort++; 24256483Ssklower return; 24356483Ssklower } 24456483Ssklower } 24556483Ssklower /* 24656483Ssklower * Calculate checksum of extended TCP header and data, 24756483Ssklower * by adjusting the checksum for missing parts of the header. 24856483Ssklower */ 24956483Ssklower m->m_data += clnp_len; 25056483Ssklower m->m_len -= clnp_len; 25156483Ssklower tlen = m->m_pkthdr.len -= clnp_len; 252*56681Ssklower REDUCE(sum, tuba_table[findex]->tc_sum_in + htons((u_short)tlen) 253*56681Ssklower + htons((u_short)ISOPROTO_TCP) 25456483Ssklower + tuba_table[lindex]->tc_sum_in + in_cksum(m, tlen)); 255*56681Ssklower if (sum) { 25656483Ssklower tcpstat.tcps_rcvbadsum++; 257*56681Ssklower tuba_badcksum(); 25856483Ssklower goto drop; 25956483Ssklower } 26056483Ssklower m->m_data -= sizeof(struct ip); 26156483Ssklower m->m_len += sizeof(struct ip); 26256483Ssklower m->m_pkthdr.len += sizeof(struct ip); 26356483Ssklower /* 26456483Ssklower * The reassembly code assumes it will be overwriting a useless 265*56681Ssklower * part of the packet, which is why we need to have it point 26656483Ssklower * into the packet itself. 26756483Ssklower * 26856483Ssklower * Check to see if the data is properly alligned 26956483Ssklower * so that we can save copying the tcp header. 27056483Ssklower * This code knows way too much about the structure of mbufs! 27156483Ssklower */ 27256565Ssklower off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ? 27356565Ssklower (m->m_data - m->m_ext.ext_buf) : (m->m_data - m->m_pktdat))); 27456483Ssklower if (off) { 27556565Ssklower struct mbuf *m0 = m_gethdr(M_DONTWAIT, MT_DATA); 27656483Ssklower if (m0 == 0) { 27756483Ssklower goto drop; 27856483Ssklower } 27956483Ssklower bcopy(mtod(m, caddr_t) + sizeof(struct ip), 28056483Ssklower mtod(m0, caddr_t) + sizeof(struct ip), 28156483Ssklower sizeof(struct tcphdr)); 28256483Ssklower m->m_data += sizeof(struct tcpiphdr); 28356483Ssklower m0->m_next = m; 28456483Ssklower m0->m_pkthdr = m->m_pkthdr; 28556565Ssklower m0->m_flags = m->m_flags & M_COPYFLAGS; 28656483Ssklower m0->m_len = sizeof(struct tcpiphdr); 28756483Ssklower m = m0; 28856483Ssklower } 28956483Ssklower ti = mtod(m, struct tcpiphdr *); 29056483Ssklower ti->ti_src.s_addr = findex; 29156483Ssklower ti->ti_dst.s_addr = lindex; 29256483Ssklower /* 29356483Ssklower * Now include the rest of TCP input 29456483Ssklower */ 29556565Ssklower #define TUBA_INCLUDE 29656483Ssklower #define in_pcbconnect tuba_pcbconnect 29756483Ssklower 29856565Ssklower #include <netinet/tcp_input.c> 29956483Ssklower } 300