Esempio n. 1
0
static void igmp_send_report(struct device *dev, unsigned long address, int type)
{
	struct sk_buff *skb=alloc_skb(MAX_IGMP_SIZE, GFP_ATOMIC);
	int tmp;
	struct igmphdr *ih;

	if(skb==NULL)
		return;
	if (type != IGMP_HOST_LEAVE_MESSAGE)
		tmp=ip_build_header(skb, dev->pa_addr, address, &dev, IPPROTO_IGMP, NULL,
			28 , 0, 1, NULL);
	else
		tmp=ip_build_header(skb, dev->pa_addr, IGMP_ALL_ROUTER, &dev, IPPROTO_IGMP, NULL,
			28, 0, 1, NULL);
	if(tmp<0)
	{
		kfree_skb(skb, FREE_WRITE);
		return;
	}
	ih=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr));
	ih->type=type;
	ih->code=0;
	ih->csum=0;
	ih->group=address;
	ih->csum=ip_compute_csum((void *)ih,sizeof(struct igmphdr));	/* Checksum fill */
	ip_queue_xmit(NULL,dev,skb,1);
}
Esempio n. 2
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);
   
}
Esempio n. 3
0
static void igmp_send_report(struct device *dev, unsigned long address, int type)
{
	struct sk_buff *skb=alloc_skb(MAX_IGMP_SIZE, GFP_ATOMIC);
	int tmp;
	struct igmphdr *igh;
	
	if(skb==NULL)
		return;
	tmp=ip_build_header(skb, INADDR_ANY, address, &dev, IPPROTO_IGMP, NULL,
				skb->mem_len, 0, 1);
	if(tmp<0)
	{
		kfree_skb(skb, FREE_WRITE);
		return;
	}
	igh=(struct igmphdr *)(skb->data+tmp);
	skb->len=tmp+sizeof(*igh);
	igh->csum=0;
	igh->unused=0;
	igh->type=type;
	igh->group=address;
	igh->csum=ip_compute_csum((void *)igh,sizeof(*igh));
	ip_queue_xmit(NULL,dev,skb,1);
}
Esempio n. 4
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 */
}