2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012 Daniel Borkmann.
4 * Subject to the GPL, version 2.
5 * Parts derived from iw, subject to ISC license.
6 * Copyright 2007, 2008 Johannes Berg
7 * Copyright 2007 Andy Lutomirski
8 * Copyright 2007 Mike Kershaw
9 * Copyright 2008-2009 Luis R. Rodriguez
18 #include <sys/socket.h>
20 #include <linux/nl80211.h>
21 #include <netlink/genl/genl.h>
22 #include <netlink/genl/family.h>
23 #include <netlink/genl/ctrl.h>
24 #include <netlink/msg.h>
25 #include <netlink/attr.h>
33 struct nl80211_state
{
34 struct nl_sock
*nl_sock
;
35 struct nl_cache
*nl_cache
;
36 struct genl_family
*nl80211
;
39 static void get_mac80211_phydev(const char *device
, char *phydev_path
,
46 ret
= asprintf(&pathstr
, "/sys/class/net/%s/phy80211", device
);
48 panic("Can't generate path name string for /sys/class/net device");
50 num
= readlink(pathstr
, phydev_path
, phydev_len
);
52 if (errno
== ENOENT
|| errno
== EINVAL
)
53 panic("It's probably not a mac80211 device!\n");
54 panic("Can't readlink %s: %s!\n", pathstr
, strerror(errno
));
58 phydev_path
[min_t(size_t, num
, phydev_len
- 1)] = 0;
61 static inline struct nl_msg
*nl80211_nlmsg_xalloc(void)
63 struct nl_msg
*ret
= nlmsg_alloc();
65 panic("Cannot allocate nlmsg memory!\n");
69 static inline struct nl_sock
*nl80211_nl_socket_xalloc(void)
71 struct nl_sock
*ret
= nl_socket_alloc();
73 panic("Cannot allocate nl socket memory!\n");
77 static void nl80211_init(struct nl80211_state
*state
)
81 state
->nl_sock
= nl80211_nl_socket_xalloc();
83 ret
= genl_connect(state
->nl_sock
);
85 panic("Cannot connect generic netlink!\n");
87 ret
= genl_ctrl_alloc_cache(state
->nl_sock
, &state
->nl_cache
);
89 panic("Failed to allocate generic netlink cache: %s!",
92 state
->nl80211
= genl_ctrl_search_by_name(state
->nl_cache
, "nl80211");
94 panic("nl80211 not found in netlink cache!\n");
97 static void nl80211_cleanup(struct nl80211_state
*state
)
99 genl_family_put(state
->nl80211
);
101 nl_cache_free(state
->nl_cache
);
102 nl_socket_free(state
->nl_sock
);
105 static int nl80211_wait_handler(struct nl_msg
*msg __maybe_unused
, void *arg
)
114 static int nl80211_error_handler(struct sockaddr_nl
*nla __maybe_unused
,
115 struct nlmsgerr
*err
,
116 void *arg __maybe_unused
)
118 panic("nl80211 returned with error (%d): %s\n", err
->error
,
119 nl_geterror(err
->error
));
122 static int nl80211_add_mon_if(struct nl80211_state
*state
, const char *device
,
123 const char *mondevice
)
127 struct nl_cb
*cb
= NULL
;
130 ifindex
= device_ifindex(device
);
132 msg
= nl80211_nlmsg_xalloc();
134 genlmsg_put(msg
, 0, 0, genl_family_get_id(state
->nl80211
), 0,
135 0, NL80211_CMD_NEW_INTERFACE
, 0);
137 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, ifindex
);
138 NLA_PUT_STRING(msg
, NL80211_ATTR_IFNAME
, mondevice
);
139 NLA_PUT_U32(msg
, NL80211_ATTR_IFTYPE
, NL80211_IFTYPE_MONITOR
);
141 ret
= nl_send_auto_complete(state
->nl_sock
, msg
);
143 if (ret
== -ENFILE
) {
148 panic("Cannot send_auto_complete!\n");
151 cb
= nl_cb_alloc(NL_CB_CUSTOM
);
153 panic("Cannot alloc nl_cb!\n");
155 nl_cb_set(cb
, NL_CB_ACK
, NL_CB_CUSTOM
, nl80211_wait_handler
, &finished
);
156 nl_cb_err(cb
, NL_CB_CUSTOM
, nl80211_error_handler
, NULL
);
158 nl_recvmsgs(state
->nl_sock
, cb
);
161 ret
= nl_wait_for_ack(state
->nl_sock
);
163 if (ret
== -ENFILE
) {
168 panic("Waiting for netlink ack failed!\n");
177 panic("nla put failure!\n");
178 return -EIO
; /* dummy */
181 static int nl80211_del_mon_if(struct nl80211_state
*state
,
182 const char *mondevice
)
187 ifindex
= device_ifindex(mondevice
);
189 msg
= nl80211_nlmsg_xalloc();
191 genlmsg_put(msg
, 0, 0, genl_family_get_id(state
->nl80211
), 0,
192 0, NL80211_CMD_DEL_INTERFACE
, 0);
194 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, ifindex
);
196 ret
= nl_send_auto_complete(state
->nl_sock
, msg
);
198 panic("Cannot send_auto_complete!\n");
200 ret
= nl_wait_for_ack(state
->nl_sock
);
202 panic("Waiting for netlink ack failed!\n");
208 panic("nla put failure!\n");
209 return -EIO
; /* dummy */
212 void enter_rfmon_mac80211(const char *device
, char **mondev
)
217 char phydev_path
[256];
218 struct nl80211_state nlstate
;
220 /* XXX: is this already a monN device? */
221 get_mac80211_phydev(device
, phydev_path
, sizeof(phydev_path
));
222 nl80211_init(&nlstate
);
224 for (n
= 0; n
< UINT_MAX
; n
++) {
227 slprintf(mondevice
, sizeof(mondevice
), "mon%u", n
);
229 if (__device_ifindex(mondevice
) > 0)
232 ret
= nl80211_add_mon_if(&nlstate
, device
, mondevice
);
234 *mondev
= xstrdup(mondevice
);
236 flags
= device_get_flags(*mondev
);
237 flags
|= IFF_UP
| IFF_RUNNING
;
238 device_set_flags(*mondev
, flags
);
240 nl80211_cleanup(&nlstate
);
245 panic("No free monN interfaces!\n");
248 void leave_rfmon_mac80211(const char *mondev
)
251 struct nl80211_state nlstate
;
253 flags
= device_get_flags(mondev
);
254 flags
&= ~(IFF_UP
| IFF_RUNNING
);
255 device_set_flags(mondev
, flags
);
257 nl80211_init(&nlstate
);
258 nl80211_del_mon_if(&nlstate
, mondev
);
259 nl80211_cleanup(&nlstate
);