156483Ssklower /* 256484Ssklower * Copyright (c) 1992 Regents of the University of California. 356483Ssklower * All rights reserved. 456483Ssklower * 556483Ssklower * %sccs.include.redist.c% 656483Ssklower * 7*56685Ssklower * @(#)tuba_subr.c 7.6 (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> 4256681Ssklower #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; 7056681Ssklower register u_long *sum; 7156485Ssklower struct sockaddr_iso *siso; 7256485Ssklower u_long index; 7356485Ssklower { 7456485Ssklower register struct tuba_cache *tc; 7556681Ssklower if (index <= tuba_table_size && (tc = tuba_table[index])) { 7656485Ssklower if (siso) { 7756485Ssklower *siso = null_siso; 7856485Ssklower siso->siso_addr = tc->tc_addr; 7956485Ssklower } 8056681Ssklower REDUCE(*sum, *sum + tc->tc_sum_out); 8156485Ssklower } else 8256485Ssklower *error = 1; 8356485Ssklower } 84*56685Ssklower int tuba_noisy = 1; 8556485Ssklower 8656485Ssklower tuba_output(m, tp) 8756485Ssklower register struct mbuf *m; 8856483Ssklower struct tcpcb *tp; 8956483Ssklower { 9056485Ssklower struct isopcb *isop; 91*56685Ssklower register struct tcpiphdr *n, *h; 92*56685Ssklower struct mbuf *p = m_gethdr(M_DONTWAIT, MT_DATA); 93*56685Ssklower u_long sum = 0, i = 0, k1, k2, k3, k4, k5, lindex, findex, len; 9456483Ssklower 95*56685Ssklower if ((m->m_flags & M_PKTHDR) == 0) 96*56685Ssklower panic("tuba_output"); 97*56685Ssklower if (p == 0) 98*56685Ssklower panic("tuba_output 2"); 99*56685Ssklower m = m_pullup(m, 40); 100*56685Ssklower if (m == 0) { 101*56685Ssklower printf("heisenberg hit us\n"); 102*56685Ssklower (void)m_free(p); 103*56685Ssklower return (ENOBUFS); 104*56685Ssklower } 105*56685Ssklower n = mtod(m, struct tcpiphdr *); 106*56685Ssklower h = mtod(p, struct tcpiphdr *); 107*56685Ssklower lindex = n->ti_src.s_addr; 108*56685Ssklower findex = n->ti_dst.s_addr; 109*56685Ssklower len = m->m_pkthdr.len; 110*56685Ssklower bzero((caddr_t)h, sizeof(*h)); 111*56685Ssklower h->ti_pr = ISOPROTO_TCP; 112*56685Ssklower h->ti_dst.s_addr = findex; 113*56685Ssklower h->ti_src.s_addr = lindex; 114*56685Ssklower h->ti_len = htons((u_short)len - 20); 115*56685Ssklower m->m_data += 20; 116*56685Ssklower m->m_len -= 20; 117*56685Ssklower k1 = in_cksum(m, len - 20); 118*56685Ssklower p->m_len = 20; 119*56685Ssklower p->m_next = m; 120*56685Ssklower k2 = in_cksum(p, 20); 121*56685Ssklower k3 = in_cksum(p, len); 122*56685Ssklower m->m_data -= 20; 123*56685Ssklower m->m_len += 20; 124*56685Ssklower 125*56685Ssklower if (tuba_noisy) { 126*56685Ssklower printf("old ti_sum is 0x%x\n", n->ti_sum); 127*56685Ssklower printf("in_cksum for old TCP part is 0x%x\n", k1); 128*56685Ssklower printf("in_cksum for ph(idx) is 0x%x\n", k2); 129*56685Ssklower printf("in_cksum for ph + TCP is 0x%x\n", k3); 130*56685Ssklower } 13156681Ssklower if (tp == 0 || (n = tp->t_template) == 0 || 13256681Ssklower (isop = (struct isopcb *)tp->t_tuba_pcb) == 0) { 13356485Ssklower isop = &tuba_isopcb; 13456681Ssklower n = mtod(m, struct tcpiphdr *); 135*56685Ssklower tuba_getaddr(&i, &sum, tuba_isopcb.isop_faddr, findex); 136*56685Ssklower tuba_getaddr(&i, &sum, tuba_isopcb.isop_laddr, lindex); 13756485Ssklower goto adjust; 13856485Ssklower } 13956565Ssklower if (n->ti_sum == 0) { 140*56685Ssklower tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, findex); 141*56685Ssklower tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, lindex); 14256485Ssklower n->ti_sum = sum; 14356485Ssklower n = mtod(m, struct tcpiphdr *); 14456485Ssklower adjust: 14556485Ssklower if (i) { 14656485Ssklower m_freem(m); 147*56685Ssklower (void)m_free(p); 14856681Ssklower return (EADDRNOTAVAIL); 14956485Ssklower } 15056681Ssklower REDUCE(n->ti_sum, n->ti_sum + (0xffff ^ sum)); 15156483Ssklower } 152*56685Ssklower h->ti_dst.s_addr = tuba_table[findex]->tc_sum_in; 153*56685Ssklower h->ti_src.s_addr = tuba_table[lindex]->tc_sum_in; 15456483Ssklower m->m_len -= sizeof (struct ip); 15556483Ssklower m->m_pkthdr.len -= sizeof (struct ip); 15656483Ssklower m->m_data += sizeof (struct ip); 157*56685Ssklower k1 = in_cksum(m, len - 20); 158*56685Ssklower k2 = in_cksum(p, 20); 159*56685Ssklower k3 = in_cksum(p, len); 160*56685Ssklower REDUCE(k4, h->ti_dst.s_addr + h->ti_src.s_addr + h->ti_len 161*56685Ssklower + ntohs((u_short)ISOPROTO_TCP) + (0xffff ^ k1)); 162*56685Ssklower k4 = 0xffff ^ k4; 163*56685Ssklower if (tuba_noisy) { 164*56685Ssklower printf("new ti_sum is 0x%x\n", n->ti_sum); 165*56685Ssklower printf("adjustment is 0x%x\n", sum); 166*56685Ssklower printf("in_cksum for new TCP part is 0x%x\n", k1); 167*56685Ssklower printf("in_cksum for ph(EIDSUM) is 0x%x\n", k2); 168*56685Ssklower printf("in_cksum for ph + TCP is 0x%x\n", k3); 169*56685Ssklower printf("calculated in the funky way is 0x%x\n", k4); 170*56685Ssklower } 171*56685Ssklower (void)m_free(p); 17256483Ssklower return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 17356483Ssklower } 17456483Ssklower 17556483Ssklower tuba_refcnt(isop, delta) 17656483Ssklower struct isopcb *isop; 17756483Ssklower { 17856483Ssklower register struct tuba_cache *tc; 17956485Ssklower unsigned index, sum; 18056483Ssklower 18156483Ssklower if (delta != 1) 18256483Ssklower delta = -1; 18356483Ssklower if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 18456483Ssklower (delta == -1 && isop->isop_tuba_cached == 0) || 18556483Ssklower (delta == 1 && isop->isop_tuba_cached != 0)) 18656483Ssklower return; 18756483Ssklower isop->isop_tuba_cached = (delta == 1); 18856681Ssklower if ((index = tuba_lookup(&isop->isop_sfaddr.siso_addr, M_DONTWAIT)) != 0 && 18956565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 19056483Ssklower tc->tc_refcnt += delta; 19156681Ssklower if ((index = tuba_lookup(&isop->isop_sladdr.siso_addr, M_DONTWAIT)) != 0 && 19256565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 19356483Ssklower tc->tc_refcnt += delta; 19456483Ssklower } 19556483Ssklower 19656483Ssklower tuba_pcbdetach(isop) 19756483Ssklower struct isopcb *isop; 19856483Ssklower { 19956483Ssklower if (isop == 0) 20056483Ssklower return; 20156483Ssklower tuba_refcnt(isop, -1); 20256483Ssklower isop->isop_socket = 0; 20356483Ssklower iso_pcbdetach(isop); 20456483Ssklower } 20556483Ssklower 20656483Ssklower /* 20756483Ssklower * Avoid in_pcbconnect in faked out tcp_input() 20856483Ssklower */ 20956483Ssklower tuba_pcbconnect(inp, nam) 21056483Ssklower register struct inpcb *inp; 21156483Ssklower struct mbuf *nam; 21256483Ssklower { 21356565Ssklower register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 21456565Ssklower struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 21556483Ssklower struct tcpcb *tp = intotcpcb(inp); 21656483Ssklower unsigned index = sin->sin_addr.s_addr; 21756483Ssklower struct tuba_cache *tc = tuba_table[index]; 21856565Ssklower struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; 21956483Ssklower int error; 22056483Ssklower 22156483Ssklower inp->inp_faddr.s_addr = index; 22256483Ssklower inp->inp_fport = sin->sin_port; 22356483Ssklower *siso = null_siso; 22456483Ssklower siso->siso_addr = tc->tc_addr; 22556483Ssklower siso->siso_tlen = sizeof(inp->inp_fport); 22656483Ssklower bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 22756483Ssklower nam->m_len = sizeof(*siso); 22856483Ssklower if ((error = iso_pcbconnect(isop, nam)) == 0) 22956483Ssklower tuba_refcnt(isop, 1); 23056483Ssklower return (error); 23156483Ssklower } 23256483Ssklower 23356681Ssklower tuba_badcksum() {} /* XXX - to set breakpoints */ 23456681Ssklower 23556483Ssklower /* 23656483Ssklower * CALLED FROM: 23756483Ssklower * clnp's input routine, indirectly through the protosw. 23856483Ssklower * FUNCTION and ARGUMENTS: 23956565Ssklower * Take a packet (m) from clnp, strip off the clnp header 24056565Ssklower * and do tcp input processing. 24156483Ssklower * No return value. 24256483Ssklower */ 24356565Ssklower tuba_tcpinput(m, src, dst, clnp_len, ce_bit) 24456483Ssklower register struct mbuf *m; 24556483Ssklower struct sockaddr_iso *src, *dst; 24656483Ssklower int clnp_len, ce_bit; 24756483Ssklower { 24856483Ssklower int s = splnet(); 24956681Ssklower unsigned long sum, lindex, findex; 25056483Ssklower register struct tcpiphdr *ti; 25156483Ssklower register struct inpcb *inp; 25256681Ssklower struct mbuf *om; 25356483Ssklower int len, tlen, off; 25456483Ssklower register struct tcpcb *tp = 0; 25556483Ssklower int tiflags; 25656483Ssklower struct socket *so; 25756483Ssklower int todrop, acked, ourfinisacked, needoutput = 0; 25856483Ssklower short ostate; 25956483Ssklower struct in_addr laddr; 26056483Ssklower int dropsocket = 0, iss = 0; 26156483Ssklower 26256681Ssklower if ((m->m_flags & M_PKTHDR) == 0) { 26356681Ssklower om = m_gethdr(M_DONTWAIT, MT_DATA); 26456681Ssklower if (om == 0) 26556681Ssklower goto drop; 26656681Ssklower om->m_next = m; 267*56685Ssklower for (len = 0; m; m = m->m_next) 268*56685Ssklower len += m->m_len; 269*56685Ssklower m = om; 270*56685Ssklower m->m_pkthdr.len = len; 271*56685Ssklower } 27256681Ssklower om = 0; 27356483Ssklower /* 27456483Ssklower * Do some housekeeping looking up CLNP addresses. 27556483Ssklower * If we are out of space might as well drop the packet now. 27656483Ssklower */ 27756483Ssklower tcpstat.tcps_rcvtotal++; 27856681Ssklower lindex = tuba_lookup(&dst->siso_addr, M_DONTWAIT); 27956681Ssklower findex = tuba_lookup(&dst->siso_addr, M_DONTWAIT); 28056681Ssklower if (lindex == 0 || findex == 0) 28156483Ssklower goto drop; 28256483Ssklower /* 28356483Ssklower * Get CLNP and TCP header together in first mbuf. 28456483Ssklower * CLNP gave us an mbuf chain WITH the clnp header pulled up, 28556483Ssklower * and the length of the clnp header. 28656483Ssklower */ 28756483Ssklower len = clnp_len + sizeof(struct tcphdr); 28856483Ssklower if (m->m_len < len) { 28956483Ssklower if ((m = m_pullup(m, len)) == 0) { 29056483Ssklower tcpstat.tcps_rcvshort++; 29156483Ssklower return; 29256483Ssklower } 29356483Ssklower } 29456483Ssklower /* 29556483Ssklower * Calculate checksum of extended TCP header and data, 29656483Ssklower * by adjusting the checksum for missing parts of the header. 29756483Ssklower */ 29856483Ssklower m->m_data += clnp_len; 29956483Ssklower m->m_len -= clnp_len; 30056483Ssklower tlen = m->m_pkthdr.len -= clnp_len; 30156483Ssklower m->m_data -= sizeof(struct ip); 30256483Ssklower m->m_len += sizeof(struct ip); 30356483Ssklower m->m_pkthdr.len += sizeof(struct ip); 30456483Ssklower /* 30556483Ssklower * The reassembly code assumes it will be overwriting a useless 30656681Ssklower * part of the packet, which is why we need to have it point 30756483Ssklower * into the packet itself. 30856483Ssklower * 30956483Ssklower * Check to see if the data is properly alligned 31056483Ssklower * so that we can save copying the tcp header. 31156483Ssklower * This code knows way too much about the structure of mbufs! 31256483Ssklower */ 31356565Ssklower off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ? 31456565Ssklower (m->m_data - m->m_ext.ext_buf) : (m->m_data - m->m_pktdat))); 31556483Ssklower if (off) { 31656565Ssklower struct mbuf *m0 = m_gethdr(M_DONTWAIT, MT_DATA); 31756483Ssklower if (m0 == 0) { 31856483Ssklower goto drop; 31956483Ssklower } 320*56685Ssklower m0->m_data += max_linkhdr; 32156483Ssklower bcopy(mtod(m, caddr_t) + sizeof(struct ip), 32256483Ssklower mtod(m0, caddr_t) + sizeof(struct ip), 32356483Ssklower sizeof(struct tcphdr)); 32456483Ssklower m->m_data += sizeof(struct tcpiphdr); 32556483Ssklower m0->m_next = m; 32656483Ssklower m0->m_pkthdr = m->m_pkthdr; 32756565Ssklower m0->m_flags = m->m_flags & M_COPYFLAGS; 32856483Ssklower m0->m_len = sizeof(struct tcpiphdr); 32956483Ssklower m = m0; 33056483Ssklower } 33156483Ssklower ti = mtod(m, struct tcpiphdr *); 332*56685Ssklower ti->ti_src.s_addr = tuba_table[findex]->tc_sum_in; 333*56685Ssklower ti->ti_dst.s_addr = tuba_table[lindex]->tc_sum_in; 334*56685Ssklower ti->ti_prev = ti->ti_next = 0; 335*56685Ssklower ti->ti_x1 = 0; ti->ti_pr = ISOPROTO_TCP; 336*56685Ssklower ti->ti_len = htons((u_short)tlen); 337*56685Ssklower if (ti->ti_sum = in_cksum(m, m->m_pkthdr.len)) { 338*56685Ssklower tcpstat.tcps_rcvbadsum++; 339*56685Ssklower tuba_badcksum(); 340*56685Ssklower goto drop; 341*56685Ssklower } 342*56685Ssklower if (tuba_noisy) 343*56685Ssklower printf("Hurray!\n"); 34456483Ssklower ti->ti_src.s_addr = findex; 34556483Ssklower ti->ti_dst.s_addr = lindex; 34656483Ssklower /* 34756483Ssklower * Now include the rest of TCP input 34856483Ssklower */ 34956565Ssklower #define TUBA_INCLUDE 35056483Ssklower #define in_pcbconnect tuba_pcbconnect 35156483Ssklower 35256565Ssklower #include <netinet/tcp_input.c> 35356483Ssklower } 354