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.4 (Berkeley) 10/15/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_addr.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 tuba_table_init(); 66 } 67 68 static void 69 tuba_getaddr(error, sum, siso, index) 70 int *error; 71 u_long *sum; 72 struct sockaddr_iso *siso; 73 u_long index; 74 { 75 register struct tuba_cache *tc; 76 if (index < tuba_table_size && (tc = tuba_table[index])) { 77 if (siso) { 78 *siso = null_siso; 79 siso->siso_addr = tc->tc_addr; 80 } 81 sum += tc->tc_sum_out; 82 } else 83 *error = 1; 84 } 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; 92 u_long sum, i; 93 94 if (tp == 0 || (n = tp->t_template) == 0) { 95 isop = &tuba_isopcb; 96 i = sum = 0; 97 n = mtod(m, struct tcpiphdr *); 98 tuba_getaddr(&i, &sum, tuba_isopcb.isop_faddr, 99 n->ti_dst.s_addr); 100 tuba_getaddr(&i, &sum, tuba_isopcb.isop_laddr, 101 n->ti_src.s_addr); 102 goto adjust; 103 } 104 isop = (struct isopcb *)tp->t_tuba_pcb; 105 if (n->ti_sum == 0) { 106 i = sum = 0; 107 tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, 108 n->ti_dst.s_addr); 109 tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, 110 n->ti_src.s_addr); 111 ICKSUM(sum, sum); 112 n->ti_sum = sum; 113 n = mtod(m, struct tcpiphdr *); 114 adjust: 115 if (i) { 116 m_freem(m); 117 return (ENOBUFS); 118 } 119 ICKSUM(n->ti_sum, sum + n->ti_sum); 120 } 121 m->m_len -= sizeof (struct ip); 122 m->m_pkthdr.len -= sizeof (struct ip); 123 m->m_data += sizeof (struct ip); 124 return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 125 } 126 127 tuba_refcnt(isop, delta) 128 struct isopcb *isop; 129 { 130 register struct tuba_cache *tc; 131 unsigned index, sum; 132 133 if (delta != 1) 134 delta = -1; 135 if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 136 (delta == -1 && isop->isop_tuba_cached == 0) || 137 (delta == 1 && isop->isop_tuba_cached != 0)) 138 return; 139 isop->isop_tuba_cached = (delta == 1); 140 if ((index = tuba_lookup(&isop->isop_sfaddr.siso_addr)) != 0 && 141 (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 142 tc->tc_refcnt += delta; 143 if ((index = tuba_lookup(&isop->isop_sladdr.siso_addr)) != 0 && 144 (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 145 tc->tc_refcnt += delta; 146 } 147 148 tuba_pcbdetach(isop) 149 struct isopcb *isop; 150 { 151 if (isop == 0) 152 return; 153 tuba_refcnt(isop, -1); 154 isop->isop_socket = 0; 155 iso_pcbdetach(isop); 156 } 157 158 /* 159 * Avoid in_pcbconnect in faked out tcp_input() 160 */ 161 tuba_pcbconnect(inp, nam) 162 register struct inpcb *inp; 163 struct mbuf *nam; 164 { 165 register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 166 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 167 struct tcpcb *tp = intotcpcb(inp); 168 unsigned index = sin->sin_addr.s_addr; 169 struct tuba_cache *tc = tuba_table[index]; 170 struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb; 171 int error; 172 173 inp->inp_faddr.s_addr = index; 174 inp->inp_fport = sin->sin_port; 175 *siso = null_siso; 176 siso->siso_addr = tc->tc_addr; 177 siso->siso_tlen = sizeof(inp->inp_fport); 178 bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 179 nam->m_len = sizeof(*siso); 180 if ((error = iso_pcbconnect(isop, nam)) == 0) 181 tuba_refcnt(isop, 1); 182 return (error); 183 } 184 185 /* 186 * CALLED FROM: 187 * clnp's input routine, indirectly through the protosw. 188 * FUNCTION and ARGUMENTS: 189 * Take a packet (m) from clnp, strip off the clnp header 190 * and do tcp input processing. 191 * No return value. 192 */ 193 tuba_tcpinput(m, src, dst, clnp_len, ce_bit) 194 register struct mbuf *m; 195 struct sockaddr_iso *src, *dst; 196 int clnp_len, ce_bit; 197 { 198 int s = splnet(); 199 unsigned long fix_cksum, lindex, findex; 200 register struct tcpiphdr *ti; 201 register struct inpcb *inp; 202 struct mbuf *om = 0; 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 panic("tuba_input"); 214 /* 215 * Do some housekeeping looking up CLNP addresses. 216 * If we are out of space might as well drop the packet now. 217 */ 218 tcpstat.tcps_rcvtotal++; 219 if ((lindex = tuba_lookup(&dst->siso_addr) == 0) || 220 (findex = tuba_lookup(&dst->siso_addr) == 0)) 221 goto drop; 222 /* 223 * Get CLNP and TCP header together in first mbuf. 224 * CLNP gave us an mbuf chain WITH the clnp header pulled up, 225 * and the length of the clnp header. 226 */ 227 len = clnp_len + sizeof(struct tcphdr); 228 if (m->m_len < len) { 229 if ((m = m_pullup(m, len)) == 0) { 230 tcpstat.tcps_rcvshort++; 231 return; 232 } 233 } 234 /* 235 * Calculate checksum of extended TCP header and data, 236 * by adjusting the checksum for missing parts of the header. 237 */ 238 m->m_data += clnp_len; 239 m->m_len -= clnp_len; 240 tlen = m->m_pkthdr.len -= clnp_len; 241 ICKSUM(fix_cksum, tuba_table[findex]->tc_sum_in + htons((u_short)tlen) 242 + tuba_table[lindex]->tc_sum_in + in_cksum(m, tlen)); 243 if (fix_cksum != 0xffff) { 244 tcpstat.tcps_rcvbadsum++; 245 goto drop; 246 } 247 m->m_data -= sizeof(struct ip); 248 m->m_len += sizeof(struct ip); 249 m->m_pkthdr.len += sizeof(struct ip); 250 /* 251 * The reassembly code assumes it will be overwriting a useless 252 * part of the packet, which is why we need to have ti 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) { 262 struct mbuf *m0 = m_gethdr(M_DONTWAIT, MT_DATA); 263 if (m0 == 0) { 264 goto drop; 265 } 266 bcopy(mtod(m, caddr_t) + sizeof(struct ip), 267 mtod(m0, caddr_t) + sizeof(struct ip), 268 sizeof(struct tcphdr)); 269 m->m_data += sizeof(struct tcpiphdr); 270 m0->m_next = m; 271 m0->m_pkthdr = m->m_pkthdr; 272 m0->m_flags = m->m_flags & M_COPYFLAGS; 273 m0->m_len = sizeof(struct tcpiphdr); 274 m = m0; 275 } 276 ti = mtod(m, struct tcpiphdr *); 277 ti->ti_src.s_addr = findex; 278 ti->ti_dst.s_addr = lindex; 279 ti->ti_len = tlen; 280 /* 281 * Now include the rest of TCP input 282 */ 283 #define TUBA_INCLUDE 284 #define in_pcbconnect tuba_pcbconnect 285 286 #include <netinet/tcp_input.c> 287 } 288