156483Ssklower /* 256484Ssklower * Copyright (c) 1992 Regents of the University of California. 356483Ssklower * All rights reserved. 456483Ssklower * 556483Ssklower * %sccs.include.redist.c% 656483Ssklower * 7*56485Ssklower * @(#)tuba_subr.c 7.3 (Berkeley) 10/09/92 856483Ssklower */ 956483Ssklower 1056483Ssklower #include "param.h" 1156483Ssklower #include "proc.h" 1256483Ssklower #include "systm.h" 1356483Ssklower #include "malloc.h" 1456483Ssklower #include "mbuf.h" 1556483Ssklower #include "socket.h" 1656483Ssklower #include "socketvar.h" 1756483Ssklower #include "protosw.h" 1856483Ssklower #include "errno.h" 1956483Ssklower 2056483Ssklower #include "../net/route.h" 2156483Ssklower #include "../net/if.h" 2256483Ssklower 2356483Ssklower #include "in.h" 2456483Ssklower #include "in_systm.h" 2556483Ssklower #include "ip.h" 2656483Ssklower #include "in_pcb.h" 2756483Ssklower #include "ip_var.h" 2856483Ssklower #include "ip_icmp.h" 2956483Ssklower #include "tcp.h" 3056483Ssklower #include "tcp_fsm.h" 3156483Ssklower #include "tcp_seq.h" 3256483Ssklower #include "tcp_timer.h" 3356483Ssklower #include "tcp_var.h" 3456483Ssklower #include "tcpip.h" 3556483Ssklower 3656483Ssklower #include "netiso/argo_debug.h" 3756483Ssklower #include "netiso/iso.h" 3856483Ssklower #include "netiso/clnp.h" 3956483Ssklower #include "netiso/iso_pcb.h" 4056483Ssklower #include "netiso/iso_var.h" 4156483Ssklower 4256483Ssklower #include "tuba_addr.h" 43*56485Ssklower static struct sockaddr_iso null_siso = { sizeof(null_siso), AF_ISO, }; 4456483Ssklower /* 4556483Ssklower * Tuba initialization 4656483Ssklower */ 4756483Ssklower tuba_init() 4856483Ssklower { 4956484Ssklower #define TUBAHDRSIZE (3 /*LLC*/ + 9 /*CLNP Fixed*/ + 42 /*Addresses*/ \ 5056484Ssklower + 6 /*CLNP Segment*/ + 20 /*TCP*/) 5156483Ssklower extern struct isopcb tuba_isopcb; 5256483Ssklower 5356483Ssklower tuba_isopcb.isop_next = tuba_isopcb.isop_prev = &tuba_isopcb; 54*56485Ssklower tuba_isopcb.isop_faddr = &tuba_isop.isop_sfaddr; 55*56485Ssklower tuba_isopcb.isop_laddr = &tuba_isop.isop_sladdr; 5656483Ssklower if (max_protohdr < TUBAHDRSIZE) 5756483Ssklower max_protohdr = TUBAHDRSIZE; 5856483Ssklower if (max_linkhdr + TUBAHDRSIZE > MHLEN) 5956483Ssklower panic("tuba_init"); 6056484Ssklower tuba_timer_init(); 6156483Ssklower } 6256483Ssklower 63*56485Ssklower static void 64*56485Ssklower tuba_getaddr(error, sum, siso, index) 65*56485Ssklower int *error; 66*56485Ssklower u_long *sum; 67*56485Ssklower struct sockaddr_iso *siso; 68*56485Ssklower u_long index; 69*56485Ssklower { 70*56485Ssklower register struct tuba_cache *tc; 71*56485Ssklower if (index < tuba_table_size && (tc = tuba_table[index])) { 72*56485Ssklower if (siso) { 73*56485Ssklower *siso = null_siso; 74*56485Ssklower siso->siso_addr = tc->tc_addr; 75*56485Ssklower } 76*56485Ssklower sum += tc->tc_sum_out 77*56485Ssklower } else 78*56485Ssklower *error = 1; 79*56485Ssklower } 80*56485Ssklower 81*56485Ssklower tuba_output(m, tp) 82*56485Ssklower register struct mbuf *m; 8356483Ssklower struct tcpcb *tp; 8456483Ssklower { 85*56485Ssklower struct isopcb *isop; 86*56485Ssklower register struct tcpiphdr *n; 87*56485Ssklower u_long sum, i; 8856483Ssklower 89*56485Ssklower if (tp == 0 || (n = tp->tp_template) == 0) { 90*56485Ssklower isop = &tuba_isopcb; 91*56485Ssklower i = sum = 0; 92*56485Ssklower n = mtod(m, struct tcpiphdr *); 93*56485Ssklower tuba_getaddr(&i, &sum, tuba_isop.isop_faddr, n->ti_dst.s_addr); 94*56485Ssklower tuba_getaddr(&i, &sum, tuba_isop.isop_laddr, n->ti_src.s_addr); 95*56485Ssklower goto adjust; 96*56485Ssklower } 97*56485Ssklower isop = (struct isopcb *)tp->t_tuba_pcb; 9856483Ssklower if (n->ni_sum == 0) { 99*56485Ssklower i = sum = 0; 100*56485Ssklower tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, 101*56485Ssklower n->ti_dst.s_addr); 102*56485Ssklower tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, 103*56485Ssklower n->ti_src.s_addr); 104*56485Ssklower ICKSUM(sum, sum); 105*56485Ssklower n->ti_sum = sum; 106*56485Ssklower n = mtod(m, struct tcpiphdr *); 107*56485Ssklower adjust: 108*56485Ssklower if (i) { 109*56485Ssklower m_freem(m); 11056483Ssklower return (ENOBUFS); 111*56485Ssklower } 112*56485Ssklower ICKSUM(n->ti_sum, sum + n->ti_sum); 11356483Ssklower } 11456483Ssklower m->m_len -= sizeof (struct ip); 11556483Ssklower m->m_pkthdr.len -= sizeof (struct ip); 11656483Ssklower m->m_data += sizeof (struct ip); 11756483Ssklower return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 11856483Ssklower } 11956483Ssklower 12056483Ssklower tuba_refcnt(isop, delta) 12156483Ssklower struct isopcb *isop; 12256483Ssklower { 12356483Ssklower register struct tuba_cache *tc; 124*56485Ssklower unsigned index, sum; 12556483Ssklower 12656483Ssklower if (delta != 1) 12756483Ssklower delta = -1; 12856483Ssklower if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 12956483Ssklower (delta == -1 && isop->isop_tuba_cached == 0) || 13056483Ssklower (delta == 1 && isop->isop_tuba_cached != 0)) 13156483Ssklower return; 13256483Ssklower isop->isop_tuba_cached = (delta == 1); 13356483Ssklower if ((index = tuba_lookup(&isop->isop_faddr.siso_addr)) != 0 && 13456483Ssklower (tc = tuba_cache[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 13556483Ssklower tc->tc_refcnt += delta; 13656483Ssklower if ((index = tuba_lookup(&isop->isop_laddr.siso_addr)) != 0 && 13756483Ssklower (tc = tuba_cache[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 13856483Ssklower tc->tc_refcnt += delta; 13956483Ssklower } 14056483Ssklower 14156483Ssklower tuba_pcbdetach(isop) 14256483Ssklower struct isopcb *isop; 14356483Ssklower { 14456483Ssklower if (isop == 0) 14556483Ssklower return; 14656483Ssklower tuba_refcnt(isop, -1); 14756483Ssklower isop->isop_socket = 0; 14856483Ssklower iso_pcbdetach(isop); 14956483Ssklower } 15056483Ssklower 15156483Ssklower /* 15256483Ssklower * Avoid in_pcbconnect in faked out tcp_input() 15356483Ssklower */ 15456483Ssklower tuba_pcbconnect(inp, nam) 15556483Ssklower register struct inpcb *inp; 15656483Ssklower struct mbuf *nam; 15756483Ssklower { 15856483Ssklower register struct sockaddr_iso *siso = mtod(m, struct sockaddr_iso *); 15956483Ssklower struct sockaddr_in *sin = mtod(m, struct sockaddr_in *); 16056483Ssklower struct tcpcb *tp = intotcpcb(inp); 16156483Ssklower unsigned index = sin->sin_addr.s_addr; 16256483Ssklower struct tuba_cache *tc = tuba_table[index]; 16356483Ssklower struct isopcb *isop = (struct isopcb *)tp->tp_tuba_pcb; 16456483Ssklower int error; 16556483Ssklower 16656483Ssklower inp->inp_faddr.s_addr = index; 16756483Ssklower inp->inp_fport = sin->sin_port; 16856483Ssklower *siso = null_siso; 16956483Ssklower siso->siso_addr = tc->tc_addr; 17056483Ssklower siso->siso_tlen = sizeof(inp->inp_fport); 17156483Ssklower bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 17256483Ssklower nam->m_len = sizeof(*siso); 17356483Ssklower if ((error = iso_pcbconnect(isop, nam)) == 0) 17456483Ssklower tuba_refcnt(isop, 1); 17556483Ssklower return (error); 17656483Ssklower } 17756483Ssklower 17856483Ssklower /* 17956483Ssklower * CALLED FROM: 18056483Ssklower * clnp's input routine, indirectly through the protosw. 18156483Ssklower * FUNCTION and ARGUMENTS: 18256483Ssklower * Take a packet (m) from clnp, strip off the clnp header and give it to tcp 18356483Ssklower * or udp. 18456483Ssklower * No return value. 18556483Ssklower */ 18656483Ssklower ProtoHook 18756483Ssklower tpclnp_input(m, src, dst, clnp_len, ce_bit) 18856483Ssklower register struct mbuf *m; 18956483Ssklower struct sockaddr_iso *src, *dst; 19056483Ssklower int clnp_len, ce_bit; 19156483Ssklower { 19256483Ssklower int s = splnet(); 19356483Ssklower unsigned long fix_csum, lindex, findex; 19456483Ssklower register struct tcpiphdr *ti; 19556483Ssklower register struct inpcb *inp; 19656483Ssklower struct mbuf *om = 0; 19756483Ssklower int len, tlen, off; 19856483Ssklower register struct tcpcb *tp = 0; 19956483Ssklower int tiflags; 20056483Ssklower struct socket *so; 20156483Ssklower int todrop, acked, ourfinisacked, needoutput = 0; 20256483Ssklower short ostate; 20356483Ssklower struct in_addr laddr; 20456483Ssklower int dropsocket = 0, iss = 0; 20556483Ssklower 20656483Ssklower if ((m->m_flags & M_PKTHDR) == 0) 20756483Ssklower panic("tuba_input"); 20856483Ssklower /* 20956483Ssklower * Do some housekeeping looking up CLNP addresses. 21056483Ssklower * If we are out of space might as well drop the packet now. 21156483Ssklower */ 21256483Ssklower tcpstat.tcps_rcvtotal++; 21356483Ssklower if ((lindex = tuba_lookup(&dst->siso_addr) == 0 || 21456483Ssklower (findex = tuba_lookup(&dst->siso_addr) == 0)) 21556483Ssklower goto drop; 21656483Ssklower /* 21756483Ssklower * Get CLNP and TCP header together in first mbuf. 21856483Ssklower * CLNP gave us an mbuf chain WITH the clnp header pulled up, 21956483Ssklower * and the length of the clnp header. 22056483Ssklower */ 22156483Ssklower len = clnp_len + sizeof(struct tcphdr); 22256483Ssklower if (m->m_len < len) { 22356483Ssklower if ((m = m_pullup(m, len)) == 0) { 22456483Ssklower tcpstat.tcps_rcvshort++; 22556483Ssklower return; 22656483Ssklower } 22756483Ssklower } 22856483Ssklower /* 22956483Ssklower * Calculate checksum of extended TCP header and data, 23056483Ssklower * by adjusting the checksum for missing parts of the header. 23156483Ssklower */ 23256483Ssklower m->m_data += clnp_len; 23356483Ssklower m->m_len -= clnp_len; 23456483Ssklower tlen = m->m_pkthdr.len -= clnp_len; 23556483Ssklower ICKSUM(fix_cksum, tuba_table[findex]->tc_sum_in + htons((u_short)tlen) 23656483Ssklower + tuba_table[lindex]->tc_sum_in + in_cksum(m, tlen)); 23756483Ssklower if (fix_cksum != 0xffff) { 23856483Ssklower tcpstat.tcps_rcvbadsum++; 23956483Ssklower goto drop; 24056483Ssklower } 24156483Ssklower m->m_data -= sizeof(struct ip); 24256483Ssklower m->m_len += sizeof(struct ip); 24356483Ssklower m->m_pkthdr.len += sizeof(struct ip); 24456483Ssklower /* 24556483Ssklower * The reassembly code assumes it will be overwriting a useless 24656483Ssklower * part of the packet, which is why we need to have ti point 24756483Ssklower * into the packet itself. 24856483Ssklower * 24956483Ssklower * Check to see if the data is properly alligned 25056483Ssklower * so that we can save copying the tcp header. 25156483Ssklower * This code knows way too much about the structure of mbufs! 25256483Ssklower */ 25356483Ssklower off = ((sizeof (long) - 1) & ((m->m_flags & EXT) ? 25456483Ssklower (m->m_data - m->m_ext.ext_buf) : (m->m_data - m_pktdat))); 25556483Ssklower if (off) { 25656483Ssklower struct mbuf *m0 = m_gethdr(M_DONTWAIT, MT_DATA) 25756483Ssklower if (m0 == 0) { 25856483Ssklower goto drop; 25956483Ssklower } 26056483Ssklower bcopy(mtod(m, caddr_t) + sizeof(struct ip), 26156483Ssklower mtod(m0, caddr_t) + sizeof(struct ip), 26256483Ssklower sizeof(struct tcphdr)); 26356483Ssklower m->m_data += sizeof(struct tcpiphdr); 26456483Ssklower m0->m_next = m; 26556483Ssklower m0->m_pkthdr = m->m_pkthdr; 26656483Ssklower m0->m_flags = m->m_pkthdr & M_COPYFLAGS; 26756483Ssklower m0->m_len = sizeof(struct tcpiphdr); 26856483Ssklower m = m0; 26956483Ssklower } 27056483Ssklower ti = mtod(m, struct tcpiphdr *); 27156483Ssklower ti->ti_src.s_addr = findex; 27256483Ssklower ti->ti_dst.s_addr = lindex; 27356483Ssklower ti->ti_len = tlen; 27456483Ssklower /* 27556483Ssklower * Now include the rest of TCP input 27656483Ssklower */ 27756483Ssklower #define TUBA_INPUT 27856483Ssklower #define in_pcbconnect tuba_pcbconnect 27956483Ssklower 28056483Ssklower #include "../netinet/tcp_input.c" 28156483Ssklower } 282