Esempio n. 1
0
int
pktwait(char * app, void * pio)
{
   u_long   tmo;

   tmo = cticks + (3 * TPS);  /* 3 second timeout */
   if (deflength > (int)lilbufsiz)
   {
      while (bigfreeq.q_len < 1)
      {
         tk_yield();
         if (tmo < cticks)
         {
            ns_printf(pio, "%s flood timeout\n", app);
            return -1;
         }
      }
   }
   else  /* can use a little packet */
   {
      while (lilfreeq.q_len < 1)
      {
         tk_yield();
         if (tmo < cticks)
         {
            ns_printf(pio, "%s flood timeout\n",app);
            return -1;
         }
      }
   }
   return 0;
}
Esempio n. 2
0
void
tcp_sleep(void * event)
{
   int   i;

   /* search event array for an unused slot */
   for (i = 0; i < MAX_EVENTS; i++)
   {
      if (tk_eventlist[i].event == 0)     /* found a slot */
      {
         tk_eventlist[i].event = event;   /* save event to wake up on */
         tk_eventlist[i].task = TK_THIS;  /* save calling task */
         UNLOCK_NET_RESOURCE(NET_RESID);  /* free stack mutex */
         TK_BLOCK();                      /* suspend calling task */
         LOCK_NET_RESOURCE(NET_RESID);    /* we woke up - reenter stack */
         tk_eventlist[i].event = NULL;    /* clear array entry */
         return;
      }
   }
   /* fall to here if we ran out of free event slots. Best thing to do is
    * let system spin, then return to caller for another sleep test.
    */
   tcp_no_taskslot++;
   tk_yield();
}
Esempio n. 3
0
void
tk_kill(task * tk_to_die)
{
   task *tk;

   if(tk_died)       /* Is another task in the process of dying? */
   {
      tk_yield();    /* this should allow it to finish */
      if(tk_died)    /* Other task still dying? */
      {
         dtrap();    /* system bug */
      }
   }
   /* hunt for the task which tk_to_die is the successor of */
   for (tk = tk_cur; tk->tk_next != tk_to_die; tk = tk->tk_next) ;

   /* now patch around tk_to_die */
   tk->tk_next = tk_to_die->tk_next;

   /* If I'm killing myself, die the next time I block */
   if (tk_cur == tk_to_die) 
   {
      tk_died = tk_cur;
   }
   else
      tk_del(tk_to_die);
}
Esempio n. 4
0
int
tcp_send_an_echo(TCPCLIENT tcpclient)
{
   int   e;
   u_long   total;
   u_long   sendsize;
   u_long   starttime;
   int      block;
   u_long   words;      /* send data word index */
   u_long   dataval;
   u_long   sent  =  0; /* sent in this loop */

   if (tcpclient->ticks > cticks)  
      return TCPE_TIME_NOT_RIPE ;
   if (tcpclient->sending)    /* guard against re-entry */
      return TCPE_BLOCKED;
   tcpclient->sending++;

   ns_printf(tcpclient->pio,"sending TCP echo %ld to %s\n", 
    tcpclient->send_cnt, print_ipad(tcpclient->rhost));

   total = tcpclient->len;
   block = 0;
   starttime = cticks;
   while (total > sent)
   {
      tcpclient->ticks = cticks + tcpclient->delay;   /* back off time for next send */
      sendsize = total - sent;
      if (sendsize > ECHOBUFSIZE)
         sendsize = ECHOBUFSIZE;

      /* write pattern into full-size data for integrity test */
      dataval = (tcpclient->tot_sent + sent)/4;    /* data for first word of buffer */
      for (words = 0; words < (ECHOBUFSIZE/4); words++)
         *((u_long*)tcpclient->inbuf + words) = dataval++;

      e = send(tcpclient->sock, tcpclient->inbuf, (int)sendsize, 0);
      if (e < 0)
      {
         e = t_errno(tcpclient->sock);
         if (e == EWOULDBLOCK)
         {
            tk_yield();
            continue;
         }
         ns_printf(tcpclient->pio,"error %d sending TCP echo number %ld\n", 
            e, tcpclient->send_cnt);
         ns_printf(tcpclient->pio,"   on byte %ld\n", e);

         tcpclient->sending--;
         return TCPE_SEND_FAILED;
      }
      sent += e;
      if ((block += e) >= ECHOBUFSIZE)
      {
         ns_printf(tcpclient->pio, ".");
         block -= ECHOBUFSIZE;
      }
      tk_yield();    /* let other tasks run */
   }

   tcpclient->send_cnt++;  /* keep counters current */
   tcpclient->tot_sent += sent;
   ns_printf(tcpclient->pio, "\ntcpecho: echoed %ld bytes", sent);

   if (total > ECHOBUFSIZE)   /* see if we should print performance numbers */
   {
      u_long   endticks;
      u_long   bps;
      int   fraction;

      /* wait for all data to come back */
      endticks = cticks + (5*TPS);        /* use endticks for timeout */
      while ((tcpclient->tot_rcvd < tcpclient->tot_sent) &&
          (cticks > endticks))
      {
         tk_yield();
      }

      endticks = cticks - starttime;
      if (endticks > 0) /* avoid divide by 0 */
      {
         bps = sent/endticks;    /* bytes per tick */
         bps *= TPS;             /* convert to bytes/Sec */
         bps /= 1024;            /* KBytes/Sec */
         fraction = (int)endticks % TPS;
         endticks /= TPS;
         ns_printf(tcpclient->pio, " in %d and %d/%d seconds.\n%ld KBytes/sec", 
          (int)endticks, fraction, TPS, bps);
      }
   }
   ns_printf(tcpclient->pio, "\n");

   tcpclient->sending--;   /* clear reentry flag */
   return SUCCESS;
}
Esempio n. 5
0
int
in_reshost(char * host, /* IN - textual IP address or host name */
   ip_addr *   address, /* OUT - address if successful */
   int   flags)         /* IN - RH_VERBOSE, RH_BLOCK */
{
   char *   cp;      /* error holder */
   unsigned snbits;  /* for pass to parse_ipad() */
#ifdef DNS_CLIENT
   int   e;          /* Net error code */
   u_long   tmo;     /* timeout for blocking calls */
   int   blocking =  flags &  RH_BLOCK;
#endif   /* DNS_CLIENT */
   int   verbose  =  flags &  RH_VERBOSE;

   cp = parse_ipad(address, &snbits, host);

   if (!cp) /* worked, string was parsable dot notation */
      return 0;

#ifndef DNS_CLIENT
   if (verbose)
      dprintf("Unable to parse IP host %s.\nerror: %s\n", host, (char*)cp);
   return ENP_PARAM;
#else /* DNS_CLIENT enabled in build */

   if (verbose)
      dprintf("can't parse %s (%s), trying DNS\n", host, cp);

   tmo = cticks + (5 * TPS);  /* set timeout value */

   if (dns_servers[0])  /* dont bother if no servers are set */
   {
      if (verbose)
         dprintf("trying DNS lookup...\n");
      e = dns_query(host, address);
      if (e == ENP_SEND_PENDING)
      {
         if (blocking)
         {
            while (tmo > cticks)
            {
               tk_yield();
               e = dns_query(host, address);
               if (e == 0)
                  goto rh_got_dns;
            }
         }
         if (verbose)
            dprintf("DNS inquiry sent\n");
         return 0;
      }
      else if(e == 0)
      {
         rh_got_dns:
         /* DNS resolution worked */
         if (verbose)
            dprintf("active host found via DNS (%u.%u.%u.%u)\n", 
          PUSH_IPADDR(*address));
         return 0;
      }
      else if(e == ENP_TIMEOUT)  /* timeout? */
      {
         if (verbose)
            dprintf("DNS timeout");
      }
      else
      {
         if (verbose)
            dprintf("DNS error %d", e);
      }
      if (verbose)
         dprintf(", host not set\n");
      return e;
   }

   if (verbose)
      dprintf("DNS/host-parse failed.\n");
   return ENP_PARAM;
#endif   /* DNS_CLIENT */
}
Esempio n. 6
0
void
pktdemux()
{
   PACKET   pkt;
   NET      ifc;                /* interface packet came from */
   IFMIB    mib;
   int      pkts;
   char *   eth;

   pkts = 0;   /* packets per loop */

   while (rcvdq.q_len)
   {
      /* If we are low on free packets, don't hog CPU cycles */
      if (pkts++ > bigfreeq.q_len)
      {
#ifdef SUPERLOOP
         return;        /* don't hog stack on superloop */
#else    /* SUPERLOOP */
         tk_yield(); /* let application tasks process received packets */
         pkts = 0;   /* reset counter */
#endif   /* SUPERLOOP else */
      }

      /* If we get receive interupt from the net during this
      lock, the MAC driver needs to wait or reschedule */
      LOCK_NET_RESOURCE(RXQ_RESID);
      pkt = (PACKET)q_deq(&rcvdq);
      UNLOCK_NET_RESOURCE(RXQ_RESID);
      if (!pkt) panic("pktdemux: got null pkt");
      ifc = pkt->net;

      mib = ifc->n_mib;
      /* maintain mib stats for unicast and broadcast */
      if (isbcast(ifc, (u_char*)pkt->nb_buff + ETHHDR_BIAS))
         mib->ifInNUcastPkts++;
      else
         mib->ifInUcastPkts++;

      if(mib->ifAdminStatus == NI_DOWN)
      {
         LOCK_NET_RESOURCE(FREEQ_RESID);
         pk_free(pkt);  /* dump packet from downed interface */
         UNLOCK_NET_RESOURCE(FREEQ_RESID);
         mib->ifInDiscards++;
         continue;      /* next packet */
      }

#ifdef NPDEBUG
      if (*(pkt->nb_buff - ALIGN_TYPE) != 'M' ||
          *(pkt->nb_buff + pkt->nb_blen) != 'M')
      {
         dtrap();
         panic("pktdemux: corrupt pkt");
      }
#endif   /* NPDEBUG */

#ifdef  LOSSY_IO
      if(NDEBUG & LOSSY_RX)
      {
         if(myloss())  
         {
            LOCK_NET_RESOURCE(FREEQ_RESID);
            pk_free(pkt);        /* punt packet */
            UNLOCK_NET_RESOURCE(FREEQ_RESID);
            in_lastloss = (int)(cticks & 0x07) - 4;  /* pseudo random reset */
            continue;            /* act as if we sent OK */
         }
      }
#endif   /* LOSSY_IO */

      /* see if driver set pkt->nb_prot and pkt->type */
      if((ifc->n_flags & NF_NBPROT) == 0)
      {
         /* Set pkt->type and pkt->nb_prot based based on media type.
          * Some device drivers pass nb_plen as the total length of the
          * packet, while others subtract the MAC header. The latter is
          * probably the right thing to do, but because of this historic
          * inconsistency we don't try to fix it here - the longer size
          * turns out to be harmless since the IP layer fixes the size
          * based on the IP header length field.
          */
         switch(ifc->n_mib->ifType)
         {
         case ETHERNET:
            /* get pointer to ethernet header */
            eth = (pkt->nb_buff + ETHHDR_BIAS);
#ifdef IEEE_802_3
            /* see if it's got snap baggage */
            if (ET_TYPE_GET(eth) <= 0x0600)
            {
               struct snap_hdr *snap;
               snap = (struct snap_hdr *)(pkt->nb_buff + ETHHDR_SIZE);
               pkt->type = (unshort)(snap->type);
               pkt->nb_prot = pkt->nb_buff + pkt->net->n_lnh;
            }
            else
            {
               pkt->type = htons((unshort)ET_TYPE_GET(eth));
               pkt->nb_prot = pkt->nb_buff + ETHHDR_SIZE;
            }
#else
            pkt->type = htons((unshort)ET_TYPE_GET(eth));
            pkt->nb_prot = pkt->nb_buff + pkt->net->n_lnh;
#endif   /* IEEE_802_3 */
            break;
#if defined(USE_PPP) || defined(USE_SLIP) || defined(PROTOCOL_LIBS)
         case PPP:   /* PPP or SLIP over a UART */
         case SLIP:
            pkt->nb_prot = pkt->nb_buff + MaxLnh;
            pkt->type = IPTP;    /* only type our PPP supports */
            break;
#endif  /* USE_PPP || USE_SLIP */
#ifdef USE_PPPOE
         case PPPOE:
            /* do not change type yet, for PPPoE */
            break;
#endif   /* USE_PPPOE */
         default:    /* driver bug? */
            dprintf("pktdemux: bad Iface type %ld\n",ifc->n_mib->ifType);
            LOCK_NET_RESOURCE(FREEQ_RESID);
            pk_free(pkt);
            UNLOCK_NET_RESOURCE(FREEQ_RESID);
            continue;
         }
      }

      /* pkt->nb_prot and pkt->type are now set. pass pkt to upper layer */
      switch(pkt->type)
      {
      case IPTP:     /* IP type */
         LOCK_NET_RESOURCE(NET_RESID);
#ifdef SHARED_IPADDRS
         add_share_route(pkt);
#endif /* SHARED_IPADDRS */
#ifdef IP_V4
         ip_rcv(pkt);
#else
            /* don't care, it's IPv4 */
            LOCK_NET_RESOURCE(FREEQ_RESID);
            pk_free(pkt);
            UNLOCK_NET_RESOURCE(FREEQ_RESID);
#endif
		UNLOCK_NET_RESOURCE(NET_RESID);
         break;
#ifdef INCLUDE_ARP
      case ARPTP:       /* ARP type */
         LOCK_NET_RESOURCE(NET_RESID);
         arprcv(pkt);
         UNLOCK_NET_RESOURCE(NET_RESID);
         break;
#endif   /* INCLUDE_ARP */
#ifdef USE_PPPOE
      case  htons(0x8863):
      case  htons(0x8864):
         LOCK_NET_RESOURCE(NET_RESID);
         poe_rcv(pkt);
         UNLOCK_NET_RESOURCE(NET_RESID);
         break;
#endif   /* USE_PPPOE */
#ifdef IP_V6
      case  htons(0x86DD):
         /* Each received v6 pkt goes thru here exactly once, so set the
          * outer (first, and usually only) ipv6 header pointer. Tunneled headers
          * may exist further into the packet.
          */
         pkt->ip6_hdr = (struct ipv6 *)pkt->nb_prot;
         LOCK_NET_RESOURCE(NET_RESID);
         ip6_rcv(pkt);
         UNLOCK_NET_RESOURCE(NET_RESID);
         break;
#endif
      default:
#ifdef NPDEBUG
         if (NDEBUG & UPCTRACE)
            dprintf("pktdemux: bad pkt type 0x%04x\n", ntohs(pkt->type));
#endif   /* NPDEBUG */
         ifc->n_mib->ifInUnknownProtos++;
         LOCK_NET_RESOURCE(FREEQ_RESID);
         pk_free(pkt);           /* return to free buffer */
         UNLOCK_NET_RESOURCE(FREEQ_RESID);
         break;
      }
      continue;
   }
}