1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)tuba_subr.c 8.1 (Berkeley) 06/10/93 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 /* 76 * Calculate contribution to fudge factor for TCP checksum, 77 * and coincidentally set pointer for convenience of clnp_output 78 * if we are are responding when there is no isopcb around. 79 */ 80 static void 81 tuba_getaddr(arg, siso, index) 82 register struct addr_arg *arg; 83 struct sockaddr_iso **siso; 84 u_long index; 85 { 86 register struct tuba_cache *tc; 87 if (index <= tuba_table_size && (tc = tuba_table[index])) { 88 if (siso) 89 *siso = &tc->tc_siso; 90 arg->sum += (arg->offset & 1 ? tc->tc_ssum : tc->tc_sum) 91 + (0xffff ^ index); 92 arg->offset += tc->tc_siso.siso_nlen + 1; 93 } else 94 arg->error = 1; 95 } 96 97 tuba_output(m, tp) 98 register struct mbuf *m; 99 struct tcpcb *tp; 100 { 101 register struct tcpiphdr *n; 102 struct isopcb *isop; 103 struct addr_arg arg; 104 105 if (tp == 0 || (n = tp->t_template) == 0 || 106 (isop = (struct isopcb *)tp->t_tuba_pcb) == 0) { 107 isop = &tuba_isopcb; 108 n = mtod(m, struct tcpiphdr *); 109 arg.error = arg.sum = arg.offset = 0; 110 tuba_getaddr(&arg, &tuba_isopcb.isop_faddr, n->ti_dst.s_addr); 111 tuba_getaddr(&arg, &tuba_isopcb.isop_laddr, n->ti_src.s_addr); 112 REDUCE(arg.sum, arg.sum); 113 goto adjust; 114 } 115 if (n->ti_sum == 0) { 116 arg.error = arg.sum = arg.offset = 0; 117 tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_dst.s_addr); 118 tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_src.s_addr); 119 REDUCE(arg.sum, arg.sum); 120 n->ti_sum = arg.sum; 121 n = mtod(m, struct tcpiphdr *); 122 adjust: 123 if (arg.error) { 124 m_freem(m); 125 return (EADDRNOTAVAIL); 126 } 127 REDUCE(n->ti_sum, n->ti_sum + (0xffff ^ arg.sum)); 128 } 129 m->m_len -= sizeof (struct ip); 130 m->m_pkthdr.len -= sizeof (struct ip); 131 m->m_data += sizeof (struct ip); 132 return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 133 } 134 135 tuba_refcnt(isop, delta) 136 struct isopcb *isop; 137 { 138 register struct tuba_cache *tc; 139 unsigned index, sum; 140 141 if (delta != 1) 142 delta = -1; 143 if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 144 (delta == -1 && isop->isop_tuba_cached == 0) || 145 (delta == 1 && isop->isop_tuba_cached != 0)) 146 return; 147 isop->isop_tuba_cached = (delta == 1); 148 if ((index = tuba_lookup(isop->isop_faddr, M_DONTWAIT)) != 0 && 149 (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 150 tc->tc_refcnt += delta; 151 if ((index = tuba_lookup(isop->isop_laddr, M_DONTWAIT)) != 0 && 152 (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 153 tc->tc_refcnt += delta; 154 } 155 156 tuba_pcbdetach(isop) 157 struct isopcb *isop; 158 { 159 if (isop == 0) 160 return; 161 tuba_refcnt(isop, -1); 162 isop->isop_socket = 0; 163 iso_pcbdetach(isop); 164 } 165 166 /* 167 * Avoid in_pcbconnect in faked out tcp_input() 168 */ 169 tuba_pcbconnect(inp, nam) 170 register struct inpcb *inp; 171 struct mbuf *nam; 172 { 173 register struct sockaddr_iso *siso; 174 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 175 struct tcpcb *tp = intotcpcb(inp); 176 struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; 177 int error; 178 179 /* hardwire iso_pcbbind() here */ 180 siso = isop->isop_laddr = &isop->isop_sladdr; 181 *siso = tuba_table[inp->inp_laddr.s_addr]->tc_siso; 182 siso->siso_tlen = sizeof(inp->inp_lport); 183 bcopy((caddr_t)&inp->inp_lport, TSEL(siso), sizeof(inp->inp_lport)); 184 185 /* hardwire in_pcbconnect() here without assigning route */ 186 inp->inp_fport = sin->sin_port; 187 inp->inp_faddr = sin->sin_addr; 188 189 /* reuse nam argument to call iso_pcbconnect() */ 190 nam->m_len = sizeof(*siso); 191 siso = mtod(nam, struct sockaddr_iso *); 192 *siso = tuba_table[inp->inp_faddr.s_addr]->tc_siso; 193 siso->siso_tlen = sizeof(inp->inp_fport); 194 bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 195 196 if ((error = iso_pcbconnect(isop, nam)) == 0) 197 tuba_refcnt(isop, 1); 198 return (error); 199 } 200 201 /* 202 * CALLED FROM: 203 * clnp's input routine, indirectly through the protosw. 204 * FUNCTION and ARGUMENTS: 205 * Take a packet (m) from clnp, strip off the clnp header 206 * and do tcp input processing. 207 * No return value. 208 */ 209 tuba_tcpinput(m, src, dst) 210 register struct mbuf *m; 211 struct sockaddr_iso *src, *dst; 212 { 213 unsigned long sum, lindex, findex; 214 register struct tcpiphdr *ti; 215 register struct inpcb *inp; 216 caddr_t optp = NULL; 217 int optlen; 218 int len, tlen, off; 219 register struct tcpcb *tp = 0; 220 int tiflags; 221 struct socket *so; 222 int todrop, acked, ourfinisacked, needoutput = 0; 223 short ostate; 224 struct in_addr laddr; 225 int dropsocket = 0, iss = 0; 226 u_long tiwin, ts_val, ts_ecr; 227 int ts_present = 0; 228 229 if ((m->m_flags & M_PKTHDR) == 0) 230 panic("tuba_tcpinput"); 231 /* 232 * Do some housekeeping looking up CLNP addresses. 233 * If we are out of space might as well drop the packet now. 234 */ 235 tcpstat.tcps_rcvtotal++; 236 lindex = tuba_lookup(dst, M_DONTWAIT); 237 findex = tuba_lookup(src, M_DONTWAIT); 238 if (lindex == 0 || findex == 0) 239 goto drop; 240 /* 241 * CLNP gave us an mbuf chain WITH the clnp header pulled up, 242 * but the data pointer pushed past it. 243 */ 244 len = m->m_len; 245 tlen = m->m_pkthdr.len; 246 m->m_data -= sizeof(struct ip); 247 m->m_len += sizeof(struct ip); 248 m->m_pkthdr.len += sizeof(struct ip); 249 m->m_flags &= ~(M_MCAST|M_BCAST); /* XXX should do this in clnp_input */ 250 /* 251 * The reassembly code assumes it will be overwriting a useless 252 * part of the packet, which is why we need to have it point 253 * into the packet itself. 254 * 255 * Check to see if the data is properly alligned 256 * so that we can save copying the tcp header. 257 * This code knows way too much about the structure of mbufs! 258 */ 259 off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ? 260 (m->m_data - m->m_ext.ext_buf) : (m->m_data - m->m_pktdat))); 261 if (off || len < sizeof(struct tcphdr)) { 262 struct mbuf *m0 = m; 263 264 MGETHDR(m, M_DONTWAIT, MT_DATA); 265 if (m == 0) { 266 m = m0; 267 goto drop; 268 } 269 m->m_next = m0; 270 m->m_data += max_linkhdr; 271 m->m_pkthdr = m0->m_pkthdr; 272 m->m_flags = m0->m_flags & M_COPYFLAGS; 273 if (len < sizeof(struct tcphdr)) { 274 m->m_len = 0; 275 if ((m = m_pullup(m, sizeof(struct tcpiphdr))) == 0) { 276 tcpstat.tcps_rcvshort++; 277 return; 278 } 279 } else { 280 bcopy(mtod(m0, caddr_t) + sizeof(struct ip), 281 mtod(m, caddr_t) + sizeof(struct ip), 282 sizeof(struct tcphdr)); 283 m0->m_len -= sizeof(struct tcpiphdr); 284 m0->m_data += sizeof(struct tcpiphdr); 285 m->m_len = sizeof(struct tcpiphdr); 286 } 287 } 288 /* 289 * Calculate checksum of extended TCP header and data, 290 * replacing what would have been IP addresses by 291 * the IP checksum of the CLNP addresses. 292 */ 293 ti = mtod(m, struct tcpiphdr *); 294 ti->ti_dst.s_addr = tuba_table[lindex]->tc_sum; 295 if (dst->siso_nlen & 1) 296 ti->ti_src.s_addr = tuba_table[findex]->tc_sum; 297 else 298 ti->ti_src.s_addr = tuba_table[findex]->tc_ssum; 299 ti->ti_prev = ti->ti_next = 0; 300 ti->ti_x1 = 0; ti->ti_pr = ISOPROTO_TCP; 301 ti->ti_len = htons((u_short)tlen); 302 if (ti->ti_sum = in_cksum(m, m->m_pkthdr.len)) { 303 tcpstat.tcps_rcvbadsum++; 304 goto drop; 305 } 306 ti->ti_src.s_addr = findex; 307 ti->ti_dst.s_addr = lindex; 308 /* 309 * Now include the rest of TCP input 310 */ 311 #define TUBA_INCLUDE 312 #define in_pcbconnect tuba_pcbconnect 313 #define tcb tuba_inpcb 314 #define tcp_last_inpcb tuba_last_inpcb 315 316 #include <netinet/tcp_input.c> 317 } 318 319 #define tcp_slowtimo tuba_slowtimo 320 #define tcp_fasttimo tuba_fasttimo 321 322 #include <netinet/tcp_timer.c> 323