2 * Netgrind -- Saving to Files
4 * (c) 2003 Martin Mares <mj@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU General Public License.
11 #include "netgrind/pkt.h"
12 #include "netgrind/netgrind.h"
18 #include <netinet/in.h>
22 void format_timestamp(byte *buf, u64 time)
25 time_t t = time / 1000000;
28 int len = strftime(buf, TIMESTAMP_LEN, "%Y-%m-%d %H:%M:%S", tm);
30 sprintf(buf+len, ".%03d", (uns)(time%1000000)/1000);
33 void sink_open(struct flow *f UNUSED, u64 when UNUSED)
37 void sink_close(struct flow *f UNUSED, int cause UNUSED, u64 when UNUSED)
41 void sink_input(struct flow *f UNUSED, int dir UNUSED, struct pkt *p)
46 struct appl_hooks appl_sink = {
56 static void save_open(struct flow *f, u64 when UNUSED)
58 struct save_state *s = xmalloc(sizeof(*s));
59 static uns save_counter;
60 for (uns dir=0; dir<2; dir++)
63 sprintf(name, "%s/%06u-%d.%d.%d.%d:%d-%d.%d.%d.%d:%d-%c", save_dir, save_counter,
64 IPQUAD(f->saddr), ntohs(f->sport), IPQUAD(f->daddr), ntohs(f->dport),
66 if (!(s->file[dir] = fopen(name, "w")))
67 die("Unable to create %s: %m", name);
73 static void save_close(struct flow *f, int cause UNUSED, u64 when UNUSED)
75 struct save_state *s = f->appl_data;
81 static void save_input(struct flow *f, int dir, struct pkt *p)
83 struct save_state *s = f->appl_data;
84 fwrite(p->data, pkt_len(p), 1, s->file[dir]);
88 struct appl_hooks appl_save = {
101 static void asave_event(struct asave_state *s, u64 time, byte *msg, ...)
106 time -= s->start_time;
107 fprintf(s->file, "%04d.%03d ", (int)(time/1000000), (int)(time%1000000)/1000);
108 vfprintf(s->file, msg, args);
112 static void asave_open(struct flow *f, u64 when)
114 struct asave_state *s = xmalloc(sizeof(*s));
115 byte name[256], stamp[TIMESTAMP_LEN];
116 static uns asave_counter;
117 sprintf(name, "%s/%06u-%d.%d.%d.%d:%d-%d.%d.%d.%d:%d", save_dir, asave_counter++,
118 IPQUAD(f->saddr), ntohs(f->sport),
119 IPQUAD(f->daddr), ntohs(f->dport));
120 if (!(s->file = fopen(name, "w")))
121 die("Unable to create %s: %m", name);
123 s->start_time = when;
124 asave_event(s, when, "Connection: %d.%d.%d.%d:%d -> %d.%d.%d.%d:%d\n",
125 IPQUAD(f->saddr), ntohs(f->sport), IPQUAD(f->daddr), ntohs(f->dport));
126 format_timestamp(stamp, when);
127 asave_event(s, when, "Initiated on: %s\n", stamp);
130 static void asave_close(struct flow *f, int cause, u64 when)
132 struct asave_state *s = f->appl_data;
133 static byte *close_reasons[] = { "Close", "Connection reset", "Timeout", "Doomsday", "Corrupted" };
134 asave_event(s, when, "Terminated: %s\n", close_reasons[cause]);
135 asave_event(s, when, "TX %Ld bytes in %Ld packets, RX %Ld bytes in %Ld packets\n",
136 f->pipe[1].stat.bytes, f->pipe[1].stat.packets,
137 f->pipe[0].stat.bytes, f->pipe[0].stat.packets);
138 asave_event(s, when, "Transferred %Ld bytes, TCP overhead %Ld bytes\n",
139 f->pipe[0].stat.bytes + f->pipe[1].stat.bytes,
140 f->stat_raw.bytes - (f->pipe[0].stat.bytes + f->pipe[1].stat.bytes));
145 static void asave_input(struct flow *f, int dir, struct pkt *p)
147 struct asave_state *s = f->appl_data;
151 asave_event(s, p->timestamp, "%s FIN\n", (dir ? ">>" : "<<"));
155 asave_event(s, p->timestamp, (dir ? ">>> " : "<<< "));
156 uns len = pkt_len(p);
158 for (uns i=0; i<len; i++)
163 else if (c >= 0x20 && c < 0x7f || c >= 0xa0)
170 fprintf(s->file, "<%02x>", c);
173 if (cnt >= asave_width+10 || (cnt == asave_width && i < len-1 && p->data[i+1] != '\n'))
176 fputc('\\', s->file);
177 fputc('\n', s->file);
179 asave_event(s, p->timestamp, (dir ? ">>> " : "<<< "));
185 fputc('\\', s->file);
186 fputc('\n', s->file);
191 struct appl_hooks appl_asave = {
193 .input = asave_input,
197 struct summary_state {
201 static void summary_open(struct flow *f, u64 when)
203 struct summary_state *s = xmalloc(sizeof(*s));
205 s->estab_time = when;
208 static void summary_close(struct flow *f, int cause, u64 when)
210 static int summary_cnt;
212 printf("# timestamp source destination elapsed close tx rx oh KB/s\n");
213 /* 2003-06-06 22:38:34.076 81.27.194.19:1165 195.113.31.123:22 1.604 OK 1991 12656 11% 8.914 */
215 struct summary_state *s = f->appl_data;
216 u64 duration = when - s->estab_time;
217 byte src[22], dst[22];
218 byte stamp[TIMESTAMP_LEN];
219 static byte *sum_causes[] = { "OK", "RE", "TO", "DD", "CO" };
220 format_timestamp(stamp, s->estab_time);
221 sprintf(src, "%d.%d.%d.%d:%d", IPQUAD(f->saddr), ntohs(f->sport));
222 sprintf(dst, "%d.%d.%d.%d:%d", IPQUAD(f->daddr), ntohs(f->dport));
223 double braw = f->stat_raw.bytes;
224 double beff = f->pipe[0].stat.bytes + f->pipe[1].stat.bytes;
225 double over = 100 * ((braw - beff) / braw);
226 double avs = duration ? ((beff / ((double)duration/1000000)) / 1024) : 1e30;
227 printf("%s %-21s %-21s %6d.%03d %s %7Ld %7Ld %3d%% ",
229 (uns)(duration/1000000), (uns)(duration%1000000)/1000, sum_causes[cause],
230 f->pipe[1].stat.bytes, f->pipe[0].stat.bytes,
231 CLAMP((int)over,0,100));
232 printf((avs < 100) ? "%6.3f" : "%6.0f", MIN(avs, 999999));
237 struct appl_hooks appl_summary = {
238 .open = summary_open,
240 .close = summary_close