Ejemplo n.º 1
0
/**
 * _eth_format_packet() places the next packet to be transmitted into
 * the above link-layer output packet.
 * \return address of higher-level protocol (IP/RARP/RARP) header.
 */
void *_eth_formatpacket (const void *mac_dest, WORD eth_type)
{
  SIO_TRACE (("_eth_formatpacket, type %04X", eth_type));

  nw_pkt = (*mac_tx_format) (TX_BUF(), mac_dest, eth_type);
  return (nw_pkt);
}
Ejemplo n.º 2
0
/**
 * Format the MAC-header for Token-Ring.
 */
static void *tok_mac_format (void *mac_buf, const void *mac_dest, WORD type)
{
  union link_Packet *buf = (union link_Packet*) mac_buf;

  SIO_TRACE (("tok_mac_format"));

  /* No need to clear data behind header.
   */
  if (mac_dest)
     memcpy (&buf->tok.head.destination, mac_dest, sizeof(mac_address));
  memcpy (&buf->tok.head.source, &_eth_addr, sizeof(mac_address));

#if 0
  /* !!fix me: need to expand the RIF
   */
  if (_pktdevclass == PDCLASSS_TOKEN_RIF)
     ((void)0);
#endif

  buf->tok.head.accessCtrl = TR_AC;
  buf->tok.head.frameCtrl  = TR_FC;
  buf->tok.head.DSAP       = TR_DSAP;
  buf->tok.head.SSAP       = TR_SSAP;
  buf->tok.head.ctrl       = TR_CTRL;
  buf->tok.head.org[0]     = TR_ORG;
  buf->tok.head.org[1]     = TR_ORG;
  buf->tok.head.org[2]     = TR_ORG;
  buf->tok.head.type       = type;
  proto = type;
  return (&buf->tok.data);
}
Ejemplo n.º 3
0
static void fix_tok_head (tok_Header **trp)
{
  tok_Header *tr = *trp;

#if defined(USE_DEBUG)
  const BYTE *raw = (const BYTE*)tr;
  int   i;

  for (i = 0; i < 50; i++)
      dbug_printf ("%02X ", raw[i]);
  dbug_write ("\n");
#endif

  SIO_TRACE (("fix_tok_head"));

  if (TR_IS_SROUTED(tr))     /* Source routed */
  {
    int rlen = TR_RIF_LENGTH (tr);

    tr->source[0] &= 0x7F;   /* clear RII bit */

    /* Set our notion of link-layer broadcast
     */
    if (TR_IS_BROADCAST(tr))
       tr->destination[0] |= 1;

    /* Copy MAC-header rlen bytes upwards
     */
    memmove ((BYTE*)tr + rlen, tr, TR_MAC_SIZE);
    *trp = (tok_Header*) ((BYTE*)tr + rlen);
  }
}
Ejemplo n.º 4
0
/**
 * Return value of protocol-type given an IP packet.
 */
WORD _eth_mac_typ (const in_Header *ip)
{
  const union link_Packet *pkt;

  SIO_TRACE (("_eth_mac_typ"));

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

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

  if (_pktdevclass == PDCLASS_TOKEN || _pktdevclass == PDCLASS_TOKEN_RIF)
     return (pkt->tok.head.type);

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

  if (_pktdevclass == PDCLASS_ARCNET)
     return (pkt->arc.head.type);

  (*_printf) ("Illegal use of `_eth_mac_typ()' for class %d\n",
              _pktdevclass);
  exit (-1);
  /*@-unreachable@*/
  return (0);
}
Ejemplo n.º 5
0
/**
 * Format the MAC-header for Ethernet.
 */
static void *eth_mac_format (void *mac_buf, const void *mac_dest, WORD type)
{
  union link_Packet *buf = (union link_Packet*) mac_buf;

  SIO_TRACE (("eth_mac_format"));

  proto = type;      /* remember protocol for _eth_send() */

  /* Clear any remains of an old small packet
   */
  memset (&buf->eth.data[0], 0, ETH_MIN-sizeof(eth_Header));

#if defined(USE_PPPOE)
  if (type == IP4_TYPE && pppoe_is_up(mac_dest))
  {
    proto = PPPOE_SESS_TYPE;
    return pppoe_mac_format (buf);
  }
#endif

  if (mac_dest)
     memcpy (&buf->eth.head.destination, mac_dest, sizeof(mac_address));
  memcpy (&buf->eth.head.source, &_eth_addr, sizeof(mac_address));

  buf->eth.head.type = type;
  return (&buf->eth.data);
}
Ejemplo n.º 6
0
/*
 * trace2com_init() - Public initialisation
 */
