📄 icmp.c
字号:
/***********************************************************************//* *//* Module: tcp_ip/icmp.c *//* Release: 2001.3 *//* Version: 2001.1 *//* Purpose: ICMP Related Routines *//* *//*---------------------------------------------------------------------*//* *//* Copyright 1999, Blunk Microsystems *//* ALL RIGHTS RESERVED *//* *//* Licensees have the non-exclusive right to use, modify, or extract *//* this computer program for software development at a single site. *//* This program may be resold or disseminated in executable format *//* only. The source code may not be redistributed or resold. *//* *//***********************************************************************/#include "tcp_ipp.h"#include <string.h>#include "ip/ip.h"#include "tcp/tcp.h"/***********************************************************************//* Configuration *//***********************************************************************/#define PING_TBL_SZ 3/***********************************************************************//* Symbol Definitions *//***********************************************************************/#define ICMP_TOS 0x00 /* default ICMP type of service */#define ICMP_HLEN 8 /* bytes */#define SOURCE_QUENCH -1 /* apply2sock() flag *//*** ICMP Type Field*/#define ICT_ECHORP 0 /* echo reply */#define ICT_DESTUR 3 /* destination unreachable */#define ICT_SRCQ 4 /* source quench */#define ICT_REDIRECT 5 /* redirect message type */#define ICT_ECHORQ 8 /* echo request */#define ICT_RTADVERT 9 /* router advertisement */#define ICT_TIMEX 11 /* time exceeded */#define ICT_PARAMP 12 /* parameter problem */#define ICT_TIMERQ 13 /* timestamp request */#define ICT_TIMERP 14 /* timestamp reply */#define ICT_MASKRQ 17 /* mask request */#define ICT_MASKRP 18 /* mask reply *//***********************************************************************//* Type Definitions *//***********************************************************************//*** Simple ICMP Message Structure*/typedef struct{ ui8 type; ui8 code; ui16 checksum; ui32 lword; ui8 datagram[1]; /* header plus 8 bytes of original */} Icmp;/*** ICMP Echo Structure*/typedef struct{ ui8 type; /* 0/8 = request/reply */ ui8 code; ui16 checksum; ui16 identifier; ui16 seq_num; ui8 data[1];} Echo;/*** Mask Request/Reply Structure*/typedef struct{ ui8 type; /* 17/18 = request/reply */ ui8 code; ui16 checksum; ui16 identifier; ui16 seq_num; ui32 mask;} Mask;/*** Ping Table Structure*/typedef struct{ ui16 seq_num; TASK taskid; NetBuf *buf; int soft_error;} PingEntry;/***********************************************************************//* Global Variable Definitions *//***********************************************************************/static PingEntry PingTbl[PING_TBL_SZ];/*** ICMP Error Message Counters*/static uint DstUrNetUr, DstUrHostUr, DstUrProtoUr, DstUrPortUr;static uint DstUrFragReq, DstUrSRCRT, DstUrNetUnk, DstUrHostUnk;static uint DstUrNetTyp, DstUrHostTyp, DstUrCommPro, DstUrPrecVio;static uint DstUrPrecCut, SrcQuench;/***********************************************************************//* Local Function Definitions *//***********************************************************************//***********************************************************************//* icmp_send: Shared ICMP output routine *//* *//* Inputs: buf = buffer to send *//* length = length of data in buffer *//* tos = type of service/priority flag *//* *//***********************************************************************/static void icmp_send(NetBuf *buf, int length, ui8 tos){ Ip *ip = (Ip *)buf->ip_pkt; Route *route; /*-------------------------------------------------------------------*/ /* Route datagram. Drop if no route exists. */ /*-------------------------------------------------------------------*/ route = RtSearch(ip->dst_ip); if (route == NULL) { tcpRetBuf(&buf); return; } /*-------------------------------------------------------------------*/ /* Complete protocol field and pass to IP layer. */ /*-------------------------------------------------------------------*/ ip->protocol = IPT_ICMP; IpSend(route, buf, length, tos);}/***********************************************************************//* simple_msg: Send simple ICMP error responses *//* *//* Inputs: type = ICMP message type *//* code = coded reason that destination is not reachable *//* buf = pointer to buffer containing error packet *//* src = IP address of host that sent packet with error *//* route = pointer to destination route *//* lword = value of long word in ICMP message *//* *//***********************************************************************/static void simple_msg(int type, int code, const NetBuf *buf, ui32 src, ui32 dst, ui32 lword){ NetBuf *reply; Icmp *icmp; Route *route; Ip *ip = (Ip *)buf->ip_pkt; int ip_hlen = IP_HLEN(buf->ip_pkt); /*-------------------------------------------------------------------*/ /* Don't send errors about error packets... */ /*-------------------------------------------------------------------*/ if (ip->protocol == IPT_ICMP) { /*-----------------------------------------------------------------*/ /* Use "type" field to not respond to error responses. */ /*-----------------------------------------------------------------*/ switch (*(ui8 *)buf->ip_data) { case ICT_DESTUR: case ICT_SRCQ: case ICT_REDIRECT: case ICT_TIMEX: case ICT_PARAMP: return; } } /*-------------------------------------------------------------------*/ /* or a fragment other than the first... */ /*-------------------------------------------------------------------*/ if (ip->frag_off & IP_FRAGOFF) return; /*-------------------------------------------------------------------*/ /* or broadcast packets. */ /*-------------------------------------------------------------------*/ route = RtSearch(dst); if ((route == NULL) || (route->flags & RT_BRDCST)) return; /*-------------------------------------------------------------------*/ /* Get a network buffer for error message. */ /*-------------------------------------------------------------------*/ reply = tcpGetBuf(NIMHLEN + IPMHLEN + ICMP_HLEN + 8 + ip_hlen); if (reply == NULL) return; /*-------------------------------------------------------------------*/ /* Error reports include header plus first 8 bytes of datagram. */ /*-------------------------------------------------------------------*/ icmp = reply->ip_data; memcpy(icmp->datagram, buf->ip_pkt, ip_hlen); memcpy(icmp->datagram + ip_hlen, buf->ip_data, 8); /*-------------------------------------------------------------------*/ /* Complete ICMP reply packet fields. */ /*-------------------------------------------------------------------*/ icmp->type = type; icmp->code = code; icmp->lword = lword; /*-------------------------------------------------------------------*/ /* Calculate checksum on completed ICMP packet. */ /*-------------------------------------------------------------------*/ icmp->checksum = 0; icmp->checksum = IpChecksum(icmp, ICMP_HLEN + 8 + ip_hlen); /*-------------------------------------------------------------------*/ /* Send response back to the host that sent the bad packet. */ /*-------------------------------------------------------------------*/ ip = (Ip *)reply->ip_pkt; ip->src_ip = route->ni->ip_addr; ip->dst_ip = src; icmp_send(reply, ICMP_HLEN + 8 + ip_hlen, ICMP_TOS);}/***********************************************************************//* apply2sock: Apply ICMP error to application socket *//* *//* Input: error = socket error code or SOURCE_QUENCH *//* *//***********************************************************************/static void apply2sock(int error){ ui8 *ip_data = RxBuf->ip_data; ui8 protocol; int ip_hlen; ui16 dst_port, src_port; ui32 dst_addr, src_addr; CircLink *link; SOCKET sock; /*-------------------------------------------------------------------*/ /* Read destination and source IP address from original datagram. */ /*-------------------------------------------------------------------*/ memcpy(&dst_addr, ip_data + offsetof(Icmp, datagram) + offsetof(Ip, dst_ip), sizeof(dst_addr)); memcpy(&src_addr, ip_data + offsetof(Icmp, datagram) + offsetof(Ip, src_ip), sizeof(src_addr)); /*-------------------------------------------------------------------*/ /* Read IP protocol and IP header length from original datagram. */ /*-------------------------------------------------------------------*/ protocol = (ip_data + offsetof(Icmp, datagram) + offsetof(Ip, protocol))[0]; ip_hlen = IP_HLEN(ip_data + offsetof(Icmp, datagram)); /*-------------------------------------------------------------------*/ /* Read the destination and source port numbers. */ /*-------------------------------------------------------------------*/ if (protocol == IPT_TCP) { memcpy(&dst_port, ip_data + offsetof(Icmp, datagram) + ip_hlen + + offsetof(Tcp, dst_port), sizeof(dst_port)); memcpy(&src_port, ip_data + offsetof(Icmp, datagram) + ip_hlen + + offsetof(Tcp, src_port), sizeof(src_port)); } else if (protocol == IPT_UDP) { memcpy(&dst_port, ip_data + offsetof(Icmp, datagram) + ip_hlen + + offsetof(Udp, dst_port), sizeof(dst_port)); memcpy(&src_port, ip_data + offsetof(Icmp, datagram) + ip_hlen + + offsetof(Udp, src_port), sizeof(src_port)); } else return; /*-------------------------------------------------------------------*/ /* If error is not source quench, apply to matching UDP socket. */ /*-------------------------------------------------------------------*/ if (error != SOURCE_QUENCH)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -