Merge pull request #59 from electronjoe/graceful-SIGTERM-handling
[netsniff-ng-old.git] / mac80211.c
blob14bcc931f5569a7af585426432933d902db168a8
1 /*
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
12 #define _GNU_SOURCE
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <limits.h>
18 #include <linux/nl80211.h>
19 #include <libnl3/netlink/genl/genl.h>
20 #include <libnl3/netlink/genl/family.h>
21 #include <libnl3/netlink/genl/ctrl.h>
22 #include <libnl3/netlink/msg.h>
23 #include <libnl3/netlink/attr.h>
25 #include "die.h"
26 #include "xutils.h"
27 #include "mac80211.h"
28 #include "xmalloc.h"
29 #include "built_in.h"
31 struct nl80211_state {
32 struct nl_sock *nl_sock;
33 struct nl_cache *nl_cache;
34 struct genl_family *nl80211;
37 static void get_mac80211_phydev(const char *device, char *phydev_path,
38 size_t phydev_len)
40 int ret;
41 char *pathstr;
42 ssize_t num;
44 ret = asprintf(&pathstr, "/sys/class/net/%s/phy80211", device);
45 if (ret < 0)
46 panic("Can't generate path name string for /sys/class/net device");
48 num = readlink(pathstr, phydev_path, phydev_len);
49 if (num < 0) {
50 if (errno == ENOENT || errno == EINVAL)
51 panic("It's probably not a mac80211 device!\n");
52 panic("Can't readlink %s: %s!\n", pathstr, strerror(errno));
55 xfree(pathstr);
56 phydev_path[min(num, phydev_len - 1)] = 0;
59 static inline struct nl_msg *nl80211_nlmsg_xalloc(void)
61 struct nl_msg *ret = nlmsg_alloc();
62 if (!ret)
63 panic("Cannot allocate nlmsg memory!\n");
64 return ret;
67 static inline struct nl_sock *nl80211_nl_socket_xalloc(void)
69 struct nl_sock *ret = nl_socket_alloc();
70 if (!ret)
71 panic("Cannot allocate nl socket memory!\n");
72 return ret;
75 static void nl80211_init(struct nl80211_state *state, const char *device)
77 int ret;
79 state->nl_sock = nl80211_nl_socket_xalloc();
81 ret = genl_connect(state->nl_sock);
82 if (ret)
83 panic("Cannot connect generic netlink!\n");
85 ret = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache);
86 if (ret < 0)
87 panic("Failed to allocate generic netlink cache: %s!",
88 nl_geterror(-ret));
90 state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211");
91 if (!state->nl80211)
92 panic("nl80211 not found in netlink cache!\n");
95 static void nl80211_cleanup(struct nl80211_state *state)
97 genl_family_put(state->nl80211);
99 nl_cache_free(state->nl_cache);
100 nl_socket_free(state->nl_sock);
103 static int nl80211_add_mon_if(struct nl80211_state *state, const char *device,
104 const char *mondevice)
106 int ifindex, ret;
107 struct nl_msg *msg;
109 ifindex = device_ifindex(device);
111 msg = nl80211_nlmsg_xalloc();
113 genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
114 0, NL80211_CMD_NEW_INTERFACE, 0);
116 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
117 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice);
118 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
120 ret = nl_send_auto_complete(state->nl_sock, msg);
121 if (ret < 0) {
122 if (ret == -ENFILE) {
123 nlmsg_free(msg);
124 return -EBUSY;
127 panic("Cannot send_auto_complete!\n");
130 ret = nl_wait_for_ack(state->nl_sock);
131 if (ret < 0) {
132 if (ret == -ENFILE) {
133 nlmsg_free(msg);
134 return -EBUSY;
137 panic("Waiting for netlink ack failed!\n");
140 nlmsg_free(msg);
141 return 0;
143 nla_put_failure:
144 panic("nla put failure!\n");
145 return -EIO; /* dummy */
148 static int nl80211_del_mon_if(struct nl80211_state *state, const char *device,
149 const char *mondevice)
151 int ifindex, ret;
152 struct nl_msg *msg;
154 ifindex = device_ifindex(mondevice);
156 msg = nl80211_nlmsg_xalloc();
158 genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
159 0, NL80211_CMD_DEL_INTERFACE, 0);
161 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
163 ret = nl_send_auto_complete(state->nl_sock, msg);
164 if (ret < 0)
165 panic("Cannot send_auto_complete!\n");
167 ret = nl_wait_for_ack(state->nl_sock);
168 if (ret < 0)
169 panic("Waiting for netlink ack failed!\n");
171 nlmsg_free(msg);
172 return 0;
174 nla_put_failure:
175 panic("nla put failure!\n");
176 return -EIO; /* dummy */
179 void enter_rfmon_mac80211(const char *device, char **mondev)
181 int ret;
182 short flags;
183 uint32_t n;
184 char phydev_path[256];
185 struct nl80211_state nlstate;
187 /* XXX: is this already a monN device? */
188 get_mac80211_phydev(device, phydev_path, sizeof(phydev_path));
189 nl80211_init(&nlstate, device);
191 for (n = 0; n < UINT_MAX; n++) {
192 char mondevice[32];
194 slprintf(mondevice, sizeof(mondevice), "mon%u", n);
195 ret = nl80211_add_mon_if(&nlstate, device, mondevice);
196 if (ret == 0) {
197 *mondev = xstrdup(mondevice);
199 flags = device_get_flags(*mondev);
200 flags |= IFF_UP | IFF_RUNNING;
201 device_set_flags(*mondev, flags);
203 nl80211_cleanup(&nlstate);
204 return;
208 panic("No free monN interfaces!\n");
211 void leave_rfmon_mac80211(const char *device, const char *mondev)
213 short flags;
214 struct nl80211_state nlstate;
216 flags = device_get_flags(mondev);
217 flags &= ~(IFF_UP | IFF_RUNNING);
218 device_set_flags(mondev, flags);
220 nl80211_init(&nlstate, device);
221 nl80211_del_mon_if(&nlstate, device, mondev);
222 nl80211_cleanup(&nlstate);