⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcsed.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
     * to-do!!: look in 'fraglist' for a match.
     */
    if (ip_ofs == 0 && (ip_flg & IP_MF) == 0)
       return (union link_Packet*) pkt;

#if defined(USE_FRAGMENTS)
    /* IP-packet is part of a fragment chain. Match with previous
     * fragments and return reassembled IP-packet.
     */
    ip = ip_defragment (ip, ip_ofs, ip_flg);

    pktq_inc_out (q);  /* drop the queued fragment */
    if (!ip)           /* not reassembled yet, or error */
       continue;       /* loop and check for more */

    /*
     * Return the reassembled segment (icmp, udp or tcp).
     * We assume MAC-header is the same on all fragments.
     * We return a packet with the MAC-header of the first
     * fragment received.
     */
    return (union link_Packet*) ((BYTE*)ip - _pkt_ip_ofs);

#else
    pktq_inc_out (q);  /* drop the fragment */
    continue;          /* poll for next */
#endif
  }
  return (NULL);
}


/*
 *  Poll the non-IP (ARP/RARP) queue.
 *  Serial drivers should always return NULL here.
 */
static union link_Packet *poll_arp_queue (WORD *type)
{
  struct pkt_ringbuf *q   = &_pkt_inf->arp_queue;
  union  link_Packet *ret = NULL;

  while (pktq_queued(q))
  {
    char *tail = pktq_out_buf (q);

    if (_pktserial)
    {
      pktq_inc_out (q);
#if defined(USE_DEBUG)
      outsnl (_LANG("Non-IP from serial-type driver !?"));
#endif
      STAT (macstats.num_err_type++);
      continue;
    }

    if (_pktdevclass == PD_TOKEN)
    {
      tok_Header *tr = (tok_Header*) tail;

      fix_tok_head (&tr);
      *type = tr->type;
      ret   = (union link_Packet*) tr;
    }
    else if (_pktdevclass == PD_FDDI)
    {
      *type = ((fddi_Header*) tail)->type;
      ret   = (union link_Packet*) tail;
    }
    else            /* must be PD_ETHER */
    {
      *type = ((eth_Header*) tail)->type;
      ret   = (union link_Packet*) tail;
    }

    if (*type != ARP_TYPE
#if defined(USE_RARP)
       && *type != RARP_TYPE)
#endif
    )
    {
      STAT (macstats.num_err_type++);
      pktq_inc_out (q);    /* drop the packet */
      continue;
    }
    return (ret);
  }
  return (NULL);
}

/*
 *  Poll IP or ARP/RARP queues.
 *  Alternate between ARP/IP on each poll. Or poll other queue if
 *  this queue is empty. Serial drivers should only get an IP-packet.
 *  Return pointer to start of MAC-header or NULL if no packets are
 *  queued.
 *
 *  Not used when e.g. libpcap has set the `_eth_recv_hook' to
 *  do it's own packet-polling.
 */
static union link_Packet *poll_recv_queues (WORD *type)
{
  static int which = 1;   /* start polling IP-queue */
  int    loop;

  ASSERT_PKT_INF (NULL);

#if defined(USE_DEBUG)
  if (!pktq_check(&_pkt_inf->ip_queue))
  {
    fprintf (stderr, "%s: IP-queue destroyed!\n", __FILE__);
    exit (-1);
  }
  if (!pktq_check(&_pkt_inf->arp_queue))
  {
    fprintf (stderr, "%s: ARP-queue destroyed!\n", __FILE__);
    exit (-1);
  }
#endif
                        
  for (loop = 0; loop < 2; loop++)
  {
    union link_Packet *pkt = which ? poll_ip_queue (type)
                                   : poll_arp_queue (type);
    which ^= 1;
    if (pkt)
       return (pkt);
  }
  return (NULL);
}  


/*
 *  _eth_arrived() - poll for new packet (IP/ARP/RARP/PPPoE protocol)
 *  arrival.  Sets protocol-type of packet received.
 *
 *  For Ethernet/TokenRing-type drivers:
 *    The return value points past the MAC-header to the IP/ARP/RARP
 *    protocol header. Also check for link-layer broadcast.
 *
 *  For PPP/SLIP-type drivers (MAC-less links):
 *    The return value points to the IP-packet itself.
 *    IP-protocol is assumed. Can never be link-layer broadcast.
 */
