Example #1
0
/*-----------------------------------------------------------------------------*/
void uip_split_output( void )
{
	u16_t	tcplen, len1, len2;

	/* We only try to split maximum sized TCP segments. */
	if( BUF->proto == UIP_PROTO_TCP && uip_len == UIP_BUFSIZE - UIP_LLH_LEN )
	{
		tcplen = uip_len - UIP_TCPIP_HLEN;

		/* Split the segment in two. If the original packet length was
       odd, we make the second packet one byte larger. */
		len1 = len2 = tcplen / 2;
		if( len1 + len2 < tcplen )
		{
			++len2;
		}

		/* Create the first packet. This is done by altering the length
       field of the IP header and updating the checksums. */
		uip_len = len1 + UIP_TCPIP_HLEN;
		#if UIP_CONF_IPV6

		/* For IPv6, the IP length field does not include the IPv6 IP header
       length. */
		BUF->len[0] = ( (uip_len - UIP_IPH_LEN) >> 8 );
		BUF->len[1] = ( (uip_len - UIP_IPH_LEN) & 0xff );
		#else /* UIP_CONF_IPV6 */
		BUF->len[0] = uip_len >> 8;
		BUF->len[1] = uip_len & 0xff;
		#endif /* UIP_CONF_IPV6 */

		/* Recalculate the TCP checksum. */
		BUF->tcpchksum = 0;
		BUF->tcpchksum = ~( uip_tcpchksum() );

		#if !UIP_CONF_IPV6

		/* Recalculate the IP checksum. */
		BUF->ipchksum = 0;
		BUF->ipchksum = ~( uip_ipchksum() );
		#endif /* UIP_CONF_IPV6 */

		/* Transmit the first packet. */

		/*    uip_fw_output();*/

		//    tcpip_output();

		/* Now, create the second packet. To do this, it is not enough to
       just alter the length field, but we must also update the TCP
       sequence number and point the uip_appdata to a new place in
       memory. This place is detemined by the length of the first
       packet (len1). */
		uip_len = len2 + UIP_TCPIP_HLEN;
		#if UIP_CONF_IPV6

		/* For IPv6, the IP length field does not include the IPv6 IP header
       length. */
		BUF->len[0] = ( (uip_len - UIP_IPH_LEN) >> 8 );
		BUF->len[1] = ( (uip_len - UIP_IPH_LEN) & 0xff );
		#else /* UIP_CONF_IPV6 */
		BUF->len[0] = uip_len >> 8;
		BUF->len[1] = uip_len & 0xff;
		#endif /* UIP_CONF_IPV6 */

		/*    uip_appdata += len1;*/
		memcpy( uip_appdata, ( u8_t * ) uip_appdata + len1, len2 );

		uip_add32( BUF->seqno, len1 );
		BUF->seqno[0] = uip_acc32[0];
		BUF->seqno[1] = uip_acc32[1];
		BUF->seqno[2] = uip_acc32[2];
		BUF->seqno[3] = uip_acc32[3];

		/* Recalculate the TCP checksum. */
		BUF->tcpchksum = 0;
		BUF->tcpchksum = ~( uip_tcpchksum() );

		#if !UIP_CONF_IPV6

		/* Recalculate the IP checksum. */
		BUF->ipchksum = 0;
		BUF->ipchksum = ~( uip_ipchksum() );
		#endif /* UIP_CONF_IPV6 */

		/* Transmit the second packet. */

		/*    uip_fw_output();*/

		//    tcpip_output();
	}
Example #2
0
s8_t uip_ipinput(struct uip_pbuf *p,struct uip_netif *inp)
{
	u16_t iphdr_len;
	struct uip_ip_hdr *iphdr;
	struct uip_netif *netif;

	iphdr = p->payload;
	if(UIP_IPH_V(iphdr)!=4) {
		UIP_ERROR("uip_ipinput: ip packet dropped due to bad version number.\n");
		uip_pbuf_free(p);
		return 0;
	}
	
	iphdr_len = UIP_IPH_HL(iphdr);
	iphdr_len *= 4;

	if(iphdr_len>p->len) {
		UIP_ERROR("uip_ipinput: ip packet dropped due to too small packet size.\n");
		uip_pbuf_free(p);
		return 0;
	}
	
	if(uip_ipchksum(iphdr,iphdr_len)!=0) {
	    UIP_STAT(++uip_stat.ip.drop);
	    UIP_STAT(++uip_stat.ip.chkerr);
		UIP_ERROR("uip_ipinput: bad checksum.\n");
		uip_pbuf_free(p);
		return 0;
	}
	
	uip_pbuf_realloc(p,ntohs(UIP_IPH_LEN(iphdr)));
	
	for(netif=uip_netif_list;netif!=NULL;netif=netif->next) {
		if(uip_netif_isup(netif) && !ip_addr_isany(&netif->ip_addr)) {
			if(ip_addr_cmp(&iphdr->dst,&netif->ip_addr) ||
				ip_addr_isbroadcast(&iphdr->dst,netif)) break;
		}
	}

	if(!netif) {
		UIP_ERROR("uip_ipinput: no route found.\n");
		uip_pbuf_free(p);
		return 0;
	}
	
	if((UIP_IPH_OFFSET(iphdr)&htons(UIP_IP_OFFMASK|UIP_IP_MF))!=0) {
#if UIP_IP_REASSEMBLY
		p = uip_ipreass(p);
		if(p==NULL) return UIP_ERR_OK;

		iphdr = (struct uip_ip_hdr*)p->payload;
#else
		uip_pbuf_free(p);
	    UIP_STAT(++uip_stat.ip.drop);
		UIP_ERROR("ip: fragment dropped.\n");
		return 0;
#endif
	}

	switch(UIP_IPH_PROTO(iphdr)) {
		case UIP_PROTO_TCP:
			uip_tcpinput(p,inp);
			break;
		case UIP_PROTO_ICMP:
			uip_icmpinput(p,inp);
			break;
		default:
			UIP_LOG("uip_ipinput: Unsupported protocol.\n");
			if(!ip_addr_isbroadcast(&(iphdr->dst),inp)
				&& !ip_addr_ismulticast(&(iphdr->dst))) {
				p->payload = iphdr;
				uip_icmp_destunreach(p,UIP_ICMP_DUR_PROTO);
			}
			uip_pbuf_free(p);
			break;
	}
	return 0;
}
Example #3
0
static struct uip_pbuf* uip_ipreass(struct uip_pbuf *p)
{
  u16_t offset, len;
  u16_t i;
  struct uip_pbuf *q;
  struct uip_ip_hdr *iphdr,*fraghdr;

  /* If ip_reasstmr is zero, no packet is present in the buffer, so we
     write the IP header of the fragment into the reassembly
     buffer. The timer is updated with the maximum age. */
  iphdr = (struct uip_ip_hdr*)uip_reassbuf;
  fraghdr = (struct uip_ip_hdr*)p->payload;
  if(uip_reasstmr == 0) {
    UIP_MEMCPY(iphdr, fraghdr, UIP_IP_HLEN);
    uip_reasstmr = UIP_REASS_MAXAGE;
    uip_reassflags = 0;
	uip_reasstime = gettime();
    /* Clear the bitmap. */
    UIP_MEMSET(uip_reassbitmap, 0,sizeof(uip_reassbitmap));
  }

  /* Check if the incoming fragment matches the one currently present
     in the reasembly buffer. If so, we proceed with copying the
     fragment into the buffer. */
  if(ip_addr_cmp(&iphdr->src,&fraghdr->src) 
	  && ip_addr_cmp(&iphdr->dst,&fraghdr->dst)
	  && UIP_IPH_ID(iphdr) == UIP_IPH_ID(fraghdr)) {

	len = ntohs(UIP_IPH_LEN(fraghdr)) - UIP_IPH_HL(fraghdr)*4;
	offset = (ntohs(UIP_IPH_OFFSET(fraghdr))&UIP_IP_OFFMASK)*8;

    /* If the offset or the offset + fragment length overflows the
       reassembly buffer, we discard the entire packet. */
    if(offset > UIP_REASS_BUFSIZE ||
       offset + len > UIP_REASS_BUFSIZE) {
      uip_reasstmr = 0;
	  uip_reasstime = 0;
      goto nullreturn;
    }

    /* Copy the fragment into the reassembly buffer, at the right
       offset. */
	i = UIP_IPH_HL(fraghdr)*4;
    uip_copyfrom_pbuf(p,&i,&uip_reassbuf[UIP_IP_HLEN+offset],len);
      
    /* Update the bitmap. */
    if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
      /* If the two endpoints are in the same byte, we only update
	 that byte. */
	     
      uip_reassbitmap[offset / (8 * 8)] |=
	     bitmap_bits[(offset / 8 ) & 7] &
	     ~bitmap_bits[((offset + len) / 8 ) & 7];
    } else {
      /* If the two endpoints are in different bytes, we update the
	 bytes in the endpoints and fill the stuff inbetween with
	 0xff. */
      uip_reassbitmap[offset / (8 * 8)] |=
	bitmap_bits[(offset / 8 ) & 7];
      for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
	uip_reassbitmap[i] = 0xff;
      }      
      uip_reassbitmap[(offset + len) / (8 * 8)] |=
	~bitmap_bits[((offset + len) / 8 ) & 7];
    }
    
    /* If this fragment has the More Fragments flag set to zero, we
       know that this is the last fragment, so we can calculate the
       size of the entire packet. We also set the
       IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
       the final fragment. */

    if((ntohs(UIP_IPH_OFFSET(fraghdr))&UIP_IP_MF)==0) {
      uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
      uip_reasslen = offset + len;
    }
    
    /* Finally, we check if we have a full packet in the buffer. We do
       this by checking if we have the last fragment and if all bits
       in the bitmap are set. */
    if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
      /* Check all bytes up to and including all but the last byte in
	 the bitmap. */
      for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
	if(uip_reassbitmap[i] != 0xff) {
	  goto nullreturn;
	}
      }
      /* Check the last byte in the bitmap. It should contain just the
	 right amount of bits. */
      if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
	 (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
	goto nullreturn;
      }

	  uip_reasslen += UIP_IP_HLEN;

      /* Pretend to be a "normal" (i.e., not fragmented) IP packet
	 from now on. */
	  UIP_IPH_LEN_SET(iphdr,htons(uip_reasslen));
	  UIP_IPH_OFFSET_SET(iphdr,0);
	  UIP_IPH_CHKSUM_SET(iphdr,0);
	  UIP_IPH_CHKSUM_SET(iphdr,uip_ipchksum(iphdr,UIP_IP_HLEN));
	
      /* If we have come this far, we have a full packet in the
	 buffer, so we allocate a pbuf and copy the packet into it. We
	 also reset the timer. */
      uip_reasstmr = 0;
	  uip_reasstime = 0;
	  uip_pbuf_free(p);
	  p = uip_pbuf_alloc(UIP_PBUF_LINK,uip_reasslen,UIP_PBUF_POOL);
	  if(p==NULL) return NULL;
	  
	  i = 0;
	  for(q=p;q!=NULL;q=q->next) {
		  UIP_MEMCPY(q->payload,&uip_reassbuf[i],((q->len>(uip_reasslen-i))?(uip_reasslen-i):q->len));
		  i += q->len;
	  }
      return p;
    }
  }

 nullreturn:
  uip_pbuf_free(p);
  return NULL;
}
Example #4
0
void uip_udpsend(struct uip_driver_s *dev, struct uip_udp_conn *conn)
{
  struct uip_udpip_hdr *pudpbuf = UDPBUF;

  if (dev->d_sndlen > 0)
    {
      /* The total lenth to send is the size of the application data plus
       * the IP and UDP headers (and, eventually, the ethernet header)
       */

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

      /* Initialize the IP header.  Note that for IPv6, the IP length field
       * does not include the IPv6 IP header length.
       */

#ifdef CONFIG_NET_IPv6

      pudpbuf->vtc         = 0x60;
      pudpbuf->tcf         = 0x00;
      pudpbuf->flow        = 0x00;
      pudpbuf->len[0]      = (dev->d_sndlen >> 8);
      pudpbuf->len[1]      = (dev->d_sndlen & 0xff);
      pudpbuf->nexthdr     = UIP_PROTO_UDP;
      pudpbuf->hoplimit    = conn->ttl;

      uip_ipaddr_copy(pudpbuf->srcipaddr, &dev->d_ipaddr);
      uip_ipaddr_copy(pudpbuf->destipaddr, &conn->ripaddr);

#else /* CONFIG_NET_IPv6 */

      pudpbuf->vhl         = 0x45;
      pudpbuf->tos         = 0;
      pudpbuf->len[0]      = (dev->d_len >> 8);
      pudpbuf->len[1]      = (dev->d_len & 0xff);
      ++g_ipid;
      pudpbuf->ipid[0]     = g_ipid >> 8;
      pudpbuf->ipid[1]     = g_ipid & 0xff;
      pudpbuf->ipoffset[0] = 0;
      pudpbuf->ipoffset[1] = 0;
      pudpbuf->ttl         = conn->ttl;
      pudpbuf->proto       = UIP_PROTO_UDP;

      uiphdr_ipaddr_copy(pudpbuf->srcipaddr, &dev->d_ipaddr);
      uiphdr_ipaddr_copy(pudpbuf->destipaddr, &conn->ripaddr);

      /* Calculate IP checksum. */

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

#endif /* CONFIG_NET_IPv6 */

      /* Initialize the UDP header */

      pudpbuf->srcport     = conn->lport;
      pudpbuf->destport    = conn->rport;
      pudpbuf->udplen      = HTONS(dev->d_sndlen + UIP_UDPH_LEN);

#ifdef CONFIG_NET_UDP_CHECKSUMS
      /* Calculate UDP checksum. */

      pudpbuf->udpchksum   = 0;
      pudpbuf->udpchksum   = ~(uip_udpchksum(dev));
      if (pudpbuf->udpchksum == 0)
        {
          pudpbuf->udpchksum = 0xffff;
        }
#else
      pudpbuf->udpchksum   = 0;
#endif

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

#ifdef CONFIG_NET_STATISTICS
      uip_stat.udp.sent++;
      uip_stat.ip.sent++;
#endif
    }