| 3177 | } |
| 3178 | |
| 3179 | static int |
| 3180 | sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct sctp_association *asoc, |
| 3181 | uint32_t last_tsn, uint32_t *biggest_tsn_acked, |
| 3182 | uint32_t *biggest_newly_acked_tsn, uint32_t *this_sack_lowest_newack, |
| 3183 | int num_seg, int num_nr_seg, int *rto_ok) |
| 3184 | { |
| 3185 | struct sctp_gap_ack_block *frag, block; |
| 3186 | struct sctp_tmit_chunk *tp1; |
| 3187 | int i; |
| 3188 | int num_frs = 0; |
| 3189 | int chunk_freed; |
| 3190 | int non_revocable; |
| 3191 | uint16_t frag_strt, frag_end, prev_frag_end; |
| 3192 | |
| 3193 | tp1 = TAILQ_FIRST(&asoc->sent_queue); |
| 3194 | prev_frag_end = 0; |
| 3195 | chunk_freed = 0; |
| 3196 | |
| 3197 | for (i = 0; i < (num_seg + num_nr_seg); i++) { |
| 3198 | if (i == num_seg) { |
| 3199 | prev_frag_end = 0; |
| 3200 | tp1 = TAILQ_FIRST(&asoc->sent_queue); |
| 3201 | } |
| 3202 | frag = (struct sctp_gap_ack_block *)sctp_m_getptr(m, *offset, |
| 3203 | sizeof(struct sctp_gap_ack_block), (uint8_t *)&block); |
| 3204 | *offset += sizeof(block); |
| 3205 | if (frag == NULL) { |
| 3206 | return (chunk_freed); |
| 3207 | } |
| 3208 | frag_strt = ntohs(frag->start); |
| 3209 | frag_end = ntohs(frag->end); |
| 3210 | |
| 3211 | if (frag_strt > frag_end) { |
| 3212 | /* This gap report is malformed, skip it. */ |
| 3213 | continue; |
| 3214 | } |
| 3215 | if (frag_strt <= prev_frag_end) { |
| 3216 | /* This gap report is not in order, so restart. */ |
| 3217 | tp1 = TAILQ_FIRST(&asoc->sent_queue); |
| 3218 | } |
| 3219 | if (SCTP_TSN_GT((last_tsn + frag_end), *biggest_tsn_acked)) { |
| 3220 | *biggest_tsn_acked = last_tsn + frag_end; |
| 3221 | } |
| 3222 | if (i < num_seg) { |
| 3223 | non_revocable = 0; |
| 3224 | } else { |
| 3225 | non_revocable = 1; |
| 3226 | } |
| 3227 | if (sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end, |
| 3228 | non_revocable, &num_frs, biggest_newly_acked_tsn, |
| 3229 | this_sack_lowest_newack, rto_ok)) { |
| 3230 | chunk_freed = 1; |
| 3231 | } |
| 3232 | prev_frag_end = frag_end; |
| 3233 | } |
| 3234 | if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { |
| 3235 | if (num_frs) |
| 3236 | sctp_log_fr(*biggest_tsn_acked, |
no test coverage detected