156483Ssklower /*
2*63222Sbostic * Copyright (c) 1992, 1993
3*63222Sbostic * The Regents of the University of California. All rights reserved.
456483Ssklower *
556483Ssklower * %sccs.include.redist.c%
656483Ssklower *
7*63222Sbostic * @(#)tuba_subr.c 8.1 (Berkeley) 06/10/93
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
4456690Ssklower static struct sockaddr_iso null_siso = { sizeof(null_siso), AF_ISO, };
4556704Ssklower extern int tuba_table_size, tcp_keepidle, tcp_keepintvl, tcp_maxidle;
4656690Ssklower extern int tcppcbcachemiss, tcppredack, tcppreddat, tcprexmtthresh;
4756690Ssklower extern struct tcpiphdr tcp_saveti;
4856690Ssklower struct inpcb tuba_inpcb;
4956704Ssklower struct inpcb *tuba_last_inpcb = &tuba_inpcb;
5056690Ssklower struct isopcb tuba_isopcb;
5156483Ssklower /*
5256483Ssklower * Tuba initialization
5356483Ssklower */
tuba_init()5456483Ssklower tuba_init()
5556483Ssklower {
5656484Ssklower #define TUBAHDRSIZE (3 /*LLC*/ + 9 /*CLNP Fixed*/ + 42 /*Addresses*/ \
5756484Ssklower + 6 /*CLNP Segment*/ + 20 /*TCP*/)
5856483Ssklower
5956690Ssklower tuba_inpcb.inp_next = tuba_inpcb.inp_prev = &tuba_inpcb;
6056483Ssklower tuba_isopcb.isop_next = tuba_isopcb.isop_prev = &tuba_isopcb;
6156565Ssklower tuba_isopcb.isop_faddr = &tuba_isopcb.isop_sfaddr;
6256565Ssklower tuba_isopcb.isop_laddr = &tuba_isopcb.isop_sladdr;
6356483Ssklower if (max_protohdr < TUBAHDRSIZE)
6456483Ssklower max_protohdr = TUBAHDRSIZE;
6556483Ssklower if (max_linkhdr + TUBAHDRSIZE > MHLEN)
6656483Ssklower panic("tuba_init");
6756483Ssklower }
6856483Ssklower
6956901Ssklower struct addr_arg {
7056901Ssklower int error;
7156901Ssklower int offset;
7256901Ssklower u_long sum;
7356901Ssklower };
7456901Ssklower
7556903Ssklower /*
7656903Ssklower * Calculate contribution to fudge factor for TCP checksum,
7756903Ssklower * and coincidentally set pointer for convenience of clnp_output
7856903Ssklower * if we are are responding when there is no isopcb around.
7956903Ssklower */
8056485Ssklower static void
tuba_getaddr(arg,siso,index)8156901Ssklower tuba_getaddr(arg, siso, index)
8256901Ssklower register struct addr_arg *arg;
8356704Ssklower struct sockaddr_iso **siso;
8456485Ssklower u_long index;
8556485Ssklower {
8656485Ssklower register struct tuba_cache *tc;
8756681Ssklower if (index <= tuba_table_size && (tc = tuba_table[index])) {
8856704Ssklower if (siso)
8956704Ssklower *siso = &tc->tc_siso;
9056903Ssklower arg->sum += (arg->offset & 1 ? tc->tc_ssum : tc->tc_sum)
9156903Ssklower + (0xffff ^ index);
9256901Ssklower arg->offset += tc->tc_siso.siso_nlen + 1;
9356485Ssklower } else
9456901Ssklower arg->error = 1;
9556485Ssklower }
9656485Ssklower
tuba_output(m,tp)9756485Ssklower tuba_output(m, tp)
9856485Ssklower register struct mbuf *m;
9956483Ssklower struct tcpcb *tp;
10056483Ssklower {
10156690Ssklower register struct tcpiphdr *n;
10256901Ssklower struct isopcb *isop;
10356901Ssklower struct addr_arg arg;
10456483Ssklower
10556681Ssklower if (tp == 0 || (n = tp->t_template) == 0 ||
10656681Ssklower (isop = (struct isopcb *)tp->t_tuba_pcb) == 0) {
10756485Ssklower isop = &tuba_isopcb;
10856681Ssklower n = mtod(m, struct tcpiphdr *);
10956901Ssklower arg.error = arg.sum = arg.offset = 0;
11056901Ssklower tuba_getaddr(&arg, &tuba_isopcb.isop_faddr, n->ti_dst.s_addr);
11156901Ssklower tuba_getaddr(&arg, &tuba_isopcb.isop_laddr, n->ti_src.s_addr);
11256901Ssklower REDUCE(arg.sum, arg.sum);
11356485Ssklower goto adjust;
11456485Ssklower }
11556565Ssklower if (n->ti_sum == 0) {
11656901Ssklower arg.error = arg.sum = arg.offset = 0;
11756901Ssklower tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_dst.s_addr);
11856901Ssklower tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_src.s_addr);
11956901Ssklower REDUCE(arg.sum, arg.sum);
12056901Ssklower n->ti_sum = arg.sum;
12156485Ssklower n = mtod(m, struct tcpiphdr *);
12256485Ssklower adjust:
12356901Ssklower if (arg.error) {
12456485Ssklower m_freem(m);
12556681Ssklower return (EADDRNOTAVAIL);
12656485Ssklower }
12756901Ssklower REDUCE(n->ti_sum, n->ti_sum + (0xffff ^ arg.sum));
12856483Ssklower }
12956483Ssklower m->m_len -= sizeof (struct ip);
13056483Ssklower m->m_pkthdr.len -= sizeof (struct ip);
13156483Ssklower m->m_data += sizeof (struct ip);
13256901Ssklower return (clnp_output(m, isop, m->m_pkthdr.len, 0));
13356483Ssklower }
13456483Ssklower
13556483Ssklower tuba_refcnt(isop, delta)
13656483Ssklower struct isopcb *isop;
13756483Ssklower {
13856483Ssklower register struct tuba_cache *tc;
13956485Ssklower unsigned index, sum;
14056483Ssklower
14156483Ssklower if (delta != 1)
14256483Ssklower delta = -1;
14356483Ssklower if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 ||
14456483Ssklower (delta == -1 && isop->isop_tuba_cached == 0) ||
14556483Ssklower (delta == 1 && isop->isop_tuba_cached != 0))
14656483Ssklower return;
14756483Ssklower isop->isop_tuba_cached = (delta == 1);
14856912Ssklower if ((index = tuba_lookup(isop->isop_faddr, M_DONTWAIT)) != 0 &&
14956565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0))
15056483Ssklower tc->tc_refcnt += delta;
15156912Ssklower if ((index = tuba_lookup(isop->isop_laddr, M_DONTWAIT)) != 0 &&
15256565Ssklower (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0))
15356483Ssklower tc->tc_refcnt += delta;
15456483Ssklower }
15556483Ssklower
15656483Ssklower tuba_pcbdetach(isop)
15756483Ssklower struct isopcb *isop;
15856483Ssklower {
15956483Ssklower if (isop == 0)
16056483Ssklower return;
16156483Ssklower tuba_refcnt(isop, -1);
16256483Ssklower isop->isop_socket = 0;
16356483Ssklower iso_pcbdetach(isop);
16456483Ssklower }
16556483Ssklower
16656483Ssklower /*
16756483Ssklower * Avoid in_pcbconnect in faked out tcp_input()
16856483Ssklower */
tuba_pcbconnect(inp,nam)16956483Ssklower tuba_pcbconnect(inp, nam)
17056483Ssklower register struct inpcb *inp;
17156483Ssklower struct mbuf *nam;
17256483Ssklower {
17356912Ssklower register struct sockaddr_iso *siso;
17456565Ssklower struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
17556483Ssklower struct tcpcb *tp = intotcpcb(inp);
17656565Ssklower struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb;
17756483Ssklower int error;
17856483Ssklower
17956912Ssklower /* hardwire iso_pcbbind() here */
18056912Ssklower siso = isop->isop_laddr = &isop->isop_sladdr;
18156912Ssklower *siso = tuba_table[inp->inp_laddr.s_addr]->tc_siso;
18256912Ssklower siso->siso_tlen = sizeof(inp->inp_lport);
18356912Ssklower bcopy((caddr_t)&inp->inp_lport, TSEL(siso), sizeof(inp->inp_lport));
18456912Ssklower
18556912Ssklower /* hardwire in_pcbconnect() here without assigning route */
18656483Ssklower inp->inp_fport = sin->sin_port;
18756912Ssklower inp->inp_faddr = sin->sin_addr;
18856912Ssklower
18956912Ssklower /* reuse nam argument to call iso_pcbconnect() */
19056912Ssklower nam->m_len = sizeof(*siso);
19156912Ssklower siso = mtod(nam, struct sockaddr_iso *);
19256912Ssklower *siso = tuba_table[inp->inp_faddr.s_addr]->tc_siso;
19356483Ssklower siso->siso_tlen = sizeof(inp->inp_fport);
19456483Ssklower bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport));
19556912Ssklower
19656483Ssklower if ((error = iso_pcbconnect(isop, nam)) == 0)
19756483Ssklower tuba_refcnt(isop, 1);
19856483Ssklower return (error);
19956483Ssklower }
20056483Ssklower
20156483Ssklower /*
20256483Ssklower * CALLED FROM:
20356483Ssklower * clnp's input routine, indirectly through the protosw.
20456483Ssklower * FUNCTION and ARGUMENTS:
20556565Ssklower * Take a packet (m) from clnp, strip off the clnp header
20656565Ssklower * and do tcp input processing.
20756483Ssklower * No return value.
20856483Ssklower */
tuba_tcpinput(m,src,dst)20956903Ssklower tuba_tcpinput(m, src, dst)
21056483Ssklower register struct mbuf *m;
21156483Ssklower struct sockaddr_iso *src, *dst;
21256483Ssklower {
21356681Ssklower unsigned long sum, lindex, findex;
21456483Ssklower register struct tcpiphdr *ti;
21556483Ssklower register struct inpcb *inp;
21657949Ssklower caddr_t optp = NULL;
21757949Ssklower int optlen;
21856483Ssklower int len, tlen, off;
21956483Ssklower register struct tcpcb *tp = 0;
22056483Ssklower int tiflags;
22156483Ssklower struct socket *so;
22256483Ssklower int todrop, acked, ourfinisacked, needoutput = 0;
22356483Ssklower short ostate;
22456483Ssklower struct in_addr laddr;
22556483Ssklower int dropsocket = 0, iss = 0;
22657949Ssklower u_long tiwin, ts_val, ts_ecr;
22757949Ssklower int ts_present = 0;
22856483Ssklower
22956903Ssklower if ((m->m_flags & M_PKTHDR) == 0)
23056903Ssklower panic("tuba_tcpinput");
23156483Ssklower /*
23256483Ssklower * Do some housekeeping looking up CLNP addresses.
23356483Ssklower * If we are out of space might as well drop the packet now.
23456483Ssklower */
23556483Ssklower tcpstat.tcps_rcvtotal++;
23656912Ssklower lindex = tuba_lookup(dst, M_DONTWAIT);
23756912Ssklower findex = tuba_lookup(src, M_DONTWAIT);
23856681Ssklower if (lindex == 0 || findex == 0)
23956483Ssklower goto drop;
24056483Ssklower /*
24156483Ssklower * CLNP gave us an mbuf chain WITH the clnp header pulled up,
24256903Ssklower * but the data pointer pushed past it.
24356483Ssklower */
24456903Ssklower len = m->m_len;
24556903Ssklower tlen = m->m_pkthdr.len;
24656483Ssklower m->m_data -= sizeof(struct ip);
24756483Ssklower m->m_len += sizeof(struct ip);
24856483Ssklower m->m_pkthdr.len += sizeof(struct ip);
24956912Ssklower m->m_flags &= ~(M_MCAST|M_BCAST); /* XXX should do this in clnp_input */
25056483Ssklower /*
25156483Ssklower * The reassembly code assumes it will be overwriting a useless
25256681Ssklower * part of the packet, which is why we need to have it 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 */
25956565Ssklower off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ?
26056565Ssklower (m->m_data - m->m_ext.ext_buf) : (m->m_data - m->m_pktdat)));
26156903Ssklower if (off || len < sizeof(struct tcphdr)) {
26256903Ssklower struct mbuf *m0 = m;
26356903Ssklower
26456903Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA);
26556903Ssklower if (m == 0) {
26656903Ssklower m = m0;
26756483Ssklower goto drop;
26856483Ssklower }
26956903Ssklower m->m_next = m0;
27056903Ssklower m->m_data += max_linkhdr;
27156912Ssklower m->m_pkthdr = m0->m_pkthdr;
27256912Ssklower m->m_flags = m0->m_flags & M_COPYFLAGS;
27356903Ssklower if (len < sizeof(struct tcphdr)) {
27456912Ssklower m->m_len = 0;
27556903Ssklower if ((m = m_pullup(m, sizeof(struct tcpiphdr))) == 0) {
27656903Ssklower tcpstat.tcps_rcvshort++;
27756903Ssklower return;
27856903Ssklower }
27956903Ssklower } else {
28056912Ssklower bcopy(mtod(m0, caddr_t) + sizeof(struct ip),
28156912Ssklower mtod(m, caddr_t) + sizeof(struct ip),
28256903Ssklower sizeof(struct tcphdr));
28356903Ssklower m0->m_len -= sizeof(struct tcpiphdr);
28456903Ssklower m0->m_data += sizeof(struct tcpiphdr);
28556903Ssklower m->m_len = sizeof(struct tcpiphdr);
28656903Ssklower }
28756483Ssklower }
28856903Ssklower /*
28956903Ssklower * Calculate checksum of extended TCP header and data,
29056903Ssklower * replacing what would have been IP addresses by
29156903Ssklower * the IP checksum of the CLNP addresses.
29256903Ssklower */
29356483Ssklower ti = mtod(m, struct tcpiphdr *);
29456901Ssklower ti->ti_dst.s_addr = tuba_table[lindex]->tc_sum;
29556901Ssklower if (dst->siso_nlen & 1)
29656901Ssklower ti->ti_src.s_addr = tuba_table[findex]->tc_sum;
29756901Ssklower else
29856901Ssklower ti->ti_src.s_addr = tuba_table[findex]->tc_ssum;
29956685Ssklower ti->ti_prev = ti->ti_next = 0;
30056685Ssklower ti->ti_x1 = 0; ti->ti_pr = ISOPROTO_TCP;
30156685Ssklower ti->ti_len = htons((u_short)tlen);
30256685Ssklower if (ti->ti_sum = in_cksum(m, m->m_pkthdr.len)) {
30356685Ssklower tcpstat.tcps_rcvbadsum++;
30456685Ssklower goto drop;
30556685Ssklower }
30656483Ssklower ti->ti_src.s_addr = findex;
30756483Ssklower ti->ti_dst.s_addr = lindex;
30856483Ssklower /*
30956483Ssklower * Now include the rest of TCP input
31056483Ssklower */
31156565Ssklower #define TUBA_INCLUDE
31256690Ssklower #define in_pcbconnect tuba_pcbconnect
31356690Ssklower #define tcb tuba_inpcb
31456690Ssklower #define tcp_last_inpcb tuba_last_inpcb
31556483Ssklower
31656565Ssklower #include <netinet/tcp_input.c>
31756483Ssklower }
31856704Ssklower
31956704Ssklower #define tcp_slowtimo tuba_slowtimo
32056704Ssklower #define tcp_fasttimo tuba_fasttimo
32156903Ssklower
32256704Ssklower #include <netinet/tcp_timer.c>
323