int trace2com_init (WORD portAddress, DWORD baudRate)
{
  BYTE  Lsb, Msb;
  WORD  base;
  DWORD div;

  /* Check/get UART address
   */
  if (portAddress < 1 || portAddress > 4)
     return (0);

  base = trace2com_stdPorts [portAddress-1];

  /* See if the chip is actually there and ready
   */
  if (_inportb (base+IER_REG) == 0xFF)    /* Nothing here */
     return (0);

  if ((_inportb (base+IER_REG) & 0x0F) != 0x00)
     return (0);    /* UART is already in use by another program */

  _outportb (base+IER_REG, 0);  /* disable all interrupts */
  if (_inportb (base+IER_REG) != 0)
     return (0);                /* Whatever is here is not an UART */

  /* Set up UARTs registers
   */
  div = 115200UL / baudRate;
  Msb = div >> 8;
  Lsb = (div << 8) >> 8;

  _outportb (base+LCR_REG, 0x80);       /* Turn address latch on */
  _outportb (base+BAUD_LSB_REG, Lsb);
  _outportb (base+BAUD_MSB_REG, Msb);
  _outportb (base+LCR_REG, 0x00);       /* Turn address latch off (again) */

  _outportb (base+IER_REG, 0x00);       /* No interrupts, we use polling */
  _outportb (base+FIFO_REG, 0x01|0x08); /* Activate FIFO @ MODE 2 */
  _outportb (base+LCR_REG , 0x03);      /* 8, N, 1 */
  _outportb (base+MCR_REG, 0x03);       /* DTR + DTS on */

  /* Check chip type, gives us the FIFO size
   */
  _outportb (base + FIFO_REG, 0x11);
  Lsb = _inportb (base + FIFO_REG);

  /* If we have a 16750 or 16550 the FIFO size is 16, otherwise we assume 1
   */
  trace2com_fifoSize_1 = ((Lsb & 0x20) != 0x20 ||
                          (Lsb & 0xC0) == 0xC0) ? 15 : 0;

  /* We are now officially open for business
   */
  trace2com_speed = baudRate;
  trace2com_base  = base;

  SIO_TRACE ((_LANG("Watt-32 COM%d trace started"), portAddress));
  return (1);
}
Ejemplo n.º 7
0
static int tok_mac_xmit (const void *buf, WORD len)
{
  SIO_TRACE (("tok_mac_xmit, len %d", len));

  if (len > TOK_MAX)  /* Token-Ring has no min. length */
      len = TOK_MAX;
  return pkt_send (buf, len);
}
Ejemplo n.º 8
0
/**
 * Leaves a multicast group (at the physical layer)
 *
 * \retval 1 The group was left successfully.
 * \retval 0 Attempt failed.
 */
BOOL _eth_leave_mcast_group (const struct MultiCast *mc)
{
  eth_address list[IPMULTI_SIZE];
  int i, len, idx;

  SIO_TRACE (("_eth_leave_mcast_group"));

  /* \note This should be expanded to include switching back to
   *       RXMODE_MULTCAST1 if the list of multicast addresses has
   *       shrunk sufficiently.
   *
   * First check to see if we're in RXMODE_MULTICAST2. if so return
   */
#if defined(WIN32)
  if (_pkt_rxmode & RXMODE_MULTICAST2)
     return (TRUE);
#else
  if (_pkt_rxmode >= RXMODE_MULTICAST2)
     return (TRUE);
#endif

  /* get the list of current multicast addresses
   */
  len = sizeof(list);
  if (!pkt_get_multicast_list (list, &len))
     return (FALSE);

  /* find the apropriate entry
   */
  for (i = 0, idx = -1; i < len/SIZEOF(list[0]); i++)
      if (!memcmp(list[i],&mc->ethaddr,sizeof(list[0])))
         idx = i;

  /* if it's not in the list, just return
   */
  if (idx == -1)
     return (TRUE);

  /* ahh, but it _is_ in the list. So shorten the list
   * and send it back to the PKTDRVR
   */
  if (idx+1 < len/SIZEOF(list[0]))
     memmove (&list[idx], &list[idx+1], len-(idx+1)*sizeof(list[0]));

  len -= sizeof(list[0]);

  if (!pkt_set_multicast_list((const eth_address*)&list, len))
  {
    /* If no space or no MC support, switch mode
     */
    if (_pkt_errno == PDERR_NO_SPACE ||
        _pkt_errno == PDERR_NO_MULTICAST)
       return pkt_set_rcv_mode (RXMODE_MULTICAST2);
    return (FALSE);
  }
  return (TRUE);
}
Ejemplo n.º 9
0
/**
 * Add a gateway to the routing table.
 *
 * The format of 'config_string' is:
 *   IP-address [, subnet] , mask]]
 *
 * If 'config_string' is NULL, simply add 'ip' with zero
 * mask and subnet.
 */
BOOL _arp_add_gateway (const char *config_string, DWORD ip)
{
  struct gate_entry *gw;
  DWORD  subnet = 0UL;
  DWORD  mask   = 0UL;
  int    i;

  SIO_TRACE (("_arp_add_gateway"));

  if (config_string)
  {
    const char* subnetp, *maskp;

    /* Get gateways IP address from string
     */
    ip = aton (config_string);
    if (ip == 0)
       return (FALSE); /* invalid */

    /* Check if optional subnet was supplied
     */
    subnetp = strchr (config_string, ',');
    if (subnetp)
    {
      /* NB: atoi (used in aton) stops conversion when the first non-number
       * is hit, so there is no need to manually null-terminate the string.
       * i.e. aton ("123.123.123.123,blabla") = 123.123.123.123
       */
      subnet = aton (++subnetp);

      /* Check if optional mask was supplied
       */
      maskp = strchr (subnetp, ',');
      if (maskp)
         mask = aton (++maskp);
      else /* No mask was supplied, we derive it from the supplied subnet */
      {
        switch (subnet >> 30)
        {
          case  0:
          case  1:
                mask = 0xFF000000UL;
                break;
          case  2:
                mask = 0xFFFFFE00UL;   /* minimal class B */
                break;
          case  3:
          default:
                mask = 0xFFFFFF00UL;
                break;
        }
      }
    }
  }
  else /* (config_string == NULL) */
  {
    if (ip == 0UL)
Ejemplo n.º 10
0
/**
 * Functions called via function pointer `mac_transmit' to
 * actually send the data.
 */
static int eth_mac_xmit (const void *buf, WORD len)
{
  SIO_TRACE (("eth_mac_xmit, len %d", len));

  if (len < ETH_MIN)
       len = ETH_MIN;  /* zero padding already done in eth_mac_format() */
  else if (len > ETH_MAX)
       len = ETH_MAX;

  return pkt_send (buf, len);
}
Ejemplo n.º 11
0
/**
 * Free an input buffer once it is no longer needed.
 */
void _eth_free (const void *pkt)
{
  SIO_TRACE (("_eth_free"));

  if (_eth_recv_hook) /* hook-function should free it's own packet */
     return;

  if (!pkt)
       pkt_buf_wipe();   /* restart the queue */
  else pkt_free_pkt (pkt);
}
Ejemplo n.º 12
0
static int arcnet_mac_xmit (const void *buf, WORD len)
{
  SIO_TRACE (("arcnet_mac_xmit, len %d", len));

  if (len < ARCNET_MIN)
       len = ARCNET_MIN;
  else if (len > ARCNET_MAX)
       len = ARCNET_MAX;

  return pkt_send (buf, len);
}
Ejemplo n.º 13
0
static int fddi_mac_xmit (const void *buf, WORD len)
{
  SIO_TRACE (("fddi_mac_xmit, len %d", len));

  if (len < FDDI_MIN)
       len = FDDI_MIN;
  else if (len > FDDI_MAX)
       len = FDDI_MAX;

  return pkt_send (buf, len);
}
Ejemplo n.º 14
0
/*
 * Fix the LLC header to look like ordinary Ethernet II
 * !! not yet.
 */
static void fix_llc_head (void **mac)
{
  SIO_TRACE (("fix_llc_head"));
#if 1
  DEBUG_RX (NULL, *mac);
  _eth_free (*mac);
  *mac = NULL;
#else
  /** \todo handle IEEE 802.3 encapsulation also.
   */
#endif
}
Ejemplo n.º 15
0
/**
 * Format MAC-header for protocols without MAC-headers.
 * Nothing done here.
 */
static void *null_mac_format (void *mac_buf, const void *mac_dest, WORD type)
{
  union link_Packet *buf = (union link_Packet*) mac_buf;

  SIO_TRACE (("null_mac_format"));

  memset (&buf->ip.head, 0, sizeof(buf->ip.head));
  ARGSUSED (mac_dest);
  ARGSUSED (type);
  proto = IP4_TYPE;
  return (void*) (&buf->ip.head);
}
Ejemplo n.º 16
0
/**
 * Return pointer to MAC header start address of an IP packet.
 */
void *_eth_mac_hdr (const in_Header *ip)
{
  SIO_TRACE (("_eth_mac_hdr"));

  if (!_pktserial)
     return (void*) ((BYTE*)ip - _pkt_ip_ofs);

  (*_printf) ("Illegal use of `_eth_mac_hdr()' for class %d\n",
              _pktdevclass);
  exit (-1);
  /*@-unreachable@*/
  return (NULL);
}
Ejemplo n.º 17
0
/**
 * Sets a new MAC address for our interface.
 */
int _eth_set_addr (const void *addr)
{
  SIO_TRACE (("_eth_set_addr"));

  if (_pktserial || _pktdevclass == PDCLASS_ARCNET)
     return (1);

  if (pkt_set_addr(addr))
  {
    memcpy (_eth_addr, addr, sizeof(_eth_addr));
    return (1);
  }
  return (0);
}
Ejemplo n.º 18
0
/**
 * Handle incoming RARP packets.
 */
BOOL _rarp_handler (const rarp_Header *rh, BOOL brdcast)
{
  SIO_TRACE (("_rarp_handler"));

  DEBUG_RX (NULL, rh);

  if (!brdcast && rh->opcode == RARP_REPLY && rh->protType == IP4_TYPE &&
      !memcmp(rh->dstEthAddr,_eth_addr,sizeof(mac_address)))
  {
    my_ip_addr = intel (rh->dstIPAddr);
    return (TRUE);
  }
  return (FALSE);
}
Ejemplo n.º 19
0
/**
 * Format the MAC-header for FDDI.
 */
static void *fddi_mac_format (void *mac_buf, const void *mac_dest, WORD type)
{
  union link_Packet *buf = (union link_Packet*) mac_buf;

  SIO_TRACE (("fddi_mac_format"));

  memset (&buf->fddi.data[0], 0, FDDI_MIN-sizeof(fddi_Header));
  if (mac_dest)
     memcpy (&buf->fddi.head.destination, mac_dest, sizeof(mac_address));
  memcpy (&buf->fddi.head.source, &_eth_addr, sizeof(mac_address));

  buf->fddi.head.frameCtrl = FDDI_FC;
  buf->fddi.head.DSAP      = FDDI_DSAP;
  buf->fddi.head.SSAP      = FDDI_SSAP;
  buf->fddi.head.ctrl      = FDDI_CTRL;
  buf->fddi.head.org[0]    = FDDI_ORG;
  buf->fddi.head.org[1]    = FDDI_ORG;
  buf->fddi.head.org[2]    = FDDI_ORG;
  buf->fddi.head.type      = type;
  proto = type;
  return (&buf->fddi.data);
}
Ejemplo n.º 20
0
/**
 * Fill in hardware address type/length for BOOTP/DHCP packets.
 * Also used for ARP/RARP packets. Should never be called for PPP/SLIP.
 */
BYTE _eth_get_hwtype (BYTE *hwtype, BYTE *hwlen)
{
  SIO_TRACE (("_eth_get_hwtype"));

  if (_pktdevclass == PDCLASS_ETHER)
  {
    if (hwlen)  *hwlen  = sizeof (eth_address);
    if (hwtype) *hwtype = HW_TYPE_ETHER;
    return (HW_TYPE_ETHER);
  }
  if (_pktdevclass == PDCLASS_FDDI)
  {
    if (hwlen)  *hwlen  = sizeof (fddi_address);
    if (hwtype) *hwtype = HW_TYPE_FDDI;
    return (HW_TYPE_FDDI);
  }
  if (_pktdevclass == PDCLASS_TOKEN || _pktdevclass == PDCLASS_TOKEN_RIF)
  {
    if (hwlen)  *hwlen  = sizeof (tok_address);
    if (hwtype) *hwtype = HW_TYPE_TOKEN;
    return (HW_TYPE_TOKEN);
  }
  if (_pktdevclass == PDCLASS_AX25)
  {
    if (hwlen)  *hwlen  = sizeof (ax25_address);
    if (hwtype) *hwtype = HW_TYPE_AX25;
    return (HW_TYPE_AX25);
  }
  if (_pktdevclass == PDCLASS_ARCNET)
  {
    if (hwlen)  *hwlen  = sizeof (arcnet_address);  /* 1 byte */
    if (hwtype) *hwtype = HW_TYPE_ARCNET;
    return (HW_TYPE_ARCNET);
  }
  return (0);
}
Ejemplo n.º 21
0
/**
 * Poll the packet queue. Return first packet in queue.
 * Optionally do receiver profiling.
 *
 *   \retval pointer to start of MAC-header.
 *   \retval NULL    no packets are queued.
 *
 * \note Not used when e.g. libpcap has set the `_eth_recv_hook' to
 *       do it's own packet-polling.
 * \note 'type' is always set.
 */
static union link_Packet *poll_recv_queue (WORD *type)
{
#if defined(USE_FAST_PKT) || defined(WIN32)
  struct pkt_rx_element *buf;
#endif
  struct pkt_ringbuf *q = &_pkt_inf->pkt_queue;
  union  link_Packet *pkt;
  struct in_Header   *ip;

  SIO_TRACE (("poll_recv_queue"));

  ASSERT_PKT_INF (NULL);

#if defined(USE_DEBUG)
#if defined(USE_FAST_PKT)
  if (!pktq_far_check(q))
#else
  if (!pktq_check(q))
#endif
  {
    fprintf (stderr, "%s: pkt-queue destroyed!\n", __FILE__);
    exit (-1);
  }
#endif

#if defined(WIN32)
  buf = pkt_poll_recv();
  if (!buf)
     return (NULL);

  PROFILE_RECV ((uint64*)&buf->tstamp_put, (uint64*)&buf->tstamp_get);
  _eth_last.rx.size      = buf->rx_length;
  _eth_last.rx.tstamp.lo = 0UL;  /* no need yet */
  _eth_last.rx.tstamp.hi = 0UL;
  pkt = (link_Packet*) &buf->rx_buf[0];

#elif defined(USE_FAST_PKT)
  buf = pkt_poll_recv();
  if (!buf)
     return (NULL);

  PROFILE_RECV ((uint64*)buf->tstamp_put, (uint64*)buf->tstamp_get);
  pkt = (link_Packet*) buf->rx_buf;
  _eth_last.rx.size      = buf->rx_length_1;    /* length on 1st upcall */
  _eth_last.rx.tstamp.lo = buf->tstamp_put[0];  /* TSC set in asmpkt */
  _eth_last.rx.tstamp.hi = buf->tstamp_put[1];

#else
  if (!pktq_queued(q))
     return (NULL);

  pkt = (link_Packet*) pktq_out_buf (q);
  _eth_last.rx.size      = ETH_MAX;  /* !! wrong, but doesn't matter for pcap */
  _eth_last.rx.tstamp.lo = 0UL;      /* pcdbug.c writes rx-time == dbg-time */
  _eth_last.rx.tstamp.hi = 0UL;
#endif


  if (_pktserial)
  {
    ip = &pkt->ip.head;       /* SLIP/PPP/AX25 */
    *type = (ip->ver == 4) ? IP4_TYPE : IP6_TYPE;
    return (pkt);
  }

  if (_pktdevclass == PDCLASS_TOKEN || _pktdevclass == PDCLASS_TOKEN_RIF)
  {
    tok_Header *tr = &pkt->tok.head;

    fix_tok_head (&tr);
    *type = tr->type;
    return (union link_Packet*) tr;
  }

  if (_pktdevclass == PDCLASS_ARCNET)
  {
    arcnet_Packet *arc = &pkt->arc;

    if (!fix_arc_head(&arc->head, type))
    {
      DEBUG_RX (NULL, &arc->data);
      pkt_free_pkt (pkt);
      pkt = NULL;
    }
    return (pkt);
  }

  if (_pktdevclass == PDCLASS_FDDI)
  {
    fddi_Packet *fddi = &pkt->fddi;

    *type = fddi->head.type;
    return (pkt);
  }

  /* must be PDCLASS_ETHER */

  *type = pkt->eth.head.type;
  ARGSUSED (q);
  return (pkt);
}
Ejemplo n.º 22
0
/**
 * Joins a multicast group (at the physical layer).
 *
 * \retval 1 The group was joined successfully.
 * \retval 0 Attempt failed.
 */
BOOL _eth_join_mcast_group (const struct MultiCast *mc)
{
  eth_address list [IPMULTI_SIZE];
  int         i, len, nextentry;
  BOOL        is_mcast1, is_mcast2, is_promis;

  SIO_TRACE (("_eth_join_mcast_group"));

  /* Return if we're already receiving all multicasts or is in
   * promiscous mode.
   */
#if defined(WIN32)
  is_mcast1 = (_pkt_rxmode & RXMODE_MULTICAST1);
  is_mcast2 = (_pkt_rxmode & RXMODE_MULTICAST2);
  is_promis = (_pkt_rxmode & RXMODE_PROMISCOUS);
#else
  is_mcast1 = (_pkt_rxmode >= RXMODE_MULTICAST1);
  is_mcast2 = (_pkt_rxmode >= RXMODE_MULTICAST2);
  is_promis = (_pkt_rxmode >= RXMODE_PROMISCOUS);
#endif

  if (is_mcast2 || is_promis)
     return (TRUE);

  if (!is_mcast1)
  {
    is_mcast1 = pkt_set_rcv_mode(RXMODE_MULTICAST1);
    if (!is_mcast1)
       is_promis = pkt_set_rcv_mode(RXMODE_PROMISCOUS);
    if (is_promis)
       return (TRUE);
    if (!is_mcast1 && !is_promis)
       return (FALSE);     /* hopeless, give up */
  }

  len = sizeof(list);
  if (!pkt_get_multicast_list (list, &len))
  {
    /* If no MC support, switch to MC2 mode
     */
    if (_pkt_errno == PDERR_NO_MULTICAST)
       return pkt_set_rcv_mode (RXMODE_MULTICAST2);
    return (FALSE);
  }

  /* check to see if the address is already in the list
   */
  for (i = 0; i < len / SIZEOF(list[0]); i++)
      if (!memcmp(list[i], &mc->ethaddr, sizeof(list[0])))
         return (TRUE);

  if (len > 0)
       nextentry = len / sizeof(list[0]);  /* append entry */
  else nextentry = 0;

  memcpy (&list[nextentry], &mc->ethaddr, sizeof(eth_address));
  len += sizeof (list[0]);

  if (!pkt_set_multicast_list((const eth_address*)&list,len))
  {
    /* If no space or no MC support, switch to MC2 mode
     */
    if (_pkt_errno == PDERR_NO_SPACE ||
        _pkt_errno == PDERR_NO_MULTICAST)
       return pkt_set_rcv_mode (RXMODE_MULTICAST2);
    return (FALSE);
  }
  return (TRUE);
}
Ejemplo n.º 23
0
static int null_mac_xmit (const void *buf, WORD len)
{
  SIO_TRACE (("null_mac_xmit, len %d", len));

  return pkt_send (buf, len);
}
Ejemplo n.º 24
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);
}
Ejemplo n.º 25
0
/**
 * Poll for arrival of new packets (IP/ARP/RARP/PPPoE protocol).
 * Sets protocol-type of packet received in 'type'.
 *
 * For Ethernet/TokenRing-type drivers: \n
 *  \retval Pointer past the MAC-header to the IP/ARP/RARP
 *          protocol header. Also check for link-layer broadcast.
 *
 * For PPP/SLIP-type drivers (no MAC-headers): \n
 *  \retval Pointer to the IP-packet itself.
 *   IP-protocol is assumed. Can never be link-layer broadcast.
 */
