PageRenderTime 64ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/ipv6calc-0.93.1/ipv6loganon/ipv6loganon.c

#
C | 501 lines | 370 code | 87 blank | 44 comment | 120 complexity | c7d8a7bfd9d5b8c73eb7f548c26c807b MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * Project : ipv6calc
  3. * File : ipv6loganon.c
  4. * Version : $Id: ipv6loganon.c,v 1.10 2012/02/04 21:01:02 peter Exp $
  5. * Copyright : 2007-2012 by Peter Bieringer <pb (at) bieringer.de>
  6. *
  7. * Information:
  8. * Dedicated program for logfile anonymization
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <getopt.h>
  14. #include <unistd.h>
  15. #include "ipv6loganon.h"
  16. #include "libipv6calcdebug.h"
  17. #include "libipv6calc.h"
  18. #include "ipv6calccommands.h"
  19. #include "ipv6calctypes.h"
  20. #include "ipv6loganonoptions.h"
  21. #include "ipv6calchelp.h"
  22. #include "ipv6loganonhelp.h"
  23. #include "libipv4addr.h"
  24. #include "libipv6addr.h"
  25. #include "libmac.h"
  26. #include "librfc1884.h"
  27. #include "librfc1886.h"
  28. #include "librfc1924.h"
  29. #include "libifinet6.h"
  30. #include "librfc2874.h"
  31. #include "librfc3056.h"
  32. #include "libeui64.h"
  33. #include "libieee.h"
  34. #define LINEBUFFER 16384
  35. long int ipv6calc_debug = 0;
  36. int flag_quiet = 1;
  37. int flag_nocache = 0;
  38. /* default values */
  39. int mask_ipv4 = 24;
  40. int mask_ipv6 = 48;
  41. int mask_iid = 1;
  42. /* prototypes */
  43. static int anonymizetoken(char *result, const char *token);
  44. static void lineparser();
  45. /* LRU cache */
  46. #define CACHE_LRU_SIZE 200
  47. static int cache_lru_max = 0;
  48. static int cache_lru_last = 0;
  49. int cache_lru_limit = 20; /* optimum */
  50. static char cache_lru_key_token[CACHE_LRU_SIZE][NI_MAXHOST];
  51. static char cache_lru_value[CACHE_LRU_SIZE][NI_MAXHOST];
  52. static long int cache_lru_statistics[CACHE_LRU_SIZE];
  53. char file_out[NI_MAXHOST] = "";
  54. int file_out_flag = 0;
  55. int file_out_flush = 0;
  56. char file_out_mode[NI_MAXHOST] = "";
  57. FILE *FILE_OUT;
  58. /**************************************************/
  59. /* main */
  60. #define DEBUG_function_name "ipv6loganon/main"
  61. int main(int argc,char *argv[]) {
  62. int i, lop;
  63. /* Fetch the command-line arguments. */
  64. while ((i = getopt_long(argc, argv, ipv6loganon_shortopts, ipv6loganon_longopts, &lop)) != EOF) {
  65. switch (i) {
  66. case -1:
  67. break;
  68. case 'v':
  69. printversion();
  70. exit(EXIT_FAILURE);
  71. break;
  72. case 'V':
  73. flag_quiet = 0;
  74. break;
  75. case 'h':
  76. case '?':
  77. ipv6loganon_printhelp();
  78. exit(EXIT_FAILURE);
  79. break;
  80. case 'd':
  81. ipv6calc_debug = atol(optarg);
  82. break;
  83. case 'f':
  84. file_out_flush = 1;
  85. break;
  86. case 'w':
  87. case 'a':
  88. if (strlen(optarg) < NI_MAXHOST) {
  89. strcpy(file_out, optarg);
  90. file_out_flag = 1;
  91. } else {
  92. fprintf(stderr, " Output file too long: %s\n", optarg);
  93. exit(EXIT_FAILURE);
  94. };
  95. switch (i) {
  96. case 'w':
  97. strcpy(file_out_mode, "w");
  98. break;
  99. case 'a':
  100. strcpy(file_out_mode, "a");
  101. break;
  102. };
  103. break;
  104. case 'c':
  105. cache_lru_limit = atoi(optarg);
  106. if (cache_lru_limit > CACHE_LRU_SIZE) {
  107. cache_lru_limit = CACHE_LRU_SIZE;
  108. fprintf(stderr, " Cache limit too big, built-in limit: %d\n", cache_lru_limit);
  109. };
  110. if (cache_lru_limit < 1) {
  111. cache_lru_limit = 1;
  112. fprintf(stderr, " Cache limit too small, take minimum: %d\n", cache_lru_limit);
  113. };
  114. break;
  115. case 'n':
  116. flag_nocache = 1;
  117. break;
  118. case CMD_ANON_NO_MASK_IID:
  119. mask_iid = 0;
  120. break;
  121. case CMD_ANON_MASK_IPV4:
  122. mask_ipv4 = atoi(optarg);
  123. if (mask_ipv4 < 0 || mask_ipv4 > 32) {
  124. fprintf(stderr, " value for option 'mask-ipv4' out-of-range [0-32]\n");
  125. exit(EXIT_FAILURE);
  126. };
  127. break;
  128. case CMD_ANON_MASK_IPV6:
  129. mask_ipv6 = atoi(optarg);
  130. if (mask_ipv6 < 0 || mask_ipv4 > 64) {
  131. fprintf(stderr, " value for option 'mask-ipv6' out-of-range [0-64]\n");
  132. exit(EXIT_FAILURE);
  133. };
  134. break;
  135. case CMD_ANON_PRESET_STANDARD:
  136. mask_ipv4 = 24;
  137. mask_ipv6 = 48;
  138. mask_iid = 1;
  139. break;
  140. case CMD_ANON_PRESET_CAREFUL:
  141. mask_ipv4 = 20;
  142. mask_ipv6 = 40;
  143. mask_iid = 1;
  144. break;
  145. case CMD_ANON_PRESET_PARANOID:
  146. mask_ipv4 = 16;
  147. mask_ipv6 = 32;
  148. mask_iid = 1;
  149. break;
  150. default:
  151. ipv6loganon_printinfo();
  152. exit(EXIT_FAILURE);
  153. break;
  154. };
  155. };
  156. argv += optind;
  157. argc -= optind;
  158. if (file_out_flag == 1) {
  159. if (ipv6calc_debug > 0) {
  160. fprintf(stderr, "Output file specified: %s\n", file_out);
  161. };
  162. FILE_OUT = fopen(file_out, file_out_mode);
  163. if (! FILE_OUT) {
  164. fprintf(stderr, "Can't open Output file: %s\n", file_out);
  165. exit(EXIT_FAILURE);
  166. } else {
  167. if (ipv6calc_debug > 0) {
  168. if (strcmp(file_out_mode, "a") == 0) {
  169. fprintf(stderr, "Output file opened successfully in append mode: %s\n", file_out);
  170. } else {
  171. fprintf(stderr, "Output file opened successfully in write mode: %s\n", file_out);
  172. };
  173. };
  174. file_out_flag = 2;
  175. };
  176. };
  177. lineparser();
  178. if (file_out_flag == 2) {
  179. if (ipv6calc_debug > 0) {
  180. fprintf(stderr, "Output file is closed now: %s\n", file_out);
  181. };
  182. fflush(FILE_OUT);
  183. fclose(FILE_OUT);
  184. } else {
  185. fflush(stdout);
  186. };
  187. exit(EXIT_SUCCESS);
  188. };
  189. #undef DEBUG_function_name
  190. /*
  191. * Line parser
  192. */
  193. #define DEBUG_function_name "ipv6loganon/lineparser"
  194. static void lineparser(void) {
  195. char linebuffer[LINEBUFFER];
  196. char token[LINEBUFFER];
  197. char resultstring[LINEBUFFER];
  198. char *charptr, *cptr, **ptrptr;
  199. int linecounter = 0, retval, i;
  200. ptrptr = &cptr;
  201. if (flag_quiet == 0) {
  202. fprintf(stderr, "Expecting log lines on stdin\n");
  203. };
  204. while (1 == 1) {
  205. /* read line from stdin */
  206. charptr = fgets(linebuffer, LINEBUFFER, stdin);
  207. if (charptr == NULL) {
  208. /* end of input */
  209. break;
  210. };
  211. linecounter++;
  212. if (linecounter == 1) {
  213. if (flag_quiet == 0) {
  214. fprintf(stderr, "Ok, proceeding stdin...\n");
  215. };
  216. };
  217. if (ipv6calc_debug == 1) {
  218. fprintf(stderr, "Line: %d\r", linecounter);
  219. };
  220. if (strlen(linebuffer) >= LINEBUFFER) {
  221. fprintf(stderr, "Line too long: %d\n", linecounter);
  222. continue;
  223. };
  224. if (strlen(linebuffer) == 0) {
  225. fprintf(stderr, "Line empty: %d\n", linecounter);
  226. continue;
  227. };
  228. if (ipv6calc_debug != 0) {
  229. fprintf(stderr, "%s: Got line: '%s'\n", DEBUG_function_name, linebuffer);
  230. };
  231. /* look for first token */
  232. charptr = strtok_r(linebuffer, " \t\n", ptrptr);
  233. if ( charptr == NULL ) {
  234. fprintf(stderr, "Line contains no token: %d\n", linecounter);
  235. continue;
  236. };
  237. if ( strlen(charptr) >= LINEBUFFER) {
  238. fprintf(stderr, "Line too strange: %d\n", linecounter);
  239. continue;
  240. };
  241. snprintf(token, sizeof(token) - 1, "%s", charptr);
  242. if (ipv6calc_debug != 0) {
  243. fprintf(stderr, "%s: Token 1: '%s'\n", DEBUG_function_name, token);
  244. };
  245. /* call anonymizer now */
  246. retval = anonymizetoken(resultstring, charptr);
  247. if (retval != 0) {
  248. continue;
  249. };
  250. /* print result and rest of line, if available */
  251. if (*ptrptr[0] != '\0') {
  252. if (file_out_flag == 2) {
  253. fprintf(FILE_OUT, "%s %s", resultstring, *ptrptr);
  254. } else {
  255. printf("%s %s", resultstring, *ptrptr);
  256. };
  257. } else {
  258. if (file_out_flag == 2) {
  259. fprintf(FILE_OUT, "%s\n", resultstring);
  260. } else {
  261. printf("%s\n", resultstring);
  262. };
  263. };
  264. if (file_out_flush == 1) {
  265. if (file_out_flag == 2) {
  266. fflush(FILE_OUT);
  267. } else {
  268. fflush(stdout);
  269. };
  270. };
  271. };
  272. if (flag_quiet == 0) {
  273. fprintf(stderr, "...finished\n");
  274. if (flag_nocache == 0) {
  275. fprintf(stderr, "Cache statistics:\n");
  276. for (i = 0; i < cache_lru_limit; i++) {
  277. fprintf(stderr, "Cache distance: %3d hits: %8ld\n", i, cache_lru_statistics[i]);
  278. };
  279. };
  280. };
  281. return;
  282. };
  283. #undef DEBUG_function_name
  284. /*
  285. * Anonymize token
  286. */
  287. #define DEBUG_function_name "ipv6loganon/anonymizetoken"
  288. static int anonymizetoken(char *resultstring, const char *token) {
  289. long int inputtype = -1;
  290. int retval = 1, i;
  291. /* used structures */
  292. ipv6calc_ipv6addr ipv6addr;
  293. ipv6calc_ipv4addr ipv4addr;
  294. if (ipv6calc_debug != 0) {
  295. fprintf(stderr, "%s: Token: '%s'\n", DEBUG_function_name, token);
  296. };
  297. /* clear resultstring */
  298. resultstring[0] = '\0';
  299. if (strlen(token) == 0) {
  300. return (1);
  301. };
  302. /* use cache ? */
  303. if (flag_nocache == 0 && cache_lru_max > 0) {
  304. /* check last seen one first */
  305. if ((ipv6calc_debug & 0x4) != 0) {
  306. fprintf(stderr, "LRU cache: look for key=%s\n", token);
  307. };
  308. if (strcmp(cache_lru_key_token[cache_lru_last - 1], token) == 0) {
  309. snprintf(resultstring, LINEBUFFER - 1, "%s", cache_lru_value[cache_lru_last - 1]);
  310. cache_lru_statistics[0]++;
  311. if ((ipv6calc_debug & 0x4) != 0) {
  312. fprintf(stderr, "LRU cache: hit last line=%d key_token=%s value=%s\n", cache_lru_last - 1, token, resultstring);
  313. };
  314. return (0);
  315. };
  316. /* run backwards to first entry */
  317. if (cache_lru_last > 1) {
  318. for (i = cache_lru_last - 1; i > 0; i--) {
  319. if (strcmp(cache_lru_key_token[i - 1], token) == 0) {
  320. snprintf(resultstring, LINEBUFFER - 1, "%s", cache_lru_value[i - 1]);
  321. cache_lru_statistics[cache_lru_last - i]++;
  322. if ((ipv6calc_debug & 0x4) != 0) {
  323. fprintf(stderr, "LRU cache: hit line=%d key_token=%s value=%s\n", i - 1, token, resultstring);
  324. };
  325. return (0);
  326. };
  327. };
  328. };
  329. /* round robin */
  330. if (cache_lru_last < cache_lru_max) {
  331. for (i = cache_lru_max; i > cache_lru_last; i--) {
  332. if (strcmp(cache_lru_key_token[i - 1], token) == 0) {
  333. snprintf(resultstring, LINEBUFFER - 1, "%s", cache_lru_value[i - 1]);
  334. cache_lru_statistics[cache_lru_max - i + cache_lru_last]++;
  335. if ((ipv6calc_debug & 0x4) != 0) {
  336. fprintf(stderr, "LRU cache: hit line=%d key_token=%s value=%s\n", i - 1, token, resultstring);
  337. };
  338. return (0);
  339. };
  340. };
  341. };
  342. };
  343. /* set addresses to invalid */
  344. ipv6addr.flag_valid = 0;
  345. ipv4addr.flag_valid = 0;
  346. /* autodetection */
  347. inputtype = libipv6calc_autodetectinput(token);
  348. if (ipv6calc_debug != 0) {
  349. if (inputtype >= 0) {
  350. for (i = 0; i < (int) (sizeof(ipv6calc_formatstrings) / sizeof(ipv6calc_formatstrings[0])); i++) {
  351. if (inputtype == ipv6calc_formatstrings[i].number) {
  352. fprintf(stderr, "%s: Found type: %s\n", DEBUG_function_name, ipv6calc_formatstrings[i].token);
  353. };
  354. break;
  355. };
  356. } else {
  357. fprintf(stderr, "%s: Input type unknown\n", DEBUG_function_name);
  358. return (1);
  359. };
  360. };
  361. /* proceed input depending on type */
  362. switch (inputtype) {
  363. case FORMAT_ipv6addr:
  364. retval = addr_to_ipv6addrstruct(token, resultstring, &ipv6addr);
  365. break;
  366. case FORMAT_ipv4addr:
  367. retval = addr_to_ipv4addrstruct(token, resultstring, &ipv4addr);
  368. break;
  369. };
  370. if (ipv6calc_debug != 0) {
  371. fprintf(stderr, "%s: Token: '%s'\n", DEBUG_function_name, token);
  372. };
  373. /***** postprocessing input *****/
  374. if (ipv6calc_debug != 0) {
  375. fprintf(stderr, "%s: Start of postprocessing input\n", DEBUG_function_name);
  376. };
  377. if (ipv6addr.flag_valid == 1) {
  378. /* anonymize IPv6 address according to settings */
  379. libipv6addr_anonymize(&ipv6addr, mask_iid, mask_ipv6, mask_ipv4);
  380. /* convert IPv6 address structure to string */
  381. ipv6addrstruct_to_compaddr(&ipv6addr, resultstring);
  382. } else if (ipv4addr.flag_valid == 1) {
  383. /* anonymize IPv6 address according to settings */
  384. libipv4addr_anonymize(&ipv4addr, mask_ipv4);
  385. /* convert IPv4 address structure to string */
  386. libipv4addr_ipv4addrstruct_to_string(&ipv4addr, resultstring, 0);
  387. } else {
  388. /* probably reverse DNS resolving lookup string, do not touch */
  389. snprintf(resultstring, LINEBUFFER - 1, "%s", token);
  390. return (0);
  391. };
  392. /* use cache ? */
  393. if (flag_nocache == 0) {
  394. /* calculate pointer */
  395. if (cache_lru_max < cache_lru_limit) {
  396. cache_lru_last++;
  397. cache_lru_max++;
  398. } else {
  399. if (cache_lru_last == cache_lru_limit) {
  400. cache_lru_last = 1;
  401. } else {
  402. cache_lru_last++;
  403. };
  404. };
  405. /* store key and value */
  406. snprintf(cache_lru_key_token[cache_lru_last - 1], NI_MAXHOST - 1, "%s", token);
  407. snprintf(cache_lru_value[cache_lru_last - 1], NI_MAXHOST - 1, "%s", resultstring);
  408. if ((ipv6calc_debug & 0x4) != 0) {
  409. fprintf(stderr, "LRU cache: fill line=%d key_token=%s value=%s\n", cache_lru_last - 1, cache_lru_key_token[cache_lru_last - 1], cache_lru_value[cache_lru_last - 1]);
  410. };
  411. };
  412. return (0);
  413. };
  414. #undef DEBUG_function_name