Improve regdomain.xml parser:

o store XML_Parser in the state block so we can report line numbers for errors
o complain about netband w/o mode
o complain about unknown modes
o complain about band w/o enclosing netband
o complain about duplicate freqband
o complain about unknown channel flags
o complain about band w/o freqband's
o complain about band w/o maxpower
o complain about country w/o ISO cc
o complain about country w/o regdomain reference
This commit is contained in:
Sam Leffler 2008-12-15 01:00:18 +00:00
parent 1b999d643c
commit cf0d500765
2 changed files with 43 additions and 30 deletions

View File

@ -48,6 +48,7 @@ static const char rcsid[] = "$FreeBSD$";
#define MAXLEVEL 20 #define MAXLEVEL 20
struct mystate { struct mystate {
XML_Parser parser;
struct regdata *rdp; struct regdata *rdp;
struct regdomain *rd; /* current domain */ struct regdomain *rd; /* current domain */
struct netband *netband; /* current netband */ struct netband *netband; /* current netband */
@ -107,7 +108,8 @@ start_element(void *data, const char *name, const char **attr)
} }
if (iseq(name, "netband") && mt->curband == NULL && mt->rd != NULL) { if (iseq(name, "netband") && mt->curband == NULL && mt->rd != NULL) {
if (mode == NULL) { if (mode == NULL) {
/* XXX complain */ warnx("no mode for netband at line %ld",
XML_GetCurrentLineNumber(mt->parser));
return; return;
} }
if (iseq(mode, "11b")) if (iseq(mode, "11b"))
@ -120,12 +122,16 @@ start_element(void *data, const char *name, const char **attr)
mt->curband = &mt->rd->bands_11ng; mt->curband = &mt->rd->bands_11ng;
else if (iseq(mode, "11na")) else if (iseq(mode, "11na"))
mt->curband = &mt->rd->bands_11na; mt->curband = &mt->rd->bands_11na;
/* XXX else complain */ else
warnx("unknown mode \"%s\" at line %ld",
__DECONST(char *, mode),
XML_GetCurrentLineNumber(mt->parser));
return; return;
} }
if (iseq(name, "band") && mt->netband == NULL) { if (iseq(name, "band") && mt->netband == NULL) {
if (mt->curband == NULL) { if (mt->curband == NULL) {
/* XXX complain */ warnx("band without enclosing netband at line %ld",
XML_GetCurrentLineNumber(mt->parser));
return; return;
} }
mt->netband = calloc(1, sizeof(struct netband)); mt->netband = calloc(1, sizeof(struct netband));
@ -135,6 +141,8 @@ start_element(void *data, const char *name, const char **attr)
if (iseq(name, "freqband") && mt->freqband == NULL && mt->netband != NULL) { if (iseq(name, "freqband") && mt->freqband == NULL && mt->netband != NULL) {
/* XXX handle inlines and merge into table? */ /* XXX handle inlines and merge into table? */
if (mt->netband->band != NULL) { if (mt->netband->band != NULL) {
warnx("duplicate freqband at line %ld ignored",
XML_GetCurrentLineNumber(mt->parser));
/* XXX complain */ /* XXX complain */
} else } else
mt->netband->band = (void *)strdup(ref); mt->netband->band = (void *)strdup(ref);
@ -144,6 +152,7 @@ start_element(void *data, const char *name, const char **attr)
if (iseq(name, "country") && mt->country == NULL) { if (iseq(name, "country") && mt->country == NULL) {
mt->country = calloc(1, sizeof(struct country)); mt->country = calloc(1, sizeof(struct country));
mt->country->isoname = strdup(id); mt->country->isoname = strdup(id);
mt->country->code = NO_COUNTRY;
mt->nident++; mt->nident++;
LIST_INSERT_HEAD(&mt->rdp->countries, mt->country, next); LIST_INSERT_HEAD(&mt->rdp->countries, mt->country, next);
return; return;
@ -159,8 +168,8 @@ start_element(void *data, const char *name, const char **attr)
#undef iseq #undef iseq
} }
static uint32_t static int
decode_flag(const char *p, int len) decode_flag(struct mystate *mt, const char *p, int len)
{ {
#define iseq(a,b) (strcasecmp(a,b) == 0) #define iseq(a,b) (strcasecmp(a,b) == 0)
static const struct { static const struct {
@ -168,7 +177,7 @@ decode_flag(const char *p, int len)
int len; int len;
uint32_t value; uint32_t value;
} flags[] = { } flags[] = {
#define FLAG(x) { #x, sizeof(#x), x } #define FLAG(x) { #x, sizeof(#x)-1, x }
FLAG(IEEE80211_CHAN_A), FLAG(IEEE80211_CHAN_A),
FLAG(IEEE80211_CHAN_B), FLAG(IEEE80211_CHAN_B),
FLAG(IEEE80211_CHAN_G), FLAG(IEEE80211_CHAN_G),
@ -205,6 +214,8 @@ decode_flag(const char *p, int len)
for (i = 0; i < sizeof(flags)/sizeof(flags[0]); i++) for (i = 0; i < sizeof(flags)/sizeof(flags[0]); i++)
if (len == flags[i].len && iseq(p, flags[i].name)) if (len == flags[i].len && iseq(p, flags[i].name))
return flags[i].value; return flags[i].value;
warnx("unknown flag \"%.*s\" at line %ld ignored",
len, p, XML_GetCurrentLineNumber(mt->parser));
return 0; return 0;
#undef iseq #undef iseq
} }
@ -241,11 +252,12 @@ end_element(void *data, const char *name)
} }
if (iseq(name, "flags")) { if (iseq(name, "flags")) {
if (mt->freqband != NULL) if (mt->freqband != NULL)
mt->freqband->flags |= decode_flag(p, len); mt->freqband->flags |= decode_flag(mt, p, len);
else if (mt->netband != NULL) else if (mt->netband != NULL)
mt->netband->flags |= decode_flag(p, len); mt->netband->flags |= decode_flag(mt, p, len);
else { else {
/* XXX complain */ warnx("flags without freqband or netband at line %ld ignored",
XML_GetCurrentLineNumber(mt->parser));
} }
goto done; goto done;
} }
@ -289,7 +301,8 @@ end_element(void *data, const char *name)
} }
if (len != 0) { if (len != 0) {
printf("Unexpected XML: name \"%s\" data \"%s\"\n", name, p); warnx("unexpected XML token \"%s\" data \"%s\" at line %ld",
name, p, XML_GetCurrentLineNumber(mt->parser));
/* XXX goto done? */ /* XXX goto done? */
} }
/* </freqband> */ /* </freqband> */
@ -307,15 +320,12 @@ end_element(void *data, const char *name)
/* </band> */ /* </band> */
if (iseq(name, "band") && mt->netband != NULL) { if (iseq(name, "band") && mt->netband != NULL) {
if (mt->netband->band == NULL) { if (mt->netband->band == NULL) {
printf("No frequency band information at line %d\n", warnx("no freqbands for band at line %ld",
#if 0 XML_GetCurrentLineNumber(mt->parser));
XML_GetCurrentLineNumber(parser));
#else
0);
#endif
} }
if (mt->netband->maxPower == 0) { if (mt->netband->maxPower == 0) {
/* XXX complain */ warnx("no maxpower for band at line %ld",
XML_GetCurrentLineNumber(mt->parser));
} }
/* default max power w/ DFS to max power */ /* default max power w/ DFS to max power */
if (mt->netband->maxPowerDFS == 0) if (mt->netband->maxPowerDFS == 0)
@ -330,14 +340,17 @@ end_element(void *data, const char *name)
} }
/* </country> */ /* </country> */
if (iseq(name, "country") && mt->country != NULL) { if (iseq(name, "country") && mt->country != NULL) {
if (mt->country->code == 0) { if (mt->country->code == NO_COUNTRY) {
/* XXX must have iso cc */ warnx("no ISO cc for country at line %ld",
XML_GetCurrentLineNumber(mt->parser));
} }
if (mt->country->name == NULL) { if (mt->country->name == NULL) {
/* XXX must have name */ warnx("no name for country at line %ld",
XML_GetCurrentLineNumber(mt->parser));
} }
if (mt->country->rd == NULL) { if (mt->country->rd == NULL) {
/* XXX? rd ref? */ warnx("no regdomain reference for country at line %ld",
XML_GetCurrentLineNumber(mt->parser));
} }
mt->country = NULL; mt->country = NULL;
goto done; goto done;
@ -383,7 +396,6 @@ findid(struct regdata *rdp, const void *id, int type)
int int
lib80211_regdomain_readconfig(struct regdata *rdp, const void *p, size_t len) lib80211_regdomain_readconfig(struct regdata *rdp, const void *p, size_t len)
{ {
XML_Parser parser;
struct mystate *mt; struct mystate *mt;
struct regdomain *dp; struct regdomain *dp;
struct country *cp; struct country *cp;
@ -398,17 +410,17 @@ lib80211_regdomain_readconfig(struct regdata *rdp, const void *p, size_t len)
return ENOMEM; return ENOMEM;
/* parse the XML input */ /* parse the XML input */
mt->rdp = rdp; mt->rdp = rdp;
parser = XML_ParserCreate(NULL); mt->parser = XML_ParserCreate(NULL);
XML_SetUserData(parser, mt); XML_SetUserData(mt->parser, mt);
XML_SetElementHandler(parser, start_element, end_element); XML_SetElementHandler(mt->parser, start_element, end_element);
XML_SetCharacterDataHandler(parser, char_data); XML_SetCharacterDataHandler(mt->parser, char_data);
if (XML_Parse(parser, p, len, 1) != XML_STATUS_OK) { if (XML_Parse(mt->parser, p, len, 1) != XML_STATUS_OK) {
warnx("%s: %s at line %ld", __func__, warnx("%s: %s at line %ld", __func__,
XML_ErrorString(XML_GetErrorCode(parser)), XML_ErrorString(XML_GetErrorCode(mt->parser)),
XML_GetCurrentLineNumber(parser)); XML_GetCurrentLineNumber(mt->parser));
return -1; return -1;
} }
XML_ParserFree(parser); XML_ParserFree(mt->parser);
/* setup the identifer table */ /* setup the identifer table */
rdp->ident = calloc(sizeof(struct ident), mt->nident + 1); rdp->ident = calloc(sizeof(struct ident), mt->nident + 1);

View File

@ -73,6 +73,7 @@ struct regdomain {
struct country { struct country {
enum ISOCountryCode code; enum ISOCountryCode code;
#define NO_COUNTRY 0xffff
const struct regdomain *rd; const struct regdomain *rd;
const char* isoname; const char* isoname;
const char* name; const char* name;