Add lib80211, a small (but hopefully soon to grow) set of library
routines to interface with net80211. This is all from the ifconfig program; the duplicate code from ifconfig will be removed when it starts using this API. Differential Revision: https://reviews.freebsd.org/D4290
This commit is contained in:
parent
2ba33d63f5
commit
2aec31058d
@ -71,6 +71,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
|
||||
${_libmp} \
|
||||
libmt \
|
||||
${_libnandfs} \
|
||||
lib80211 \
|
||||
libnetbsd \
|
||||
${_libnetgraph} \
|
||||
${_libngatm} \
|
||||
|
15
lib/lib80211/Makefile
Normal file
15
lib/lib80211/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
# $FreeBSD$
|
||||
|
||||
LIB= 80211
|
||||
SHLIBDIR?= /lib
|
||||
SHLIB_MAJOR= 1
|
||||
SRCS= lib80211_regdomain.c lib80211_ioctl.c
|
||||
|
||||
INCSDIR= ${INCLUDEDIR}/lib80211/
|
||||
INCS= lib80211_regdomain.h lib80211_ioctl.h
|
||||
|
||||
MAN= lib80211.3
|
||||
|
||||
CFLAGS+=-I${.CURDIR}
|
||||
|
||||
.include <bsd.lib.mk>
|
118
lib/lib80211/lib80211.3
Normal file
118
lib/lib80211/lib80211.3
Normal file
@ -0,0 +1,118 @@
|
||||
.\" Copyright (c) 2015 Adrian Chadd.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 24, 2015
|
||||
.Dt 80211 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm lib80211_alloc_regdata ,
|
||||
.Nm lib80211_free_regdata ,
|
||||
.Nm lib80211_regdomain_readconfig ,
|
||||
.Nm lib80211_regdomain_cleanup ,
|
||||
.Nm lib80211_regdomain_findbysku ,
|
||||
.Nm lib80211_regdomain_findbyname ,
|
||||
.Nm lib80211_country_findbycc ,
|
||||
.Nm lib80211_country_findbyname
|
||||
.Nd manage net80211 configuration and regulatory database.
|
||||
.Sh LIBRARY
|
||||
.Lb lib80211
|
||||
.Sh SYNOPSIS
|
||||
.In lib80211/lib80211_regdomain.h
|
||||
.In lib80211/lib80211_ioctl.h
|
||||
.Ft struct regdata *
|
||||
.Fn lib80211_alloc_regdata void
|
||||
.Ft void
|
||||
.Fn lib80211_free_regdata "struct regdata *reg"
|
||||
.Ft int
|
||||
.Fn lib80211_regdomain_readconfig "struct regdata *reg" "const void *config" "size_t size"
|
||||
.Ft void
|
||||
.Fn lib80211_regdomain_cleanup "struct regdata *reg"
|
||||
.Ft const struct regdomain *
|
||||
.Fn lib80211_regdomain_findbysku "const struct regdata *reg" "enumRegDomainCode"
|
||||
.Ft const struct regdomain *
|
||||
.Fn lib80211_regdomain_findbyname "const struct regdata *reg" "const char *sku"
|
||||
.Ft const struct country *
|
||||
.Fn lib80211_country_findbycc "const struct regdata *reg" "enum ISOCountryCode"
|
||||
.Ft const struct country *
|
||||
.Fn lib80211_country_findbyname "const struct regdata *reg" "const char *cc"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm lib80211
|
||||
library is an interface to the
|
||||
.Xr net80211 4
|
||||
infrastructure.
|
||||
It implements wrappers around the
|
||||
.Xr net80211 4
|
||||
ioctl command, as well as providing a convenient API to access the regulatory
|
||||
database.
|
||||
.Pp
|
||||
The
|
||||
.Fn lib80211_alloc_regdata
|
||||
and
|
||||
.Fn lib80211_free_regdata
|
||||
function allocates / frees a regdata structure to store regulatory domain
|
||||
information in.
|
||||
.Pp
|
||||
The
|
||||
.Fn lib80211_regdomain_readconfig
|
||||
and
|
||||
.Fn lib80211_regdomain_cleanup
|
||||
functions read in the regulatory database XML configuration and free it when
|
||||
finished.
|
||||
.Pp
|
||||
The
|
||||
.Fn lib80211_regdomain_findbysku
|
||||
and
|
||||
.Fn lib80211_regdomain_findbyname
|
||||
functions lookup a regulatory domain entry by SKU enum and SKU name
|
||||
respectively.
|
||||
.Pp
|
||||
The
|
||||
.Fn lib80211_country_findbycc
|
||||
and
|
||||
.Fn lib80211_country_findbyname
|
||||
functions lookup a country information entry by ISO country enum and
|
||||
ISO country code string respectively.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn lib80211_alloc_regdata ,
|
||||
.Fn lib80211_regdomain_readconfig ,
|
||||
.Fn lib80211_regdomain_findbysku ,
|
||||
.Fn lib80211_regdomain_findbyname ,
|
||||
.Fn lib80211_country_findbycc ,
|
||||
.Fn lib80211_country_findbyname
|
||||
return NULL upon error.
|
||||
|
||||
.Sh SEE ALSO
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr net80211 4
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm lib80211
|
||||
library first appeared in
|
||||
.Fx 11.0 .
|
||||
.Sh AUTHORS
|
||||
.An Adrian Chadd
|
159
lib/lib80211/lib80211_ioctl.c
Normal file
159
lib/lib80211/lib80211_ioctl.c
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2001 The Aerospace Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of The Aerospace Corporation may not be used to endorse or
|
||||
* promote products derived from this software.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <net80211/ieee80211_ioctl.h>
|
||||
#include <net80211/ieee80211_freebsd.h>
|
||||
#include <net80211/ieee80211_superg.h>
|
||||
#include <net80211/ieee80211_tdma.h>
|
||||
#include <net80211/ieee80211_mesh.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h> /* NB: for offsetof */
|
||||
|
||||
#include "lib80211_ioctl.h"
|
||||
|
||||
/*
|
||||
* These implement basic net80211 accessor methods to wrap the IOCTL
|
||||
* calls.
|
||||
*/
|
||||
|
||||
int
|
||||
lib80211_get80211(int s, const char *name, int type, void *data, int len)
|
||||
{
|
||||
struct ieee80211req ireq;
|
||||
|
||||
(void) memset(&ireq, 0, sizeof(ireq));
|
||||
(void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
|
||||
ireq.i_type = type;
|
||||
ireq.i_data = data;
|
||||
ireq.i_len = len;
|
||||
return ioctl(s, SIOCG80211, &ireq);
|
||||
}
|
||||
|
||||
int
|
||||
lib80211_get80211len(int s, const char *name, int type, void *data, int len, int *plen)
|
||||
{
|
||||
struct ieee80211req ireq;
|
||||
|
||||
(void) memset(&ireq, 0, sizeof(ireq));
|
||||
(void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
|
||||
ireq.i_type = type;
|
||||
ireq.i_len = len;
|
||||
assert(ireq.i_len == len); /* NB: check for 16-bit truncation */
|
||||
ireq.i_data = data;
|
||||
if (ioctl(s, SIOCG80211, &ireq) < 0)
|
||||
return -1;
|
||||
*plen = ireq.i_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lib80211_get80211val(int s, const char *name, int type, int *val)
|
||||
{
|
||||
struct ieee80211req ireq;
|
||||
|
||||
(void) memset(&ireq, 0, sizeof(ireq));
|
||||
(void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
|
||||
ireq.i_type = type;
|
||||
if (ioctl(s, SIOCG80211, &ireq) < 0)
|
||||
return -1;
|
||||
*val = ireq.i_val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lib80211_set80211(int s, const char *name, int type, int val, int len, void *data)
|
||||
{
|
||||
struct ieee80211req ireq;
|
||||
|
||||
(void) memset(&ireq, 0, sizeof(ireq));
|
||||
(void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
|
||||
ireq.i_type = type;
|
||||
ireq.i_val = val;
|
||||
ireq.i_len = len;
|
||||
assert(ireq.i_len == len); /* NB: check for 16-bit truncation */
|
||||
ireq.i_data = data;
|
||||
if (ioctl(s, SIOCS80211, &ireq) < 0)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
71
lib/lib80211/lib80211_ioctl.h
Normal file
71
lib/lib80211/lib80211_ioctl.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2001 The Aerospace Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of The Aerospace Corporation may not be used to endorse or
|
||||
* promote products derived from this software.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __LIB80211_IOCTL_H__
|
||||
#define __LIB80211_IOCTL_H__
|
||||
|
||||
extern int lib80211_get80211(int s, const char *name, int type, void *data,
|
||||
int len);
|
||||
extern int lib80211_get80211len(int s, const char *name, int type, void *data,
|
||||
int len, int *plen);
|
||||
extern int lib80211_get80211val(int s, const char *name, int type, int *val);
|
||||
extern int lib80211_set80211(int s, const char *name, int type, int val,
|
||||
int len, void *data);
|
||||
|
||||
#endif /* __LIB80211_IOCTL_H__ */
|
707
lib/lib80211/lib80211_regdomain.c
Normal file
707
lib/lib80211/lib80211_regdomain.c
Normal file
@ -0,0 +1,707 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 Sam Leffler, Errno Consulting
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef lint
|
||||
static const char rcsid[] = "$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <bsdxml.h>
|
||||
|
||||
#include "lib80211_regdomain.h"
|
||||
|
||||
#include <net80211/_ieee80211.h>
|
||||
|
||||
#define MAXLEVEL 20
|
||||
|
||||
struct mystate {
|
||||
XML_Parser parser;
|
||||
struct regdata *rdp;
|
||||
struct regdomain *rd; /* current domain */
|
||||
struct netband *netband; /* current netband */
|
||||
struct freqband *freqband; /* current freqband */
|
||||
struct country *country; /* current country */
|
||||
netband_head *curband; /* current netband list */
|
||||
int level;
|
||||
struct sbuf *sbuf[MAXLEVEL];
|
||||
int nident;
|
||||
};
|
||||
|
||||
struct ident {
|
||||
const void *id;
|
||||
void *p;
|
||||
enum { DOMAIN, COUNTRY, FREQBAND } type;
|
||||
};
|
||||
|
||||
static void
|
||||
start_element(void *data, const char *name, const char **attr)
|
||||
{
|
||||
#define iseq(a,b) (strcasecmp(a,b) == 0)
|
||||
struct mystate *mt;
|
||||
const void *id, *ref, *mode;
|
||||
int i;
|
||||
|
||||
mt = data;
|
||||
if (++mt->level == MAXLEVEL) {
|
||||
/* XXX force parser to abort */
|
||||
return;
|
||||
}
|
||||
mt->sbuf[mt->level] = sbuf_new_auto();
|
||||
id = ref = mode = NULL;
|
||||
for (i = 0; attr[i] != NULL; i += 2) {
|
||||
if (iseq(attr[i], "id")) {
|
||||
id = attr[i+1];
|
||||
} else if (iseq(attr[i], "ref")) {
|
||||
ref = attr[i+1];
|
||||
} else if (iseq(attr[i], "mode")) {
|
||||
mode = attr[i+1];
|
||||
} else
|
||||
printf("%*.*s[%s = %s]\n", mt->level + 1,
|
||||
mt->level + 1, "", attr[i], attr[i+1]);
|
||||
}
|
||||
if (iseq(name, "rd") && mt->rd == NULL) {
|
||||
if (mt->country == NULL) {
|
||||
mt->rd = calloc(1, sizeof(struct regdomain));
|
||||
mt->rd->name = strdup(id);
|
||||
mt->nident++;
|
||||
LIST_INSERT_HEAD(&mt->rdp->domains, mt->rd, next);
|
||||
} else
|
||||
mt->country->rd = (void *)strdup(ref);
|
||||
return;
|
||||
}
|
||||
if (iseq(name, "defcc") && mt->rd != NULL) {
|
||||
mt->rd->cc = (void *)strdup(ref);
|
||||
return;
|
||||
}
|
||||
if (iseq(name, "netband") && mt->curband == NULL && mt->rd != NULL) {
|
||||
if (mode == NULL) {
|
||||
warnx("no mode for netband at line %ld",
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
return;
|
||||
}
|
||||
if (iseq(mode, "11b"))
|
||||
mt->curband = &mt->rd->bands_11b;
|
||||
else if (iseq(mode, "11g"))
|
||||
mt->curband = &mt->rd->bands_11g;
|
||||
else if (iseq(mode, "11a"))
|
||||
mt->curband = &mt->rd->bands_11a;
|
||||
else if (iseq(mode, "11ng"))
|
||||
mt->curband = &mt->rd->bands_11ng;
|
||||
else if (iseq(mode, "11na"))
|
||||
mt->curband = &mt->rd->bands_11na;
|
||||
else
|
||||
warnx("unknown mode \"%s\" at line %ld",
|
||||
__DECONST(char *, mode),
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
return;
|
||||
}
|
||||
if (iseq(name, "band") && mt->netband == NULL) {
|
||||
if (mt->curband == NULL) {
|
||||
warnx("band without enclosing netband at line %ld",
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
return;
|
||||
}
|
||||
mt->netband = calloc(1, sizeof(struct netband));
|
||||
LIST_INSERT_HEAD(mt->curband, mt->netband, next);
|
||||
return;
|
||||
}
|
||||
if (iseq(name, "freqband") && mt->freqband == NULL && mt->netband != NULL) {
|
||||
/* XXX handle inlines and merge into table? */
|
||||
if (mt->netband->band != NULL) {
|
||||
warnx("duplicate freqband at line %ld ignored",
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
/* XXX complain */
|
||||
} else
|
||||
mt->netband->band = (void *)strdup(ref);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iseq(name, "country") && mt->country == NULL) {
|
||||
mt->country = calloc(1, sizeof(struct country));
|
||||
mt->country->isoname = strdup(id);
|
||||
mt->country->code = NO_COUNTRY;
|
||||
mt->nident++;
|
||||
LIST_INSERT_HEAD(&mt->rdp->countries, mt->country, next);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iseq(name, "freqband") && mt->freqband == NULL) {
|
||||
mt->freqband = calloc(1, sizeof(struct freqband));
|
||||
mt->freqband->id = strdup(id);
|
||||
mt->nident++;
|
||||
LIST_INSERT_HEAD(&mt->rdp->freqbands, mt->freqband, next);
|
||||
return;
|
||||
}
|
||||
#undef iseq
|
||||
}
|
||||
|
||||
static int
|
||||
decode_flag(struct mystate *mt, const char *p, int len)
|
||||
{
|
||||
#define iseq(a,b) (strcasecmp(a,b) == 0)
|
||||
static const struct {
|
||||
const char *name;
|
||||
int len;
|
||||
uint32_t value;
|
||||
} flags[] = {
|
||||
#define FLAG(x) { #x, sizeof(#x)-1, x }
|
||||
FLAG(IEEE80211_CHAN_A),
|
||||
FLAG(IEEE80211_CHAN_B),
|
||||
FLAG(IEEE80211_CHAN_G),
|
||||
FLAG(IEEE80211_CHAN_HT20),
|
||||
FLAG(IEEE80211_CHAN_HT40),
|
||||
FLAG(IEEE80211_CHAN_ST),
|
||||
FLAG(IEEE80211_CHAN_TURBO),
|
||||
FLAG(IEEE80211_CHAN_PASSIVE),
|
||||
FLAG(IEEE80211_CHAN_DFS),
|
||||
FLAG(IEEE80211_CHAN_CCK),
|
||||
FLAG(IEEE80211_CHAN_OFDM),
|
||||
FLAG(IEEE80211_CHAN_2GHZ),
|
||||
FLAG(IEEE80211_CHAN_5GHZ),
|
||||
FLAG(IEEE80211_CHAN_DYN),
|
||||
FLAG(IEEE80211_CHAN_GFSK),
|
||||
FLAG(IEEE80211_CHAN_GSM),
|
||||
FLAG(IEEE80211_CHAN_STURBO),
|
||||
FLAG(IEEE80211_CHAN_HALF),
|
||||
FLAG(IEEE80211_CHAN_QUARTER),
|
||||
FLAG(IEEE80211_CHAN_HT40U),
|
||||
FLAG(IEEE80211_CHAN_HT40D),
|
||||
FLAG(IEEE80211_CHAN_4MSXMIT),
|
||||
FLAG(IEEE80211_CHAN_NOADHOC),
|
||||
FLAG(IEEE80211_CHAN_NOHOSTAP),
|
||||
FLAG(IEEE80211_CHAN_11D),
|
||||
FLAG(IEEE80211_CHAN_FHSS),
|
||||
FLAG(IEEE80211_CHAN_PUREG),
|
||||
FLAG(IEEE80211_CHAN_108A),
|
||||
FLAG(IEEE80211_CHAN_108G),
|
||||
#undef FLAG
|
||||
{ "ECM", 3, REQ_ECM },
|
||||
{ "INDOOR", 6, REQ_INDOOR },
|
||||
{ "OUTDOOR", 7, REQ_OUTDOOR },
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < nitems(flags); i++)
|
||||
if (len == flags[i].len && iseq(p, flags[i].name))
|
||||
return flags[i].value;
|
||||
warnx("unknown flag \"%.*s\" at line %ld ignored",
|
||||
len, p, XML_GetCurrentLineNumber(mt->parser));
|
||||
return 0;
|
||||
#undef iseq
|
||||
}
|
||||
|
||||
static void
|
||||
end_element(void *data, const char *name)
|
||||
{
|
||||
#define iseq(a,b) (strcasecmp(a,b) == 0)
|
||||
struct mystate *mt;
|
||||
int len;
|
||||
char *p;
|
||||
|
||||
mt = data;
|
||||
sbuf_finish(mt->sbuf[mt->level]);
|
||||
p = sbuf_data(mt->sbuf[mt->level]);
|
||||
len = sbuf_len(mt->sbuf[mt->level]);
|
||||
|
||||
/* <freqband>...</freqband> */
|
||||
if (iseq(name, "freqstart") && mt->freqband != NULL) {
|
||||
mt->freqband->freqStart = strtoul(p, NULL, 0);
|
||||
goto done;
|
||||
}
|
||||
if (iseq(name, "freqend") && mt->freqband != NULL) {
|
||||
mt->freqband->freqEnd = strtoul(p, NULL, 0);
|
||||
goto done;
|
||||
}
|
||||
if (iseq(name, "chanwidth") && mt->freqband != NULL) {
|
||||
mt->freqband->chanWidth = strtoul(p, NULL, 0);
|
||||
goto done;
|
||||
}
|
||||
if (iseq(name, "chansep") && mt->freqband != NULL) {
|
||||
mt->freqband->chanSep = strtoul(p, NULL, 0);
|
||||
goto done;
|
||||
}
|
||||
if (iseq(name, "flags")) {
|
||||
if (mt->freqband != NULL)
|
||||
mt->freqband->flags |= decode_flag(mt, p, len);
|
||||
else if (mt->netband != NULL)
|
||||
mt->netband->flags |= decode_flag(mt, p, len);
|
||||
else {
|
||||
warnx("flags without freqband or netband at line %ld ignored",
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* <rd> ... </rd> */
|
||||
if (iseq(name, "name") && mt->rd != NULL) {
|
||||
mt->rd->name = strdup(p);
|
||||
goto done;
|
||||
}
|
||||
if (iseq(name, "sku") && mt->rd != NULL) {
|
||||
mt->rd->sku = strtoul(p, NULL, 0);
|
||||
goto done;
|
||||
}
|
||||
if (iseq(name, "netband") && mt->rd != NULL) {
|
||||
mt->curband = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* <band> ... </band> */
|
||||
if (iseq(name, "freqband") && mt->netband != NULL) {
|
||||
/* XXX handle inline freqbands */
|
||||
goto done;
|
||||
}
|
||||
if (iseq(name, "maxpower") && mt->netband != NULL) {
|
||||
mt->netband->maxPower = strtoul(p, NULL, 0);
|
||||
goto done;
|
||||
}
|
||||
if (iseq(name, "maxpowerdfs") && mt->netband != NULL) {
|
||||
mt->netband->maxPowerDFS = strtoul(p, NULL, 0);
|
||||
goto done;
|
||||
}
|
||||
if (iseq(name, "maxantgain") && mt->netband != NULL) {
|
||||
mt->netband->maxAntGain = strtoul(p, NULL, 0);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* <country>...</country> */
|
||||
if (iseq(name, "isocc") && mt->country != NULL) {
|
||||
mt->country->code = strtoul(p, NULL, 0);
|
||||
goto done;
|
||||
}
|
||||
if (iseq(name, "name") && mt->country != NULL) {
|
||||
mt->country->name = strdup(p);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (len != 0) {
|
||||
warnx("unexpected XML token \"%s\" data \"%s\" at line %ld",
|
||||
name, p, XML_GetCurrentLineNumber(mt->parser));
|
||||
/* XXX goto done? */
|
||||
}
|
||||
/* </freqband> */
|
||||
if (iseq(name, "freqband") && mt->freqband != NULL) {
|
||||
/* XXX must have start/end frequencies */
|
||||
/* XXX must have channel width/sep */
|
||||
mt->freqband = NULL;
|
||||
goto done;
|
||||
}
|
||||
/* </rd> */
|
||||
if (iseq(name, "rd") && mt->rd != NULL) {
|
||||
mt->rd = NULL;
|
||||
goto done;
|
||||
}
|
||||
/* </band> */
|
||||
if (iseq(name, "band") && mt->netband != NULL) {
|
||||
if (mt->netband->band == NULL) {
|
||||
warnx("no freqbands for band at line %ld",
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
}
|
||||
if (mt->netband->maxPower == 0) {
|
||||
warnx("no maxpower for band at line %ld",
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
}
|
||||
/* default max power w/ DFS to max power */
|
||||
if (mt->netband->maxPowerDFS == 0)
|
||||
mt->netband->maxPowerDFS = mt->netband->maxPower;
|
||||
mt->netband = NULL;
|
||||
goto done;
|
||||
}
|
||||
/* </netband> */
|
||||
if (iseq(name, "netband") && mt->netband != NULL) {
|
||||
mt->curband = NULL;
|
||||
goto done;
|
||||
}
|
||||
/* </country> */
|
||||
if (iseq(name, "country") && mt->country != NULL) {
|
||||
/* XXX NO_COUNTRY should be in the net80211 country enum */
|
||||
if ((int) mt->country->code == NO_COUNTRY) {
|
||||
warnx("no ISO cc for country at line %ld",
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
}
|
||||
if (mt->country->name == NULL) {
|
||||
warnx("no name for country at line %ld",
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
}
|
||||
if (mt->country->rd == NULL) {
|
||||
warnx("no regdomain reference for country at line %ld",
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
}
|
||||
mt->country = NULL;
|
||||
goto done;
|
||||
}
|
||||
done:
|
||||
sbuf_delete(mt->sbuf[mt->level]);
|
||||
mt->sbuf[mt->level--] = NULL;
|
||||
#undef iseq
|
||||
}
|
||||
|
||||
static void
|
||||
char_data(void *data, const XML_Char *s, int len)
|
||||
{
|
||||
struct mystate *mt;
|
||||
const char *b, *e;
|
||||
|
||||
mt = data;
|
||||
|
||||
b = s;
|
||||
e = s + len-1;
|
||||
for (; isspace(*b) && b < e; b++)
|
||||
;
|
||||
for (; isspace(*e) && e > b; e++)
|
||||
;
|
||||
if (e != b || (*b != '\0' && !isspace(*b)))
|
||||
sbuf_bcat(mt->sbuf[mt->level], b, e-b+1);
|
||||
}
|
||||
|
||||
static void *
|
||||
findid(struct regdata *rdp, const void *id, int type)
|
||||
{
|
||||
struct ident *ip;
|
||||
|
||||
for (ip = rdp->ident; ip->id != NULL; ip++)
|
||||
if ((int) ip->type == type && strcasecmp(ip->id, id) == 0)
|
||||
return ip->p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse an regdomain XML configuration and build the internal representation.
|
||||
*/
|
||||
int
|
||||
lib80211_regdomain_readconfig(struct regdata *rdp, const void *p, size_t len)
|
||||
{
|
||||
struct mystate *mt;
|
||||
struct regdomain *dp;
|
||||
struct country *cp;
|
||||
struct freqband *fp;
|
||||
struct netband *nb;
|
||||
const void *id;
|
||||
int i, errors;
|
||||
|
||||
memset(rdp, 0, sizeof(struct regdata));
|
||||
mt = calloc(1, sizeof(struct mystate));
|
||||
if (mt == NULL)
|
||||
return ENOMEM;
|
||||
/* parse the XML input */
|
||||
mt->rdp = rdp;
|
||||
mt->parser = XML_ParserCreate(NULL);
|
||||
XML_SetUserData(mt->parser, mt);
|
||||
XML_SetElementHandler(mt->parser, start_element, end_element);
|
||||
XML_SetCharacterDataHandler(mt->parser, char_data);
|
||||
if (XML_Parse(mt->parser, p, len, 1) != XML_STATUS_OK) {
|
||||
warnx("%s: %s at line %ld", __func__,
|
||||
XML_ErrorString(XML_GetErrorCode(mt->parser)),
|
||||
XML_GetCurrentLineNumber(mt->parser));
|
||||
return -1;
|
||||
}
|
||||
XML_ParserFree(mt->parser);
|
||||
|
||||
/* setup the identifer table */
|
||||
rdp->ident = calloc(sizeof(struct ident), mt->nident + 1);
|
||||
if (rdp->ident == NULL)
|
||||
return ENOMEM;
|
||||
free(mt);
|
||||
|
||||
errors = 0;
|
||||
i = 0;
|
||||
LIST_FOREACH(dp, &rdp->domains, next) {
|
||||
rdp->ident[i].id = dp->name;
|
||||
rdp->ident[i].p = dp;
|
||||
rdp->ident[i].type = DOMAIN;
|
||||
i++;
|
||||
}
|
||||
LIST_FOREACH(fp, &rdp->freqbands, next) {
|
||||
rdp->ident[i].id = fp->id;
|
||||
rdp->ident[i].p = fp;
|
||||
rdp->ident[i].type = FREQBAND;
|
||||
i++;
|
||||
}
|
||||
LIST_FOREACH(cp, &rdp->countries, next) {
|
||||
rdp->ident[i].id = cp->isoname;
|
||||
rdp->ident[i].p = cp;
|
||||
rdp->ident[i].type = COUNTRY;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* patch references */
|
||||
LIST_FOREACH(dp, &rdp->domains, next) {
|
||||
if (dp->cc != NULL) {
|
||||
id = dp->cc;
|
||||
dp->cc = findid(rdp, id, COUNTRY);
|
||||
if (dp->cc == NULL) {
|
||||
warnx("undefined country \"%s\"",
|
||||
__DECONST(char *, id));
|
||||
errors++;
|
||||
}
|
||||
free(__DECONST(char *, id));
|
||||
}
|
||||
LIST_FOREACH(nb, &dp->bands_11b, next) {
|
||||
id = findid(rdp, nb->band, FREQBAND);
|
||||
if (id == NULL) {
|
||||
warnx("undefined 11b band \"%s\"",
|
||||
__DECONST(char *, nb->band));
|
||||
errors++;
|
||||
}
|
||||
nb->band = id;
|
||||
}
|
||||
LIST_FOREACH(nb, &dp->bands_11g, next) {
|
||||
id = findid(rdp, nb->band, FREQBAND);
|
||||
if (id == NULL) {
|
||||
warnx("undefined 11g band \"%s\"",
|
||||
__DECONST(char *, nb->band));
|
||||
errors++;
|
||||
}
|
||||
nb->band = id;
|
||||
}
|
||||
LIST_FOREACH(nb, &dp->bands_11a, next) {
|
||||
id = findid(rdp, nb->band, FREQBAND);
|
||||
if (id == NULL) {
|
||||
warnx("undefined 11a band \"%s\"",
|
||||
__DECONST(char *, nb->band));
|
||||
errors++;
|
||||
}
|
||||
nb->band = id;
|
||||
}
|
||||
LIST_FOREACH(nb, &dp->bands_11ng, next) {
|
||||
id = findid(rdp, nb->band, FREQBAND);
|
||||
if (id == NULL) {
|
||||
warnx("undefined 11ng band \"%s\"",
|
||||
__DECONST(char *, nb->band));
|
||||
errors++;
|
||||
}
|
||||
nb->band = id;
|
||||
}
|
||||
LIST_FOREACH(nb, &dp->bands_11na, next) {
|
||||
id = findid(rdp, nb->band, FREQBAND);
|
||||
if (id == NULL) {
|
||||
warnx("undefined 11na band \"%s\"",
|
||||
__DECONST(char *, nb->band));
|
||||
errors++;
|
||||
}
|
||||
nb->band = id;
|
||||
}
|
||||
}
|
||||
LIST_FOREACH(cp, &rdp->countries, next) {
|
||||
id = cp->rd;
|
||||
cp->rd = findid(rdp, id, DOMAIN);
|
||||
if (cp->rd == NULL) {
|
||||
warnx("undefined country \"%s\"",
|
||||
__DECONST(char *, id));
|
||||
errors++;
|
||||
}
|
||||
free(__DECONST(char *, id));
|
||||
}
|
||||
|
||||
return errors ? EINVAL : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_bands(netband_head *head)
|
||||
{
|
||||
struct netband *nb;
|
||||
|
||||
for (;;) {
|
||||
nb = LIST_FIRST(head);
|
||||
if (nb == NULL)
|
||||
break;
|
||||
free(nb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup state/resources for a previously parsed regdomain database.
|
||||
*/
|
||||
void
|
||||
lib80211_regdomain_cleanup(struct regdata *rdp)
|
||||
{
|
||||
|
||||
free(rdp->ident);
|
||||
rdp->ident = NULL;
|
||||
for (;;) {
|
||||
struct regdomain *dp = LIST_FIRST(&rdp->domains);
|
||||
if (dp == NULL)
|
||||
break;
|
||||
LIST_REMOVE(dp, next);
|
||||
cleanup_bands(&dp->bands_11b);
|
||||
cleanup_bands(&dp->bands_11g);
|
||||
cleanup_bands(&dp->bands_11a);
|
||||
cleanup_bands(&dp->bands_11ng);
|
||||
cleanup_bands(&dp->bands_11na);
|
||||
if (dp->name != NULL)
|
||||
free(__DECONST(char *, dp->name));
|
||||
}
|
||||
for (;;) {
|
||||
struct country *cp = LIST_FIRST(&rdp->countries);
|
||||
if (cp == NULL)
|
||||
break;
|
||||
LIST_REMOVE(cp, next);
|
||||
if (cp->name != NULL)
|
||||
free(__DECONST(char *, cp->name));
|
||||
free(cp);
|
||||
}
|
||||
for (;;) {
|
||||
struct freqband *fp = LIST_FIRST(&rdp->freqbands);
|
||||
if (fp == NULL)
|
||||
break;
|
||||
LIST_REMOVE(fp, next);
|
||||
free(fp);
|
||||
}
|
||||
}
|
||||
|
||||
struct regdata *
|
||||
lib80211_alloc_regdata(void)
|
||||
{
|
||||
struct regdata *rdp;
|
||||
struct stat sb;
|
||||
void *xml;
|
||||
int fd;
|
||||
|
||||
rdp = calloc(1, sizeof(struct regdata));
|
||||
|
||||
fd = open(_PATH_REGDOMAIN, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
#ifdef DEBUG
|
||||
warn("%s: open(%s)", __func__, _PATH_REGDOMAIN);
|
||||
#endif
|
||||
free(rdp);
|
||||
return NULL;
|
||||
}
|
||||
if (fstat(fd, &sb) < 0) {
|
||||
#ifdef DEBUG
|
||||
warn("%s: fstat(%s)", __func__, _PATH_REGDOMAIN);
|
||||
#endif
|
||||
close(fd);
|
||||
free(rdp);
|
||||
return NULL;
|
||||
}
|
||||
xml = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (xml == MAP_FAILED) {
|
||||
#ifdef DEBUG
|
||||
warn("%s: mmap", __func__);
|
||||
#endif
|
||||
close(fd);
|
||||
free(rdp);
|
||||
return NULL;
|
||||
}
|
||||
if (lib80211_regdomain_readconfig(rdp, xml, sb.st_size) != 0) {
|
||||
#ifdef DEBUG
|
||||
warn("%s: error reading regulatory database", __func__);
|
||||
#endif
|
||||
munmap(xml, sb.st_size);
|
||||
close(fd);
|
||||
free(rdp);
|
||||
return NULL;
|
||||
}
|
||||
munmap(xml, sb.st_size);
|
||||
close(fd);
|
||||
|
||||
return rdp;
|
||||
}
|
||||
|
||||
void
|
||||
lib80211_free_regdata(struct regdata *rdp)
|
||||
{
|
||||
lib80211_regdomain_cleanup(rdp);
|
||||
free(rdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a regdomain by SKU.
|
||||
*/
|
||||
const struct regdomain *
|
||||
lib80211_regdomain_findbysku(const struct regdata *rdp, enum RegdomainCode sku)
|
||||
{
|
||||
const struct regdomain *dp;
|
||||
|
||||
LIST_FOREACH(dp, &rdp->domains, next) {
|
||||
if (dp->sku == sku)
|
||||
return dp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a regdomain by name.
|
||||
*/
|
||||
const struct regdomain *
|
||||
lib80211_regdomain_findbyname(const struct regdata *rdp, const char *name)
|
||||
{
|
||||
const struct regdomain *dp;
|
||||
|
||||
LIST_FOREACH(dp, &rdp->domains, next) {
|
||||
if (strcasecmp(dp->name, name) == 0)
|
||||
return dp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a country by ISO country code.
|
||||
*/
|
||||
const struct country *
|
||||
lib80211_country_findbycc(const struct regdata *rdp, enum ISOCountryCode cc)
|
||||
{
|
||||
const struct country *cp;
|
||||
|
||||
LIST_FOREACH(cp, &rdp->countries, next) {
|
||||
if (cp->code == cc)
|
||||
return cp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a country by ISO/long name.
|
||||
*/
|
||||
const struct country *
|
||||
lib80211_country_findbyname(const struct regdata *rdp, const char *name)
|
||||
{
|
||||
const struct country *cp;
|
||||
int len;
|
||||
|
||||
len = strlen(name);
|
||||
LIST_FOREACH(cp, &rdp->countries, next) {
|
||||
if (strcasecmp(cp->isoname, name) == 0)
|
||||
return cp;
|
||||
}
|
||||
LIST_FOREACH(cp, &rdp->countries, next) {
|
||||
if (strncasecmp(cp->name, name, len) == 0)
|
||||
return cp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
121
lib/lib80211/lib80211_regdomain.h
Normal file
121
lib/lib80211/lib80211_regdomain.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*-
|
||||
* Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#ifndef _LIB80211_REGDOMAIN_H_
|
||||
#define _LIB80211_REGDOMAIN_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <net80211/ieee80211_regdomain.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct freqband {
|
||||
uint16_t freqStart; /* starting frequency (MHz) */
|
||||
uint16_t freqEnd; /* ending frequency (MHz) */
|
||||
uint8_t chanWidth; /* channel width (MHz) */
|
||||
uint8_t chanSep; /* channel sepaaration (MHz) */
|
||||
uint32_t flags; /* common operational constraints */
|
||||
|
||||
const void *id;
|
||||
LIST_ENTRY(freqband) next;
|
||||
};
|
||||
|
||||
/* private flags, don't pass to os */
|
||||
#define REQ_ECM 0x1 /* enable if ECM set */
|
||||
#define REQ_INDOOR 0x2 /* enable only for indoor operation */
|
||||
#define REQ_OUTDOOR 0x4 /* enable only for outdoor operation */
|
||||
|
||||
#define REQ_FLAGS (REQ_ECM|REQ_INDOOR|REQ_OUTDOOR)
|
||||
|
||||
struct netband {
|
||||
const struct freqband *band; /* channel list description */
|
||||
uint8_t maxPower; /* regulatory cap on tx power (dBm) */
|
||||
uint8_t maxPowerDFS; /* regulatory cap w/ DFS (dBm) */
|
||||
uint8_t maxAntGain; /* max allowed antenna gain (.5 dBm) */
|
||||
uint32_t flags; /* net80211 channel flags */
|
||||
|
||||
LIST_ENTRY(netband) next;
|
||||
};
|
||||
typedef LIST_HEAD(, netband) netband_head;
|
||||
|
||||
struct country;
|
||||
|
||||
struct regdomain {
|
||||
enum RegdomainCode sku; /* regdomain code/SKU */
|
||||
const char *name; /* printable name */
|
||||
const struct country *cc; /* country code for 1-1/default map */
|
||||
|
||||
netband_head bands_11b; /* 11b operation */
|
||||
netband_head bands_11g; /* 11g operation */
|
||||
netband_head bands_11a; /* 11a operation */
|
||||
netband_head bands_11ng;/* 11ng operation */
|
||||
netband_head bands_11na;/* 11na operation */
|
||||
|
||||
LIST_ENTRY(regdomain) next;
|
||||
};
|
||||
|
||||
struct country {
|
||||
enum ISOCountryCode code;
|
||||
#define NO_COUNTRY 0xffff
|
||||
const struct regdomain *rd;
|
||||
const char* isoname;
|
||||
const char* name;
|
||||
|
||||
LIST_ENTRY(country) next;
|
||||
};
|
||||
|
||||
struct ident;
|
||||
|
||||
struct regdata {
|
||||
LIST_HEAD(, country) countries; /* country code table */
|
||||
LIST_HEAD(, regdomain) domains; /* regulatory domains */
|
||||
LIST_HEAD(, freqband) freqbands; /* frequency band table */
|
||||
struct ident *ident; /* identifier table */
|
||||
};
|
||||
|
||||
#define _PATH_REGDOMAIN "/etc/regdomain.xml"
|
||||
|
||||
struct regdata *lib80211_alloc_regdata(void);
|
||||
void lib80211_free_regdata(struct regdata *);
|
||||
|
||||
int lib80211_regdomain_readconfig(struct regdata *, const void *, size_t);
|
||||
void lib80211_regdomain_cleanup(struct regdata *);
|
||||
|
||||
const struct regdomain *lib80211_regdomain_findbysku(const struct regdata *,
|
||||
enum RegdomainCode);
|
||||
const struct regdomain *lib80211_regdomain_findbyname(const struct regdata *,
|
||||
const char *);
|
||||
|
||||
const struct country *lib80211_country_findbycc(const struct regdata *,
|
||||
enum ISOCountryCode);
|
||||
const struct country *lib80211_country_findbyname(const struct regdata *,
|
||||
const char *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _LIB80211_REGDOMAIN_H_ */
|
Loading…
Reference in New Issue
Block a user