📄 neticmp.c
字号:
goto freeit;
}
/*
* Message type specific processing.
*/
ICMPDEBUG((LOG_INFO, "icmp_input, type %d code %d\n", icp->icmp_type,
icp->icmp_code));
if (icp->icmp_type > ICMP_MAXTYPE)
goto raw;
icmpStats.icps_inhist[icp->icmp_type]++;
code = icp->icmp_code;
switch (icp->icmp_type) {
case ICMP_UNREACH:
switch (code) {
case ICMP_UNREACH_NET:
case ICMP_UNREACH_HOST:
case ICMP_UNREACH_PROTOCOL:
case ICMP_UNREACH_PORT:
case ICMP_UNREACH_SRCFAIL:
code += PRC_UNREACH_NET;
break;
case ICMP_UNREACH_NEEDFRAG:
code = PRC_MSGSIZE;
break;
case ICMP_UNREACH_NET_UNKNOWN:
case ICMP_UNREACH_NET_PROHIB:
case ICMP_UNREACH_TOSNET:
code = PRC_UNREACH_NET;
break;
case ICMP_UNREACH_HOST_UNKNOWN:
case ICMP_UNREACH_ISOLATED:
case ICMP_UNREACH_HOST_PROHIB:
case ICMP_UNREACH_TOSHOST:
code = PRC_UNREACH_HOST;
break;
default:
goto badcode;
}
goto deliver;
case ICMP_TIMXCEED:
if (code > 1)
goto badcode;
code += PRC_TIMXCEED_INTRANS;
goto deliver;
case ICMP_PARAMPROB:
if (code > 1)
goto badcode;
code = PRC_PARAMPROB;
goto deliver;
case ICMP_SOURCEQUENCH:
if (code)
goto badcode;
code = PRC_QUENCH;
deliver:
/*
* Problem with datagram; advise higher level routines.
*/
if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
icp->icmp_ip.ip_hl < (sizeof(IPHdr) >> 2)) {
icmpStats.icps_badlen++;
goto freeit;
}
NTOHS(icp->icmp_ip.ip_len);
ICMPDEBUG((LOG_INFO, "icmp_input: deliver to protocol %d\n", icp->icmp_ip.ip_p));
icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
#ifdef XXX /* We need a method here of selecting input handlers... */
if (ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput)
(*ctlfunc)(code, (struct sockaddr *)&icmpsrc, &icp->icmp_ip);
#endif
break;
badcode:
icmpStats.icps_badcode++;
break;
case ICMP_ECHO:
icp->icmp_type = ICMP_ECHOREPLY;
goto reflect;
case ICMP_TSTAMP:
if (icmplen < ICMP_TSLEN) {
icmpStats.icps_badlen++;
break;
}
icp->icmp_type = ICMP_TSTAMPREPLY;
icp->icmp_rtime = iptime();
icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */
goto reflect;
case ICMP_MASKREQ:
#ifdef XXX /* Not currently supported... */
#define satosin(sa) ((struct sockaddr_in*)(sa))
if (icmpmaskrepl == 0)
break;
/*
* We are not able to respond with all ones broadcast
* unless we receive it over a point-to-point interface.
*/
if (icmplen < ICMP_MASKLEN)
break;
switch (ip->ip_dst.s_addr) {
case INADDR_BROADCAST:
case INADDR_ANY:
icmpdst.sin_addr = ip->ip_src;
break;
default:
icmpdst.sin_addr = ip->ip_dst;
}
ia = (struct in_ifaddr*)ifaof_ifpforaddr(
(struct sockaddr*)&icmpdst, m->m_pkthdr.rcvif);
if (ia == 0)
break;
icp->icmp_type = ICMP_MASKREPLY;
icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
if (ip->ip_src.s_addr == 0) {
if (ia->ia_ifp->if_flags & IFF_BROADCAST)
ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr;
else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr;
}
#else
break;
#endif
reflect:
#ifdef XXX
/* XXX No longer! */
ip->ip_len += ipHdrLen; /* since ip_input deducts this */
#endif
icmpStats.icps_reflect++;
icmpStats.icps_outhist[icp->icmp_type]++;
icmpReflect(inBuf);
return;
case ICMP_REDIRECT:
#ifdef XXX /* Not currently supported... */
if (code > 3)
goto badcode;
if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
icp->icmp_ip.ip_hl < (sizeof(IPHdr) >> 2)) {
icmpStats.icps_badlen++;
break;
}
/*
* Short circuit routing redirects to force
* immediate change in the kernel's routing
* tables. The message is also handed to anyone
* listening on a raw socket (e.g. the routing
* daemon for use in updating its tables).
*/
icmpgw.sin_addr = ip->ip_src;
icmpdst.sin_addr = icp->icmp_gwaddr;
#ifdef ICMPPRINTFS
if (icmpprintfs)
ICMPDEBUG("redirect dst %x to %x\n", icp->icmp_ip.ip_dst,
icp->icmp_gwaddr);
#endif
icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
rtredirect((struct sockaddr*)&icmpsrc,
(struct sockaddr*)&icmpdst,
(struct sockaddr*)0, RTF_GATEWAY | RTF_HOST,
(struct sockaddr*)&icmpgw, (struct rtentry**)0);
pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr*)&icmpsrc);
#endif
break;
/*
* No kernel processing for the following;
* just fall through to send to raw listener.
*/
case ICMP_ECHOREPLY:
case ICMP_ROUTERADVERT:
case ICMP_ROUTERSOLICIT:
case ICMP_TSTAMPREPLY:
case ICMP_IREQREPLY:
case ICMP_MASKREPLY:
default:
break;
}
raw:
ripInput(inBuf);
return;
freeit:
nFreeChain(inBuf);
}
/**********************************/
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
/*
* Reflect the ip packet back to the source
*/
static void icmpReflect(NBuf* nb)
{
register IPHdr* ip = nBUFTOPTR(nb, IPHdr*);
/* Send back to source, use our address as new source. */
ip->ip_dst = ip->ip_src;
ip->ip_src.s_addr = htonl(localHost);
ip->ip_ttl = MAXTTL;
icmpSend(nb, NULL);
}
/*
* Send an icmp packet back to the ip level,
* after supplying a checksum.
*/
static void icmpSend(register NBuf* nb, NBuf* opts)
{
register IPHdr* ip = nBUFTOPTR(nb, IPHdr*);
register int ipHdrLen;
register IcmpHdr* icp;
/* Compute the ICMP checksum on the datagram body only. */
ipHdrLen = ip->ip_hl << 2;
icp = (IcmpHdr*)(nBUFTOPTR(nb, char*) + ipHdrLen);
icp->icmp_cksum = 0;
icp->icmp_cksum = inChkSum(nb, ip->ip_len - ipHdrLen, ipHdrLen);
ICMPDEBUG((LOG_INFO, "icmp_send %d p%d t%d c%d from %s to %s chk=%X\n",
nb->len, ip->ip_p,
icp->icmp_type, icp->icmp_code,
ip_ntoa(ip->ip_src.s_addr),
ip_ntoa2(ip->ip_dst.s_addr),
icp->icmp_cksum));
ipRawOut(nb);
}
static u_long iptime(void)
{
u_long t;
#if 1
struct tm ctime;
if (clk_stat()) {
gettime(&ctime);
t = ((((u_long)ctime.tm_hour * 24
+ (u_long)ctime.tm_min) * 60
+ (u_long)ctime.tm_sec) * 60
#ifdef XXX /* iptime includes thousands if possible */
+ (u_long)ctime.hund
#endif
) * 10;
} else {
t = 0;
}
#else
t = time(NULL);
#endif
return (htonl(t));
}
#pragma warning (pop)
////////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -