| /* Analyzes the concurrent use of charon's threads |
| * |
| * Copyright (C) 2008 Andreas Steffen |
| * |
| * Copyright (C) secunet Security Networks AG |
| * |
| * 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. See <http://www.fsf.org/copyleft/gpl.txt>. |
| * |
| * 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. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #define LOGFILE "moon.daemon.log" |
| #define LINE_LEN 2048 |
| #define THREADS 99 |
| |
| typedef enum state_t state_t; |
| |
| enum state_t { |
| STATE_IDLE = 0, |
| STATE_INIT = 1, |
| STATE_AUTH = 2, |
| STATE_BUSY = 3, |
| STATE_RETRY = 4, |
| STATE_ERROR = 5 |
| }; |
| |
| typedef enum print_t print_t; |
| |
| enum print_t { |
| MODE_ANY = 0, |
| MODE_ADD = 1, |
| MODE_DEL = 2 |
| }; |
| |
| static char *state_names[] = { "idle", "init", "auth", "busy", "retry", "error" }; |
| |
| static int readline(FILE *fd, char *line) |
| { |
| while (fread(line, 1, 1, fd)) |
| { |
| if (*line == '\n') |
| { |
| *line = '\0'; |
| return 1; |
| } |
| line++; |
| } |
| *line = '\0'; |
| return 0; |
| } |
| |
| static void printline(state_t *state, char *timestamp) |
| { |
| int states[] = { 0, 0, 0, 0, 0}; |
| int th, total ; |
| |
| printf(" <tr>\n"); |
| printf(" <td class=\"log\">%.15s</td>", timestamp); |
| |
| for (th = 1; th <= THREADS; th++) |
| { |
| states[state[th]]++; |
| printf("<td class=\"%s\"></td>", state_names[state[th]]); |
| } |
| total = states[STATE_INIT] + states[STATE_AUTH] + states[STATE_BUSY] + states[STATE_RETRY]; |
| printf("<td class=\"init\">%d</td><td class=\"auth\">%d</td><td class=\"busy\">%d</td>", |
| states[STATE_INIT], states[STATE_AUTH], total); |
| for (th = 10; th <= (THREADS + 2); th += 5) |
| { |
| printf("<td class=\"%s\"></td>", (th <= total + 2)? "busy":"idle"); |
| } |
| printf("\n"); |
| printf(" </tr>\n"); |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| char line[LINE_LEN]; |
| int section = 0; |
| int mode = MODE_ANY; |
| int th; |
| FILE *fd; |
| |
| state_t state[THREADS + 1]; |
| |
| /* threads 1..5 and 9 are always busy */ |
| for (th = 1; th <= THREADS; th++) |
| { |
| state[th] = (th <= 7 && th != 3)? STATE_BUSY : STATE_IDLE; |
| } |
| |
| /* open the log file */ |
| fd = fopen(LOGFILE, "r"); |
| if (!fd) |
| { |
| printf("could not open log file '%s'\n", LOGFILE); |
| return 1; |
| } |
| |
| printf("<html>\n"); |
| printf("<head>\n"); |
| printf(" <title>Charon Thread Analysis</title>\n"); |
| printf(" <style>\n"); |
| printf(" body { font: 11px verdana,arial, helvetica, sans-serif }\n"); |
| printf(" td { font: 10px verdana,arial, helvetica, sans-serif;\n"); |
| printf(" text-align: center; padding: 0px 1px 0px 1px; background: #FFFF66 }\n"); |
| printf(" td.log { text-align: left; background: #FFFF66; white-space: nowrap }\n"); |
| printf(" td.idle { background: #FFFF66 }\n"); |
| printf(" td.init { background: #FFA522 }\n"); |
| printf(" td.auth { background: #90EE90 }\n"); |
| printf(" td.busy { background: #ADD8E6 }\n"); |
| printf(" td.retry { background: #7B68EE }\n"); |
| printf(" td.error { background: #FF6347 }\n"); |
| printf(" hr { background-color: #000000; border: 0; height: 1px; }\n"); |
| printf(" a:visited { color: #000000 }\n"); |
| printf(" a:link { color: #000000 }\n"); |
| printf(" a:hover { color: #0000FF }\n"); |
| printf(" </style>\n"); |
| printf("</head>\n"); |
| printf("<body>\n"); |
| printf(" <h1>Charon Thread Analysis</h1>\n"); |
| printf(" <table>\n"); |
| |
| /* print table header */ |
| printf(" <tr>\n"); |
| printf(" <td class=\"log\">Timestamp</td>"); |
| for (th = 1 ; th <= THREADS; th++) |
| { |
| printf("<td>%02d</td>", th); |
| } |
| printf("<td class=\"init\">I</td><td class=\"auth\">A</td><td class=\"busy\">B</td>"); |
| for (th = 10; th <= (THREADS + 2); th += 5) |
| { |
| printf("<td class=\"busy\">%d</td>", (th == 100)? 99:th); |
| } |
| printf("\n"); |
| printf(" </tr>\n"); |
| |
| while (readline(fd, line)) |
| { |
| char *p_section, *p_charon, *p_thread, *p_log; |
| |
| p_section = strstr(line, "---"); |
| if (p_section) |
| { |
| printline(state, line); |
| mode = MODE_ANY; |
| |
| if (section++ < 1) |
| { |
| continue; |
| } |
| else |
| { |
| break; |
| } |
| } |
| |
| p_charon = strstr(line, "charon"); |
| if (!p_charon) |
| { |
| continue; |
| } |
| |
| /* determine thread */ |
| p_thread = p_charon + 8; |
| th = atol(p_thread); |
| |
| /* determine log message */ |
| p_log = p_charon + 16; |
| if (strstr(p_log, "received packet")) |
| { |
| if (mode == MODE_DEL) |
| { |
| printline(state, line); |
| } |
| mode = MODE_ADD; |
| if (state[th] != STATE_IDLE) |
| { |
| state[th] = STATE_ERROR; |
| } |
| else |
| { |
| state[th] = STATE_BUSY; |
| } |
| } |
| if (strstr(p_log, "sending packet")) |
| { |
| if (mode == MODE_ADD) |
| { |
| printline(state, line); |
| } |
| mode = MODE_DEL; |
| if (state[th] == STATE_IDLE) |
| { |
| state[th] = STATE_ERROR; |
| } |
| else |
| { |
| state[th] = STATE_IDLE; |
| } |
| } |
| if (strstr(p_log, "parsed IKE_SA_INIT request")) |
| { |
| if (state[th] != STATE_BUSY) |
| { |
| state[th] = STATE_ERROR; |
| } |
| else |
| { |
| state[th] = STATE_INIT; |
| } |
| } |
| if (strstr(p_log, "parsed IKE_AUTH request")) |
| { |
| if (state[th] != STATE_BUSY) |
| { |
| state[th] = STATE_ERROR; |
| } |
| else |
| { |
| state[th] = STATE_AUTH; |
| } |
| } |
| if (strstr(p_log, "already processing")) |
| { |
| if (state[th] != STATE_IDLE) |
| { |
| state[th] = STATE_ERROR; |
| } |
| else |
| { |
| state[th] = STATE_RETRY; |
| } |
| printline(state, line); |
| mode = MODE_ANY; |
| state[th] = STATE_IDLE; |
| } |
| } |
| printf(" </table>\n"); |
| printf(" <p>\n"); |
| printf(" <table>\n"); |
| printf(" <tr>\n"); |
| printf(" <td class=\"init\"> I </td><td>IKE_SA_INIT Thread </td>\n"); |
| printf(" <td class=\"auth\"> A </td><td>IKE_AUTH Thread </td>\n"); |
| printf(" <td class=\"retry\"> R </td><td>Retransmit Thread </td>\n"); |
| printf(" <td class=\"busy\"> B </td><td>Busy Thread </td>\n"); |
| printf(" <td class=\"error\"> E </td><td>State Error </td>\n"); |
| printf(" </tr>\n"); |
| printf(" </table>\n"); |
| printf(" <p>\n"); |
| printf("</body>\n"); |
| printf("</html>\n"); |
| |
| fclose(fd); |
| return 0; |
| } |