summaryrefslogtreecommitdiff
path: root/drivers/net/bih/pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bih/pool.c')
-rw-r--r--drivers/net/bih/pool.c283
1 files changed, 283 insertions, 0 deletions
diff --git a/drivers/net/bih/pool.c b/drivers/net/bih/pool.c
new file mode 100644
index 00000000..e5cc2f49
--- /dev/null
+++ b/drivers/net/bih/pool.c
@@ -0,0 +1,283 @@
+/*
+ * Bump in the Host (BIH)
+ * http://code.google.com/p/bump-in-the-host/source/
+ * ----------------------------------------------------------
+ *
+ * Copyrighted (C) 2010,2011 by the China Mobile Communications
+ * Corporation <bih.cmcc@gmail.com>;
+ * See the COPYRIGHT file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+#include "voslist.h"
+#include "map.h"
+#define NIPQUAD(addr) \
+ ((unsigned char *)&addr)[0], \
+ ((unsigned char *)&addr)[1], \
+ ((unsigned char *)&addr)[2], \
+ ((unsigned char *)&addr)[3]
+struct pool_node
+{
+ struct listnode *addr;
+ struct listnode *currnode;
+ unsigned int curraddr;
+}ADDRPOOL;
+
+int pool_addr_add(unsigned int first,unsigned int last);
+int pool_addr_add2(char *string);
+int pool_addr_del(unsigned int first,unsigned int last);
+int pool_addr_del2(char *string);
+char *pool_addr_show(void);
+unsigned int pool_addr_assign(struct in6_addr *in6addr);
+
+/*
+ Insert an address block(from 'first' to 'last') into the address pool.
+*/
+int pool_addr_add(unsigned int first,unsigned int last)
+{
+ struct pool_node *node=&ADDRPOOL;
+ struct listnode *listnode;
+
+ if(ntohl(first)>ntohl(last))
+ {
+ lprintf(0,"argument error\n");
+ return(-1);
+ }
+ listnode=listnode_find(node->addr,first);
+ if(listnode)
+ {
+ listnode->data=(void *)last;
+ return(0);
+ }
+ listnode=listnode_add(&(node->addr),first,(void *)last,0);
+ if(listnode==NULL)
+ {
+ lprintf(0,"listnode_add error \n");
+ return(-1);
+ }
+ return(0);
+}
+
+/*
+ Insert an address block into the address pool, not numbers but characters.
+*/
+int pool_addr_add2(char *string)
+{
+ unsigned int first,last;
+ char *pstr,*firststr,*laststr;
+ int ret,slen,num=0,pstrlen,firststrlen,laststrlen;
+
+ if(string==NULL)
+ {
+ lprintf(0,"arguments error\n");
+ return(-1);
+ }
+ slen=strlen(string);
+ if(string[slen-1]=='\n')
+ {
+ slen--;
+ string[slen]=0;
+ }
+ if(string[slen-1]=='\r')
+ {
+ slen--;
+ string[slen]=0;
+ }
+ ret=0;
+ while(msg_field2(string,slen,num++,&pstr,&pstrlen,',')==0)
+ {
+ if(msg_field2(pstr,pstrlen,0,&firststr,&firststrlen,'-')==0&&
+ msg_field2(pstr,pstrlen,1,&laststr,&laststrlen,'-')==0)
+ {
+ first=sk_inet_addr(buff2String(firststr,firststrlen));
+ last=sk_inet_addr(buff2String(laststr,laststrlen));
+ ret=pool_addr_add(first,last);
+ if(ret!=0)
+ lprintf(0,"\"%.*s\" error\n",pstrlen,pstr);
+ }
+ else
+ lprintf(0,"addr(%.*s) error\n",pstrlen,pstr);
+ }
+ return(0);
+}
+
+/*
+ Delete the address block from 'first' to 'last'.
+*/
+int pool_addr_del(unsigned int first,unsigned int last)
+{
+ struct pool_node *node=&ADDRPOOL;
+ struct listnode *listnode;
+
+ if(ntohl(first)>ntohl(last))
+ {
+ lprintf(0,"argument error\n");
+ return(-1);
+ }
+ listnode=listnode_find(node->addr,first);
+ if(listnode&&listnode->data==(void *)last)
+ {
+ listnode_del(&(node->addr),first,NULL);
+ return(0);
+ }
+ lprintf(0,"\"%u.%u.%u.%u-%u.%u.%u.%u\" is not exist\n",NIPQUAD(first),NIPQUAD(last));
+ return(-1);
+}
+
+/*
+ Delete the address block.
+*/
+int pool_addr_del2(char *string)
+{
+ unsigned int first,last;
+ char *pstr,*firststr,*laststr;
+ int ret,slen,num=0,pstrlen,firststrlen,laststrlen;
+
+ if(string==NULL)
+ {
+ lprintf(0,"arguments error\n");
+ return(-1);
+ }
+ slen=strlen(string);
+ if(string[slen-1]=='\n')
+ {
+ slen--;
+ string[slen]=0;
+ }
+ if(string[slen-1]=='\r')
+ {
+ slen--;
+ string[slen]=0;
+ }
+ ret=0;
+ while(msg_field2(string,slen,num++,&pstr,&pstrlen,',')==0)
+ {
+ if(msg_field2(pstr,pstrlen,0,&firststr,&firststrlen,'-')==0&&
+ msg_field2(pstr,pstrlen,1,&laststr,&laststrlen,'-')==0)
+ {
+ first=sk_inet_addr(buff2String(firststr,firststrlen));
+ last=sk_inet_addr(buff2String(laststr,laststrlen));
+ ret=pool_addr_del(first,last);
+ if(ret!=0)
+ lprintf(0,"\"%.*s\" error\n",pstrlen,pstr);
+ }
+ else
+ lprintf(0,"addr(%.*s) error\n",pstrlen,pstr);
+ }
+ return(0);
+}
+
+/*
+ Print the information of the address block.
+*/
+char *pool_addr_show(void)
+{
+ struct listnode *node,*head=ADDRPOOL.addr;
+ unsigned int first,last;
+ SHOW2BUF_DEF;
+ SHOW2BUF_INIT();
+ node=head;
+ while(node)
+ {
+ first=node->key;
+ last=(unsigned int)(node->data);
+ if(node!=head)
+ SHOW2BUF(",");
+ SHOW2BUF("%u.%u.%u.%u-%u.%u.%u.%u %u.%u.%u.%u",NIPQUAD(first),NIPQUAD(last),NIPQUAD(ADDRPOOL.curraddr));
+ node=node->next;
+ }
+ SHOW2BUF_RET;
+}
+
+/*
+ If there is a new IPv6 address arrival:
+ 1. If this IPv6 address already exists in the mapping relationship, return the IPv4 address;
+ 2. Otherwise, check the address block to find a free IPv4 address to make a mapping relationship with this IPv6 address;
+ 3. If there is no free IPv4 address, then check the next address block, and repeat step 2;
+ 4. If there is no free IPv4 address in all the address blocks, start from the first block and repeate step 2;
+ 5. If there is no free IPv4 address in the address pool, print the error message 'There is on free ip address'.
+*/
+unsigned int pool_addr_assign(struct in6_addr *in6addr)
+{
+ struct pool_node *node=&ADDRPOOL;
+ struct listnode *list_node;
+ unsigned int addr,first_addr,last_addr;
+ struct map_node *mapnode;
+
+ if((node==NULL)||(node->addr==NULL))
+ {
+ lprintf(0,"argument error\n");
+ return(0);
+ }
+ if(node->currnode==NULL)
+ node->currnode=node->addr;
+ list_node=node->currnode;
+ if(in6addr)
+ {
+ mapnode=map_find(*in6addr);
+ if(mapnode)
+ return(mapnode->id);
+ }
+ do
+ {
+ first_addr=list_node->key;
+ last_addr=(unsigned int)(list_node->data);
+ if(node->curraddr==0)
+ {
+ node->curraddr=first_addr;
+ addr=node->curraddr;
+ }
+ else
+ {
+ addr=htonl(ntohl(node->curraddr)+1);
+ }
+ do
+ {
+ if(ntohl(addr)>ntohl(last_addr))
+ addr=first_addr;
+ if(map_search(addr)==NULL)
+ {
+ node->currnode=list_node;
+ node->curraddr=addr;
+ if(in6addr)
+ map_add(addr,*in6addr);
+ return(addr);
+ }
+ else
+ {
+ addr=htonl(ntohl(addr)+1);
+ }
+ }
+ while(addr!=node->curraddr);
+ list_node=list_node->next;
+ if(list_node==NULL)
+ list_node=node->addr;
+ }
+ while(list_node!=node->currnode);
+ lprintf(0,"There is no free ip address\n");
+ return(0);
+}