root/netinet/ip_icmp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. icmp_init
  2. icmp_do_error
  3. icmp_error
  4. icmp_input
  5. icmp_reflect
  6. icmp_send
  7. iptime
  8. icmp_sysctl
  9. icmp_mtudisc_clone
  10. icmp_mtudisc
  11. icmp_mtudisc_timeout
  12. icmp_ratelimit
  13. icmp_redirect_timeout

    1 /*      $OpenBSD: ip_icmp.c,v 1.76 2007/06/11 11:29:35 henning Exp $    */
    2 /*      $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $    */
    3 
    4 /*
    5  * Copyright (c) 1982, 1986, 1988, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  *      @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
   33  *
   34  * NRL grants permission for redistribution and use in source and binary
   35  * forms, with or without modification, of the software and documentation
   36  * created at NRL provided that the following conditions are met:
   37  *
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  * 3. All advertising materials mentioning features or use of this software
   44  *    must display the following acknowledgements:
   45  *      This product includes software developed by the University of
   46  *      California, Berkeley and its contributors.
   47  *      This product includes software developed at the Information
   48  *      Technology Division, US Naval Research Laboratory.
   49  * 4. Neither the name of the NRL nor the names of its contributors
   50  *    may be used to endorse or promote products derived from this software
   51  *    without specific prior written permission.
   52  *
   53  * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
   54  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   55  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   56  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
   57  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   58  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   59  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   60  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   61  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   62  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   63  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   64  *
   65  * The views and conclusions contained in the software and documentation
   66  * are those of the authors and should not be interpreted as representing
   67  * official policies, either expressed or implied, of the US Naval
   68  * Research Laboratory (NRL).
   69  */
   70 
   71 #include "carp.h"
   72 
   73 #include <sys/param.h>
   74 #include <sys/systm.h>
   75 #include <sys/mbuf.h>
   76 #include <sys/protosw.h>
   77 #include <sys/socket.h>
   78 #include <sys/sysctl.h>
   79 
   80 #include <net/if.h>
   81 #include <net/route.h>
   82 
   83 #include <netinet/in.h>
   84 #include <netinet/in_systm.h>
   85 #include <netinet/in_var.h>
   86 #include <netinet/ip.h>
   87 #include <netinet/ip_icmp.h>
   88 #include <netinet/ip_var.h>
   89 #include <netinet/icmp_var.h>
   90 
   91 #if NCARP > 0
   92 #include <net/if_types.h>
   93 #include <netinet/ip_carp.h>
   94 #endif
   95 
   96 /*
   97  * ICMP routines: error generation, receive packet processing, and
   98  * routines to turnaround packets back to the originator, and
   99  * host table maintenance routines.
  100  */
  101 
  102 int     icmpmaskrepl = 0;
  103 int     icmpbmcastecho = 0;
  104 int     icmptstamprepl = 1;
  105 #ifdef ICMPPRINTFS
  106 int     icmpprintfs = 0;
  107 #endif
  108 int     icmperrppslim = 100;
  109 int     icmperrpps_count = 0;
  110 struct timeval icmperrppslim_last;
  111 int     icmp_rediraccept = 1;
  112 int     icmp_redirtimeout = 10 * 60;
  113 static struct rttimer_queue *icmp_redirect_timeout_q = NULL;
  114 struct  icmpstat icmpstat;
  115 
  116 int *icmpctl_vars[ICMPCTL_MAXID] = ICMPCTL_VARS;
  117 
  118 void icmp_mtudisc_timeout(struct rtentry *, struct rttimer *);
  119 int icmp_ratelimit(const struct in_addr *, const int, const int);
  120 void icmp_redirect_timeout(struct rtentry *, struct rttimer *);
  121 
  122 extern  struct protosw inetsw[];
  123 
  124 void
  125 icmp_init(void)
  126 {
  127         /*
  128          * This is only useful if the user initializes redirtimeout to
  129          * something other than zero.
  130          */
  131         if (icmp_redirtimeout != 0) {
  132                 icmp_redirect_timeout_q =
  133                     rt_timer_queue_create(icmp_redirtimeout);
  134         }
  135 }
  136 
  137 struct mbuf *
  138 icmp_do_error(struct mbuf *n, int type, int code, n_long dest, int destmtu)
  139 {
  140         struct ip *oip = mtod(n, struct ip *), *nip;
  141         unsigned oiplen = oip->ip_hl << 2;
  142         struct icmp *icp;
  143         struct mbuf *m;
  144         unsigned icmplen, mblen;
  145 
  146 #ifdef ICMPPRINTFS
  147         if (icmpprintfs)
  148                 printf("icmp_error(%x, %d, %d)\n", oip, type, code);
  149 #endif
  150         if (type != ICMP_REDIRECT)
  151                 icmpstat.icps_error++;
  152         /*
  153          * Don't send error if not the first fragment of message.
  154          * Don't error if the old packet protocol was ICMP
  155          * error message, only known informational types.
  156          */
  157         if (oip->ip_off & htons(IP_OFFMASK))
  158                 goto freeit;
  159         if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
  160             n->m_len >= oiplen + ICMP_MINLEN &&
  161             !ICMP_INFOTYPE(((struct icmp *)
  162             ((caddr_t)oip + oiplen))->icmp_type)) {
  163                 icmpstat.icps_oldicmp++;
  164                 goto freeit;
  165         }
  166         /* Don't send error in response to a multicast or broadcast packet */
  167         if (n->m_flags & (M_BCAST|M_MCAST))
  168                 goto freeit;
  169 
  170         /*
  171          * First, do a rate limitation check.
  172          */
  173         if (icmp_ratelimit(&oip->ip_src, type, code))
  174                 goto freeit;    /* XXX stat */
  175 
  176         /*
  177          * Now, formulate icmp message
  178          */
  179         icmplen = oiplen + min(8, ntohs(oip->ip_len));
  180         /*
  181          * Defend against mbuf chains shorter than oip->ip_len:
  182          */
  183         mblen = 0;
  184         for (m = n; m && (mblen < icmplen); m = m->m_next)
  185                 mblen += m->m_len;
  186         icmplen = min(mblen, icmplen);
  187 
  188         /*
  189          * As we are not required to return everything we have,
  190          * we return whatever we can return at ease.
  191          *
  192          * Note that ICMP datagrams longer than 576 octets are out of spec
  193          * according to RFC1812;
  194          */
  195 
  196         KASSERT(ICMP_MINLEN <= MCLBYTES);
  197 
  198         if (icmplen + ICMP_MINLEN > MCLBYTES)
  199                 icmplen = MCLBYTES - ICMP_MINLEN - sizeof (struct ip);
  200 
  201         m = m_gethdr(M_DONTWAIT, MT_HEADER);
  202         if (m && (sizeof (struct ip) + icmplen + ICMP_MINLEN > MHLEN)) {
  203                 MCLGET(m, M_DONTWAIT);
  204                 if ((m->m_flags & M_EXT) == 0) {
  205                         m_freem(m);
  206                         m = NULL;
  207                 }
  208         }
  209         if (m == NULL)
  210                 goto freeit;
  211         m->m_len = icmplen + ICMP_MINLEN;
  212         if ((m->m_flags & M_EXT) == 0)
  213                 MH_ALIGN(m, m->m_len);
  214         icp = mtod(m, struct icmp *);
  215         if ((u_int)type > ICMP_MAXTYPE)
  216                 panic("icmp_error");
  217         icmpstat.icps_outhist[type]++;
  218         icp->icmp_type = type;
  219         if (type == ICMP_REDIRECT)
  220                 icp->icmp_gwaddr.s_addr = dest;
  221         else {
  222                 icp->icmp_void = 0;
  223                 /*
  224                  * The following assignments assume an overlay with the
  225                  * zeroed icmp_void field.
  226                  */
  227                 if (type == ICMP_PARAMPROB) {
  228                         icp->icmp_pptr = code;
  229                         code = 0;
  230                 } else if (type == ICMP_UNREACH &&
  231                     code == ICMP_UNREACH_NEEDFRAG && destmtu)
  232                         icp->icmp_nextmtu = htons(destmtu);
  233         }
  234 
  235         icp->icmp_code = code;
  236         m_copydata(n, 0, icmplen, (caddr_t)&icp->icmp_ip);
  237 
  238         /*
  239          * Now, copy old ip header (without options)
  240          * in front of icmp message.
  241          */
  242         if ((m->m_flags & M_EXT) == 0 &&
  243             m->m_data - sizeof(struct ip) < m->m_pktdat)
  244                 panic("icmp len");
  245         m->m_data -= sizeof(struct ip);
  246         m->m_len += sizeof(struct ip);
  247         m->m_pkthdr.len = m->m_len;
  248         m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
  249         nip = mtod(m, struct ip *);
  250         /* ip_v set in ip_output */
  251         nip->ip_hl = sizeof(struct ip) >> 2;
  252         nip->ip_tos = 0;
  253         nip->ip_len = htons(m->m_len);
  254         /* ip_id set in ip_output */
  255         nip->ip_off = 0;
  256         /* ip_ttl set in icmp_reflect */
  257         nip->ip_p = IPPROTO_ICMP;
  258         nip->ip_src = oip->ip_src;
  259         nip->ip_dst = oip->ip_dst;
  260 
  261         /* move PF_GENERATED to new packet, if existant XXX preserve more? */
  262         if (n->m_pkthdr.pf.flags & PF_TAG_GENERATED)
  263                 m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
  264 
  265         m_freem(n);
  266         return (m);
  267 
  268 freeit:
  269         m_freem(n);
  270         return (NULL);
  271 }
  272 
  273 /*
  274  * Generate an error packet of type error
  275  * in response to bad packet ip.
  276  *
  277  * The ip packet inside has ip_off and ip_len in host byte order.
  278  */
  279 void
  280 icmp_error(struct mbuf *n, int type, int code, n_long dest, int destmtu)
  281 {
  282         struct mbuf *m;
  283 
  284         m = icmp_do_error(n, type, code, dest, destmtu);
  285         if (m != NULL)
  286                 icmp_reflect(m);
  287 }
  288 
  289 struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };
  290 static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };
  291 static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };
  292 
  293 /*
  294  * Process a received ICMP message.
  295  */
  296 void
  297 icmp_input(struct mbuf *m, ...)
  298 {
  299         struct icmp *icp;
  300         struct ip *ip = mtod(m, struct ip *);
  301         int icmplen;
  302         int i;
  303         struct in_ifaddr *ia;
  304         void *(*ctlfunc)(int, struct sockaddr *, void *);
  305         int code;
  306         extern u_char ip_protox[];
  307         int hlen;
  308         va_list ap;
  309         struct rtentry *rt;
  310 
  311         va_start(ap, m);
  312         hlen = va_arg(ap, int);
  313         va_end(ap);
  314 
  315         /*
  316          * Locate icmp structure in mbuf, and check
  317          * that not corrupted and of at least minimum length.
  318          */
  319         icmplen = ntohs(ip->ip_len) - hlen;
  320 #ifdef ICMPPRINTFS
  321         if (icmpprintfs) {
  322                 char buf[4 * sizeof("123")];
  323 
  324                 strlcpy(buf, inet_ntoa(ip->ip_dst), sizeof buf);
  325                 printf("icmp_input from %s to %s, len %d\n",
  326                     inet_ntoa(ip->ip_src), buf, icmplen);
  327         }
  328 #endif
  329         if (icmplen < ICMP_MINLEN) {
  330                 icmpstat.icps_tooshort++;
  331                 goto freeit;
  332         }
  333         i = hlen + min(icmplen, ICMP_ADVLENMIN);
  334         if (m->m_len < i && (m = m_pullup(m, i)) == NULL) {
  335                 icmpstat.icps_tooshort++;
  336                 return;
  337         }
  338         ip = mtod(m, struct ip *);
  339         m->m_len -= hlen;
  340         m->m_data += hlen;
  341         icp = mtod(m, struct icmp *);
  342         if (in_cksum(m, icmplen)) {
  343                 icmpstat.icps_checksum++;
  344                 goto freeit;
  345         }
  346         m->m_len += hlen;
  347         m->m_data -= hlen;
  348 
  349 #ifdef ICMPPRINTFS
  350         /*
  351          * Message type specific processing.
  352          */
  353         if (icmpprintfs)
  354                 printf("icmp_input, type %d code %d\n", icp->icmp_type,
  355                     icp->icmp_code);
  356 #endif
  357         if (icp->icmp_type > ICMP_MAXTYPE)
  358                 goto raw;
  359         icmpstat.icps_inhist[icp->icmp_type]++;
  360         code = icp->icmp_code;
  361         switch (icp->icmp_type) {
  362 
  363         case ICMP_UNREACH:
  364                 switch (code) {
  365                 case ICMP_UNREACH_NET:
  366                 case ICMP_UNREACH_HOST:
  367                 case ICMP_UNREACH_PROTOCOL:
  368                 case ICMP_UNREACH_PORT:
  369                 case ICMP_UNREACH_SRCFAIL:
  370                         code += PRC_UNREACH_NET;
  371                         break;
  372 
  373                 case ICMP_UNREACH_NEEDFRAG:
  374                         code = PRC_MSGSIZE;
  375                         break;
  376 
  377                 case ICMP_UNREACH_NET_UNKNOWN:
  378                 case ICMP_UNREACH_NET_PROHIB:
  379                 case ICMP_UNREACH_TOSNET:
  380                         code = PRC_UNREACH_NET;
  381                         break;
  382 
  383                 case ICMP_UNREACH_HOST_UNKNOWN:
  384                 case ICMP_UNREACH_ISOLATED:
  385                 case ICMP_UNREACH_HOST_PROHIB:
  386                 case ICMP_UNREACH_TOSHOST:
  387                 case ICMP_UNREACH_FILTER_PROHIB:
  388                 case ICMP_UNREACH_HOST_PRECEDENCE:
  389                 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
  390                         code = PRC_UNREACH_HOST;
  391                         break;
  392 
  393                 default:
  394                         goto badcode;
  395                 }
  396                 goto deliver;
  397 
  398         case ICMP_TIMXCEED:
  399                 if (code > 1)
  400                         goto badcode;
  401                 code += PRC_TIMXCEED_INTRANS;
  402                 goto deliver;
  403 
  404         case ICMP_PARAMPROB:
  405                 if (code > 1)
  406                         goto badcode;
  407                 code = PRC_PARAMPROB;
  408                 goto deliver;
  409 
  410         case ICMP_SOURCEQUENCH:
  411                 if (code)
  412                         goto badcode;
  413                 code = PRC_QUENCH;
  414         deliver:
  415                 /* Free packet atttributes */
  416                 if (m->m_flags & M_PKTHDR)
  417                         m_tag_delete_chain(m);
  418 
  419                 /*
  420                  * Problem with datagram; advise higher level routines.
  421                  */
  422                 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
  423                     icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
  424                         icmpstat.icps_badlen++;
  425                         goto freeit;
  426                 }
  427                 if (IN_MULTICAST(icp->icmp_ip.ip_dst.s_addr))
  428                         goto badcode;
  429 #ifdef INET6
  430                 /* Get more contiguous data for a v6 in v4 ICMP message. */
  431                 if (icp->icmp_ip.ip_p == IPPROTO_IPV6) {
  432                         if (icmplen < ICMP_V6ADVLENMIN ||
  433                             icmplen < ICMP_V6ADVLEN(icp)) {
  434                                 icmpstat.icps_badlen++;
  435                                 goto freeit;
  436                         } else {
  437                                 if ((m = m_pullup(m, (ip->ip_hl << 2) +
  438                                     ICMP_V6ADVLEN(icp))) == NULL) {
  439                                         icmpstat.icps_tooshort++;
  440                                         return;
  441                                 }
  442                                 ip = mtod(m, struct ip *);
  443                                 icp = (struct icmp *)
  444                                     (m->m_data + (ip->ip_hl << 2));
  445                         }
  446                 }
  447 #endif /* INET6 */
  448 #ifdef ICMPPRINTFS
  449                 if (icmpprintfs)
  450                         printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
  451 #endif
  452                 icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
  453 #if NCARP > 0
  454                 if (m->m_pkthdr.rcvif->if_type == IFT_CARP &&
  455                     m->m_pkthdr.rcvif->if_flags & IFF_LINK0 &&
  456                     carp_lsdrop(m, AF_INET, &icmpsrc.sin_addr.s_addr,
  457                     &ip->ip_dst.s_addr))
  458                         goto freeit;
  459 #endif
  460                 /*
  461                  * XXX if the packet contains [IPv4 AH TCP], we can't make a
  462                  * notification to TCP layer.
  463                  */
  464                 ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput;
  465                 if (ctlfunc)
  466                         (*ctlfunc)(code, sintosa(&icmpsrc), &icp->icmp_ip);
  467                 break;
  468 
  469         badcode:
  470                 icmpstat.icps_badcode++;
  471                 break;
  472 
  473         case ICMP_ECHO:
  474                 if (!icmpbmcastecho &&
  475                     (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
  476                         icmpstat.icps_bmcastecho++;
  477                         break;
  478                 }
  479                 icp->icmp_type = ICMP_ECHOREPLY;
  480                 goto reflect;
  481 
  482         case ICMP_TSTAMP:
  483                 if (icmptstamprepl == 0)
  484                         break;
  485 
  486                 if (!icmpbmcastecho &&
  487                     (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
  488                         icmpstat.icps_bmcastecho++;
  489                         break;
  490                 }
  491                 if (icmplen < ICMP_TSLEN) {
  492                         icmpstat.icps_badlen++;
  493                         break;
  494                 }
  495                 icp->icmp_type = ICMP_TSTAMPREPLY;
  496                 icp->icmp_rtime = iptime();
  497                 icp->icmp_ttime = icp->icmp_rtime;      /* bogus, do later! */
  498                 goto reflect;
  499 
  500         case ICMP_MASKREQ:
  501                 if (icmpmaskrepl == 0)
  502                         break;
  503                 /*
  504                  * We are not able to respond with all ones broadcast
  505                  * unless we receive it over a point-to-point interface.
  506                  */
  507                 if (icmplen < ICMP_MASKLEN) {
  508                         icmpstat.icps_badlen++;
  509                         break;
  510                 }
  511                 if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
  512                     ip->ip_dst.s_addr == INADDR_ANY)
  513                         icmpdst.sin_addr = ip->ip_src;
  514                 else
  515                         icmpdst.sin_addr = ip->ip_dst;
  516                 if (m->m_pkthdr.rcvif == NULL)
  517                         break;
  518                 ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst),
  519                     m->m_pkthdr.rcvif));
  520                 if (ia == 0)
  521                         break;
  522                 icp->icmp_type = ICMP_MASKREPLY;
  523                 icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
  524                 if (ip->ip_src.s_addr == 0) {
  525                         if (ia->ia_ifp->if_flags & IFF_BROADCAST)
  526                                 ip->ip_src = ia->ia_broadaddr.sin_addr;
  527                         else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
  528                                 ip->ip_src = ia->ia_dstaddr.sin_addr;
  529                 }
  530 reflect:
  531 #if NCARP > 0
  532                 if (m->m_pkthdr.rcvif->if_type == IFT_CARP &&
  533                     m->m_pkthdr.rcvif->if_flags & IFF_LINK0 &&
  534                     carp_lsdrop(m, AF_INET, &ip->ip_src.s_addr,
  535                     &ip->ip_dst.s_addr))
  536                         goto freeit;
  537 #endif
  538                 /* Free packet atttributes */
  539                 if (m->m_flags & M_PKTHDR)
  540                         m_tag_delete_chain(m);
  541 
  542                 icmpstat.icps_reflect++;
  543                 icmpstat.icps_outhist[icp->icmp_type]++;
  544                 icmp_reflect(m);
  545                 return;
  546 
  547         case ICMP_REDIRECT:
  548                 /* Free packet atttributes */
  549                 if (m->m_flags & M_PKTHDR)
  550                         m_tag_delete_chain(m);
  551                 if (icmp_rediraccept == 0)
  552                         goto freeit;
  553                 if (code > 3)
  554                         goto badcode;
  555                 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
  556                     icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
  557                         icmpstat.icps_badlen++;
  558                         break;
  559                 }
  560                 /*
  561                  * Short circuit routing redirects to force
  562                  * immediate change in the kernel's routing
  563                  * tables.  The message is also handed to anyone
  564                  * listening on a raw socket (e.g. the routing
  565                  * daemon for use in updating its tables).
  566                  */
  567                 icmpgw.sin_addr = ip->ip_src;
  568                 icmpdst.sin_addr = icp->icmp_gwaddr;
  569 #ifdef  ICMPPRINTFS
  570                 if (icmpprintfs) {
  571                         char buf[4 * sizeof("123")];
  572                         strlcpy(buf, inet_ntoa(icp->icmp_ip.ip_dst),
  573                             sizeof buf);
  574 
  575                         printf("redirect dst %s to %s\n",
  576                             buf, inet_ntoa(icp->icmp_gwaddr));
  577                 }
  578 #endif
  579                 icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
  580 #if NCARP > 0
  581                 if (m->m_pkthdr.rcvif->if_type == IFT_CARP &&
  582                     m->m_pkthdr.rcvif->if_flags & IFF_LINK0 &&
  583                     carp_lsdrop(m, AF_INET, &icmpsrc.sin_addr.s_addr,
  584                     &ip->ip_dst.s_addr))
  585                         goto freeit;
  586 #endif
  587                 rt = NULL;
  588                 rtredirect(sintosa(&icmpsrc), sintosa(&icmpdst),
  589                     (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
  590                     sintosa(&icmpgw), (struct rtentry **)&rt);
  591                 if (rt != NULL && icmp_redirtimeout != 0) {
  592                         (void)rt_timer_add(rt, icmp_redirect_timeout,
  593                             icmp_redirect_timeout_q);
  594                 }
  595                 if (rt != NULL)
  596                         rtfree(rt);
  597                 pfctlinput(PRC_REDIRECT_HOST, sintosa(&icmpsrc));
  598                 break;
  599 
  600         /*
  601          * No kernel processing for the following;
  602          * just fall through to send to raw listener.
  603          */
  604         case ICMP_ECHOREPLY:
  605         case ICMP_ROUTERADVERT:
  606         case ICMP_ROUTERSOLICIT:
  607         case ICMP_TSTAMPREPLY:
  608         case ICMP_IREQREPLY:
  609         case ICMP_MASKREPLY:
  610         case ICMP_TRACEROUTE:
  611         case ICMP_DATACONVERR:
  612         case ICMP_MOBILE_REDIRECT:
  613         case ICMP_IPV6_WHEREAREYOU:
  614         case ICMP_IPV6_IAMHERE:
  615         case ICMP_MOBILE_REGREQUEST:
  616         case ICMP_MOBILE_REGREPLY:
  617         case ICMP_PHOTURIS:
  618         default:
  619                 break;
  620         }
  621 
  622 raw:
  623         rip_input(m);
  624         return;
  625 
  626 freeit:
  627         m_freem(m);
  628 }
  629 
  630 /*
  631  * Reflect the ip packet back to the source
  632  */
  633 void
  634 icmp_reflect(struct mbuf *m)
  635 {
  636         struct ip *ip = mtod(m, struct ip *);
  637         struct in_ifaddr *ia;
  638         struct in_addr t;
  639         struct mbuf *opts = 0;
  640         int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
  641 
  642         if (!in_canforward(ip->ip_src) &&
  643             ((ip->ip_src.s_addr & IN_CLASSA_NET) !=
  644             htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) {
  645                 m_freem(m);     /* Bad return address */
  646                 goto done;      /* ip_output() will check for broadcast */
  647         }
  648         t = ip->ip_dst;
  649         ip->ip_dst = ip->ip_src;
  650         /*
  651          * If the incoming packet was addressed directly to us,
  652          * use dst as the src for the reply.  For broadcast, use
  653          * the address which corresponds to the incoming interface.
  654          */
  655         TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
  656                 if (t.s_addr == ia->ia_addr.sin_addr.s_addr)
  657                         break;
  658                 if ((ia->ia_ifp->if_flags & IFF_BROADCAST) &&
  659                     t.s_addr == ia->ia_broadaddr.sin_addr.s_addr)
  660                         break;
  661         }
  662         /*
  663          * The following happens if the packet was not addressed to us.
  664          * Use the new source address and do a route lookup. If it fails
  665          * drop the packet as there is no path to the host.
  666          */
  667         if (ia == (struct in_ifaddr *)0) {
  668                 struct sockaddr_in *dst;
  669                 struct route ro;
  670 
  671                 bzero((caddr_t) &ro, sizeof(ro));
  672                 dst = satosin(&ro.ro_dst);
  673                 dst->sin_family = AF_INET;
  674                 dst->sin_len = sizeof(*dst);
  675                 dst->sin_addr = ip->ip_src;
  676 
  677                 rtalloc(&ro);
  678                 if (ro.ro_rt == 0) {
  679                         ipstat.ips_noroute++;
  680                         m_freem(m);
  681                         goto done;
  682                 }
  683 
  684                 ia = ifatoia(ro.ro_rt->rt_ifa);
  685                 ro.ro_rt->rt_use++;
  686                 RTFREE(ro.ro_rt);
  687         }
  688 
  689         t = ia->ia_addr.sin_addr;
  690         ip->ip_src = t;
  691         ip->ip_ttl = MAXTTL;
  692 
  693         if (optlen > 0) {
  694                 u_char *cp;
  695                 int opt, cnt;
  696                 u_int len;
  697 
  698                 /*
  699                  * Retrieve any source routing from the incoming packet;
  700                  * add on any record-route or timestamp options.
  701                  */
  702                 cp = (u_char *) (ip + 1);
  703                 if ((opts = ip_srcroute()) == 0 &&
  704                     (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
  705                         opts->m_len = sizeof(struct in_addr);
  706                         mtod(opts, struct in_addr *)->s_addr = 0;
  707                 }
  708                 if (opts) {
  709 #ifdef ICMPPRINTFS
  710                         if (icmpprintfs)
  711                                 printf("icmp_reflect optlen %d rt %d => ",
  712                                     optlen, opts->m_len);
  713 #endif
  714                         for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
  715                                 opt = cp[IPOPT_OPTVAL];
  716                                 if (opt == IPOPT_EOL)
  717                                         break;
  718                                 if (opt == IPOPT_NOP)
  719                                         len = 1;
  720                                 else {
  721                                         if (cnt < IPOPT_OLEN + sizeof(*cp))
  722                                                 break;
  723                                         len = cp[IPOPT_OLEN];
  724                                         if (len < IPOPT_OLEN + sizeof(*cp) ||
  725                                             len > cnt)
  726                                                 break;
  727                                 }
  728                                 /*
  729                                  * Should check for overflow, but it
  730                                  * "can't happen"
  731                                  */
  732                                 if (opt == IPOPT_RR || opt == IPOPT_TS ||
  733                                     opt == IPOPT_SECURITY) {
  734                                         bcopy((caddr_t)cp,
  735                                             mtod(opts, caddr_t) + opts->m_len,
  736                                             len);
  737                                         opts->m_len += len;
  738                                 }
  739                         }
  740                         /* Terminate & pad, if necessary */
  741                         if ((cnt = opts->m_len % 4) != 0)
  742                                 for (; cnt < 4; cnt++) {
  743                                         *(mtod(opts, caddr_t) + opts->m_len) =
  744                                             IPOPT_EOL;
  745                                         opts->m_len++;
  746                                 }
  747 #ifdef ICMPPRINTFS
  748                         if (icmpprintfs)
  749                                 printf("%d\n", opts->m_len);
  750 #endif
  751                 }
  752                 /*
  753                  * Now strip out original options by copying rest of first
  754                  * mbuf's data back, and adjust the IP length.
  755                  */
  756                 ip->ip_len = htons(ntohs(ip->ip_len) - optlen);
  757                 ip->ip_hl = sizeof(struct ip) >> 2;
  758                 m->m_len -= optlen;
  759                 if (m->m_flags & M_PKTHDR)
  760                         m->m_pkthdr.len -= optlen;
  761                 optlen += sizeof(struct ip);
  762                 bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
  763                     (unsigned)(m->m_len - sizeof(struct ip)));
  764         }
  765         m->m_flags &= ~(M_BCAST|M_MCAST);
  766         icmp_send(m, opts);
  767 done:
  768         if (opts)
  769                 (void)m_free(opts);
  770 }
  771 
  772 /*
  773  * Send an icmp packet back to the ip level,
  774  * after supplying a checksum.
  775  */
  776 void
  777 icmp_send(struct mbuf *m, struct mbuf *opts)
  778 {
  779         struct ip *ip = mtod(m, struct ip *);
  780         int hlen;
  781         struct icmp *icp;
  782 
  783         hlen = ip->ip_hl << 2;
  784         m->m_data += hlen;
  785         m->m_len -= hlen;
  786         icp = mtod(m, struct icmp *);
  787         icp->icmp_cksum = 0;
  788         icp->icmp_cksum = in_cksum(m, ntohs(ip->ip_len) - hlen);
  789         m->m_data -= hlen;
  790         m->m_len += hlen;
  791 #ifdef ICMPPRINTFS
  792         if (icmpprintfs) {
  793                 char buf[4 * sizeof("123")];
  794 
  795                 strlcpy(buf, inet_ntoa(ip->ip_dst), sizeof buf);
  796                 printf("icmp_send dst %s src %s\n",
  797                     buf, inet_ntoa(ip->ip_src));
  798         }
  799 #endif
  800         (void)ip_output(m, opts, (void *)NULL, 0, (void *)NULL, (void *)NULL);
  801 }
  802 
  803 n_time
  804 iptime(void)
  805 {
  806         struct timeval atv;
  807         u_long t;
  808 
  809         microtime(&atv);
  810         t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
  811         return (htonl(t));
  812 }
  813 
  814 int
  815 icmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
  816     size_t newlen)
  817 {
  818 
  819         /* All sysctl names at this level are terminal. */
  820         if (namelen != 1)
  821                 return (ENOTDIR);
  822 
  823         switch (name[0]) {
  824         case ICMPCTL_REDIRTIMEOUT: {
  825                 int error;
  826 
  827                 error = sysctl_int(oldp, oldlenp, newp, newlen,
  828                     &icmp_redirtimeout);
  829                 if (icmp_redirect_timeout_q != NULL) {
  830                         if (icmp_redirtimeout == 0) {
  831                                 rt_timer_queue_destroy(icmp_redirect_timeout_q,
  832                                     TRUE);
  833                                 icmp_redirect_timeout_q = NULL;
  834                         } else
  835                                 rt_timer_queue_change(icmp_redirect_timeout_q,
  836                                     icmp_redirtimeout);
  837                 } else if (icmp_redirtimeout > 0) {
  838                         icmp_redirect_timeout_q =
  839                             rt_timer_queue_create(icmp_redirtimeout);
  840                 }
  841                 return (error);
  842 
  843                 break;
  844         }
  845         default:
  846                 if (name[0] < ICMPCTL_MAXID)
  847                         return (sysctl_int_arr(icmpctl_vars, name, namelen,
  848                             oldp, oldlenp, newp, newlen));
  849                 return (ENOPROTOOPT);
  850         }
  851         /* NOTREACHED */
  852 }
  853 
  854 
  855 /* XXX only handles table 0 right now */
  856 struct rtentry *
  857 icmp_mtudisc_clone(struct sockaddr *dst)
  858 {
  859         struct rtentry *rt;
  860         int error;
  861 
  862         rt = rtalloc1(dst, 1, 0);
  863         if (rt == 0)
  864                 return (NULL);
  865 
  866         /* If we didn't get a host route, allocate one */
  867 
  868         if ((rt->rt_flags & RTF_HOST) == 0) {
  869                 struct rtentry *nrt;
  870 
  871                 error = rtrequest((int) RTM_ADD, dst,
  872                     (struct sockaddr *) rt->rt_gateway,
  873                     (struct sockaddr *) 0,
  874                     RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC, &nrt, 0);
  875                 if (error) {
  876                         rtfree(rt);
  877                         return (NULL);
  878                 }
  879                 nrt->rt_rmx = rt->rt_rmx;
  880                 rtfree(rt);
  881                 rt = nrt;
  882         }
  883         error = rt_timer_add(rt, icmp_mtudisc_timeout, ip_mtudisc_timeout_q);
  884         if (error) {
  885                 rtfree(rt);
  886                 return (NULL);
  887         }
  888 
  889         return (rt);
  890 }
  891 
  892 void
  893 icmp_mtudisc(struct icmp *icp)
  894 {
  895         struct rtentry *rt;
  896         struct sockaddr *dst = sintosa(&icmpsrc);
  897         u_long mtu = ntohs(icp->icmp_nextmtu);  /* Why a long?  IPv6 */
  898 
  899         /* Table of common MTUs: */
  900 
  901         static u_short mtu_table[] = {
  902                 65535, 65280, 32000, 17914, 9180, 8166,
  903                 4352, 2002, 1492, 1006, 508, 296, 68, 0
  904         };
  905 
  906         rt = icmp_mtudisc_clone(dst);
  907         if (rt == 0)
  908                 return;
  909 
  910         if (mtu == 0) {
  911                 int i = 0;
  912 
  913                 mtu = ntohs(icp->icmp_ip.ip_len);
  914                 /* Some 4.2BSD-based routers incorrectly adjust the ip_len */
  915                 if (mtu > rt->rt_rmx.rmx_mtu && rt->rt_rmx.rmx_mtu != 0)
  916                         mtu -= (icp->icmp_ip.ip_hl << 2);
  917 
  918                 /* If we still can't guess a value, try the route */
  919 
  920                 if (mtu == 0) {
  921                         mtu = rt->rt_rmx.rmx_mtu;
  922 
  923                         /* If no route mtu, default to the interface mtu */
  924 
  925                         if (mtu == 0)
  926                                 mtu = rt->rt_ifp->if_mtu;
  927                 }
  928 
  929                 for (i = 0; i < sizeof(mtu_table) / sizeof(mtu_table[0]); i++)
  930                         if (mtu > mtu_table[i]) {
  931                                 mtu = mtu_table[i];
  932                                 break;
  933                         }
  934         }
  935 
  936         /*
  937          * XXX:   RTV_MTU is overloaded, since the admin can set it
  938          *        to turn off PMTU for a route, and the kernel can
  939          *        set it to indicate a serious problem with PMTU
  940          *        on a route.  We should be using a separate flag
  941          *        for the kernel to indicate this.
  942          */
  943 
  944         if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) {
  945                 if (mtu < 296 || mtu > rt->rt_ifp->if_mtu)
  946                         rt->rt_rmx.rmx_locks |= RTV_MTU;
  947                 else if (rt->rt_rmx.rmx_mtu > mtu ||
  948                     rt->rt_rmx.rmx_mtu == 0)
  949                         rt->rt_rmx.rmx_mtu = mtu;
  950         }
  951 
  952         rtfree(rt);
  953 }
  954 
  955 /* XXX only handles table 0 right now */
  956 void
  957 icmp_mtudisc_timeout(struct rtentry *rt, struct rttimer *r)
  958 {
  959         if (rt == NULL)
  960                 panic("icmp_mtudisc_timeout:  bad route to timeout");
  961         if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) ==
  962             (RTF_DYNAMIC | RTF_HOST)) {
  963                 void *(*ctlfunc)(int, struct sockaddr *, void *);
  964                 extern u_char ip_protox[];
  965                 struct sockaddr_in sa;
  966 
  967                 sa = *(struct sockaddr_in *)rt_key(rt);
  968                 rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt),
  969                     rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0, 0);
  970 
  971                 /* Notify TCP layer of increased Path MTU estimate */
  972                 ctlfunc = inetsw[ip_protox[IPPROTO_TCP]].pr_ctlinput;
  973                 if (ctlfunc)
  974                         (*ctlfunc)(PRC_MTUINC,(struct sockaddr *)&sa, NULL);
  975         } else
  976                 if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
  977                         rt->rt_rmx.rmx_mtu = 0;
  978 }
  979 
  980 /*
  981  * Perform rate limit check.
  982  * Returns 0 if it is okay to send the icmp packet.
  983  * Returns 1 if the router SHOULD NOT send this icmp packet due to rate
  984  * limitation.
  985  *
  986  * XXX per-destination/type check necessary?
  987  */
  988 int
  989 icmp_ratelimit(const struct in_addr *dst, const int type, const int code)
  990 {
  991 
  992         /* PPS limit */
  993         if (!ppsratecheck(&icmperrppslim_last, &icmperrpps_count,
  994             icmperrppslim))
  995                 return 1;
  996 
  997         /*okay to send*/
  998         return 0;
  999 }
 1000 
 1001 /* XXX only handles table 0 right now */
 1002 void
 1003 icmp_redirect_timeout(struct rtentry *rt, struct rttimer *r)
 1004 {
 1005         if (rt == NULL)
 1006                 panic("icmp_redirect_timeout:  bad route to timeout");
 1007         if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) ==
 1008             (RTF_DYNAMIC | RTF_HOST)) {
 1009                 rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt),
 1010                     rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0, 0);
 1011         }
 1012 }

/* [<][>][^][v][top][bottom][index][help] */