/src/logread.c

http://holyshield.googlecode.com/ · C · 186 lines · 140 code · 26 blank · 20 comment · 46 complexity · 236f7e352952210b38d815c68b282355 MD5 · raw file

  1. //#include <config.h>
  2. //#include <gnome.h>
  3. #include <gtk/gtk.h>
  4. #include <netdb.h>
  5. #include "globals.h"
  6. #include "logread.h"
  7. #include "util.h"
  8. #include "hitview.h"
  9. #include "statusview.h"
  10. #include "service.h"
  11. static gboolean BUSY = FALSE;
  12. /* [ gvfs_seek_callback ]
  13. * Zero the buffer and read again
  14. */
  15. static void
  16. gvfs_seek_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer data)
  17. {
  18. Parse *info = data;
  19. if (result != GNOME_VFS_OK) {
  20. g_warning ("Seek error");
  21. }
  22. memset (info->buffer, 0, FILE_BUF);
  23. gnome_vfs_async_read (handle, info->buffer, FILE_BUF, logread_async_read_callback, info);
  24. }
  25. static void
  26. gvfs_seek_end_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer data)
  27. {
  28. if (result != GNOME_VFS_OK)
  29. g_warning ("Seek end error");
  30. }
  31. /* [ logread_async_read_callback ]
  32. * Read file parsing for iptables pattern, add to hitview on match
  33. */
  34. void
  35. logread_async_read_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer buffer,
  36. GnomeVFSFileSize bytes_requested, GnomeVFSFileSize bytes_read, gpointer data)
  37. {
  38. gchar **lines = NULL;
  39. Parse *info = data;
  40. Hit *h;
  41. int i = 0;
  42. if (g_str_has_suffix (info->buffer,"\n"))
  43. info->half_line=0;
  44. else
  45. info->half_line=1;
  46. if (result == GNOME_VFS_OK && bytes_read > 0) {
  47. /* split line into (gchar **) and check for pattern */
  48. lines = g_strsplit_set (info->buffer, "\n",-1);
  49. while (*(lines+(i+info->half_line)) && (*lines+i != NULL)) {
  50. if (g_pattern_match_string (info->pattern,*(lines+i) )) {
  51. h = parse_log_line (*(lines+i));
  52. if (hitview_append_hit (h) && !hitview_reload_in_progress ())
  53. status_set_state (STATUS_HIT);
  54. free_hit (h);
  55. }
  56. i++;
  57. }
  58. /* end of file or error */
  59. if (bytes_requested != bytes_read) {
  60. if (info->continuous) {
  61. memset (info->buffer, 0, FILE_BUF); /* fill buffer with zeros, next line might be half line */
  62. BUSY = FALSE;
  63. } else
  64. gnome_vfs_async_close (handle, hitview_abort_reload_callback, info);
  65. } else if ((info->half_line) == 1 && (i > 1)) { /* if last line was half line seek back */
  66. int len=strlen (*(lines+i));
  67. gnome_vfs_async_seek (handle,GNOME_VFS_SEEK_CURRENT, -len,
  68. gvfs_seek_callback, info);
  69. } else {
  70. memset (info->buffer, 0, FILE_BUF); /* fill buffer with zeros, next line might be half line */
  71. info->bytes_read += bytes_read;
  72. gnome_vfs_async_read (handle, info->buffer, FILE_BUF, logread_async_read_callback, info);
  73. }
  74. } else {
  75. if (info->continuous) {
  76. memset (info->buffer, 0, FILE_BUF); /* fill buffer with zeros, next line might be half line */
  77. BUSY = FALSE;
  78. } else {
  79. gnome_vfs_async_close (handle, hitview_abort_reload_callback, info);
  80. }
  81. }
  82. if (lines)
  83. g_strfreev (lines);
  84. }
  85. /* [ poll_log_timeout ]
  86. * Polls the logfile every 500ms for change, if change, parse lines
  87. */
  88. static int
  89. poll_log_timeout (gpointer data)
  90. {
  91. Parse *info = data;
  92. if (BUSY == FALSE) { /* start reading only when previous read has finished */
  93. BUSY = TRUE;
  94. gnome_vfs_async_read (info->handle, info->buffer, FILE_BUF, logread_async_read_callback, info);
  95. }
  96. return TRUE; /* TRUE means we want to keep calling the function */
  97. }
  98. static void
  99. gvfs_open_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer data)
  100. {
  101. Parse *info;
  102. if (result != GNOME_VFS_OK) {
  103. g_warning ("Log file not found or access denied.\n"
  104. "Firewall log monitoring disabled.");
  105. } else {
  106. info = g_new (Parse, 1);
  107. info->buffer = g_new (gchar, FILE_BUF+1);
  108. info->pattern = g_pattern_spec_new ("* IN=* OUT=* SRC=* ");
  109. info->handle = handle;
  110. info->continuous = TRUE;
  111. /* seek to the end of file and add a timeout */
  112. gnome_vfs_async_seek (handle, GNOME_VFS_SEEK_END, 0, gvfs_seek_end_callback, info);
  113. g_timeout_add (500, poll_log_timeout, info);
  114. }
  115. }
  116. Hit *
  117. parse_log_line (gchar *line)
  118. {
  119. struct protoent *protocol;
  120. Hit *h;
  121. gchar *type = NULL; // ICMP service type, not part of hit model
  122. h = g_new0 (Hit, 1);
  123. /* Take 15 first characters as timestamp */
  124. h->time = g_strndup (line, 15);
  125. h->direction = g_strstrip (get_text_between (line, "kernel:", "IN"));
  126. h->in = get_text_between (line, "IN=", " ");
  127. h->out = get_text_between (line, "OUT=", " ");
  128. h->source = get_text_between (line, "SRC=", " ");
  129. h->destination = get_text_between (line, "DST=", " ");
  130. h->length = get_text_between (line, "LEN=", " ");
  131. h->tos = get_text_between (line, "TOS=", " ");
  132. h->protocol = get_text_between (line, "PROTO=", " ");
  133. type = get_text_between (line, "TYPE=", " ");
  134. h->port = get_text_between (line, "DPT=", " ");
  135. /* If the protocol is a number we do a protocol name lookup */
  136. if (h->protocol != NULL)
  137. if (g_ascii_isdigit(h->protocol[0])) {
  138. protocol = getprotobynumber (atoi (h->protocol));
  139. if (protocol != NULL) {
  140. g_free (h->protocol);
  141. h->protocol = g_utf8_strup (protocol->p_name, -1);
  142. }
  143. }
  144. /* Determine service used based on the port and protocol */
  145. if (type != "" && strcmp (h->protocol, "icmp") == 0) {
  146. h->service = service_get_icmp_name (atoi (type));
  147. } else if (h->port != NULL && h->protocol != NULL)
  148. h->service = service_get_name (atoi (h->port), g_strdup (h->protocol));
  149. g_free (type);
  150. return h;
  151. }
  152. /* [ open_logfile ]
  153. * Open the system log and attach a reader function with a timeout
  154. */
  155. void
  156. open_logfile (char *logpath) {
  157. GnomeVFSAsyncHandle *handle;
  158. gnome_vfs_async_open(&handle, logpath, GNOME_VFS_OPEN_READ, GNOME_VFS_PRIORITY_DEFAULT,
  159. gvfs_open_callback, NULL);
  160. }