Example #1
0
int pkt_test_upcall (void)
{
#if !defined(NO_RMODE_CALL)
  int i, max = RX_BUFS + 3;

  for (i = 0; i < max; i++)
  {
    eth_Packet eth;
    IREGS      regs;
    DWORD      linear = 0;

    memset (&regs, 0, sizeof(regs));
    memset (&eth, 0, sizeof(eth));
    eth.head.type = IP4_TYPE;
    memset (&eth.head.destination, 0xFF, 6);
    memcpy (&eth.head.source, _eth_addr, 6);

#if (DOSX & (PHARLAP|X32VM))
    rmc.eax = 0;
    rmc.ebx = _pkt_inf->handle;
    rmc.ecx = ETH_MAX;
#endif
    regs.r_cx = ETH_MAX;
    regs.r_bx = _pkt_inf->handle;
    regs.r_ax = 0;
    regs.r_cs = _pkt_inf->rm_seg;
    regs.r_ip = PktReceiver;

    if (DPMI_REAL_CALL(&regs))
    {
      linear = SEG_OFS_ADDR (regs.r_es, regs.r_di);

      printf ("Upcall AX=0: ES:DI %04X:%04X\n",
              (WORD)regs.r_es, (WORD)regs.r_di);
#if (DOSX & DJGPP)
      if (linear)
         dosmemput (&eth, (WORD)regs.r_cx, linear);
#elif (DOSX & (DOS4GW|X32VM))
      if (linear)
         memcpy ((void*)linear, &eth, (WORD)regs.r_cx);
#elif (DOSX & (PHARLAP|POWERPAK))
      if (linear)
      {
        RP_SET (linear, regs.r_es, regs.r_di);
        WriteRealMem (linear, &eth, (WORD)regs.r_cx);
      }
#else
  #error Help me!
#endif
    }
    if (linear)
    {
      regs.r_ss = regs.r_sp = 0;
      regs.r_ax = 1;
      regs.r_cs = _pkt_inf->rm_seg;
      regs.r_ip = PktReceiver;
      regs.r_ds = regs.r_es;
      regs.r_si = regs.r_di;
      if (DPMI_REAL_CALL(&regs))
         printf ("Upcall AX=1\n");
    }
    printf ("buffers used %d, dropped %lu\n",
            pkt_buffers_used(), pkt_rx_dropped());
  }
#endif

  pkt_dump_real_mem();
  return (0);
}
Example #2
0
/**
 * Enqueue a link-layer frame (IPv4/v6 only) to the internal 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).
 */
static int send_loopback (link_Packet pkt, BOOL is_ip6, unsigned *err_line)
{
  struct pkt_ringbuf *q;
  const  in_Header   *ip;
  int    ip_len;

  SIO_TRACE (("send_loopback"));

  if (!_pkt_inf)
  {
    *err_line = __LINE__;
    goto drop_it;
  }

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

  q = &_pkt_inf->pkt_queue;

  if (!q || ip_len > (int)_mtu)
  {
    *err_line = __LINE__;
    goto drop_it;
  }

  if (ip_len > 0)
  {
#if defined(USE_FAST_PKT)
    /*
     * Don't let pkt_receiver() modify the queue while testing/copying.
     */
    if (pkt_buffers_used() >= _pkt_inf->pkt_queue.num_buf - 1)
    {
      *err_line = __LINE__;
      goto drop_it;
    }
    {
      char     tx_buf [ETH_MAX];
      unsigned len = ip_len;

      /* Enqueue packet to head of input IP-queue.
       */
      if (!_pktserial)
      {
        void *data = (*mac_tx_format) (tx_buf, _eth_addr,
                                       is_ip6 ? IP6_TYPE : IP4_TYPE);
        memcpy (MAC_SRC(data), &_eth_loop_addr, sizeof(mac_address));
        memcpy (data, ip, ip_len);
        len += _pkt_ip_ofs;
      }
      else
        memcpy (tx_buf, ip, ip_len);

      if (!pkt_append_recv(tx_buf, len))
      {
        *err_line = __LINE__;
        goto drop_it;
      }
    }
#elif defined(WIN32)
    struct pkt_rx_element *head;

    ENTER_CRIT();
    if (pktq_in_index(q) == q->out_index)  /* queue is full, drop it */
    {
      q->num_drop++;
      LEAVE_CRIT();
      *err_line = __LINE__;
      goto drop_it;
    }

    head = (struct pkt_rx_element*) pktq_in_buf (q);
    head->rx_length = _pkt_ip_ofs + ip_len;
    gettimeofday (&head->tstamp_put, NULL);

    /* Enqueue packet to head of input IP-queue.
     */
    if (!_pktserial)
    {
      void *data = (*mac_tx_format) (&head->rx_buf, _eth_addr,
                                     is_ip6 ? IP6_TYPE : IP4_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);

    LEAVE_CRIT();

#else
    union link_Packet *head;

    DISABLE();
    if (pktq_in_index(q) == q->out_index)  /* queue is full, drop it */
    {
      q->num_drop++;
      ENABLE();
      *err_line = __LINE__;
      goto drop_it;
    }

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

    /* Enqueue packet to head of input IP-queue.
     */
    if (!_pktserial)
    {
      void *data = (*mac_tx_format) (head, _eth_addr,
                                     is_ip6 ? IP6_TYPE : IP4_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();
#endif
  }
  *err_line = 0;
  return (ip_len + _pkt_ip_ofs);

drop_it:
  /*
   * Maybe this should be an input counter
   */
  if (is_ip6)
       STAT (ip6stats.ip6s_odropped++);
  else STAT (ip4stats.ips_odropped++);
  return (0);
}