* Pass some notification to all connections of a protocol * associated with address dst. The local address and/or port numbers * may be specified to limit the search. The "usual action" will be * taken, depending on the ctlinput cmd. The caller must filter any * cmds that are uninteresting (e.g., no error in the map). * Call the protocol specific routine (if any) to report * any errors fo
| 638 | * any errors for each matching socket. |
| 639 | */ |
| 640 | void |
| 641 | in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr *dst, |
| 642 | u_int fport_arg, const struct sockaddr *src, u_int lport_arg, |
| 643 | int cmd, void *cmdarg, |
| 644 | struct inpcb *(*notify)(struct inpcb *, int)) |
| 645 | { |
| 646 | struct inpcb *inp, *inp_temp; |
| 647 | struct sockaddr_in6 sa6_src, *sa6_dst; |
| 648 | u_short fport = fport_arg, lport = lport_arg; |
| 649 | u_int32_t flowinfo; |
| 650 | int errno; |
| 651 | |
| 652 | if ((unsigned)cmd >= PRC_NCMDS || dst->sa_family != AF_INET6) |
| 653 | return; |
| 654 | |
| 655 | sa6_dst = (struct sockaddr_in6 *)dst; |
| 656 | if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr)) |
| 657 | return; |
| 658 | |
| 659 | /* |
| 660 | * note that src can be NULL when we get notify by local fragmentation. |
| 661 | */ |
| 662 | sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src; |
| 663 | flowinfo = sa6_src.sin6_flowinfo; |
| 664 | |
| 665 | /* |
| 666 | * Redirects go to all references to the destination, |
| 667 | * and use in6_rtchange to invalidate the route cache. |
| 668 | * Dead host indications: also use in6_rtchange to invalidate |
| 669 | * the cache, and deliver the error to all the sockets. |
| 670 | * Otherwise, if we have knowledge of the local port and address, |
| 671 | * deliver only to that socket. |
| 672 | */ |
| 673 | if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { |
| 674 | fport = 0; |
| 675 | lport = 0; |
| 676 | bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr)); |
| 677 | |
| 678 | if (cmd != PRC_HOSTDEAD) |
| 679 | notify = in6_rtchange; |
| 680 | } |
| 681 | errno = inet6ctlerrmap[cmd]; |
| 682 | INP_INFO_WLOCK(pcbinfo); |
| 683 | CK_LIST_FOREACH_SAFE(inp, pcbinfo->ipi_listhead, inp_list, inp_temp) { |
| 684 | INP_WLOCK(inp); |
| 685 | if ((inp->inp_vflag & INP_IPV6) == 0) { |
| 686 | INP_WUNLOCK(inp); |
| 687 | continue; |
| 688 | } |
| 689 | |
| 690 | /* |
| 691 | * If the error designates a new path MTU for a destination |
| 692 | * and the application (associated with this socket) wanted to |
| 693 | * know the value, notify. |
| 694 | * XXX: should we avoid to notify the value to TCP sockets? |
| 695 | */ |
| 696 | if (cmd == PRC_MSGSIZE && cmdarg != NULL) |
| 697 | ip6_notify_pmtu(inp, (struct sockaddr_in6 *)dst, |
no test coverage detected