void *_eth_arrived (WORD *type_ptr, BOOL *broadcast)
{
  union link_Packet *pkt;
  mac_address       *dst;
  void              *ret = NULL;
  BOOL               is_bcast = FALSE;
  WORD               type = 0;

  SIO_TRACE (("_eth_arrived"));

  if (!_eth_is_init)  /* GvB 2002-09, Lets us run without a working driver */
     return (NULL);

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

  if (!pkt)
     return (NULL);

  if (_eth_recv_peek && !(*_eth_recv_peek)(pkt))
  {
    _eth_free (pkt);
    return (NULL);
  }

  /* Hack: If _ip?_handler() can't be reentered, only accept
   *       non-IP packets. Assume PPPoE session packets carry only IP.
   */
  if (_ip_recursion &&
      (type == IP4_TYPE || type == IP6_TYPE || type == PPPOE_SESS_TYPE))
  {
    /**< \todo push back packet, else it's lost */
    STAT (macstats.num_ip_recurse++);
    _eth_free (pkt);
    return (NULL);
  }

  if (_pktserial)
  {
    dst = NULL;
    ret = (void*) &pkt->ip;
  }
  else if (_pktdevclass == PDCLASS_TOKEN || _pktdevclass == PDCLASS_TOKEN_RIF)
  {
    dst = &pkt->tok.head.destination;
    ret = (void*) &pkt->tok.data;
  }
  else if (_pktdevclass == PDCLASS_FDDI)
  {
    dst = &pkt->fddi.head.destination;
    ret = (void*) &pkt->fddi.data;
  }
  else if (_pktdevclass == PDCLASS_ARCNET)
  {
    dst = (mac_address*) &pkt->arc.head.destination;
    ret = (void*) ((BYTE*)pkt + ARC_HDRLEN);
  }
  else   /* must be ether */
  {
    dst = &pkt->eth.head.destination;
    ret = (void*) &pkt->eth.data;
  }

#if defined(NEED_PKT_SPLIT)
  pkt_split_mac_in (pkt);
#endif

#if defined(USE_STATISTICS)
  update_in_stat();
#endif

#if defined(NEED_PKT_SPLIT) && defined(USE_DEBUG) && 0  /* test */
  pkt_print_split_in();
#endif

  /* ARCnet should never have LLC fields. So don't test for it
   */
  if (_pktdevclass != PDCLASS_ARCNET)
  {
    if (dst && !memcmp(dst, &_eth_brdcast, sizeof(_eth_brdcast)))
       is_bcast = TRUE;

    if (intel16(type) < 0x600)       /* LLC length field */
       fix_llc_head (&ret);
  }
  else if (dst && *(BYTE*)dst == 0)  /* ARCnet broadcast */
  {
    is_bcast = TRUE;
  }

  if (type_ptr)
     *type_ptr = type;

  if (broadcast)
     *broadcast = is_bcast;

  return (ret);
}
Ejemplo n.º 26
0
/**
 * Initialize the network driver interface.
 * \return 0 okay.
 * \return error-code otherwise.
 */
