xref: /freebsd/tools/tools/ath/common/ctrl.c (revision b3e76948)
105ec4b52SAdrian Chadd /*-
205ec4b52SAdrian Chadd  * Copyright (c) 2016 Adrian Chadd <adrian@FreeBSD.org>.
305ec4b52SAdrian Chadd  * All rights reserved.
405ec4b52SAdrian Chadd  *
505ec4b52SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
605ec4b52SAdrian Chadd  * modification, are permitted provided that the following conditions
705ec4b52SAdrian Chadd  * are met:
805ec4b52SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
905ec4b52SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
1005ec4b52SAdrian Chadd  *    without modification.
1105ec4b52SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1205ec4b52SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
1305ec4b52SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
1405ec4b52SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
1505ec4b52SAdrian Chadd  *
1605ec4b52SAdrian Chadd  * NO WARRANTY
1705ec4b52SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1805ec4b52SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1905ec4b52SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
2005ec4b52SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
2105ec4b52SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
2205ec4b52SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2305ec4b52SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2405ec4b52SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2505ec4b52SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2605ec4b52SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2705ec4b52SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
2805ec4b52SAdrian Chadd  */
2905ec4b52SAdrian Chadd 
3005ec4b52SAdrian Chadd /*
3105ec4b52SAdrian Chadd  * This is a simple abstraction of the control channel used to access
3205ec4b52SAdrian Chadd  * device specific data.
3305ec4b52SAdrian Chadd  *
3405ec4b52SAdrian Chadd  * In the past it used a ifnet socket on athX, but since those devices
3505ec4b52SAdrian Chadd  * are now gone, they can use wlanX.  However, there are debug cases
3605ec4b52SAdrian Chadd  * where you'll instead want to talk to the hardware before any VAPs are
3705ec4b52SAdrian Chadd  * up, so we should also handle the case of talking to /dev/athX.
3805ec4b52SAdrian Chadd  *
3905ec4b52SAdrian Chadd  * For now this'll be a drop-in replacement for the existing ioctl()
4005ec4b52SAdrian Chadd  * based method until the /dev/athX (and associated new ioctls) land
4105ec4b52SAdrian Chadd  * in the tree.
4205ec4b52SAdrian Chadd  */
4305ec4b52SAdrian Chadd 
4405ec4b52SAdrian Chadd #include <sys/param.h>
4505ec4b52SAdrian Chadd #include <sys/file.h>
4605ec4b52SAdrian Chadd #include <sys/sockio.h>
4705ec4b52SAdrian Chadd #include <sys/socket.h>
4805ec4b52SAdrian Chadd 
4905ec4b52SAdrian Chadd #include <net/if.h>
5005ec4b52SAdrian Chadd #include <net/if_media.h>
5105ec4b52SAdrian Chadd #include <net/if_var.h>
5205ec4b52SAdrian Chadd 
5305ec4b52SAdrian Chadd #include <err.h>
5405ec4b52SAdrian Chadd #include <signal.h>
5505ec4b52SAdrian Chadd #include <stdio.h>
5605ec4b52SAdrian Chadd #include <stdlib.h>
5705ec4b52SAdrian Chadd #include <string.h>
5805ec4b52SAdrian Chadd #include <unistd.h>
5905ec4b52SAdrian Chadd 
6005ec4b52SAdrian Chadd #include "ah.h"
6105ec4b52SAdrian Chadd #include "ah_desc.h"
6205ec4b52SAdrian Chadd #include "net80211/ieee80211_ioctl.h"
6305ec4b52SAdrian Chadd #include "net80211/ieee80211_radiotap.h"
6405ec4b52SAdrian Chadd #include "if_athioctl.h"
6505ec4b52SAdrian Chadd #include "if_athrate.h"
6605ec4b52SAdrian Chadd 
6705ec4b52SAdrian Chadd #include "ctrl.h"
6805ec4b52SAdrian Chadd 
6905ec4b52SAdrian Chadd int
ath_driver_req_init(struct ath_driver_req * req)7005ec4b52SAdrian Chadd ath_driver_req_init(struct ath_driver_req *req)
7105ec4b52SAdrian Chadd {
7205ec4b52SAdrian Chadd 
7305ec4b52SAdrian Chadd 	bzero(req, sizeof(*req));
7405ec4b52SAdrian Chadd 	req->s = -1;
7505ec4b52SAdrian Chadd 	return (0);
7605ec4b52SAdrian Chadd }
7705ec4b52SAdrian Chadd 
7805ec4b52SAdrian Chadd /*
7905ec4b52SAdrian Chadd  * Open a suitable file descriptor and populate the relevant interface
8005ec4b52SAdrian Chadd  * information for ioctls.
8105ec4b52SAdrian Chadd  *
8205ec4b52SAdrian Chadd  * For file path based access the ifreq isn't required; it'll just be
8305ec4b52SAdrian Chadd  * a direct ioctl on the file descriptor.
8405ec4b52SAdrian Chadd  */
8505ec4b52SAdrian Chadd int
ath_driver_req_open(struct ath_driver_req * req,const char * ifname)8605ec4b52SAdrian Chadd ath_driver_req_open(struct ath_driver_req *req, const char *ifname)
8705ec4b52SAdrian Chadd {
8805ec4b52SAdrian Chadd 	int s;
8905ec4b52SAdrian Chadd 
9005ec4b52SAdrian Chadd 	if (s != -1)
9105ec4b52SAdrian Chadd 		ath_driver_req_close(req);
9205ec4b52SAdrian Chadd 
9305ec4b52SAdrian Chadd 	/* For now, netif socket, not /dev/ filedescriptor */
9405ec4b52SAdrian Chadd 	s = socket(AF_INET, SOCK_DGRAM, 0);
9505ec4b52SAdrian Chadd 	if (s < 0) {
9605ec4b52SAdrian Chadd 		warn("%s: socket", __func__);
9705ec4b52SAdrian Chadd 		return (-1);
9805ec4b52SAdrian Chadd 	}
9905ec4b52SAdrian Chadd 	req->ifname = strdup(ifname);
10005ec4b52SAdrian Chadd 	req->s = s;
10105ec4b52SAdrian Chadd 
10205ec4b52SAdrian Chadd 	return (0);
10305ec4b52SAdrian Chadd }
10405ec4b52SAdrian Chadd 
10505ec4b52SAdrian Chadd /*
10605ec4b52SAdrian Chadd  * Close an open descriptor.
10705ec4b52SAdrian Chadd  */
10805ec4b52SAdrian Chadd int
ath_driver_req_close(struct ath_driver_req * req)10905ec4b52SAdrian Chadd ath_driver_req_close(struct ath_driver_req *req)
11005ec4b52SAdrian Chadd {
11105ec4b52SAdrian Chadd 	if (req->s == -1)
11205ec4b52SAdrian Chadd 		return (0);
11305ec4b52SAdrian Chadd 	close(req->s);
11405ec4b52SAdrian Chadd 	free(req->ifname);
11505ec4b52SAdrian Chadd 	req->s = -1;
11605ec4b52SAdrian Chadd 	req->ifname = NULL;
11705ec4b52SAdrian Chadd 	return (0);
11805ec4b52SAdrian Chadd }
11905ec4b52SAdrian Chadd 
12005ec4b52SAdrian Chadd /*
12105ec4b52SAdrian Chadd  * Issue a diagnostic API request.
12205ec4b52SAdrian Chadd  */
12305ec4b52SAdrian Chadd int
ath_driver_req_fetch_diag(struct ath_driver_req * req,unsigned long cmd,struct ath_diag * ad)12405ec4b52SAdrian Chadd ath_driver_req_fetch_diag(struct ath_driver_req *req, unsigned long cmd,
12505ec4b52SAdrian Chadd     struct ath_diag *ad)
12605ec4b52SAdrian Chadd {
12705ec4b52SAdrian Chadd 	int ret;
12805ec4b52SAdrian Chadd 
12905ec4b52SAdrian Chadd 	ret = ioctl(req->s, cmd, ad);
13005ec4b52SAdrian Chadd 	if (ret < 0)
13105ec4b52SAdrian Chadd 		warn("%s: ioctl", __func__);
13205ec4b52SAdrian Chadd 	return (ret);
13305ec4b52SAdrian Chadd }
13405ec4b52SAdrian Chadd 
13505ec4b52SAdrian Chadd /*
13605ec4b52SAdrian Chadd  * Issue a zero statistics API request.
13705ec4b52SAdrian Chadd  */
13805ec4b52SAdrian Chadd int
ath_driver_req_zero_stats(struct ath_driver_req * req)13905ec4b52SAdrian Chadd ath_driver_req_zero_stats(struct ath_driver_req *req)
14005ec4b52SAdrian Chadd {
14105ec4b52SAdrian Chadd 	struct ifreq ifr;
14205ec4b52SAdrian Chadd 	int ret;
14305ec4b52SAdrian Chadd 
14405ec4b52SAdrian Chadd 	/* Setup ifreq */
14505ec4b52SAdrian Chadd 	bzero(&ifr, sizeof(ifr));
14605ec4b52SAdrian Chadd 	strncpy(ifr.ifr_name, req->ifname, sizeof (ifr.ifr_name));
14705ec4b52SAdrian Chadd 	ifr.ifr_data = NULL;
14805ec4b52SAdrian Chadd 
14905ec4b52SAdrian Chadd 	/* ioctl */
15005ec4b52SAdrian Chadd 	ret = ioctl(req->s, SIOCZATHSTATS, &ifr);
15105ec4b52SAdrian Chadd 	if (ret < 0)
15205ec4b52SAdrian Chadd 		warn("%s: ioctl", __func__);
15305ec4b52SAdrian Chadd 	return (ret);
15405ec4b52SAdrian Chadd }
15505ec4b52SAdrian Chadd 
15605ec4b52SAdrian Chadd /*
15705ec4b52SAdrian Chadd  * Fetch general statistics.
15805ec4b52SAdrian Chadd  */
15905ec4b52SAdrian Chadd int
ath_driver_req_fetch_stats(struct ath_driver_req * req,struct ath_stats * st)16005ec4b52SAdrian Chadd ath_driver_req_fetch_stats(struct ath_driver_req *req, struct ath_stats *st)
16105ec4b52SAdrian Chadd {
16205ec4b52SAdrian Chadd 	struct ifreq ifr;
16305ec4b52SAdrian Chadd 	int ret;
16405ec4b52SAdrian Chadd 
16505ec4b52SAdrian Chadd 	/* Setup ifreq */
16605ec4b52SAdrian Chadd 	bzero(&ifr, sizeof(ifr));
16705ec4b52SAdrian Chadd 	strncpy(ifr.ifr_name, req->ifname, sizeof (ifr.ifr_name));
16805ec4b52SAdrian Chadd 	ifr.ifr_data = (caddr_t) st;
16905ec4b52SAdrian Chadd 
17005ec4b52SAdrian Chadd 	/* ioctl */
17105ec4b52SAdrian Chadd 	ret = ioctl(req->s, SIOCGATHSTATS, &ifr);
17205ec4b52SAdrian Chadd 	if (ret < 0)
17305ec4b52SAdrian Chadd 		warn("%s: ioctl", __func__);
17405ec4b52SAdrian Chadd 	return (ret);
17505ec4b52SAdrian Chadd }
17605ec4b52SAdrian Chadd 
17705ec4b52SAdrian Chadd /*
17805ec4b52SAdrian Chadd  * Fetch aggregate statistics.
17905ec4b52SAdrian Chadd  */
18005ec4b52SAdrian Chadd int
ath_drive_req_fetch_aggr_stats(struct ath_driver_req * req,struct ath_tx_aggr_stats * tx)18105ec4b52SAdrian Chadd ath_drive_req_fetch_aggr_stats(struct ath_driver_req *req,
18205ec4b52SAdrian Chadd     struct ath_tx_aggr_stats *tx)
18305ec4b52SAdrian Chadd {
18405ec4b52SAdrian Chadd 	struct ifreq ifr;
18505ec4b52SAdrian Chadd 	int ret;
18605ec4b52SAdrian Chadd 
18705ec4b52SAdrian Chadd 	/* Setup ifreq */
18805ec4b52SAdrian Chadd 	bzero(&ifr, sizeof(ifr));
18905ec4b52SAdrian Chadd 	strncpy(ifr.ifr_name, req->ifname, sizeof (ifr.ifr_name));
19005ec4b52SAdrian Chadd 	ifr.ifr_data = (caddr_t) tx;
19105ec4b52SAdrian Chadd 
19205ec4b52SAdrian Chadd 	/* ioctl */
19305ec4b52SAdrian Chadd 	ret = ioctl(req->s, SIOCGATHAGSTATS, &ifr);
19405ec4b52SAdrian Chadd 	if (ret < 0)
19505ec4b52SAdrian Chadd 		warn("%s: ioctl", __func__);
19605ec4b52SAdrian Chadd 	return (ret);
19705ec4b52SAdrian Chadd 
19805ec4b52SAdrian Chadd }
19905ec4b52SAdrian Chadd 
20005ec4b52SAdrian Chadd /*
20105ec4b52SAdrian Chadd  * Fetch rate control statistics.
20205ec4b52SAdrian Chadd  *
20305ec4b52SAdrian Chadd  * Caller has to populate the interface name and MAC address.
20405ec4b52SAdrian Chadd  */
20505ec4b52SAdrian Chadd int
ath_drive_req_fetch_ratectrl_stats(struct ath_driver_req * req,struct ath_rateioctl * r)20605ec4b52SAdrian Chadd ath_drive_req_fetch_ratectrl_stats(struct ath_driver_req *req,
20705ec4b52SAdrian Chadd     struct ath_rateioctl *r)
20805ec4b52SAdrian Chadd {
20905ec4b52SAdrian Chadd 	int ret;
21005ec4b52SAdrian Chadd 
21105ec4b52SAdrian Chadd 	/* ioctl */
21205ec4b52SAdrian Chadd 	ret = ioctl(req->s, SIOCGATHNODERATESTATS, r);
21305ec4b52SAdrian Chadd 	if (ret < 0)
21405ec4b52SAdrian Chadd 		warn("%s: ioctl", __func__);
21505ec4b52SAdrian Chadd 	return (ret);
21605ec4b52SAdrian Chadd }
217