Branch data Line data Source code
1 : : /// $Id: FlowSrc.cc 4621 2007-07-10 13:37:13Z bager $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : : //
5 : : // Written by Bernhard Ager, TU Berlin (2006/2007).
6 : :
7 : : #include <stdio.h>
8 : : #include <unistd.h>
9 : : #include <fcntl.h>
10 : : #include <netdb.h>
11 : :
12 : : #include "FlowSrc.h"
13 : : #include "Net.h"
14 : : #include "netflow_pac.h"
15 : : #include <errno.h>
16 : :
17 : 0 : FlowSrc::FlowSrc()
18 : : { // TODO: v9.
19 : 0 : idle = false;
20 : 0 : data = 0;
21 : 0 : current_timestamp = next_timestamp = 0.0;
22 : 0 : netflow_analyzer = new binpac::NetFlow::NetFlow_Analyzer();
23 : 0 : }
24 : :
25 : 0 : FlowSrc::~FlowSrc()
26 : : {
27 [ # # ][ # # ]: 0 : delete netflow_analyzer;
[ # # ]
28 [ # # ][ # # ]: 0 : }
[ # # ]
29 : :
30 : 0 : void FlowSrc::GetFds(int* read, int* write, int* except)
31 : : {
32 [ # # ]: 0 : if ( selectable_fd >= 0 )
33 : 0 : *read = selectable_fd;
34 : 0 : }
35 : :
36 : 0 : double FlowSrc::NextTimestamp(double* network_time)
37 : : {
38 [ # # ][ # # ]: 0 : if ( ! data && ! ExtractNextPDU() )
[ # # ]
39 : 0 : return -1.0;
40 : : else
41 : 0 : return next_timestamp;
42 : : }
43 : :
44 : 0 : void FlowSrc::Process()
45 : : {
46 [ # # ][ # # ]: 0 : if ( ! data && ! ExtractNextPDU() )
[ # # ]
47 : 0 : return;
48 : :
49 : : // This is normally done by calling net_packet_dispatch(),
50 : : // but as we don't have a packet to dispatch ...
51 : 0 : network_time = next_timestamp;
52 : 0 : expire_timers();
53 : :
54 : 0 : netflow_analyzer->downflow()->set_exporter_ip(exporter_ip);
55 : :
56 : : // We handle exceptions in NewData (might have changed w/ new binpac).
57 : 0 : netflow_analyzer->NewData(0, data, data + pdu_len);
58 : 0 : data = 0;
59 : : }
60 : :
61 : 0 : void FlowSrc::Close()
62 : : {
63 : 0 : close(selectable_fd);
64 : 0 : }
65 : :
66 : :
67 : 0 : FlowSocketSrc::~FlowSocketSrc()
68 : : {
69 [ # # ][ # # ]: 0 : delete [] listenparms;
[ # # ]
70 [ # # ][ # # ]: 0 : }
[ # # ]
71 : :
72 : 0 : int FlowSocketSrc::ExtractNextPDU()
73 : : {
74 : : sockaddr_in from;
75 : 0 : socklen_t fromlen = sizeof(from);
76 : : pdu_len = recvfrom(selectable_fd, buffer, NF_MAX_PKT_SIZE, 0,
77 : 0 : (struct sockaddr*) &from, &fromlen);
78 [ # # ]: 0 : if ( pdu_len < 0 )
79 : : {
80 : 0 : run_time("problem reading NetFlow data from socket");
81 : 0 : data = 0;
82 : 0 : next_timestamp = -1.0;
83 : 0 : closed = 1;
84 : 0 : return 0;
85 : : }
86 : :
87 [ # # ]: 0 : if ( fromlen != sizeof(from) )
88 : : {
89 : 0 : run_time("malformed NetFlow PDU");
90 : 0 : return 0;
91 : : }
92 : :
93 : 0 : data = buffer;
94 : 0 : exporter_ip = from.sin_addr.s_addr;
95 : 0 : next_timestamp = current_time();
96 : :
97 [ # # ]: 0 : if ( next_timestamp < current_timestamp )
98 : 0 : next_timestamp = current_timestamp;
99 : : else
100 : 0 : current_timestamp = next_timestamp;
101 : :
102 : 0 : return 1;
103 : : }
104 : :
105 : 0 : FlowSocketSrc::FlowSocketSrc(const char* listen_parms)
106 : : {
107 : 0 : int n = strlen(listen_parms) + 1;
108 : :
109 : 0 : char laddr[n], port[n], ident[n];
110 : 0 : laddr[0] = port[0] = ident[0] = '\0';
111 : :
112 : 0 : int ret = sscanf(listen_parms, "%[^:]:%[^=]=%s", laddr, port, ident);
113 [ # # # # ]: 0 : if ( ret < 2 )
114 : : {
115 : : snprintf(errbuf, BRO_FLOW_ERRBUF_SIZE,
116 : : "parsing your listen-spec went nuts: laddr='%s', port='%s'\n",
117 [ # # ][ # # ]: 0 : laddr[0] ? laddr : "", port[0] ? port : "");
[ # # ][ # # ]
118 : 0 : closed = 1;
119 : 0 : return;
120 : : }
121 : :
122 [ # # ][ # # ]: 0 : const char* id = (ret == 3) ? ident : listen_parms;
123 : 0 : netflow_analyzer->downflow()->set_identifier(id);
124 : :
125 : : struct addrinfo aiprefs = {
126 : : 0, PF_INET, SOCK_DGRAM, IPPROTO_UDP, 0, NULL, NULL, NULL
127 : 0 : };
128 : 0 : struct addrinfo* ainfo = 0;
129 [ # # # # ]: 0 : if ( (ret = getaddrinfo(laddr, port, &aiprefs, &ainfo)) != 0 )
130 : : {
131 : : snprintf(errbuf, BRO_FLOW_ERRBUF_SIZE,
132 : : "getaddrinfo(%s, %s, ...): %s",
133 : 0 : laddr, port, gai_strerror(ret));
134 : 0 : closed = 1;
135 : : return;
136 : : }
137 : :
138 [ # # ][ # # ]: 0 : if ( (selectable_fd = socket (PF_INET, SOCK_DGRAM, 0)) < 0 )
139 : : {
140 : : snprintf(errbuf, BRO_FLOW_ERRBUF_SIZE,
141 : 0 : "socket: %s", strerror(errno));
142 : 0 : closed = 1;
143 : 0 : goto cleanup;
144 : : }
145 : :
146 [ # # ][ # # ]: 0 : if ( bind (selectable_fd, ainfo->ai_addr, ainfo->ai_addrlen) < 0 )
147 : : {
148 : : snprintf(errbuf, BRO_FLOW_ERRBUF_SIZE,
149 : 0 : "bind: %s", strerror(errno));
150 : 0 : closed = 1;
151 : 0 : goto cleanup;
152 : : }
153 : :
154 : 0 : cleanup:
155 [ # # ][ # # ]: 0 : freeaddrinfo(ainfo);
156 : 0 : }
157 : :
158 : :
159 : 0 : FlowFileSrc::~FlowFileSrc()
160 : : {
161 [ # # ][ # # ]: 0 : delete [] readfile;
[ # # ]
162 [ # # ][ # # ]: 0 : }
[ # # ]
163 : :
164 : 0 : int FlowFileSrc::ExtractNextPDU()
165 : : {
166 : : FlowFileSrcPDUHeader pdu_header;
167 : :
168 [ # # ]: 0 : if ( read(selectable_fd, &pdu_header, sizeof(pdu_header)) <
169 : : int(sizeof(pdu_header)) )
170 : 0 : return Error(errno, "read header");
171 : :
172 [ # # ]: 0 : if ( pdu_header.pdu_length > NF_MAX_PKT_SIZE )
173 : : {
174 : 0 : run_time("NetFlow packet too long");
175 : :
176 : : // Safely skip over the too-long PDU.
177 [ # # ]: 0 : if ( lseek(selectable_fd, pdu_header.pdu_length, SEEK_CUR) < 0 )
178 : 0 : return Error(errno, "lseek");
179 : 0 : return 0;
180 : : }
181 : :
182 [ # # ]: 0 : if ( read(selectable_fd, buffer, pdu_header.pdu_length) <
183 : : pdu_header.pdu_length )
184 : 0 : return Error(errno, "read data");
185 : :
186 [ # # ]: 0 : if ( next_timestamp < pdu_header.network_time )
187 : : {
188 : 0 : next_timestamp = pdu_header.network_time;
189 : 0 : current_timestamp = pdu_header.network_time;
190 : : }
191 : : else
192 : 0 : current_timestamp = next_timestamp;
193 : :
194 : 0 : data = buffer;
195 : 0 : pdu_len = pdu_header.pdu_length;
196 : 0 : exporter_ip = pdu_header.ipaddr;
197 : :
198 : 0 : return 1;
199 : : }
200 : :
201 : 0 : FlowFileSrc::FlowFileSrc(const char* readfile)
202 : : {
203 : 0 : int n = strlen(readfile) + 1;
204 : 0 : char ident[n];
205 : 0 : this->readfile = new char[n];
206 : :
207 : 0 : int ret = sscanf(readfile, "%[^=]=%s", this->readfile, ident);
208 [ # # ][ # # ]: 0 : const char* id = (ret == 2) ? ident : this->readfile;
209 : 0 : netflow_analyzer->downflow()->set_identifier(id);
210 : :
211 : 0 : selectable_fd = open(this->readfile, O_RDONLY);
212 [ # # # # ]: 0 : if ( selectable_fd < 0 )
213 : : {
214 : 0 : closed = 1;
215 : : snprintf(errbuf, BRO_FLOW_ERRBUF_SIZE,
216 : 0 : "open: %s", strerror(errno));
217 : : }
218 : 0 : }
219 : :
220 : 0 : int FlowFileSrc::Error(int errlvl, const char* errmsg)
221 : : {
222 : : snprintf(errbuf, BRO_FLOW_ERRBUF_SIZE,
223 : 0 : "%s: %s", errmsg, strerror(errlvl));
224 : 0 : data = 0;
225 : 0 : next_timestamp = -1.0;
226 : 0 : closed = 1;
227 : 0 : return 0;
228 [ + - ][ + - ]: 6 : }
|