示例#1
0
static void
pcapif_check_linkstate(void *netif_ptr)
{
  struct netif *netif = (struct netif*)netif_ptr;
  struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
  enum pcapifh_link_event le;

  le = pcapifh_linkstate_get(pa->link_state);

  if (pa->last_link_event != le) {
    pa->last_link_event = le;
    switch (le) {
      case PCAPIF_LINKEVENT_UP: {
        PCAPIF_NOTIFY_LINKSTATE(netif, netif_set_link_up);
        break;
      }
      case PCAPIF_LINKEVENT_DOWN: {
        PCAPIF_NOTIFY_LINKSTATE(netif, netif_set_link_down);
        break;
      }
      case PCAPIF_LINKEVENT_UNKNOWN: /* fall through */
      default:
        break;
    }
  }
  sys_timeout(PCAPIF_LINKCHECK_INTERVAL_MS, pcapif_check_linkstate, netif);
}
示例#2
0
/** RX running in its own thread */
static void
pcapif_input_thread(void *arg)
{
  struct netif *netif = (struct netif *)arg;
  struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
  do
  {
    struct pcap_pkthdr pkt_header;
    const u_char *packet = pcap_next(pa->adapter, &pkt_header);
    if(packet != NULL) {
      pcapif_input((u_char*)pa, &pkt_header, packet);
    }
  } while (pa->rx_run);
  pa->rx_running = 0;
}
示例#3
0
static int
pcaipf_is_tx_packet(struct netif *netif, const void *packet, int packet_len)
{
  struct pcapif_private *priv = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
  struct pcapipf_pending_packet *iter, *last;
  SYS_ARCH_DECL_PROTECT(lev);

  last = priv->tx_packets;
  if (last == NULL) {
    /* list is empty */
    return 0;
  }
  /* compare the first packet */
  if (pcapif_compare_packets(last, packet, packet_len)) {
    SYS_ARCH_PROTECT(lev);
    LWIP_ASSERT("list has changed", last == priv->tx_packets);
    priv->tx_packets = last->next;
    last->next = priv->free_packets;
    priv->free_packets = last;
    last->len = 0;
    SYS_ARCH_UNPROTECT(lev);
    return 1;
  }
  SYS_ARCH_PROTECT(lev);
  for (iter = last->next; iter != NULL; last = iter, iter = iter->next) {
    /* unlock while comparing (this works because we have a clean threading separation
       of adding and removing items and adding is only done at the end) */
    SYS_ARCH_UNPROTECT(lev);
    if (pcapif_compare_packets(iter, packet, packet_len)) {
      SYS_ARCH_PROTECT(lev);
      LWIP_ASSERT("last != NULL", last != NULL);
      last->next = iter->next;
      iter->next = priv->free_packets;
      priv->free_packets = iter;
      last->len = 0;
      SYS_ARCH_UNPROTECT(lev);
      return 1;
    }
    SYS_ARCH_PROTECT(lev);
  }
  SYS_ARCH_UNPROTECT(lev);
  return 0;
}
示例#4
0
void
pcapif_poll(struct netif *netif)
{
  struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);

  int ret;
  do {
    if (pa->adapter != NULL) {
      ret = pcap_dispatch(pa->adapter, -1, pcapif_input, (u_char*)pa);
    } else {
      ret = -1;
    }
    if (ret < 0) {
      /* error (e.g. adapter removed or resume from standby), try to reopen the adapter */
      pcap_reopen_adapter(pa);
    }
  } while (ret > 0);

}
示例#5
0
/**
 * Close the adapter (no more packets can be sent or received)
 *
 * @param netif netif to shutdown
 */
void
pcapif_shutdown(struct netif *netif)
{
  struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
  if (pa) {
#if PCAPIF_RX_USE_THREAD
    pa->rx_run = 0;
#endif /* PCAPIF_RX_USE_THREAD */
    if (pa->adapter) {
      pcap_breakloop(pa->adapter);
      pcap_close(pa->adapter);
    }
#if PCAPIF_RX_USE_THREAD
    /* wait for rxthread to end */
    while(pa->rx_running);
#endif /* PCAPIF_RX_USE_THREAD */
#if PCAPIF_HANDLE_LINKSTATE
    pcapifh_linkstate_close(pa->link_state);
#endif /* PCAPIF_HANDLE_LINKSTATE */
    free(pa);
  }
}
示例#6
0
/** low_level_output():
 * Transmit a packet. The packet is contained in the pbuf that is passed to
 * the function. This pbuf might be chained.
 */
static err_t
pcapif_low_level_output(struct netif *netif, struct pbuf *p)
{
  struct pbuf *q;
  unsigned char buffer[ETH_MAX_FRAME_LEN + ETH_PAD_SIZE];
  unsigned char *buf = buffer;
  unsigned char *ptr;
  struct eth_hdr *ethhdr;
  u16_t tot_len = p->tot_len - ETH_PAD_SIZE;
  struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);

#if defined(LWIP_DEBUG) && LWIP_NETIF_TX_SINGLE_PBUF && !(LWIP_IPV4 && IP_FRAG) && (LWIP_IPV6 && LWIP_IPV6_FRAG)
  LWIP_ASSERT("p->next == NULL && p->len == p->tot_len", p->next == NULL && p->len == p->tot_len);
#endif

  /* initiate transfer */
  if ((p->len == p->tot_len) && (p->len >= ETH_MIN_FRAME_LEN + ETH_PAD_SIZE)) {
    /* no pbuf chain, don't have to copy -> faster */
    buf = &((unsigned char*)p->payload)[ETH_PAD_SIZE];
  } else {
    /* pbuf chain, copy into contiguous buffer */
    if (p->tot_len >= sizeof(buffer)) {
      LINK_STATS_INC(link.lenerr);
      LINK_STATS_INC(link.drop);
      snmp_inc_ifoutdiscards(netif);
      return ERR_BUF;
    }
    ptr = buffer;
    for(q = p; q != NULL; q = q->next) {
      /* Send the data from the pbuf to the interface, one pbuf at a
         time. The size of the data in each pbuf is kept in the ->len
         variable. */
      /* send data from(q->payload, q->len); */
      LWIP_DEBUGF(NETIF_DEBUG, ("netif: send ptr %p q->payload %p q->len %i q->next %p\n", ptr, q->payload, (int)q->len, (void*)q->next));
      if (q == p) {
        memcpy(ptr, &((char*)q->payload)[ETH_PAD_SIZE], q->len - ETH_PAD_SIZE);
        ptr += q->len - ETH_PAD_SIZE;
      } else {
        memcpy(ptr, q->payload, q->len);
        ptr += q->len;
      }
    }
  }

  if (tot_len < ETH_MIN_FRAME_LEN) {
    /* ensure minimal frame length */
    memset(&buf[tot_len], 0, ETH_MIN_FRAME_LEN - tot_len);
    tot_len = ETH_MIN_FRAME_LEN;
  }

  /* signal that packet should be sent */
  if (pcap_sendpacket(pa->adapter, buf, tot_len) < 0) {
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    snmp_inc_ifoutdiscards(netif);
    return ERR_BUF;
  }

  LINK_STATS_INC(link.xmit);
  snmp_add_ifoutoctets(netif, tot_len);
  ethhdr = (struct eth_hdr *)p->payload;
  if ((ethhdr->dest.addr[0] & 1) != 0) {
    /* broadcast or multicast packet*/
    snmp_inc_ifoutnucastpkts(netif);
  } else {
    /* unicast packet */
    snmp_inc_ifoutucastpkts(netif);
  }
  return ERR_OK;
}