Ejemplo n.º 1
0
int
arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
{
   struct arp *arp;
   struct arp_table *tbl;
   int ret;

   PRINTK ("<<\n");
   arp = skb->h.arp;
   print_arp(arp);

  /* if this test doesn't pass, something fishy is going on. */
  if (arp->hlen != dev->addr_len || dev->type !=NET16( arp->hrd))
    {
       free_skb(skb, FREE_READ);
       return (0);
    }

  /* for now we will only deal with ip addresses. */
  if (arp->pro != NET16(ARP_IP_PROT) || arp->plen != 4)
    {
       free_skb (skb, FREE_READ);
       return (0);
    }

  /* now look up the ip address in the table. */
  tbl = arp_lookup (*arp_sourcep(arp));
  if (tbl != NULL)
    {
       memcpy (tbl->hard, arp+1, arp->hlen);
       tbl->hlen = arp->hlen;
       tbl->last_used = timer_seq;
    }

  if (!my_ip_addr(*arp_targetp(arp)))
    {
       free_skb (skb, FREE_READ);
       return (0);
    }

  if (tbl == NULL)
    create_arp (*arp_sourcep(arp), arp_sourceh(arp), arp->hlen);

   /* now see if we can send anything. */
   send_arp_q();
     
  if (arp->op != NET16(ARP_REQUEST))
    {
       free_skb (skb, FREE_READ);
       return (0);
    }

  /* now we need to create a new packet. */
   ret = arp_response(arp, dev);
   free_skb (skb, FREE_READ);
   return (ret);
}
Ejemplo n.º 2
0
/* this should be the easiest of all, all we do is copy it into
   a buffer. */
