pcicmp.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 561 行 · 第 1/2 页

C
561
字号
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "copyrigh.h"
#include "wattcp.h"
#include "strings.h"
#include "language.h"
#include "chksum.h"
#include "misc.h"
#include "pctcp.h"
#include "pcsed.h"
#include "pcarp.h"
#include "pcbsd.h"
#include "pcstat.h"
#include "pcdbug.h"
#include "pcconfig.h"
#include "pcqueue.h"
#include "pcpkt.h"
#include "sock_ini.h"
#include "ip_out.h"
#include "pcicmp.h"

/*
 * ICMP - RFC 792
 */

const char *icmp_type_str [ICMP_MAXTYPE+1] = {
      __LANG("Echo Reply"),  "1", "2",
      __LANG("Destination Unreachable"),
      __LANG("Source Quench"),
      __LANG("Redirect"),    "6", "7",
      __LANG("Echo Request"),
      __LANG("Router Advert"),
      __LANG("Router Solic"),
      __LANG("TTL exceeded"),
      __LANG("Param Problem"),
      __LANG("Timestamp Message"),
      __LANG("Timestamp Reply"),
      __LANG("Info Request"),
      __LANG("Info Reply"),
      __LANG("Mask Request"),
      __LANG("Mask Reply")
    };

const char *icmp_unreach_str [16] = {
      __LANG("Network Unreachable"),
      __LANG("Host Unreachable"),
      __LANG("Protocol Unreachable"),
      __LANG("Port Unreachable"),
      __LANG("Fragmentation needed and DF set"),
      __LANG("Source Route Failed"),
      __LANG("Network unknown"),
      __LANG("Host unknown"),
      __LANG("Source host isolated"),
      __LANG("Net-access denied"),
      __LANG("Host-access denied"),
      __LANG("Bad TOS for net"),
      __LANG("Bad TOS for host"),
      __LANG("Admin prohibited"),
      __LANG("Host precedence violation"),
      __LANG("Precedence cutoff")
    };

const char *icmp_redirect_str [4] = {
      __LANG("Redirect for Network"),
      __LANG("Redirect for Host"),
      __LANG("Redirect for TOS and Network"),
      __LANG("Redirect for TOS and Host")
    };

const char *icmp_exceed_str [2] = {
      __LANG("TTL exceeded in transit"),
      __LANG("Frag ReAsm time exceeded")
    };

#include <sys/packon.h>

struct _pkt {
       in_Header  in;
       ICMP_PKT   icmp;
       in_Header  data;
     };

#include <sys/packoff.h>

static struct {
       char  icmp;
       char  igmp;
       char  udp;
       char  tcp;
     } do_redirect = { 1,1,1,1 };

static DWORD ping_hcache = 0;   /* host */
static DWORD ping_tcache = 0;   /* time */
static DWORD ping_number = 0;


DWORD _chk_ping (DWORD host, DWORD *ping_num)
{
  if (ping_hcache == host)
  {
    ping_hcache = 0xFFFFFFFFL;
    *ping_num = ping_number;
    return (ping_tcache);
  }
  return (0xFFFFFFFFL);
}


static void icmp_print (int dbg_lvl, const char *msg, DWORD src)
{
  if (debug_on < dbg_lvl)
     return;

  outs ("\r\nICMP: ");
  if (src)
  {
    char adr[20];
    outs ("(");
    outs (_inet_ntoa(adr,intel(src)));
    outs ("): ");
  }
  outsnl (_LANG(msg));
}

/*
 * print info about bogus and possibly dangerous ICMP messages
 * e.g. "ICMP: (144.133.122.111) Bogus Redirect; GW = 111.110.109.108"
 */
static void icmp_bogus (const in_Header *ip, int type, const char *msg)
{
  char buf[100];

  strcpy (buf, _LANG("Bogus "));
  strcat (buf, icmp_type_str[type]);
  if (msg)
     strcat (buf, msg);
  icmp_print (1, buf, ip->source);
}

#ifdef NOT_USED
/*
 */
void *icmp_Format (DWORD host)
{
  mac_address dest;

  /* We use ARP rather than supplied hardware address.
   * After first ping this will still be in cache.
   */
  if (!_arp_resolve(host,&dest,0))  /* unable to find address */
     return (NULL);     

  return _eth_formatpacket (&dest, IP_TYPE);
}
#endif


