PageRenderTime 142ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/commoncpp2-1.8.1/src/cidr.cpp

#
C++ | 350 lines | 244 code | 64 blank | 42 comment | 34 complexity | 3743fd908c1f820ce537fe918e51c7a3 MD5 | raw file
Possible License(s): GPL-2.0
  1. // Copyright (C) 2006-2010 David Sugar, Tycho Softworks
  2. //
  3. // This program is free software; you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation; either version 2 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  16. //
  17. // As a special exception, you may use this file as part of a free software
  18. // library without restriction. Specifically, if other files instantiate
  19. // templates or use macros or inline functions from this file, or you compile
  20. // this file and link it with other files to produce an executable, this
  21. // file does not by itself cause the resulting executable to be covered by
  22. // the GNU General Public License. This exception does not however
  23. // invalidate any other reasons why the executable file might be covered by
  24. // the GNU General Public License.
  25. //
  26. // This exception applies only to the code released under the name GNU
  27. // Common C++. If you copy code from other releases into a copy of GNU
  28. // Common C++, as the General Public License permits, the exception does
  29. // not apply to the code that you add in this way. To avoid misleading
  30. // anyone as to the status of such modified files, you must delete
  31. // this exception notice from them.
  32. //
  33. // If you write modifications of your own for GNU Common C++, it is your choice
  34. // whether to permit this exception to apply to your modifications.
  35. // If you do not wish that, delete this exception notice.
  36. //
  37. #include <cc++/config.h>
  38. #include <cc++/export.h>
  39. #include <cc++/address.h>
  40. #include "private.h"
  41. #include <cstdlib>
  42. #include <fcntl.h>
  43. #include <cstdio>
  44. #ifdef CCXX_NAMESPACES
  45. namespace ost {
  46. #endif
  47. typedef unsigned char bit_t;
  48. static void bitmask(bit_t *bits, bit_t *mask, unsigned len)
  49. {
  50. while(len--)
  51. *(bits++) &= *(mask++);
  52. }
  53. static void bitimask(bit_t *bits, bit_t *mask, unsigned len)
  54. {
  55. while(len--)
  56. *(bits++) |= ~(*(mask++));
  57. }
  58. static void bitset(bit_t *bits, unsigned blen)
  59. {
  60. bit_t mask;
  61. while(blen) {
  62. mask = (bit_t)(1 << 7);
  63. while(mask && blen) {
  64. *bits |= mask;
  65. mask >>= 1;
  66. --blen;
  67. }
  68. ++bits;
  69. }
  70. }
  71. static unsigned bitcount(bit_t *bits, unsigned len)
  72. {
  73. unsigned count = 0;
  74. bit_t mask, test;
  75. while(len--) {
  76. mask = (bit_t)(1<<7);
  77. test = *bits++;
  78. while(mask) {
  79. if(!(mask & test))
  80. return count;
  81. ++count;
  82. mask >>= 1;
  83. }
  84. }
  85. return count;
  86. }
  87. IPV4Cidr::IPV4Cidr()
  88. {
  89. memset(&network, 0, sizeof(network));
  90. memset(&netmask, 0, sizeof(netmask));
  91. }
  92. IPV4Cidr::IPV4Cidr(const char *cp)
  93. {
  94. set(cp);
  95. }
  96. IPV4Cidr::IPV4Cidr(IPV4Cidr &cidr)
  97. {
  98. memcpy(&network, &cidr.network, sizeof(network));
  99. memcpy(&netmask, &cidr.netmask, sizeof(netmask));
  100. }
  101. bool IPV4Cidr::isMember(const struct in_addr &addr) const
  102. {
  103. struct in_addr host = addr;
  104. bitmask((bit_t *)&host, (bit_t *)&netmask, sizeof(host));
  105. if(!memcmp(&host, &network, sizeof(host)))
  106. return true;
  107. return false;
  108. }
  109. bool IPV4Cidr::isMember(const struct sockaddr *saddr) const
  110. {
  111. struct sockaddr_in *addr = (struct sockaddr_in *)saddr;
  112. struct in_addr host;
  113. if(saddr->sa_family != AF_INET)
  114. return false;
  115. memcpy(&host, &addr->sin_addr.s_addr, sizeof(host));
  116. bitmask((bit_t *)&host, (bit_t *)&netmask, sizeof(host));
  117. if(!memcmp(&host, &network, sizeof(host)))
  118. return true;
  119. return false;
  120. }
  121. struct in_addr IPV4Cidr::getBroadcast(void) const
  122. {
  123. struct in_addr bcast;
  124. memcpy(&bcast, &network, sizeof(network));
  125. bitimask((bit_t *)&bcast, (bit_t *)&netmask, sizeof(bcast));
  126. return bcast;
  127. }
  128. unsigned IPV4Cidr::getMask(const char *cp) const
  129. {
  130. unsigned dcount = 0;
  131. const char *gp = cp;
  132. const char *mp = strchr(cp, '/');
  133. unsigned char dots[4];
  134. #ifdef WIN32
  135. DWORD mask;
  136. #else
  137. uint32 mask;
  138. #endif
  139. if(mp) {
  140. if(!strchr(++mp, '.'))
  141. return atoi(mp);
  142. mask = inet_addr(mp);
  143. return bitcount((bit_t *)&mask, sizeof(mask));
  144. }
  145. memset(dots, 0, sizeof(dots));
  146. dots[0] = atoi(cp);
  147. while(*gp && dcount < 3) {
  148. if(*(gp++) == '.')
  149. dots[++dcount] = atoi(gp);
  150. }
  151. if(dots[3])
  152. return 32;
  153. if(dots[2])
  154. return 24;
  155. if(dots[1])
  156. return 16;
  157. return 8;
  158. }
  159. void IPV4Cidr::set(const char *cp)
  160. {
  161. char cbuf[INET_IPV4_ADDRESS_SIZE];
  162. char *ep;
  163. unsigned dots = 0;
  164. #ifdef WIN32
  165. DWORD addr;
  166. #endif
  167. memset(&netmask, 0, sizeof(netmask));
  168. bitset((bit_t *)&netmask, getMask(cp));
  169. setString(cbuf, sizeof(cbuf), cp);
  170. ep = (char *)strchr(cp, '/');
  171. if(ep)
  172. *ep = 0;
  173. cp = cbuf;
  174. while(NULL != (cp = strchr(cp, '.'))) {
  175. ++dots;
  176. ++cp;
  177. }
  178. while(dots++ < 3)
  179. addString(cbuf, sizeof(cbuf), ".0");
  180. #ifdef WIN32
  181. addr = inet_addr(cbuf);
  182. memcpy(&network, &addr, sizeof(network));
  183. #else
  184. inet_aton(cbuf, &network);
  185. #endif
  186. bitmask((bit_t *)&network, (bit_t *)&netmask, sizeof(network));
  187. }
  188. #ifdef CCXX_IPV6
  189. IPV6Cidr::IPV6Cidr()
  190. {
  191. memset(&network, 0, sizeof(network));
  192. memset(&netmask, 0, sizeof(netmask));
  193. }
  194. IPV6Cidr::IPV6Cidr(const char *cp)
  195. {
  196. set(cp);
  197. }
  198. IPV6Cidr::IPV6Cidr(IPV6Cidr &cidr)
  199. {
  200. memcpy(&network, &cidr.network, sizeof(network));
  201. memcpy(&netmask, &cidr.netmask, sizeof(netmask));
  202. }
  203. bool IPV6Cidr::isMember(const struct in6_addr &addr) const
  204. {
  205. struct in6_addr host = addr;
  206. bitmask((bit_t *)&host, (bit_t *)&netmask, sizeof(host));
  207. if(!memcmp(&host, &network, sizeof(host)))
  208. return true;
  209. return false;
  210. }
  211. bool IPV6Cidr::isMember(const struct sockaddr *saddr) const
  212. {
  213. struct sockaddr_in6 *addr = (struct sockaddr_in6 *)saddr;
  214. struct in6_addr host;
  215. if(saddr->sa_family != AF_INET6)
  216. return false;
  217. memcpy(&host, &addr->sin6_addr, sizeof(host));
  218. bitmask((bit_t *)&host, (bit_t *)&netmask, sizeof(host));
  219. if(!memcmp(&host, &network, sizeof(host)))
  220. return true;
  221. return false;
  222. }
  223. struct in6_addr IPV6Cidr::getBroadcast(void) const
  224. {
  225. struct in6_addr bcast;
  226. memcpy(&bcast, &network, sizeof(network));
  227. bitimask((bit_t *)&bcast, (bit_t *)&netmask, sizeof(bcast));
  228. return bcast;
  229. }
  230. unsigned IPV6Cidr::getMask(const char *cp) const
  231. {
  232. unsigned count = 0, rcount = 0;
  233. const char *sp = strchr(cp, '/');
  234. int flag = 0;
  235. if(sp)
  236. return atoi(++sp);
  237. if(!strncmp(cp, "ff00:", 5))
  238. return 8;
  239. if(!strncmp(cp, "fe80:", 5))
  240. return 10;
  241. if(!strncmp(cp, "2002:", 5))
  242. return 16;
  243. sp = strrchr(cp, ':');
  244. while(*(++sp) == '0')
  245. ++sp;
  246. if(*sp)
  247. return 128;
  248. while(*cp && count < 128) {
  249. if(*(cp++) == ':') {
  250. count+= 16;
  251. while(*cp == '0')
  252. ++cp;
  253. if(*cp == ':') {
  254. if(!flag)
  255. rcount = count;
  256. flag = 1;
  257. }
  258. else
  259. flag = 0;
  260. }
  261. }
  262. return rcount;
  263. }
  264. void IPV6Cidr::set(const char *cp)
  265. {
  266. char cbuf[INET_IPV6_ADDRESS_SIZE];
  267. char *ep;
  268. memset(&netmask, 0, sizeof(netmask));
  269. bitset((bit_t *)&netmask, getMask(cp));
  270. setString(cbuf, sizeof(cbuf), cp);
  271. ep = (char *)strchr(cp, '/');
  272. if(ep)
  273. *ep = 0;
  274. inet_pton(AF_INET6, cbuf, &network);
  275. bitmask((bit_t *)&network, (bit_t *)&netmask, sizeof(network));
  276. }
  277. #endif
  278. #ifdef CCXX_NAMESPACES
  279. }
  280. #endif
  281. /** EMACS **
  282. * Local variables:
  283. * mode: c++
  284. * c-basic-offset: 4
  285. * End:
  286. */