| 171 | } |
| 172 | |
| 173 | void |
| 174 | sctp6_notify(struct sctp_inpcb *inp, |
| 175 | struct sctp_tcb *stcb, |
| 176 | struct sctp_nets *net, |
| 177 | uint8_t icmp6_type, |
| 178 | uint8_t icmp6_code, |
| 179 | uint32_t next_mtu) |
| 180 | { |
| 181 | int timer_stopped; |
| 182 | |
| 183 | switch (icmp6_type) { |
| 184 | case ICMP6_DST_UNREACH: |
| 185 | if ((icmp6_code == ICMP6_DST_UNREACH_NOROUTE) || |
| 186 | (icmp6_code == ICMP6_DST_UNREACH_ADMIN) || |
| 187 | (icmp6_code == ICMP6_DST_UNREACH_BEYONDSCOPE) || |
| 188 | (icmp6_code == ICMP6_DST_UNREACH_ADDR)) { |
| 189 | /* Mark the net unreachable. */ |
| 190 | if (net->dest_state & SCTP_ADDR_REACHABLE) { |
| 191 | /* Ok that destination is not reachable */ |
| 192 | net->dest_state &= ~SCTP_ADDR_REACHABLE; |
| 193 | net->dest_state &= ~SCTP_ADDR_PF; |
| 194 | sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, |
| 195 | stcb, 0, (void *)net, SCTP_SO_NOT_LOCKED); |
| 196 | } |
| 197 | } |
| 198 | SCTP_TCB_UNLOCK(stcb); |
| 199 | break; |
| 200 | case ICMP6_PARAM_PROB: |
| 201 | /* Treat it like an ABORT. */ |
| 202 | if (icmp6_code == ICMP6_PARAMPROB_NEXTHEADER) { |
| 203 | sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED); |
| 204 | (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, |
| 205 | SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2); |
| 206 | } else { |
| 207 | SCTP_TCB_UNLOCK(stcb); |
| 208 | } |
| 209 | break; |
| 210 | case ICMP6_PACKET_TOO_BIG: |
| 211 | if (net->dest_state & SCTP_ADDR_NO_PMTUD) { |
| 212 | SCTP_TCB_UNLOCK(stcb); |
| 213 | break; |
| 214 | } |
| 215 | if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { |
| 216 | timer_stopped = 1; |
| 217 | sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, |
| 218 | SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1); |
| 219 | } else { |
| 220 | timer_stopped = 0; |
| 221 | } |
| 222 | /* Update the path MTU. */ |
| 223 | if (net->port) { |
| 224 | next_mtu -= sizeof(struct udphdr); |
| 225 | } |
| 226 | if (net->mtu > next_mtu) { |
| 227 | net->mtu = next_mtu; |
| 228 | if (net->port) { |
| 229 | sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu + sizeof(struct udphdr)); |
| 230 | } else { |
no test coverage detected