No pcap, no interfaces to monitor.
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24 #include "config.h"
25
26 #ifdef HAVE_LIBPCAP
27
28 #include "iface_monitor.h"
29
30 #ifdef HAVE_LIBNL
31
32 #include <stdio.h>
33 #include <strings.h>
34 #include <errno.h>
35
36 #include <net/if.h>
37
38 #include <netlink/msg.h>
39 #include <netlink/attr.h>
40 #include <netlink/route/link.h>
41
42 /* libnl 1.x compatibility code */
43 #ifdef HAVE_LIBNL1
44 #define nl_sock nl_handle
45 #define nl_socket_disable_seq_check nl_disable_sequence_check
46
47 static inline struct nl_handle *nl_socket_alloc(void)
48 {
49     return nl_handle_alloc();
50 }
51
52 static inline void nl_socket_free(struct nl_sock *h)
53 {
54     nl_handle_destroy(h);
55 }
56 #endif /* HAVE_LIBNL1 */
57
58 static struct nl_sock *iface_mon_sock;
59
60 static void
61 iface_mon_handler2(struct nl_object *obj, void *arg)
62 {
63     struct rtnl_link *filter;
64     struct rtnl_link *link_obj;
65     int flags, up;
66     char *ifname;
67     iface_mon_cb cb = arg;
68
69     filter = rtnl_link_alloc();
70     if (!filter) {
71         fprintf(stderr, "error allocating filter\n");
72         return;
73     }
74
75     if (nl_object_match_filter (obj, OBJ_CAST (filter)) == 0) {
76         rtnl_link_put(filter);
77         return;
78     }
79
80     link_obj = (struct rtnl_link *) obj;
81     flags = rtnl_link_get_flags (link_obj);
82     ifname = rtnl_link_get_name(link_obj);
83
84     up = (flags & IFF_UP) ? 1 : 0;
85
86     cb(ifname, up);
87
88     rtnl_link_put(filter);
89
90     return;
91 }
92
93 static int
94 iface_mon_handler(struct nl_msg *msg, void *arg)
95 {
96     nl_msg_parse (msg, &iface_mon_handler2, arg);
97     return 0;
98 }
99
100 static int
101 iface_mon_nl_init(void *arg)
102 {
103     int err;
104
105     iface_mon_sock = nl_socket_alloc();
106     if (!iface_mon_sock) {
107         fprintf(stderr, "Failed to allocate netlink socket.\n");
108         return -ENOMEM;
109     }
110
111     nl_socket_disable_seq_check(iface_mon_sock);
112
113     nl_socket_modify_cb(iface_mon_sock, NL_CB_VALID, NL_CB_CUSTOM, iface_mon_handler, arg);
114
115     if (nl_connect(iface_mon_sock, NETLINK_ROUTE)) {
116         fprintf(stderr, "Failed to connect to generic netlink.\n");
117         err = -ENOLINK;
118         goto out_handle_destroy;
119     }
120
121     nl_socket_add_membership(iface_mon_sock, RTNLGRP_LINK);
122
123     return 0;
124
125 out_handle_destroy:
126     nl_socket_free(iface_mon_sock);
127     return err;
128 }
129
130 void
131 iface_mon_event(void)
132 {
133     nl_recvmsgs_default(iface_mon_sock);
134 }
135
136 int
137 iface_mon_get_sock(void)
138 {
139     return nl_socket_get_fd(iface_mon_sock);
140 }
141
142 int
143 iface_mon_start(iface_mon_cb cb)
144 {
145     return iface_mon_nl_init(cb);
146 }
147
148 void
149 iface_mon_stop(void)
150 {
151     if(iface_mon_sock)
152         nl_socket_free(iface_mon_sock);
153     iface_mon_sock = NULL;
154 }
155
156 #else /* HAVE_LIBNL */
157
158 int
159 iface_mon_start(iface_mon_cb cb _U_)
160 {
161     return -1;
162 }
163
164 void
165 iface_mon_stop(void)
166 {
167 }
168
169 int
170 iface_mon_get_sock(void)
171 {
172     return -1;
173 }
174
175 void
176 iface_mon_event(void)
177 {
178 }
179
180 #endif /* HAVE_LIBNL */
181
182 #endif /* HAVE_LIBPCAP */