| 3280 | } |
| 3281 | |
| 3282 | static void |
| 3283 | sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state, |
| 3284 | struct sockaddr *sa, uint32_t error, int so_locked) |
| 3285 | { |
| 3286 | struct mbuf *m_notify; |
| 3287 | struct sctp_paddr_change *spc; |
| 3288 | struct sctp_queued_to_read *control; |
| 3289 | |
| 3290 | if ((stcb == NULL) || |
| 3291 | sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) { |
| 3292 | /* event not enabled */ |
| 3293 | return; |
| 3294 | } |
| 3295 | m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_paddr_change), 0, M_NOWAIT, 1, MT_DATA); |
| 3296 | if (m_notify == NULL) |
| 3297 | return; |
| 3298 | SCTP_BUF_LEN(m_notify) = 0; |
| 3299 | spc = mtod(m_notify, struct sctp_paddr_change *); |
| 3300 | memset(spc, 0, sizeof(struct sctp_paddr_change)); |
| 3301 | spc->spc_type = SCTP_PEER_ADDR_CHANGE; |
| 3302 | spc->spc_flags = 0; |
| 3303 | spc->spc_length = sizeof(struct sctp_paddr_change); |
| 3304 | switch (sa->sa_family) { |
| 3305 | #ifdef INET |
| 3306 | case AF_INET: |
| 3307 | #ifdef INET6 |
| 3308 | if (sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) { |
| 3309 | in6_sin_2_v4mapsin6((struct sockaddr_in *)sa, |
| 3310 | (struct sockaddr_in6 *)&spc->spc_aaddr); |
| 3311 | } else { |
| 3312 | memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in)); |
| 3313 | } |
| 3314 | #else |
| 3315 | memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in)); |
| 3316 | #endif |
| 3317 | break; |
| 3318 | #endif |
| 3319 | #ifdef INET6 |
| 3320 | case AF_INET6: |
| 3321 | { |
| 3322 | struct sockaddr_in6 *sin6; |
| 3323 | |
| 3324 | memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6)); |
| 3325 | |
| 3326 | sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; |
| 3327 | if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { |
| 3328 | if (sin6->sin6_scope_id == 0) { |
| 3329 | /* recover scope_id for user */ |
| 3330 | (void)sa6_recoverscope(sin6); |
| 3331 | } else { |
| 3332 | /* clear embedded scope_id for user */ |
| 3333 | in6_clearscope(&sin6->sin6_addr); |
| 3334 | } |
| 3335 | } |
| 3336 | break; |
| 3337 | } |
| 3338 | #endif |
| 3339 | default: |
no test coverage detected