proto_ipv4: don't trim length of pkt_buff
[netsniff-ng.git] / src / mac80211.c
blobec2d9650d8118f78a4042c28a4eae9130d6c926a
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 <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>
26 #include "die.h"
27 #include "xsys.h"
28 #include "xstring.h"
29 #include "mac80211.h"
30 #include "xmalloc.h"
31 #include "built_in.h"
33 #ifdef HAVE_LIBNL_2_x
34 # define LIBNL_FAILURE NLE_FAILURE
35 # define get_nl_errmsg nl_geterror
36 #else
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)
48 nl_handle_destroy(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);
57 if (!tmp)
58 return -ENOMEM;
59 *cache = tmp;
60 return 0;
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,
73 size_t phydev_len)
75 int ret;
76 char *pathstr;
77 ssize_t num;
79 ret = asprintf(&pathstr, "/sys/class/net/%s/phy80211", device);
80 if (ret < 0)
81 panic("Can't generate path name string for /sys/class/net device");
83 num = readlink(pathstr, phydev_path, phydev_len);
84 if (num < 0) {
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));
90 xfree(pathstr);
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();
97 if (!ret)
98 panic("Cannot allocate nlmsg memory!\n");
99 return ret;
102 static inline struct nl_handle *nl80211_nl_socket_xalloc(void)
104 struct nl_handle *ret = nl_socket_alloc();
105 if (!ret)
106 panic("Cannot allocate nl socket memory!\n");
107 return ret;
110 static void nl80211_init(struct nl80211_state *state, const char *device)
112 int ret;
114 state->nl_sock = nl80211_nl_socket_xalloc();
116 ret = genl_connect(state->nl_sock);
117 if (ret)
118 panic("Cannot connect generic netlink!\n");
120 ret = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache);
121 if (ret < 0)
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");
126 if (!state->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)
141 int ifindex, ret;
142 struct nl_msg *msg;
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);
156 if (ret < 0) {
157 if (ret == -LIBNL_FAILURE) {
158 nlmsg_free(msg);
159 return -EBUSY;
162 panic("Cannot send_auto_complete!\n");
165 ret = nl_wait_for_ack(state->nl_sock);
166 if (ret < 0) {
167 if (ret == -LIBNL_FAILURE) {
168 nlmsg_free(msg);
169 return -EBUSY;
172 panic("Waiting for netlink ack failed!\n");
175 nlmsg_free(msg);
176 return 0;
178 nla_put_failure:
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)
186 int ifindex, ret;
187 struct nl_msg *msg;
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);
199 if (ret < 0)
200 panic("Cannot send_auto_complete!\n");
202 ret = nl_wait_for_ack(state->nl_sock);
203 if (ret < 0)
204 panic("Waiting for netlink ack failed!\n");
206 nlmsg_free(msg);
207 return 0;
209 nla_put_failure:
210 panic("nla put failure!\n");
211 return -EIO; /* dummy */
214 void enter_rfmon_mac80211(const char *device, char **mondev)
216 int ret;
217 short flags;
218 uint32_t n;
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++) {
227 char mondevice[32];
229 slprintf(mondevice, sizeof(mondevice), "mon%u", n);
230 ret = nl80211_add_mon_if(&nlstate, device, mondevice);
231 if (ret == 0) {
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);
239 return;
243 panic("No free monN interfaces!\n");
246 void leave_rfmon_mac80211(const char *device, const char *mondev)
248 short flags;
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);