int
packet_rcv (struct sk_buff *skb, struct device *dev,  struct packet_type *pt)
{
   volatile struct sock *sk;

   sk = pt->data;
   skb->dev = dev;
   skb->len += dev->hard_header_len;

   /* now see if we are in use. */
   cli();
   if (sk->inuse)
     {
	sti();
	/* drop any packets if we can't currently deal with them.
	   Assume that the other end will retransmit if it was
	   important. */
	skb->sk = NULL;
	free_skb (skb, FREE_READ);
	return (0);

     }
   sk->inuse = 1;
   sti ();

   skb->sk = sk;

   /* charge it too the socket. */
   if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX)
     {
	skb->sk = NULL;
	free_skb (skb, FREE_READ);
	return (0);
     }
	     
   sk->rmem_alloc += skb->mem_len;

   /* now just put it onto the queue. */
   if (sk->rqueue == NULL)
     {
	sk->rqueue = skb;
	skb->next = skb;
	skb->prev = skb;
     }
   else
     {
	skb->next = sk->rqueue;
	skb->prev = sk->rqueue->prev;
	skb->prev->next = skb;
	skb->next->prev = skb;
     }
   wake_up (sk->sleep);
   release_sock (sk);
   return (0);
}
Ejemplo n.º 3
0
void RecvRoutine()
{
	//char recv[1532];
	int i,len;
	
	/*len=ReceivePacket(recv);
	printf("\n\r-===Recieve packet size:%d===-\n\r",len);
 	for (i=0;i<len;i++)
 	{
		printf(" %2x", recv[i]);
		if ((i>1)&&((i%16)==0)) printf("\n\r");  	
	}*///uncomment test code to see more detail about our packet
	struct sk_buff *skb;
	struct ethhdr *eth_hdr;		
	
	
	
	
	skb = alloc_skb(ETH_FRAME_LEN);
	len=ReceivePacket((char *)skb->data);
	skb->len=len;
	if (startTFTP==true)
	{
		eth_hdr = (struct ethhdr *)(skb->data);					
		skb_pull(skb, ETH_HLEN);
		if (ntohs(eth_hdr->h_proto) == ETH_P_ARP)
			arp_rcv_packet(skb);
		else if(ntohs(eth_hdr->h_proto) == ETH_P_IP)						
		 	ip_rcv_packet(skb);	
	}else free_skb(skb);
}
Ejemplo n.º 4
0
static int console_hup(int s, int ifindex)
{
	int rc;
	uint8_t *p;
	struct sk_buff *skb = alloc_skb(64);

	p = skb_put(skb, 0);
	*p++ = EGETTY_HUP;
	*p++ = conf.console;
	p = skb_put(skb, 2);
	
	rc = console_send(s, ifindex, skb);
	if(rc == -1) {
		printf("sendto failed: %s\n", strerror(errno));
		free_skb(skb);
		return -1;
	}
	free_skb(skb);
	return 0;
}
Ejemplo n.º 5
0
void
unlock_skb (struct sk_buff *skb, int rw)
{
   if (skb->lock != 1)
     {
	printk ("*** bug unlocking non-locked sk_buff. \n");
     }
   skb->lock = 0;
   if (skb->free)
     free_skb (skb, rw);
}
Ejemplo n.º 6
0
/* this will do terrible things if len + ipheader + devheader > dev->mtu */
static int
packet_sendto (volatile struct sock *sk, unsigned char *from, int len,
	       int noblock,
	       unsigned flags, struct sockaddr_in *usin, int addr_len)
{
   struct sk_buff *skb;
   struct device *dev;
   struct sockaddr saddr;

   /* check the flags. */
   if (flags) return (-EINVAL);
   if (len < 0) return (-EINVAL);

   /* get and verify the address. */
   if (usin)
     {
	if (addr_len < sizeof (saddr))
	  return (-EINVAL);
	verify_area (usin, sizeof (saddr));
	memcpy_fromfs (&saddr, usin, sizeof(saddr));
     }
   else
     return (-EINVAL);

   skb = sk->prot->wmalloc (sk, len+sizeof (*skb) + sk->prot->max_header, 0);
   /* this shouldn't happen, but it could. */
   if (skb == NULL)
     {
	PRINTK ("packet_sendto: write buffer full?\n");
	print_sk (sk);
	return (-EAGAIN);
     }
   skb->mem_addr = skb;
   skb->mem_len = len + sizeof (*skb) +sk->prot->max_header;
   skb->sk = sk;
   skb->free = 1;
   saddr.sa_data[13] = 0;
   dev = get_dev (saddr.sa_data);
   if (dev == NULL)
     {
	sk->prot->wfree (sk, skb->mem_addr, skb->mem_len);
	return (-ENXIO);
     }
   verify_area (from, len);
   memcpy_fromfs (skb+1, from, len);
   skb->len = len;
   skb->next = NULL;
   if (dev->up)
     dev->queue_xmit (skb, dev, sk->priority);
   else
     free_skb (skb, FREE_WRITE);
   return (len);
}
Ejemplo n.º 7
0
/* sends an icmp message in response to a packet. */
void
icmp_reply (struct sk_buff *skb_in,  int type, int code, struct device *dev)
{
   struct sk_buff *skb;
   struct ip_header *iph;
   int offset;
   struct icmp_header *icmph;

   int len;
   /* get some memory for the replay. */
   len = sizeof (*skb) + 8 /* amount of header to return. */ +
         sizeof (struct icmp_header) +
	 64 /* enough for an ip header. */ +
	 dev->hard_header_len;
	   
   skb = malloc (len);
   if (skb == NULL) return;

   skb->mem_addr = skb;
   skb->mem_len = len;

   len -= sizeof (*skb);

   /* find the ip header. */
   iph = (struct ip_header *)(skb_in+1);
   iph = (struct ip_header *)((unsigned char *)iph + dev->hard_header_len);

   /* Build Layer 2-3 headers for message back to source */
   offset = ip_build_header( skb, iph->daddr, iph->saddr,
			    &dev, IP_ICMP, NULL, len );

   if (offset < 0)
     {
	skb->sk = NULL;
	free_skb (skb, FREE_READ);
	return;
     }

   /* Readjust length according to actual IP header size */
   skb->len = offset + sizeof (struct icmp_header) + 8;
   
   icmph = (struct icmp_header *)((unsigned char *)(skb+1) + offset);
   icmph->type = type;
   icmph->code = code;
   icmph->checksum = 0; /* we don't need to compute this. */
   icmph->un.gateway = 0; /* might as well 0 it. */
   memcpy (icmph+1, iph+1, 8);
   /* send it and free it. */
   ip_queue_xmit (NULL, dev, skb, 1);
   
}
Ejemplo n.º 8
0
void icmpv4_incoming(struct sk_buff *skb) 
{
    struct iphdr *iphdr = ip_hdr(skb);
    struct icmp_v4 *icmp = (struct icmp_v4 *) iphdr->data;

    //TODO: Check csum

    switch (icmp->type) {
    case ICMP_V4_ECHO:
        icmpv4_reply(skb);
        return;
    case ICMP_V4_DST_UNREACHABLE:
        print_err("ICMPv4 received 'dst unreachable' code %d, "
                  "check your routes and firewall rules\n", icmp->code);
        goto drop_pkt;
    default:
        print_err("ICMPv4 did not match supported types\n");
        goto drop_pkt;
    }

drop_pkt:
    free_skb(skb);
    return;
}
Ejemplo n.º 9
0
void icmpv4_reply(struct sk_buff *skb)
{
    struct iphdr *iphdr = ip_hdr(skb);
    struct icmp_v4 *icmp;
    struct sock sk;
    memset(&sk, 0, sizeof(struct sock));
    
    uint16_t icmp_len = iphdr->len - (iphdr->ihl * 4);

    skb_reserve(skb, ETH_HDR_LEN + IP_HDR_LEN + icmp_len);
    skb_push(skb, icmp_len);
    
    icmp = (struct icmp_v4 *)skb->data;
        
    icmp->type = ICMP_V4_REPLY;
    icmp->csum = 0;
    icmp->csum = checksum(icmp, icmp_len, 0);

    skb->protocol = ICMPV4;
    sk.daddr = iphdr->saddr;

    ip_output(&sk, skb);
    free_skb(skb);
}
Ejemplo n.º 10
0
int
icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
	unsigned long daddr, unsigned short len,
	unsigned long saddr, int redo, struct ip_protocol *protocol )
{
   int size, offset;
   struct icmp_header *icmph, *icmphr;
   struct sk_buff *skb;
   unsigned char *buff;


   /* drop broadcast packets.  */
   if ((daddr & 0xff000000) == 0 || (daddr & 0xff000000) == 0xff000000)
     {
	skb1->sk = NULL;
	free_skb (skb1, FREE_READ);
	return (0);
     }

   buff = skb1->h.raw;

   icmph = (struct icmp_header *)buff;

   /* Validate the packet first */
   if( icmph->checksum )
     { /* Checksums Enabled? */
	if( ip_compute_csum( (unsigned char *)icmph, len ) )
	  {
	     /* Failed checksum! */
	     PRINTK("\nICMP ECHO failed checksum!");
	     skb1->sk = NULL;
	     free_skb (skb1, FREE_READ);
	     return (0);
	  }
     }

   print_icmph(icmph);

   /* Parse the ICMP message */
   switch( icmph->type )
     {
       case ICMP_DEST_UNREACH:
       case ICMP_SOURCE_QUENCH:
	{
	   struct ip_header *iph;
	   struct ip_protocol *ipprot;
	   unsigned char hash;
	   int err;

	   err = icmph->type << 8 | icmph->code;

	   /* we need to cause the socket to be closed and the error message
	      to be set appropriately. */
	   iph = (struct ip_header *)(icmph+1);

	   /* get the protocol(s) */
	   hash = iph->protocol & (MAX_IP_PROTOS -1 );
	   for (ipprot = ip_protos[hash]; ipprot != NULL; ipprot=ipprot->next)
	     {
		/* pass it off to everyone who wants it. */
		ipprot->err_handler (err, (unsigned char *)iph+4*iph->ihl,
				     iph->daddr, iph->saddr, ipprot);
	     }
	   skb1->sk = NULL;
	   free_skb (skb1, FREE_READ);
	   return (0);
	}

       case ICMP_REDIRECT:
	{
	   /* we need to put a new route in the routing table. */
	   struct rtable *rt; /* we will add a new route. */
	   struct ip_header *iph;

	   iph = (struct ip_header *)(icmph+1);
	   rt = malloc (sizeof (*rt));
	   if (rt != NULL)
	     {
		rt->net = iph->daddr;
		/* assume class C network.  Technically this is incorrect,
		   but will give it a try. */
		if ((icmph->code & 1) == 0) rt->net &= 0x00ffffff;
		rt->dev = dev;
		rt->router = icmph->un.gateway;
		add_route (rt);
	     }
	   skb1->sk = NULL;
	   free_skb (skb1, FREE_READ);
	   return (0);
	}

       case ICMP_ECHO: 
	
	/* Allocate an sk_buff response buffer (assume 64 byte IP header) */

	size = sizeof( struct sk_buff ) + dev->hard_header_len + 64 + len;
	skb = malloc( size );
	if (skb == NULL)
	  {
	     skb1->sk = NULL;
	     free_skb (skb1, FREE_READ);
	     return (0);
	  }
	skb->sk = NULL;
	skb->mem_addr = skb;
	skb->mem_len = size;

	/* Build Layer 2-3 headers for message back to source */
	offset = ip_build_header( skb, daddr, saddr, &dev, IP_ICMP, opt, len );
	if (offset < 0)
	  {
	     /* Problems building header */
	     PRINTK("\nCould not build IP Header for ICMP ECHO Response");
	     free_s (skb->mem_addr, skb->mem_len);
	     skb1->sk = NULL;
	     free_skb (skb1, FREE_READ);
	     return( 0 ); /* just toss the received packet */
	  }

	/* Readjust length according to actual IP header size */
	skb->len = offset + len;

	/* Build ICMP_ECHO Response message */
	icmphr = (struct icmp_header *)( (char *)( skb + 1 ) + offset );
	memcpy( (char *)icmphr, (char *)icmph, len );
	icmphr->type = ICMP_ECHOREPLY;
	icmphr->code = 0;
	icmphr->checksum = 0;

	if( icmph->checksum )
	  { /* Calculate Checksum */
	     icmphr->checksum = ip_compute_csum( (void *)icmphr, len );
	  }

	/* Ship it out - free it when done */
	ip_queue_xmit( (volatile struct sock *)NULL, dev, skb, 1 );
	
	skb1->sk = NULL;
	free_skb (skb1, FREE_READ);
	return( 0 );

	default:
	PRINTK("\nUnsupported ICMP type = x%x", icmph->type );
	skb1->sk = NULL;
	free_skb (skb1, FREE_READ);
	return( 0 ); /* just toss the packet */
     }

   /* should be unecessary, but just in case. */
   skb1->sk = NULL;
   free_skb (skb1, FREE_READ);
   return( 0 ); /* just toss the packet */
}
Ejemplo n.º 11
0
int
packet_recvfrom (volatile struct sock *sk, unsigned char *to, int len,
	      int noblock,
	      unsigned flags, struct sockaddr_in *sin, int *addr_len)
{
	/* this should be easy, if there is something there we
	   return it, otherwise we block. */
	int copied=0;
	struct sk_buff *skb;
	struct sockaddr *saddr;
	saddr = (struct sockaddr *)sin;

	if (len == 0) return (0);
	if (len < 0) return (-EINVAL);
	if (addr_len)
	  {
		  verify_area (addr_len, sizeof(*addr_len));
		  put_fs_long (sizeof (*saddr), addr_len);
	  }

	sk->inuse = 1;
	while (sk->rqueue == NULL)
	  {
	     if (noblock)
	       {
		  release_sock (sk);
		  return (-EAGAIN);
	       }
	     release_sock (sk);
	     cli();
	     if (sk->rqueue == NULL)
	       {
		  interruptible_sleep_on (sk->sleep);
		  if (current->signal & ~current->blocked)
		    {
		       return (-ERESTARTSYS);
		    }
	       }
	     sti();
	  }
	skb = sk->rqueue;

	if (!(flags & MSG_PEEK))
	  {
		  if (skb->next == skb )
		    {
			    sk->rqueue = NULL;
		    }
		  else
		    {
			    sk->rqueue = sk->rqueue ->next;
			    skb->prev->next = skb->next;
			    skb->next->prev = skb->prev;
		    }
	  }
	copied = min (len, skb->len);
	verify_area (to, copied);
	memcpy_tofs (to, skb+1,  copied);
	/* copy the address. */
	if (saddr)
	  {
		  struct sockaddr addr;
		  addr.sa_family = skb->dev->type;
		  memcpy (addr.sa_data,skb->dev->name, 14);
		  verify_area (saddr, sizeof (*saddr));
		  memcpy_tofs(saddr, &addr, sizeof (*saddr));
	  }

	if (!(flags & MSG_PEEK))
	  {
	     free_skb (skb, FREE_READ);
	  }

	release_sock (sk);
	return (copied);

}
Ejemplo n.º 12
0
void
destroy_sock(volatile struct sock *sk)
{

  struct sk_buff *skb;
  PRINTK ("destroying socket %X\n",sk);
  /* just to be safe. */
  sk->inuse = 1;

  remove_sock (sk);
  /* now we can no longer get new packets. */

  delete_timer((struct timer *)&sk->time_wait);

  /* cleanup up the write buffer. */
  for (skb = sk->wfront; skb != NULL; )
    {
      struct sk_buff *skb2;
      skb2=skb->next;
      free_skb(skb, FREE_WRITE);
      skb=skb2;
    }

  sk->wfront = NULL;

  if (sk->rqueue != NULL)
    {
       skb = sk->rqueue;
       do {
	  struct sk_buff *skb2;
	  skb2=skb->next;
	  /* this will take care of closing sockets that were
	     listening and didn't accept everything. */

	  if (skb->sk != NULL && skb->sk != sk)
	    {
	       skb->sk->dead = 1;
	       skb->sk->prot->close (skb->sk, 0);
	    }
	  free_skb(skb, FREE_READ);
	  skb=skb2;
       } while (skb != sk->rqueue);
    }

  sk->rqueue = NULL;

  /* now we need to clean up the send head. */
  for (skb = sk->send_head; skb != NULL; )
    {
      struct sk_buff *skb2;
      /* we need to remove skb from the transmit queue. */
      cli();
      /* see if it's in a transmit queue. */
      if (skb->next != NULL)
	{
	   if (skb->next != skb)
	     {
		skb->next->prev = skb->prev;
		skb->prev->next = skb->next;
	     }
	   else
	     {
		int i;
		for (i = 0; i < DEV_NUMBUFFS; i++)
		  {
		     if (skb->dev && skb->dev->buffs[i] == skb)
		       {
			  skb->dev->buffs[i]= NULL;
			  break;
		       }
		  }
	     }
	}
      sti();
      skb2=skb->link3;
      free_skb(skb, FREE_WRITE);
      skb=skb2;
    }

  sk->send_head = NULL;

  /* and now the backlog. */

  if (sk->back_log != NULL)
    {
       /* this should never happen. */
       printk ("cleaning back_log. \n");
       cli();
       skb = sk->back_log;
       do {
	  struct sk_buff *skb2;
	  skb2=skb->next;
	  free_skb(skb, FREE_READ);
	  skb=skb2;
       } while (skb != sk->back_log);
       sti();
    }

  sk->back_log = NULL;

  /* now if everything is gone we can free the socket structure, 
     otherwise we need to keep it around until everything is gone. */
  if (sk->rmem_alloc == 0 && sk->wmem_alloc == 0)
    {
       free_s ((void *)sk,sizeof (*sk));
    }
  else
    {
       /* this should never happen. */
       /* actually it can if an ack has just been sent. */
       PRINTK ("possible memory leak in socket = %X\n", sk);
       print_sk (sk);
       sk->destroy = 1;
       sk->ack_backlog = 0;
       sk->inuse = 0;
       sk->time_wait.len = SOCK_DESTROY_TIME;
       sk->timeout = TIME_DESTROY;
       reset_timer ((struct timer *)&sk->time_wait);
    }
  
}