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.3 (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 static struct sockaddr_iso null_siso = { sizeof(null_siso), AF_ISO, }; 44 /* 45 * Tuba initialization 46 */ 47 tuba_init() 48 { 49 #define TUBAHDRSIZE (3 /*LLC*/ + 9 /*CLNP Fixed*/ + 42 /*Addresses*/ \ 50 + 6 /*CLNP Segment*/ + 20 /*TCP*/) 51 extern struct isopcb tuba_isopcb; 52 53 tuba_isopcb.isop_next = tuba_isopcb.isop_prev = &tuba_isopcb; 54 tuba_isopcb.isop_faddr = &tuba_isop.isop_sfaddr; 55 tuba_isopcb.isop_laddr = &tuba_isop.isop_sladdr; 56 if (max_protohdr < TUBAHDRSIZE) 57 max_protohdr = TUBAHDRSIZE; 58 if (max_linkhdr + TUBAHDRSIZE > MHLEN) 59 panic("tuba_init"); 60 tuba_timer_init(); 61 } 62 63 static void 64 tuba_getaddr(error, sum, siso, index) 65 int *error; 66 u_long *sum; 67 struct sockaddr_iso *siso; 68 u_long index; 69 { 70 register struct tuba_cache *tc; 71 if (index < tuba_table_size && (tc = tuba_table[index])) { 72 if (siso) { 73 *siso = null_siso; 74 siso->siso_addr = tc->tc_addr; 75 } 76 sum += tc->tc_sum_out 77 } else 78 *error = 1; 79 } 80 81 tuba_output(m, tp) 82 register struct mbuf *m; 83 struct tcpcb *tp; 84 { 85 struct isopcb *isop; 86 register struct tcpiphdr *n; 87 u_long sum, i; 88 89 if (tp == 0 || (n = tp->tp_template) == 0) { 90 isop = &tuba_isopcb; 91 i = sum = 0; 92 n = mtod(m, struct tcpiphdr *); 93 tuba_getaddr(&i, &sum, tuba_isop.isop_faddr, n->ti_dst.s_addr); 94 tuba_getaddr(&i, &sum, tuba_isop.isop_laddr, n->ti_src.s_addr); 95 goto adjust; 96 } 97 isop = (struct isopcb *)tp->t_tuba_pcb; 98 if (n->ni_sum == 0) { 99 i = sum = 0; 100 tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, 101 n->ti_dst.s_addr); 102 tuba_getaddr(&i, &sum, (struct sockaddr_iso *)0, 103 n->ti_src.s_addr); 104 ICKSUM(sum, sum); 105 n->ti_sum = sum; 106 n = mtod(m, struct tcpiphdr *); 107 adjust: 108 if (i) { 109 m_freem(m); 110 return (ENOBUFS); 111 } 112 ICKSUM(n->ti_sum, sum + n->ti_sum); 113 } 114 m->m_len -= sizeof (struct ip); 115 m->m_pkthdr.len -= sizeof (struct ip); 116 m->m_data += sizeof (struct ip); 117 return (clnp_output(m, isop, m->m_pkthdr.len, 0)); 118 } 119 120 tuba_refcnt(isop, delta) 121 struct isopcb *isop; 122 { 123 register struct tuba_cache *tc; 124 unsigned index, sum; 125 126 if (delta != 1) 127 delta = -1; 128 if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 || 129 (delta == -1 && isop->isop_tuba_cached == 0) || 130 (delta == 1 && isop->isop_tuba_cached != 0)) 131 return; 132 isop->isop_tuba_cached = (delta == 1); 133 if ((index = tuba_lookup(&isop->isop_faddr.siso_addr)) != 0 && 134 (tc = tuba_cache[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 135 tc->tc_refcnt += delta; 136 if ((index = tuba_lookup(&isop->isop_laddr.siso_addr)) != 0 && 137 (tc = tuba_cache[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0)) 138 tc->tc_refcnt += delta; 139 } 140 141 tuba_pcbdetach(isop) 142 struct isopcb *isop; 143 { 144 if (isop == 0) 145 return; 146 tuba_refcnt(isop, -1); 147 isop->isop_socket = 0; 148 iso_pcbdetach(isop); 149 } 150 151 /* 152 * Avoid in_pcbconnect in faked out tcp_input() 153 */ 154 tuba_pcbconnect(inp, nam) 155 register struct inpcb *inp; 156 struct mbuf *nam; 157 { 158 register struct sockaddr_iso *siso = mtod(m, struct sockaddr_iso *); 159 struct sockaddr_in *sin = mtod(m, struct sockaddr_in *); 160 struct tcpcb *tp = intotcpcb(inp); 161 unsigned index = sin->sin_addr.s_addr; 162 struct tuba_cache *tc = tuba_table[index]; 163 struct isopcb *isop = (struct isopcb *)tp->tp_tuba_pcb; 164 int error; 165 166 inp->inp_faddr.s_addr = index; 167 inp->inp_fport = sin->sin_port; 168 *siso = null_siso; 169 siso->siso_addr = tc->tc_addr; 170 siso->siso_tlen = sizeof(inp->inp_fport); 171 bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport)); 172 nam->m_len = sizeof(*siso); 173 if ((error = iso_pcbconnect(isop, nam)) == 0) 174 tuba_refcnt(isop, 1); 175 return (error); 176 } 177 178 /* 179 * CALLED FROM: 180 * clnp's input routine, indirectly through the protosw. 181 * FUNCTION and ARGUMENTS: 182 * Take a packet (m) from clnp, strip off the clnp header and give it to tcp 183 * or udp. 184 * No return value. 185 */ 186 ProtoHook 187 tpclnp_input(m, src, dst, clnp_len, ce_bit) 188 register struct mbuf *m; 189 struct sockaddr_iso *src, *dst; 190 int clnp_len, ce_bit; 191 { 192 int s = splnet(); 193 unsigned long fix_csum, lindex, findex; 194 register struct tcpiphdr *ti; 195 register struct inpcb *inp; 196 struct mbuf *om = 0; 197 int len, tlen, off; 198 register struct tcpcb *tp = 0; 199 int tiflags; 200 struct socket *so; 201 int todrop, acked, ourfinisacked, needoutput = 0; 202 short ostate; 203 struct in_addr laddr; 204 int dropsocket = 0, iss = 0; 205 206 if ((m->m_flags & M_PKTHDR) == 0) 207 panic("tuba_input"); 208 /* 209 * Do some housekeeping looking up CLNP addresses. 210 * If we are out of space might as well drop the packet now. 211 */ 212 tcpstat.tcps_rcvtotal++; 213 if ((lindex = tuba_lookup(&dst->siso_addr) == 0 || 214 (findex = tuba_lookup(&dst->siso_addr) == 0)) 215 goto drop; 216 /* 217 * Get CLNP and TCP header together in first mbuf. 218 * CLNP gave us an mbuf chain WITH the clnp header pulled up, 219 * and the length of the clnp header. 220 */ 221 len = clnp_len + sizeof(struct tcphdr); 222 if (m->m_len < len) { 223 if ((m = m_pullup(m, len)) == 0) { 224 tcpstat.tcps_rcvshort++; 225 return; 226 } 227 } 228 /* 229 * Calculate checksum of extended TCP header and data, 230 * by adjusting the checksum for missing parts of the header. 231 */ 232 m->m_data += clnp_len; 233 m->m_len -= clnp_len; 234 tlen = m->m_pkthdr.len -= clnp_len; 235 ICKSUM(fix_cksum, tuba_table[findex]->tc_sum_in + htons((u_short)tlen) 236 + tuba_table[lindex]->tc_sum_in + in_cksum(m, tlen)); 237 if (fix_cksum != 0xffff) { 238 tcpstat.tcps_rcvbadsum++; 239 goto drop; 240 } 241 m->m_data -= sizeof(struct ip); 242 m->m_len += sizeof(struct ip); 243 m->m_pkthdr.len += sizeof(struct ip); 244 /* 245 * The reassembly code assumes it will be overwriting a useless 246 * part of the packet, which is why we need to have ti point 247 * into the packet itself. 248 * 249 * Check to see if the data is properly alligned 250 * so that we can save copying the tcp header. 251 * This code knows way too much about the structure of mbufs! 252 */ 253 off = ((sizeof (long) - 1) & ((m->m_flags & EXT) ? 254 (m->m_data - m->m_ext.ext_buf) : (m->m_data - m_pktdat))); 255 if (off) { 256 struct mbuf *m0 = m_gethdr(M_DONTWAIT, MT_DATA) 257 if (m0 == 0) { 258 goto drop; 259 } 260 bcopy(mtod(m, caddr_t) + sizeof(struct ip), 261 mtod(m0, caddr_t) + sizeof(struct ip), 262 sizeof(struct tcphdr)); 263 m->m_data += sizeof(struct tcpiphdr); 264 m0->m_next = m; 265 m0->m_pkthdr = m->m_pkthdr; 266 m0->m_flags = m->m_pkthdr & M_COPYFLAGS; 267 m0->m_len = sizeof(struct tcpiphdr); 268 m = m0; 269 } 270 ti = mtod(m, struct tcpiphdr *); 271 ti->ti_src.s_addr = findex; 272 ti->ti_dst.s_addr = lindex; 273 ti->ti_len = tlen; 274 /* 275 * Now include the rest of TCP input 276 */ 277 #define TUBA_INPUT 278 #define in_pcbconnect tuba_pcbconnect 279 280 #include "../netinet/tcp_input.c" 281 } 282