int _eth_init (void)
{
  int rc;

  SIO_TRACE (("_eth_init"));

  if (_eth_is_init)
     return (0);

  rc = pkt_eth_init (&_eth_addr);
  if (rc)
     return (rc);  /* error message already printed */

  /* Save our MAC-address incase we change it. Change back at exit.
   */
  memcpy (_eth_real_addr, _eth_addr, sizeof(_eth_real_addr));

  switch (_pktdevclass)
  {
    case PDCLASS_ETHER:
         mac_tx_format = eth_mac_format;
         mac_transmit  = eth_mac_xmit;
         break;
    case PDCLASS_TOKEN:
    case PDCLASS_TOKEN_RIF:
         mac_tx_format = tok_mac_format;
         mac_transmit  = tok_mac_xmit;
         break;
    case PDCLASS_FDDI:
         mac_tx_format = fddi_mac_format;
         mac_transmit  = fddi_mac_xmit;
         break;
    case PDCLASS_ARCNET:
         mac_tx_format = arcnet_mac_format;
         mac_transmit  = arcnet_mac_xmit;
         break;
    case PDCLASS_SLIP:
    case PDCLASS_PPP:
    case PDCLASS_AX25:  /* !! for now */
         mac_tx_format = null_mac_format;
         mac_transmit  = null_mac_xmit;
         break;
    default:
         outsnl (_LANG("No supported driver class found"));
         return (WERR_NO_DRIVER);
  }

  memset (TX_BUF(), 0, sizeof(union link_Packet));
  memset (&_eth_brdcast, 0xFF, sizeof(_eth_brdcast));
  _eth_loop_addr[0] = 0xCF;
  pkt_buf_wipe();

  if (!_eth_get_hwtype(NULL, &_eth_mac_len))
     _eth_mac_len = sizeof(eth_address);

  if (!strcmp(_pktdrvrname,"NDIS3PKT"))
     _eth_ndis3pkt = TRUE;

  else if (!strcmp(_pktdrvrname,"SwsVpkt"))
     _eth_SwsVpkt = TRUE;

  _eth_is_init = TRUE;
  RUNDOWN_ADD (_eth_release, 10);

  return (0);  /* everything okay */
}
Ejemplo n.º 27
0
/**
 * _eth_send() does the actual transmission once we are complete with
 * filling the buffer.  Do any last minute patches here, like fix the
 * size. Send to "loopback" device if it's IP and destination matches
 * loopback network (127.x.x.x.).
 *
 * Return length of network-layer packet (not length of link-layer
 * packet).
 */
