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