diff options
author | 1995-10-18 08:37:01 +0000 | |
---|---|---|
committer | 1995-10-18 08:37:01 +0000 | |
commit | df930be708d50e9715f173caa26ffe1b7599b157 (patch) | |
tree | aa317e49e28cb999c9cf3db7f00c20903fe6010a /sys/netiso/tuba_subr.c | |
download | wireguard-openbsd-df930be708d50e9715f173caa26ffe1b7599b157.tar.xz wireguard-openbsd-df930be708d50e9715f173caa26ffe1b7599b157.zip |
initial import of NetBSD tree
Diffstat (limited to 'sys/netiso/tuba_subr.c')
-rw-r--r-- | sys/netiso/tuba_subr.c | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/sys/netiso/tuba_subr.c b/sys/netiso/tuba_subr.c new file mode 100644 index 00000000000..465af6293db --- /dev/null +++ b/sys/netiso/tuba_subr.c @@ -0,0 +1,352 @@ +/* $NetBSD: tuba_subr.c,v 1.4 1995/06/13 07:58:24 mycroft Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tuba_subr.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/protosw.h> +#include <sys/errno.h> + +#include <net/route.h> +#include <net/if.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/ip_var.h> +#include <netinet/ip_icmp.h> +#include <netinet/tcp.h> +#include <netinet/tcp_fsm.h> +#include <netinet/tcp_seq.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include <netinet/tcpip.h> +#include <netinet/tcp_debug.h> + +#include <netiso/argo_debug.h> +#include <netiso/iso.h> +#include <netiso/clnp.h> +#include <netiso/iso_pcb.h> +#include <netiso/iso_var.h> +#include <netiso/tuba_table.h> + +static struct sockaddr_iso null_siso = { sizeof(null_siso), AF_ISO, }; +extern int tuba_table_size, tcp_keepidle, tcp_keepintvl, tcp_maxidle; +extern int tcppcbcachemiss, tcppredack, tcppreddat, tcprexmtthresh; +extern struct tcpiphdr tcp_saveti; +struct inpcbtable tuba_inpcb; +struct inpcb *tuba_last_inpcb = 0; +struct isopcb tuba_isopcb; +/* + * Tuba initialization + */ +void +tuba_init() +{ +#define TUBAHDRSIZE (3 /*LLC*/ + 9 /*CLNP Fixed*/ + 42 /*Addresses*/ \ + + 6 /*CLNP Segment*/ + 20 /*TCP*/) + + in_pcbinit(&tuba_inpcb); + tuba_isopcb.isop_next = tuba_isopcb.isop_prev = &tuba_isopcb; + tuba_isopcb.isop_faddr = &tuba_isopcb.isop_sfaddr; + tuba_isopcb.isop_laddr = &tuba_isopcb.isop_sladdr; + if (max_protohdr < TUBAHDRSIZE) + max_protohdr = TUBAHDRSIZE; + if (max_linkhdr + TUBAHDRSIZE > MHLEN) + panic("tuba_init"); +} + +struct addr_arg { + int error; + int offset; + u_long sum; +}; + +/* + * Calculate contribution to fudge factor for TCP checksum, + * and coincidentally set pointer for convenience of clnp_output + * if we are are responding when there is no isopcb around. + */ +static void +tuba_getaddr(arg, siso, index) + register struct addr_arg *arg; + struct sockaddr_iso **siso; + u_long index; +{ + register struct tuba_cache *tc; + if (index <= tuba_table_size && (tc = tuba_table[index])) { + if (siso) + *siso = &tc->tc_siso; + arg->sum += (arg->offset & 1 ? tc->tc_ssum : tc->tc_sum) + + (0xffff ^ index); + arg->offset += tc->tc_siso.siso_nlen + 1; + } else + arg->error = 1; +} + +tuba_output(m, tp) + register struct mbuf *m; + struct tcpcb *tp; +{ + register struct tcpiphdr *n; + struct isopcb *isop; + struct addr_arg arg; + + if (tp == 0 || (n = tp->t_template) == 0 || + (isop = (struct isopcb *)tp->t_tuba_pcb) == 0) { + isop = &tuba_isopcb; + n = mtod(m, struct tcpiphdr *); + arg.error = arg.sum = arg.offset = 0; + tuba_getaddr(&arg, &tuba_isopcb.isop_faddr, n->ti_dst.s_addr); + tuba_getaddr(&arg, &tuba_isopcb.isop_laddr, n->ti_src.s_addr); + REDUCE(arg.sum, arg.sum); + goto adjust; + } + if (n->ti_sum == 0) { + arg.error = arg.sum = arg.offset = 0; + tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_dst.s_addr); + tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_src.s_addr); + REDUCE(arg.sum, arg.sum); + n->ti_sum = arg.sum; + n = mtod(m, struct tcpiphdr *); + adjust: + if (arg.error) { + m_freem(m); + return (EADDRNOTAVAIL); + } + REDUCE(n->ti_sum, n->ti_sum + (0xffff ^ arg.sum)); + } + m->m_len -= sizeof (struct ip); + m->m_pkthdr.len -= sizeof (struct ip); + m->m_data += sizeof (struct ip); + return (clnp_output(m, isop, m->m_pkthdr.len, 0)); +} + +tuba_refcnt(isop, delta) + struct isopcb *isop; +{ + register struct tuba_cache *tc; + unsigned index, sum; + + if (delta != 1) + delta = -1; + if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || + (delta == -1 && isop->isop_tuba_cached == 0) || + (delta == 1 && isop->isop_tuba_cached != 0)) + return; + isop->isop_tuba_cached = (delta == 1); + if ((index = tuba_lookup(isop->isop_faddr, M_DONTWAIT)) != 0 && + (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) + tc->tc_refcnt += delta; + if ((index = tuba_lookup(isop->isop_laddr, M_DONTWAIT)) != 0 && + (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) + tc->tc_refcnt += delta; +} + +tuba_pcbdetach(isop) + struct isopcb *isop; +{ + if (isop == 0) + return; + tuba_refcnt(isop, -1); + isop->isop_socket = 0; + iso_pcbdetach(isop); +} + +/* + * Avoid in_pcbconnect in faked out tcp_input() + */ +tuba_pcbconnect(inp, nam) + register struct inpcb *inp; + struct mbuf *nam; +{ + register struct sockaddr_iso *siso; + struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); + struct tcpcb *tp = intotcpcb(inp); + struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; + int error; + + /* hardwire iso_pcbbind() here */ + siso = isop->isop_laddr = &isop->isop_sladdr; + *siso = tuba_table[inp->inp_laddr.s_addr]->tc_siso; + siso->siso_tlen = sizeof(inp->inp_lport); + bcopy((caddr_t)&inp->inp_lport, TSEL(siso), sizeof(inp->inp_lport)); + + /* hardwire in_pcbconnect() here without assigning route */ + inp->inp_fport = sin->sin_port; + inp->inp_faddr = sin->sin_addr; + + /* reuse nam argument to call iso_pcbconnect() */ + nam->m_len = sizeof(*siso); + siso = mtod(nam, struct sockaddr_iso *); + *siso = tuba_table[inp->inp_faddr.s_addr]->tc_siso; + siso->siso_tlen = sizeof(inp->inp_fport); + bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); + + if ((error = iso_pcbconnect(isop, nam)) == 0) + tuba_refcnt(isop, 1); + return (error); +} + +/* + * CALLED FROM: + * clnp's input routine, indirectly through the protosw. + * FUNCTION and ARGUMENTS: + * Take a packet (m) from clnp, strip off the clnp header + * and do tcp input processing. + * No return value. + */ +tuba_tcpinput(m, src, dst) + register struct mbuf *m; + struct sockaddr_iso *src, *dst; +{ + unsigned long sum, lindex, findex; + register struct tcpiphdr *ti; + register struct inpcb *inp; + caddr_t optp = NULL; + int optlen; + int len, tlen, off; + register struct tcpcb *tp = 0; + int tiflags; + struct socket *so; + int todrop, acked, ourfinisacked, needoutput = 0; + short ostate; + struct in_addr laddr; + int dropsocket = 0, iss = 0; + u_long tiwin; + u_int32_t ts_val, ts_ecr; + int ts_present = 0; + + if ((m->m_flags & M_PKTHDR) == 0) + panic("tuba_tcpinput"); + /* + * Do some housekeeping looking up CLNP addresses. + * If we are out of space might as well drop the packet now. + */ + tcpstat.tcps_rcvtotal++; + lindex = tuba_lookup(dst, M_DONTWAIT); + findex = tuba_lookup(src, M_DONTWAIT); + if (lindex == 0 || findex == 0) + goto drop; + /* + * CLNP gave us an mbuf chain WITH the clnp header pulled up, + * but the data pointer pushed past it. + */ + len = m->m_len; + tlen = m->m_pkthdr.len; + m->m_data -= sizeof(struct ip); + m->m_len += sizeof(struct ip); + m->m_pkthdr.len += sizeof(struct ip); + m->m_flags &= ~(M_MCAST|M_BCAST); /* XXX should do this in clnp_input */ + /* + * The reassembly code assumes it will be overwriting a useless + * part of the packet, which is why we need to have it point + * into the packet itself. + * + * Check to see if the data is properly alligned + * so that we can save copying the tcp header. + * This code knows way too much about the structure of mbufs! + */ + off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ? + (m->m_data - m->m_ext.ext_buf) : (m->m_data - m->m_pktdat))); + if (off || len < sizeof(struct tcphdr)) { + struct mbuf *m0 = m; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m = m0; + goto drop; + } + m->m_next = m0; + m->m_data += max_linkhdr; + m->m_pkthdr = m0->m_pkthdr; + m->m_flags = m0->m_flags & M_COPYFLAGS; + if (len < sizeof(struct tcphdr)) { + m->m_len = 0; + if ((m = m_pullup(m, sizeof(struct tcpiphdr))) == 0) { + tcpstat.tcps_rcvshort++; + return; + } + } else { + bcopy(mtod(m0, caddr_t) + sizeof(struct ip), + mtod(m, caddr_t) + sizeof(struct ip), + sizeof(struct tcphdr)); + m0->m_len -= sizeof(struct tcpiphdr); + m0->m_data += sizeof(struct tcpiphdr); + m->m_len = sizeof(struct tcpiphdr); + } + } + /* + * Calculate checksum of extended TCP header and data, + * replacing what would have been IP addresses by + * the IP checksum of the CLNP addresses. + */ + ti = mtod(m, struct tcpiphdr *); + ti->ti_dst.s_addr = tuba_table[lindex]->tc_sum; + if (dst->siso_nlen & 1) + ti->ti_src.s_addr = tuba_table[findex]->tc_sum; + else + ti->ti_src.s_addr = tuba_table[findex]->tc_ssum; + ti->ti_prev = ti->ti_next = 0; + ti->ti_x1 = 0; ti->ti_pr = ISOPROTO_TCP; + ti->ti_len = htons((u_short)tlen); + if (ti->ti_sum = in_cksum(m, m->m_pkthdr.len)) { + tcpstat.tcps_rcvbadsum++; + goto drop; + } + ti->ti_src.s_addr = findex; + ti->ti_dst.s_addr = lindex; + /* + * Now include the rest of TCP input + */ +#define TUBA_INCLUDE +#define in_pcbconnect tuba_pcbconnect +#define tcb tuba_inpcb +#define tcp_last_inpcb tuba_last_inpcb + +#include <netinet/tcp_input.c> +} + +#define tcp_slowtimo tuba_slowtimo +#define tcp_fasttimo tuba_fasttimo + +#include <netinet/tcp_timer.c> |