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.6 (Berkeley) 11/05/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 struct isopcb tuba_isopcb; 46 extern int tuba_table_size; 47 extern int tcppcbcachemiss, tcppredack, tcppreddat, tcprexmtthresh; 48 extern struct inpcb *tcp_last_inpcb; 49 extern struct tcpiphdr tcp_saveti; 50 /* 51 * Tuba initialization 52 */ 53 tuba_init() 54 { 55 #define TUBAHDRSIZE (3 /*LLC*/ + 9 /*CLNP Fixed*/ + 42 /*Addresses*/ \ 56 + 6 /*CLNP Segment*/ + 20 /*TCP*/) 57 58 tuba_isopcb.isop_next = tuba_isopcb.isop_prev = &tuba_isopcb; 59 tuba_isopcb.isop_faddr = &tuba_isopcb.isop_sfaddr; 60 tuba_isopcb.isop_laddr = &tuba_isopcb.isop_sladdr; 61 if (max_protohdr < TUBAHDRSIZE) 62 max_protohdr = TUBAHDRSIZE; 63 if (max_linkhdr + TUBAHDRSIZE > MHLEN) 64 panic("tuba_init"); 65 } 66 67 static void 68 tuba_getaddr(error, sum, siso, index) 69 int *error; 70 register u_long *sum; 71 struct sockaddr_iso *siso; 72 u_long index; 73 { 74 register struct tuba_cache *tc; 75 if (index <= tuba_table_size && (tc = tuba_table[index])) { 76 if (siso) { 77 *siso = null_siso; 78 siso->siso_addr = tc->tc_addr; 79 } 80 REDUCE(*sum, *sum + tc->tc_sum_out); 81 } else 82 *error = 1; 83 } 84 int tuba_noisy = 1; 85 86 tuba_output(m, tp) 87 register struct mbuf *m; 88 struct tcpcb *tp; 89 { 90 struct isopcb *isop; 91 register struct tcpiphdr *n, *h; 92 struct mbuf *p = m_gethdr(M_DONTWAIT, MT_DATA); 93 u_long sum = 0, i = 0, k1, k2, k3, k4, k5, lindex, findex, len; 94 95 if ((m->m_flags & M_PKTHDR) == 0) 96 panic("tuba_output"); 97 if (p == 0) 98 panic("tuba_output 2"); 99 m = m_pullup(m, 40); 100 if (m == 0) { 101 printf("heisenberg hit us\n"); 102 (void)m_free(p); 103 return (ENOBUFS); 104 } 105 n = mtod(m, struct tcpiphdr *); 106 h = mtod(p, struct tcpiphdr *); 107 lindex = n->ti_src.s_addr; 108 findex = n->ti_dst.s_addr; 109 len = m->m_pkthdr.len; 110 bzero((caddr_t)h, sizeof(*h)); 111 h->ti_pr = ISOPROTO_TCP; 112 h->ti_dst.s_addr = findex; 113 h->ti_src.s_addr = lindex; 114 h->ti_len = htons((u_short)len - 20); 115 m->m_data += 20; 116 m->m_len -= 20; 117 k1 = in_cksum(m, len - 20); 118 p->m_len = 20; 119 p->m_next = m; 120 k2 = in_cksum(p, 20); 121 k3 = in_cksum(p, len); 122 m->m_data -= 20; 123 m->m_len += 20; 124 125 if (tuba_noisy) { 126 printf("old ti_sum is 0x%x\n", n->ti_sum); 127 printf("in_cksum for old TCP part is 0x%x\n", k1); 128 printf("in_cksum for ph(idx) is 0x%x\n", k2); 129 printf("in_cksum for ph + TCP is 0x%x\n", k3); 130 } 131 if (tp == 0 || (n = tp->t_template) == 0 || 132 (isop = (struct isopcb *)tp->t_tuba_pcb) == 0) { 133 isop = &tuba_isopcb; 134 n = mtod(m, struct tcpiphdr *); 135 tuba_getaddr(&i, &sum, tuba_isopcb.isop_faddr, findex); 136 tuba_getaddr(&i, &sum, tuba_isopcb.isop_laddr, lindex); 137 goto adjust; 138 } 139 if (n->ti_sum == 0) { 140 tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, findex); 141 tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, lindex); 142 n->ti_sum = sum; 143 n = mtod(m, struct tcpiphdr *); 144 adjust: 145 if (i) { 146 m_freem(m); 147 (void)m_free(p); 148 return (EADDRNOTAVAIL); 149 } 150 REDUCE(n->ti_sum, n->ti_sum + (0xffff ^ sum)); 151 } 152 h->ti_dst.s_addr = tuba_table[findex]->tc_sum_in; 153 h->ti_src.s_addr = tuba_table[lindex]->tc_sum_in; 154 m->m_len -= sizeof (struct ip); 155 m->m_pkthdr.len -= sizeof (struct ip); 156 m->m_data += sizeof (struct ip); 157 k1 = in_cksum(m, len - 20); 158 k2 = in_cksum(p, 20); 159 k3 = in_cksum(p, len); 160 REDUCE(k4, h->ti_dst.s_addr + h->ti_src.s_addr + h->ti_len 161 + ntohs((u_short)ISOPROTO_TCP) + (0xffff ^ k1)); 162 k4 = 0xffff ^ k4; 163 if (tuba_noisy) { 164 printf("new ti_sum is 0x%x\n", n->ti_sum); 165 printf("adjustment is 0x%x\n", sum); 166 printf("in_cksum for new TCP part is 0x%x\n", k1); 167 printf("in_cksum for ph(EIDSUM) is 0x%x\n", k2); 168 printf("in_cksum for ph + TCP is 0x%x\n", k3); 169 printf("calculated in the funky way is 0x%x\n", k4); 170 } 171 (void)m_free(p); 172 return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 173 } 174 175 tuba_refcnt(isop, delta) 176 struct isopcb *isop; 177 { 178 register struct tuba_cache *tc; 179 unsigned index, sum; 180 181 if (delta != 1) 182 delta = -1; 183 if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 184 (delta == -1 && isop->isop_tuba_cached == 0) || 185 (delta == 1 && isop->isop_tuba_cached != 0)) 186 return; 187 isop->isop_tuba_cached = (delta == 1); 188 if ((index = tuba_lookup(&isop->isop_sfaddr.siso_addr, M_DONTWAIT)) != 0 && 189 (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 190 tc->tc_refcnt += delta; 191 if ((index = tuba_lookup(&isop->isop_sladdr.siso_addr, M_DONTWAIT)) != 0 && 192 (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 193 tc->tc_refcnt += delta; 194 } 195 196 tuba_pcbdetach(isop) 197 struct isopcb *isop; 198 { 199 if (isop == 0) 200 return; 201 tuba_refcnt(isop, -1); 202 isop->isop_socket = 0; 203 iso_pcbdetach(isop); 204 } 205 206 /* 207 * Avoid in_pcbconnect in faked out tcp_input() 208 */ 209 tuba_pcbconnect(inp, nam) 210 register struct inpcb *inp; 211 struct mbuf *nam; 212 { 213 register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 214 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 215 struct tcpcb *tp = intotcpcb(inp); 216 unsigned index = sin->sin_addr.s_addr; 217 struct tuba_cache *tc = tuba_table[index]; 218 struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; 219 int error; 220 221 inp->inp_faddr.s_addr = index; 222 inp->inp_fport = sin->sin_port; 223 *siso = null_siso; 224 siso->siso_addr = tc->tc_addr; 225 siso->siso_tlen = sizeof(inp->inp_fport); 226 bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 227 nam->m_len = sizeof(*siso); 228 if ((error = iso_pcbconnect(isop, nam)) == 0) 229 tuba_refcnt(isop, 1); 230 return (error); 231 } 232 233 tuba_badcksum() {} /* XXX - to set breakpoints */ 234 235 /* 236 * CALLED FROM: 237 * clnp's input routine, indirectly through the protosw. 238 * FUNCTION and ARGUMENTS: 239 * Take a packet (m) from clnp, strip off the clnp header 240 * and do tcp input processing. 241 * No return value. 242 */ 243 tuba_tcpinput(m, src, dst, clnp_len, ce_bit) 244 register struct mbuf *m; 245 struct sockaddr_iso *src, *dst; 246 int clnp_len, ce_bit; 247 { 248 int s = splnet(); 249 unsigned long sum, lindex, findex; 250 register struct tcpiphdr *ti; 251 register struct inpcb *inp; 252 struct mbuf *om; 253 int len, tlen, off; 254 register struct tcpcb *tp = 0; 255 int tiflags; 256 struct socket *so; 257 int todrop, acked, ourfinisacked, needoutput = 0; 258 short ostate; 259 struct in_addr laddr; 260 int dropsocket = 0, iss = 0; 261 262 if ((m->m_flags & M_PKTHDR) == 0) { 263 om = m_gethdr(M_DONTWAIT, MT_DATA); 264 if (om == 0) 265 goto drop; 266 om->m_next = m; 267 for (len = 0; m; m = m->m_next) 268 len += m->m_len; 269 m = om; 270 m->m_pkthdr.len = len; 271 } 272 om = 0; 273 /* 274 * Do some housekeeping looking up CLNP addresses. 275 * If we are out of space might as well drop the packet now. 276 */ 277 tcpstat.tcps_rcvtotal++; 278 lindex = tuba_lookup(&dst->siso_addr, M_DONTWAIT); 279 findex = tuba_lookup(&dst->siso_addr, M_DONTWAIT); 280 if (lindex == 0 || findex == 0) 281 goto drop; 282 /* 283 * Get CLNP and TCP header together in first mbuf. 284 * CLNP gave us an mbuf chain WITH the clnp header pulled up, 285 * and the length of the clnp header. 286 */ 287 len = clnp_len + sizeof(struct tcphdr); 288 if (m->m_len < len) { 289 if ((m = m_pullup(m, len)) == 0) { 290 tcpstat.tcps_rcvshort++; 291 return; 292 } 293 } 294 /* 295 * Calculate checksum of extended TCP header and data, 296 * by adjusting the checksum for missing parts of the header. 297 */ 298 m->m_data += clnp_len; 299 m->m_len -= clnp_len; 300 tlen = m->m_pkthdr.len -= clnp_len; 301 m->m_data -= sizeof(struct ip); 302 m->m_len += sizeof(struct ip); 303 m->m_pkthdr.len += sizeof(struct ip); 304 /* 305 * The reassembly code assumes it will be overwriting a useless 306 * part of the packet, which is why we need to have it point 307 * into the packet itself. 308 * 309 * Check to see if the data is properly alligned 310 * so that we can save copying the tcp header. 311 * This code knows way too much about the structure of mbufs! 312 */ 313 off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ? 314 (m->m_data - m->m_ext.ext_buf) : (m->m_data - m->m_pktdat))); 315 if (off) { 316 struct mbuf *m0 = m_gethdr(M_DONTWAIT, MT_DATA); 317 if (m0 == 0) { 318 goto drop; 319 } 320 m0->m_data += max_linkhdr; 321 bcopy(mtod(m, caddr_t) + sizeof(struct ip), 322 mtod(m0, caddr_t) + sizeof(struct ip), 323 sizeof(struct tcphdr)); 324 m->m_data += sizeof(struct tcpiphdr); 325 m0->m_next = m; 326 m0->m_pkthdr = m->m_pkthdr; 327 m0->m_flags = m->m_flags & M_COPYFLAGS; 328 m0->m_len = sizeof(struct tcpiphdr); 329 m = m0; 330 } 331 ti = mtod(m, struct tcpiphdr *); 332 ti->ti_src.s_addr = tuba_table[findex]->tc_sum_in; 333 ti->ti_dst.s_addr = tuba_table[lindex]->tc_sum_in; 334 ti->ti_prev = ti->ti_next = 0; 335 ti->ti_x1 = 0; ti->ti_pr = ISOPROTO_TCP; 336 ti->ti_len = htons((u_short)tlen); 337 if (ti->ti_sum = in_cksum(m, m->m_pkthdr.len)) { 338 tcpstat.tcps_rcvbadsum++; 339 tuba_badcksum(); 340 goto drop; 341 } 342 if (tuba_noisy) 343 printf("Hurray!\n"); 344 ti->ti_src.s_addr = findex; 345 ti->ti_dst.s_addr = lindex; 346 /* 347 * Now include the rest of TCP input 348 */ 349 #define TUBA_INCLUDE 350 #define in_pcbconnect tuba_pcbconnect 351 352 #include <netinet/tcp_input.c> 353 } 354