blob: 04d2d25291d4d6a3638c282a7abb93142661bfa8 [file] [log] [blame]
Holger Hans Peter Freyther3b9b38c2011-05-31 17:42:13 +02001/*
2 * osmo-pcap-client code
3 *
4 * (C) 2011 by Holger Hans Peter Freyther <zecke@selfish.org>
5 * (C) 2011 by On-Waves
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include <osmo-pcap/osmo_pcap_client.h>
24#include <osmo-pcap/common.h>
25
26#include <osmocom/core/talloc.h>
27
28#include <limits.h>
29
30
Holger Hans Peter Freythercd2d3db2011-05-31 18:39:33 +020031static int pcap_read_cb(struct osmo_fd *fd, unsigned int what)
32{
33 struct osmo_pcap_client *client = fd->data;
34 struct pcap_pkthdr hdr;
35 const u_char *data;
36
37 data = pcap_next(client->handle, &hdr);
38 if (!data)
39 return -1;
Holger Hans Peter Freyther77288202011-05-31 21:19:22 +020040
41 osmo_client_send_data(client, &hdr, data);
Holger Hans Peter Freythercd2d3db2011-05-31 18:39:33 +020042 return 0;
43}
44
45static int osmo_install_filter(struct osmo_pcap_client *client)
46{
47 int rc;
48 pcap_freecode(&client->bpf);
49
50 if (!client->handle) {
51 LOGP(DCLIENT, LOGL_NOTICE,
52 "Filter will only be applied later.\n");
53 return 1;
54 }
55
56 rc = pcap_compile(client->handle, &client->bpf,
57 client->filter_string, 1, PCAP_NETMASK_UNKNOWN);
58 if (rc != 0) {
59 LOGP(DCLIENT, LOGL_ERROR,
60 "Failed to compile the filter: %s\n",
61 pcap_geterr(client->handle));
62 return rc;
63 }
64
65 rc = pcap_setfilter(client->handle, &client->bpf);
66 if (rc != 0) {
67 LOGP(DCLIENT, LOGL_ERROR,
68 "Failed to set the filter on the interface: %s\n",
69 pcap_geterr(client->handle));
70 pcap_freecode(&client->bpf);
71 return rc;
72 }
73
74 return rc;
75}
76
Holger Hans Peter Freyther3b9b38c2011-05-31 17:42:13 +020077static void free_all(struct osmo_pcap_client *client)
78{
79 if (!client->handle)
80 return;
81
Holger Hans Peter Freythercd2d3db2011-05-31 18:39:33 +020082 pcap_freecode(&client->bpf);
Holger Hans Peter Freyther3b9b38c2011-05-31 17:42:13 +020083
84 if (client->fd.fd != -1) {
85 osmo_fd_unregister(&client->fd);
86 client->fd.fd = -1;
87 }
88
89 pcap_close(client->handle);
90 client->handle = NULL;
91}
92
93int osmo_client_capture(struct osmo_pcap_client *client, const char *device)
94{
Holger Hans Peter Freythercd2d3db2011-05-31 18:39:33 +020095 int fd;
96
Holger Hans Peter Freyther3b9b38c2011-05-31 17:42:13 +020097 talloc_free(client->device);
98 free_all(client);
99
100 client->device = talloc_strdup(client, device);
101 if (!client) {
102 LOGP(DCLIENT, LOGL_ERROR, "Failed to copy string.\n");
103 return 1;
104 }
105
106 client->handle = pcap_open_live(client->device, 2000, 0,
107 1000, client->errbuf);
108 if (!client->handle) {
109 LOGP(DCLIENT, LOGL_ERROR,
110 "Failed to open the device: %s\n", client->errbuf);
111 return 2;
112 }
113
Holger Hans Peter Freythercd2d3db2011-05-31 18:39:33 +0200114 fd = pcap_fileno(client->handle);
115 if (fd == -1) {
116 LOGP(DCLIENT, LOGL_ERROR,
117 "No file descriptor provided.\n");
118 free_all(client);
119 return 3;
120 }
121
122 client->fd.fd = fd;
123 client->fd.when = BSC_FD_READ;
124 client->fd.cb = pcap_read_cb;
125 client->fd.data = client;
126 if (osmo_fd_register(&client->fd) != 0) {
127 LOGP(DCLIENT, LOGL_ERROR,
128 "Failed to register the fd.\n");
129 client->fd.fd = -1;
130 free_all(client);
131 return 4;
132 }
133
Holger Hans Peter Freyther77288202011-05-31 21:19:22 +0200134 osmo_client_send_link(client);
135
Holger Hans Peter Freythercd2d3db2011-05-31 18:39:33 +0200136 if (client->filter_string) {
137 osmo_install_filter(client);
138 }
139
Holger Hans Peter Freyther3b9b38c2011-05-31 17:42:13 +0200140 return 0;
141}
142
143int osmo_client_filter(struct osmo_pcap_client *client, const char *filter)
144{
Holger Hans Peter Freythercd2d3db2011-05-31 18:39:33 +0200145 talloc_free(client->filter_string);
146 client->filter_string = talloc_strdup(client, filter);
147 return osmo_install_filter(client);
Holger Hans Peter Freyther3b9b38c2011-05-31 17:42:13 +0200148}