void *_eth_arrived (WORD *type, BOOL *brdcast)
{
  union link_Packet *pkt;
  BOOL  bcast = FALSE;
  void *ret   = NULL;

  if (_eth_recv_hook)
       pkt = (union link_Packet*) (*_eth_recv_hook) (type);
  else pkt = poll_recv_queues (type);

  if (!pkt)
     return (NULL);

  /* If ip_handler() can't be reentered, only accept
   * non-IP packets
   */ 
  if (_ip_recursion && *type == IP_TYPE)
     return (NULL);

  if (_pktserial)
  {
    bcast = FALSE;
    ret   = (void*) &pkt->ip;
  }
  else if (_pktdevclass == PD_TOKEN)
  {
    bcast = (pkt->tok.head.destination[0] & 1);
    ret   = (void*) &pkt->tok.data;
  }
  else if (_pktdevclass == PD_FDDI)
  {
    bcast = (pkt->fddi.head.destination[0] & 1);
    ret   = (void*) &pkt->fddi.data;
  }
  else
  {
    bcast = (pkt->eth.head.destination[0] & 1);
    ret   = (void*) &pkt->eth.data;
  }

  if (intel16(*type) < ETH_MAX)  /* LLC field */
  {
    STAT (macstats.num_llc_frames++);
#if 1
    _eth_free (ret, *type);
    return (NULL);
#else
    /* !!to-do: handle IEEE 802.3 encapsulation also
     */
    fix_llc_head (&ret);
#endif
  }

  update_in_stat (ret, *type);

  if (brdcast)
     *brdcast = bcast;

  return (ret);
}


#if defined(USE_DEBUG)
/*
 * Return pointer to MAC header start address of an IP packet.
 */
void *_eth_mac_hdr (const in_Header *ip)
{
  if (!_pktserial)
     return (void*) ((BYTE*)ip - _pkt_ip_ofs);

  (*_printf) ("Illegal use of `_eth_mac_hdr()' for class %d\r\n",
              _pktdevclass);
  exit (-1);
  /*@-unreachable@*/
  return (NULL);
}

/*
 * Return pointer to MAC source address of an IP packet.
 */
void *_eth_mac_src (const in_Header *ip)
{
  const union link_Packet *pkt;

  pkt = (const union link_Packet*) ((BYTE*)ip - _pkt_ip_ofs);

  if (_pktdevclass == PD_ETHER)
     return (void*) &pkt->eth.head.source;

  if (_pktdevclass == PD_TOKEN)
     return (void*) &pkt->tok.head.source;

  if (_pktdevclass == PD_FDDI)
     return (void*) &pkt->fddi.head.source;

  (*_printf) ("Illegal use of `_eth_mac_src()' for class %d\r\n",
              _pktdevclass);
  exit (-1);
  /*@-unreachable@*/
  return (NULL);
}

/*
 * Return value of protocol-type given an IP packet.
 */
WORD _eth_mac_typ (const in_Header *ip)
{
  const union link_Packet *pkt;

  pkt = (const union link_Packet*) ((BYTE*)ip - _pkt_ip_ofs);

  if (_pktdevclass == PD_ETHER)
     return (pkt->eth.head.type);

  if (_pktdevclass == PD_TOKEN)
     return (pkt->tok.head.type);

  if (_pktdevclass == PD_FDDI)
     return (pkt->fddi.head.type);

  (*_printf) ("Illegal use of `_eth_mac_typ()' for class %d\r\n",
              _pktdevclass);
  exit (-1);
  /*@-unreachable@*/
  return (0);
}
#endif /* USE_DEBUG */


#if defined(USE_LOOPBACK)
/*
 *  _eth_send_loopback() - enqueue a link-layer frame (ip only)
 *                         to the loopback device.
 *
 *  Note: this function uses call-by-value. Thus 'pkt' buffer can
 *  be modified by loopback_device() and loopback handler may send
 *  using _eth_send().
 *
 *  Note: loopback device cannot send to itself (potential recursion)
 */
int _eth_send_loopback (link_Packet pkt)
{
  struct pkt_ringbuf *q;
  const  in_Header   *ip;
  int    ip_len;

  if (!_pkt_inf)
  {
    STAT (ipstats.ips_odropped++); /* maybe this should be an input counter */
    return (0);
  }

  /* Call loopback handler with IP-packet
   */
  ip     = (in_Header*) ((BYTE*)&pkt + _pkt_ip_ofs);
  ip_len = loopback_device ((in_Header*)ip);

  q = &_pkt_inf->ip_queue;

  if (!q || ip_len > ETH_MAX_DATA) /* !!should be MTU of current driver */
  {
    STAT (ipstats.ips_odropped++); /* maybe this should be an input counter */
    return (0);
  }

  if (ip_len > 0)
  {
    union link_Packet *head;

    /* Don't let pkt_receiver() modify the queue while testing/copying.
     */
    DISABLE();

    if (pktq_in_index(q) == q->out_index)  /* queue is full, drop it */
    {
      STAT (ipstats.ips_odropped++);
      q->num_drop++;
      ENABLE();
      return (0);
    }

    head = (union link_Packet*) pktq_in_buf (q);

    /* Enqueue packet to head of input IP-queue.
     */
    if (!_pktserial)
    {
      BYTE *data = (*mac_format) (head, &_eth_addr, IP_TYPE);
      memcpy (MAC_SRC(data), &_eth_loop_addr, sizeof(mac_address));
      memcpy (data, ip, ip_len);
    }
    else
      memcpy (head, ip, ip_len);

    /* Update queue head index
     */
    q->in_index = pktq_in_index (q);
    ENABLE();
  }
  return (ip_len + _pkt_ip_ofs);
}
#endif  /* USE_LOOPBACK */


