Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Nov 2015 04:41:50 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r291464 - in head/lib: . lib80211
Message-ID:  <201511300441.tAU4foZb066520@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Mon Nov 30 04:41:50 2015
New Revision: 291464
URL: https://svnweb.freebsd.org/changeset/base/291464

Log:
  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

Added:
  head/lib/lib80211/
  head/lib/lib80211/Makefile   (contents, props changed)
  head/lib/lib80211/lib80211.3   (contents, props changed)
  head/lib/lib80211/lib80211_ioctl.c   (contents, props changed)
  head/lib/lib80211/lib80211_ioctl.h   (contents, props changed)
  head/lib/lib80211/lib80211_regdomain.c   (contents, props changed)
  head/lib/lib80211/lib80211_regdomain.h   (contents, props changed)
Modified:
  head/lib/Makefile

Modified: head/lib/Makefile
==============================================================================
--- head/lib/Makefile	Mon Nov 30 02:40:41 2015	(r291463)
+++ head/lib/Makefile	Mon Nov 30 04:41:50 2015	(r291464)
@@ -71,6 +71,7 @@ SUBDIR=	${SUBDIR_ORDERED} \
 	${_libmp} \
 	libmt \
 	${_libnandfs} \
+	lib80211 \
 	libnetbsd \
 	${_libnetgraph} \
 	${_libngatm} \

Added: head/lib/lib80211/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/lib80211/Makefile	Mon Nov 30 04:41:50 2015	(r291464)
@@ -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>

Added: head/lib/lib80211/lib80211.3
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/lib80211/lib80211.3	Mon Nov 30 04:41:50 2015	(r291464)
@@ -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

Added: head/lib/lib80211/lib80211_ioctl.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/lib80211/lib80211_ioctl.c	Mon Nov 30 04:41:50 2015	(r291464)
@@ -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);
+}
+

Added: head/lib/lib80211/lib80211_ioctl.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/lib80211/lib80211_ioctl.h	Mon Nov 30 04:41:50 2015	(r291464)
@@ -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__ */

Added: head/lib/lib80211/lib80211_regdomain.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/lib80211/lib80211_regdomain.c	Mon Nov 30 04:41:50 2015	(r291464)
@@ -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);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201511300441.tAU4foZb066520>