Home | History | Annotate | Line # | Download | only in netinet
ip_icmp.c revision 1.65
      1  1.65      matt /*	$NetBSD: ip_icmp.c,v 1.65 2001/11/04 20:55:27 matt Exp $	*/
      2  1.37    itojun 
      3  1.37    itojun /*
      4  1.37    itojun  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
      5  1.37    itojun  * All rights reserved.
      6  1.37    itojun  *
      7  1.37    itojun  * Redistribution and use in source and binary forms, with or without
      8  1.37    itojun  * modification, are permitted provided that the following conditions
      9  1.37    itojun  * are met:
     10  1.37    itojun  * 1. Redistributions of source code must retain the above copyright
     11  1.37    itojun  *    notice, this list of conditions and the following disclaimer.
     12  1.37    itojun  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.37    itojun  *    notice, this list of conditions and the following disclaimer in the
     14  1.37    itojun  *    documentation and/or other materials provided with the distribution.
     15  1.37    itojun  * 3. Neither the name of the project nor the names of its contributors
     16  1.37    itojun  *    may be used to endorse or promote products derived from this software
     17  1.37    itojun  *    without specific prior written permission.
     18  1.37    itojun  *
     19  1.37    itojun  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     20  1.37    itojun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  1.37    itojun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  1.37    itojun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     23  1.37    itojun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  1.37    itojun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  1.37    itojun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  1.37    itojun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  1.37    itojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  1.37    itojun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  1.37    itojun  * SUCH DAMAGE.
     30  1.37    itojun  */
     31  1.10       cgd 
     32  1.31   thorpej /*-
     33  1.55   thorpej  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
     34  1.31   thorpej  * All rights reserved.
     35  1.31   thorpej  *
     36  1.31   thorpej  * This code is derived from software contributed to The NetBSD Foundation
     37  1.31   thorpej  * by Public Access Networks Corporation ("Panix").  It was developed under
     38  1.31   thorpej  * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
     39  1.31   thorpej  *
     40  1.55   thorpej  * This code is derived from software contributed to The NetBSD Foundation
     41  1.55   thorpej  * by Jason R. Thorpe of Zembu Labs, Inc.
     42  1.55   thorpej  *
     43  1.31   thorpej  * Redistribution and use in source and binary forms, with or without
     44  1.31   thorpej  * modification, are permitted provided that the following conditions
     45  1.31   thorpej  * are met:
     46  1.31   thorpej  * 1. Redistributions of source code must retain the above copyright
     47  1.31   thorpej  *    notice, this list of conditions and the following disclaimer.
     48  1.31   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     49  1.31   thorpej  *    notice, this list of conditions and the following disclaimer in the
     50  1.31   thorpej  *    documentation and/or other materials provided with the distribution.
     51  1.31   thorpej  * 3. All advertising materials mentioning features or use of this software
     52  1.31   thorpej  *    must display the following acknowledgement:
     53  1.31   thorpej  *	This product includes software developed by the NetBSD
     54  1.31   thorpej  *	Foundation, Inc. and its contributors.
     55  1.31   thorpej  * 4. Neither the name of The NetBSD Foundation nor the names of its
     56  1.31   thorpej  *    contributors may be used to endorse or promote products derived
     57  1.31   thorpej  *    from this software without specific prior written permission.
     58  1.31   thorpej  *
     59  1.31   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     60  1.31   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     61  1.31   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     62  1.31   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     63  1.31   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     64  1.31   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     65  1.31   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     66  1.31   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     67  1.31   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     68  1.31   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     69  1.31   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     70  1.31   thorpej  */
     71  1.31   thorpej 
     72   1.1       cgd /*
     73   1.9   mycroft  * Copyright (c) 1982, 1986, 1988, 1993
     74   1.9   mycroft  *	The Regents of the University of California.  All rights reserved.
     75   1.1       cgd  *
     76   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     77   1.1       cgd  * modification, are permitted provided that the following conditions
     78   1.1       cgd  * are met:
     79   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     80   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     81   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     82   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     83   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     84   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     85   1.1       cgd  *    must display the following acknowledgement:
     86   1.1       cgd  *	This product includes software developed by the University of
     87   1.1       cgd  *	California, Berkeley and its contributors.
     88   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     89   1.1       cgd  *    may be used to endorse or promote products derived from this software
     90   1.1       cgd  *    without specific prior written permission.
     91   1.1       cgd  *
     92   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     93   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     94   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     95   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     96   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     97   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     98   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     99   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    100   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    101   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    102   1.1       cgd  * SUCH DAMAGE.
    103   1.1       cgd  *
    104  1.10       cgd  *	@(#)ip_icmp.c	8.2 (Berkeley) 1/4/94
    105   1.1       cgd  */
    106  1.38   thorpej 
    107  1.38   thorpej #include "opt_ipsec.h"
    108   1.1       cgd 
    109   1.4   mycroft #include <sys/param.h>
    110   1.4   mycroft #include <sys/systm.h>
    111   1.4   mycroft #include <sys/malloc.h>
    112   1.4   mycroft #include <sys/mbuf.h>
    113   1.4   mycroft #include <sys/protosw.h>
    114   1.4   mycroft #include <sys/socket.h>
    115   1.4   mycroft #include <sys/time.h>
    116   1.4   mycroft #include <sys/kernel.h>
    117  1.63       kml #include <sys/syslog.h>
    118  1.19  christos #include <sys/sysctl.h>
    119   1.1       cgd 
    120   1.9   mycroft #include <net/if.h>
    121   1.4   mycroft #include <net/route.h>
    122   1.1       cgd 
    123   1.4   mycroft #include <netinet/in.h>
    124   1.4   mycroft #include <netinet/in_systm.h>
    125   1.4   mycroft #include <netinet/in_var.h>
    126   1.4   mycroft #include <netinet/ip.h>
    127   1.4   mycroft #include <netinet/ip_icmp.h>
    128  1.19  christos #include <netinet/ip_var.h>
    129  1.39  sommerfe #include <netinet/in_pcb.h>
    130   1.4   mycroft #include <netinet/icmp_var.h>
    131   1.1       cgd 
    132  1.37    itojun #ifdef IPSEC
    133  1.37    itojun #include <netinet6/ipsec.h>
    134  1.37    itojun #include <netkey/key.h>
    135  1.37    itojun #endif
    136  1.37    itojun 
    137  1.19  christos #include <machine/stdarg.h>
    138  1.19  christos 
    139   1.1       cgd /*
    140   1.1       cgd  * ICMP routines: error generation, receive packet processing, and
    141   1.1       cgd  * routines to turnaround packets back to the originator, and
    142   1.1       cgd  * host table maintenance routines.
    143   1.1       cgd  */
    144   1.9   mycroft 
    145   1.9   mycroft int	icmpmaskrepl = 0;
    146   1.1       cgd #ifdef ICMPPRINTFS
    147   1.1       cgd int	icmpprintfs = 0;
    148   1.1       cgd #endif
    149  1.47   darrenr int	icmpreturndatabytes = 8;
    150   1.1       cgd 
    151  1.55   thorpej /*
    152  1.55   thorpej  * List of callbacks to notify when Path MTU changes are made.
    153  1.55   thorpej  */
    154  1.57    itojun struct icmp_mtudisc_callback {
    155  1.57    itojun 	LIST_ENTRY(icmp_mtudisc_callback) mc_list;
    156  1.55   thorpej 	void (*mc_func) __P((struct in_addr));
    157  1.55   thorpej };
    158  1.55   thorpej 
    159  1.57    itojun LIST_HEAD(, icmp_mtudisc_callback) icmp_mtudisc_callbacks =
    160  1.55   thorpej     LIST_HEAD_INITIALIZER(&icmp_mtudisc_callbacks);
    161  1.55   thorpej 
    162  1.37    itojun #if 0
    163  1.37    itojun static int	ip_next_mtu __P((int, int));
    164  1.37    itojun #else
    165  1.37    itojun /*static*/ int	ip_next_mtu __P((int, int));
    166  1.37    itojun #endif
    167  1.37    itojun 
    168  1.51    itojun extern int icmperrppslim;
    169  1.51    itojun static int icmperrpps_count = 0;
    170  1.51    itojun static struct timeval icmperrppslim_last;
    171  1.63       kml static int icmp_rediraccept = 1;
    172  1.63       kml static int icmp_redirtimeout = 0;
    173  1.63       kml static struct rttimer_queue *icmp_redirect_timeout_q = NULL;
    174  1.40   thorpej 
    175  1.29       kml static void icmp_mtudisc_timeout __P((struct rtentry *, struct rttimer *));
    176  1.63       kml static void icmp_redirect_timeout __P((struct rtentry *, struct rttimer *));
    177  1.24       kml 
    178  1.40   thorpej static int icmp_ratelimit __P((const struct in_addr *, const int, const int));
    179  1.40   thorpej 
    180  1.63       kml 
    181  1.63       kml void
    182  1.63       kml icmp_init()
    183  1.63       kml {
    184  1.63       kml 	/*
    185  1.63       kml 	 * This is only useful if the user initializes redirtimeout to
    186  1.63       kml 	 * something other than zero.
    187  1.63       kml 	 */
    188  1.63       kml 	if (icmp_redirtimeout != 0) {
    189  1.63       kml 		icmp_redirect_timeout_q =
    190  1.63       kml 			rt_timer_queue_create(icmp_redirtimeout);
    191  1.63       kml 	}
    192  1.63       kml }
    193  1.63       kml 
    194   1.1       cgd /*
    195  1.55   thorpej  * Register a Path MTU Discovery callback.
    196  1.55   thorpej  */
    197  1.55   thorpej void
    198  1.55   thorpej icmp_mtudisc_callback_register(func)
    199  1.55   thorpej 	void (*func) __P((struct in_addr));
    200  1.55   thorpej {
    201  1.57    itojun 	struct icmp_mtudisc_callback *mc;
    202  1.55   thorpej 
    203  1.55   thorpej 	for (mc = LIST_FIRST(&icmp_mtudisc_callbacks); mc != NULL;
    204  1.55   thorpej 	     mc = LIST_NEXT(mc, mc_list)) {
    205  1.55   thorpej 		if (mc->mc_func == func)
    206  1.55   thorpej 			return;
    207  1.55   thorpej 	}
    208  1.55   thorpej 
    209  1.55   thorpej 	mc = malloc(sizeof(*mc), M_PCB, M_NOWAIT);
    210  1.55   thorpej 	if (mc == NULL)
    211  1.55   thorpej 		panic("icmp_mtudisc_callback_register");
    212  1.55   thorpej 
    213  1.55   thorpej 	mc->mc_func = func;
    214  1.55   thorpej 	LIST_INSERT_HEAD(&icmp_mtudisc_callbacks, mc, mc_list);
    215  1.55   thorpej }
    216  1.55   thorpej 
    217  1.55   thorpej /*
    218   1.1       cgd  * Generate an error packet of type error
    219   1.1       cgd  * in response to bad packet ip.
    220   1.1       cgd  */
    221   1.6   mycroft void
    222   1.9   mycroft icmp_error(n, type, code, dest, destifp)
    223   1.1       cgd 	struct mbuf *n;
    224   1.1       cgd 	int type, code;
    225   1.9   mycroft 	n_long dest;
    226   1.9   mycroft 	struct ifnet *destifp;
    227   1.1       cgd {
    228  1.44  augustss 	struct ip *oip = mtod(n, struct ip *), *nip;
    229  1.44  augustss 	unsigned oiplen = oip->ip_hl << 2;
    230  1.44  augustss 	struct icmp *icp;
    231  1.44  augustss 	struct mbuf *m;
    232  1.52  sommerfe 	unsigned icmplen, mblen;
    233   1.1       cgd 
    234   1.1       cgd #ifdef ICMPPRINTFS
    235   1.1       cgd 	if (icmpprintfs)
    236  1.22  christos 		printf("icmp_error(%x, %d, %d)\n", oip, type, code);
    237   1.1       cgd #endif
    238   1.1       cgd 	if (type != ICMP_REDIRECT)
    239   1.1       cgd 		icmpstat.icps_error++;
    240   1.1       cgd 	/*
    241  1.42    itojun 	 * Don't send error if the original packet was encrypted.
    242   1.1       cgd 	 * Don't send error if not the first fragment of message.
    243   1.1       cgd 	 * Don't error if the old packet protocol was ICMP
    244   1.1       cgd 	 * error message, only known informational types.
    245   1.1       cgd 	 */
    246  1.42    itojun 	if (n->m_flags & M_DECRYPTED)
    247  1.42    itojun 		goto freeit;
    248   1.1       cgd 	if (oip->ip_off &~ (IP_MF|IP_DF))
    249   1.1       cgd 		goto freeit;
    250   1.1       cgd 	if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
    251   1.1       cgd 	  n->m_len >= oiplen + ICMP_MINLEN &&
    252   1.1       cgd 	  !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {
    253   1.1       cgd 		icmpstat.icps_oldicmp++;
    254   1.1       cgd 		goto freeit;
    255   1.1       cgd 	}
    256   1.3   hpeyerl 	/* Don't send error in response to a multicast or broadcast packet */
    257   1.9   mycroft 	if (n->m_flags & (M_BCAST|M_MCAST))
    258   1.3   hpeyerl 		goto freeit;
    259  1.40   thorpej 
    260   1.1       cgd 	/*
    261  1.40   thorpej 	 * First, do a rate limitation check.
    262  1.40   thorpej 	 */
    263  1.40   thorpej 	if (icmp_ratelimit(&oip->ip_src, type, code)) {
    264  1.40   thorpej 		/* XXX stat */
    265  1.40   thorpej 		goto freeit;
    266  1.40   thorpej 	}
    267  1.40   thorpej 
    268  1.40   thorpej 	/*
    269  1.40   thorpej 	 * Now, formulate icmp message
    270   1.1       cgd 	 */
    271  1.52  sommerfe 	icmplen = oiplen + min(icmpreturndatabytes, oip->ip_len - oiplen);
    272  1.52  sommerfe 	/*
    273  1.52  sommerfe 	 * Defend against mbuf chains shorter than oip->ip_len:
    274  1.52  sommerfe 	 */
    275  1.52  sommerfe 	mblen = 0;
    276  1.52  sommerfe 	for (m = n; m && (mblen < icmplen); m = m->m_next)
    277  1.52  sommerfe 		mblen += m->m_len;
    278  1.52  sommerfe 	icmplen = min(mblen, icmplen);
    279  1.52  sommerfe 
    280  1.52  sommerfe 	/*
    281  1.52  sommerfe 	 * As we are not required to return everything we have,
    282  1.52  sommerfe 	 * we return whatever we can return at ease.
    283  1.52  sommerfe 	 *
    284  1.52  sommerfe 	 * Note that ICMP datagrams longer than 576 octets are out of spec
    285  1.52  sommerfe 	 * according to RFC1812; the limit on icmpreturndatabytes below in
    286  1.52  sommerfe 	 * icmp_sysctl will keep things below that limit.
    287  1.52  sommerfe 	 */
    288  1.52  sommerfe 
    289  1.52  sommerfe 	KASSERT(ICMP_MINLEN <= MCLBYTES);
    290  1.52  sommerfe 
    291  1.52  sommerfe 	if (icmplen + ICMP_MINLEN > MCLBYTES)
    292  1.52  sommerfe 		icmplen = MCLBYTES - ICMP_MINLEN;
    293  1.52  sommerfe 
    294   1.1       cgd 	m = m_gethdr(M_DONTWAIT, MT_HEADER);
    295  1.52  sommerfe 	if (m && (icmplen + ICMP_MINLEN > MHLEN)) {
    296  1.52  sommerfe 		MCLGET(m, M_DONTWAIT);
    297  1.52  sommerfe 		if ((m->m_flags & M_EXT) == 0) {
    298  1.52  sommerfe 			m_freem(m);
    299  1.52  sommerfe 			m = NULL;
    300  1.52  sommerfe 		}
    301  1.52  sommerfe 	}
    302   1.1       cgd 	if (m == NULL)
    303   1.1       cgd 		goto freeit;
    304   1.1       cgd 	m->m_len = icmplen + ICMP_MINLEN;
    305  1.52  sommerfe 	if ((m->m_flags & M_EXT) == 0)
    306  1.52  sommerfe 		MH_ALIGN(m, m->m_len);
    307   1.1       cgd 	icp = mtod(m, struct icmp *);
    308   1.1       cgd 	if ((u_int)type > ICMP_MAXTYPE)
    309   1.1       cgd 		panic("icmp_error");
    310   1.1       cgd 	icmpstat.icps_outhist[type]++;
    311   1.1       cgd 	icp->icmp_type = type;
    312   1.1       cgd 	if (type == ICMP_REDIRECT)
    313   1.9   mycroft 		icp->icmp_gwaddr.s_addr = dest;
    314   1.9   mycroft 	else {
    315   1.1       cgd 		icp->icmp_void = 0;
    316   1.9   mycroft 		/*
    317   1.9   mycroft 		 * The following assignments assume an overlay with the
    318   1.9   mycroft 		 * zeroed icmp_void field.
    319   1.9   mycroft 		 */
    320   1.9   mycroft 		if (type == ICMP_PARAMPROB) {
    321   1.9   mycroft 			icp->icmp_pptr = code;
    322   1.9   mycroft 			code = 0;
    323   1.9   mycroft 		} else if (type == ICMP_UNREACH &&
    324  1.12       cgd 		    code == ICMP_UNREACH_NEEDFRAG && destifp)
    325   1.9   mycroft 			icp->icmp_nextmtu = htons(destifp->if_mtu);
    326   1.1       cgd 	}
    327   1.9   mycroft 
    328  1.32   thorpej 	HTONS(oip->ip_off);
    329  1.32   thorpej 	HTONS(oip->ip_len);
    330   1.1       cgd 	icp->icmp_code = code;
    331  1.47   darrenr 	m_copydata(n, 0, icmplen, (caddr_t)&icp->icmp_ip);
    332   1.1       cgd 	nip = &icp->icmp_ip;
    333   1.1       cgd 
    334   1.1       cgd 	/*
    335   1.1       cgd 	 * Now, copy old ip header (without options)
    336   1.1       cgd 	 * in front of icmp message.
    337   1.1       cgd 	 */
    338   1.1       cgd 	if (m->m_data - sizeof(struct ip) < m->m_pktdat)
    339   1.1       cgd 		panic("icmp len");
    340   1.1       cgd 	m->m_data -= sizeof(struct ip);
    341   1.1       cgd 	m->m_len += sizeof(struct ip);
    342   1.1       cgd 	m->m_pkthdr.len = m->m_len;
    343   1.1       cgd 	m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
    344   1.1       cgd 	nip = mtod(m, struct ip *);
    345  1.47   darrenr 	/* ip_v set in ip_output */
    346  1.47   darrenr 	nip->ip_hl = sizeof(struct ip) >> 2;
    347  1.47   darrenr 	nip->ip_tos = 0;
    348   1.1       cgd 	nip->ip_len = m->m_len;
    349  1.47   darrenr 	/* ip_id set in ip_output */
    350  1.47   darrenr 	nip->ip_off = 0;
    351  1.47   darrenr 	/* ip_ttl set in icmp_reflect */
    352   1.1       cgd 	nip->ip_p = IPPROTO_ICMP;
    353  1.47   darrenr 	nip->ip_src = oip->ip_src;
    354  1.47   darrenr 	nip->ip_dst = oip->ip_dst;
    355   1.1       cgd 	icmp_reflect(m);
    356   1.1       cgd 
    357   1.1       cgd freeit:
    358   1.1       cgd 	m_freem(n);
    359   1.1       cgd }
    360   1.1       cgd 
    361   1.1       cgd static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };
    362   1.1       cgd static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };
    363   1.1       cgd static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };
    364   1.1       cgd struct sockaddr_in icmpmask = { 8, 0 };
    365   1.1       cgd 
    366   1.1       cgd /*
    367   1.1       cgd  * Process a received ICMP message.
    368   1.1       cgd  */
    369   1.6   mycroft void
    370  1.19  christos #if __STDC__
    371  1.19  christos icmp_input(struct mbuf *m, ...)
    372  1.19  christos #else
    373  1.19  christos icmp_input(m, va_alist)
    374  1.19  christos 	struct mbuf *m;
    375  1.19  christos 	va_dcl
    376  1.19  christos #endif
    377   1.1       cgd {
    378  1.37    itojun 	int proto;
    379  1.44  augustss 	struct icmp *icp;
    380  1.44  augustss 	struct ip *ip = mtod(m, struct ip *);
    381  1.34   mycroft 	int icmplen;
    382  1.44  augustss 	int i;
    383   1.1       cgd 	struct in_ifaddr *ia;
    384  1.19  christos 	void *(*ctlfunc) __P((int, struct sockaddr *, void *));
    385   1.9   mycroft 	int code;
    386  1.19  christos 	int hlen;
    387  1.19  christos 	va_list ap;
    388  1.63       kml 	struct rtentry *rt;
    389  1.19  christos 
    390  1.19  christos 	va_start(ap, m);
    391  1.19  christos 	hlen = va_arg(ap, int);
    392  1.37    itojun 	proto = va_arg(ap, int);
    393  1.19  christos 	va_end(ap);
    394   1.1       cgd 
    395   1.1       cgd 	/*
    396   1.1       cgd 	 * Locate icmp structure in mbuf, and check
    397   1.1       cgd 	 * that not corrupted and of at least minimum length.
    398   1.1       cgd 	 */
    399  1.34   mycroft 	icmplen = ip->ip_len - hlen;
    400   1.1       cgd #ifdef ICMPPRINTFS
    401   1.1       cgd 	if (icmpprintfs)
    402  1.22  christos 		printf("icmp_input from %x to %x, len %d\n",
    403  1.20   mycroft 		    ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr),
    404  1.20   mycroft 		    icmplen);
    405   1.1       cgd #endif
    406   1.1       cgd 	if (icmplen < ICMP_MINLEN) {
    407   1.1       cgd 		icmpstat.icps_tooshort++;
    408   1.1       cgd 		goto freeit;
    409   1.1       cgd 	}
    410   1.9   mycroft 	i = hlen + min(icmplen, ICMP_ADVLENMIN);
    411  1.20   mycroft 	if (m->m_len < i && (m = m_pullup(m, i)) == 0) {
    412   1.1       cgd 		icmpstat.icps_tooshort++;
    413   1.1       cgd 		return;
    414   1.1       cgd 	}
    415   1.5   mycroft 	ip = mtod(m, struct ip *);
    416   1.1       cgd 	m->m_len -= hlen;
    417   1.1       cgd 	m->m_data += hlen;
    418   1.1       cgd 	icp = mtod(m, struct icmp *);
    419   1.1       cgd 	if (in_cksum(m, icmplen)) {
    420   1.1       cgd 		icmpstat.icps_checksum++;
    421   1.1       cgd 		goto freeit;
    422   1.1       cgd 	}
    423   1.1       cgd 	m->m_len += hlen;
    424   1.1       cgd 	m->m_data -= hlen;
    425   1.1       cgd 
    426   1.1       cgd #ifdef ICMPPRINTFS
    427   1.1       cgd 	/*
    428   1.1       cgd 	 * Message type specific processing.
    429   1.1       cgd 	 */
    430   1.1       cgd 	if (icmpprintfs)
    431  1.22  christos 		printf("icmp_input, type %d code %d\n", icp->icmp_type,
    432   1.1       cgd 		    icp->icmp_code);
    433  1.37    itojun #endif
    434   1.1       cgd 	if (icp->icmp_type > ICMP_MAXTYPE)
    435   1.1       cgd 		goto raw;
    436   1.1       cgd 	icmpstat.icps_inhist[icp->icmp_type]++;
    437   1.1       cgd 	code = icp->icmp_code;
    438   1.1       cgd 	switch (icp->icmp_type) {
    439   1.1       cgd 
    440   1.1       cgd 	case ICMP_UNREACH:
    441   1.9   mycroft 		switch (code) {
    442   1.9   mycroft 			case ICMP_UNREACH_NET:
    443   1.9   mycroft 			case ICMP_UNREACH_HOST:
    444   1.9   mycroft 			case ICMP_UNREACH_PROTOCOL:
    445   1.9   mycroft 			case ICMP_UNREACH_PORT:
    446   1.9   mycroft 			case ICMP_UNREACH_SRCFAIL:
    447   1.9   mycroft 				code += PRC_UNREACH_NET;
    448   1.9   mycroft 				break;
    449   1.9   mycroft 
    450   1.9   mycroft 			case ICMP_UNREACH_NEEDFRAG:
    451   1.9   mycroft 				code = PRC_MSGSIZE;
    452   1.9   mycroft 				break;
    453   1.9   mycroft 
    454   1.9   mycroft 			case ICMP_UNREACH_NET_UNKNOWN:
    455   1.9   mycroft 			case ICMP_UNREACH_NET_PROHIB:
    456   1.9   mycroft 			case ICMP_UNREACH_TOSNET:
    457   1.9   mycroft 				code = PRC_UNREACH_NET;
    458   1.9   mycroft 				break;
    459   1.9   mycroft 
    460   1.9   mycroft 			case ICMP_UNREACH_HOST_UNKNOWN:
    461   1.9   mycroft 			case ICMP_UNREACH_ISOLATED:
    462   1.9   mycroft 			case ICMP_UNREACH_HOST_PROHIB:
    463   1.9   mycroft 			case ICMP_UNREACH_TOSHOST:
    464   1.9   mycroft 				code = PRC_UNREACH_HOST;
    465   1.9   mycroft 				break;
    466   1.9   mycroft 
    467   1.9   mycroft 			default:
    468   1.9   mycroft 				goto badcode;
    469   1.9   mycroft 		}
    470   1.1       cgd 		goto deliver;
    471   1.1       cgd 
    472   1.1       cgd 	case ICMP_TIMXCEED:
    473   1.1       cgd 		if (code > 1)
    474   1.1       cgd 			goto badcode;
    475   1.1       cgd 		code += PRC_TIMXCEED_INTRANS;
    476   1.1       cgd 		goto deliver;
    477   1.1       cgd 
    478   1.1       cgd 	case ICMP_PARAMPROB:
    479   1.9   mycroft 		if (code > 1)
    480   1.1       cgd 			goto badcode;
    481   1.1       cgd 		code = PRC_PARAMPROB;
    482   1.1       cgd 		goto deliver;
    483   1.1       cgd 
    484   1.1       cgd 	case ICMP_SOURCEQUENCH:
    485   1.1       cgd 		if (code)
    486   1.1       cgd 			goto badcode;
    487   1.1       cgd 		code = PRC_QUENCH;
    488  1.20   mycroft 		goto deliver;
    489  1.20   mycroft 
    490   1.1       cgd 	deliver:
    491   1.1       cgd 		/*
    492   1.1       cgd 		 * Problem with datagram; advise higher level routines.
    493   1.1       cgd 		 */
    494   1.1       cgd 		if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
    495   1.1       cgd 		    icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
    496   1.1       cgd 			icmpstat.icps_badlen++;
    497   1.1       cgd 			goto freeit;
    498   1.1       cgd 		}
    499  1.14   mycroft 		if (IN_MULTICAST(icp->icmp_ip.ip_dst.s_addr))
    500  1.13   mycroft 			goto badcode;
    501   1.1       cgd 		NTOHS(icp->icmp_ip.ip_len);
    502   1.1       cgd #ifdef ICMPPRINTFS
    503   1.1       cgd 		if (icmpprintfs)
    504  1.22  christos 			printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
    505   1.1       cgd #endif
    506   1.1       cgd 		icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
    507  1.19  christos 		ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput;
    508  1.19  christos 		if (ctlfunc)
    509  1.55   thorpej 			(void) (*ctlfunc)(code, sintosa(&icmpsrc),
    510  1.55   thorpej 			    &icp->icmp_ip);
    511   1.1       cgd 		break;
    512   1.1       cgd 
    513   1.1       cgd 	badcode:
    514   1.1       cgd 		icmpstat.icps_badcode++;
    515   1.1       cgd 		break;
    516   1.1       cgd 
    517   1.1       cgd 	case ICMP_ECHO:
    518   1.1       cgd 		icp->icmp_type = ICMP_ECHOREPLY;
    519   1.1       cgd 		goto reflect;
    520   1.1       cgd 
    521   1.1       cgd 	case ICMP_TSTAMP:
    522   1.1       cgd 		if (icmplen < ICMP_TSLEN) {
    523   1.1       cgd 			icmpstat.icps_badlen++;
    524   1.1       cgd 			break;
    525   1.1       cgd 		}
    526   1.1       cgd 		icp->icmp_type = ICMP_TSTAMPREPLY;
    527   1.1       cgd 		icp->icmp_rtime = iptime();
    528   1.1       cgd 		icp->icmp_ttime = icp->icmp_rtime;	/* bogus, do later! */
    529   1.1       cgd 		goto reflect;
    530   1.9   mycroft 
    531   1.9   mycroft 	case ICMP_MASKREQ:
    532   1.9   mycroft 		if (icmpmaskrepl == 0)
    533   1.9   mycroft 			break;
    534   1.9   mycroft 		/*
    535   1.9   mycroft 		 * We are not able to respond with all ones broadcast
    536   1.9   mycroft 		 * unless we receive it over a point-to-point interface.
    537   1.9   mycroft 		 */
    538  1.23   thorpej 		if (icmplen < ICMP_MASKLEN) {
    539  1.23   thorpej 			icmpstat.icps_badlen++;
    540   1.9   mycroft 			break;
    541  1.23   thorpej 		}
    542  1.15   mycroft 		if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
    543  1.20   mycroft 		    in_nullhost(ip->ip_dst))
    544   1.9   mycroft 			icmpdst.sin_addr = ip->ip_src;
    545  1.15   mycroft 		else
    546   1.9   mycroft 			icmpdst.sin_addr = ip->ip_dst;
    547  1.16   mycroft 		ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst),
    548  1.16   mycroft 		    m->m_pkthdr.rcvif));
    549   1.9   mycroft 		if (ia == 0)
    550   1.1       cgd 			break;
    551   1.1       cgd 		icp->icmp_type = ICMP_MASKREPLY;
    552   1.1       cgd 		icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
    553  1.20   mycroft 		if (in_nullhost(ip->ip_src)) {
    554   1.1       cgd 			if (ia->ia_ifp->if_flags & IFF_BROADCAST)
    555  1.17   mycroft 				ip->ip_src = ia->ia_broadaddr.sin_addr;
    556   1.1       cgd 			else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
    557  1.17   mycroft 				ip->ip_src = ia->ia_dstaddr.sin_addr;
    558   1.1       cgd 		}
    559   1.1       cgd reflect:
    560   1.1       cgd 		icmpstat.icps_reflect++;
    561   1.1       cgd 		icmpstat.icps_outhist[icp->icmp_type]++;
    562   1.1       cgd 		icmp_reflect(m);
    563   1.1       cgd 		return;
    564   1.1       cgd 
    565   1.1       cgd 	case ICMP_REDIRECT:
    566   1.9   mycroft 		if (code > 3)
    567   1.9   mycroft 			goto badcode;
    568  1.63       kml 		if (icmp_rediraccept == 0)
    569  1.63       kml 			goto freeit;
    570   1.9   mycroft 		if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
    571   1.9   mycroft 		    icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
    572   1.1       cgd 			icmpstat.icps_badlen++;
    573   1.1       cgd 			break;
    574   1.1       cgd 		}
    575   1.1       cgd 		/*
    576   1.1       cgd 		 * Short circuit routing redirects to force
    577   1.1       cgd 		 * immediate change in the kernel's routing
    578   1.1       cgd 		 * tables.  The message is also handed to anyone
    579   1.1       cgd 		 * listening on a raw socket (e.g. the routing
    580   1.1       cgd 		 * daemon for use in updating its tables).
    581   1.1       cgd 		 */
    582   1.1       cgd 		icmpgw.sin_addr = ip->ip_src;
    583   1.1       cgd 		icmpdst.sin_addr = icp->icmp_gwaddr;
    584   1.1       cgd #ifdef	ICMPPRINTFS
    585   1.1       cgd 		if (icmpprintfs)
    586  1.22  christos 			printf("redirect dst %x to %x\n", icp->icmp_ip.ip_dst,
    587  1.20   mycroft 			    icp->icmp_gwaddr);
    588   1.1       cgd #endif
    589   1.9   mycroft 		icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
    590  1.63       kml 		rt = NULL;
    591  1.16   mycroft 		rtredirect(sintosa(&icmpsrc), sintosa(&icmpdst),
    592  1.12       cgd 		    (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
    593  1.63       kml 		    sintosa(&icmpgw), (struct rtentry **)&rt);
    594  1.63       kml 		if (rt != NULL && icmp_redirtimeout != 0) {
    595  1.63       kml 			i = rt_timer_add(rt, icmp_redirect_timeout,
    596  1.63       kml 					 icmp_redirect_timeout_q);
    597  1.63       kml 			if (i)
    598  1.63       kml 				log(LOG_ERR, "ICMP:  redirect failed to "
    599  1.63       kml 				    "register timeout for route to %x, "
    600  1.63       kml 				    "code %d\n",
    601  1.63       kml 				    icp->icmp_ip.ip_dst.s_addr, i);
    602  1.63       kml 		}
    603  1.63       kml 		if (rt != NULL)
    604  1.63       kml 			rtfree(rt);
    605  1.63       kml 
    606  1.16   mycroft 		pfctlinput(PRC_REDIRECT_HOST, sintosa(&icmpsrc));
    607  1.37    itojun #ifdef IPSEC
    608  1.37    itojun 		key_sa_routechange((struct sockaddr *)&icmpsrc);
    609  1.37    itojun #endif
    610   1.1       cgd 		break;
    611   1.1       cgd 
    612   1.1       cgd 	/*
    613   1.1       cgd 	 * No kernel processing for the following;
    614   1.1       cgd 	 * just fall through to send to raw listener.
    615   1.1       cgd 	 */
    616   1.1       cgd 	case ICMP_ECHOREPLY:
    617   1.9   mycroft 	case ICMP_ROUTERADVERT:
    618   1.9   mycroft 	case ICMP_ROUTERSOLICIT:
    619   1.1       cgd 	case ICMP_TSTAMPREPLY:
    620   1.1       cgd 	case ICMP_IREQREPLY:
    621   1.1       cgd 	case ICMP_MASKREPLY:
    622   1.1       cgd 	default:
    623   1.1       cgd 		break;
    624   1.1       cgd 	}
    625   1.1       cgd 
    626   1.1       cgd raw:
    627  1.37    itojun 	rip_input(m, hlen, proto);
    628   1.1       cgd 	return;
    629   1.1       cgd 
    630   1.1       cgd freeit:
    631   1.1       cgd 	m_freem(m);
    632  1.37    itojun 	return;
    633   1.1       cgd }
    634   1.1       cgd 
    635   1.1       cgd /*
    636   1.1       cgd  * Reflect the ip packet back to the source
    637   1.1       cgd  */
    638   1.6   mycroft void
    639   1.1       cgd icmp_reflect(m)
    640   1.1       cgd 	struct mbuf *m;
    641   1.1       cgd {
    642  1.44  augustss 	struct ip *ip = mtod(m, struct ip *);
    643  1.44  augustss 	struct in_ifaddr *ia;
    644  1.44  augustss 	struct ifaddr *ifa;
    645  1.39  sommerfe 	struct sockaddr_in *sin = 0;
    646   1.1       cgd 	struct in_addr t;
    647  1.19  christos 	struct mbuf *opts = 0;
    648   1.1       cgd 	int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
    649   1.1       cgd 
    650   1.9   mycroft 	if (!in_canforward(ip->ip_src) &&
    651  1.14   mycroft 	    ((ip->ip_src.s_addr & IN_CLASSA_NET) !=
    652  1.14   mycroft 	     htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) {
    653   1.9   mycroft 		m_freem(m);	/* Bad return address */
    654  1.12       cgd 		goto done;	/* ip_output() will check for broadcast */
    655   1.9   mycroft 	}
    656   1.1       cgd 	t = ip->ip_dst;
    657   1.1       cgd 	ip->ip_dst = ip->ip_src;
    658   1.1       cgd 	/*
    659  1.39  sommerfe 	 * If the incoming packet was addressed directly to us, use
    660  1.39  sommerfe 	 * dst as the src for the reply.  Otherwise (broadcast or
    661  1.39  sommerfe 	 * anonymous), use an address which corresponds to the
    662  1.39  sommerfe 	 * incoming interface, with a preference for the address which
    663  1.39  sommerfe 	 * corresponds to the route to the destination of the ICMP.
    664   1.1       cgd 	 */
    665  1.39  sommerfe 
    666  1.39  sommerfe 	/* Look for packet addressed to us */
    667  1.27       tls 	INADDR_TO_IA(t, ia);
    668  1.39  sommerfe 
    669  1.39  sommerfe 	/* look for packet sent to broadcast address */
    670  1.27       tls 	if (ia == NULL && (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST)) {
    671  1.65      matt 		TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrlist, ifa_list) {
    672  1.27       tls 			if (ifa->ifa_addr->sa_family != AF_INET)
    673  1.27       tls 				continue;
    674  1.39  sommerfe 			if (in_hosteq(t,ifatoia(ifa)->ia_broadaddr.sin_addr)) {
    675  1.39  sommerfe 				ia = ifatoia(ifa);
    676  1.27       tls 				break;
    677  1.39  sommerfe 			}
    678  1.27       tls 		}
    679   1.1       cgd 	}
    680  1.27       tls 
    681  1.39  sommerfe 	if (ia)
    682  1.39  sommerfe 		sin = &ia->ia_addr;
    683  1.39  sommerfe 
    684   1.9   mycroft 	icmpdst.sin_addr = t;
    685  1.39  sommerfe 
    686  1.39  sommerfe 	/* if the packet is addressed somewhere else, compute the
    687  1.39  sommerfe 	   source address for packets routed back to the source, and
    688  1.39  sommerfe 	   use that, if it's an address on the interface which
    689  1.39  sommerfe 	   received the packet */
    690  1.39  sommerfe 	if (sin == (struct sockaddr_in *)0) {
    691  1.39  sommerfe 		struct sockaddr_in sin_dst;
    692  1.39  sommerfe 		struct route icmproute;
    693  1.39  sommerfe 		int errornum;
    694  1.39  sommerfe 
    695  1.39  sommerfe 		sin_dst.sin_family = AF_INET;
    696  1.39  sommerfe 		sin_dst.sin_len = sizeof(struct sockaddr_in);
    697  1.39  sommerfe 		sin_dst.sin_addr = ip->ip_dst;
    698  1.39  sommerfe 		bzero(&icmproute, sizeof(icmproute));
    699  1.39  sommerfe 		errornum = 0;
    700  1.39  sommerfe 		sin = in_selectsrc(&sin_dst, &icmproute, 0, NULL, &errornum);
    701  1.39  sommerfe 		/* errornum is never used */
    702  1.39  sommerfe 		if (icmproute.ro_rt)
    703  1.39  sommerfe 			RTFREE(icmproute.ro_rt);
    704  1.39  sommerfe 		/* check to make sure sin is a source address on rcvif */
    705  1.39  sommerfe 		if (sin) {
    706  1.39  sommerfe 			t = sin->sin_addr;
    707  1.39  sommerfe 			sin = (struct sockaddr_in *)0;
    708  1.39  sommerfe 			INADDR_TO_IA(t, ia);
    709  1.39  sommerfe 			while (ia) {
    710  1.39  sommerfe 				if (ia->ia_ifp == m->m_pkthdr.rcvif) {
    711  1.39  sommerfe 					sin = &ia->ia_addr;
    712  1.39  sommerfe 					break;
    713  1.39  sommerfe 				}
    714  1.39  sommerfe 				NEXT_IA_WITH_SAME_ADDR(ia);
    715  1.39  sommerfe 			}
    716  1.39  sommerfe 		}
    717  1.39  sommerfe 	}
    718  1.39  sommerfe 
    719  1.39  sommerfe 	/* if it was not addressed to us, but the route doesn't go out
    720  1.39  sommerfe 	   the source interface, pick an address on the source
    721  1.39  sommerfe 	   interface.  This can happen when routing is asymmetric, or
    722  1.39  sommerfe 	   when the incoming packet was encapsulated */
    723  1.39  sommerfe 	if (sin == (struct sockaddr_in *)0) {
    724  1.65      matt 		TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrlist, ifa_list) {
    725  1.39  sommerfe 			if (ifa->ifa_addr->sa_family != AF_INET)
    726  1.39  sommerfe 				continue;
    727  1.39  sommerfe 			sin = &(ifatoia(ifa)->ia_addr);
    728  1.39  sommerfe 			break;
    729  1.39  sommerfe 		}
    730  1.39  sommerfe 	}
    731  1.39  sommerfe 
    732   1.9   mycroft 	/*
    733   1.9   mycroft 	 * The following happens if the packet was not addressed to us,
    734  1.27       tls 	 * and was received on an interface with no IP address:
    735  1.27       tls 	 * We find the first AF_INET address on the first non-loopback
    736  1.27       tls 	 * interface.
    737   1.9   mycroft 	 */
    738  1.39  sommerfe 	if (sin == (struct sockaddr_in *)0)
    739  1.65      matt 		TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
    740  1.27       tls 			if (ia->ia_ifp->if_flags & IFF_LOOPBACK)
    741  1.27       tls 				continue;
    742  1.39  sommerfe 			sin = &ia->ia_addr;
    743  1.27       tls 			break;
    744  1.27       tls 		}
    745  1.39  sommerfe 
    746  1.36   mycroft 	/*
    747  1.36   mycroft 	 * If we still didn't find an address, punt.  We could have an
    748  1.36   mycroft 	 * interface up (and receiving packets) with no address.
    749  1.36   mycroft 	 */
    750  1.39  sommerfe 	if (sin == (struct sockaddr_in *)0) {
    751  1.36   mycroft 		m_freem(m);
    752  1.36   mycroft 		goto done;
    753  1.36   mycroft 	}
    754  1.36   mycroft 
    755  1.39  sommerfe 	ip->ip_src = sin->sin_addr;
    756   1.1       cgd 	ip->ip_ttl = MAXTTL;
    757   1.1       cgd 
    758   1.1       cgd 	if (optlen > 0) {
    759  1.44  augustss 		u_char *cp;
    760   1.1       cgd 		int opt, cnt;
    761   1.1       cgd 		u_int len;
    762   1.1       cgd 
    763   1.1       cgd 		/*
    764   1.1       cgd 		 * Retrieve any source routing from the incoming packet;
    765   1.1       cgd 		 * add on any record-route or timestamp options.
    766   1.1       cgd 		 */
    767   1.1       cgd 		cp = (u_char *) (ip + 1);
    768   1.1       cgd 		if ((opts = ip_srcroute()) == 0 &&
    769   1.1       cgd 		    (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
    770   1.1       cgd 			opts->m_len = sizeof(struct in_addr);
    771  1.20   mycroft 			*mtod(opts, struct in_addr *) = zeroin_addr;
    772   1.1       cgd 		}
    773   1.1       cgd 		if (opts) {
    774   1.1       cgd #ifdef ICMPPRINTFS
    775   1.1       cgd 		    if (icmpprintfs)
    776  1.22  christos 			    printf("icmp_reflect optlen %d rt %d => ",
    777   1.1       cgd 				optlen, opts->m_len);
    778   1.1       cgd #endif
    779   1.1       cgd 		    for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
    780   1.1       cgd 			    opt = cp[IPOPT_OPTVAL];
    781   1.1       cgd 			    if (opt == IPOPT_EOL)
    782   1.1       cgd 				    break;
    783   1.1       cgd 			    if (opt == IPOPT_NOP)
    784   1.1       cgd 				    len = 1;
    785   1.1       cgd 			    else {
    786  1.45    itojun 				    if (cnt < IPOPT_OLEN + sizeof(*cp))
    787  1.45    itojun 					    break;
    788   1.1       cgd 				    len = cp[IPOPT_OLEN];
    789  1.45    itojun 				    if (len < IPOPT_OLEN + sizeof(*cp) ||
    790  1.45    itojun 				        len > cnt)
    791   1.1       cgd 					    break;
    792   1.1       cgd 			    }
    793   1.1       cgd 			    /*
    794   1.9   mycroft 			     * Should check for overflow, but it "can't happen"
    795   1.1       cgd 			     */
    796   1.9   mycroft 			    if (opt == IPOPT_RR || opt == IPOPT_TS ||
    797   1.9   mycroft 				opt == IPOPT_SECURITY) {
    798   1.1       cgd 				    bcopy((caddr_t)cp,
    799   1.1       cgd 					mtod(opts, caddr_t) + opts->m_len, len);
    800   1.1       cgd 				    opts->m_len += len;
    801   1.1       cgd 			    }
    802   1.1       cgd 		    }
    803   1.9   mycroft 		    /* Terminate & pad, if necessary */
    804  1.19  christos 		    if ((cnt = opts->m_len % 4) != 0) {
    805   1.9   mycroft 			    for (; cnt < 4; cnt++) {
    806   1.9   mycroft 				    *(mtod(opts, caddr_t) + opts->m_len) =
    807   1.9   mycroft 					IPOPT_EOL;
    808   1.9   mycroft 				    opts->m_len++;
    809   1.9   mycroft 			    }
    810   1.1       cgd 		    }
    811   1.1       cgd #ifdef ICMPPRINTFS
    812   1.1       cgd 		    if (icmpprintfs)
    813  1.22  christos 			    printf("%d\n", opts->m_len);
    814   1.1       cgd #endif
    815   1.1       cgd 		}
    816   1.1       cgd 		/*
    817   1.1       cgd 		 * Now strip out original options by copying rest of first
    818   1.1       cgd 		 * mbuf's data back, and adjust the IP length.
    819   1.1       cgd 		 */
    820   1.1       cgd 		ip->ip_len -= optlen;
    821   1.1       cgd 		ip->ip_hl = sizeof(struct ip) >> 2;
    822   1.1       cgd 		m->m_len -= optlen;
    823   1.1       cgd 		if (m->m_flags & M_PKTHDR)
    824   1.1       cgd 			m->m_pkthdr.len -= optlen;
    825   1.1       cgd 		optlen += sizeof(struct ip);
    826   1.1       cgd 		bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
    827   1.1       cgd 			 (unsigned)(m->m_len - sizeof(struct ip)));
    828   1.1       cgd 	}
    829   1.3   hpeyerl 	m->m_flags &= ~(M_BCAST|M_MCAST);
    830   1.1       cgd 	icmp_send(m, opts);
    831   1.9   mycroft done:
    832   1.1       cgd 	if (opts)
    833   1.1       cgd 		(void)m_free(opts);
    834   1.1       cgd }
    835   1.1       cgd 
    836   1.1       cgd /*
    837   1.1       cgd  * Send an icmp packet back to the ip level,
    838   1.1       cgd  * after supplying a checksum.
    839   1.1       cgd  */
    840   1.6   mycroft void
    841   1.1       cgd icmp_send(m, opts)
    842  1.44  augustss 	struct mbuf *m;
    843   1.1       cgd 	struct mbuf *opts;
    844   1.1       cgd {
    845  1.44  augustss 	struct ip *ip = mtod(m, struct ip *);
    846  1.44  augustss 	int hlen;
    847  1.44  augustss 	struct icmp *icp;
    848   1.1       cgd 
    849   1.1       cgd 	hlen = ip->ip_hl << 2;
    850   1.1       cgd 	m->m_data += hlen;
    851   1.1       cgd 	m->m_len -= hlen;
    852   1.1       cgd 	icp = mtod(m, struct icmp *);
    853   1.1       cgd 	icp->icmp_cksum = 0;
    854   1.1       cgd 	icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
    855   1.1       cgd 	m->m_data -= hlen;
    856   1.1       cgd 	m->m_len += hlen;
    857   1.1       cgd #ifdef ICMPPRINTFS
    858   1.1       cgd 	if (icmpprintfs)
    859  1.22  christos 		printf("icmp_send dst %x src %x\n", ip->ip_dst, ip->ip_src);
    860   1.1       cgd #endif
    861  1.37    itojun #ifdef IPSEC
    862  1.43    itojun 	/* Don't lookup socket */
    863  1.58    itojun 	(void)ipsec_setsocket(m, NULL);
    864  1.43    itojun #endif
    865   1.7   mycroft 	(void) ip_output(m, opts, NULL, 0, NULL);
    866   1.1       cgd }
    867   1.1       cgd 
    868   1.1       cgd n_time
    869   1.1       cgd iptime()
    870   1.1       cgd {
    871   1.1       cgd 	struct timeval atv;
    872   1.1       cgd 	u_long t;
    873   1.1       cgd 
    874   1.1       cgd 	microtime(&atv);
    875   1.1       cgd 	t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
    876   1.1       cgd 	return (htonl(t));
    877   1.9   mycroft }
    878   1.9   mycroft 
    879   1.9   mycroft int
    880   1.9   mycroft icmp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
    881   1.9   mycroft 	int *name;
    882   1.9   mycroft 	u_int namelen;
    883   1.9   mycroft 	void *oldp;
    884   1.9   mycroft 	size_t *oldlenp;
    885   1.9   mycroft 	void *newp;
    886   1.9   mycroft 	size_t newlen;
    887   1.9   mycroft {
    888  1.54    itojun 	int arg, error;
    889   1.9   mycroft 
    890   1.9   mycroft 	/* All sysctl names at this level are terminal. */
    891   1.9   mycroft 	if (namelen != 1)
    892   1.9   mycroft 		return (ENOTDIR);
    893   1.9   mycroft 
    894  1.47   darrenr 	switch (name[0])
    895  1.47   darrenr 	{
    896   1.9   mycroft 	case ICMPCTL_MASKREPL:
    897  1.47   darrenr 		error = sysctl_int(oldp, oldlenp, newp, newlen, &icmpmaskrepl);
    898  1.47   darrenr 		break;
    899  1.47   darrenr 	case ICMPCTL_RETURNDATABYTES:
    900  1.47   darrenr 		arg = icmpreturndatabytes;
    901  1.47   darrenr 		error = sysctl_int(oldp, oldlenp, newp, newlen, &arg);
    902  1.40   thorpej 		if (error)
    903  1.47   darrenr 			break;
    904  1.47   darrenr 		if ((arg >= 8) || (arg <= 512))
    905  1.47   darrenr 			icmpreturndatabytes = arg;
    906  1.47   darrenr 		else
    907  1.47   darrenr 			error = EINVAL;
    908  1.47   darrenr 		break;
    909  1.51    itojun 	case ICMPCTL_ERRPPSLIMIT:
    910  1.51    itojun 		error = sysctl_int(oldp, oldlenp, newp, newlen, &icmperrppslim);
    911  1.51    itojun 		break;
    912  1.63       kml 	case ICMPCTL_REDIRACCEPT:
    913  1.63       kml 		error = sysctl_int(oldp, oldlenp, newp, newlen,
    914  1.63       kml 				   &icmp_rediraccept);
    915  1.63       kml 		break;
    916  1.63       kml 	case ICMPCTL_REDIRTIMEOUT:
    917  1.63       kml 		error = sysctl_int(oldp, oldlenp, newp, newlen,
    918  1.63       kml 				   &icmp_redirtimeout);
    919  1.63       kml 		if (icmp_redirect_timeout_q != NULL) {
    920  1.63       kml 			if (icmp_redirtimeout == 0) {
    921  1.63       kml 				rt_timer_queue_destroy(icmp_redirect_timeout_q,
    922  1.63       kml 						       TRUE);
    923  1.63       kml 				icmp_redirect_timeout_q = NULL;
    924  1.63       kml 			} else {
    925  1.63       kml 				rt_timer_queue_change(icmp_redirect_timeout_q,
    926  1.63       kml 						      icmp_redirtimeout);
    927  1.63       kml 			}
    928  1.63       kml 		} else if (icmp_redirtimeout > 0) {
    929  1.63       kml 			icmp_redirect_timeout_q =
    930  1.63       kml 				rt_timer_queue_create(icmp_redirtimeout);
    931  1.63       kml 		}
    932  1.63       kml 		return (error);
    933  1.63       kml 
    934  1.63       kml 		break;
    935   1.9   mycroft 	default:
    936  1.47   darrenr 		error = ENOPROTOOPT;
    937  1.47   darrenr 		break;
    938   1.9   mycroft 	}
    939  1.47   darrenr 	return error;
    940  1.24       kml }
    941  1.24       kml 
    942  1.64      matt /* Table of common MTUs: */
    943  1.64      matt 
    944  1.64      matt static const u_int mtu_table[] = {
    945  1.64      matt 	65535, 65280, 32000, 17914, 9180, 8166,
    946  1.64      matt 	4352, 2002, 1492, 1006, 508, 296, 68, 0
    947  1.64      matt };
    948  1.64      matt 
    949  1.55   thorpej void
    950  1.55   thorpej icmp_mtudisc(icp, faddr)
    951  1.24       kml 	struct icmp *icp;
    952  1.55   thorpej 	struct in_addr faddr;
    953  1.24       kml {
    954  1.57    itojun 	struct icmp_mtudisc_callback *mc;
    955  1.55   thorpej 	struct sockaddr *dst = sintosa(&icmpsrc);
    956  1.24       kml 	struct rtentry *rt;
    957  1.26       kml 	u_long mtu = ntohs(icp->icmp_nextmtu);  /* Why a long?  IPv6 */
    958  1.29       kml 	int    error;
    959  1.24       kml 
    960  1.24       kml 	rt = rtalloc1(dst, 1);
    961  1.24       kml 	if (rt == 0)
    962  1.24       kml 		return;
    963  1.24       kml 
    964  1.24       kml 	/* If we didn't get a host route, allocate one */
    965  1.24       kml 
    966  1.24       kml 	if ((rt->rt_flags & RTF_HOST) == 0) {
    967  1.24       kml 		struct rtentry *nrt;
    968  1.24       kml 
    969  1.24       kml 		error = rtrequest((int) RTM_ADD, dst,
    970  1.24       kml 		    (struct sockaddr *) rt->rt_gateway,
    971  1.24       kml 		    (struct sockaddr *) 0,
    972  1.24       kml 		    RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC, &nrt);
    973  1.24       kml 		if (error) {
    974  1.24       kml 			rtfree(rt);
    975  1.24       kml 			return;
    976  1.24       kml 		}
    977  1.24       kml 		nrt->rt_rmx = rt->rt_rmx;
    978  1.24       kml 		rtfree(rt);
    979  1.24       kml 		rt = nrt;
    980  1.24       kml 	}
    981  1.29       kml 	error = rt_timer_add(rt, icmp_mtudisc_timeout, ip_mtudisc_timeout_q);
    982  1.29       kml 	if (error) {
    983  1.29       kml 		rtfree(rt);
    984  1.29       kml 		return;
    985  1.29       kml 	}
    986  1.24       kml 
    987  1.24       kml 	if (mtu == 0) {
    988  1.24       kml 		int i = 0;
    989  1.24       kml 
    990  1.26       kml 		mtu = icp->icmp_ip.ip_len; /* NTOHS happened in deliver: */
    991  1.24       kml 		/* Some 4.2BSD-based routers incorrectly adjust the ip_len */
    992  1.24       kml 		if (mtu > rt->rt_rmx.rmx_mtu && rt->rt_rmx.rmx_mtu != 0)
    993  1.24       kml 			mtu -= (icp->icmp_ip.ip_hl << 2);
    994  1.24       kml 
    995  1.26       kml 		/* If we still can't guess a value, try the route */
    996  1.26       kml 
    997  1.26       kml 		if (mtu == 0) {
    998  1.24       kml 			mtu = rt->rt_rmx.rmx_mtu;
    999  1.24       kml 
   1000  1.26       kml 			/* If no route mtu, default to the interface mtu */
   1001  1.26       kml 
   1002  1.26       kml 			if (mtu == 0)
   1003  1.26       kml 				mtu = rt->rt_ifp->if_mtu;
   1004  1.26       kml 		}
   1005  1.26       kml 
   1006  1.24       kml 		for (i = 0; i < sizeof(mtu_table) / sizeof(mtu_table[0]); i++)
   1007  1.26       kml 			if (mtu > mtu_table[i]) {
   1008  1.26       kml 				mtu = mtu_table[i];
   1009  1.24       kml 				break;
   1010  1.26       kml 			}
   1011  1.24       kml 	}
   1012  1.24       kml 
   1013  1.29       kml 	/*
   1014  1.29       kml 	 * XXX:   RTV_MTU is overloaded, since the admin can set it
   1015  1.29       kml 	 *	  to turn off PMTU for a route, and the kernel can
   1016  1.29       kml 	 *	  set it to indicate a serious problem with PMTU
   1017  1.29       kml 	 *	  on a route.  We should be using a separate flag
   1018  1.29       kml 	 *	  for the kernel to indicate this.
   1019  1.29       kml 	 */
   1020  1.29       kml 
   1021  1.24       kml 	if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) {
   1022  1.26       kml 		if (mtu < 296 || mtu > rt->rt_ifp->if_mtu)
   1023  1.24       kml 			rt->rt_rmx.rmx_locks |= RTV_MTU;
   1024  1.24       kml 		else if (rt->rt_rmx.rmx_mtu > mtu ||
   1025  1.56    itojun 			 rt->rt_rmx.rmx_mtu == 0) {
   1026  1.56    itojun 			icmpstat.icps_pmtuchg++;
   1027  1.24       kml 			rt->rt_rmx.rmx_mtu = mtu;
   1028  1.56    itojun 		}
   1029  1.24       kml 	}
   1030  1.26       kml 
   1031  1.24       kml 	if (rt)
   1032  1.24       kml 		rtfree(rt);
   1033  1.55   thorpej 
   1034  1.55   thorpej 	/*
   1035  1.55   thorpej 	 * Notify protocols that the MTU for this destination
   1036  1.55   thorpej 	 * has changed.
   1037  1.55   thorpej 	 */
   1038  1.55   thorpej 	for (mc = LIST_FIRST(&icmp_mtudisc_callbacks); mc != NULL;
   1039  1.55   thorpej 	     mc = LIST_NEXT(mc, mc_list))
   1040  1.55   thorpej 		(*mc->mc_func)(faddr);
   1041  1.37    itojun }
   1042  1.37    itojun 
   1043  1.37    itojun /*
   1044  1.37    itojun  * Return the next larger or smaller MTU plateau (table from RFC 1191)
   1045  1.37    itojun  * given current value MTU.  If DIR is less than zero, a larger plateau
   1046  1.37    itojun  * is returned; otherwise, a smaller value is returned.
   1047  1.37    itojun  */
   1048  1.37    itojun int
   1049  1.37    itojun ip_next_mtu(mtu, dir)	/* XXX */
   1050  1.37    itojun 	int mtu;
   1051  1.37    itojun 	int dir;
   1052  1.37    itojun {
   1053  1.37    itojun 	int i;
   1054  1.37    itojun 
   1055  1.64      matt 	for (i = 0; i < (sizeof mtu_table) / (sizeof mtu_table[0]); i++) {
   1056  1.64      matt 		if (mtu >= mtu_table[i])
   1057  1.37    itojun 			break;
   1058  1.37    itojun 	}
   1059  1.37    itojun 
   1060  1.37    itojun 	if (dir < 0) {
   1061  1.37    itojun 		if (i == 0) {
   1062  1.37    itojun 			return 0;
   1063  1.37    itojun 		} else {
   1064  1.64      matt 			return mtu_table[i - 1];
   1065  1.37    itojun 		}
   1066  1.37    itojun 	} else {
   1067  1.64      matt 		if (mtu_table[i] == 0) {
   1068  1.37    itojun 			return 0;
   1069  1.64      matt 		} else if (mtu > mtu_table[i]) {
   1070  1.64      matt 			return mtu_table[i];
   1071  1.37    itojun 		} else {
   1072  1.64      matt 			return mtu_table[i + 1];
   1073  1.37    itojun 		}
   1074  1.37    itojun 	}
   1075  1.29       kml }
   1076  1.29       kml 
   1077  1.29       kml static void
   1078  1.29       kml icmp_mtudisc_timeout(rt, r)
   1079  1.29       kml 	struct rtentry *rt;
   1080  1.29       kml 	struct rttimer *r;
   1081  1.29       kml {
   1082  1.29       kml 	if (rt == NULL)
   1083  1.29       kml 		panic("icmp_mtudisc_timeout:  bad route to timeout");
   1084  1.29       kml 	if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) ==
   1085  1.29       kml 	    (RTF_DYNAMIC | RTF_HOST)) {
   1086  1.29       kml 		rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt),
   1087  1.29       kml 		    rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
   1088  1.29       kml 	} else {
   1089  1.29       kml 		if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) {
   1090  1.29       kml 			rt->rt_rmx.rmx_mtu = 0;
   1091  1.29       kml 		}
   1092  1.63       kml 	}
   1093  1.63       kml }
   1094  1.63       kml 
   1095  1.63       kml static void
   1096  1.63       kml icmp_redirect_timeout(rt, r)
   1097  1.63       kml 	struct rtentry *rt;
   1098  1.63       kml 	struct rttimer *r;
   1099  1.63       kml {
   1100  1.63       kml 	if (rt == NULL)
   1101  1.63       kml 		panic("icmp_redirect_timeout:  bad route to timeout");
   1102  1.63       kml 	if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) ==
   1103  1.63       kml 	    (RTF_DYNAMIC | RTF_HOST)) {
   1104  1.63       kml 		rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt),
   1105  1.63       kml 		    rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
   1106  1.29       kml 	}
   1107  1.40   thorpej }
   1108  1.40   thorpej 
   1109  1.40   thorpej /*
   1110  1.40   thorpej  * Perform rate limit check.
   1111  1.40   thorpej  * Returns 0 if it is okay to send the icmp packet.
   1112  1.40   thorpej  * Returns 1 if the router SHOULD NOT send this icmp packet due to rate
   1113  1.40   thorpej  * limitation.
   1114  1.40   thorpej  *
   1115  1.40   thorpej  * XXX per-destination/type check necessary?
   1116  1.40   thorpej  */
   1117  1.40   thorpej static int
   1118  1.40   thorpej icmp_ratelimit(dst, type, code)
   1119  1.49  sommerfe 	const struct in_addr *dst;
   1120  1.40   thorpej 	const int type;			/* not used at this moment */
   1121  1.40   thorpej 	const int code;			/* not used at this moment */
   1122  1.40   thorpej {
   1123  1.40   thorpej 
   1124  1.51    itojun 	/* PPS limit */
   1125  1.51    itojun 	if (!ppsratecheck(&icmperrppslim_last, &icmperrpps_count,
   1126  1.51    itojun 	    icmperrppslim)) {
   1127  1.51    itojun 		/* The packet is subject to rate limit */
   1128  1.51    itojun 		return 1;
   1129  1.51    itojun 	}
   1130  1.51    itojun 
   1131  1.51    itojun 	/*okay to send*/
   1132  1.51    itojun 	return 0;
   1133   1.1       cgd }
   1134