Bluetooth: Highlight correct bytes in some SDP trees (Part 2). Bug 8700 (https:...
[metze/wireshark/wip.git] / iface_monitor.c
1 /* iface_monitor.c
2  * interface monitor by Pontus Fuchs <pontus.fuchs@gmail.com>
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 #include "config.h"
25
26 #ifdef HAVE_LIBPCAP
27
28 #include "iface_monitor.h"
29
30 #if defined(HAVE_LIBNL)
31
32 /*
33  * Linux with libnl.
34  */
35
36 #include <stdio.h>
37 #include <strings.h>
38 #include <errno.h>
39
40 #include <netlink/msg.h>
41 #include <netlink/attr.h>
42 #include <netlink/route/link.h>
43
44 #ifndef IFF_UP
45 /*
46  * Apparently, some versions of libnl drag in headers that define IFF_UP
47  * and others don't.  Include <net/if.h> iff IFF_UP isn't already defined,
48  * so that if <linux/if.h> has been included by some or all of the
49  * netlink headers, we don't include <net/if.h> and get a bunch of
50  * complaints about various structures being redefined.
51  */
52 #include <net/if.h>
53 #endif
54
55 /* libnl 1.x compatibility code */
56 #ifdef HAVE_LIBNL1
57 #define nl_sock nl_handle
58 #define nl_socket_disable_seq_check nl_disable_sequence_check
59
60 static inline struct nl_handle *nl_socket_alloc(void)
61 {
62     return nl_handle_alloc();
63 }
64
65 static inline void nl_socket_free(struct nl_sock *h)
66 {
67     nl_handle_destroy(h);
68 }
69 #endif /* HAVE_LIBNL1 */
70
71 static struct nl_sock *iface_mon_sock;
72
73 static void
74 iface_mon_handler2(struct nl_object *obj, void *arg)
75 {
76     struct rtnl_link *filter;
77     struct rtnl_link *link_obj;
78     int flags, up;
79     char *ifname;
80     iface_mon_cb cb = (iface_mon_cb)arg;
81
82     filter = rtnl_link_alloc();
83     if (!filter) {
84         fprintf(stderr, "error allocating filter\n");
85         return;
86     }
87
88     if (nl_object_match_filter (obj, OBJ_CAST (filter)) == 0) {
89         rtnl_link_put(filter);
90         return;
91     }
92
93     link_obj = (struct rtnl_link *) obj;
94     flags = rtnl_link_get_flags (link_obj);
95     ifname = rtnl_link_get_name(link_obj);
96
97     /*
98      * You can't bind a PF_PACKET socket to an interface that's not
99      * up, so an interface going down is an "interface should be
100      * removed" indication.
101      *
102      * XXX - what indication, if any, do we get if the interface
103      * *completely goes away*?
104      *
105      * XXX - can we get events if an interface's link-layer or
106      * network addresses change?
107      */
108     up = (flags & IFF_UP) ? 1 : 0;
109
110     cb(ifname, up);
111
112     rtnl_link_put(filter);
113
114     return;
115 }
116
117 static int
118 iface_mon_handler(struct nl_msg *msg, void *arg)
119 {
120     nl_msg_parse (msg, &iface_mon_handler2, arg);
121     return 0;
122 }
123
124 void
125 iface_mon_event(void)
126 {
127     nl_recvmsgs_default(iface_mon_sock);
128 }
129
130 int
131 iface_mon_get_sock(void)
132 {
133     return nl_socket_get_fd(iface_mon_sock);
134 }
135
136 int
137 iface_mon_start(iface_mon_cb cb)
138 {
139     int err;
140
141     iface_mon_sock = nl_socket_alloc();
142     if (!iface_mon_sock) {
143         fprintf(stderr, "Failed to allocate netlink socket.\n");
144         return -ENOMEM;
145     }
146
147     nl_socket_disable_seq_check(iface_mon_sock);
148
149     nl_socket_modify_cb(iface_mon_sock, NL_CB_VALID, NL_CB_CUSTOM, iface_mon_handler, cb);
150
151     if (nl_connect(iface_mon_sock, NETLINK_ROUTE)) {
152         fprintf(stderr, "Failed to connect to generic netlink.\n");
153         err = -ENOLINK;
154         goto out_handle_destroy;
155     }
156
157     nl_socket_add_membership(iface_mon_sock, RTNLGRP_LINK);
158
159     return 0;
160
161 out_handle_destroy:
162     nl_socket_free(iface_mon_sock);
163     return err;
164 }
165
166 void
167 iface_mon_stop(void)
168 {
169     if(iface_mon_sock)
170         nl_socket_free(iface_mon_sock);
171     iface_mon_sock = NULL;
172 }
173
174 #elif defined(__APPLE__)
175
176 /*
177  * OS X.
178  */
179
180 #include <stddef.h>
181 #include <stdio.h>
182 #include <errno.h>
183 #include <unistd.h>
184
185 #include <sys/socket.h>
186 #include <sys/ioctl.h>
187 #include <sys/types.h>
188 #include <net/if.h>
189 #include <sys/kern_event.h>
190
191 #include <glib.h>
192
193 static int s;
194 static iface_mon_cb callback;
195
196 int
197 iface_mon_start(iface_mon_cb cb)
198 {
199     int ret;
200     struct kev_request key;
201
202     /* Create a socket of type PF_SYSTEM to listen for events. */
203     s = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
204     if (s == -1)
205         return -errno;
206
207     /*
208      * Ask for DLIL messages.
209      *
210      * XXX - also ask for KEV_INET_SUBCLASS and KEV_INET6_SUBCLASS,
211      * to detect new or changed network addresses, so those can be
212      * updated as well?  Can we specify multiple filters on a socket,
213      * or must we specify KEV_ANY_SUBCLASS and filter the events after
214      * receiving them?
215      */
216     key.vendor_code = KEV_VENDOR_APPLE;
217     key.kev_class = KEV_NETWORK_CLASS;
218     key.kev_subclass = KEV_DL_SUBCLASS;
219     if (ioctl(s, SIOCSKEVFILT, &key) == -1) {
220         ret = -errno;
221         close(s);
222         return ret;
223     }
224
225     callback = cb;
226     return 0;
227 }
228
229 void
230 iface_mon_stop(void)
231 {
232     close(s);
233 }
234
235 int
236 iface_mon_get_sock(void)
237 {
238     return s;
239 }
240
241 /*
242  * Size of buffer for kernel network event.
243  */
244 #define NET_EVENT_DATA_SIZE     (KEV_MSG_HEADER_SIZE + sizeof (struct net_event_data))
245
246 void
247 iface_mon_event(void)
248 {
249     char msg[NET_EVENT_DATA_SIZE];
250     ssize_t received;
251     struct kern_event_msg *kem;
252     struct net_event_data *evd;
253     size_t evd_len;
254     char ifr_name[IFNAMSIZ];
255
256     received = recv(s, msg, sizeof msg, 0);
257     if (received < 0) {
258         /* Error - ignore. */
259         return;
260     }
261     if ((size_t)received < sizeof msg) {
262         /* Short read - ignore. */
263         return;
264     }
265     kem = (struct kern_event_msg *)msg;
266     evd_len = kem->total_size - KEV_MSG_HEADER_SIZE;
267     if (evd_len != sizeof (struct net_event_data)) {
268         /* Length of the message is bogus. */
269         return;
270     }
271     evd = (struct net_event_data *)&kem->event_data[0];
272     g_snprintf(ifr_name, IFNAMSIZ, "%s%u", evd->if_name, evd->if_unit);
273
274     /*
275      * Check type of event.
276      *
277      * Note: if we also ask for KEV_INET_SUBCLASS, we will get
278      * events with keys
279      *
280      *    KEV_INET_NEW_ADDR
281      *    KEV_INET_CHANGED_ADDR
282      *    KEV_INET_CHANGED_ADDR
283      *    KEV_INET_SIFDSTADDR
284      *    KEV_INET_SIFBRDADDR
285      *    KEV_INET_SIFNETMASK
286      *
287      * reflecting network address changes, with the data being a
288      * struct kev_in_data rather than struct net_event_data, and
289      * if we also ask for KEV_INET6_SUBCLASS, we will get events
290      * with keys
291      *
292      *    KEV_INET6_NEW_LL_ADDR
293      *    KEV_INET6_NEW_USER_ADDR
294      *    KEV_INET6_NEW_RTADV_ADDR
295      *    KEV_INET6_ADDR_DELETED
296      *
297      * with the data being a struct kev_in6_data.
298      */
299     switch (kem->event_code) {
300
301     case KEV_DL_IF_ATTACHED:
302         /*
303          * A new interface has arrived.
304          *
305          * XXX - what we really want is "a new BPFable interface
306          * has arrived", but that's not available.  While we're
307          * asking for additional help from BPF, it'd also be
308          * nice if we could ask it for a list of all interfaces
309          * that have had bpfattach()/bpf_attach() done on them,
310          * so we don't have to try to open the device in order
311          * to see whether we should show it as something on
312          * which we can capture.
313          */
314         callback(ifr_name, 1);
315         break;
316
317     case KEV_DL_IF_DETACHED:
318         /*
319          * An existing interface has been removed.
320          *
321          * XXX - use KEV_DL_IF_DETACHING instead, as that's
322          * called shortly after bpfdetach() is called, and
323          * bpfdetach() makes an interface no longer BPFable,
324          * and that's what we *really* care about.
325          */
326         callback(ifr_name, 0);
327         break;
328
329     default:
330         /*
331          * Is there any reason to care about:
332          *
333          *    KEV_DL_LINK_ON
334          *    KEV_DL_LINK_OFF
335          *    KEV_DL_SIFFLAGS
336          *    KEV_DL_LINK_ADDRESS_CHANGED
337          *    KEV_DL_IFCAP_CHANGED
338          *
339          * or any of the other events?  On Snow Leopard and, I think,
340          * earlier releases, you can't attach a BPF device to an
341          * interface that's not up, so KEV_DL_SIFFLAGS might be
342          * worth listening to so that we only say "here's a new
343          * interface" when it goes up; on Lion (and possibly Mountain
344          * Lion), an interface doesn't have to be up in order to
345          * have a BPF device attached to it.
346          */
347         break;
348     }
349 }
350
351 #else /* don't have something we support */
352
353 int
354 iface_mon_start(iface_mon_cb cb _U_)
355 {
356     return -1;
357 }
358
359 void
360 iface_mon_stop(void)
361 {
362 }
363
364 int
365 iface_mon_get_sock(void)
366 {
367     return -1;
368 }
369
370 void
371 iface_mon_event(void)
372 {
373 }
374
375 #endif /* HAVE_LIBNL */
376
377 #endif /* HAVE_LIBPCAP */