xref: /freebsd/tools/tools/ath/common/ctrl.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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 
30 /*
31  * This is a simple abstraction of the control channel used to access
32  * device specific data.
33  *
34  * In the past it used a ifnet socket on athX, but since those devices
35  * are now gone, they can use wlanX.  However, there are debug cases
36  * where you'll instead want to talk to the hardware before any VAPs are
37  * up, so we should also handle the case of talking to /dev/athX.
38  *
39  * For now this'll be a drop-in replacement for the existing ioctl()
40  * based method until the /dev/athX (and associated new ioctls) land
41  * in the tree.
42  */
43 
44 #include <sys/param.h>
45 #include <sys/file.h>
46 #include <sys/sockio.h>
47 #include <sys/socket.h>
48 
49 #include <net/if.h>
50 #include <net/if_media.h>
51 #include <net/if_var.h>
52 
53 #include <err.h>
54 #include <signal.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <unistd.h>
59 
60 #include "ah.h"
61 #include "ah_desc.h"
62 #include "net80211/ieee80211_ioctl.h"
63 #include "net80211/ieee80211_radiotap.h"
64 #include "if_athioctl.h"
65 #include "if_athrate.h"
66 
67 #include "ctrl.h"
68 
69 int
ath_driver_req_init(struct ath_driver_req * req)70 ath_driver_req_init(struct ath_driver_req *req)
71 {
72 
73 	bzero(req, sizeof(*req));
74 	req->s = -1;
75 	return (0);
76 }
77 
78 /*
79  * Open a suitable file descriptor and populate the relevant interface
80  * information for ioctls.
81  *
82  * For file path based access the ifreq isn't required; it'll just be
83  * a direct ioctl on the file descriptor.
84  */
85 int
ath_driver_req_open(struct ath_driver_req * req,const char * ifname)86 ath_driver_req_open(struct ath_driver_req *req, const char *ifname)
87 {
88 	int s;
89 
90 	if (s != -1)
91 		ath_driver_req_close(req);
92 
93 	/* For now, netif socket, not /dev/ filedescriptor */
94 	s = socket(AF_INET, SOCK_DGRAM, 0);
95 	if (s < 0) {
96 		warn("%s: socket", __func__);
97 		return (-1);
98 	}
99 	req->ifname = strdup(ifname);
100 	req->s = s;
101 
102 	return (0);
103 }
104 
105 /*
106  * Close an open descriptor.
107  */
108 int
ath_driver_req_close(struct ath_driver_req * req)109 ath_driver_req_close(struct ath_driver_req *req)
110 {
111 	if (req->s == -1)
112 		return (0);
113 	close(req->s);
114 	free(req->ifname);
115 	req->s = -1;
116 	req->ifname = NULL;
117 	return (0);
118 }
119 
120 /*
121  * Issue a diagnostic API request.
122  */
123 int
ath_driver_req_fetch_diag(struct ath_driver_req * req,unsigned long cmd,struct ath_diag * ad)124 ath_driver_req_fetch_diag(struct ath_driver_req *req, unsigned long cmd,
125     struct ath_diag *ad)
126 {
127 	int ret;
128 
129 	ret = ioctl(req->s, cmd, ad);
130 	if (ret < 0)
131 		warn("%s: ioctl", __func__);
132 	return (ret);
133 }
134 
135 /*
136  * Issue a zero statistics API request.
137  */
138 int
ath_driver_req_zero_stats(struct ath_driver_req * req)139 ath_driver_req_zero_stats(struct ath_driver_req *req)
140 {
141 	struct ifreq ifr;
142 	int ret;
143 
144 	/* Setup ifreq */
145 	bzero(&ifr, sizeof(ifr));
146 	strncpy(ifr.ifr_name, req->ifname, sizeof (ifr.ifr_name));
147 	ifr.ifr_data = NULL;
148 
149 	/* ioctl */
150 	ret = ioctl(req->s, SIOCZATHSTATS, &ifr);
151 	if (ret < 0)
152 		warn("%s: ioctl", __func__);
153 	return (ret);
154 }
155 
156 /*
157  * Fetch general statistics.
158  */
159 int
ath_driver_req_fetch_stats(struct ath_driver_req * req,struct ath_stats * st)160 ath_driver_req_fetch_stats(struct ath_driver_req *req, struct ath_stats *st)
161 {
162 	struct ifreq ifr;
163 	int ret;
164 
165 	/* Setup ifreq */
166 	bzero(&ifr, sizeof(ifr));
167 	strncpy(ifr.ifr_name, req->ifname, sizeof (ifr.ifr_name));
168 	ifr.ifr_data = (caddr_t) st;
169 
170 	/* ioctl */
171 	ret = ioctl(req->s, SIOCGATHSTATS, &ifr);
172 	if (ret < 0)
173 		warn("%s: ioctl", __func__);
174 	return (ret);
175 }
176 
177 /*
178  * Fetch aggregate statistics.
179  */
180 int
ath_drive_req_fetch_aggr_stats(struct ath_driver_req * req,struct ath_tx_aggr_stats * tx)181 ath_drive_req_fetch_aggr_stats(struct ath_driver_req *req,
182     struct ath_tx_aggr_stats *tx)
183 {
184 	struct ifreq ifr;
185 	int ret;
186 
187 	/* Setup ifreq */
188 	bzero(&ifr, sizeof(ifr));
189 	strncpy(ifr.ifr_name, req->ifname, sizeof (ifr.ifr_name));
190 	ifr.ifr_data = (caddr_t) tx;
191 
192 	/* ioctl */
193 	ret = ioctl(req->s, SIOCGATHAGSTATS, &ifr);
194 	if (ret < 0)
195 		warn("%s: ioctl", __func__);
196 	return (ret);
197 
198 }
199 
200 /*
201  * Fetch rate control statistics.
202  *
203  * Caller has to populate the interface name and MAC address.
204  */
205 int
ath_drive_req_fetch_ratectrl_stats(struct ath_driver_req * req,struct ath_rateioctl * r)206 ath_drive_req_fetch_ratectrl_stats(struct ath_driver_req *req,
207     struct ath_rateioctl *r)
208 {
209 	int ret;
210 
211 	/* ioctl */
212 	ret = ioctl(req->s, SIOCGATHNODERATESTATS, r);
213 	if (ret < 0)
214 		warn("%s: ioctl", __func__);
215 	return (ret);
216 }
217