xref: /freebsd/tools/tools/ath/common/ctrl.c (revision 42249ef2)
1 /*-
2  * Copyright (c) 2016 Adrian Chadd <adrian@FreeBSD.org>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  *
29  * $FreeBSD$
30  */
31 
32 /*
33  * This is a simple abstraction of the control channel used to access
34  * device specific data.
35  *
36  * In the past it used a ifnet socket on athX, but since those devices
37  * are now gone, they can use wlanX.  However, there are debug cases
38  * where you'll instead want to talk to the hardware before any VAPs are
39  * up, so we should also handle the case of talking to /dev/athX.
40  *
41  * For now this'll be a drop-in replacement for the existing ioctl()
42  * based method until the /dev/athX (and associated new ioctls) land
43  * in the tree.
44  */
45 
46 #include <sys/param.h>
47 #include <sys/file.h>
48 #include <sys/sockio.h>
49 #include <sys/socket.h>
50 
51 #include <net/if.h>
52 #include <net/if_media.h>
53 #include <net/if_var.h>
54 
55 #include <err.h>
56 #include <signal.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <unistd.h>
61 
62 #include "ah.h"
63 #include "ah_desc.h"
64 #include "net80211/ieee80211_ioctl.h"
65 #include "net80211/ieee80211_radiotap.h"
66 #include "if_athioctl.h"
67 #include "if_athrate.h"
68 
69 #include "ctrl.h"
70 
71 int
72 ath_driver_req_init(struct ath_driver_req *req)
73 {
74 
75 	bzero(req, sizeof(*req));
76 	req->s = -1;
77 	return (0);
78 }
79 
80 /*
81  * Open a suitable file descriptor and populate the relevant interface
82  * information for ioctls.
83  *
84  * For file path based access the ifreq isn't required; it'll just be
85  * a direct ioctl on the file descriptor.
86  */
87 int
88 ath_driver_req_open(struct ath_driver_req *req, const char *ifname)
89 {
90 	int s;
91 
92 	if (s != -1)
93 		ath_driver_req_close(req);
94 
95 	/* For now, netif socket, not /dev/ filedescriptor */
96 	s = socket(AF_INET, SOCK_DGRAM, 0);
97 	if (s < 0) {
98 		warn("%s: socket", __func__);
99 		return (-1);
100 	}
101 	req->ifname = strdup(ifname);
102 	req->s = s;
103 
104 	return (0);
105 }
106 
107 /*
108  * Close an open descriptor.
109  */
110 int
111 ath_driver_req_close(struct ath_driver_req *req)
112 {
113 	if (req->s == -1)
114 		return (0);
115 	close(req->s);
116 	free(req->ifname);
117 	req->s = -1;
118 	req->ifname = NULL;
119 	return (0);
120 }
121 
122 /*
123  * Issue a diagnostic API request.
124  */
125 int
126 ath_driver_req_fetch_diag(struct ath_driver_req *req, unsigned long cmd,
127     struct ath_diag *ad)
128 {
129 	int ret;
130 
131 	ret = ioctl(req->s, cmd, ad);
132 	if (ret < 0)
133 		warn("%s: ioctl", __func__);
134 	return (ret);
135 }
136 
137 /*
138  * Issue a zero statistics API request.
139  */
140 int
141 ath_driver_req_zero_stats(struct ath_driver_req *req)
142 {
143 	struct ifreq ifr;
144 	int ret;
145 
146 	/* Setup ifreq */
147 	bzero(&ifr, sizeof(ifr));
148 	strncpy(ifr.ifr_name, req->ifname, sizeof (ifr.ifr_name));
149 	ifr.ifr_data = NULL;
150 
151 	/* ioctl */
152 	ret = ioctl(req->s, SIOCZATHSTATS, &ifr);
153 	if (ret < 0)
154 		warn("%s: ioctl", __func__);
155 	return (ret);
156 }
157 
158 /*
159  * Fetch general statistics.
160  */
161 int
162 ath_driver_req_fetch_stats(struct ath_driver_req *req, struct ath_stats *st)
163 {
164 	struct ifreq ifr;
165 	int ret;
166 
167 	/* Setup ifreq */
168 	bzero(&ifr, sizeof(ifr));
169 	strncpy(ifr.ifr_name, req->ifname, sizeof (ifr.ifr_name));
170 	ifr.ifr_data = (caddr_t) st;
171 
172 	/* ioctl */
173 	ret = ioctl(req->s, SIOCGATHSTATS, &ifr);
174 	if (ret < 0)
175 		warn("%s: ioctl", __func__);
176 	return (ret);
177 }
178 
179 /*
180  * Fetch aggregate statistics.
181  */
182 int
183 ath_drive_req_fetch_aggr_stats(struct ath_driver_req *req,
184     struct ath_tx_aggr_stats *tx)
185 {
186 	struct ifreq ifr;
187 	int ret;
188 
189 	/* Setup ifreq */
190 	bzero(&ifr, sizeof(ifr));
191 	strncpy(ifr.ifr_name, req->ifname, sizeof (ifr.ifr_name));
192 	ifr.ifr_data = (caddr_t) tx;
193 
194 	/* ioctl */
195 	ret = ioctl(req->s, SIOCGATHAGSTATS, &ifr);
196 	if (ret < 0)
197 		warn("%s: ioctl", __func__);
198 	return (ret);
199 
200 }
201 
202 /*
203  * Fetch rate control statistics.
204  *
205  * Caller has to populate the interface name and MAC address.
206  */
207 int
208 ath_drive_req_fetch_ratectrl_stats(struct ath_driver_req *req,
209     struct ath_rateioctl *r)
210 {
211 	int ret;
212 
213 	/* ioctl */
214 	ret = ioctl(req->s, SIOCGATHNODERATESTATS, r);
215 	if (ret < 0)
216 		warn("%s: ioctl", __func__);
217 	return (ret);
218 }
219