]> mj.ucw.cz Git - netgrind.git/blob - netgrind/save.c
... splitting ...
[netgrind.git] / netgrind / save.c
1 /*
2  *      Netgrind -- Saving to Files
3  *
4  *      (c) 2003 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU General Public License.
8  */
9
10 #include "lib/lib.h"
11 #include "netgrind/pkt.h"
12 #include "netgrind/netgrind.h"
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17
18 struct save_state {
19   FILE *file[2];
20 };
21
22 static void save_open(struct flow *f, u64 when UNUSED)
23 {
24   struct save_state *s = xmalloc(sizeof(*s));
25   static uns save_counter;
26   for (uns dir=0; dir<2; dir++)
27     {
28       byte name[256];
29       sprintf(name, "flows/%06u-%04x:%d-%04x:%d-%c", save_counter, f->saddr, f->sport, f->daddr, f->dport, 'A' + dir);
30       if (!(s->file[dir] = fopen(name, "w")))
31         die("Unable to create %s: %m", name);
32     }
33   f->appl_data = s;
34   save_counter++;
35 }
36
37 static void save_close(struct flow *f, int cause UNUSED, u64 when UNUSED)
38 {
39   struct save_state *s = f->appl_data;
40   fclose(s->file[0]);
41   fclose(s->file[1]);
42   xfree(s);
43 }
44
45 static void save_input(struct flow *f, int dir, struct pkt *p)
46 {
47   struct save_state *s = f->appl_data;
48   fwrite(p->data, pkt_len(p), 1, s->file[dir]);
49   pkt_free(p);
50 }
51
52 struct appl_hooks appl_save = {
53   .open = save_open,
54   .input = save_input,
55   .close = save_close
56 };
57
58 uns asave_width = 80;
59
60 struct asave_state {
61   FILE *file;
62   u64 start_time;
63 };
64
65 static void asave_event(struct asave_state *s, u64 time, byte *msg, ...)
66 {
67   va_list args;
68
69   va_start(args, msg);
70   time -= s->start_time;
71   fprintf(s->file, "%04d.%03d ", (int)(time/1000000), (int)(time%1000000)%1000);
72   vfprintf(s->file, msg, args);
73   va_end(args);
74 }
75
76 static void asave_open(struct flow *f, u64 when)
77 {
78   struct asave_state *s = xmalloc(sizeof(*s));
79   byte name[256];
80   static uns asave_counter;
81   sprintf(name, "flows/%06u-%04x:%d-%04x:%d", asave_counter++, f->saddr, f->sport, f->daddr, f->dport);
82   if (!(s->file = fopen(name, "w")))
83     die("Unable to create %s: %m", name);
84   f->appl_data = s;
85   s->start_time = when;
86   asave_event(s, when, "Established\n");
87 }
88
89 static void asave_close(struct flow *f, int cause, u64 when)
90 {
91   struct asave_state *s = f->appl_data;
92   static byte *close_reasons[] = { "Closed", "Connection reset", "Timed out", "Doomsday" };
93   asave_event(s, when, "%s\n", close_reasons[cause]);
94   asave_event(s, when, "TX %Ld bytes in %Ld packets, RX %Ld bytes in %Ld packets\n",
95               f->pipe[0].
96 XXXXXXXXXXXXXXXXXXXXX
97   fclose(s->file);
98   xfree(s);
99 }
100
101 static void asave_input(struct flow *f, int dir, struct pkt *p)
102 {
103   struct asave_state *s = f->appl_data;
104   asave_event(s, p->timestamp, (dir ? ">>> " : "<<< "));
105   uns len = pkt_len(p);
106   uns cnt = 0;
107   uns last_char = 0;
108   for (uns i=0; i<len; i++)
109     {
110       if (cnt >= asave_width)
111         {
112           if (last_char != '\n')
113             fputc('\\', s->file);
114           fputc('\n', s->file);
115           asave_event(s, p->timestamp, (dir ? ">>> " : "<<< "));
116           cnt = 0;
117         }
118       uns c = p->data[i];
119       if (c == '\n')
120         cnt = ~0U;
121       else if (c >= 0x20 && c < 0x7f || c >= 0xa0)
122         {
123           fputc(c, s->file);
124           cnt++;
125         }
126       else
127         {
128           fprintf(s->file, "<%02x>", c);
129           cnt += 4;
130         }
131       last_char = c;
132     }
133   if (cnt)
134     {
135       if (last_char != '\n')
136         fputc('\\', s->file);
137       fputc('\n', s->file);
138     }
139   pkt_free(p);
140 }
141
142 struct appl_hooks appl_asave = {
143   .open = asave_open,
144   .input = asave_input,
145   .close = asave_close
146 };