📄 ip_icmp.c
字号:
/* ip_icmp.c - internet ICMP routines *//* Copyright 1984 - 2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 *//*modification history--------------------03h,18apr02,vvv removed incorrect icmpmaskrepl initialization from icmp_init (SPR #74338)03g,18dec01,vvv reflect messages with correct source address (SPR #71684)03f,12oct01,rae merge from truestack ver 03j, base 03e (SPRs 69344, 69683 etc)03e,16mar99,spm recovered orphaned code from tor2_0_x branch (SPR #25770)03d,09feb99,ham fixed SPR#24975.03c,31jan97,vin changed declaration according to prototype decl in protosw.h03b,07jan96,vin added icmp_init(..) for scalability, moved iptime to ip_input.c03a,31oct96,vin changed m_gethdr(..) to mHdrClGet(..).02u,24aug96,vin integrated with BSD44 and 02t of ip_icmp.c.*//* * ICMP routines: error generation, receive packet processing, and * routines to turnaround packets back to the originator, and * host table maintenance routines. */#include "vxWorks.h"#include "net/mbuf.h"#include "net/protosw.h"#include "sys/socket.h"#include "sys/ioctl.h"#include "net/systm.h"#include "net/route.h"#include "net/if.h"#include "net/if_types.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_var.h"#include "netinet/ip.h"#include "netinet/ip_var.h"#include "netinet/ip_icmp.h"#include "netinet/icmp_var.h"#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET#include "wvNetLib.h"#endif#endif#ifdef VIRTUAL_STACK#include "netinet/vsLib.h"#endif /* VIRTUAL_STACK *//* defines */#ifndef VIRTUAL_STACK#define MAXTABLESIZE 64 /* * smallest cluster limits setsockopt() * routine to 64 2-byte integers */#endif /* VIRTUAL_STACK */#define PATHMTU_MIN 68 /* Lowest allowable path MTU estimate *//* externs */extern void pfctlinput ();#ifndef VIRTUAL_STACKextern struct protosw inetsw[];extern VOIDFUNCPTR _icmpErrorHook; #endif /* VIRTUAL_STACK *//* globals */#ifndef VIRTUAL_STACKstruct icmpstat icmpstat;struct sockaddr_in icmpmask = { 8, 0 };int icmpmaskrepl = 0;#ifdef ICMPPRINTFSint icmpprintfs = 0;#endif#endif /* VIRTUAL_STACK *//* locals */#ifndef VIRTUAL_STACKstatic struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };LOCAL u_short mtuTable [MAXTABLESIZE] = {68, 296, 508, 1006, 1492, 2002, 4352, 8166, 17914, 32000, 65535};LOCAL int mtuTableSize = 11;#endif /* VIRTUAL_STACK *//* forward declarations */static void icmp_error (struct mbuf *, int, int, n_long, struct ifnet *);static void icmp_reflect (struct mbuf *);static void icmp_send (struct mbuf *, struct mbuf *);LOCAL void ip_next_mtu (struct sockaddr *, int);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* Set common fields of event identifiers for this module. */LOCAL UCHAR wvNetModuleId = WV_NET_IPICMP_MODULE; /* Value for ip_icmp.c */LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE; /* Available event filter */LOCAL ULONG wvNetEventId; /* Event identifier: see wvNetLib.h */#endif /* INCLUDE_WVNET */#endifvoidicmp_init(){ if (_icmpErrorHook == NULL) /* initialize the hook if not null */ _icmpErrorHook = icmp_error; #ifdef ICMPPRINTFS icmpprintfs = 0;#endif icmpsrc.sin_len = sizeof(struct sockaddr_in); icmpsrc.sin_family = AF_INET; icmpdst.sin_len = sizeof(struct sockaddr_in); icmpdst.sin_family = AF_INET; icmpgw.sin_len = sizeof(struct sockaddr_in); icmpgw.sin_family = AF_INET; mtuTable[0] = 68; mtuTable[1] = 296; mtuTable[2] = 508; mtuTable[3] = 1006; mtuTable[4] = 1492; mtuTable[5] = 2002; mtuTable[6] = 4352; mtuTable[7] = 8166; mtuTable[8] = 17914; mtuTable[9] = 32000; mtuTable[10] = 65535; mtuTableSize = 11;}/* * ICMP routines: error generation, receive packet processing, and * routines to turnaround packets back to the originator, and * host table maintenance routines. *//* * Generate an error packet of type error * in response to bad packet ip. */static voidicmp_error(n, type, code, dest, destifp) struct mbuf *n; int type, code; n_long dest; struct ifnet *destifp;{ register struct ip *oip = mtod(n, struct ip *), *nip; register unsigned oiplen = oip->ip_hl << 2; register struct icmp *icp; register struct mbuf *m; MTU_QUERY mtuQuery; unsigned icmplen; short offset;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY or WV_NET_ALERT event */ if (type == ICMP_SOURCEQUENCH) /* ENOBUFS error: out of memory. */ { WV_NET_MARKER_2 (NET_CORE_EVENT, WV_NET_EMERGENCY, 9, 2, WV_NETEVENT_ICMPERR_START, type, code) } else { WV_NET_MARKER_2 (NET_CORE_EVENT, WV_NET_CRITICAL, 8, 2, WV_NETEVENT_ICMPERR_START, type, code) }#endif /* INCLUDE_WVNET */#endif#ifdef ICMPPRINTFS if (icmpprintfs) printf("icmp_error(%x, %d, %d)\n", oip, type, code);#endif if (type != ICMP_REDIRECT) {#ifdef VIRTUAL_STACK _icmpstat.icps_error++;#else icmpstat.icps_error++;#endif /* VIRTUAL_STACK */ offset = oip->ip_off; } else { /* * If ICMP_REDIRECT, offset field is in network host order * (changed when ip_output forwarded this packet). We need it * to be in host order for the processing. */ offset = ntohs (oip->ip_off); } /* * Don't send error if not the first fragment of message. * Don't error if the old packet protocol was ICMP * error message, only known informational types. */ if (offset &~ (IP_MF|IP_DF)) goto freeit; if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && n->m_len >= oiplen + ICMP_MINLEN && !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {#ifdef VIRTUAL_STACK _icmpstat.icps_oldicmp++;#else icmpstat.icps_oldicmp++;#endif /* VIRTUAL_STACK */ goto freeit; } /* Don't send error in response to a multicast or broadcast packet */ if (n->m_flags & (M_BCAST|M_MCAST)) goto freeit; /* * First, formulate icmp message */ if ((m = mHdrClGet(M_DONTWAIT, MT_HEADER, CL_SIZE_128, TRUE)) == NULL) goto freeit; icmplen = oiplen + min(8, oip->ip_len); m->m_len = icmplen + ICMP_MINLEN; MH_ALIGN(m, m->m_len); icp = mtod(m, struct icmp *); if ((u_int)type > ICMP_MAXTYPE) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_1 (NET_CORE_EVENT, WV_NET_EMERGENCY, 14, 1, WV_NETEVENT_ICMPERR_PANIC, type)#endif /* INCLUDE_WVNET */#endif panic("icmp_error"); }#ifdef VIRTUAL_STACK _icmpstat.icps_outhist[type]++;#else icmpstat.icps_outhist[type]++;#endif /* VIRTUAL_STACK */ icp->icmp_type = type; if (type == ICMP_REDIRECT) icp->icmp_gwaddr.s_addr = dest; else { icp->icmp_void = 0; /* * The following assignments assume an overlay with the * zeroed icmp_void field. */ if (type == ICMP_PARAMPROB) { icp->icmp_pptr = code; code = 0; } else if (type == ICMP_UNREACH && code == ICMP_UNREACH_NEEDFRAG && destifp) { /* * Point-to-multipoint devices allow a separate MTU * for each destination address. Get that value or * leave the next MTU unspecified if not available. */ if (destifp->if_type == IFT_PMP) { mtuQuery.family = AF_INET; mtuQuery.dstIpAddr = dest; if (destifp->if_ioctl (destifp, SIOCGMTU, (caddr_t) &mtuQuery) == 0) { icp->icmp_nextmtu = htons (mtuQuery.mtu); } } else { icp->icmp_nextmtu = htons(destifp->if_mtu); } } } icp->icmp_code = code; bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen); nip = &icp->icmp_ip; if (type != ICMP_REDIRECT) { /* * If ICMP_REDIRECT, these changes have already been made in * ip_output when the packet was forwarded. */ nip->ip_len = htons((u_short)(nip->ip_len + oiplen)); HTONS (nip->ip_id); HTONS (nip->ip_off); } /* * Now, copy old ip header (without options) * in front of icmp message. */ if (m->m_data - sizeof(struct ip) < m->m_extBuf) panic("icmp len"); m->m_data -= sizeof(struct ip); m->m_len += sizeof(struct ip); m->m_pkthdr.len = m->m_len; m->m_pkthdr.rcvif = n->m_pkthdr.rcvif; nip = mtod(m, struct ip *); bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip)); nip->ip_len = m->m_len; nip->ip_hl = sizeof(struct ip) >> 2; nip->ip_p = IPPROTO_ICMP; nip->ip_tos = 0; icmp_reflect(m);freeit: m_freem(n);}/* * Process a received ICMP message. */void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -