+ case ICMP_MASKREQ:
+ if (icmplen < ICMP_MASKLEN || (ia = ifptoia(ifp)) == 0)
+ break;
+ icp->icmp_type = ICMP_MASKREPLY;
+ icp->icmp_mask = ia->ia_netmask;
+ if (ip->ip_src.s_addr == 0) {
+ if (ia->ia_ifp->if_flags & IFF_BROADCAST)
+ ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr;
+ else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
+ ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr;
+ }
+reflect:
+ ip->ip_len += hlen; /* since ip_input deducts this */
+ icmpstat.icps_reflect++;
+ icmpstat.icps_outhist[icp->icmp_type]++;
+ icmp_reflect(ip, ifp);
+ return;
+
+ case ICMP_REDIRECT:
+ if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) {
+ icmpstat.icps_badlen++;
+ break;
+ }
+ /*
+ * Short circuit routing redirects to force
+ * immediate change in the kernel's routing
+ * tables. The message is also handed to anyone
+ * listening on a raw socket (e.g. the routing
+ * daemon for use in updating its tables).
+ */
+ icmpgw.sin_addr = ip->ip_src;
+ icmpdst.sin_addr = icp->icmp_gwaddr;
+#ifdef ICMPPRINTFS
+ if (icmpprintfs)
+ printf("redirect dst %x to %x\n", icp->icmp_ip.ip_dst,
+ icp->icmp_gwaddr);
+#endif
+ if (code == ICMP_REDIRECT_NET || code == ICMP_REDIRECT_TOSNET) {
+ icmpsrc.sin_addr =
+ in_makeaddr(in_netof(icp->icmp_ip.ip_dst), INADDR_ANY);
+ rtredirect((struct sockaddr *)&icmpsrc,
+ (struct sockaddr *)&icmpdst, RTF_GATEWAY,
+ (struct sockaddr *)&icmpgw);
+ icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
+ pfctlinput(PRC_REDIRECT_NET,
+ (struct sockaddr *)&icmpsrc);
+ } else {
+ icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
+ rtredirect((struct sockaddr *)&icmpsrc,
+ (struct sockaddr *)&icmpdst, RTF_GATEWAY | RTF_HOST,
+ (struct sockaddr *)&icmpgw);
+ pfctlinput(PRC_REDIRECT_HOST,
+ (struct sockaddr *)&icmpsrc);
+ }
+ break;
+
+ /*
+ * No kernel processing for the following;
+ * just fall through to send to raw listener.
+ */