docs: minor: fix headline of mz
[netsniff-ng.git] / src / mac80211.c
blob001ebf76380aa34eaa260e8fa693a8880c0d3ece
1 /*
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
13 #define _GNU_SOURCE
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <errno.h>
17 #include <string.h>
18 #include <limits.h>
19 #include <linux/nl80211.h>
20 #include <libnl3/netlink/genl/genl.h>
21 #include <libnl3/netlink/genl/family.h>
22 #include <libnl3/netlink/genl/ctrl.h>
23 #include <libnl3/netlink/msg.h>
24 #include <libnl3/netlink/attr.h>
26 #include "die.h"
27 #include "xutils.h"
28 #include "mac80211.h"
29 #include "xmalloc.h"
30 #include "built_in.h"
32 struct nl80211_state {
33 struct nl_sock *nl_sock;
34 struct nl_cache *nl_cache;
35 struct genl_family *nl80211;
38 static void get_mac80211_phydev(const char *device, char *phydev_path,
39 size_t phydev_len)
41 int ret;
42 char *pathstr;
43 ssize_t num;
45 ret = asprintf(&pathstr, "/sys/class/net/%s/phy80211", device);
46 if (ret < 0)
47 panic("Can't generate path name string for /sys/class/net device");
49 num = readlink(pathstr, phydev_path, phydev_len);
50 if (num < 0) {
51 if (errno == ENOENT || errno == EINVAL)
52 panic("It's probably not a mac80211 device!\n");
53 panic("Can't readlink %s: %s!\n", pathstr, strerror(errno));
56 xfree(pathstr);
57 phydev_path[min(num, phydev_len - 1)] = 0;
60 static inline struct nl_msg *nl80211_nlmsg_xalloc(void)
62 struct nl_msg *ret = nlmsg_alloc();
63 if (!ret)
64 panic("Cannot allocate nlmsg memory!\n");
65 return ret;
68 static inline struct nl_sock *nl80211_nl_socket_xalloc(void)
70 struct nl_sock *ret = nl_socket_alloc();
71 if (!ret)
72 panic("Cannot allocate nl socket memory!\n");
73 return ret;
76 static void nl80211_init(struct nl80211_state *state, const char *device)
78 int ret;
80 state->nl_sock = nl80211_nl_socket_xalloc();
82 ret = genl_connect(state->nl_sock);
83 if (ret)
84 panic("Cannot connect generic netlink!\n");
86 ret = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache);
87 if (ret < 0)
88 panic("Failed to allocate generic netlink cache: %s!",
89 nl_geterror(-ret));
91 state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211");
92 if (!state->nl80211)
93 panic("nl80211 not found in netlink cache!\n");
96 static void nl80211_cleanup(struct nl80211_state *state)
98 genl_family_put(state->nl80211);
100 nl_cache_free(state->nl_cache);
101 nl_socket_free(state->nl_sock);
104 static int nl80211_add_mon_if(struct nl80211_state *state, const char *device,
105 const char *mondevice)
107 int ifindex, ret;
108 struct nl_msg *msg;
110 ifindex = device_ifindex(device);
112 msg = nl80211_nlmsg_xalloc();
114 genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
115 0, NL80211_CMD_NEW_INTERFACE, 0);
117 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
118 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice);
119 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
121 ret = nl_send_auto_complete(state->nl_sock, msg);
122 if (ret < 0) {
123 if (ret == -ENFILE) {
124 nlmsg_free(msg);
125 return -EBUSY;
128 panic("Cannot send_auto_complete!\n");
131 ret = nl_wait_for_ack(state->nl_sock);
132 if (ret < 0) {
133 if (ret == -ENFILE) {
134 nlmsg_free(msg);
135 return -EBUSY;
138 panic("Waiting for netlink ack failed!\n");
141 nlmsg_free(msg);
142 return 0;
144 nla_put_failure:
145 panic("nla put failure!\n");
146 return -EIO; /* dummy */
149 static int nl80211_del_mon_if(struct nl80211_state *state, const char *device,
150 const char *mondevice)
152 int ifindex, ret;
153 struct nl_msg *msg;
155 ifindex = device_ifindex(mondevice);
157 msg = nl80211_nlmsg_xalloc();
159 genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
160 0, NL80211_CMD_DEL_INTERFACE, 0);
162 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
164 ret = nl_send_auto_complete(state->nl_sock, msg);
165 if (ret < 0)
166 panic("Cannot send_auto_complete!\n");
168 ret = nl_wait_for_ack(state->nl_sock);
169 if (ret < 0)
170 panic("Waiting for netlink ack failed!\n");
172 nlmsg_free(msg);
173 return 0;
175 nla_put_failure:
176 panic("nla put failure!\n");
177 return -EIO; /* dummy */
180 void enter_rfmon_mac80211(const char *device, char **mondev)
182 int ret;
183 short flags;
184 uint32_t n;
185 char phydev_path[256];
186 struct nl80211_state nlstate;
188 /* XXX: is this already a monN device? */
189 get_mac80211_phydev(device, phydev_path, sizeof(phydev_path));
190 nl80211_init(&nlstate, device);
192 for (n = 0; n < UINT_MAX; n++) {
193 char mondevice[32];
195 slprintf(mondevice, sizeof(mondevice), "mon%u", n);
196 ret = nl80211_add_mon_if(&nlstate, device, mondevice);
197 if (ret == 0) {
198 *mondev = xstrdup(mondevice);
200 flags = device_get_flags(*mondev);
201 flags |= IFF_UP | IFF_RUNNING;
202 device_set_flags(*mondev, flags);
204 nl80211_cleanup(&nlstate);
205 return;
209 panic("No free monN interfaces!\n");
212 void leave_rfmon_mac80211(const char *device, const char *mondev)
214 short flags;
215 struct nl80211_state nlstate;
217 flags = device_get_flags(mondev);
218 flags &= ~(IFF_UP | IFF_RUNNING);
219 device_set_flags(mondev, flags);
221 nl80211_init(&nlstate, device);
222 nl80211_del_mon_if(&nlstate, device, mondev);
223 nl80211_cleanup(&nlstate);