- Timestamp:
- Dec 14, 2008 8:57:47 PM (16 years ago)
- Location:
- trunk/src/VBox/Devices/Network/slirp
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/if.c
r14951 r15472 13 13 static void ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) 14 14 { 15 16 17 18 15 ifm->ifs_next = ifmhead->ifs_next; 16 ifmhead->ifs_next = ifm; 17 ifm->ifs_prev = ifmhead; 18 ifm->ifs_next->ifs_prev = ifm; 19 19 } 20 20 21 21 static void ifs_remque(struct mbuf *ifm) 22 22 { 23 24 23 ifm->ifs_prev->ifs_next = ifm->ifs_next; 24 ifm->ifs_next->ifs_prev = ifm->ifs_prev; 25 25 } 26 26 … … 28 28 if_init(PNATState pData) 29 29 { 30 31 32 33 34 35 36 37 38 39 /*sl_compress_init(&comp_s); */40 30 /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ 31 if_maxlinkhdr = 2 + 14 + 40; 32 if_queued = 0; 33 if_thresh = 10; 34 if_mtu = 1500; 35 if_mru = 1500; 36 if_comp = IF_AUTOCOMP; 37 if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq; 38 if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq; 39 /* sl_compress_init(&comp_s); */ 40 next_m = &if_batchq; 41 41 } 42 42 … … 57 57 if_output(PNATState pData, struct socket *so, struct mbuf *ifm) 58 58 { 59 struct mbuf *ifq; 60 int on_fastq = 1; 61 62 DEBUG_CALL("if_output"); 63 DEBUG_ARG("so = %lx", (long)so); 64 DEBUG_ARG("ifm = %lx", (long)ifm); 65 59 struct mbuf *ifq; 60 int on_fastq = 1; 61 62 DEBUG_CALL("if_output"); 63 DEBUG_ARG("so = %lx", (long)so); 64 DEBUG_ARG("ifm = %lx", (long)ifm); 65 66 /* 67 * First remove the mbuf from m_usedlist, 68 * since we're gonna use m_next and m_prev ourselves 69 * XXX Shouldn't need this, gotta change dtom() etc. 70 */ 71 if (ifm->m_flags & M_USEDLIST) 72 { 73 remque(pData, ifm); 74 ifm->m_flags &= ~M_USEDLIST; 75 } 76 77 /* 78 * See if there's already a batchq list for this session. 79 * This can include an interactive session, which should go on fastq, 80 * but gets too greedy... hence it'll be downgraded from fastq to batchq. 81 * We mustn't put this packet back on the fastq (or we'll send it out of order) 82 * XXX add cache here? 83 */ 84 for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev) 85 { 86 if (so == ifq->ifq_so) 87 { 88 /* A match! */ 89 ifm->ifq_so = so; 90 ifs_insque(ifm, ifq->ifs_prev); 91 goto diddit; 92 } 93 } 94 95 /* No match, check which queue to put it on */ 96 if (so && (so->so_iptos & IPTOS_LOWDELAY)) 97 { 98 ifq = if_fastq.ifq_prev; 99 on_fastq = 1; 66 100 /* 67 * First remove the mbuf from m_usedlist, 68 * since we're gonna use m_next and m_prev ourselves 69 * XXX Shouldn't need this, gotta change dtom() etc. 101 * Check if this packet is a part of the last 102 * packet's session 70 103 */ 71 if (ifm->m_flags & M_USEDLIST) { 72 remque(pData, ifm); 73 ifm->m_flags &= ~M_USEDLIST; 74 } 75 104 if (ifq->ifq_so == so) 105 { 106 ifm->ifq_so = so; 107 ifs_insque(ifm, ifq->ifs_prev); 108 goto diddit; 109 } 110 } 111 else 112 ifq = if_batchq.ifq_prev; 113 114 /* Create a new doubly linked list for this session */ 115 ifm->ifq_so = so; 116 ifs_init(ifm); 117 insque(pData, ifm, ifq); 118 119 diddit: 120 ++if_queued; 121 122 if (so) 123 { 124 /* Update *_queued */ 125 so->so_queued++; 126 so->so_nqueued++; 76 127 /* 77 * See if there's already a batchq list for this session.78 * This can include an interactive session, which should go on fastq,79 * but gets too greedy... hence it'll be downgraded from fastq to batchq.80 * We mustn't put this packet back on the fastq (or we'll send it out of order)81 * XXX add cache here?128 * Check if the interactive session should be downgraded to 129 * the batchq. A session is downgraded if it has queued 6 130 * packets without pausing, and at least 3 of those packets 131 * have been sent over the link 132 * (XXX These are arbitrary numbers, probably not optimal..) 82 133 */ 83 for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev) { 84 if (so == ifq->ifq_so) { 85 /* A match! */ 86 ifm->ifq_so = so; 87 ifs_insque(ifm, ifq->ifs_prev); 88 goto diddit; 89 } 90 } 91 92 /* No match, check which queue to put it on */ 93 if (so && (so->so_iptos & IPTOS_LOWDELAY)) { 94 ifq = if_fastq.ifq_prev; 95 on_fastq = 1; 96 /* 97 * Check if this packet is a part of the last 98 * packet's session 99 */ 100 if (ifq->ifq_so == so) { 101 ifm->ifq_so = so; 102 ifs_insque(ifm, ifq->ifs_prev); 103 goto diddit; 104 } 105 } else 106 ifq = if_batchq.ifq_prev; 107 108 /* Create a new doubly linked list for this session */ 109 ifm->ifq_so = so; 110 ifs_init(ifm); 111 insque(pData, ifm, ifq); 112 113 diddit: 114 ++if_queued; 115 116 if (so) { 117 /* Update *_queued */ 118 so->so_queued++; 119 so->so_nqueued++; 120 /* 121 * Check if the interactive session should be downgraded to 122 * the batchq. A session is downgraded if it has queued 6 123 * packets without pausing, and at least 3 of those packets 124 * have been sent over the link 125 * (XXX These are arbitrary numbers, probably not optimal..) 126 */ 127 if (on_fastq && ((so->so_nqueued >= 6) && 128 (so->so_nqueued - so->so_queued) >= 3)) { 129 130 /* Remove from current queue... */ 131 remque(pData, ifm->ifs_next); 132 133 /* ...And insert in the new. That'll teach ya! */ 134 insque(pData, ifm->ifs_next, &if_batchq); 135 } 136 } 134 if (on_fastq 135 && so->so_nqueued >= 6 136 && (so->so_nqueued - so->so_queued) >= 3) 137 { 138 /* Remove from current queue... */ 139 remque(pData, ifm->ifs_next); 140 141 /* ...And insert in the new. That'll teach ya! */ 142 insque(pData, ifm->ifs_next, &if_batchq); 143 } 144 } 137 145 138 146 #ifndef FULL_BOLT 139 /* 140 * This prevents us from malloc()ing too many mbufs 141 */ 142 if (link_up) { 143 /* if_start will check towrite */ 144 if_start(pData); 145 } 147 /* 148 * This prevents us from malloc()ing too many mbufs 149 */ 150 if (link_up) 151 { 152 /* if_start will check towrite */ 153 if_start(pData); 154 } 146 155 #endif 147 156 } … … 162 171 if_start(PNATState pData) 163 172 { 164 struct mbuf *ifm, *ifqt; 165 166 DEBUG_CALL("if_start"); 167 168 if (if_queued == 0) 169 return; /* Nothing to do */ 170 171 again: 173 struct mbuf *ifm, *ifqt; 174 175 DEBUG_CALL("if_start"); 176 177 if (!if_queued) 178 return; /* Nothing to do */ 179 180 for (;;) 181 { 172 182 /* check if we can really output */ 173 183 if (!slirp_can_output(pData->pvUser)) … … 178 188 * If there's something in the fastq, select it immediately 179 189 */ 180 if (if_fastq.ifq_next != &if_fastq) { 181 ifm = if_fastq.ifq_next; 182 } else { 183 /* Nothing on fastq, see if next_m is valid */ 184 if (next_m != &if_batchq) 185 ifm = next_m; 186 else 187 ifm = if_batchq.ifq_next; 188 189 /* Set which packet to send on next iteration */ 190 next_m = ifm->ifq_next; 190 if (if_fastq.ifq_next != &if_fastq) 191 ifm = if_fastq.ifq_next; 192 else 193 { 194 /* Nothing on fastq, see if next_m is valid */ 195 if (next_m != &if_batchq) 196 ifm = next_m; 197 else 198 ifm = if_batchq.ifq_next; 199 200 /* Set which packet to send on next iteration */ 201 next_m = ifm->ifq_next; 191 202 } 192 203 /* Remove it from the queue */ … … 196 207 197 208 /* If there are more packets for this session, re-queue them */ 198 if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { 199 insque(pData, ifm->ifs_next, ifqt); 200 ifs_remque(ifm); 209 if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) 210 { 211 insque(pData, ifm->ifs_next, ifqt); 212 ifs_remque(ifm); 201 213 } 202 214 203 215 /* Update so_queued */ 204 if (ifm->ifq_so) { 205 if (--ifm->ifq_so->so_queued == 0) 206 /* If there's no more queued, reset nqueued */ 207 ifm->ifq_so->so_nqueued = 0; 216 if (ifm->ifq_so) 217 { 218 if (--ifm->ifq_so->so_queued == 0) 219 /* If there's no more queued, reset nqueued */ 220 ifm->ifq_so->so_nqueued = 0; 208 221 } 209 222 … … 213 226 m_free(pData, ifm); 214 227 215 if (if_queued) 216 goto again; 217 } 228 if (!if_queued) 229 return; 230 } 231 } -
trunk/src/VBox/Devices/Network/slirp/tcp_input.c
r15453 r15472 73 73 tcp_reass(PNATState pData, struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) 74 74 { 75 struct tseg_qent *q; 76 struct tseg_qent *p = NULL; 77 struct tseg_qent *nq; 78 struct tseg_qent *te = NULL; 79 struct socket *so = tp->t_socket; 80 int flags; 81 82 /* 83 * XXX: tcp_reass() is rather inefficient with its data structures 84 * and should be rewritten (see NetBSD for optimizations). While 85 * doing that it should move to its own file tcp_reass.c. 86 */ 87 88 /* 89 * Call with th==NULL after become established to 90 * force pre-ESTABLISHED data up to user socket. 91 */ 92 if (th == NULL) 93 goto present; 94 95 /* 96 * Limit the number of segments in the reassembly queue to prevent 97 * holding on to too many segments (and thus running out of mbufs). 98 * Make sure to let the missing segment through which caused this 99 * queue. Always keep one global queue entry spare to be able to 100 * process the missing segment. 101 */ 102 if (th->th_seq != tp->rcv_nxt && 103 (tcp_reass_qsize + 1 >= tcp_reass_maxseg || 104 tp->t_segqlen >= tcp_reass_maxqlen)) { 105 tcp_reass_overflows++; 106 tcpstat.tcps_rcvmemdrop++; 75 struct tseg_qent *q; 76 struct tseg_qent *p = NULL; 77 struct tseg_qent *nq; 78 struct tseg_qent *te = NULL; 79 struct socket *so = tp->t_socket; 80 int flags; 81 82 /* 83 * XXX: tcp_reass() is rather inefficient with its data structures 84 * and should be rewritten (see NetBSD for optimizations). While 85 * doing that it should move to its own file tcp_reass.c. 86 */ 87 88 /* 89 * Call with th==NULL after become established to 90 * force pre-ESTABLISHED data up to user socket. 91 */ 92 if (th == NULL) 93 goto present; 94 95 /* 96 * Limit the number of segments in the reassembly queue to prevent 97 * holding on to too many segments (and thus running out of mbufs). 98 * Make sure to let the missing segment through which caused this 99 * queue. Always keep one global queue entry spare to be able to 100 * process the missing segment. 101 */ 102 if ( th->th_seq != tp->rcv_nxt 103 && ( tcp_reass_qsize + 1 >= tcp_reass_maxseg 104 || tp->t_segqlen >= tcp_reass_maxqlen)) 105 { 106 tcp_reass_overflows++; 107 tcpstat.tcps_rcvmemdrop++; 108 m_freem(pData, m); 109 *tlenp = 0; 110 return (0); 111 } 112 113 /* 114 * Allocate a new queue entry. If we can't, or hit the zone limit 115 * just drop the pkt. 116 */ 117 te = malloc(sizeof(struct tseg_qent)); 118 if (te == NULL) 119 { 120 tcpstat.tcps_rcvmemdrop++; 121 m_freem(pData, m); 122 *tlenp = 0; 123 return (0); 124 } 125 tp->t_segqlen++; 126 tcp_reass_qsize++; 127 128 /* 129 * Find a segment which begins after this one does. 130 */ 131 LIST_FOREACH(q, &tp->t_segq, tqe_q) 132 { 133 if (SEQ_GT(q->tqe_th->th_seq, th->th_seq)) 134 break; 135 p = q; 136 } 137 138 /* 139 * If there is a preceding segment, it may provide some of 140 * our data already. If so, drop the data from the incoming 141 * segment. If it provides all of our data, drop us. 142 */ 143 if (p != NULL) 144 { 145 int i; 146 /* conversion to int (in i) handles seq wraparound */ 147 i = p->tqe_th->th_seq + p->tqe_len - th->th_seq; 148 if (i > 0) 149 { 150 if (i >= *tlenp) 151 { 152 tcpstat.tcps_rcvduppack++; 153 tcpstat.tcps_rcvdupbyte += *tlenp; 107 154 m_freem(pData, m); 108 *tlenp = 0; 109 return (0); 110 } 111 112 /* 113 * Allocate a new queue entry. If we can't, or hit the zone limit 114 * just drop the pkt. 115 */ 116 te = malloc(sizeof(struct tseg_qent)); 117 if (te == NULL) { 118 tcpstat.tcps_rcvmemdrop++; 119 m_freem(pData, m); 120 *tlenp = 0; 121 return (0); 122 } 123 tp->t_segqlen++; 124 tcp_reass_qsize++; 125 126 /* 127 * Find a segment which begins after this one does. 128 */ 129 LIST_FOREACH(q, &tp->t_segq, tqe_q) { 130 if (SEQ_GT(q->tqe_th->th_seq, th->th_seq)) 131 break; 132 p = q; 133 } 134 135 /* 136 * If there is a preceding segment, it may provide some of 137 * our data already. If so, drop the data from the incoming 138 * segment. If it provides all of our data, drop us. 139 */ 140 if (p != NULL) { 141 int i; 142 /* conversion to int (in i) handles seq wraparound */ 143 i = p->tqe_th->th_seq + p->tqe_len - th->th_seq; 144 if (i > 0) { 145 if (i >= *tlenp) { 146 tcpstat.tcps_rcvduppack++; 147 tcpstat.tcps_rcvdupbyte += *tlenp; 148 m_freem(pData, m); 149 free(te); 150 tp->t_segqlen--; 151 tcp_reass_qsize--; 152 /* 153 * Try to present any queued data 154 * at the left window edge to the user. 155 * This is needed after the 3-WHS 156 * completes. 157 */ 158 goto present; /* ??? */ 159 } 160 m_adj(m, i); 161 *tlenp -= i; 162 th->th_seq += i; 163 } 164 } 165 tcpstat.tcps_rcvoopack++; 166 tcpstat.tcps_rcvoobyte += *tlenp; 167 168 /* 169 * While we overlap succeeding segments trim them or, 170 * if they are completely covered, dequeue them. 171 */ 172 while (q) { 173 int i = (th->th_seq + *tlenp) - q->tqe_th->th_seq; 174 if (i <= 0) 175 break; 176 if (i < q->tqe_len) { 177 q->tqe_th->th_seq += i; 178 q->tqe_len -= i; 179 m_adj(q->tqe_m, i); 180 break; 181 } 182 183 nq = LIST_NEXT(q, tqe_q); 184 LIST_REMOVE(q, tqe_q); 185 m_freem(pData, q->tqe_m); 186 free(q); 155 free(te); 187 156 tp->t_segqlen--; 188 157 tcp_reass_qsize--; 189 q = nq; 190 } 191 192 /* Insert the new segment queue entry into place. */ 193 te->tqe_m = m; 194 te->tqe_th = th; 195 te->tqe_len = *tlenp; 196 197 if (p == NULL) { 198 LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q); 199 } else { 200 LIST_INSERT_AFTER(p, te, tqe_q); 201 } 158 /* 159 * Try to present any queued data 160 * at the left window edge to the user. 161 * This is needed after the 3-WHS 162 * completes. 163 */ 164 goto present; /* ??? */ 165 } 166 m_adj(m, i); 167 *tlenp -= i; 168 th->th_seq += i; 169 } 170 } 171 tcpstat.tcps_rcvoopack++; 172 tcpstat.tcps_rcvoobyte += *tlenp; 173 174 /* 175 * While we overlap succeeding segments trim them or, 176 * if they are completely covered, dequeue them. 177 */ 178 while (q) 179 { 180 int i = (th->th_seq + *tlenp) - q->tqe_th->th_seq; 181 if (i <= 0) 182 break; 183 if (i < q->tqe_len) 184 { 185 q->tqe_th->th_seq += i; 186 q->tqe_len -= i; 187 m_adj(q->tqe_m, i); 188 break; 189 } 190 191 nq = LIST_NEXT(q, tqe_q); 192 LIST_REMOVE(q, tqe_q); 193 m_freem(pData, q->tqe_m); 194 free(q); 195 tp->t_segqlen--; 196 tcp_reass_qsize--; 197 q = nq; 198 } 199 200 /* Insert the new segment queue entry into place. */ 201 te->tqe_m = m; 202 te->tqe_th = th; 203 te->tqe_len = *tlenp; 204 205 if (p == NULL) 206 { 207 LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q); 208 } 209 else 210 { 211 LIST_INSERT_AFTER(p, te, tqe_q); 212 } 202 213 203 214 present: 204 /* 205 * Present data to user, advancing rcv_nxt through 206 * completed sequence space. 215 /* 216 * Present data to user, advancing rcv_nxt through 217 * completed sequence space. 218 */ 219 if (!TCPS_HAVEESTABLISHED(tp->t_state)) 220 return (0); 221 q = LIST_FIRST(&tp->t_segq); 222 if (!q || q->tqe_th->th_seq != tp->rcv_nxt) 223 return (0); 224 do 225 { 226 tp->rcv_nxt += q->tqe_len; 227 flags = q->tqe_th->th_flags & TH_FIN; 228 nq = LIST_NEXT(q, tqe_q); 229 LIST_REMOVE(q, tqe_q); 230 /* XXX: This place should be checked for the same code in 231 * original BSD code for Slirp and current BSD used SS_FCANTRCVMORE 207 232 */ 208 if (!TCPS_HAVEESTABLISHED(tp->t_state)) 209 return (0); 210 q = LIST_FIRST(&tp->t_segq); 211 if (!q || q->tqe_th->th_seq != tp->rcv_nxt) 212 return (0); 213 do { 214 tp->rcv_nxt += q->tqe_len; 215 flags = q->tqe_th->th_flags & TH_FIN; 216 nq = LIST_NEXT(q, tqe_q); 217 LIST_REMOVE(q, tqe_q); 218 /* XXX: This place should be checked for the same code in 219 * original BSD code for Slirp and current BSD used SS_FCANTRCVMORE 220 */ 221 if (so->so_state & SS_FCANTSENDMORE) 222 m_freem(pData, q->tqe_m); 223 else 224 sbappend(pData, so, q->tqe_m); 225 free(q); 226 tp->t_segqlen--; 227 tcp_reass_qsize--; 228 q = nq; 229 } while (q && q->tqe_th->th_seq == tp->rcv_nxt); 230 return (flags); 233 if (so->so_state & SS_FCANTSENDMORE) 234 m_freem(pData, q->tqe_m); 235 else 236 sbappend(pData, so, q->tqe_m); 237 free(q); 238 tp->t_segqlen--; 239 tcp_reass_qsize--; 240 q = nq; 241 } 242 while (q && q->tqe_th->th_seq == tp->rcv_nxt); 243 244 return flags; 231 245 } 232 246 … … 238 252 tcp_input(PNATState pData, register struct mbuf *m, int iphlen, struct socket *inso) 239 253 { 240 struct ip save_ip, *ip; 241 register struct tcpiphdr *ti; 242 caddr_t optp = NULL; 243 int optlen = 0; 244 int len, tlen, off; 245 register struct tcpcb *tp = 0; 246 register int tiflags; 247 struct socket *so = 0; 248 int todrop, acked, ourfinisacked, needoutput = 0; 249 /* int dropsocket = 0; */ 250 int iss = 0; 251 u_long tiwin; 252 /* int ts_present = 0; */ 253 254 DEBUG_CALL("tcp_input"); 255 DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n", 256 (long )m, iphlen, (long )inso )); 254 struct ip save_ip, *ip; 255 register struct tcpiphdr *ti; 256 caddr_t optp = NULL; 257 int optlen = 0; 258 int len, tlen, off; 259 register struct tcpcb *tp = 0; 260 register int tiflags; 261 struct socket *so = 0; 262 int todrop, acked, ourfinisacked, needoutput = 0; 263 /* int dropsocket = 0; */ 264 int iss = 0; 265 u_long tiwin; 266 /* int ts_present = 0; */ 267 268 DEBUG_CALL("tcp_input"); 269 DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n", 270 (long )m, iphlen, (long )inso )); 271 272 /* 273 * If called with m == 0, then we're continuing the connect 274 */ 275 if (m == NULL) 276 { 277 so = inso; 278 279 /* Re-set a few variables */ 280 tp = sototcpcb(so); 281 m = so->so_m; 282 so->so_m = 0; 283 ti = so->so_ti; 284 tiwin = ti->ti_win; 285 tiflags = ti->ti_flags; 286 287 goto cont_conn; 288 } 289 290 tcpstat.tcps_rcvtotal++; 291 /* 292 * Get IP and TCP header together in first mbuf. 293 * Note: IP leaves IP header in first mbuf. 294 */ 295 ti = mtod(m, struct tcpiphdr *); 296 if (iphlen > sizeof(struct ip )) 297 { 298 ip_stripoptions(m, (struct mbuf *)0); 299 iphlen = sizeof(struct ip ); 300 } 301 /* XXX Check if too short */ 302 303 304 /* 305 * Save a copy of the IP header in case we want restore it 306 * for sending an ICMP error message in response. 307 */ 308 ip = mtod(m, struct ip *); 309 save_ip = *ip; 310 save_ip.ip_len+= iphlen; 311 312 /* 313 * Checksum extended TCP header and data. 314 */ 315 tlen = ((struct ip *)ti)->ip_len; 316 memset(ti->ti_x1, 0, 9); 317 ti->ti_len = htons((u_int16_t)tlen); 318 len = sizeof(struct ip ) + tlen; 319 /* keep checksum for ICMP reply 320 * ti->ti_sum = cksum(m, len); 321 * if (ti->ti_sum) { */ 322 if (cksum(m, len)) 323 { 324 tcpstat.tcps_rcvbadsum++; 325 goto drop; 326 } 327 328 /* 329 * Check that TCP offset makes sense, 330 * pull out TCP options and adjust length. XXX 331 */ 332 off = ti->ti_off << 2; 333 if ( off < sizeof (struct tcphdr) 334 || off > tlen) 335 { 336 tcpstat.tcps_rcvbadoff++; 337 goto drop; 338 } 339 tlen -= off; 340 ti->ti_len = tlen; 341 if (off > sizeof (struct tcphdr)) 342 { 343 optlen = off - sizeof (struct tcphdr); 344 optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr); 257 345 258 346 /* 259 * If called with m == 0, then we're continuing the connect 347 * Do quick retrieval of timestamp options ("options 348 * prediction?"). If timestamp is the only option and it's 349 * formatted as recommended in RFC 1323 appendix A, we 350 * quickly get the values now and not bother calling 351 * tcp_dooptions(), etc. 260 352 */ 261 if (m == NULL) { 262 so = inso; 263 264 /* Re-set a few variables */ 265 tp = sototcpcb(so); 266 m = so->so_m; 267 so->so_m = 0; 268 ti = so->so_ti; 269 tiwin = ti->ti_win; 270 tiflags = ti->ti_flags; 271 272 goto cont_conn; 273 } 274 275 276 tcpstat.tcps_rcvtotal++; 277 /* 278 * Get IP and TCP header together in first mbuf. 279 * Note: IP leaves IP header in first mbuf. 280 */ 281 ti = mtod(m, struct tcpiphdr *); 282 if (iphlen > sizeof(struct ip )) { 283 ip_stripoptions(m, (struct mbuf *)0); 284 iphlen=sizeof(struct ip ); 285 } 286 /* XXX Check if too short */ 287 288 289 /* 290 * Save a copy of the IP header in case we want restore it 291 * for sending an ICMP error message in response. 292 */ 293 ip=mtod(m, struct ip *); 294 save_ip = *ip; 295 save_ip.ip_len+= iphlen; 296 297 /* 298 * Checksum extended TCP header and data. 299 */ 300 tlen = ((struct ip *)ti)->ip_len; 301 memset(ti->ti_x1, 0, 9); 302 ti->ti_len = htons((u_int16_t)tlen); 303 len = sizeof(struct ip ) + tlen; 304 /* keep checksum for ICMP reply 305 * ti->ti_sum = cksum(m, len); 306 * if (ti->ti_sum) { */ 307 if(cksum(m, len)) { 308 tcpstat.tcps_rcvbadsum++; 309 goto drop; 310 } 311 312 /* 313 * Check that TCP offset makes sense, 314 * pull out TCP options and adjust length. XXX 315 */ 316 off = ti->ti_off << 2; 317 if (off < sizeof (struct tcphdr) || off > tlen) { 318 tcpstat.tcps_rcvbadoff++; 319 goto drop; 320 } 321 tlen -= off; 322 ti->ti_len = tlen; 323 if (off > sizeof (struct tcphdr)) { 324 optlen = off - sizeof (struct tcphdr); 325 optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr); 326 327 /* 328 * Do quick retrieval of timestamp options ("options 329 * prediction?"). If timestamp is the only option and it's 330 * formatted as recommended in RFC 1323 appendix A, we 331 * quickly get the values now and not bother calling 332 * tcp_dooptions(), etc. 333 */ 334 /* if ((optlen == TCPOLEN_TSTAMP_APPA || 335 * (optlen > TCPOLEN_TSTAMP_APPA && 336 * optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) && 337 * *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) && 338 * (ti->ti_flags & TH_SYN) == 0) { 339 * ts_present = 1; 340 * ts_val = ntohl(*(u_int32_t *)(optp + 4)); 341 * ts_ecr = ntohl(*(u_int32_t *)(optp + 8)); 342 * optp = NULL; / * we've parsed the options * / 343 * } 344 */ 345 } 346 tiflags = ti->ti_flags; 347 348 /* 349 * Convert TCP protocol specific fields to host format. 350 */ 351 NTOHL(ti->ti_seq); 352 NTOHL(ti->ti_ack); 353 NTOHS(ti->ti_win); 354 NTOHS(ti->ti_urp); 355 356 /* 357 * Drop TCP, IP headers and TCP options. 358 */ 359 m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 360 m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 361 362 /* 363 * Locate pcb for segment. 364 */ 353 #if 0 354 if (( optlen == TCPOLEN_TSTAMP_APPA 355 || ( optlen > TCPOLEN_TSTAMP_APPA 356 && optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) && 357 *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) && 358 (ti->ti_flags & TH_SYN) == 0) 359 { 360 ts_present = 1; 361 ts_val = ntohl(*(u_int32_t *)(optp + 4)); 362 ts_ecr = ntohl(*(u_int32_t *)(optp + 8)); 363 optp = NULL; / * we have parsed the options * / 364 } 365 #endif 366 } 367 tiflags = ti->ti_flags; 368 369 /* 370 * Convert TCP protocol specific fields to host format. 371 */ 372 NTOHL(ti->ti_seq); 373 NTOHL(ti->ti_ack); 374 NTOHS(ti->ti_win); 375 NTOHS(ti->ti_urp); 376 377 /* 378 * Drop TCP, IP headers and TCP options. 379 */ 380 m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 381 m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 382 383 /* 384 * Locate pcb for segment. 385 */ 365 386 findso: 366 so = tcp_last_so; 367 if (so->so_fport != ti->ti_dport || 368 so->so_lport != ti->ti_sport || 369 so->so_laddr.s_addr != ti->ti_src.s_addr || 370 so->so_faddr.s_addr != ti->ti_dst.s_addr) { 371 so = solookup(&tcb, ti->ti_src, ti->ti_sport, 372 ti->ti_dst, ti->ti_dport); 373 if (so) 374 tcp_last_so = so; 375 ++tcpstat.tcps_socachemiss; 376 } 377 378 /* 379 * If the state is CLOSED (i.e., TCB does not exist) then 380 * all data in the incoming segment is discarded. 381 * If the TCB exists but is in CLOSED state, it is embryonic, 382 * but should either do a listen or a connect soon. 383 * 384 * state == CLOSED means we've done socreate() but haven't 385 * attached it to a protocol yet... 386 * 387 * XXX If a TCB does not exist, and the TH_SYN flag is 388 * the only flag set, then create a session, mark it 389 * as if it was LISTENING, and continue... 390 */ 391 if (so == 0) { 392 if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN) 387 so = tcp_last_so; 388 if ( so->so_fport != ti->ti_dport 389 || so->so_lport != ti->ti_sport 390 || so->so_laddr.s_addr != ti->ti_src.s_addr 391 || so->so_faddr.s_addr != ti->ti_dst.s_addr) 392 { 393 so = solookup(&tcb, ti->ti_src, ti->ti_sport, 394 ti->ti_dst, ti->ti_dport); 395 if (so) 396 tcp_last_so = so; 397 ++tcpstat.tcps_socachemiss; 398 } 399 400 /* 401 * If the state is CLOSED (i.e., TCB does not exist) then 402 * all data in the incoming segment is discarded. 403 * If the TCB exists but is in CLOSED state, it is embryonic, 404 * but should either do a listen or a connect soon. 405 * 406 * state == CLOSED means we've done socreate() but haven't 407 * attached it to a protocol yet... 408 * 409 * XXX If a TCB does not exist, and the TH_SYN flag is 410 * the only flag set, then create a session, mark it 411 * as if it was LISTENING, and continue... 412 */ 413 if (so == 0) 414 { 415 if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN) 393 416 goto dropwithreset; 394 417 395 418 if ((so = socreate()) == NULL) 396 419 goto dropwithreset; 397 if (tcp_attach(pData, so) < 0) { 420 if (tcp_attach(pData, so) < 0) 421 { 398 422 free(so); /* Not sofree (if it failed, it's not insqued) */ 399 423 goto dropwithreset; 400 401 402 403 404 405 /*tcp_last_so = so; */ /* XXX ? */406 /*tp = sototcpcb(so); */407 408 409 410 411 412 413 424 } 425 426 sbreserve(&so->so_snd, tcp_sndspace); 427 sbreserve(&so->so_rcv, tcp_rcvspace); 428 429 /* tcp_last_so = so; */ /* XXX ? */ 430 /* tp = sototcpcb(so); */ 431 432 so->so_laddr = ti->ti_src; 433 so->so_lport = ti->ti_sport; 434 so->so_faddr = ti->ti_dst; 435 so->so_fport = ti->ti_dport; 436 437 if ((so->so_iptos = tcp_tos(so)) == 0) 414 438 so->so_iptos = ((struct ip *)ti)->ip_tos; 415 439 416 tp = sototcpcb(so);417 tp->t_state = TCPS_LISTEN;418 }419 420 /*421 * If this is a still-connecting socket, this probably422 * a retransmit of the SYN. Whether it's a retransmit SYN423 * or something else, we nuke it.424 */425 if (so->so_state & SS_ISFCONNECTING)426 goto drop;427 428 440 tp = sototcpcb(so); 429 430 /* XXX Should never fail */ 431 if (tp == 0) 432 goto dropwithreset; 433 if (tp->t_state == TCPS_CLOSED) 434 goto drop; 435 436 /* Unscale the window into a 32-bit value. */ 437 /* if ((tiflags & TH_SYN) == 0) 438 * tiwin = ti->ti_win << tp->snd_scale; 439 * else 441 tp->t_state = TCPS_LISTEN; 442 } 443 444 /* 445 * If this is a still-connecting socket, this probably 446 * a retransmit of the SYN. Whether it's a retransmit SYN 447 * or something else, we nuke it. 448 */ 449 if (so->so_state & SS_ISFCONNECTING) 450 goto drop; 451 452 tp = sototcpcb(so); 453 454 /* XXX Should never fail */ 455 if (tp == 0) 456 goto dropwithreset; 457 if (tp->t_state == TCPS_CLOSED) 458 goto drop; 459 460 /* Unscale the window into a 32-bit value. */ 461 /* if ((tiflags & TH_SYN) == 0) 462 * tiwin = ti->ti_win << tp->snd_scale; 463 * else 440 464 */ 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 465 tiwin = ti->ti_win; 466 467 /* 468 * Segment received on connection. 469 * Reset idle time and keep-alive timer. 470 */ 471 tp->t_idle = 0; 472 if (so_options) 473 tp->t_timer[TCPT_KEEP] = tcp_keepintvl; 474 else 475 tp->t_timer[TCPT_KEEP] = tcp_keepidle; 476 477 /* 478 * Process options if not in LISTEN state, 479 * else do it below (after getting remote address). 480 */ 481 if (optp && tp->t_state != TCPS_LISTEN) 482 tcp_dooptions(pData, tp, (u_char *)optp, optlen, ti); 459 483 /* , */ 460 484 /* &ts_present, &ts_val, &ts_ecr); */ 461 485 486 /* 487 * Header prediction: check for the two common cases 488 * of a uni-directional data xfer. If the packet has 489 * no control flags, is in-sequence, the window didn't 490 * change and we're not retransmitting, it's a 491 * candidate. If the length is zero and the ack moved 492 * forward, we're the sender side of the xfer. Just 493 * free the data acked & wake any higher level process 494 * that was blocked waiting for space. If the length 495 * is non-zero and the ack didn't move, we're the 496 * receiver side. If we're getting packets in-order 497 * (the reassembly queue is empty), add the data to 498 * the socket buffer and note that we need a delayed ack. 499 * 500 * XXX Some of these tests are not needed 501 * eg: the tiwin == tp->snd_wnd prevents many more 502 * predictions.. with no *real* advantage.. 503 */ 504 if ( tp->t_state == TCPS_ESTABLISHED 505 && (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK 506 /* && (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) */ 507 && ti->ti_seq == tp->rcv_nxt 508 && tiwin && tiwin == tp->snd_wnd 509 && tp->snd_nxt == tp->snd_max) 510 { 462 511 /* 463 * Header prediction: check for the two common cases 464 * of a uni-directional data xfer. If the packet has 465 * no control flags, is in-sequence, the window didn't 466 * change and we're not retransmitting, it's a 467 * candidate. If the length is zero and the ack moved 468 * forward, we're the sender side of the xfer. Just 469 * free the data acked & wake any higher level process 470 * that was blocked waiting for space. If the length 471 * is non-zero and the ack didn't move, we're the 472 * receiver side. If we're getting packets in-order 473 * (the reassembly queue is empty), add the data to 474 * the socket buffer and note that we need a delayed ack. 475 * 476 * XXX Some of these tests are not needed 477 * eg: the tiwin == tp->snd_wnd prevents many more 478 * predictions.. with no *real* advantage.. 512 * If last ACK falls within this segment's sequence numbers, 513 * record the timestamp. 479 514 */ 480 if (tp->t_state == TCPS_ESTABLISHED && 481 (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK && 482 /* (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */ 483 ti->ti_seq == tp->rcv_nxt && 484 tiwin && tiwin == tp->snd_wnd && 485 tp->snd_nxt == tp->snd_max) { 515 #if 0 516 if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && 517 SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) { 518 tp->ts_recent_age = tcp_now; 519 tp->ts_recent = ts_val; 520 } 521 #endif 522 523 if (ti->ti_len == 0) 524 { 525 if ( SEQ_GT(ti->ti_ack, tp->snd_una) 526 && SEQ_LEQ(ti->ti_ack, tp->snd_max) 527 && tp->snd_cwnd >= tp->snd_wnd) 528 { 486 529 /* 487 * If last ACK falls within this segment's sequence numbers, 488 * record the timestamp. 530 * this is a pure ack for outstanding data. 489 531 */ 490 /* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && 491 * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) { 492 * tp->ts_recent_age = tcp_now; 493 * tp->ts_recent = ts_val; 494 * } 495 */ 496 if (ti->ti_len == 0) { 497 if (SEQ_GT(ti->ti_ack, tp->snd_una) && 498 SEQ_LEQ(ti->ti_ack, tp->snd_max) && 499 tp->snd_cwnd >= tp->snd_wnd) { 500 /* 501 * this is a pure ack for outstanding data. 502 */ 503 ++tcpstat.tcps_predack; 504 /* if (ts_present) 505 * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); 506 * else 507 */ if (tp->t_rtt && 508 SEQ_GT(ti->ti_ack, tp->t_rtseq)) 509 tcp_xmit_timer(pData, tp, tp->t_rtt); 510 acked = ti->ti_ack - tp->snd_una; 511 tcpstat.tcps_rcvackpack++; 512 tcpstat.tcps_rcvackbyte += acked; 513 sbdrop(&so->so_snd, acked); 514 tp->snd_una = ti->ti_ack; 515 m_freem(pData, m); 516 517 /* 518 * If all outstanding data are acked, stop 519 * retransmit timer, otherwise restart timer 520 * using current (possibly backed-off) value. 521 * If process is waiting for space, 522 * wakeup/selwakeup/signal. If data 523 * are ready to send, let tcp_output 524 * decide between more output or persist. 525 */ 526 if (tp->snd_una == tp->snd_max) 527 tp->t_timer[TCPT_REXMT] = 0; 528 else if (tp->t_timer[TCPT_PERSIST] == 0) 529 tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; 530 531 /* 532 * There's room in so_snd, sowwakup will read() 533 * from the socket if we can 534 */ 535 /* if (so->so_snd.sb_flags & SB_NOTIFY) 536 * sowwakeup(so); 537 */ 538 /* 539 * This is called because sowwakeup might have 540 * put data into so_snd. Since we don't so sowwakeup, 541 * we don't need this.. XXX??? 542 */ 543 if (so->so_snd.sb_cc) 544 (void) tcp_output(pData, tp); 545 546 return; 547 } 548 } else if (ti->ti_ack == tp->snd_una && 549 LIST_FIRST(&tp->t_segq) && 550 ti->ti_len <= sbspace(&so->so_rcv)) { 551 /* 552 * this is a pure, in-sequence data packet 553 * with nothing on the reassembly queue and 554 * we have enough buffer space to take it. 555 */ 556 ++tcpstat.tcps_preddat; 557 tp->rcv_nxt += ti->ti_len; 558 tcpstat.tcps_rcvpack++; 559 tcpstat.tcps_rcvbyte += ti->ti_len; 560 /* 561 * Add data to socket buffer. 562 */ 563 if (so->so_emu) { 564 if (tcp_emu(pData, so,m)) sbappend(pData, so, m); 565 } else 566 sbappend(pData, so, m); 567 568 /* 569 * XXX This is called when data arrives. Later, check 570 * if we can actually write() to the socket 571 * XXX Need to check? It's be NON_BLOCKING 572 */ 573 /* sorwakeup(so); */ 574 575 /* 576 * If this is a short packet, then ACK now - with Nagel 577 * congestion avoidance sender won't send more until 578 * he gets an ACK. 579 * 580 * It is better to not delay acks at all to maximize 581 * TCP throughput. See RFC 2581. 582 */ 583 tp->t_flags |= TF_ACKNOW; 584 tcp_output(pData, tp); 585 return; 586 } 587 } /* header prediction */ 588 /* 589 * Calculate amount of space in receive window, 590 * and then do TCP input processing. 591 * Receive window is amount of space in rcv queue, 592 * but not less than advertised window. 593 */ 594 { int win; 595 win = sbspace(&so->so_rcv); 596 if (win < 0) 532 ++tcpstat.tcps_predack; 533 #if 0 534 if (ts_present) 535 tcp_xmit_timer(tp, tcp_now-ts_ecr+1); 536 else 537 #endif 538 if ( tp->t_rtt 539 && SEQ_GT(ti->ti_ack, tp->t_rtseq)) 540 tcp_xmit_timer(pData, tp, tp->t_rtt); 541 acked = ti->ti_ack - tp->snd_una; 542 tcpstat.tcps_rcvackpack++; 543 tcpstat.tcps_rcvackbyte += acked; 544 sbdrop(&so->so_snd, acked); 545 tp->snd_una = ti->ti_ack; 546 m_freem(pData, m); 547 548 /* 549 * If all outstanding data are acked, stop 550 * retransmit timer, otherwise restart timer 551 * using current (possibly backed-off) value. 552 * If process is waiting for space, 553 * wakeup/selwakeup/signal. If data 554 * are ready to send, let tcp_output 555 * decide between more output or persist. 556 */ 557 if (tp->snd_una == tp->snd_max) 558 tp->t_timer[TCPT_REXMT] = 0; 559 else if (tp->t_timer[TCPT_PERSIST] == 0) 560 tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; 561 562 /* 563 * There's room in so_snd, sowwakup will read() 564 * from the socket if we can 565 */ 566 #if 0 567 if (so->so_snd.sb_flags & SB_NOTIFY) 568 sowwakeup(so); 569 #endif 570 /* 571 * This is called because sowwakeup might have 572 * put data into so_snd. Since we don't so sowwakeup, 573 * we don't need this.. XXX??? 574 */ 575 if (so->so_snd.sb_cc) 576 (void) tcp_output(pData, tp); 577 578 return; 579 } 580 } 581 else if ( ti->ti_ack == tp->snd_una 582 && LIST_FIRST(&tp->t_segq) 583 && ti->ti_len <= sbspace(&so->so_rcv)) 584 { 585 /* 586 * this is a pure, in-sequence data packet 587 * with nothing on the reassembly queue and 588 * we have enough buffer space to take it. 589 */ 590 ++tcpstat.tcps_preddat; 591 tp->rcv_nxt += ti->ti_len; 592 tcpstat.tcps_rcvpack++; 593 tcpstat.tcps_rcvbyte += ti->ti_len; 594 /* 595 * Add data to socket buffer. 596 */ 597 if (so->so_emu) 598 { 599 if (tcp_emu(pData, so,m)) sbappend(pData, so, m); 600 } 601 else 602 sbappend(pData, so, m); 603 604 /* 605 * XXX This is called when data arrives. Later, check 606 * if we can actually write() to the socket 607 * XXX Need to check? It's be NON_BLOCKING 608 */ 609 /* sorwakeup(so); */ 610 611 /* 612 * If this is a short packet, then ACK now - with Nagel 613 * congestion avoidance sender won't send more until 614 * he gets an ACK. 615 * 616 * It is better to not delay acks at all to maximize 617 * TCP throughput. See RFC 2581. 618 */ 619 tp->t_flags |= TF_ACKNOW; 620 tcp_output(pData, tp); 621 return; 622 } 623 } /* header prediction */ 624 /* 625 * Calculate amount of space in receive window, 626 * and then do TCP input processing. 627 * Receive window is amount of space in rcv queue, 628 * but not less than advertised window. 629 */ 630 { 631 int win; 632 win = sbspace(&so->so_rcv); 633 if (win < 0) 597 634 win = 0; 598 599 600 601 switch (tp->t_state) {602 635 tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt)); 636 } 637 638 switch (tp->t_state) 639 { 603 640 /* 604 641 * If the state is LISTEN then ignore segment if it contains an RST. … … 614 651 * segment in this state. 615 652 */ 616 case TCPS_LISTEN: { 617 618 if (tiflags & TH_RST) 619 goto drop; 620 if (tiflags & TH_ACK) 621 goto dropwithreset; 622 if ((tiflags & TH_SYN) == 0) 623 goto drop; 624 625 /* 626 * This has way too many gotos... 627 * But a bit of spaghetti code never hurt anybody :) 628 */ 629 630 if (so->so_emu & EMU_NOCONNECT) { 631 so->so_emu &= ~EMU_NOCONNECT; 632 goto cont_input; 633 } 634 635 if((tcp_fconnect(pData, so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { 636 u_char code=ICMP_UNREACH_NET; 637 DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n", 638 errno,strerror(errno))); 639 if(errno == ECONNREFUSED) { 640 /* ACK the SYN, send RST to refuse the connection */ 641 tcp_respond(pData, tp, ti, m, ti->ti_seq+1, (tcp_seq)0, 642 TH_RST|TH_ACK); 643 } else { 644 if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; 645 HTONL(ti->ti_seq); /* restore tcp header */ 646 HTONL(ti->ti_ack); 647 HTONS(ti->ti_win); 648 HTONS(ti->ti_urp); 649 m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 650 m->m_len += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 651 *ip=save_ip; 652 icmp_error(pData, m, ICMP_UNREACH,code, 0,strerror(errno)); 653 } 654 tp = tcp_close(pData, tp); 655 m_free(pData, m); 656 } else { 657 /* 658 * Haven't connected yet, save the current mbuf 659 * and ti, and return 660 * XXX Some OS's don't tell us whether the connect() 661 * succeeded or not. So we must time it out. 662 */ 663 so->so_m = m; 664 so->so_ti = ti; 653 case TCPS_LISTEN: 654 { 655 if (tiflags & TH_RST) 656 goto drop; 657 if (tiflags & TH_ACK) 658 goto dropwithreset; 659 if ((tiflags & TH_SYN) == 0) 660 goto drop; 661 662 /* 663 * This has way too many gotos... 664 * But a bit of spaghetti code never hurt anybody :) 665 */ 666 667 if (so->so_emu & EMU_NOCONNECT) 668 { 669 so->so_emu &= ~EMU_NOCONNECT; 670 goto cont_input; 671 } 672 673 if ( (tcp_fconnect(pData, so) == -1) 674 && errno != EINPROGRESS 675 && errno != EWOULDBLOCK) 676 { 677 u_char code = ICMP_UNREACH_NET; 678 DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n", 679 errno,strerror(errno))); 680 if (errno == ECONNREFUSED) 681 { 682 /* ACK the SYN, send RST to refuse the connection */ 683 tcp_respond(pData, tp, ti, m, ti->ti_seq+1, (tcp_seq)0, 684 TH_RST|TH_ACK); 685 } 686 else 687 { 688 if (errno == EHOSTUNREACH) 689 code = ICMP_UNREACH_HOST; 690 HTONL(ti->ti_seq); /* restore tcp header */ 691 HTONL(ti->ti_ack); 692 HTONS(ti->ti_win); 693 HTONS(ti->ti_urp); 694 m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 695 m->m_len += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 696 *ip = save_ip; 697 icmp_error(pData, m, ICMP_UNREACH,code, 0,strerror(errno)); 698 } 699 tp = tcp_close(pData, tp); 700 m_free(pData, m); 701 } 702 else 703 { 704 /* 705 * Haven't connected yet, save the current mbuf 706 * and ti, and return 707 * XXX Some OS's don't tell us whether the connect() 708 * succeeded or not. So we must time it out. 709 */ 710 so->so_m = m; 711 so->so_ti = ti; 712 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; 713 tp->t_state = TCPS_SYN_RECEIVED; 714 } 715 return; 716 717 cont_conn: 718 /* m==NULL 719 * Check if the connect succeeded 720 */ 721 if (so->so_state & SS_NOFDREF) 722 { 723 tp = tcp_close(pData, tp); 724 goto dropwithreset; 725 } 726 cont_input: 727 tcp_template(tp); 728 729 if (optp) 730 tcp_dooptions(pData, tp, (u_char *)optp, optlen, ti); 731 732 if (iss) 733 tp->iss = iss; 734 else 735 tp->iss = tcp_iss; 736 tcp_iss += TCP_ISSINCR/2; 737 tp->irs = ti->ti_seq; 738 tcp_sendseqinit(tp); 739 tcp_rcvseqinit(tp); 740 tp->t_flags |= TF_ACKNOW; 741 tp->t_state = TCPS_SYN_RECEIVED; 665 742 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; 666 tp->t_state = TCPS_SYN_RECEIVED; 667 } 668 return; 669 670 cont_conn: 671 /* m==NULL 672 * Check if the connect succeeded 673 */ 674 if (so->so_state & SS_NOFDREF) { 675 tp = tcp_close(pData, tp); 676 goto dropwithreset; 677 } 678 cont_input: 679 tcp_template(tp); 680 681 if (optp) 682 tcp_dooptions(pData, tp, (u_char *)optp, optlen, ti); 683 /* , */ 684 /* &ts_present, &ts_val, &ts_ecr); */ 685 686 if (iss) 687 tp->iss = iss; 688 else 689 tp->iss = tcp_iss; 690 tcp_iss += TCP_ISSINCR/2; 691 tp->irs = ti->ti_seq; 692 tcp_sendseqinit(tp); 693 tcp_rcvseqinit(tp); 694 tp->t_flags |= TF_ACKNOW; 695 tp->t_state = TCPS_SYN_RECEIVED; 696 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; 697 tcpstat.tcps_accepts++; 698 goto trimthenstep6; 743 tcpstat.tcps_accepts++; 744 goto trimthenstep6; 699 745 } /* case TCPS_LISTEN */ 700 746 … … 712 758 */ 713 759 case TCPS_SYN_SENT: 714 if ((tiflags & TH_ACK) && 715 (SEQ_LEQ(ti->ti_ack, tp->iss) || 716 SEQ_GT(ti->ti_ack, tp->snd_max))) 717 goto dropwithreset; 718 719 if (tiflags & TH_RST) { 720 if (tiflags & TH_ACK) 721 tp = tcp_drop(pData, tp,0); /* XXX Check t_softerror! */ 722 goto drop; 760 if ( (tiflags & TH_ACK) 761 && ( SEQ_LEQ(ti->ti_ack, tp->iss) 762 || SEQ_GT(ti->ti_ack, tp->snd_max))) 763 goto dropwithreset; 764 765 if (tiflags & TH_RST) 766 { 767 if (tiflags & TH_ACK) 768 tp = tcp_drop(pData, tp,0); /* XXX Check t_softerror! */ 769 goto drop; 770 } 771 772 if ((tiflags & TH_SYN) == 0) 773 goto drop; 774 if (tiflags & TH_ACK) 775 { 776 tp->snd_una = ti->ti_ack; 777 if (SEQ_LT(tp->snd_nxt, tp->snd_una)) 778 tp->snd_nxt = tp->snd_una; 779 } 780 781 tp->t_timer[TCPT_REXMT] = 0; 782 tp->irs = ti->ti_seq; 783 tcp_rcvseqinit(tp); 784 tp->t_flags |= TF_ACKNOW; 785 if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) 786 { 787 tcpstat.tcps_connects++; 788 soisfconnected(so); 789 tp->t_state = TCPS_ESTABLISHED; 790 791 /* Do window scaling on this connection? */ 792 #if 0 793 if (( tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) 794 == (TF_RCVD_SCALE|TF_REQ_SCALE)) 795 { 796 tp->snd_scale = tp->requested_s_scale; 797 tp->rcv_scale = tp->request_r_scale; 723 798 } 724 725 if ((tiflags & TH_SYN) == 0) 726 goto drop; 727 if (tiflags & TH_ACK) { 728 tp->snd_una = ti->ti_ack; 729 if (SEQ_LT(tp->snd_nxt, tp->snd_una)) 730 tp->snd_nxt = tp->snd_una; 731 } 732 733 tp->t_timer[TCPT_REXMT] = 0; 734 tp->irs = ti->ti_seq; 735 tcp_rcvseqinit(tp); 799 #endif 800 (void) tcp_reass(pData, tp, (struct tcphdr *)0, NULL, (struct mbuf *)0); 801 /* 802 * if we didn't have to retransmit the SYN, 803 * use its rtt as our initial srtt & rtt var. 804 */ 805 if (tp->t_rtt) 806 tcp_xmit_timer(pData, tp, tp->t_rtt); 807 } 808 else 809 tp->t_state = TCPS_SYN_RECEIVED; 810 811 trimthenstep6: 812 /* 813 * Advance ti->ti_seq to correspond to first data byte. 814 * If data, trim to stay within window, 815 * dropping FIN if necessary. 816 */ 817 ti->ti_seq++; 818 if (ti->ti_len > tp->rcv_wnd) 819 { 820 todrop = ti->ti_len - tp->rcv_wnd; 821 m_adj(m, -todrop); 822 ti->ti_len = tp->rcv_wnd; 823 tiflags &= ~TH_FIN; 824 tcpstat.tcps_rcvpackafterwin++; 825 tcpstat.tcps_rcvbyteafterwin += todrop; 826 } 827 tp->snd_wl1 = ti->ti_seq - 1; 828 tp->rcv_up = ti->ti_seq; 829 goto step6; 830 } /* switch tp->t_state */ 831 /* 832 * States other than LISTEN or SYN_SENT. 833 * First check timestamp, if present. 834 * Then check that at least some bytes of segment are within 835 * receive window. If segment begins before rcv_nxt, 836 * drop leading data (and SYN); if nothing left, just ack. 837 * 838 * RFC 1323 PAWS: If we have a timestamp reply on this segment 839 * and it's less than ts_recent, drop it. 840 */ 841 #if 0 842 if ( ts_present 843 && (tiflags & TH_RST) == 0 844 && tp->ts_recent 845 && TSTMP_LT(ts_val, tp->ts_recent)) 846 { 847 /* Check to see if ts_recent is over 24 days old. */ 848 if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) 849 { 850 /* 851 * Invalidate ts_recent. If this segment updates 852 * ts_recent, the age will be reset later and ts_recent 853 * will get a valid value. If it does not, setting 854 * ts_recent to zero will at least satisfy the 855 * requirement that zero be placed in the timestamp 856 * echo reply when ts_recent isn't valid. The 857 * age isn't reset until we get a valid ts_recent 858 * because we don't want out-of-order segments to be 859 * dropped when ts_recent is old. 860 */ 861 tp->ts_recent = 0; 862 } 863 else 864 { 865 tcpstat.tcps_rcvduppack++; 866 tcpstat.tcps_rcvdupbyte += ti->ti_len; 867 tcpstat.tcps_pawsdrop++; 868 goto dropafterack; 869 } 870 } 871 #endif 872 873 todrop = tp->rcv_nxt - ti->ti_seq; 874 if (todrop > 0) 875 { 876 if (tiflags & TH_SYN) 877 { 878 tiflags &= ~TH_SYN; 879 ti->ti_seq++; 880 if (ti->ti_urp > 1) 881 ti->ti_urp--; 882 else 883 tiflags &= ~TH_URG; 884 todrop--; 885 } 886 /* 887 * Following if statement from Stevens, vol. 2, p. 960. 888 */ 889 if ( todrop > ti->ti_len 890 || ( todrop == ti->ti_len 891 && (tiflags & TH_FIN) == 0)) 892 { 893 /* 894 * Any valid FIN must be to the left of the window. 895 * At this point the FIN must be a duplicate or out 896 * of sequence; drop it. 897 */ 898 tiflags &= ~TH_FIN; 899 900 /* 901 * Send an ACK to resynchronize and drop any data. 902 * But keep on processing for RST or ACK. 903 */ 904 tp->t_flags |= TF_ACKNOW; 905 todrop = ti->ti_len; 906 tcpstat.tcps_rcvduppack++; 907 tcpstat.tcps_rcvdupbyte += todrop; 908 } 909 else 910 { 911 tcpstat.tcps_rcvpartduppack++; 912 tcpstat.tcps_rcvpartdupbyte += todrop; 913 } 914 m_adj(m, todrop); 915 ti->ti_seq += todrop; 916 ti->ti_len -= todrop; 917 if (ti->ti_urp > todrop) 918 ti->ti_urp -= todrop; 919 else 920 { 921 tiflags &= ~TH_URG; 922 ti->ti_urp = 0; 923 } 924 } 925 /* 926 * If new data are received on a connection after the 927 * user processes are gone, then RST the other end. 928 */ 929 if ( (so->so_state & SS_NOFDREF) 930 && tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) 931 { 932 tp = tcp_close(pData, tp); 933 tcpstat.tcps_rcvafterclose++; 934 goto dropwithreset; 935 } 936 937 /* 938 * If segment ends after window, drop trailing data 939 * (and PUSH and FIN); if nothing left, just ACK. 940 */ 941 todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd); 942 if (todrop > 0) 943 { 944 tcpstat.tcps_rcvpackafterwin++; 945 if (todrop >= ti->ti_len) 946 { 947 tcpstat.tcps_rcvbyteafterwin += ti->ti_len; 948 /* 949 * If a new connection request is received 950 * while in TIME_WAIT, drop the old connection 951 * and start over if the sequence numbers 952 * are above the previous ones. 953 */ 954 if ( tiflags & TH_SYN 955 && tp->t_state == TCPS_TIME_WAIT 956 && SEQ_GT(ti->ti_seq, tp->rcv_nxt)) 957 { 958 iss = tp->rcv_nxt + TCP_ISSINCR; 959 tp = tcp_close(pData, tp); 960 goto findso; 961 } 962 /* 963 * If window is closed can only take segments at 964 * window edge, and have to drop data and PUSH from 965 * incoming segments. Continue processing, but 966 * remember to ack. Otherwise, drop segment 967 * and ack. 968 */ 969 if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) 970 { 736 971 tp->t_flags |= TF_ACKNOW; 737 if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { 738 tcpstat.tcps_connects++; 739 soisfconnected(so); 740 tp->t_state = TCPS_ESTABLISHED; 741 742 /* Do window scaling on this connection? */ 743 /* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == 744 * (TF_RCVD_SCALE|TF_REQ_SCALE)) { 745 * tp->snd_scale = tp->requested_s_scale; 746 * tp->rcv_scale = tp->request_r_scale; 747 * } 748 */ 749 (void) tcp_reass(pData, tp, (struct tcphdr *)0, NULL, (struct mbuf *)0); 750 /* 751 * if we didn't have to retransmit the SYN, 752 * use its rtt as our initial srtt & rtt var. 753 */ 754 if (tp->t_rtt) 755 tcp_xmit_timer(pData, tp, tp->t_rtt); 756 } else 757 tp->t_state = TCPS_SYN_RECEIVED; 758 759 trimthenstep6: 760 /* 761 * Advance ti->ti_seq to correspond to first data byte. 762 * If data, trim to stay within window, 763 * dropping FIN if necessary. 764 */ 765 ti->ti_seq++; 766 if (ti->ti_len > tp->rcv_wnd) { 767 todrop = ti->ti_len - tp->rcv_wnd; 768 m_adj(m, -todrop); 769 ti->ti_len = tp->rcv_wnd; 770 tiflags &= ~TH_FIN; 771 tcpstat.tcps_rcvpackafterwin++; 772 tcpstat.tcps_rcvbyteafterwin += todrop; 773 } 774 tp->snd_wl1 = ti->ti_seq - 1; 775 tp->rcv_up = ti->ti_seq; 776 goto step6; 777 } /* switch tp->t_state */ 778 /* 779 * States other than LISTEN or SYN_SENT. 780 * First check timestamp, if present. 781 * Then check that at least some bytes of segment are within 782 * receive window. If segment begins before rcv_nxt, 783 * drop leading data (and SYN); if nothing left, just ack. 784 * 785 * RFC 1323 PAWS: If we have a timestamp reply on this segment 786 * and it's less than ts_recent, drop it. 787 */ 788 /* if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent && 789 * TSTMP_LT(ts_val, tp->ts_recent)) { 790 * 791 */ /* Check to see if ts_recent is over 24 days old. */ 792 /* if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) { 793 */ /* 794 * * Invalidate ts_recent. If this segment updates 795 * * ts_recent, the age will be reset later and ts_recent 796 * * will get a valid value. If it does not, setting 797 * * ts_recent to zero will at least satisfy the 798 * * requirement that zero be placed in the timestamp 799 * * echo reply when ts_recent isn't valid. The 800 * * age isn't reset until we get a valid ts_recent 801 * * because we don't want out-of-order segments to be 802 * * dropped when ts_recent is old. 803 * */ 804 /* tp->ts_recent = 0; 805 * } else { 806 * tcpstat.tcps_rcvduppack++; 807 * tcpstat.tcps_rcvdupbyte += ti->ti_len; 808 * tcpstat.tcps_pawsdrop++; 809 * goto dropafterack; 810 * } 811 * } 812 */ 813 814 todrop = tp->rcv_nxt - ti->ti_seq; 815 if (todrop > 0) { 816 if (tiflags & TH_SYN) { 817 tiflags &= ~TH_SYN; 818 ti->ti_seq++; 819 if (ti->ti_urp > 1) 820 ti->ti_urp--; 821 else 822 tiflags &= ~TH_URG; 823 todrop--; 824 } 825 /* 826 * Following if statement from Stevens, vol. 2, p. 960. 827 */ 828 if (todrop > ti->ti_len 829 || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) { 830 /* 831 * Any valid FIN must be to the left of the window. 832 * At this point the FIN must be a duplicate or out 833 * of sequence; drop it. 834 */ 835 tiflags &= ~TH_FIN; 836 837 /* 838 * Send an ACK to resynchronize and drop any data. 839 * But keep on processing for RST or ACK. 840 */ 841 tp->t_flags |= TF_ACKNOW; 842 todrop = ti->ti_len; 843 tcpstat.tcps_rcvduppack++; 844 tcpstat.tcps_rcvdupbyte += todrop; 845 } else { 846 tcpstat.tcps_rcvpartduppack++; 847 tcpstat.tcps_rcvpartdupbyte += todrop; 848 } 849 m_adj(m, todrop); 850 ti->ti_seq += todrop; 851 ti->ti_len -= todrop; 852 if (ti->ti_urp > todrop) 853 ti->ti_urp -= todrop; 854 else { 855 tiflags &= ~TH_URG; 856 ti->ti_urp = 0; 857 } 858 } 859 /* 860 * If new data are received on a connection after the 861 * user processes are gone, then RST the other end. 862 */ 863 if ((so->so_state & SS_NOFDREF) && 864 tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { 865 tp = tcp_close(pData, tp); 866 tcpstat.tcps_rcvafterclose++; 867 goto dropwithreset; 868 } 869 870 /* 871 * If segment ends after window, drop trailing data 872 * (and PUSH and FIN); if nothing left, just ACK. 873 */ 874 todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd); 875 if (todrop > 0) { 876 tcpstat.tcps_rcvpackafterwin++; 877 if (todrop >= ti->ti_len) { 878 tcpstat.tcps_rcvbyteafterwin += ti->ti_len; 879 /* 880 * If a new connection request is received 881 * while in TIME_WAIT, drop the old connection 882 * and start over if the sequence numbers 883 * are above the previous ones. 884 */ 885 if (tiflags & TH_SYN && 886 tp->t_state == TCPS_TIME_WAIT && 887 SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { 888 iss = tp->rcv_nxt + TCP_ISSINCR; 889 tp = tcp_close(pData, tp); 890 goto findso; 891 } 892 /* 893 * If window is closed can only take segments at 894 * window edge, and have to drop data and PUSH from 895 * incoming segments. Continue processing, but 896 * remember to ack. Otherwise, drop segment 897 * and ack. 898 */ 899 if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { 900 tp->t_flags |= TF_ACKNOW; 901 tcpstat.tcps_rcvwinprobe++; 902 } else 903 goto dropafterack; 904 } else 905 tcpstat.tcps_rcvbyteafterwin += todrop; 906 m_adj(m, -todrop); 907 ti->ti_len -= todrop; 908 tiflags &= ~(TH_PUSH|TH_FIN); 909 } 910 911 /* 912 * If last ACK falls within this segment's sequence numbers, 913 * record its timestamp. 914 */ 915 /* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && 916 * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len + 917 * ((tiflags & (TH_SYN|TH_FIN)) != 0))) { 918 * tp->ts_recent_age = tcp_now; 919 * tp->ts_recent = ts_val; 920 * } 921 */ 922 923 /* 924 * If the RST bit is set examine the state: 925 * SYN_RECEIVED STATE: 926 * If passive open, return to LISTEN state. 927 * If active open, inform user that connection was refused. 928 * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: 929 * Inform user that connection was reset, and close tcb. 930 * CLOSING, LAST_ACK, TIME_WAIT STATES 931 * Close the tcb. 932 */ 933 if (tiflags&TH_RST) switch (tp->t_state) { 934 935 case TCPS_SYN_RECEIVED: 972 tcpstat.tcps_rcvwinprobe++; 973 } 974 else 975 goto dropafterack; 976 } 977 else 978 tcpstat.tcps_rcvbyteafterwin += todrop; 979 m_adj(m, -todrop); 980 ti->ti_len -= todrop; 981 tiflags &= ~(TH_PUSH|TH_FIN); 982 } 983 984 /* 985 * If last ACK falls within this segment's sequence numbers, 986 * record its timestamp. 987 */ 988 #if 0 989 if ( ts_present 990 && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) 991 && SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len + ((tiflags & (TH_SYN|TH_FIN)) != 0))) 992 { 993 tp->ts_recent_age = tcp_now; 994 tp->ts_recent = ts_val; 995 } 996 #endif 997 998 /* 999 * If the RST bit is set examine the state: 1000 * SYN_RECEIVED STATE: 1001 * If passive open, return to LISTEN state. 1002 * If active open, inform user that connection was refused. 1003 * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: 1004 * Inform user that connection was reset, and close tcb. 1005 * CLOSING, LAST_ACK, TIME_WAIT STATES 1006 * Close the tcb. 1007 */ 1008 if (tiflags&TH_RST) 1009 switch (tp->t_state) 1010 { 1011 case TCPS_SYN_RECEIVED: 936 1012 /* so->so_error = ECONNREFUSED; */ 937 1013 goto close; 938 1014 939 case TCPS_ESTABLISHED:940 case TCPS_FIN_WAIT_1:941 case TCPS_FIN_WAIT_2:942 case TCPS_CLOSE_WAIT:1015 case TCPS_ESTABLISHED: 1016 case TCPS_FIN_WAIT_1: 1017 case TCPS_FIN_WAIT_2: 1018 case TCPS_CLOSE_WAIT: 943 1019 /* so->so_error = ECONNRESET; */ 944 1020 close: 945 1021 tp->t_state = TCPS_CLOSED; 946 1022 tcpstat.tcps_drops++; … … 948 1024 goto drop; 949 1025 950 case TCPS_CLOSING:951 case TCPS_LAST_ACK:952 case TCPS_TIME_WAIT:1026 case TCPS_CLOSING: 1027 case TCPS_LAST_ACK: 1028 case TCPS_TIME_WAIT: 953 1029 tp = tcp_close(pData, tp); 954 1030 goto drop; 955 1031 } 956 1032 957 /* 958 * If a SYN is in the window, then this is an 959 * error and we send an RST and drop the connection. 960 */ 961 if (tiflags & TH_SYN) { 962 tp = tcp_drop(pData, tp,0); 963 goto dropwithreset; 964 } 965 966 /* 967 * If the ACK bit is off we drop the segment and return. 968 */ 969 if ((tiflags & TH_ACK) == 0) goto drop; 970 971 /* 972 * Ack processing. 973 */ 974 switch (tp->t_state) { 1033 /* 1034 * If a SYN is in the window, then this is an 1035 * error and we send an RST and drop the connection. 1036 */ 1037 if (tiflags & TH_SYN) 1038 { 1039 tp = tcp_drop(pData, tp,0); 1040 goto dropwithreset; 1041 } 1042 1043 /* 1044 * If the ACK bit is off we drop the segment and return. 1045 */ 1046 if ((tiflags & TH_ACK) == 0) 1047 goto drop; 1048 1049 /* 1050 * Ack processing. 1051 */ 1052 switch (tp->t_state) 1053 { 975 1054 /* 976 1055 * In SYN_RECEIVED state if the ack ACKs our SYN then enter … … 979 1058 */ 980 1059 case TCPS_SYN_RECEIVED: 981 982 if (SEQ_GT(tp->snd_una, ti->ti_ack) || 983 SEQ_GT(ti->ti_ack, tp->snd_max)) 984 goto dropwithreset; 985 tcpstat.tcps_connects++; 986 tp->t_state = TCPS_ESTABLISHED; 987 /* 988 * The sent SYN is ack'ed with our sequence number +1 989 * The first data byte already in the buffer will get 990 * lost if no correction is made. This is only needed for 991 * SS_CTL since the buffer is empty otherwise. 992 * tp->snd_una++; or: 993 */ 994 tp->snd_una=ti->ti_ack; 995 soisfconnected(so); 996 997 /* Do window scaling? */ 998 /* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == 999 * (TF_RCVD_SCALE|TF_REQ_SCALE)) { 1000 * tp->snd_scale = tp->requested_s_scale; 1001 * tp->rcv_scale = tp->request_r_scale; 1002 * } 1003 */ 1004 (void) tcp_reass(pData, tp, (struct tcphdr *)0, (int *)0, (struct mbuf *)0); 1005 tp->snd_wl1 = ti->ti_seq - 1; 1006 /* Avoid ack processing; snd_una==ti_ack => dup ack */ 1007 goto synrx_to_est; 1008 /* fall into ... */ 1009 1010 /* 1011 * In ESTABLISHED state: drop duplicate ACKs; ACK out of range 1012 * ACKs. If the ack is in the range 1013 * tp->snd_una < ti->ti_ack <= tp->snd_max 1014 * then advance tp->snd_una to ti->ti_ack and drop 1015 * data from the retransmission queue. If this ACK reflects 1016 * more up to date window information we update our window information. 1017 */ 1060 if ( SEQ_GT(tp->snd_una, ti->ti_ack) 1061 || SEQ_GT(ti->ti_ack, tp->snd_max)) 1062 goto dropwithreset; 1063 tcpstat.tcps_connects++; 1064 tp->t_state = TCPS_ESTABLISHED; 1065 /* 1066 * The sent SYN is ack'ed with our sequence number +1 1067 * The first data byte already in the buffer will get 1068 * lost if no correction is made. This is only needed for 1069 * SS_CTL since the buffer is empty otherwise. 1070 * tp->snd_una++; or: 1071 */ 1072 tp->snd_una = ti->ti_ack; 1073 soisfconnected(so); 1074 1075 /* Do window scaling? */ 1076 #if 0 1077 if ( (tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) 1078 == (TF_RCVD_SCALE|TF_REQ_SCALE)) 1079 { 1080 tp->snd_scale = tp->requested_s_scale; 1081 tp->rcv_scale = tp->request_r_scale; 1082 } 1083 #endif 1084 (void) tcp_reass(pData, tp, (struct tcphdr *)0, (int *)0, (struct mbuf *)0); 1085 tp->snd_wl1 = ti->ti_seq - 1; 1086 /* Avoid ack processing; snd_una==ti_ack => dup ack */ 1087 goto synrx_to_est; 1088 /* fall into ... */ 1089 1090 /* 1091 * In ESTABLISHED state: drop duplicate ACKs; ACK out of range 1092 * ACKs. If the ack is in the range 1093 * tp->snd_una < ti->ti_ack <= tp->snd_max 1094 * then advance tp->snd_una to ti->ti_ack and drop 1095 * data from the retransmission queue. If this ACK reflects 1096 * more up to date window information we update our window information. 1097 */ 1018 1098 case TCPS_ESTABLISHED: 1019 1099 case TCPS_FIN_WAIT_1: … … 1023 1103 case TCPS_LAST_ACK: 1024 1104 case TCPS_TIME_WAIT: 1025 1026 if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { 1027 if (ti->ti_len == 0 && tiwin == tp->snd_wnd) { 1028 tcpstat.tcps_rcvdupack++; 1029 DEBUG_MISC((dfd," dup ack m = %lx so = %lx \n", 1030 (long )m, (long )so)); 1031 /* 1032 * If we have outstanding data (other than 1033 * a window probe), this is a completely 1034 * duplicate ack (ie, window info didn't 1035 * change), the ack is the biggest we've 1036 * seen and we've seen exactly our rexmt 1037 * threshold of them, assume a packet 1038 * has been dropped and retransmit it. 1039 * Kludge snd_nxt & the congestion 1040 * window so we send only this one 1041 * packet. 1042 * 1043 * We know we're losing at the current 1044 * window size so do congestion avoidance 1045 * (set ssthresh to half the current window 1046 * and pull our congestion window back to 1047 * the new ssthresh). 1048 * 1049 * Dup acks mean that packets have left the 1050 * network (they're now cached at the receiver) 1051 * so bump cwnd by the amount in the receiver 1052 * to keep a constant cwnd packets in the 1053 * network. 1054 */ 1055 if (tp->t_timer[TCPT_REXMT] == 0 || 1056 ti->ti_ack != tp->snd_una) 1057 tp->t_dupacks = 0; 1058 else if (++tp->t_dupacks == tcprexmtthresh) { 1059 tcp_seq onxt = tp->snd_nxt; 1060 u_int win = 1061 min(tp->snd_wnd, tp->snd_cwnd) / 2 / 1062 tp->t_maxseg; 1063 1064 if (win < 2) 1065 win = 2; 1066 tp->snd_ssthresh = win * tp->t_maxseg; 1067 tp->t_timer[TCPT_REXMT] = 0; 1068 tp->t_rtt = 0; 1069 tp->snd_nxt = ti->ti_ack; 1070 tp->snd_cwnd = tp->t_maxseg; 1071 (void) tcp_output(pData, tp); 1072 tp->snd_cwnd = tp->snd_ssthresh + 1073 tp->t_maxseg * tp->t_dupacks; 1074 if (SEQ_GT(onxt, tp->snd_nxt)) 1075 tp->snd_nxt = onxt; 1076 goto drop; 1077 } else if (tp->t_dupacks > tcprexmtthresh) { 1078 tp->snd_cwnd += tp->t_maxseg; 1079 (void) tcp_output(pData, tp); 1080 goto drop; 1081 } 1082 } else 1083 tp->t_dupacks = 0; 1084 break; 1105 if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) 1106 { 1107 if (ti->ti_len == 0 && tiwin == tp->snd_wnd) 1108 { 1109 tcpstat.tcps_rcvdupack++; 1110 DEBUG_MISC((dfd," dup ack m = %lx so = %lx \n", 1111 (long )m, (long )so)); 1112 /* 1113 * If we have outstanding data (other than 1114 * a window probe), this is a completely 1115 * duplicate ack (ie, window info didn't 1116 * change), the ack is the biggest we've 1117 * seen and we've seen exactly our rexmt 1118 * threshold of them, assume a packet 1119 * has been dropped and retransmit it. 1120 * Kludge snd_nxt & the congestion 1121 * window so we send only this one 1122 * packet. 1123 * 1124 * We know we're losing at the current 1125 * window size so do congestion avoidance 1126 * (set ssthresh to half the current window 1127 * and pull our congestion window back to 1128 * the new ssthresh). 1129 * 1130 * Dup acks mean that packets have left the 1131 * network (they're now cached at the receiver) 1132 * so bump cwnd by the amount in the receiver 1133 * to keep a constant cwnd packets in the 1134 * network. 1135 */ 1136 if ( tp->t_timer[TCPT_REXMT] == 0 1137 || ti->ti_ack != tp->snd_una) 1138 tp->t_dupacks = 0; 1139 else if (++tp->t_dupacks == tcprexmtthresh) 1140 { 1141 tcp_seq onxt = tp->snd_nxt; 1142 u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; 1143 if (win < 2) 1144 win = 2; 1145 tp->snd_ssthresh = win * tp->t_maxseg; 1146 tp->t_timer[TCPT_REXMT] = 0; 1147 tp->t_rtt = 0; 1148 tp->snd_nxt = ti->ti_ack; 1149 tp->snd_cwnd = tp->t_maxseg; 1150 (void) tcp_output(pData, tp); 1151 tp->snd_cwnd = tp->snd_ssthresh + 1152 tp->t_maxseg * tp->t_dupacks; 1153 if (SEQ_GT(onxt, tp->snd_nxt)) 1154 tp->snd_nxt = onxt; 1155 goto drop; 1156 } 1157 else if (tp->t_dupacks > tcprexmtthresh) 1158 { 1159 tp->snd_cwnd += tp->t_maxseg; 1160 (void) tcp_output(pData, tp); 1161 goto drop; 1162 } 1085 1163 } 1086 synrx_to_est: 1087 /* 1088 * If the congestion window was inflated to account 1089 * for the other side's cached packets, retract it. 1090 */ 1091 if (tp->t_dupacks > tcprexmtthresh && 1092 tp->snd_cwnd > tp->snd_ssthresh) 1093 tp->snd_cwnd = tp->snd_ssthresh; 1094 tp->t_dupacks = 0; 1095 if (SEQ_GT(ti->ti_ack, tp->snd_max)) { 1096 tcpstat.tcps_rcvacktoomuch++; 1097 goto dropafterack; 1098 } 1099 acked = ti->ti_ack - tp->snd_una; 1100 tcpstat.tcps_rcvackpack++; 1101 tcpstat.tcps_rcvackbyte += acked; 1102 1103 /* 1104 * If we have a timestamp reply, update smoothed 1105 * round trip time. If no timestamp is present but 1106 * transmit timer is running and timed sequence 1107 * number was acked, update smoothed round trip time. 1108 * Since we now have an rtt measurement, cancel the 1109 * timer backoff (cf., Phil Karn's retransmit alg.). 1110 * Recompute the initial retransmit timer. 1111 */ 1112 /* if (ts_present) 1113 * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); 1114 * else 1115 */ 1116 if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) 1117 tcp_xmit_timer(pData, tp,tp->t_rtt); 1118 1119 /* 1120 * If all outstanding data is acked, stop retransmit 1121 * timer and remember to restart (more output or persist). 1122 * If there is more data to be acked, restart retransmit 1123 * timer, using current (possibly backed-off) value. 1124 */ 1125 if (ti->ti_ack == tp->snd_max) { 1126 tp->t_timer[TCPT_REXMT] = 0; 1127 needoutput = 1; 1128 } else if (tp->t_timer[TCPT_PERSIST] == 0) 1129 tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; 1130 /* 1131 * When new data is acked, open the congestion window. 1132 * If the window gives us less than ssthresh packets 1133 * in flight, open exponentially (maxseg per packet). 1134 * Otherwise open linearly: maxseg per window 1135 * (maxseg^2 / cwnd per packet). 1136 */ 1137 { 1138 register u_int cw = tp->snd_cwnd; 1139 register u_int incr = tp->t_maxseg; 1140 1141 if (cw > tp->snd_ssthresh) 1164 else 1165 tp->t_dupacks = 0; 1166 break; 1167 } 1168 synrx_to_est: 1169 /* 1170 * If the congestion window was inflated to account 1171 * for the other side's cached packets, retract it. 1172 */ 1173 if ( tp->t_dupacks > tcprexmtthresh 1174 && tp->snd_cwnd > tp->snd_ssthresh) 1175 tp->snd_cwnd = tp->snd_ssthresh; 1176 tp->t_dupacks = 0; 1177 if (SEQ_GT(ti->ti_ack, tp->snd_max)) 1178 { 1179 tcpstat.tcps_rcvacktoomuch++; 1180 goto dropafterack; 1181 } 1182 acked = ti->ti_ack - tp->snd_una; 1183 tcpstat.tcps_rcvackpack++; 1184 tcpstat.tcps_rcvackbyte += acked; 1185 1186 /* 1187 * If we have a timestamp reply, update smoothed 1188 * round trip time. If no timestamp is present but 1189 * transmit timer is running and timed sequence 1190 * number was acked, update smoothed round trip time. 1191 * Since we now have an rtt measurement, cancel the 1192 * timer backoff (cf., Phil Karn's retransmit alg.). 1193 * Recompute the initial retransmit timer. 1194 */ 1195 #if 0 1196 if (ts_present) 1197 tcp_xmit_timer(tp, tcp_now-ts_ecr+1); 1198 else 1199 #endif 1200 if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) 1201 tcp_xmit_timer(pData, tp,tp->t_rtt); 1202 1203 /* 1204 * If all outstanding data is acked, stop retransmit 1205 * timer and remember to restart (more output or persist). 1206 * If there is more data to be acked, restart retransmit 1207 * timer, using current (possibly backed-off) value. 1208 */ 1209 if (ti->ti_ack == tp->snd_max) 1210 { 1211 tp->t_timer[TCPT_REXMT] = 0; 1212 needoutput = 1; 1213 } 1214 else if (tp->t_timer[TCPT_PERSIST] == 0) 1215 tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; 1216 /* 1217 * When new data is acked, open the congestion window. 1218 * If the window gives us less than ssthresh packets 1219 * in flight, open exponentially (maxseg per packet). 1220 * Otherwise open linearly: maxseg per window 1221 * (maxseg^2 / cwnd per packet). 1222 */ 1223 { 1224 register u_int cw = tp->snd_cwnd; 1225 register u_int incr = tp->t_maxseg; 1226 1227 if (cw > tp->snd_ssthresh) 1142 1228 incr = incr * incr / cw; 1143 tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale); 1144 } 1145 if (acked > so->so_snd.sb_cc) { 1146 tp->snd_wnd -= so->so_snd.sb_cc; 1147 sbdrop(&so->so_snd, (int )so->so_snd.sb_cc); 1148 ourfinisacked = 1; 1149 } else { 1150 sbdrop(&so->so_snd, acked); 1151 tp->snd_wnd -= acked; 1152 ourfinisacked = 0; 1153 } 1154 /* 1155 * XXX sowwakup is called when data is acked and there's room for 1156 * for more data... it should read() the socket 1157 */ 1158 /* if (so->so_snd.sb_flags & SB_NOTIFY) 1159 * sowwakeup(so); 1160 */ 1161 tp->snd_una = ti->ti_ack; 1162 if (SEQ_LT(tp->snd_nxt, tp->snd_una)) 1163 tp->snd_nxt = tp->snd_una; 1164 1165 switch (tp->t_state) { 1166 1229 tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale); 1230 } 1231 if (acked > so->so_snd.sb_cc) 1232 { 1233 tp->snd_wnd -= so->so_snd.sb_cc; 1234 sbdrop(&so->so_snd, (int )so->so_snd.sb_cc); 1235 ourfinisacked = 1; 1236 } 1237 else 1238 { 1239 sbdrop(&so->so_snd, acked); 1240 tp->snd_wnd -= acked; 1241 ourfinisacked = 0; 1242 } 1243 /* 1244 * XXX sowwakup is called when data is acked and there's room for 1245 * for more data... it should read() the socket 1246 */ 1247 #if 0 1248 if (so->so_snd.sb_flags & SB_NOTIFY) 1249 sowwakeup(so); 1250 #endif 1251 tp->snd_una = ti->ti_ack; 1252 if (SEQ_LT(tp->snd_nxt, tp->snd_una)) 1253 tp->snd_nxt = tp->snd_una; 1254 1255 switch (tp->t_state) 1256 { 1167 1257 /* 1168 1258 * In FIN_WAIT_1 STATE in addition to the processing … … 1171 1261 */ 1172 1262 case TCPS_FIN_WAIT_1: 1173 if (ourfinisacked) {1174 /*1175 * If we can't receive any more1176 * data, then closing user can proceed.1177 * Starting the timer is contrary to the1178 * specification, but if we don't get a FIN1179 * we'll hang forever.1180 */1181 if (so->so_state & SS_FCANTRCVMORE) {1182 soisfdisconnected(so);1183 tp->t_timer[TCPT_2MSL] = tcp_maxidle;1184 }1185 tp->t_state = TCPS_FIN_WAIT_2;1263 if (ourfinisacked) 1264 { 1265 /* 1266 * If we can't receive any more 1267 * data, then closing user can proceed. 1268 * Starting the timer is contrary to the 1269 * specification, but if we don't get a FIN 1270 * we'll hang forever. 1271 */ 1272 if (so->so_state & SS_FCANTRCVMORE) 1273 { 1274 soisfdisconnected(so); 1275 tp->t_timer[TCPT_2MSL] = tcp_maxidle; 1186 1276 } 1187 break; 1277 tp->t_state = TCPS_FIN_WAIT_2; 1278 } 1279 break; 1188 1280 1189 1281 /* … … 1194 1286 */ 1195 1287 case TCPS_CLOSING: 1196 if (ourfinisacked) { 1197 tp->t_state = TCPS_TIME_WAIT; 1198 tcp_canceltimers(tp); 1199 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 1200 soisfdisconnected(so); 1201 } 1202 break; 1288 if (ourfinisacked) 1289 { 1290 tp->t_state = TCPS_TIME_WAIT; 1291 tcp_canceltimers(tp); 1292 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 1293 soisfdisconnected(so); 1294 } 1295 break; 1203 1296 1204 1297 /* … … 1209 1302 */ 1210 1303 case TCPS_LAST_ACK: 1211 if (ourfinisacked) { 1212 tp = tcp_close(pData, tp); 1213 goto drop; 1214 } 1215 break; 1304 if (ourfinisacked) 1305 { 1306 tp = tcp_close(pData, tp); 1307 goto drop; 1308 } 1309 break; 1216 1310 1217 1311 /* … … 1221 1315 */ 1222 1316 case TCPS_TIME_WAIT: 1223 1224 1225 1226 1317 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 1318 goto dropafterack; 1319 } 1320 } /* switch(tp->t_state) */ 1227 1321 1228 1322 step6: 1323 /* 1324 * Update window information. 1325 * Don't look at window if no ACK: TAC's send garbage on first SYN. 1326 */ 1327 if ( (tiflags & TH_ACK) 1328 && ( SEQ_LT(tp->snd_wl1, ti->ti_seq) 1329 || ( tp->snd_wl1 == ti->ti_seq 1330 && ( SEQ_LT(tp->snd_wl2, ti->ti_ack) 1331 || ( tp->snd_wl2 == ti->ti_ack 1332 && tiwin > tp->snd_wnd))))) 1333 { 1334 /* keep track of pure window updates */ 1335 if ( ti->ti_len == 0 1336 && tp->snd_wl2 == ti->ti_ack 1337 && tiwin > tp->snd_wnd) 1338 tcpstat.tcps_rcvwinupd++; 1339 tp->snd_wnd = tiwin; 1340 tp->snd_wl1 = ti->ti_seq; 1341 tp->snd_wl2 = ti->ti_ack; 1342 if (tp->snd_wnd > tp->max_sndwnd) 1343 tp->max_sndwnd = tp->snd_wnd; 1344 needoutput = 1; 1345 } 1346 1347 /* 1348 * Process segments with URG. 1349 */ 1350 if ((tiflags & TH_URG) && ti->ti_urp && 1351 TCPS_HAVERCVDFIN(tp->t_state) == 0) 1352 { 1229 1353 /* 1230 * Update window information. 1231 * Don't look at window if no ACK: TAC's send garbage on first SYN. 1354 * This is a kludge, but if we receive and accept 1355 * random urgent pointers, we'll crash in 1356 * soreceive. It's hard to imagine someone 1357 * actually wanting to send this much urgent data. 1232 1358 */ 1233 if ((tiflags & TH_ACK) && 1234 (SEQ_LT(tp->snd_wl1, ti->ti_seq) || 1235 (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) || 1236 (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) { 1237 /* keep track of pure window updates */ 1238 if (ti->ti_len == 0 && 1239 tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd) 1240 tcpstat.tcps_rcvwinupd++; 1241 tp->snd_wnd = tiwin; 1242 tp->snd_wl1 = ti->ti_seq; 1243 tp->snd_wl2 = ti->ti_ack; 1244 if (tp->snd_wnd > tp->max_sndwnd) 1245 tp->max_sndwnd = tp->snd_wnd; 1246 needoutput = 1; 1247 } 1248 1359 if (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen) 1360 { 1361 ti->ti_urp = 0; 1362 tiflags &= ~TH_URG; 1363 goto dodata; 1364 } 1249 1365 /* 1250 * Process segments with URG. 1366 * If this segment advances the known urgent pointer, 1367 * then mark the data stream. This should not happen 1368 * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since 1369 * a FIN has been received from the remote side. 1370 * In these states we ignore the URG. 1371 * 1372 * According to RFC961 (Assigned Protocols), 1373 * the urgent pointer points to the last octet 1374 * of urgent data. We continue, however, 1375 * to consider it to indicate the first octet 1376 * of data past the urgent section as the original 1377 * spec states (in one of two places). 1251 1378 */ 1252 if ((tiflags & TH_URG) && ti->ti_urp && 1253 TCPS_HAVERCVDFIN(tp->t_state) == 0) { 1254 /* 1255 * This is a kludge, but if we receive and accept 1256 * random urgent pointers, we'll crash in 1257 * soreceive. It's hard to imagine someone 1258 * actually wanting to send this much urgent data. 1259 */ 1260 if (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen) { 1261 ti->ti_urp = 0; 1262 tiflags &= ~TH_URG; 1263 goto dodata; 1264 } 1265 /* 1266 * If this segment advances the known urgent pointer, 1267 * then mark the data stream. This should not happen 1268 * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since 1269 * a FIN has been received from the remote side. 1270 * In these states we ignore the URG. 1271 * 1272 * According to RFC961 (Assigned Protocols), 1273 * the urgent pointer points to the last octet 1274 * of urgent data. We continue, however, 1275 * to consider it to indicate the first octet 1276 * of data past the urgent section as the original 1277 * spec states (in one of two places). 1278 */ 1279 if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) { 1280 tp->rcv_up = ti->ti_seq + ti->ti_urp; 1281 so->so_urgc = so->so_rcv.sb_cc + 1282 (tp->rcv_up - tp->rcv_nxt); /* -1; */ 1283 tp->rcv_up = ti->ti_seq + ti->ti_urp; 1284 1285 } 1286 } else 1287 /* 1288 * If no out of band data is expected, 1289 * pull receive urgent pointer along 1290 * with the receive window. 1291 */ 1292 if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) 1293 tp->rcv_up = tp->rcv_nxt; 1379 if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) 1380 { 1381 tp->rcv_up = ti->ti_seq + ti->ti_urp; 1382 so->so_urgc = so->so_rcv.sb_cc + 1383 (tp->rcv_up - tp->rcv_nxt); /* -1; */ 1384 tp->rcv_up = ti->ti_seq + ti->ti_urp; 1385 } 1386 } 1387 else 1388 /* 1389 * If no out of band data is expected, 1390 * pull receive urgent pointer along 1391 * with the receive window. 1392 */ 1393 if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) 1394 tp->rcv_up = tp->rcv_nxt; 1294 1395 dodata: 1295 1396 1397 /* 1398 * If this is a small packet, then ACK now - with Nagel 1399 * congestion avoidance sender won't send more until 1400 * he gets an ACK. 1401 * 1402 * See above. 1403 */ 1404 if ( ti->ti_len 1405 && (unsigned)ti->ti_len <= 5 1406 && ((struct tcpiphdr_2 *)ti)->first_char == (char)27) 1407 { 1408 tp->t_flags |= TF_ACKNOW; 1409 } 1410 1411 /* 1412 * Process the segment text, merging it into the TCP sequencing queue, 1413 * and arranging for acknowledgment of receipt if necessary. 1414 * This process logically involves adjusting tp->rcv_wnd as data 1415 * is presented to the user (this happens in tcp_usrreq.c, 1416 * case PRU_RCVD). If a FIN has already been received on this 1417 * connection then we just ignore the text. 1418 */ 1419 if ( (ti->ti_len || (tiflags&TH_FIN)) 1420 && TCPS_HAVERCVDFIN(tp->t_state) == 0) 1421 { 1422 if ( ti->ti_seq == tp->rcv_nxt 1423 && LIST_EMPTY(&tp->t_segq) 1424 && tp->t_state == TCPS_ESTABLISHED) 1425 { 1426 DELAY_ACK(tp, ti); /* little bit different from BSD declaration see netinet/tcp_input.c */ 1427 tp->rcv_nxt += tlen; 1428 tiflags = ti->ti_t.th_flags & TH_FIN; 1429 tcpstat.tcps_rcvpack++; 1430 tcpstat.tcps_rcvbyte += tlen; 1431 if (so->so_state & SS_FCANTRCVMORE) 1432 m_freem(pData, m); 1433 else 1434 sbappend(pData, so, m); 1435 } 1436 else 1437 { 1438 tiflags = tcp_reass(pData, tp, &ti->ti_t, &tlen, m); 1439 tiflags |= TF_ACKNOW; 1440 } 1296 1441 /* 1297 * If this is a small packet, then ACK now - with Nagel 1298 * congestion avoidance sender won't send more until 1299 * he gets an ACK. 1300 * 1301 * See above. 1442 * Note the amount of data that peer has sent into 1443 * our window, in order to estimate the sender's 1444 * buffer size. 1302 1445 */ 1303 if (ti->ti_len && (unsigned)ti->ti_len <= 5 && 1304 ((struct tcpiphdr_2 *)ti)->first_char == (char)27) { 1305 tp->t_flags |= TF_ACKNOW; 1306 } 1307 1308 /* 1309 * Process the segment text, merging it into the TCP sequencing queue, 1310 * and arranging for acknowledgment of receipt if necessary. 1311 * This process logically involves adjusting tp->rcv_wnd as data 1312 * is presented to the user (this happens in tcp_usrreq.c, 1313 * case PRU_RCVD). If a FIN has already been received on this 1314 * connection then we just ignore the text. 1315 */ 1316 if ((ti->ti_len || (tiflags&TH_FIN)) && 1317 TCPS_HAVERCVDFIN(tp->t_state) == 0) { 1318 if (ti->ti_seq == tp->rcv_nxt 1319 && LIST_EMPTY(&tp->t_segq) 1320 && tp->t_state == TCPS_ESTABLISHED) { 1321 DELAY_ACK(tp, ti); /* little bit different from BSD declaration see netinet/tcp_input.c */ 1322 tp->rcv_nxt += tlen; 1323 tiflags = ti->ti_t.th_flags & TH_FIN; 1324 tcpstat.tcps_rcvpack++; 1325 tcpstat.tcps_rcvbyte += tlen; 1326 if (so->so_state & SS_FCANTRCVMORE) 1327 m_freem(pData, m); 1328 else 1329 sbappend(pData, so, m); 1330 } 1331 else { 1332 tiflags = tcp_reass(pData, tp, &ti->ti_t, &tlen, m); 1333 tiflags |= TF_ACKNOW; 1334 } 1335 /* 1336 * Note the amount of data that peer has sent into 1337 * our window, in order to estimate the sender's 1338 * buffer size. 1339 */ 1340 len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt); 1341 } else { 1342 m_free(pData, m); 1343 tiflags &= ~TH_FIN; 1344 } 1345 1346 /* 1347 * If FIN is received ACK the FIN and let the user know 1348 * that the connection is closing. 1349 */ 1350 if (tiflags & TH_FIN) { 1351 if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { 1352 /* 1353 * If we receive a FIN we can't send more data, 1354 * set it SS_FDRAIN 1355 * Shutdown the socket if there is no rx data in the 1356 * buffer. 1357 * soread() is called on completion of shutdown() and 1358 * will got to TCPS_LAST_ACK, and use tcp_output() 1359 * to send the FIN. 1360 */ 1361 /* sofcantrcvmore(so); */ 1362 sofwdrain(so); 1363 1364 tp->t_flags |= TF_ACKNOW; 1365 tp->rcv_nxt++; 1366 } 1367 switch (tp->t_state) { 1368 1369 /* 1370 * In SYN_RECEIVED and ESTABLISHED STATES 1371 * enter the CLOSE_WAIT state. 1372 */ 1373 case TCPS_SYN_RECEIVED: 1374 case TCPS_ESTABLISHED: 1375 if(so->so_emu == EMU_CTL) /* no shutdown on socket */ 1446 len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt); 1447 } 1448 else 1449 { 1450 m_free(pData, m); 1451 tiflags &= ~TH_FIN; 1452 } 1453 1454 /* 1455 * If FIN is received ACK the FIN and let the user know 1456 * that the connection is closing. 1457 */ 1458 if (tiflags & TH_FIN) 1459 { 1460 if (TCPS_HAVERCVDFIN(tp->t_state) == 0) 1461 { 1462 /* 1463 * If we receive a FIN we can't send more data, 1464 * set it SS_FDRAIN 1465 * Shutdown the socket if there is no rx data in the 1466 * buffer. 1467 * soread() is called on completion of shutdown() and 1468 * will got to TCPS_LAST_ACK, and use tcp_output() 1469 * to send the FIN. 1470 */ 1471 /* sofcantrcvmore(so); */ 1472 sofwdrain(so); 1473 1474 tp->t_flags |= TF_ACKNOW; 1475 tp->rcv_nxt++; 1476 } 1477 switch (tp->t_state) 1478 { 1479 /* 1480 * In SYN_RECEIVED and ESTABLISHED STATES 1481 * enter the CLOSE_WAIT state. 1482 */ 1483 case TCPS_SYN_RECEIVED: 1484 case TCPS_ESTABLISHED: 1485 if(so->so_emu == EMU_CTL) /* no shutdown on socket */ 1376 1486 tp->t_state = TCPS_LAST_ACK; 1377 1487 else 1378 1488 tp->t_state = TCPS_CLOSE_WAIT; 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 if (needoutput || (tp->t_flags & TF_ACKNOW)) {1414 (void)tcp_output(pData, tp);1415 } 1416 1489 break; 1490 1491 /* 1492 * If still in FIN_WAIT_1 STATE FIN has not been acked so 1493 * enter the CLOSING state. 1494 */ 1495 case TCPS_FIN_WAIT_1: 1496 tp->t_state = TCPS_CLOSING; 1497 break; 1498 1499 /* 1500 * In FIN_WAIT_2 state enter the TIME_WAIT state, 1501 * starting the time-wait timer, turning off the other 1502 * standard timers. 1503 */ 1504 case TCPS_FIN_WAIT_2: 1505 tp->t_state = TCPS_TIME_WAIT; 1506 tcp_canceltimers(tp); 1507 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 1508 soisfdisconnected(so); 1509 break; 1510 1511 /* 1512 * In TIME_WAIT state restart the 2 MSL time_wait timer. 1513 */ 1514 case TCPS_TIME_WAIT: 1515 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 1516 break; 1517 } 1518 } 1519 1520 /* 1521 * Return any desired output. 1522 */ 1523 if (needoutput || (tp->t_flags & TF_ACKNOW)) 1524 tcp_output(pData, tp); 1525 1526 return; 1417 1527 1418 1528 dropafterack: 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1529 /* 1530 * Generate an ACK dropping incoming segment if it occupies 1531 * sequence space, where the ACK reflects our state. 1532 */ 1533 if (tiflags & TH_RST) 1534 goto drop; 1535 m_freem(pData, m); 1536 tp->t_flags |= TF_ACKNOW; 1537 (void) tcp_output(pData, tp); 1538 return; 1429 1539 1430 1540 dropwithreset: 1431 /* reuses m if m!=NULL, m_free() unnecessary */ 1432 if (tiflags & TH_ACK) 1433 tcp_respond(pData, tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); 1434 else { 1435 if (tiflags & TH_SYN) ti->ti_len++; 1436 tcp_respond(pData, tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0, 1541 /* reuses m if m!=NULL, m_free() unnecessary */ 1542 if (tiflags & TH_ACK) 1543 tcp_respond(pData, tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); 1544 else 1545 { 1546 if (tiflags & TH_SYN) ti->ti_len++; 1547 tcp_respond(pData, tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0, 1437 1548 TH_RST|TH_ACK); 1438 1439 1440 1549 } 1550 1551 return; 1441 1552 1442 1553 drop: 1443 1444 1445 1446 1447 1448 1554 /* 1555 * Drop space held by incoming segment and return. 1556 */ 1557 m_free(pData, m); 1558 1559 return; 1449 1560 } 1450 1561 1451 /* , ts_present, ts_val, ts_ecr) */1452 /* int *ts_present;1453 * u_int32_t *ts_val, *ts_ecr;1454 */1455 1562 void 1456 1563 tcp_dooptions(PNATState pData, struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti) 1457 1564 { 1458 u_int16_t mss; 1459 int opt, optlen; 1460 1461 DEBUG_CALL("tcp_dooptions"); 1462 DEBUG_ARGS((dfd," tp = %lx cnt=%i \n", (long )tp, cnt)); 1463 1464 for (; cnt > 0; cnt -= optlen, cp += optlen) { 1465 opt = cp[0]; 1466 if (opt == TCPOPT_EOL) 1467 break; 1468 if (opt == TCPOPT_NOP) 1469 optlen = 1; 1470 else { 1471 optlen = cp[1]; 1472 if (optlen <= 0) 1473 break; 1565 u_int16_t mss; 1566 int opt, optlen; 1567 1568 DEBUG_CALL("tcp_dooptions"); 1569 DEBUG_ARGS((dfd," tp = %lx cnt=%i \n", (long )tp, cnt)); 1570 1571 for (; cnt > 0; cnt -= optlen, cp += optlen) 1572 { 1573 opt = cp[0]; 1574 if (opt == TCPOPT_EOL) 1575 break; 1576 if (opt == TCPOPT_NOP) 1577 optlen = 1; 1578 else 1579 { 1580 optlen = cp[1]; 1581 if (optlen <= 0) 1582 break; 1583 } 1584 switch (opt) 1585 { 1586 default: 1587 continue; 1588 1589 case TCPOPT_MAXSEG: 1590 if (optlen != TCPOLEN_MAXSEG) 1591 continue; 1592 if (!(ti->ti_flags & TH_SYN)) 1593 continue; 1594 memcpy((char *) &mss, (char *) cp + 2, sizeof(mss)); 1595 NTOHS(mss); 1596 (void) tcp_mss(pData, tp, mss); /* sets t_maxseg */ 1597 break; 1598 1599 #if 0 1600 case TCPOPT_WINDOW: 1601 if (optlen != TCPOLEN_WINDOW) 1602 continue; 1603 if (!(ti->ti_flags & TH_SYN)) 1604 continue; 1605 tp->t_flags |= TF_RCVD_SCALE; 1606 tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT); 1607 break; 1608 1609 case TCPOPT_TIMESTAMP: 1610 if (optlen != TCPOLEN_TIMESTAMP) 1611 continue; 1612 *ts_present = 1; 1613 memcpy((char *) ts_val, (char *)cp + 2, sizeof(*ts_val)); 1614 NTOHL(*ts_val); 1615 memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr)); 1616 NTOHL(*ts_ecr); 1617 1618 /* 1619 * A timestamp received in a SYN makes 1620 * it ok to send timestamp requests and replies. 1621 */ 1622 if (ti->ti_flags & TH_SYN) 1623 { 1624 tp->t_flags |= TF_RCVD_TSTMP; 1625 tp->ts_recent = *ts_val; 1626 tp->ts_recent_age = tcp_now; 1474 1627 } 1475 switch (opt) { 1476 1477 default: 1478 continue; 1479 1480 case TCPOPT_MAXSEG: 1481 if (optlen != TCPOLEN_MAXSEG) 1482 continue; 1483 if (!(ti->ti_flags & TH_SYN)) 1484 continue; 1485 memcpy((char *) &mss, (char *) cp + 2, sizeof(mss)); 1486 NTOHS(mss); 1487 (void) tcp_mss(pData, tp, mss); /* sets t_maxseg */ 1488 break; 1489 1490 /* case TCPOPT_WINDOW: 1491 * if (optlen != TCPOLEN_WINDOW) 1492 * continue; 1493 * if (!(ti->ti_flags & TH_SYN)) 1494 * continue; 1495 * tp->t_flags |= TF_RCVD_SCALE; 1496 * tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT); 1497 * break; 1498 */ 1499 /* case TCPOPT_TIMESTAMP: 1500 * if (optlen != TCPOLEN_TIMESTAMP) 1501 * continue; 1502 * *ts_present = 1; 1503 * memcpy((char *) ts_val, (char *)cp + 2, sizeof(*ts_val)); 1504 * NTOHL(*ts_val); 1505 * memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr)); 1506 * NTOHL(*ts_ecr); 1507 * 1508 */ /* 1509 * * A timestamp received in a SYN makes 1510 * * it ok to send timestamp requests and replies. 1511 * */ 1512 /* if (ti->ti_flags & TH_SYN) { 1513 * tp->t_flags |= TF_RCVD_TSTMP; 1514 * tp->ts_recent = *ts_val; 1515 * tp->ts_recent_age = tcp_now; 1516 * } 1517 */ break; 1628 break; 1629 #endif 1518 1630 } 1519 1631 } … … 1528 1640 */ 1529 1641 1530 #ifdef notdef 1531 1642 #if 0 1532 1643 void 1533 tcp_pulloutofband(so, ti, m) 1534 struct socket *so; 1535 struct tcpiphdr *ti; 1536 register struct mbuf *m; 1644 tcp_pulloutofband(struct socket *so, struct tcpiphdr *ti, struct mbuf *m) 1537 1645 { 1538 int cnt = ti->ti_urp - 1; 1539 1540 while (cnt >= 0) { 1541 if (m->m_len > cnt) { 1542 char *cp = mtod(m, caddr_t) + cnt; 1543 struct tcpcb *tp = sototcpcb(so); 1544 1545 tp->t_iobc = *cp; 1546 tp->t_oobflags |= TCPOOB_HAVEDATA; 1547 memcpy(sp, cp+1, (unsigned)(m->m_len - cnt - 1)); 1548 m->m_len--; 1549 return; 1550 } 1551 cnt -= m->m_len; 1552 m = m->m_next; /* XXX WRONG! Fix it! */ 1553 if (m == 0) 1554 break; 1555 } 1556 panic("tcp_pulloutofband"); 1646 int cnt = ti->ti_urp - 1; 1647 1648 while (cnt >= 0) 1649 { 1650 if (m->m_len > cnt) 1651 { 1652 char *cp = mtod(m, caddr_t) + cnt; 1653 struct tcpcb *tp = sototcpcb(so); 1654 1655 tp->t_iobc = *cp; 1656 tp->t_oobflags |= TCPOOB_HAVEDATA; 1657 memcpy(sp, cp+1, (unsigned)(m->m_len - cnt - 1)); 1658 m->m_len--; 1659 return; 1660 } 1661 cnt -= m->m_len; 1662 m = m->m_next; /* XXX WRONG! Fix it! */ 1663 if (m == 0) 1664 break; 1665 } 1666 panic("tcp_pulloutofband"); 1557 1667 } 1558 1559 #endif /* notdef */ 1668 #endif 1560 1669 1561 1670 /* … … 1567 1676 tcp_xmit_timer(PNATState pData, register struct tcpcb *tp, int rtt) 1568 1677 { 1569 register short delta; 1570 1571 DEBUG_CALL("tcp_xmit_timer"); 1572 DEBUG_ARG("tp = %lx", (long)tp); 1573 DEBUG_ARG("rtt = %d", rtt); 1574 1575 tcpstat.tcps_rttupdated++; 1576 if (tp->t_srtt != 0) { 1577 /* 1578 * srtt is stored as fixed point with 3 bits after the 1579 * binary point (i.e., scaled by 8). The following magic 1580 * is equivalent to the smoothing algorithm in rfc793 with 1581 * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed 1582 * point). Adjust rtt to origin 0. 1583 */ 1584 delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT); 1585 if ((tp->t_srtt += delta) <= 0) 1586 tp->t_srtt = 1; 1587 /* 1588 * We accumulate a smoothed rtt variance (actually, a 1589 * smoothed mean difference), then set the retransmit 1590 * timer to smoothed rtt + 4 times the smoothed variance. 1591 * rttvar is stored as fixed point with 2 bits after the 1592 * binary point (scaled by 4). The following is 1593 * equivalent to rfc793 smoothing with an alpha of .75 1594 * (rttvar = rttvar*3/4 + |delta| / 4). This replaces 1595 * rfc793's wired-in beta. 1596 */ 1597 if (delta < 0) 1598 delta = -delta; 1599 delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT); 1600 if ((tp->t_rttvar += delta) <= 0) 1601 tp->t_rttvar = 1; 1602 } else { 1603 /* 1604 * No rtt measurement yet - use the unsmoothed rtt. 1605 * Set the variance to half the rtt (so our first 1606 * retransmit happens at 3*rtt). 1607 */ 1608 tp->t_srtt = rtt << TCP_RTT_SHIFT; 1609 tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1); 1610 } 1611 tp->t_rtt = 0; 1612 tp->t_rxtshift = 0; 1613 1678 register short delta; 1679 1680 DEBUG_CALL("tcp_xmit_timer"); 1681 DEBUG_ARG("tp = %lx", (long)tp); 1682 DEBUG_ARG("rtt = %d", rtt); 1683 1684 tcpstat.tcps_rttupdated++; 1685 if (tp->t_srtt != 0) 1686 { 1614 1687 /* 1615 * the retransmit should happen at rtt + 4 * rttvar. 1616 * Because of the way we do the smoothing, srtt and rttvar 1617 * will each average +1/2 tick of bias. When we compute 1618 * the retransmit timer, we want 1/2 tick of rounding and 1619 * 1 extra tick because of +-1/2 tick uncertainty in the 1620 * firing of the timer. The bias will give us exactly the 1621 * 1.5 tick we need. But, because the bias is 1622 * statistical, we have to test that we don't drop below 1623 * the minimum feasible timer (which is 2 ticks). 1688 * srtt is stored as fixed point with 3 bits after the 1689 * binary point (i.e., scaled by 8). The following magic 1690 * is equivalent to the smoothing algorithm in rfc793 with 1691 * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed 1692 * point). Adjust rtt to origin 0. 1624 1693 */ 1625 TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),1626 (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */1627 1694 delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT); 1695 if ((tp->t_srtt += delta) <= 0) 1696 tp->t_srtt = 1; 1628 1697 /* 1629 * We received an ack for a packet that wasn't retransmitted; 1630 * it is probably safe to discard any error indications we've 1631 * received recently. This isn't quite right, but close enough 1632 * for now (a route might have failed after we sent a segment, 1633 * and the return path might not be symmetrical). 1698 * We accumulate a smoothed rtt variance (actually, a 1699 * smoothed mean difference), then set the retransmit 1700 * timer to smoothed rtt + 4 times the smoothed variance. 1701 * rttvar is stored as fixed point with 2 bits after the 1702 * binary point (scaled by 4). The following is 1703 * equivalent to rfc793 smoothing with an alpha of .75 1704 * (rttvar = rttvar*3/4 + |delta| / 4). This replaces 1705 * rfc793's wired-in beta. 1634 1706 */ 1635 tp->t_softerror = 0; 1707 if (delta < 0) 1708 delta = -delta; 1709 delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT); 1710 if ((tp->t_rttvar += delta) <= 0) 1711 tp->t_rttvar = 1; 1712 } 1713 else 1714 { 1715 /* 1716 * No rtt measurement yet - use the unsmoothed rtt. 1717 * Set the variance to half the rtt (so our first 1718 * retransmit happens at 3*rtt). 1719 */ 1720 tp->t_srtt = rtt << TCP_RTT_SHIFT; 1721 tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1); 1722 } 1723 tp->t_rtt = 0; 1724 tp->t_rxtshift = 0; 1725 1726 /* 1727 * the retransmit should happen at rtt + 4 * rttvar. 1728 * Because of the way we do the smoothing, srtt and rttvar 1729 * will each average +1/2 tick of bias. When we compute 1730 * the retransmit timer, we want 1/2 tick of rounding and 1731 * 1 extra tick because of +-1/2 tick uncertainty in the 1732 * firing of the timer. The bias will give us exactly the 1733 * 1.5 tick we need. But, because the bias is 1734 * statistical, we have to test that we don't drop below 1735 * the minimum feasible timer (which is 2 ticks). 1736 */ 1737 TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), 1738 (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ 1739 1740 /* 1741 * We received an ack for a packet that wasn't retransmitted; 1742 * it is probably safe to discard any error indications we've 1743 * received recently. This isn't quite right, but close enough 1744 * for now (a route might have failed after we sent a segment, 1745 * and the return path might not be symmetrical). 1746 */ 1747 tp->t_softerror = 0; 1636 1748 } 1637 1749 … … 1655 1767 tcp_mss(PNATState pData, register struct tcpcb *tp, u_int offer) 1656 1768 { 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1769 struct socket *so = tp->t_socket; 1770 int mss; 1771 1772 DEBUG_CALL("tcp_mss"); 1773 DEBUG_ARG("tp = %lx", (long)tp); 1774 DEBUG_ARG("offer = %d", offer); 1775 1776 mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr); 1777 if (offer) 1778 mss = min(mss, offer); 1779 mss = max(mss, 32); 1780 if (mss < tp->t_maxseg || offer != 0) 1781 tp->t_maxseg = mss; 1782 1783 tp->snd_cwnd = mss; 1784 1785 sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0)); 1786 sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0)); 1787 1788 DEBUG_MISC((dfd, " returning mss = %d\n", mss)); 1789 1790 return mss; 1679 1791 } -
trunk/src/VBox/Devices/Network/slirp/udp.c
r15453 r15472 246 246 } 247 247 #endif 248 if (sosendto(pData, so,m) == -1)248 if (sosendto(pData, so, m) == -1) 249 249 { 250 250 m->m_len += iphlen; 251 251 m->m_data -= iphlen; 252 252 *ip = save_ip; 253 DEBUG_MISC((dfd,"udp tx errno = %d-%s\n", errno,strerror(errno)));254 icmp_error(pData, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0, strerror(errno));253 DEBUG_MISC((dfd,"udp tx errno = %d-%s\n", errno, strerror(errno))); 254 icmp_error(pData, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0, strerror(errno)); 255 255 } 256 256
Note:
See TracChangeset
for help on using the changeset viewer.