2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2012 Daniel Borkmann.
5 * Subject to the GPL, version 2.
6 * Parts derived from iw, subject to ISC license.
7 * Copyright 2007, 2008 Johannes Berg
8 * Copyright 2007 Andy Lutomirski
9 * Copyright 2007 Mike Kershaw
10 * Copyright 2008-2009 Luis R. Rodriguez
19 #include <linux/nl80211.h>
20 #include <netlink/genl/genl.h>
21 #include <netlink/genl/family.h>
22 #include <netlink/genl/ctrl.h>
23 #include <netlink/msg.h>
24 #include <netlink/attr.h>
34 # define LIBNL_FAILURE NLE_FAILURE
35 # define get_nl_errmsg nl_geterror
37 # define LIBNL_FAILURE ENFILE
38 /* libnl 2.x compatibility code */
39 # define nl_sock nl_handle
41 static inline struct nl_handle
*nl_socket_alloc(void)
43 return nl_handle_alloc();
46 static inline void nl_socket_free(struct nl_handle
*h
)
51 # define get_nl_errmsg strerror
53 static inline int __genl_ctrl_alloc_cache(struct nl_handle
*h
,
54 struct nl_cache
**cache
)
56 struct nl_cache
*tmp
= genl_ctrl_alloc_cache(h
);
63 # define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache
64 #endif /* !HAVE_LIBNL_2_x */
66 struct nl80211_state
{
67 struct nl_sock
*nl_sock
;
68 struct nl_cache
*nl_cache
;
69 struct genl_family
*nl80211
;
72 static void get_mac80211_phydev(const char *device
, char *phydev_path
,
79 ret
= asprintf(&pathstr
, "/sys/class/net/%s/phy80211", device
);
81 panic("Can't generate path name string for /sys/class/net device");
83 num
= readlink(pathstr
, phydev_path
, phydev_len
);
85 if (errno
== ENOENT
|| errno
== EINVAL
)
86 panic("It's probably not a mac80211 device!\n");
87 panic("Can't readlink %s: %s!\n", pathstr
, strerror(errno
));
91 phydev_path
[min(num
, phydev_len
- 1)] = 0;
94 static inline struct nl_msg
*nl80211_nlmsg_xalloc(void)
96 struct nl_msg
*ret
= nlmsg_alloc();
98 panic("Cannot allocate nlmsg memory!\n");
102 static inline struct nl_handle
*nl80211_nl_socket_xalloc(void)
104 struct nl_handle
*ret
= nl_socket_alloc();
106 panic("Cannot allocate nl socket memory!\n");
110 static void nl80211_init(struct nl80211_state
*state
, const char *device
)
114 state
->nl_sock
= nl80211_nl_socket_xalloc();
116 ret
= genl_connect(state
->nl_sock
);
118 panic("Cannot connect generic netlink!\n");
120 ret
= genl_ctrl_alloc_cache(state
->nl_sock
, &state
->nl_cache
);
122 panic("Failed to allocate generic netlink cache: %s!",
123 get_nl_errmsg(-ret
));
125 state
->nl80211
= genl_ctrl_search_by_name(state
->nl_cache
, "nl80211");
127 panic("nl80211 not found in netlink cache!\n");
130 static void nl80211_cleanup(struct nl80211_state
*state
)
132 genl_family_put(state
->nl80211
);
134 nl_cache_free(state
->nl_cache
);
135 nl_socket_free(state
->nl_sock
);
138 static int nl80211_add_mon_if(struct nl80211_state
*state
, const char *device
,
139 const char *mondevice
)
144 ifindex
= device_ifindex(device
);
146 msg
= nl80211_nlmsg_xalloc();
148 genlmsg_put(msg
, 0, 0, genl_family_get_id(state
->nl80211
), 0,
149 0, NL80211_CMD_NEW_INTERFACE
, 0);
151 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, ifindex
);
152 NLA_PUT_STRING(msg
, NL80211_ATTR_IFNAME
, mondevice
);
153 NLA_PUT_U32(msg
, NL80211_ATTR_IFTYPE
, NL80211_IFTYPE_MONITOR
);
155 ret
= nl_send_auto_complete(state
->nl_sock
, msg
);
157 if (ret
== -LIBNL_FAILURE
) {
162 panic("Cannot send_auto_complete!\n");
165 ret
= nl_wait_for_ack(state
->nl_sock
);
167 if (ret
== -LIBNL_FAILURE
) {
172 panic("Waiting for netlink ack failed!\n");
179 panic("nla put failure!\n");
180 return -EIO
; /* dummy */
183 static int nl80211_del_mon_if(struct nl80211_state
*state
, const char *device
,
184 const char *mondevice
)
189 ifindex
= device_ifindex(mondevice
);
191 msg
= nl80211_nlmsg_xalloc();
193 genlmsg_put(msg
, 0, 0, genl_family_get_id(state
->nl80211
), 0,
194 0, NL80211_CMD_DEL_INTERFACE
, 0);
196 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, ifindex
);
198 ret
= nl_send_auto_complete(state
->nl_sock
, msg
);
200 panic("Cannot send_auto_complete!\n");
202 ret
= nl_wait_for_ack(state
->nl_sock
);
204 panic("Waiting for netlink ack failed!\n");
210 panic("nla put failure!\n");
211 return -EIO
; /* dummy */
214 void enter_rfmon_mac80211(const char *device
, char **mondev
)
219 char phydev_path
[256];
220 struct nl80211_state nlstate
;
222 /* XXX: is this already a monN device? */
223 get_mac80211_phydev(device
, phydev_path
, sizeof(phydev_path
));
224 nl80211_init(&nlstate
, device
);
226 for (n
= 0; n
< UINT_MAX
; n
++) {
229 slprintf(mondevice
, sizeof(mondevice
), "mon%u", n
);
230 ret
= nl80211_add_mon_if(&nlstate
, device
, mondevice
);
232 *mondev
= xstrdup(mondevice
);
234 flags
= device_get_flags(*mondev
);
235 flags
|= IFF_UP
| IFF_RUNNING
;
236 device_set_flags(*mondev
, flags
);
238 nl80211_cleanup(&nlstate
);
243 panic("No free monN interfaces!\n");
246 void leave_rfmon_mac80211(const char *device
, const char *mondev
)
249 struct nl80211_state nlstate
;
251 flags
= device_get_flags(mondev
);
252 flags
&= ~(IFF_UP
| IFF_RUNNING
);
253 device_set_flags(mondev
, flags
);
255 nl80211_init(&nlstate
, device
);
256 nl80211_del_mon_if(&nlstate
, device
, mondev
);
257 nl80211_cleanup(&nlstate
);