#if defined(USE_MULTICAST)   /* Jim Martin's Multicast extensions */
/*
 * _eth_join_mcast_group - joins a multicast group (at the physical layer)
 *
 * int _eth_join_mcast_group (int entry)
 * Where:
 *    entry   the entry # in the _ipmulti table
 * Returns:
 *    1       if the group was joined successfully
 *    0       if attempt failed
 */
int _eth_join_mcast_group (int entry)
{
  eth_address list [IPMULTI_SIZE];
  int         i, len, mode;
  BYTE        nextentry = 0;

  /* initialize a few things
   */
  _ipmulti[entry].active    = 0;
  _ipmulti[entry].replytime = set_timeout (0);
  _ipmulti[entry].processes = 1;

  /* Fill in the hardware address
   */
  multi_to_eth (_ipmulti[entry].ina, (BYTE*)&_ipmulti[entry].ethaddr);

  mode = _pkt_get_ip_rcv_mode();
  if (mode == -1)               /* something seems to be broken */
     return (0);

  if (mode == RM_MULTICAST2)    /* we're already in all mcast mode */
  {
    _ipmulti[entry].active = 1;
    return (1);
  }

  len = _pkt_get_multicast_list (sizeof(list), list);
  if (len == -1)
     return (0);

  /* check to see if the address is already in the list
   */
  for (i = 0; i < len/sizeof(list[0]); i++)
  {
    if (!memcmp(list[i], _ipmulti[entry].ethaddr, sizeof(list[0])))
    {
      _ipmulti[entry].active = 1;
      return (1);
    }
  }

  if (len)
     nextentry = len / sizeof(list[0]);

  memcpy (&list[nextentry], &_ipmulti[entry].ethaddr, sizeof(eth_address));
  len += sizeof (list[0]);

  if (_pkt_set_multicast_list(len,list) == -1)
  {
    if (_pkterror == NO_SPACE)     /* out of space, switch mode */
    {
      if (_pkt_set_ip_rcv_mode(RM_MULTICAST2) == -1)
         return (0);
    }
    else
      return (0);
  }

  _ipmulti[entry].active = 1;
  return (1);
}


/*
 * _eth_leave_mcast_group - leaves a multicast group (at the physical layer)
 *
 * int _eth_leave_mcast_group (int entry)
 * Where:
 *    entry   the entry # in the _ipmulti table
 * Returns:
 *    1       if the group was left successfully
 *    0       if attempt failed
 */
int _eth_leave_mcast_group (int entry)
{
  eth_address list[IPMULTI_SIZE];
  unsigned    i;
  int  len, mode;
  int  ethindex = -1;

  /* NOTE: This should be expanded to include switching back to mode 4
   * if the list of multicast addresses has shrunk sufficiently.
   *
   * First check to see if we're in mode 5. if so, mark
   * the entry as inactive and return.
   */

  mode = _pkt_get_ip_rcv_mode();
  if (mode == -1)
     return (0);

  if (mode == RM_MULTICAST2)
  {
    _ipmulti[entry].active = 0;
    return (1);
  }

  /* get the list of current multicast addresses
   */
  len = _pkt_get_multicast_list (sizeof(list), list);
  if (len < 0)
     return (0);

  /* find the apropriate entry
   */
  for (i = 0; i < len/sizeof(list[0]); i++)
      if (!memcmp(list[i],_ipmulti[entry].ethaddr,sizeof(list[0])))
         ethindex = i;

  /* if it's not in the list, just set the entry inactive and return
   */
  if (ethindex == -1)
  {
    _ipmulti[entry].active = 0;
    return (1);
  }

  /* ahh, but it _is_ in the list. So shorten the list
   * and send it back to the PD
   */
  if (ethindex+1 < (int)(len/sizeof(list[0])))
     movmem (&list[ethindex+1], &list[ethindex],
             len-(ethindex+1)*sizeof(list[0]));

  len -= sizeof (list[0]);

  if (_pkt_set_multicast_list(len,&list[0]) == -1)
  {
    if (_pkterror == NO_SPACE)     /* out of space, switch mode */
    {
      if (_pkt_set_ip_rcv_mode(RM_MULTICAST2) == -1)
         return (0);
    }
    else
      return (0);
  }

  _ipmulti[entry].active = 0;
  return (1);
}
#endif /* USE_MULTICAST */

/*
 * Turn off stack-checking because eth_release() might be called from
 * exception handler.
 */
#if defined(__HIGHC__) || defined(__WATCOMC__)
#pragma Off(check_stack)
#endif

#if defined(__BORLANDC__)
#pragma option -N-
#endif


⌨️ 快捷键说明

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