Beispiel #1
0
void uip_igmpsend(FAR struct uip_driver_s *dev, FAR struct igmp_group_s *group,
                  FAR uip_ipaddr_t *destipaddr)
{
  nllvdbg("msgid: %02x destipaddr: %08x\n", group->msgid, (int)*destipaddr);

  /* The total length to send is the size of the IP and IGMP headers and 4
   * bytes for the ROUTER ALERT (and, eventually, the ethernet header)
   */

  dev->d_len           = UIP_IPIGMPH_LEN;

  /* The total size of the data is the size of the IGMP header */

  dev->d_sndlen        = UIP_IGMPH_LEN;

  /* Add the router alert option */

  IGMPBUF->ra[0]       = HTONS(IPOPT_RA >> 16);
  IGMPBUF->ra[1]       = HTONS(IPOPT_RA & 0xffff);

  /* Initialize the IPv4 header */

  IGMPBUF->vhl         = 0x46;  /* 4->IP; 6->24 bytes */
  IGMPBUF->tos         = 0;
  IGMPBUF->len[0]      = (dev->d_len >> 8);
  IGMPBUF->len[1]      = (dev->d_len & 0xff);
  ++g_ipid;
  IGMPBUF->ipid[0]     = g_ipid >> 8;
  IGMPBUF->ipid[1]     = g_ipid & 0xff;
  IGMPBUF->ipoffset[0] = UIP_TCPFLAG_DONTFRAG >> 8;
  IGMPBUF->ipoffset[1] = UIP_TCPFLAG_DONTFRAG & 0xff;
  IGMPBUF->ttl         = IGMP_TTL;
  IGMPBUF->proto       = UIP_PROTO_IGMP;

  uiphdr_ipaddr_copy(IGMPBUF->srcipaddr, &dev->d_ipaddr);
  uiphdr_ipaddr_copy(IGMPBUF->destipaddr, destipaddr);

  /* Calculate IP checksum. */

  IGMPBUF->ipchksum    = 0;
  IGMPBUF->ipchksum    = ~uip_igmpchksum((FAR uint8_t *)IGMPBUF, UIP_IPH_LEN + RASIZE);

  /* Set up the IGMP message */

  IGMPBUF->type        = group->msgid;
  IGMPBUF->maxresp     = 0;
  uiphdr_ipaddr_copy(IGMPBUF->grpaddr, &group->grpaddr);

  /* Calculate the IGMP checksum. */

  IGMPBUF->chksum      = 0;
  IGMPBUF->chksum      = ~uip_igmpchksum(&IGMPBUF->type, UIP_IPIGMPH_LEN);

  IGMP_STATINCR(uip_stat.igmp.poll_send);
  IGMP_STATINCR(uip_stat.ip.sent);

  nllvdbg("Outgoing IGMP packet length: %d (%d)\n",
          dev->d_len, (IGMPBUF->len[0] << 8) | IGMPBUF->len[1]);
  igmp_dumppkt(RA, UIP_IPIGMPH_LEN + RASIZE);
}
Beispiel #2
0
static uint16_t ack_interrupt(FAR struct net_driver_s *dev, FAR void *pvconn,
                              FAR void *pvpriv, uint16_t flags)
{
  FAR struct sendfile_s *pstate = (FAR struct sendfile_s *)pvpriv;

  nllvdbg("flags: %04x\n", flags);

  if ((flags & TCP_ACKDATA) != 0)
    {
#ifdef CONFIG_NET_SOCKOPTS
      /* Update the timeout */

      pstate->snd_time = clock_systimer();
#endif

      /* The current acknowledgement number number is the (relative) offset
       * of the of the next byte needed by the receiver.  The snd_isn is the
       * offset of the first byte to send to the receiver.  The difference
       * is the number of bytes to be acknowledged.
       */

      pstate->snd_acked = tcp_getsequence(TCPBUF->ackno) - pstate->snd_isn;
      nllvdbg("ACK: acked=%d sent=%d flen=%d\n",
             pstate->snd_acked, pstate->snd_sent, pstate->snd_flen);

      dev->d_sndlen = 0;

      flags &= ~TCP_ACKDATA;
    }
  else if ((flags & TCP_REXMIT) != 0)
    {
      nlldbg("REXMIT\n");

      /* Yes.. in this case, reset the number of bytes that have been sent
       * to the number of bytes that have been ACKed.
       */

      pstate->snd_sent = pstate->snd_acked;
    }

  /* Check for a loss of connection */

  else if ((flags & (TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT)) != 0)
    {
      /* Report not connected */

      nlldbg("Lost connection\n");

      net_lostconnection(pstate->snd_sock, flags);
      pstate->snd_sent = -ENOTCONN;
    }

  /* Wake up the waiting thread */

  sem_post(&pstate->snd_sem);

  return flags;
}
Beispiel #3
0
static inline uint16_t
tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
               uint16_t flags)
{
  uint16_t ret;

  /* Assume that we will ACK the data.  The data will be ACKed if it is
   * placed in the read-ahead buffer -OR- if it zero length
   */

  ret = (flags & ~TCP_NEWDATA) | TCP_SNDACK;

  /* Is there new data?  With non-zero length?  (Certain connection events
   * can have zero-length with TCP_NEWDATA set just to cause an ACK).
   */

  if (dev->d_len > 0)
    {
#ifdef CONFIG_NET_TCP_READAHEAD
      uint8_t *buffer = dev->d_appdata;
      int      buflen = dev->d_len;
      uint16_t recvlen;
#endif

      nllvdbg("No listener on connection\n");

#ifdef CONFIG_NET_TCP_READAHEAD
      /* Save as the packet data as in the read-ahead buffer.  NOTE that
       * partial packets will not be buffered.
       */

      recvlen = tcp_datahandler(conn, buffer, buflen);
      if (recvlen < buflen)
#endif
        {
          /* There is no handler to receive new data and there are no free
           * read-ahead buffers to retain the data -- drop the packet.
           */

         nllvdbg("Dropped %d bytes\n", dev->d_len);

 #ifdef CONFIG_NET_STATISTICS
          g_netstats.tcp.syndrop++;
          g_netstats.tcp.drop++;
#endif
          /* Clear the TCP_SNDACK bit so that no ACK will be sent */

          ret &= ~TCP_SNDACK;
        }
    }

  /* In any event, the new data has now been handled */

  dev->d_len = 0;
  return ret;
}
Beispiel #4
0
static int lo_txpoll(FAR struct net_driver_s *dev)
{
  FAR struct lo_driver_s *priv = (FAR struct lo_driver_s *)dev->d_private;

  /* Loop while there is data "sent", i.e., while d_len > 0.  That should be
   * the case upon entry here and while the processing of the IPv4/6 packet
   * generates a new packet to be sent.  Sending, of course, just means
   * relaying back through the network for this driver.
   */

  while (priv->lo_dev.d_len > 0)
    {
       NETDEV_TXPACKETS(&priv->lo_dev);
       NETDEV_RXPACKETS(&priv->lo_dev);

#ifdef CONFIG_NET_PKT
      /* When packet sockets are enabled, feed the frame into the packet tap */

       pkt_input(&priv->lo_dev);
#endif

      /* We only accept IP packets of the configured type and ARP packets */

#ifdef CONFIG_NET_IPv4
      if ((IPv4BUF->vhl & IP_VERSION_MASK) == IPv4_VERSION)
        {
          nllvdbg("IPv4 frame\n");
          NETDEV_RXIPV4(&priv->lo_dev);
          ipv4_input(&priv->lo_dev);
        }
      else
#endif
#ifdef CONFIG_NET_IPv6
      if ((IPv6BUF->vtc & IP_VERSION_MASK) == IPv6_VERSION)
        {
          nllvdbg("Iv6 frame\n");
          NETDEV_RXIPV6(&priv->lo_dev);
          ipv6_input(&priv->lo_dev);
        }
      else
#endif
        {
          ndbg("WARNING: Unrecognized packet type dropped: %02x\n", IPv4BUF->vhl);
          NETDEV_RXDROPPED(&priv->lo_dev);
          priv->lo_dev.d_len = 0;
        }

      priv->lo_txdone = true;
      NETDEV_TXDONE(&priv->lo_dev);
    }

  return 0;
}
Beispiel #5
0
static inline uint16_t
net_dataevent(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn,
              uint16_t flags)
{
  uint16_t ret;

  ret = (flags & ~UDP_NEWDATA);

  /* Is there new data?  With non-zero length?  (Certain connection events
   * can have zero-length with UDP_NEWDATA set just to cause an ACK).
   */

  if (dev->d_len > 0)
    {
#ifdef CONFIG_NET_UDP_READAHEAD
      uint8_t *buffer = dev->d_appdata;
      int      buflen = dev->d_len;
      uint16_t recvlen;
#endif

      nllvdbg("No receive on connection\n");

#ifdef CONFIG_NET_UDP_READAHEAD
      /* Save as the packet data as in the read-ahead buffer.  NOTE that
       * partial packets will not be buffered.
       */

      recvlen = udp_datahandler(dev, conn, buffer, buflen);
      if (recvlen < buflen)
#endif
        {
          /* There is no handler to receive new data and there are no free
           * read-ahead buffers to retain the data -- drop the packet.
           */

         nllvdbg("Dropped %d bytes\n", dev->d_len);

 #ifdef CONFIG_NET_STATISTICS
          g_netstats.udp.drop++;
#endif
        }
    }

  /* In any event, the new data has now been handled */

  dev->d_len = 0;
  return ret;
}
Beispiel #6
0
static size_t recvfrom_newdata(FAR struct uip_driver_s *dev,
                               FAR struct recvfrom_s *pstate)
{
  size_t recvlen;

  /* Get the length of the data to return */

  if (dev->d_len > pstate->rf_buflen)
    {
      recvlen = pstate->rf_buflen;
    }
  else
    {
      recvlen = dev->d_len;
    }

  /* Copy the new appdata into the user buffer */

  memcpy(pstate->rf_buffer, dev->d_appdata, recvlen);
  nllvdbg("Received %d bytes (of %d)\n", (int)recvlen, (int)dev->d_len);

  /* Update the accumulated size of the data read */

  pstate->rf_recvlen += recvlen;
  pstate->rf_buffer  += recvlen;
  pstate->rf_buflen  -= recvlen;

  return recvlen;
}
Beispiel #7
0
static void tcp_sendcomplete(FAR struct net_driver_s *dev,
                             FAR struct tcp_hdr_s *tcp)
{
#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
  if (IFF_IS_IPv6(dev->d_flags))
#endif
    {
      tcp_ipv6_sendcomplete(dev, tcp, IPv6BUF);
    }
#endif /* CONFIG_NET_IPv6 */

#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
  else
#endif
    {
      tcp_ipv4_sendcomplete(dev, tcp, IPv4BUF);
    }
#endif /* CONFIG_NET_IPv4 */

  nllvdbg("Outgoing TCP packet length: %d bytes\n", dev->d_len);

#ifdef CONFIG_NET_STATISTICS
  g_netstats.tcp.sent++;
#endif
}
Beispiel #8
0
void igmp_poll(FAR struct net_driver_s *dev)
{
  FAR struct igmp_group_s *group;

  nllvdbg("Entry\n");

  /* Setup the poll operation */

  dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev) + IPIGMP_HDRLEN];
  dev->d_snddata = &dev->d_buf[NET_LL_HDRLEN(dev) + IPIGMP_HDRLEN];

  dev->d_len     = 0;
  dev->d_sndlen  = 0;

  /* Check each member of the group */

  for (group = (FAR struct igmp_group_s *)dev->grplist.head;
       group;
       group = group->next)
    {
      /* Does this member have a pending outgoing message? */

      if (IS_SCHEDMSG(group->flags))
        {
          /* Yes, create the IGMP message in the driver buffer */

          igmp_sched_send(dev, group);

          /* Mark the message as sent and break out */

          CLR_SCHEDMSG(group->flags);
          break;
        }
    }
}
Beispiel #9
0
static void connection_event(struct uip_conn *conn, uint16_t flags)
{
  FAR struct socket *psock = (FAR struct socket *)conn->connection_private;

  if (psock)
    {
      nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags);

      /* UIP_CLOSE: The remote host has closed the connection
       * UIP_ABORT: The remote host has aborted the connection
       * UIP_TIMEDOUT: Connection aborted due to too many retransmissions.
       */
      if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
        {
          /* Indicate that the socket is no longer connected */

          psock->s_flags &= ~_SF_CONNECTED;
        }

      /* UIP_CONNECTED: The socket is successfully connected */

      else if ((flags & UIP_CONNECTED) != 0)
        {
          /* Indicate that the socket is now connected */

          psock->s_flags |= _SF_CONNECTED;
        }
    }
}
Beispiel #10
0
static void uip_tcpsendcomplete(struct uip_driver_s *dev)
{
  struct uip_tcpip_hdr *pbuf = BUF;

  pbuf->ttl         = UIP_TTL;

#ifdef CONFIG_NET_IPv6

  /* For IPv6, the IP length field does not include the IPv6 IP header
   * length.
   */

  pbuf->len[0]      = ((dev->d_len - UIP_IPH_LEN) >> 8);
  pbuf->len[1]      = ((dev->d_len - UIP_IPH_LEN) & 0xff);

#else /* CONFIG_NET_IPv6 */

  pbuf->len[0]      = (dev->d_len >> 8);
  pbuf->len[1]      = (dev->d_len & 0xff);

#endif /* CONFIG_NET_IPv6 */

  pbuf->urgp[0]     = pbuf->urgp[1] = 0;

  /* Calculate TCP checksum. */

  pbuf->tcpchksum   = 0;
  pbuf->tcpchksum   = ~(uip_tcpchksum(dev));

#ifdef CONFIG_NET_IPv6

  pbuf->vtc         = 0x60;
  pbuf->tcf         = 0x00;
  pbuf->flow        = 0x00;

#else /* CONFIG_NET_IPv6 */

  pbuf->vhl         = 0x45;
  pbuf->tos         = 0;
  pbuf->ipoffset[0] = 0;
  pbuf->ipoffset[1] = 0;
  ++g_ipid;
  pbuf->ipid[0]     = g_ipid >> 8;
  pbuf->ipid[1]     = g_ipid & 0xff;

  /* Calculate IP checksum. */

  pbuf->ipchksum    = 0;
  pbuf->ipchksum    = ~(uip_ipchksum(dev));

#endif /* CONFIG_NET_IPv6 */

  nllvdbg("Outgoing TCP packet length: %d (%d)\n",
          dev->d_len, (pbuf->len[0] << 8) | pbuf->len[1]);

#ifdef CONFIG_NET_STATISTICS
  uip_stat.tcp.sent++;
  uip_stat.ip.sent++;
#endif
}
Beispiel #11
0
void uip_tcprexmit(struct uip_driver_s *dev, struct uip_conn *conn,
                   uint16_t result)
{
    nllvdbg("result: %04x d_sndlen: %d conn->unacked: %d\n",
            result, dev->d_sndlen, conn->unacked);

    dev->d_appdata = dev->d_snddata;

    /* If the application has data to be sent, or if the incoming packet had
     * new data in it, we must send out a packet.
     */

    if (dev->d_sndlen > 0 && conn->unacked > 0)
    {
        /* We always set the ACK flag in response packets adding the length of
         * the IP and TCP headers.
         */

        uip_tcpsend(dev, conn, TCP_ACK | TCP_PSH, dev->d_sndlen + UIP_TCPIP_HLEN);
    }

    /* If there is no data to send, just send out a pure ACK if one is requested`. */

    else if ((result & UIP_SNDACK) != 0)
    {
        uip_tcpsend(dev, conn, TCP_ACK, UIP_TCPIP_HLEN);
    }

    /* There is nothing to do -- drop the packet */

    else
    {
        dev->d_len = 0;
    }
}
Beispiel #12
0
static void uip_igmptimeout(int argc, uint32_t arg, ...)
{
  FAR struct igmp_group_s *group;

  /* If the state is DELAYING_MEMBER then we send a report for this group */

  nllvdbg("Timeout!\n");
  group = (FAR struct igmp_group_s *)arg;
  DEBUGASSERT(argc == 1 && group);

  /* If the group exists and is no an IDLE MEMBER, then it must be a DELAYING
   * member.  Race conditions are avoided because (1) the timer is not started
   * until after the first IGMPv2_MEMBERSHIP_REPORT during the join, and (2)
   * the timer is canceled before sending the IGMP_LEAVE_GROUP during a leave.
   */

  if (!IS_IDLEMEMBER(group->flags))
    {
      /* Schedule (and forget) the Membership Report.  NOTE:
       * Since we are executing from a timer interrupt, we cannot wait
       * for the message to be sent.
       */

      IGMP_STATINCR(uip_stat.igmp.report_sched);
      uip_igmpschedmsg(group, IGMPv2_MEMBERSHIP_REPORT);

      /* Also note:  The Membership Report is sent at most two times becasue
       * the timer is not reset here.  Hmm.. does this mean that the group
       * is stranded if both reports were lost?  This is consistent with the
       * RFC that states: "To cover the possibility of the initial Membership
       * Report being lost or damaged, it is recommended that it be repeated
       * once or twice after shortdelays [Unsolicited Report Interval]..."
       */
    }
}
static void connection_event(FAR struct uip_conn *conn, uint16_t flags)
{
  FAR struct socket *psock = (FAR struct socket *)conn->connection_private;

  if (psock)
    {
      nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags);

      /* UIP_CLOSE, UIP_ABORT, or UIP_TIMEDOUT: Loss-of-connection events */

      if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
        {
          net_lostconnection(psock, flags);
        }

      /* UIP_CONNECTED: The socket is successfully connected */

      else if ((flags & UIP_CONNECTED) != 0)
        {
          /* Indicate that the socket is now connected */

          psock->s_flags |= _SF_CONNECTED;
          psock->s_flags &= ~_SF_CLOSED;
        }
    }
}
Beispiel #14
0
static uint16_t connection_event(FAR struct net_driver_s *dev,
                                 FAR void *pvconn, FAR void *pvpriv,
                                 uint16_t flags)
{
  FAR struct socket *psock = (FAR struct socket *)pvpriv;

  if (psock)
    {
      nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags);

      /* TCP_DISCONN_EVENTS: TCP_CLOSE, TCP_ABORT, TCP_TIMEDOUT, or
       * NETDEV_DOWN.  All loss-of-connection events.
       */

      if ((flags & TCP_DISCONN_EVENTS) != 0)
        {
          connection_closed(psock, flags);
        }

      /* TCP_CONNECTED: The socket is successfully connected */

      else if ((flags & TCP_CONNECTED) != 0)
        {
          /* Indicate that the socket is now connected */

          psock->s_flags |= _SF_CONNECTED;
          psock->s_flags &= ~_SF_CLOSED;
        }
    }

  return flags;
}
Beispiel #15
0
void icmp_send(FAR struct net_driver_s *dev, FAR in_addr_t *destaddr)
{
  FAR struct icmp_iphdr_s *picmp = ICMPBUF;

  if (dev->d_sndlen > 0)
    {
      IFF_SET_IPv4(dev->d_flags);

      /* The total length to send is the size of the application data plus
       * the IP and ICMP headers (and, eventually, the Ethernet header)
       */

      dev->d_len = dev->d_sndlen + IPICMP_HDRLEN;

      /* The total size of the data (for ICMP checksum calculation) includes
       * the size of the ICMP header
       */

      dev->d_sndlen += ICMP_HDRLEN;

      /* Initialize the IP header. */

      picmp->vhl         = 0x45;
      picmp->tos         = 0;
      picmp->len[0]      = (dev->d_len >> 8);
      picmp->len[1]      = (dev->d_len & 0xff);
      ++g_ipid;
      picmp->ipid[0]     = g_ipid >> 8;
      picmp->ipid[1]     = g_ipid & 0xff;
      picmp->ipoffset[0] = IP_FLAG_DONTFRAG >> 8;
      picmp->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff;
      picmp->ttl         = IP_TTL;
      picmp->proto       = IP_PROTO_ICMP;

      net_ipv4addr_hdrcopy(picmp->srcipaddr, &dev->d_ipaddr);
      net_ipv4addr_hdrcopy(picmp->destipaddr, destaddr);

      /* Calculate IP checksum. */

      picmp->ipchksum    = 0;
      picmp->ipchksum    = ~(ipv4_chksum(dev));

      /* Calculate the ICMP checksum. */

      picmp->icmpchksum  = 0;
      picmp->icmpchksum  = ~(icmp_chksum(dev, dev->d_sndlen));
      if (picmp->icmpchksum == 0)
        {
          picmp->icmpchksum = 0xffff;
        }

      nllvdbg("Outgoing ICMP packet length: %d (%d)\n",
              dev->d_len, (picmp->len[0] << 8) | picmp->len[1]);

#ifdef CONFIG_NET_STATISTICS
      g_netstats.icmp.sent++;
      g_netstats.ipv4.sent++;
#endif
    }
Beispiel #16
0
uint16_t uip_tcpcallback(struct uip_driver_s *dev, struct uip_conn *conn,
                         uint16_t flags)
{
    /* Preserve the UIP_ACKDATA, UIP_CLOSE, and UIP_ABORT in the response.
     * These is needed by uIP to handle responses and buffer state.  The
     * UIP_NEWDATA indication will trigger the ACK response, but must be
     * explicitly set in the callback.
     */

    nllvdbg("flags: %04x\n", flags);

    /* Perform the data callback.  When a data callback is executed from 'list',
     * the input flags are normally returned, however, the implementation
     * may set one of the following:
     *
     *   UIP_CLOSE   - Gracefully close the current connection
     *   UIP_ABORT   - Abort (reset) the current connection on an error that
     *                 prevents UIP_CLOSE from working.
     *
     * And/Or set/clear the following:
     *
     *   UIP_NEWDATA - May be cleared to indicate that the data was consumed
     *                 and that no further process of the new data should be
     *                 attempted.
     *   UIP_SNDACK  - If UIP_NEWDATA is cleared, then UIP_SNDACK may be set
     *                 to indicate that an ACK should be included in the response.
     *                 (In UIP_NEWDATA is cleared bu UIP_SNDACK is not set, then
     *                 dev->d_len should also be cleared).
     */

    flags = uip_callbackexecute(dev, conn, flags, conn->list);

    /* There may be no new data handler in place at them moment that the new
     * incoming data is received.  If the new incoming data was not handled, then
     * either (1) put the unhandled incoming data in the read-ahead buffer (if
     * enabled) or (2) suppress the ACK to the data in the hope that it will
     * be re-transmitted at a better time.
     */

    if ((flags & UIP_NEWDATA) != 0)
    {
        /* Data was not handled.. dispose of it appropriately */

        flags = uip_dataevent(dev, conn, flags);
    }

    /* Check if there is a connection-related event and a connection
     * callback.
     */

    if (((flags & UIP_CONN_EVENTS) != 0) && conn->connection_event)
    {
        /* Perform the callback */

        conn->connection_event(conn, flags);
    }

    return flags;
}
Beispiel #17
0
int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blconn)
{
  FAR struct uip_backlog_s     *bls;
  FAR struct uip_blcontainer_s *blc;
  FAR struct uip_blcontainer_s *prev;

  nllvdbg("conn=%p blconn=%p\n", conn, blconn);

#ifdef CONFIG_DEBUG
  if (!conn)
    {
      return -EINVAL;
    }
#endif

  bls = conn->backlog;
  if (bls)
    {
       /* Find the container hold the connection */

       for (blc = (FAR struct uip_blcontainer_s *)sq_peek(&bls->bl_pending), prev = NULL;
            blc;
            prev = blc, blc = (FAR struct uip_blcontainer_s *)sq_next(&blc->bc_node))
         {
            if (blc->bc_conn == blconn)
              {
                if (prev)
                  {
                    /* Remove the a container from the middle of the list of
                     * pending connections
                      */

                    (void)sq_remafter(&prev->bc_node, &bls->bl_pending);
                  }
                else
                  {
                    /* Remove the a container from the head of the list of
                     * pending connections
                     */

                    (void)sq_remfirst(&bls->bl_pending);
                  }

                /* Put container in the free list */

                blc->bc_conn = NULL;
                sq_addlast(&blc->bc_node, &bls->bl_free);
                return OK;
              }
          }

        nlldbg("Failed to find pending connection\n");
        return -EINVAL;
    }
  return OK;
}
Beispiel #18
0
static inline void igmp_sched_send(FAR struct net_driver_s *dev,
                                   FAR struct igmp_group_s *group)
{
  net_ipaddr_t *dest;

  /* Check what kind of message we need to send.  There are only two
   * possibilities:
   */

  if (group->msgid == IGMPv2_MEMBERSHIP_REPORT)
    {
      dest = &group->grpaddr;
      nllvdbg("Send IGMPv2_MEMBERSHIP_REPORT, dest=%08x flags=%02x\n",
               *dest, group->flags);
      IGMP_STATINCR(g_netstats.igmp.report_sched);
      SET_LASTREPORT(group->flags); /* Remember we were the last to report */
    }
  else
    {
      DEBUGASSERT(group->msgid == IGMP_LEAVE_GROUP);
      dest = &g_allrouters;
      nllvdbg("Send IGMP_LEAVE_GROUP, dest=%08x flags=%02x\n",
               *dest, group->flags);
      IGMP_STATINCR(g_netstats.igmp.leave_sched);
    }

  /* Send the message */

  igmp_send(dev, group, dest);

  /* Indicate that the message has been sent */

  CLR_SCHEDMSG(group->flags);
  group->msgid = 0;

  /* If there is a thread waiting fore the message to be sent, wake it up */

  if (IS_WAITMSG(group->flags))
    {
      nllvdbg("Awakening waiter\n");
      sem_post(&group->sem);
    }
}
Beispiel #19
0
uint16_t hci_command_send(uint16_t usOpcode, uint8_t *pucBuff,
                          uint8_t ucArgsLength)
{
  uint8_t *stream;

  stream = (pucBuff + SPI_HEADER_SIZE);

  nllvdbg("Send 0x%x\n", usOpcode);
  UINT8_TO_STREAM(stream, HCI_TYPE_CMND);
  stream = UINT16_TO_STREAM(stream, usOpcode);
  UINT8_TO_STREAM(stream, ucArgsLength);

  /* Update the opcode of the event we will be waiting for */

  cc3000_write(pucBuff, ucArgsLength + SIMPLE_LINK_HCI_CMND_HEADER_SIZE);
  nllvdbg("Send of 0x%x Completed\n", usOpcode);

  return 0;
}
Beispiel #20
0
void SimpleLinkWaitData(uint8_t *pBuf, uint8_t *from, uint8_t *fromlen)
{
  /* In the blocking implementation the control to caller will be returned only
   * after the end of current transaction, i.e. only after data will be received
   */

  nllvdbg("Looking for Data\n");
  uint16_t event_type;
  uint16_t opcode = tSLInformation.usRxEventOpcode;

  do
    {
      tSLInformation.pucReceivedData = cc3000_wait();
      tSLInformation.usEventOrDataReceived = 1;

      if (*tSLInformation.pucReceivedData == HCI_TYPE_DATA)
        {
          tSLInformation.usRxDataPending = 1;
          hci_event_handler(pBuf, from, fromlen);
          break;
        }
      else
        {
          STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET, event_type);
          nllvdbg("Evtn:0x%x\n", event_type);

          if (hci_unsolicited_event_handler() == 1)
            {
              nllvdbg("Processed Event  0x%x want Data! Opcode 0x%x\n", event_type, opcode);
            }
          else
            {
              nllvdbg("!!!!!opcode 0x%x\n", opcode);
            }

          UNUSED(event_type);
        }
    }
  while (*tSLInformation.pucReceivedData == HCI_TYPE_EVNT);

  nllvdbg("Done for Data 0x%x\n", opcode);
  UNUSED(opcode);
}
Beispiel #21
0
uint16_t uip_datahandler(FAR struct uip_conn *conn, FAR uint8_t *buffer,
                         uint16_t buflen)
{
    FAR struct uip_readahead_s *readahead1;
    FAR struct uip_readahead_s *readahead2 = NULL;
    uint16_t remaining;
    uint16_t recvlen = 0;

    /* First, we need to determine if we have space to buffer the data.  This
     * needs to be verified before we actually begin buffering the data. We
     * will use any remaining space in the last allocated readahead buffer
     * plus as much one additional buffer.  It is expected that the size of
     * readahead buffers are tuned so that one full packet will always fit
     * into one readahead buffer (for example if the buffer size is 420, then
     * a readahead buffer of 366 will hold a full packet of TCP data).
     */

    readahead1 = (FAR struct uip_readahead_s*)conn->readahead.tail;
    if ((readahead1 &&
            (CONFIG_NET_TCP_READAHEAD_BUFSIZE - readahead1->rh_nbytes) > buflen) ||
            (readahead2 = uip_tcpreadahead_alloc()) != NULL)
    {
        /* We have buffer space.  Now try to append add as much data as possible
         * to the last readahead buffer attached to this connection.
         */

        remaining = buflen;
        if (readahead1)
        {
            recvlen = uip_readahead(readahead1, buffer, remaining);
            if (recvlen > 0)
            {
                buffer    += recvlen;
                remaining -= recvlen;
            }
        }

        /* Do we need to buffer into the newly allocated buffer as well? */

        if (readahead2)
        {
            readahead2->rh_nbytes = 0;
            recvlen += uip_readahead(readahead2, buffer, remaining);

            /* Save the readahead buffer in the connection structure where
             * it can be found with recv() is called.
             */

            sq_addlast(&readahead2->rh_node, &conn->readahead);
        }
    }

    nllvdbg("Buffered %d bytes (of %d)\n", recvlen, buflen);
    return recvlen;
}
Beispiel #22
0
static uint32_t arp_send_interrupt(FAR struct net_driver_s *dev,
                                   FAR void *pvconn,
                                   FAR void *priv, uint32_t flags)
{
  FAR struct arp_send_s *state = (FAR struct arp_send_s *)priv;

  nllvdbg("flags: %04x sent: %d\n", flags, state->snd_sent);

  if (state)
    {
      /* Check if the network is still up */

      if ((flags & NETDEV_DOWN) != 0)
        {
          nlldbg("ERROR: Interface is down\n");
          arp_send_terminate(state, -ENETUNREACH);
          return flags;
        }

      /* Check if the outgoing packet is available. It may have been claimed
       * by a send interrupt serving a different thread -OR- if the output
       * buffer currently contains unprocessed incoming data. In these cases
       * we will just have to wait for the next polling cycle.
       */

      if (dev->d_sndlen > 0 || (flags & PKT_NEWDATA) != 0)
        {
          /* Another thread has beat us sending data or the buffer is busy,
           * Check for a timeout. If not timed out, wait for the next
           * polling cycle and check again.
           */

          /* REVISIT: No timeout. Just wait for the next polling cycle */

          return flags;
        }

      /* It looks like we are good to send the data */
      /* Copy the packet data into the device packet buffer and send it */

      arp_format(dev, state->snd_ipaddr);

      /* Make sure no ARP request overwrites this ARP request.  This
       * flag will be cleared in arp_out().
       */

      IFF_SET_NOARP(dev->d_flags);

      /* Don't allow any further call backs. */

      arp_send_terminate(state, OK);
    }

  return flags;
}
void SpiReceiveHandler(void *pvBuffer)
{
  tSLInformation.pucReceivedData = (uint8_t *)pvBuffer;
  tSLInformation.usEventOrDataReceived = 1;

  uint16_t event_type;
  STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET,event_type);
  nllvdbg("Evtn:0x%x\n", event_type);

  hci_unsolicited_event_handler();
}
Beispiel #24
0
static void connection_event(struct uip_conn *conn, uint16_t flags)
{
  FAR struct socket *psock = (FAR struct socket *)conn->connection_private;

  if (psock)
    {
      nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags);

      /* These loss-of-connection events may be reported:
       *
       *   UIP_CLOSE: The remote host has closed the connection
       *   UIP_ABORT: The remote host has aborted the connection
       *   UIP_TIMEDOUT: Connection aborted due to too many retransmissions.
       *
       * And we need to set these two socket status bits appropriately:
       *
       *  _SF_CONNECTED==1 && _SF_CLOSED==0 - the socket is connected
       *  _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was gracefully disconnected
       *  _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was rudely disconnected
       */

      if ((flags & UIP_CLOSE) != 0)
        {
          /* The peer gracefully closed the connection.  Marking the
           * connection as disconnected will suppress some subsequent
           * ENOTCONN errors from receive.  A graceful disconnection is
           * not handle as an error but as an "end-of-file"
           */

          psock->s_flags &= ~_SF_CONNECTED;
          psock->s_flags |= _SF_CLOSED;
        }
      else if ((flags & (UIP_ABORT|UIP_TIMEDOUT)) != 0)
        {
          /* The loss of connection was less than graceful.  This will (eventually)
           * be reported as an ENOTCONN error.
           */

          psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED);
        }

      /* UIP_CONNECTED: The socket is successfully connected */

      else if ((flags & UIP_CONNECTED) != 0)
        {
          /* Indicate that the socket is now connected */

          psock->s_flags |= _SF_CONNECTED;
          psock->s_flags &= ~_SF_CLOSED;
        }
    }
}
Beispiel #25
0
static int telnetd_open(FAR struct file *filep)
{
  FAR struct inode *inode = filep->f_inode;
  FAR struct telnetd_dev_s *priv = inode->i_private;
  int tmp;
  int ret;

  nllvdbg("td_crefs: %d\n", priv->td_crefs);

  /* O_NONBLOCK is not supported */

  if (filep->f_oflags & O_NONBLOCK)
    {
      ret = -ENOSYS;
      goto errout;
    }

  /* Get exclusive access to the device structures */

  ret = sem_wait(&priv->td_exclsem);
  if (ret < 0)
    {
      ret = -errno;
      goto errout;
    }

  /* Increment the count of references to the device.  If this the first
   * time that the driver has been opened for this device, then initialize
   * the device.
   */

  tmp = priv->td_crefs + 1;
  if (tmp > 255)
    {
      /* More than 255 opens; uint8_t would overflow to zero */

      ret = -EMFILE;
      goto errout_with_sem;
    }

  /* Save the new open count on success */

  priv->td_crefs = tmp;
  ret = OK;

errout_with_sem:
  sem_post(&priv->td_exclsem);

errout:
  return ret;
}
Beispiel #26
0
FAR struct igmp_group_s *igmp_grpalloc(FAR struct net_driver_s *dev,
                                       FAR const in_addr_t *addr)
{
  FAR struct igmp_group_s *group;
  net_lock_t flags;

  nllvdbg("addr: %08x dev: %p\n", *addr, dev);
  if (up_interrupt_context())
    {
#if CONFIG_PREALLOC_IGMPGROUPS > 0
      grplldbg("Use a pre-allocated group entry\n");
      group = igmp_grpprealloc();
#else
      grplldbg("Cannot allocate from interrupt handler\n");
      group = NULL;
#endif
    }
  else
    {
      grplldbg("Allocate from the heap\n");
      group = igmp_grpheapalloc();
    }

  grplldbg("group: %p\n", group);

  /* Check if we successfully allocated a group structure */

  if (group)
    {
      /* Initialize the non-zero elements of the group structure */

      net_ipv4addr_copy(group->grpaddr, *addr);
      sem_init(&group->sem, 0, 0);

      /* Initialize the group timer (but don't start it yet) */

      group->wdog = wd_create();
      DEBUGASSERT(group->wdog);

      /* Interrupts must be disabled in order to modify the group list */

      flags = net_lock();

      /* Add the group structure to the list in the device structure */

      sq_addfirst((FAR sq_entry_t *)group, &dev->grplist);
      net_unlock(flags);
    }

  return group;
}
Beispiel #27
0
static uint32_t connection_event(FAR struct net_driver_s *dev,
                                 FAR void *pvconn, FAR void *pvpriv,
                                 uint32_t flags)
{
  FAR struct socket *psock = (FAR struct socket *)pvpriv;

  if (psock)
    {
      nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags);

      /* TCP_DISCONN_EVENTS: TCP_CLOSE, TCP_ABORT, TCP_TIMEDOUT, or
       * NETDEV_DOWN.  All loss-of-connection events.
       */

      if ((flags & TCP_DISCONN_EVENTS) != 0)
        {
          connection_closed(psock, flags);
        }

      /* TCP_CONNECTED: The socket is successfully connected */

      else if ((flags & TCP_CONNECTED) != 0)
        {
#if 0 /* REVISIT: Assertion fires.  Why? */
#ifdef CONFIG_NETDEV_MULTINIC
          FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)psock->s_conn;

          /* Make sure that this is the device bound to the connection */

          DEBUGASSERT(conn->dev == NULL || conn->dev == dev);
          conn->dev = dev;
#endif
#endif

          /* If there is no local address assigned to the socket (perhaps
           * because it was INADDR_ANY), then assign it the address of the
           * connecting device.
           *
           * TODO: Implement this.
           */

          /* Indicate that the socket is now connected */

          psock->s_flags |= _SF_CONNECTED;
          psock->s_flags &= ~_SF_CLOSED;
        }
    }

  return flags;
}
void uip_udpcallback(struct uip_driver_s *dev, struct uip_udp_conn *conn,
                     uint16_t flags)
{
  nllvdbg("flags: %04x\n", flags);

  /* Some sanity checking */

  if (conn)
    {
      /* Perform the callback */

      flags = uip_callbackexecute(dev, conn, flags, conn->list);
    }
}
Beispiel #29
0
static uint16_t tcp_poll_interrupt(FAR struct net_driver_s *dev, FAR void *conn,
                                   FAR void *pvpriv, uint16_t flags)
{
  FAR struct tcp_poll_s *info = (FAR struct tcp_poll_s *)pvpriv;

  nllvdbg("flags: %04x\n", flags);

  DEBUGASSERT(!info || (info->psock && info->fds));

  /* 'priv' might be null in some race conditions (?) */

  if (info)
    {
      pollevent_t eventset = 0;

      /* Check for data or connection availability events. */

      if ((flags & (TCP_NEWDATA | TCP_BACKLOG)) != 0)
        {
          eventset |= POLLIN & info->fds->events;
        }

      /* A poll is a sign that we are free to send data. */

      if ((flags & TCP_POLL) != 0)
        {
          eventset |= (POLLOUT & info->fds->events);
        }

      /* Check for a loss of connection events. */

      if ((flags & (TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT)) != 0)
        {
          /* Marki that the connection has been lost */

          net_lostconnection(info->psock, flags);
          eventset |= (POLLERR | POLLHUP);
        }

      /* Awaken the caller of poll() is requested event occurred. */

      if (eventset)
        {
          info->fds->revents |= eventset;
          sem_post(info->fds->sem);
        }
    }

  return flags;
}
Beispiel #30
0
static uint16_t netclose_interrupt(struct uip_driver_s *dev, void *pvconn,
                                   void *pvpriv, uint16_t flags)
{
  struct tcp_close_s *pstate = (struct tcp_close_s *)pvpriv;

  nllvdbg("flags: %04x\n", flags);

  if (pstate)
    {
      /* UIP_CLOSE: The remote host has closed the connection
       * UIP_ABORT: The remote host has aborted the connection
       */

      if ((flags & (UIP_CLOSE|UIP_ABORT)) != 0)
        {
          /* The disconnection is complete */

          pstate->cl_cb->flags   = 0;
          pstate->cl_cb->priv    = NULL;
          pstate->cl_cb->event   = NULL;
          sem_post(&pstate->cl_sem);
          nllvdbg("Resuming\n");
        }
      else
        {
          /* Drop data received in this state and make sure that UIP_CLOSE
           * is set in the response
           */

          dev->d_len = 0;
          return (flags & ~UIP_NEWDATA) | UIP_CLOSE;
        }
    }

  return flags;
}