/*
 * Check if ip-source is a (directed) broadcast address.
 * Some hacker may try to create a broadcast storm.
 * Also check for null source address (0.0.0.0).
 * Broadcast destination is already filtered out by icmp_handler().
 */
static int icmp_chk_src (const in_Header *ip, int type)
{
  BOOL bcast = (~intel(ip->source) & ~sin_mask) == 0;

  if (bcast)
  {
    icmp_bogus (ip, type, _LANG(" (broadcast)"));
    return (0);
  }
  if (ip->source == 0UL)
  {
    icmp_bogus (ip, type, _LANG(" (network)"));
    return (0);
  }
  return (1);
}

/*
 * icmp_send - format and send a ICMP packet
 *           - note that src and dest are network order.
 */
static int icmp_send (struct _pkt *pkt, DWORD src, DWORD dest, int length)
{
  in_Header *ip   = &pkt->in;
  ICMP_PKT  *icmp = &pkt->icmp;

  icmp->unused.checksum = 0;
  icmp->unused.checksum = ~checksum (icmp, length);

  return IP_OUTPUT (ip, src, dest, ICMP_PROTO, 0, 0, 0, length, NULL);
}

/*
 *  Send an ICMP destination/protocol unreachable back to ip->source
 */
void icmp_unreach (const in_Header *ip, int code)
{
  struct _pkt    *pkt;
  union icmp_pkt *unr;
  int             len;

  if (!icmp_chk_src(ip,ICMP_UNREACH))
     return;

  pkt = (struct _pkt*) _eth_formatpacket (MAC_SRC(ip), IP_TYPE);
  unr = &pkt->icmp;
  len = intel16 (ip->length) - in_GetHdrLen (ip);
  len = min (len, sizeof(*ip)+sizeof(unr->unused.spares));

  icmp_print (1, icmp_unreach_str[code], ip->destination);
  memcpy (&unr->unused.ip, ip, len);
  unr->unused.type = ICMP_UNREACH;
  unr->unused.code = code;

  icmp_send (pkt, ip->destination, ip->source, sizeof(unr->unused));
}

/*
 *  Send an "ICMP Time Exceeded" (reassebly timeout) back to 'ip->source'
 */
void icmp_timexceed (const in_Header *ip, const void *mac_dest)
{
  struct _pkt    *pkt;
  union icmp_pkt *tim;
  int             len;

  if (!icmp_chk_src(ip,ICMP_TIMXCEED))
     return;

  pkt = (struct _pkt*) _eth_formatpacket (mac_dest, IP_TYPE);
  tim = &pkt->icmp;
  len = intel16 (ip->length) - in_GetHdrLen (ip);
  len = min (len, sizeof(*ip) + sizeof(tim->unused.spares));

  icmp_print (1, icmp_exceed_str[1], ip->destination);
  memcpy (&tim->unused.ip, ip, len);
  tim->unused.type = ICMP_TIMXCEED;
  tim->unused.code = 1;

  icmp_send (pkt, ip->destination, ip->source, sizeof(tim->unused));
}

/*
 *  Send an ICMP Address Mask Request as link-layer + IP broadcast
 *  Even if we know our address, we send with src = 0.0.0.0.
 */
static WORD addr_mask_id  = 0;
static WORD addr_mask_seq = 0;

void icmp_mask_req (void)
{
  mac_address    *dst = (_pktserial ? NULL : &_eth_brdcast);
  struct _pkt    *pkt = (struct _pkt*) _eth_formatpacket (dst, IP_TYPE);
  union icmp_pkt *req = &pkt->icmp;

  addr_mask_id = (WORD) set_timeout (0);   /* get a random ID */
  req->mask.type       = ICMP_MASKREQ;
  req->mask.code       = 0;
  req->mask.identifier = addr_mask_id;
  req->mask.sequence   = addr_mask_seq++;
  req->mask.mask       = 0;
  icmp_send (pkt, 0, (DWORD)INADDR_BROADCAST, sizeof(req->mask));
}

/*
 *  Handler for incoming ICMP packets
 */
void icmp_handler (const in_Header *ip, BOOL broadcast)
{
  union icmp_pkt *icmp;
  in_Header      *orig_ip;
  int             len, type, code;
  BOOL            for_me, i_orig;  /* is it for me, did I originate it */
  const char     *msg;

  DEBUG_RX (NULL, ip);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?