1 /* 2 * Copyright (c) 1992 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)tuba_subr.c 7.9 (Berkeley) 11/19/92 8 */ 9 10 #include <sys/param.h> 11 #include <sys/proc.h> 12 #include <sys/systm.h> 13 #include <sys/malloc.h> 14 #include <sys/mbuf.h> 15 #include <sys/socket.h> 16 #include <sys/socketvar.h> 17 #include <sys/protosw.h> 18 #include <sys/errno.h> 19 20 #include <net/route.h> 21 #include <net/if.h> 22 23 #include <netinet/in.h> 24 #include <netinet/in_systm.h> 25 #include <netinet/ip.h> 26 #include <netinet/in_pcb.h> 27 #include <netinet/ip_var.h> 28 #include <netinet/ip_icmp.h> 29 #include <netinet/tcp.h> 30 #include <netinet/tcp_fsm.h> 31 #include <netinet/tcp_seq.h> 32 #include <netinet/tcp_timer.h> 33 #include <netinet/tcp_var.h> 34 #include <netinet/tcpip.h> 35 #include <netinet/tcp_debug.h> 36 37 #include <netiso/argo_debug.h> 38 #include <netiso/iso.h> 39 #include <netiso/clnp.h> 40 #include <netiso/iso_pcb.h> 41 #include <netiso/iso_var.h> 42 #include <netiso/tuba_table.h> 43 44 static struct sockaddr_iso null_siso = { sizeof(null_siso), AF_ISO, }; 45 extern int tuba_table_size, tcp_keepidle, tcp_keepintvl, tcp_maxidle; 46 extern int tcppcbcachemiss, tcppredack, tcppreddat, tcprexmtthresh; 47 extern struct tcpiphdr tcp_saveti; 48 struct inpcb tuba_inpcb; 49 struct inpcb *tuba_last_inpcb = &tuba_inpcb; 50 struct isopcb tuba_isopcb; 51 /* 52 * Tuba initialization 53 */ 54 tuba_init() 55 { 56 #define TUBAHDRSIZE (3 /*LLC*/ + 9 /*CLNP Fixed*/ + 42 /*Addresses*/ \ 57 + 6 /*CLNP Segment*/ + 20 /*TCP*/) 58 59 tuba_inpcb.inp_next = tuba_inpcb.inp_prev = &tuba_inpcb; 60 tuba_isopcb.isop_next = tuba_isopcb.isop_prev = &tuba_isopcb; 61 tuba_isopcb.isop_faddr = &tuba_isopcb.isop_sfaddr; 62 tuba_isopcb.isop_laddr = &tuba_isopcb.isop_sladdr; 63 if (max_protohdr < TUBAHDRSIZE) 64 max_protohdr = TUBAHDRSIZE; 65 if (max_linkhdr + TUBAHDRSIZE > MHLEN) 66 panic("tuba_init"); 67 } 68 69 struct addr_arg { 70 int error; 71 int offset; 72 u_long sum; 73 }; 74 75 static void 76 tuba_getaddr(arg, siso, index) 77 register struct addr_arg *arg; 78 struct sockaddr_iso **siso; 79 u_long index; 80 { 81 register struct tuba_cache *tc; 82 if (index <= tuba_table_size && (tc = tuba_table[index])) { 83 if (siso) 84 *siso = &tc->tc_siso; 85 arg->sum += (arg->offset & 1 ? tc->tc_ssum_d : tc->tc_sum_d); 86 arg->offset += tc->tc_siso.siso_nlen + 1; 87 } else 88 arg->error = 1; 89 } 90 91 tuba_output(m, tp) 92 register struct mbuf *m; 93 struct tcpcb *tp; 94 { 95 register struct tcpiphdr *n; 96 struct isopcb *isop; 97 struct addr_arg arg; 98 99 if (tp == 0 || (n = tp->t_template) == 0 || 100 (isop = (struct isopcb *)tp->t_tuba_pcb) == 0) { 101 isop = &tuba_isopcb; 102 n = mtod(m, struct tcpiphdr *); 103 arg.error = arg.sum = arg.offset = 0; 104 tuba_getaddr(&arg, &tuba_isopcb.isop_faddr, n->ti_dst.s_addr); 105 tuba_getaddr(&arg, &tuba_isopcb.isop_laddr, n->ti_src.s_addr); 106 REDUCE(arg.sum, arg.sum); 107 goto adjust; 108 } 109 if (n->ti_sum == 0) { 110 arg.error = arg.sum = arg.offset = 0; 111 tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_dst.s_addr); 112 tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_src.s_addr); 113 REDUCE(arg.sum, arg.sum); 114 n->ti_sum = arg.sum; 115 n = mtod(m, struct tcpiphdr *); 116 adjust: 117 if (arg.error) { 118 m_freem(m); 119 return (EADDRNOTAVAIL); 120 } 121 REDUCE(n->ti_sum, n->ti_sum + (0xffff ^ arg.sum)); 122 } 123 m->m_len -= sizeof (struct ip); 124 m->m_pkthdr.len -= sizeof (struct ip); 125 m->m_data += sizeof (struct ip); 126 return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 127 } 128 129 tuba_refcnt(isop, delta) 130 struct isopcb *isop; 131 { 132 register struct tuba_cache *tc; 133 unsigned index, sum; 134 135 if (delta != 1) 136 delta = -1; 137 if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 138 (delta == -1 && isop->isop_tuba_cached == 0) || 139 (delta == 1 && isop->isop_tuba_cached != 0)) 140 return; 141 isop->isop_tuba_cached = (delta == 1); 142 if ((index = tuba_lookup(&isop->isop_sfaddr.siso_addr, M_DONTWAIT)) != 0 && 143 (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 144 tc->tc_refcnt += delta; 145 if ((index = tuba_lookup(&isop->isop_sladdr.siso_addr, M_DONTWAIT)) != 0 && 146 (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 147 tc->tc_refcnt += delta; 148 } 149 150 tuba_pcbdetach(isop) 151 struct isopcb *isop; 152 { 153 if (isop == 0) 154 return; 155 tuba_refcnt(isop, -1); 156 isop->isop_socket = 0; 157 iso_pcbdetach(isop); 158 } 159 160 /* 161 * Avoid in_pcbconnect in faked out tcp_input() 162 */ 163 tuba_pcbconnect(inp, nam) 164 register struct inpcb *inp; 165 struct mbuf *nam; 166 { 167 register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 168 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 169 struct tcpcb *tp = intotcpcb(inp); 170 unsigned index = sin->sin_addr.s_addr; 171 struct tuba_cache *tc = tuba_table[index]; 172 struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; 173 int error; 174 175 inp->inp_faddr.s_addr = index; 176 inp->inp_fport = sin->sin_port; 177 *siso = tc->tc_siso; 178 siso->siso_tlen = sizeof(inp->inp_fport); 179 bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 180 nam->m_len = sizeof(*siso); 181 if ((error = iso_pcbconnect(isop, nam)) == 0) 182 tuba_refcnt(isop, 1); 183 return (error); 184 } 185 186 /* 187 * CALLED FROM: 188 * clnp's input routine, indirectly through the protosw. 189 * FUNCTION and ARGUMENTS: 190 * Take a packet (m) from clnp, strip off the clnp header 191 * and do tcp input processing. 192 * No return value. 193 */ 194 tuba_tcpinput(m, src, dst, clnp_len, ce_bit) 195 register struct mbuf *m; 196 struct sockaddr_iso *src, *dst; 197 int clnp_len, ce_bit; 198 { 199 unsigned long sum, lindex, findex; 200 register struct tcpiphdr *ti; 201 register struct inpcb *inp; 202 struct mbuf *om; 203 int len, tlen, off; 204 register struct tcpcb *tp = 0; 205 int tiflags; 206 struct socket *so; 207 int todrop, acked, ourfinisacked, needoutput = 0; 208 short ostate; 209 struct in_addr laddr; 210 int dropsocket = 0, iss = 0; 211 212 if ((m->m_flags & M_PKTHDR) == 0) { 213 om = m_gethdr(M_DONTWAIT, MT_DATA); 214 if (om == 0) 215 goto drop; 216 om->m_next = m; 217 for (len = 0; m; m = m->m_next) 218 len += m->m_len; 219 m = om; 220 m->m_pkthdr.len = len; 221 } 222 om = 0; 223 /* 224 * Do some housekeeping looking up CLNP addresses. 225 * If we are out of space might as well drop the packet now. 226 */ 227 tcpstat.tcps_rcvtotal++; 228 lindex = tuba_lookup(&dst->siso_addr, M_DONTWAIT); 229 findex = tuba_lookup(&src->siso_addr, M_DONTWAIT); 230 if (lindex == 0 || findex == 0) 231 goto drop; 232 /* 233 * Get CLNP and TCP header together in first mbuf. 234 * CLNP gave us an mbuf chain WITH the clnp header pulled up, 235 * and the length of the clnp header. 236 */ 237 len = clnp_len + sizeof(struct tcphdr); 238 if (m->m_len < len) { 239 if ((m = m_pullup(m, len)) == 0) { 240 tcpstat.tcps_rcvshort++; 241 return; 242 } 243 } 244 /* 245 * Calculate checksum of extended TCP header and data, 246 * by adjusting the checksum for missing parts of the header. 247 */ 248 m->m_data += clnp_len; 249 m->m_len -= clnp_len; 250 tlen = m->m_pkthdr.len -= clnp_len; 251 m->m_data -= sizeof(struct ip); 252 m->m_len += sizeof(struct ip); 253 m->m_pkthdr.len += sizeof(struct ip); 254 /* 255 * The reassembly code assumes it will be overwriting a useless 256 * part of the packet, which is why we need to have it point 257 * into the packet itself. 258 * 259 * Check to see if the data is properly alligned 260 * so that we can save copying the tcp header. 261 * This code knows way too much about the structure of mbufs! 262 */ 263 off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ? 264 (m->m_data - m->m_ext.ext_buf) : (m->m_data - m->m_pktdat))); 265 if (off) { 266 struct mbuf *m0 = m_gethdr(M_DONTWAIT, MT_DATA); 267 if (m0 == 0) { 268 goto drop; 269 } 270 m0->m_data += max_linkhdr; 271 bcopy(mtod(m, caddr_t) + sizeof(struct ip), 272 mtod(m0, caddr_t) + sizeof(struct ip), 273 sizeof(struct tcphdr)); 274 m->m_data += sizeof(struct tcpiphdr); 275 m->m_len -= sizeof(struct tcpiphdr); 276 m0->m_next = m; 277 m0->m_pkthdr = m->m_pkthdr; 278 m0->m_flags = m->m_flags & M_COPYFLAGS; 279 m0->m_len = sizeof(struct tcpiphdr); 280 m = m0; 281 } 282 ti = mtod(m, struct tcpiphdr *); 283 ti->ti_dst.s_addr = tuba_table[lindex]->tc_sum; 284 if (dst->siso_nlen & 1) 285 ti->ti_src.s_addr = tuba_table[findex]->tc_sum; 286 else 287 ti->ti_src.s_addr = tuba_table[findex]->tc_ssum; 288 ti->ti_prev = ti->ti_next = 0; 289 ti->ti_x1 = 0; ti->ti_pr = ISOPROTO_TCP; 290 ti->ti_len = htons((u_short)tlen); 291 if (ti->ti_sum = in_cksum(m, m->m_pkthdr.len)) { 292 tcpstat.tcps_rcvbadsum++; 293 goto drop; 294 } 295 ti->ti_src.s_addr = findex; 296 ti->ti_dst.s_addr = lindex; 297 /* 298 * Now include the rest of TCP input 299 */ 300 #define TUBA_INCLUDE 301 #define in_pcbconnect tuba_pcbconnect 302 #define tcb tuba_inpcb 303 #define tcp_last_inpcb tuba_last_inpcb 304 305 #include <netinet/tcp_input.c> 306 } 307 308 #define tcp_slowtimo tuba_slowtimo 309 #define tcp_fasttimo tuba_fasttimo 310 #include <netinet/tcp_timer.c> 311