* Reflect the ip packet back to the source */
| 754 | * Reflect the ip packet back to the source |
| 755 | */ |
| 756 | static void |
| 757 | icmp_reflect(struct mbuf *m) |
| 758 | { |
| 759 | struct rm_priotracker in_ifa_tracker; |
| 760 | struct ip *ip = mtod(m, struct ip *); |
| 761 | struct ifaddr *ifa; |
| 762 | struct ifnet *ifp; |
| 763 | struct in_ifaddr *ia; |
| 764 | struct in_addr t; |
| 765 | struct nhop_object *nh; |
| 766 | struct mbuf *opts = NULL; |
| 767 | int optlen = (ip->ip_hl << 2) - sizeof(struct ip); |
| 768 | |
| 769 | NET_EPOCH_ASSERT(); |
| 770 | |
| 771 | if (IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || |
| 772 | IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)) || |
| 773 | IN_ZERONET(ntohl(ip->ip_src.s_addr)) ) { |
| 774 | m_freem(m); /* Bad return address */ |
| 775 | ICMPSTAT_INC(icps_badaddr); |
| 776 | goto done; /* Ip_output() will check for broadcast */ |
| 777 | } |
| 778 | |
| 779 | t = ip->ip_dst; |
| 780 | ip->ip_dst = ip->ip_src; |
| 781 | |
| 782 | /* |
| 783 | * Source selection for ICMP replies: |
| 784 | * |
| 785 | * If the incoming packet was addressed directly to one of our |
| 786 | * own addresses, use dst as the src for the reply. |
| 787 | */ |
| 788 | IN_IFADDR_RLOCK(&in_ifa_tracker); |
| 789 | LIST_FOREACH(ia, INADDR_HASH(t.s_addr), ia_hash) { |
| 790 | if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) { |
| 791 | t = IA_SIN(ia)->sin_addr; |
| 792 | IN_IFADDR_RUNLOCK(&in_ifa_tracker); |
| 793 | goto match; |
| 794 | } |
| 795 | } |
| 796 | IN_IFADDR_RUNLOCK(&in_ifa_tracker); |
| 797 | |
| 798 | /* |
| 799 | * If the incoming packet was addressed to one of our broadcast |
| 800 | * addresses, use the first non-broadcast address which corresponds |
| 801 | * to the incoming interface. |
| 802 | */ |
| 803 | ifp = m->m_pkthdr.rcvif; |
| 804 | if (ifp != NULL && ifp->if_flags & IFF_BROADCAST) { |
| 805 | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { |
| 806 | if (ifa->ifa_addr->sa_family != AF_INET) |
| 807 | continue; |
| 808 | ia = ifatoia(ifa); |
| 809 | if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == |
| 810 | t.s_addr) { |
| 811 | t = IA_SIN(ia)->sin_addr; |
| 812 | goto match; |
| 813 | } |
no test coverage detected