1 /* 2 * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)tuba_subr.c 7.1 (Berkeley) 10/09/92 8 */ 9 10 #include "param.h" 11 #include "proc.h" 12 #include "systm.h" 13 #include "malloc.h" 14 #include "mbuf.h" 15 #include "socket.h" 16 #include "socketvar.h" 17 #include "protosw.h" 18 #include "errno.h" 19 20 #include "../net/route.h" 21 #include "../net/if.h" 22 23 #include "in.h" 24 #include "in_systm.h" 25 #include "ip.h" 26 #include "in_pcb.h" 27 #include "ip_var.h" 28 #include "ip_icmp.h" 29 #include "tcp.h" 30 #include "tcp_fsm.h" 31 #include "tcp_seq.h" 32 #include "tcp_timer.h" 33 #include "tcp_var.h" 34 #include "tcpip.h" 35 36 #include "netiso/argo_debug.h" 37 #include "netiso/iso.h" 38 #include "netiso/clnp.h" 39 #include "netiso/iso_pcb.h" 40 #include "netiso/iso_var.h" 41 42 #include "tuba_addr.h" 43 /* 44 * Tuba initialization 45 */ 46 tuba_init() 47 { 48 49 extern struct isopcb tuba_isopcb; 50 51 tuba_isopcb.isop_next = tuba_isopcb.isop_prev = &tuba_isopcb; 52 #define TUBAHDRSIZE (3 /*LLC*/ + 9 /*CLNP Fixed*/ + 42 /*Addresses*/ \ 53 + 6 /*CLNP Segment*/ + 20 /*TCP*/) 54 55 if (max_protohdr < TUBAHDRSIZE) 56 max_protohdr = TUBAHDRSIZE; 57 if (max_linkhdr + TUBAHDRSIZE > MHLEN) 58 panic("tuba_init"); 59 } 60 61 tuba_output(tp, m) 62 struct tcpcb *tp; 63 register struct mbuf *m; 64 { 65 struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; 66 register struct tcpiphdr *n = tp->tp_template; 67 68 if (n->ni_sum == 0) { 69 register struct inpcb *inp = tp->tp_inpcb; 70 register struct tuba_cache *tc; 71 u_long cksum_fixup; 72 73 if ((tc = tuba_table[inp->in_faddr.s_addr]) == 0) 74 return (ENOBUFS); 75 cksum_fixup = tc->tc_sum_out; /* includes -index */ 76 if ((tc = tuba_table[inp->in_laddr.s_addr]) == 0) 77 return (ENOBUFS); 78 ICKSUM(cksum_fixup, cksum_fixup + tc->tc_sum_out); 79 n->ti_sum = cksum_fixup; 80 n = mtod(m, struct tcpiphdr *); 81 ICKSUM(n->ti_sum, cksum_fixup + n->ti_sum); 82 } 83 m->m_len -= sizeof (struct ip); 84 m->m_pkthdr.len -= sizeof (struct ip); 85 m->m_data += sizeof (struct ip); 86 return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 87 } 88 89 tuba_refcnt(isop, delta) 90 struct isopcb *isop; 91 { 92 register struct tuba_cache *tc; 93 unsigned index; 94 95 if (delta != 1) 96 delta = -1; 97 if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 98 (delta == -1 && isop->isop_tuba_cached == 0) || 99 (delta == 1 && isop->isop_tuba_cached != 0)) 100 return; 101 isop->isop_tuba_cached = (delta == 1); 102 if ((index = tuba_lookup(&isop->isop_faddr.siso_addr)) != 0 && 103 (tc = tuba_cache[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 104 tc->tc_refcnt += delta; 105 if ((index = tuba_lookup(&isop->isop_laddr.siso_addr)) != 0 && 106 (tc = tuba_cache[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 107 tc->tc_refcnt += delta; 108 } 109 110 tuba_pcbdetach(isop) 111 struct isopcb *isop; 112 { 113 if (isop == 0) 114 return; 115 tuba_refcnt(isop, -1); 116 isop->isop_socket = 0; 117 iso_pcbdetach(isop); 118 } 119 120 static struct sockaddr_iso null_siso = { sizeof(null_siso), AF_ISO, }; 121 /* 122 * Avoid in_pcbconnect in faked out tcp_input() 123 */ 124 tuba_pcbconnect(inp, nam) 125 register struct inpcb *inp; 126 struct mbuf *nam; 127 { 128 register struct sockaddr_iso *siso = mtod(m, struct sockaddr_iso *); 129 struct sockaddr_in *sin = mtod(m, struct sockaddr_in *); 130 struct tcpcb *tp = intotcpcb(inp); 131 unsigned index = sin->sin_addr.s_addr; 132 struct tuba_cache *tc = tuba_table[index]; 133 struct isopcb *isop = (struct isopcb *)tp->tp_tuba_pcb; 134 int error; 135 136 inp->inp_faddr.s_addr = index; 137 inp->inp_fport = sin->sin_port; 138 *siso = null_siso; 139 siso->siso_addr = tc->tc_addr; 140 siso->siso_tlen = sizeof(inp->inp_fport); 141 bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 142 nam->m_len = sizeof(*siso); 143 if ((error = iso_pcbconnect(isop, nam)) == 0) 144 tuba_refcnt(isop, 1); 145 return (error); 146 } 147 148 /* 149 * CALLED FROM: 150 * clnp's input routine, indirectly through the protosw. 151 * FUNCTION and ARGUMENTS: 152 * Take a packet (m) from clnp, strip off the clnp header and give it to tcp 153 * or udp. 154 * No return value. 155 */ 156 ProtoHook 157 tpclnp_input(m, src, dst, clnp_len, ce_bit) 158 register struct mbuf *m; 159 struct sockaddr_iso *src, *dst; 160 int clnp_len, ce_bit; 161 { 162 int s = splnet(); 163 unsigned long fix_csum, lindex, findex; 164 register struct tcpiphdr *ti; 165 register struct inpcb *inp; 166 struct mbuf *om = 0; 167 int len, tlen, off; 168 register struct tcpcb *tp = 0; 169 int tiflags; 170 struct socket *so; 171 int todrop, acked, ourfinisacked, needoutput = 0; 172 short ostate; 173 struct in_addr laddr; 174 int dropsocket = 0, iss = 0; 175 176 if ((m->m_flags & M_PKTHDR) == 0) 177 panic("tuba_input"); 178 /* 179 * Do some housekeeping looking up CLNP addresses. 180 * If we are out of space might as well drop the packet now. 181 */ 182 tcpstat.tcps_rcvtotal++; 183 if ((lindex = tuba_lookup(&dst->siso_addr) == 0 || 184 (findex = tuba_lookup(&dst->siso_addr) == 0)) 185 goto drop; 186 /* 187 * Get CLNP and TCP header together in first mbuf. 188 * CLNP gave us an mbuf chain WITH the clnp header pulled up, 189 * and the length of the clnp header. 190 */ 191 len = clnp_len + sizeof(struct tcphdr); 192 if (m->m_len < len) { 193 if ((m = m_pullup(m, len)) == 0) { 194 tcpstat.tcps_rcvshort++; 195 return; 196 } 197 } 198 /* 199 * Calculate checksum of extended TCP header and data, 200 * by adjusting the checksum for missing parts of the header. 201 */ 202 m->m_data += clnp_len; 203 m->m_len -= clnp_len; 204 tlen = m->m_pkthdr.len -= clnp_len; 205 ICKSUM(fix_cksum, tuba_table[findex]->tc_sum_in + htons((u_short)tlen) 206 + tuba_table[lindex]->tc_sum_in + in_cksum(m, tlen)); 207 if (fix_cksum != 0xffff) { 208 tcpstat.tcps_rcvbadsum++; 209 goto drop; 210 } 211 m->m_data -= sizeof(struct ip); 212 m->m_len += sizeof(struct ip); 213 m->m_pkthdr.len += sizeof(struct ip); 214 /* 215 * The reassembly code assumes it will be overwriting a useless 216 * part of the packet, which is why we need to have ti point 217 * into the packet itself. 218 * 219 * Check to see if the data is properly alligned 220 * so that we can save copying the tcp header. 221 * This code knows way too much about the structure of mbufs! 222 */ 223 off = ((sizeof (long) - 1) & ((m->m_flags & EXT) ? 224 (m->m_data - m->m_ext.ext_buf) : (m->m_data - m_pktdat))); 225 if (off) { 226 struct mbuf *m0 = m_gethdr(M_DONTWAIT, MT_DATA) 227 if (m0 == 0) { 228 goto drop; 229 } 230 bcopy(mtod(m, caddr_t) + sizeof(struct ip), 231 mtod(m0, caddr_t) + sizeof(struct ip), 232 sizeof(struct tcphdr)); 233 m->m_data += sizeof(struct tcpiphdr); 234 m0->m_next = m; 235 m0->m_pkthdr = m->m_pkthdr; 236 m0->m_flags = m->m_pkthdr & M_COPYFLAGS; 237 m0->m_len = sizeof(struct tcpiphdr); 238 m = m0; 239 } 240 ti = mtod(m, struct tcpiphdr *); 241 ti->ti_src.s_addr = findex; 242 ti->ti_dst.s_addr = lindex; 243 ti->ti_len = tlen; 244 /* 245 * Now include the rest of TCP input 246 */ 247 #define TUBA_INPUT 248 #define in_pcbconnect tuba_pcbconnect 249 250 #include "../netinet/tcp_input.c" 251 } 252