/* * 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 ; * 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 #include #include #include #include #else #include #include #include #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); }