int _eth_send (WORD len, const void *sock, const char *file, unsigned line)
{
#if defined(USE_DEBUG) || defined(USE_LOOPBACK)
  unsigned errline = 0;
#endif
  BOOL send_loopback_to_driver = FALSE;

  SIO_TRACE (("_eth_send, len %d", len));

  if (!_eth_is_init)  /* GvB 2002-09, Lets us run without a working eth */
  {
    SOCK_ERRNO (ENETDOWN);
    return (0);
  }

#if defined(WIN32)
  /*
   * Just a test for now; send it to the driver and look what happens....
   * They go on the wire and not to the Winsock loopback provider.
   * No surprise here yet.
   */
  if (loopback_mode & LBACK_MODE_WINSOCK)
     send_loopback_to_driver = TRUE;
#endif

  if (proto == IP4_TYPE)
  {
    /* Sending to loopback device if IPv4.
     */
    const in_Header *ip = (const in_Header*) nw_pkt;

    if (!send_loopback_to_driver &&
        _ip4_is_loopback_addr(intel(ip->destination)))
    {
#if defined(USE_LOOPBACK)
      len = send_loopback (*TX_BUF(), FALSE, &errline);
#else
      STAT (ip4stats.ips_odropped++);    /* packet dropped (null-device) */
#endif
      goto debug_tx;
    }
  }

#if defined(USE_IPV6)
  else if (proto == IP6_TYPE)
  {
    const in6_Header *ip = (const in6_Header*) nw_pkt;

    if (!send_loopback_to_driver &&
        IN6_IS_ADDR_LOOPBACK(&ip->destination))
    {
#if defined(USE_LOOPBACK)
      len = send_loopback (*TX_BUF(), TRUE, &errline);
#else
      STAT (ip6stats.ip6s_odropped++);
#endif
      goto debug_tx;
    }
  }
#endif  /* USE_IPV6 */

#if defined(USE_PPPOE)
  else if (proto == PPPOE_SESS_TYPE)
  {
    pppoe_Packet *pppoe = (pppoe_Packet*) TX_BUF()->eth.data;

    pppoe->length = intel16 (len+2);
    len += PPPOE_HDR_SIZE + 2;      /* add 2 for protocol */
  }
#endif

  /* Store the last Tx CPU timestamp (for debugging).
   */
#if (DOSX) && !(DOSX & WINWATT)
  if (_dbugxmit && has_rdtsc)
     get_rdtsc2 (&_eth_last.tx.tstamp);
#endif

  /* Do the MAC-dependant transmit. `len' on return is total length
   * of link-layer packet sent. `len' is 0 on failure. The xmit-hook
   * is used by e.g. libpcap/libnet.
   */
  if (_eth_xmit_hook)
       len = (*_eth_xmit_hook) (TX_BUF(), len + _pkt_ip_ofs);
  else len = (*mac_transmit) (TX_BUF(), len + _pkt_ip_ofs);

  if (len > _pkt_ip_ofs)
  {
    _eth_last.tx.size = len;
    len -= _pkt_ip_ofs;
  }
  else
  {
    if (debug_on)
       outs ("Tx failed. ");
    len = 0;
    _eth_last.tx.size = 0;
  }

debug_tx:

#if defined(NEED_PKT_SPLIT)
  pkt_split_mac_out (TX_BUF());
#endif

#if defined(USE_STATISTICS)
  if (len > 0)
     update_out_stat();
#endif

#if defined(USE_DEBUG)
  if (_dbugxmit)
    (*_dbugxmit) (sock, (const in_Header*)nw_pkt, file, line);

  if (len == 0)
  {
    if (errline && !send_loopback_to_driver)
       dbug_printf ("** Error in loopback handler, line %u\n", errline);
    else
    {
      const char err[] = "** Transmit fault **\n";
      TCP_CONSOLE_MSG (0, ("%s", err));
      dbug_printf (err);
    }
  }
#else
  ARGSUSED (sock);
  ARGSUSED (file);
  ARGSUSED (line);
#endif

  /* Undo hack done in pppoe_mac_format()
   */
  if (proto == PPPOE_SESS_TYPE || _pktdevclass == PDCLASS_ETHER)
     _pkt_ip_ofs = sizeof(eth_Header);
  return (len);
}