Libipq behaveing abormally!

Manzoor hpmanzoor at rediffmail.com
Fri Dec 10 11:13:00 CET 2004


  
Hi,
I am a newbee in this field.I am trying to devise a bandwidth manager in my LAN. I am having three PCs one PC I have made a gateway. Other two are connected to it using two interface cards. My program works very well sometimes and I am able to download big files like 150MB, 200MB at the allocated bandwidth. But when I tried to ping using 10 to 12 terminals taking 1000 bytes packets then suddenly after sometime the program terminates giving error message "recieved message truncated". If I restart the program then it again terminates after sometime. What may be the problem? Is it related to less memory or what? I am using RedHat Linux 9, kernel version 2.4.xx. The algorithm I have used is Token Bucket Algorithm and I am dropping packets when there is no token in the bucket. I have used some linked list structure and file operations in the code that are used in implementing token bucket and to store the IP address and the bandwidth allocated against each IP. I am giving the sample code below:

//------------------------------------------------------------------


static void die(struct ipq_handle *h)
{
   ipq_perror("bwmanager ");
   ipq_destroy_handle(h);
   exit(1);
}


int main(int argc, char * argv[])
{
 int status;
initialize();

 signal(SIGALRM, sigalarm_handler);
 alarm(1);

 h = ipq_create_handle(0, PF_INET);
 if (!h)
    die(h);
                                                                                                                             
 status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE);
 if (status < 0)
          die(h);                                                                                                                     
 do{
        status = ipq_read(h, buf, BUFSIZE, 0);
        if (status < 0)
                   die(h);
                                                                                                                             
        switch (ipq_message_type(buf))
            {
              case NLMSG_ERROR:
                               fprintf(stderr, "Received error message %d\n", ipq_get_msgerr(buf));
                               break;
                                                                                                                             
              case IPQM_PACKET: {
                                         if(!test())
                                         {
                                                status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL);
                                                if (status < 0)
                                                 die(h);
                                          }
                                  break;
                                 }
                                                                                                                             
              default:
                                  fprintf(stderr, "Unknown message type!\n");
                                  break;
            }
   } while (1);
                                                                                                                             
   ipq_destroy_handle(h);
                   return 0;

 }

}







void initialize()
{
 FILE *fp_block, *fp_bwmanager;
 char ip_addr[16];
 struct ip_record rec;
 struct bw_node * bw_temp;
                                                                                                                             
 
 fp_bwmanager = fopen("/etc/bwmanager.conf","rb");
 if(fp_bwmanager == NULL)
        printf("\nCan not open the bwmanager.conf file\n");
 else
  {
    while(fread(&rec, sizeof(rec), 1, fp_bwmanager) == 1)
                     bwlist_insert(&bwlist_start, rec);
  }
 fclose(fp_bwmanager);                                                                                                                             
                                                                                                                             
 fp_block = fopen("/etc/ip_block.conf","rb");
 if(fp_block == NULL)
        printf("\nCan not open the ip_block.conf file\n");
 else
  {
        while(fread(ip_addr, sizeof(ip_addr), 1, fp_block) == 1)
                blocklist_insert(&blocklist_start, ip_addr);
  }
 fclose(fp_block);


 bw_temp = bwlist_start;
 while(bw_temp != NULL)
 {
	tokenlist_insert(&tokenlist_start, bw_temp->ip_rec.IP, bw_temp->ip_rec.upload, bw_temp->ip_rec.download);
	bw_temp = bw_temp->next;
 }

 system("modprobe iptable_filter");
 system("modprobe ip_queue");
 system("iptables -F");
 system("iptables -A INPUT -j QUEUE");
 system("iptables -A FORWARD -j QUEUE");
 system("iptables -A OUTPUT -j QUEUE");
}


//This function updates the token bucket after 1 sec
void sigalarm_handler()
{
 struct token_node * temp=tokenlist_start;

 while(temp != NULL)
 {
	if(temp->current_upload_token + temp->upload_token_rate <= temp->upload_bucket_size)
					temp->current_upload_token+=temp->upload_token_rate;
	else
		temp->current_upload_token = temp->upload_bucket_size;


        if(temp->current_download_token + temp->download_token_rate <= temp->download_bucket_size)
			                temp->current_download_token+=temp->download_token_rate;
        else
                temp->current_download_token = temp->download_bucket_size;


	temp = temp->next;
 }
 alarm(1);
}





int test()
{
 int status;
 struct token_node *token_temp = tokenlist_start;
 struct block_node *block_temp = blocklist_start;
 m = ipq_get_packet(buf);
 iph = (struct iphdr *)m->payload;
 add.s_addr = iph->saddr;

 while(block_temp != NULL)
 {
	if(iph->saddr == inet_addr(block_temp->IP) || iph->daddr == inet_addr(block_temp->IP) )
           {
		status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL);
		if(status < 0)
        	 	die(h);
		return 1;
	   }

	block_temp = block_temp->next;
 }

 while(token_temp != NULL)
 {
	if(iph->saddr == inet_addr(token_temp->IP))
	{
	     if(m->data_len <= token_temp->current_upload_token)
		{
			token_temp->current_upload_token-=m->data_len;
			status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL);
        		if (status < 0)
                		die(h);
        		return 1;
		}
	      else
		{
                        status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL);
                        if (status < 0)
                                die(h);
                        return 1;
		}
	}


	if(iph->daddr == inet_addr(token_temp->IP))
	{
             if(m->data_len <= token_temp->current_download_token)
                {
                        token_temp->current_download_token-=m->data_len;
                        status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL);
                        if (status < 0)
                                die(h);
                        return 1;
                }
              else
                {
                        status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL);
                        if (status < 0)
                                die(h);
                        return 1;
                }
        }


 	token_temp = token_temp->next;
 }
 return 0;
                                                                                                 
}


With regards

..Manzoor


More information about the netfilter-devel mailing list