| 248 | } |
| 249 | |
| 250 | void |
| 251 | sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d) |
| 252 | { |
| 253 | struct ip6ctlparam *ip6cp; |
| 254 | struct sctp_inpcb *inp; |
| 255 | struct sctp_tcb *stcb; |
| 256 | struct sctp_nets *net; |
| 257 | struct sctphdr sh; |
| 258 | struct sockaddr_in6 src, dst; |
| 259 | |
| 260 | if (pktdst->sa_family != AF_INET6 || |
| 261 | pktdst->sa_len != sizeof(struct sockaddr_in6)) { |
| 262 | return; |
| 263 | } |
| 264 | |
| 265 | if ((unsigned)cmd >= PRC_NCMDS) { |
| 266 | return; |
| 267 | } |
| 268 | if (PRC_IS_REDIRECT(cmd)) { |
| 269 | d = NULL; |
| 270 | } else if (inet6ctlerrmap[cmd] == 0) { |
| 271 | return; |
| 272 | } |
| 273 | /* If the parameter is from icmp6, decode it. */ |
| 274 | if (d != NULL) { |
| 275 | ip6cp = (struct ip6ctlparam *)d; |
| 276 | } else { |
| 277 | ip6cp = (struct ip6ctlparam *)NULL; |
| 278 | } |
| 279 | |
| 280 | if (ip6cp != NULL) { |
| 281 | /* |
| 282 | * XXX: We assume that when IPV6 is non NULL, M and OFF are |
| 283 | * valid. |
| 284 | */ |
| 285 | if (ip6cp->ip6c_m == NULL) { |
| 286 | return; |
| 287 | } |
| 288 | |
| 289 | /* |
| 290 | * Check if we can safely examine the ports and the |
| 291 | * verification tag of the SCTP common header. |
| 292 | */ |
| 293 | if (ip6cp->ip6c_m->m_pkthdr.len < |
| 294 | (int32_t)(ip6cp->ip6c_off + offsetof(struct sctphdr, checksum))) { |
| 295 | return; |
| 296 | } |
| 297 | |
| 298 | /* Copy out the port numbers and the verification tag. */ |
| 299 | memset(&sh, 0, sizeof(sh)); |
| 300 | m_copydata(ip6cp->ip6c_m, |
| 301 | ip6cp->ip6c_off, |
| 302 | sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t), |
| 303 | (caddr_t)&sh); |
| 304 | memset(&src, 0, sizeof(struct sockaddr_in6)); |
| 305 | src.sin6_family = AF_INET6; |
| 306 | src.sin6_len = sizeof(struct sockaddr_in6); |
| 307 | src.sin6_port = sh.src_port; |
nothing calls this directly
no test coverage detected