| 543 | } |
| 544 | |
| 545 | static void |
| 546 | udp6_common_ctlinput(int cmd, struct sockaddr *sa, void *d, |
| 547 | struct inpcbinfo *pcbinfo) |
| 548 | { |
| 549 | struct udphdr uh; |
| 550 | struct ip6_hdr *ip6; |
| 551 | struct mbuf *m; |
| 552 | int off = 0; |
| 553 | struct ip6ctlparam *ip6cp = NULL; |
| 554 | const struct sockaddr_in6 *sa6_src = NULL; |
| 555 | void *cmdarg; |
| 556 | struct inpcb *(*notify)(struct inpcb *, int) = udp_notify; |
| 557 | struct udp_portonly { |
| 558 | u_int16_t uh_sport; |
| 559 | u_int16_t uh_dport; |
| 560 | } *uhp; |
| 561 | |
| 562 | if (sa->sa_family != AF_INET6 || |
| 563 | sa->sa_len != sizeof(struct sockaddr_in6)) |
| 564 | return; |
| 565 | |
| 566 | if ((unsigned)cmd >= PRC_NCMDS) |
| 567 | return; |
| 568 | if (PRC_IS_REDIRECT(cmd)) |
| 569 | notify = in6_rtchange, d = NULL; |
| 570 | else if (cmd == PRC_HOSTDEAD) |
| 571 | d = NULL; |
| 572 | else if (inet6ctlerrmap[cmd] == 0) |
| 573 | return; |
| 574 | |
| 575 | /* if the parameter is from icmp6, decode it. */ |
| 576 | if (d != NULL) { |
| 577 | ip6cp = (struct ip6ctlparam *)d; |
| 578 | m = ip6cp->ip6c_m; |
| 579 | ip6 = ip6cp->ip6c_ip6; |
| 580 | off = ip6cp->ip6c_off; |
| 581 | cmdarg = ip6cp->ip6c_cmdarg; |
| 582 | sa6_src = ip6cp->ip6c_src; |
| 583 | } else { |
| 584 | m = NULL; |
| 585 | ip6 = NULL; |
| 586 | cmdarg = NULL; |
| 587 | sa6_src = &sa6_any; |
| 588 | } |
| 589 | |
| 590 | if (ip6) { |
| 591 | /* |
| 592 | * XXX: We assume that when IPV6 is non NULL, |
| 593 | * M and OFF are valid. |
| 594 | */ |
| 595 | |
| 596 | /* Check if we can safely examine src and dst ports. */ |
| 597 | if (m->m_pkthdr.len < off + sizeof(*uhp)) |
| 598 | return; |
| 599 | |
| 600 | bzero(&uh, sizeof(uh)); |
| 601 | m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh); |
| 602 |
no test coverage detected