#pragma implementation #include #include #include #include "ipstuff.h" PUBLIC IP_ADDR::IP_ADDR() { a[0] = a[1] = a[2] = a[3] = -1; } PUBLIC IP_ADDR::IP_ADDR(const SSTRING &str) { setfrom (str.get()); } PUBLIC IP_ADDR::IP_ADDR(const IP_ADDR &adr) { memcpy (a,adr.a,sizeof(a)); SSTRING::setfrom (adr.get()); } /* Record an IP address (potentially incomplete, from a string Return the remaining of the string. */ PUBLIC char *IP_ADDR::copyword (const char *pt) { SSTRING::setfrom (pt); int i=0; a[0] = a[1] = a[2] = a[3] = -1; while (isdigit(*pt) && i < 4){ a[i] = atoi(pt); i++; pt = str_skipdig(pt); if (*pt != '.') break; pt++; } return (char*)pt; } /* Record an IP address (potentially incomplete, from a string Return the remaining of the string. */ PUBLIC void IP_ADDR::setfrom (const char *pt) { copyword (pt); } /* Return != 0 if this is a valid IP number */ PUBLIC int IP_ADDR::is_valid() { return ipnum_validip(get(),false); } /* Reformat the string representation from the four numbers */ PUBLIC void IP_ADDR::reformat() { char buf[20]; char *ctl = "%d"; char *pt = buf; for (int i=0; i<4 && a[i] != -1; i++){ pt += ::sprintf (pt,ctl,a[i]); ctl = ".%d"; } SSTRING::setfrom (buf); } #if 0 /* Compute the domain for reverse mapping IN-ADDR.ARPA */ PUBLIC void IP_ADDR::setrev ( int nbn, // Number of IP number used to define to reverse // domain char *str) { for (int i=nbn-1; i>=0; i--){ str += ::sprintf (str,"%u.",a[i]); } strcpy (str,"IN-ADDR.ARPA"); } #endif /* Compute the domain for reverse mapping IN-ADDR.ARPA Guess the type of network from the amount ot -1's in the address. */ PUBLIC void IP_ADDR::setrev ( char *str) { for (int i=3; i>=0; i--){ if (a[i] != -1){ str += ::sprintf (str,"%d.",a[i]); } } strcpy (str,"IN-ADDR.ARPA"); } /* Turn the IP number upside-down */ PUBLIC void IP_ADDR::reverse() { int b[4]; b[0] = a[3]; b[1] = a[2]; b[2] = a[1]; b[3] = a[0]; memcpy (a,b,sizeof(a)); reformat(); } PUBLIC int IP_ADDR::cmp(const IP_ADDR *p) { int ret = 0; for (int i=0; i<4; i++){ ret = a[i] - p->a[i]; if (ret != 0) break; } return ret; } PUBLIC int IP_ADDR::cmp(const char *str) { return SSTRING::cmp(str); } /* Shift the IP numbers to the left over the -1's (0.0.1.2 -> 1.2.0.0) */ PUBLIC void IP_ADDR::shift() { for (int i=0; i<4; i++){ if (a[0] == -1){ memmove (a,a+1,3*sizeof(a[0])); a[3] = -1; }else{ break; } } reformat(); } /* Shift the IP numbers to the right over the -1's (1.2.0.0 -> 0.0.1.2) */ PUBLIC void IP_ADDR::shift_right() { for (int i=3; i>0; i--){ if (a[3] == -1){ memmove (a+1,a,3*sizeof(a[0])); a[0] = -1; }else{ break; } } reformat(); } /* Augment the IP number by one. No reformat is done since this function is called often */ PUBLIC void IP_ADDR::increm() { for (int i=3; i>=0; i--){ a[i]++; if (a[i] < 256) break; a[i] = 0; } } /* Merge one IP number end over another. */ PUBLIC void IP_ADDR::merge(IP_ADDR &partial) { for (int i=0; i<4; i++){ if (partial.a[i] != -1) a[i] = partial.a[i]; } reformat(); } PUBLIC IP_ADDR *IP_ADDRS::getitem(int no) const { return (IP_ADDR*)ARRAY::getitem(no); } static int cmp_by_addr (const ARRAY_OBJ *op1, const ARRAY_OBJ *op2) { IP_ADDR *p1 = (IP_ADDR*)op1; IP_ADDR *p2 = (IP_ADDR*)op2; return p1->cmp(p2); } PUBLIC void IP_ADDRS::sort() { ARRAY::sort(cmp_by_addr); } PUBLIC IPMAP::IPMAP(const char *line) { line = iprange.copyword (line); line = str_skip(line); comment.setfrom (line); } PUBLIC IPMAP::IPMAP() { } /* Parse the IP range and prepare for the search of an available IP. Return -1 if the IP range is invalid (not x.y.z.w1-w2) */ PUBLIC int IPMAP::setup() { int ret = -1; char tmp[200]; iprange.copy(tmp); char *pt = strchr(tmp,'-'); over = 0; if (pt != NULL){ *pt++ = '\0'; minimum.setfrom(tmp); if (minimum.is_valid()){ IP_ADDR part; pt = part.copyword(str_skip(pt)); if (*pt == '\0'){ maximum.setfrom (tmp); part.shift_right(); maximum.merge (part); if (maximum.is_valid()){ if (maximum.cmp(&minimum)>=0){ ret = 0; reset(); } } } } } return ret; } /* Reset the available IP number to the minimum of the range */ PUBLIC void IPMAP::reset() { avail.setfrom (minimum.get()); } /* Go to the next available IP number of the range Return -1 if the range limit is reached. */ PUBLIC int IPMAP::next() { int ret = 0; if (avail.cmp(&maximum)==0){ ret = -1; over = 1; }else{ avail.increm(); } return ret; } /* Obtain the current available IP in the range. Use this function to walk a range with the next() function. */ PUBLIC const char *IPMAP::getcur() { avail.reformat(); return avail.get(); } /* Record the fact that the IP "adr" is in use. This function assume that it will be called with adr always increasing. */ PUBLIC void IPMAP::setuse (const IP_ADDR *adr) { if (minimum.cmp(adr)<=0 && maximum.cmp(adr)>=0){ if (avail.cmp(adr)==0){ next(); } } }