PERFORCE change 127144 for review
Fredrik Lindberg
fli at FreeBSD.org
Wed Oct 3 14:11:16 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=127144
Change 127144 by fli at fli_nexus on 2007/10/03 21:11:03
- Follow changes to the record subsystem.
- Make dbr_init() return an int to indicate success/failure.
- Better failure handling (NULL checks etc)
- Clean up the header file.
- Minor fixes and comments.
Affected files ...
.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/dbrec.c#8 edit
.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/dbrec.h#5 edit
Differences ...
==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/dbrec.c#8 (text+ko) ====
@@ -33,6 +33,7 @@
#include "output.h"
#include "record.h"
#include "log.h"
+#include "util.h"
#include "var.h"
static void rec_update(struct dbr_ident *, struct vt_data *, size_t);
@@ -60,20 +61,30 @@
/*
* Initialize a database record system
*/
-void
+int
dbr_init(struct dbr *dbr, void *context)
{
struct md_if *mif = context;
+ int error;
dbr->dbr_ctx = context;
- MDNS_INIT_SET(dbr, dbr_magic);
- hashtbl_init(&dbr->dbr_ident, 8, 512, 3);
+ error = hashtbl_init(&dbr->dbr_ident, 8, 512, 3);
+ if (error != 0)
+ goto dbr_init_fail;
TAILQ_INIT(&dbr->dbr_ilist);
+ MDNS_INIT_SET(dbr, dbr_magic);
var_init(&dbr->dbr_vars, mif->mif_glob->g_evl, dbr);
- /* We only do the IN class */
- records_init(&dbr->dbr_recs, mdns_c_in);
- dprintf(DEBUG_DBR, "Database records initialized");
+ error = records_init(&dbr->dbr_recs);
+ if (error != 0)
+ goto dbr_init_fail2;
+ dprintf(DEBUG_DBR, "Record database initialized");
+ return (0);
+dbr_init_fail2:
+ hashtbl_destroy(&dbr->dbr_ident);
+dbr_init_fail:
+ dprintf(DEBUG_DBR, "Failed to initialize record database");
+ return (-1);
}
/*
@@ -303,6 +314,7 @@
{
struct dbr_ident *dbi;
size_t ilen;
+ int error;
ilen = strlen(ident);
@@ -314,12 +326,12 @@
dbi->dbi_flags &= flags;
dbi->dbi_flags |= flags;
- goto out;
+ goto dbr_ident_fail;
}
dbi = malloc(sizeof(struct dbr_ident));
if (dbi == NULL)
- goto out;
+ goto dbr_ident_fail;
bzero(dbi, sizeof(struct dbr_ident));
MTX_INIT(dbi, dbi_mtx, NULL);
dbi->dbi_dbr = dbr;
@@ -330,14 +342,20 @@
TAILQ_INIT(&dbi->dbi_res_ptr);
MDNS_INIT_SET(dbi, dbi_magic);
+ error = hashtbl_add(&dbr->dbr_ident, dbi->dbi_ident, ilen, dbi, 0);
+ if (error != 0) {
+ free(dbi->dbi_ident);
+ free(dbi);
+ goto dbr_ident_fail;
+ }
TAILQ_INSERT_TAIL(&dbr->dbr_ilist, dbi, dbi_next);
- hashtbl_add(&dbr->dbr_ident, dbi->dbi_ident, ilen, dbi, 0);
dprintf(DEBUG_DBR, "Added record set identifier %s, dbi=%x",
ident, dbi);
RW_UNLOCK(dbr, dbr_lock);
return (0);
-out:
+dbr_ident_fail:
+ dprintf(DEBUG_DBR, "Failed to add record set identifier %s", ident);
RW_UNLOCK(dbr, dbr_lock);
return (-1);
}
@@ -420,7 +438,8 @@
{
struct dbr_ident *dbi;
char **ident;
- int i;
+ void *tmp;
+ int i, j;
MDNS_INIT_ASSERT(dbr, dbr_magic);
@@ -429,15 +448,30 @@
RW_RLOCK(dbr, dbr_lock);
TAILQ_FOREACH(dbi, &dbr->dbr_ilist, dbi_next) {
MDNS_INIT_ASSERT(dbi, dbi_magic);
- ident = realloc(ident, sizeof(char *) * ++i);
+ tmp = realloc(ident, sizeof(char *) * ++i);
+ if (tmp == NULL) {
+ i--;
+ goto dbr_ident_list_fail;
+ }
+ ident = tmp;
ident[i - 1] = strdup(dbi->dbi_ident);
+ if (ident[i - 1] == NULL)
+ goto dbr_ident_list_fail;
}
RW_UNLOCK(dbr, dbr_lock);
- ident = realloc(ident, sizeof(char *) * ++i);
+ tmp = realloc(ident, sizeof(char *) * ++i);
+ if (tmp == NULL)
+ goto dbr_ident_list_fail;
ident[i - 1] = NULL;
return (ident);
+dbr_ident_list_fail:
+ for (j = 0; j < i; j++)
+ free(ident[j]);
+ if (ident != NULL)
+ free(ident);
+ return (NULL);
}
/*
@@ -953,7 +987,9 @@
struct record *r;
size_t i, vtd_len;
struct vt_data *vtd;
+ struct recpar rp;
char *p;
+ int error;
dbr = dbi->dbi_dbr;
MDNS_INIT_ASSERT(dbr, dbr_magic);
@@ -968,10 +1004,15 @@
MDNS_INIT_SET(dr, dr_magic);
p = mdns_name_encode(nam, wcslen(nam), MDNS_ENC_AUTO);
+ if (p == NULL)
+ goto rec_add_fail;
r = &dr->dr_rec;
- record_get(&dbr->dbr_recs, &r, RECORD_NOALLOC, p);
- record_setparent(r, dr);
+ rp.rp_handle = dr;
+ rp.rp_del_cb = NULL;
+ error = record_get(&dbr->dbr_recs, &r, &rp, REC_NOALLOC, p);
free(p);
+ if (error != 0)
+ goto rec_add_fail;
TAILQ_INSERT_TAIL(&dbi->dbi_rech, dr, dr_next);
dbi->dbi_records++;
@@ -987,10 +1028,8 @@
dr2 = TAILQ_FIRST(&dbi2->dbi_rech);
dsh = res_add(dr, dir, NULL, dr2->dr_name);
- while ((dr2 = TAILQ_NEXT(dr2, dr_next))
- != NULL) {
+ while ((dr2 = TAILQ_NEXT(dr2, dr_next)) != NULL)
res_add(dr, dir, dsh, dr2->dr_name);
- }
}
else {
vtd = var_expand(&dbr->dbr_vars, dir->dir_data.wp,
@@ -1002,8 +1041,12 @@
var_vtdfree(vtd, vtd_len);
}
}
-
+ dprintf(DEBUG_DBR, "Added real record, nam=%ls", nam);
return (dr);
+rec_add_fail:
+ free(dr->dr_name);
+ dprintf(DEBUG_DBR, "Failed to add record to database, nam=%ls", nam);
+ return (NULL);
}
/*
@@ -1050,8 +1093,8 @@
struct dbr_res *ds, *ds2;
struct dbr_rec *dr;
size_t rlen;
- ssize_t diff;
char *p;
+ int error;
uint32_t i;
assert(dsh->ds_chead == dsh);
@@ -1070,16 +1113,65 @@
if (dsh->ds_data != NULL)
free(dsh->ds_data);
- dsh->ds_data = _wcsdup(res[0]);
- p = mdns_res_encode(dir->dir_class, dir->dir_type, res[0],
- MDNS_ENC_WCHAR, wcslen(res[0]), &rlen);
- record_res_setdata(&dsh->ds_res, p, rlen);
+
+ /*
+ * Try each resource, continue for as long as there are resources
+ * and they keep failing.
+ */
+ for (i = 0; i < reslen; i++) {
+ p = mdns_res_encode(dir->dir_class, dir->dir_type, res[i],
+ MDNS_ENC_WCHAR, wcslen(res[i]), &rlen);
+ if (p == NULL)
+ continue;
+ error = record_res_setdata(&dsh->ds_res, REC_RESOWN, p, rlen);
+ if (error != 0) {
+ free(p);
+ continue;
+ }
+ dsh->ds_data = _wcsdup(res[i]);
+ i++;
+ break;
+ }
- i = 1;
/*
* Replace resource data as long as there is enough clones
* and results available.
*/
+ ds = TAILQ_FIRST(&dsh->ds_clone.head);
+ for (; i < reslen; i++) {
+ if (ds == NULL)
+ break;
+ if (ds->ds_data != NULL)
+ free(ds->ds_data);
+ ds->ds_data = _wcsdup(res[i]);
+
+ p = mdns_res_encode(dir->dir_class, dir->dir_type, res[i],
+ MDNS_ENC_WCHAR, wcslen(res[i]), &rlen);
+ if (p == NULL)
+ continue;
+ error = record_res_setdata(&ds->ds_res, REC_RESOWN, p, rlen);
+ if (error != 0)
+ continue;
+
+ ds = TAILQ_NEXT(ds, ds_next);
+ }
+
+ if (ds == NULL) {
+ /* More results than clones, expand */
+ for (; i < reslen; i++) {
+ res_add(dr, dir, dsh, res[i]);
+ }
+ }
+ else {
+ /* More clones than results, shrink */
+ while (ds != NULL) {
+ ds2 = TAILQ_NEXT(ds, ds_next);
+ res_del(ds);
+ ds = ds2;
+ }
+ }
+
+#if 0
TAILQ_FOREACH(ds, &dsh->ds_clone.head, ds_clone.next) {
if (i == dsh->ds_clones || i == reslen)
break;
@@ -1089,7 +1181,14 @@
p = mdns_res_encode(dir->dir_class, dir->dir_type, res[i],
MDNS_ENC_WCHAR, wcslen(res[i]), &rlen);
- record_res_setdata(&ds->ds_res, p, rlen);
+ if (p == NULL) {
+ dprintf(DEBUG_DBR, "Failed to encode resource");
+ continue;
+ }
+ error = record_res_setdata(&ds->ds_res, REC_RESOWN, p, rlen);
+ if (error != 0) {
+
+ }
i++;
}
@@ -1109,7 +1208,7 @@
res_del(ds);
}
}
-
+#endif
}
/*
@@ -1200,16 +1299,21 @@
res_add(struct dbr_rec *dr, struct dbr_ident_res *dir, struct dbr_res *dsh,
wchar_t *res)
{
+ struct dbr *dbr;
struct dbr_res *ds;
struct dbr_ident *dbi;
- char *p;
- size_t rlen;
struct record *r;
struct record_res *rr;
+ struct recpar rp;
+ size_t rlen;
+ int error;
+ char *p;
MDNS_INIT_ASSERT(dir, dir_magic);
dbi = dir->dir_dbi;
MDNS_INIT_ASSERT(dbi, dbi_magic);
+ dbr = dbi->dbi_dbr;
+ MDNS_INIT_ASSERT(dbr, dbr_magic);
ds = malloc(sizeof(struct dbr_res));
if (ds == NULL)
@@ -1233,21 +1337,38 @@
r = &dr->dr_rec;
rr = &ds->ds_res;
+ ds->ds_data = _wcsdup(res);
+ if (ds->ds_data == NULL)
+ goto res_add_fail;
+
p = mdns_res_encode(dir->dir_class, dir->dir_type, res,
MDNS_ENC_WCHAR, wcslen(res), &rlen);
+ if (p == NULL)
+ goto res_add_fail2;
- record_res_add(r, &rr, RECORD_NOALLOC, dir->dir_type, p, rlen);
- record_res_setparent(&ds->ds_res, ds);
-
+ rp.rp_handle = ds;
+ rp.rp_del_cb = NULL;
+ error = record_res_add(&dbr->dbr_recs, &rr,
+ REC_NOALLOC | REC_OBJNAME | REC_RESOWN,
+ &rp, r, dir->dir_class, dir->dir_type, p, rlen);
+ if (error != 0) {
+ free(p);
+ goto res_add_fail2;
+ }
+
ds->ds_rec = dr;
- ds->ds_data = _wcsdup(res);
ds->ds_dir = dir;
MDNS_INIT_SET(ds, ds_magic);
dprintf(DEBUG_DBR, "Added real resource ds=%x to record %ls, dr=%x, "
"dir=%x", ds, dr->dr_name, dr, dir);
-
return (ds);
+res_add_fail2:
+ free(ds->ds_data);
+res_add_fail:
+ dprintf(DEBUG_DBR, "Failed to add real resource %ls, dir=%p",
+ res, dir);
+ return (NULL);
}
/*
@@ -1285,87 +1406,93 @@
free(ds);
}
-#if 0
/*
- * Remove a resource from a database record
- * ds - Database resource pointer
- *
- * All clones will be removed aswell, to remove/free only one resource
- * use res_del().
+ * Look up exact matching resource
*/
-void
-dbr_res_del(struct dbr_res *ds)
+struct dbr_res *
+dbr_find_res(struct dbr *dbr, char *name, uint16_t class, uint16_t type,
+ char *res, size_t rlen)
{
- struct dbr_rec *dr;
- struct dbr *dbr;
- struct dbr_type *dt;
- struct dbr_res *ds2, *ds_tmp;
+ struct record_res *rr;
- MDNS_INIT_ASSERT(ds, ds_magic);
- dt = ds->ds_type;
- MDNS_INIT_ASSERT(dt, dt_magic);
- dr = dt->dt_rec;
- MDNS_INIT_ASSERT(dr, dr_magic);
- dbr = dr->dr_dbr;
- MDNS_INIT_ASSERT(dbr, dbr_magic);
+ /* Unlocked by either dbr_find_next() or dbr_find_end() */
+ RW_RLOCK(dbr, dbr_lock);
- ds2 = ds->ds_chead;
- if (ds2->ds_flags & DS_POINTER)
- TAILQ_REMOVE(&ds2->ds_vdata.rec->dr_res_ptr, ds2, ds_ptr_next);
- else
- var_dereg(&dbr->dbr_vars, ds2->ds_vdata.wp, ds2);
-
- TAILQ_FOREACH_SAFE(ds, &ds2->ds_clone.head, ds_clone.next, ds_tmp) {
- dprintf(DEBUG_DBR, "Removing clone %x (orig %x)", ds, ds2);
- res_del(ds);
- }
-
- res_del(ds2);
- record_type_release(&dt->dt_type);
- dprintf(DEBUG_DBR, "Database resource %x removed", ds2);
+ rr = record_res_find(&dbr->dbr_recs, 0, name, class, type, res, rlen);
+ if (rr == NULL)
+ goto dbr_find_res_fail;
+ return (record_res_getparent(rr));
+dbr_find_res_fail:
+ RW_UNLOCK(dbr, dbr_lock);
+ return (NULL);
}
-#endif
struct dbr_res *
-dbr_find_res(struct dbr *dbr, char *name, uint16_t type, char *res,
- size_t rlen)
+dbr_find(struct dbr *dbr, const char *name, uint16_t class, uint16_t type)
{
+ struct record_res *rr;
struct record_type *rt;
- struct record_res *rr;
+
+ /* Unlocked by either dbr_find_next() or dbr_find_end() */
+ RW_RLOCK(dbr, dbr_lock);
+
+ rt = record_type_find(&dbr->dbr_recs, REC_CTANY, name, class, type);
+ if (rt == NULL)
+ goto dbr_find_fail;
- rt = record_type_find(&dbr->dbr_recs, name, type);
- record_type_foreach(rr, rt) {
- if (rlen == rr->rr_len)
- if (memcmp(res, rr->rr_data, rlen) == 0)
- return (record_res_getparent(rr));
- }
+ rr = record_res_first(rt);
+ if (rr == NULL)
+ goto dbr_find_fail;
+ return (record_res_getparent(rr));
+dbr_find_fail:
+ RW_UNLOCK(dbr, dbr_lock);
return (NULL);
}
-struct dbr_type *
-dbr_find_type(struct dbr *dbr, char *name, uint16_t type)
+struct dbr_res *
+dbr_find_next(struct dbr *dbr, struct dbr_res *ds, uint16_t class,
+ uint16_t type)
{
+ struct record_res *rr;
struct record_type *rt;
- struct dbr_type *dt = NULL;
+ struct record_class *rc;
+
+ rr = &ds->ds_res;
+ rt = record_get_type(rr);
+ rc = record_get_class(rt);
+ rr = record_res_next(rr);
+ if (rr != NULL)
+ return (record_res_getparent(rr));
- rt = record_type_find(&dbr->dbr_recs, name, type);
- if (rt != NULL)
- dt = record_type_getparent(rt);
+ rt = record_type_find_next(rt, type);
+ if (rt != NULL) {
+ rr = record_res_first(rt);
+ if (rr == NULL)
+ goto dbr_find_next_end;
+ return (record_res_getparent(rr));
+ }
- return (dt);
+ rc = record_class_find_next(rc, class);
+ if (rc == NULL)
+ goto dbr_find_next_end;
+ rt = record_type_find(&dbr->dbr_recs, REC_CTANY | REC_OBJCLASS, NULL,
+ (uintptr_t)rc, type);
+ if (rt == NULL)
+ goto dbr_find_next_end;
+ rr = record_res_first(rt);
+ if (rr == NULL)
+ goto dbr_find_next_end;
+ return (record_res_getparent(rr));
+dbr_find_next_end:
+ RW_UNLOCK(dbr, dbr_lock);
+ return (NULL);
}
-struct dbr_rec *
-dbr_find(struct dbr *dbr, char *name)
+void
+dbr_find_end(struct dbr *dbr)
{
- struct record *r;
- struct dbr_rec *dr = NULL;
- r = record_find(&dbr->dbr_recs, name);
- if (r != NULL)
- dr = record_getparent(r);
-
- return (dr);
+ RW_UNLOCK(dbr, dbr_lock);
}
/*
@@ -1508,6 +1635,7 @@
dbr_tiebreak(struct dbr *dbr __unused, struct dbr_rec *dr, struct record *pr)
{
struct record *r;
+ struct record_class *rc, *prc;
struct record_type *rt, *prt;
struct record_res *rr, *prr;
int diff, len;
@@ -1519,68 +1647,92 @@
if (!(dr->dr_flags & DR_PROBING))
return;
- prt = record_first(pr);
+ prc = record_class_first(pr);
+ if (prc == NULL)
+ return;
+
if (prt == NULL)
return;
r = &dr->dr_rec;
- rt = record_first(r);
+ rc = record_class_first(r);
/*
- * Compare record types one by one, the numerical greater one
- * wins. If types are equal, its resource data is byte compared.
+ * Compare resources pairwaise, numerical greater one wins.
+ * The record sub-system keeps classes and types sorted.
*/
- while (rt != NULL && prt != NULL) {
- if (prt->rt_type > rt->rt_type) {
+ while (rc != NULL && prc != NULL) {
+ if (prc->rc_class > rc->rc_class) {
outcome = 1;
break;
}
- else if (prt->rt_type < rt->rt_type) {
+ else if (prc->rc_class < rc->rc_class) {
outcome = 2;
break;
}
+
+ prt = record_type_first(prc);
+ rt = record_type_first(rc);
+
+ while (rt != NULL && prt != NULL) {
+ if (prt->rt_type > rt->rt_type) {
+ outcome = 1;
+ break;
+ }
+ else if (prt->rt_type < rt->rt_type) {
+ outcome = 2;
+ break;
+ }
- rr = record_type_first(rt);
- prr = record_type_first(prt);
+ rr = record_res_first(rt);
+ prr = record_res_first(prt);
- while (rr != NULL && prr != NULL) {
- len = rr->rr_len > prr->rr_len ?
- prr->rr_len : rr->rr_len;
+ while (rr != NULL && prr != NULL) {
+ len = rr->rr_len > prr->rr_len ?
+ prr->rr_len : rr->rr_len;
- diff = memcmp(rr->rr_data, prr->rr_data, len);
- if (diff < 0)
- outcome = 1;
- else if (diff > 0)
- outcome = 2;
- /*
- * If the data differs in length and the data upto
- * the common minimum length is identical we
- * assume that the longest resource is the
- * "lexiographically later" one.
- */
- else if (diff == 0) {
- if (prr->rr_len > rr->rr_len)
- outcome = 1;
- else if (rr->rr_len > prr->rr_len)
+ diff = memcmp(rr->rr_data, prr->rr_data, len);
+ if (diff < 0)
+ outcome = 1;
+ else if (diff > 0)
outcome = 2;
+ /*
+ * If the data differs in length and the data
+ * upto the common minimum length is identical
+ * we assume that the longest resource is the
+ * "lexiographically later" one.
+ */
+ else if (diff == 0) {
+ if (prr->rr_len > rr->rr_len)
+ outcome = 1;
+ else if (rr->rr_len > prr->rr_len)
+ outcome = 2;
+ }
}
+ if (prr != NULL && rr == NULL)
+ outcome = 1;
+ else if (prr == NULL && rr != NULL)
+ outcome = 2;
+
+ if (outcome != 0)
+ break;
+
+ rt = record_type_next(rt);
+ prt = record_type_next(prt);
}
- if (prr != NULL && rr == NULL)
- outcome = 1;
- else if (prr == NULL && rr != NULL)
- outcome = 2;
-
if (outcome != 0)
break;
-
- rt = record_next(rt);
- prt = record_next(prt);
}
/*
* If the peer still has record types, but we don't we are
* deemed the loser and the other way around.
*/
+ if (prc != NULL && rc == NULL)
+ outcome = 1;
+ else if (prc == NULL && rc != NULL)
+ outcome = 2;
+
if (prt != NULL && rt == NULL)
outcome = 1;
else if (prt == NULL && rt != NULL)
@@ -1594,7 +1746,7 @@
dprintf(DEBUG_DBR, "Lost tie-breaking on %ls", dr->dr_name);
col_probe(dr);
}
- else if (outcome == 1) {
+ else if (outcome == 2) {
dprintf(DEBUG_DBR, "Won tie-breaking on %ls", dr->dr_name);
}
}
@@ -1610,6 +1762,7 @@
struct mdns_rrset *rs;
struct dbr_res *ds;
struct record *r;
+ struct record_class *rc;
struct record_type *rt;
struct record_res *rr;
struct mdns_pkgchain pc;
@@ -1633,8 +1786,8 @@
}
/* Check if resource data is identical with what we have */
- ds = dbr_find_res(dbr, prs->r_name, prs->r_type, prs->r_data,
- prs->r_datalen);
+ ds = dbr_find_res(dbr, prs->r_name, prs->r_class, prs->r_type,
+ prs->r_data, prs->r_datalen);
if (ds != NULL) {
dprintf(DEBUG_DBR, "Identical resource data on record %s, "
"no need to defend", prs->r_name);
@@ -1645,16 +1798,18 @@
mdns_pkgchain_init(&mif->mif_stack, &pc, MDNS_PC_NONE);
r = &dr->dr_rec;
- record_foreach(rt, r) {
- record_type_foreach(rr, rt) {
- rs = mdns_pkg_getrrset();
- mdns_rrset_name(rs, r->r_name);
- rs->r_type = rt->rt_type;
- rs->r_class = mdns_c_in;
- rs->r_cflush = 1;
- rs->r_datalen = rr->rr_len;
- rs->r_data = rr->rr_data;
- mdns_pkg_addanswer(&pc, rs, 0);
+ record_foreach(rc, r) {
+ record_class_foreach(rt, rc) {
+ record_type_foreach(rr, rt) {
+ rs = mdns_pkg_getrrset();
+ mdns_rrset_name(rs, r->r_name);
+ rs->r_type = rt->rt_type;
+ rs->r_class = rc->rc_class;
+ rs->r_cflush = 1;
+ rs->r_datalen = rr->rr_len;
+ rs->r_data = rr->rr_data;
+ mdns_pkg_addanswer(&pc, rs, 0);
+ }
}
}
oq_enqueue(&mif->mif_oq, &pc, family, NULL, 0);
@@ -1662,23 +1817,6 @@
RW_UNLOCK(dbr, dbr_lock);
}
-static void
-record_probe_cb(struct record *r, void *arg)
-{
- struct dbr_pac *pac;
- struct dbr_rec *dr;
-
- pac = arg;
- MDNS_INIT_ASSERT(pac, pac_magic);
- dr = record_getparent(r);
- if (dr->dr_flags & DR_PROBING)
- dbr_probe_del(dr);
- if (dr->dr_flags & DR_ANNOUNCE)
- dbr_an_del(dr);
- if (!(dr->dr_flags & DR_SHARED))
- dbr_probe_add(pac, dr);
-}
-
/*
* Initiate probe for all non-shared records in the given database
* dbr - Record database
@@ -1687,9 +1825,21 @@
dbr_probe_all(struct dbr *dbr)
{
struct dbr_pac *pac;
+ struct dbr_rec *dr;
+ struct record *r;
+ RW_RLOCK(dbr, dbr_lock);
pac = dbr_pac_new(dbr, PAC_PROBE);
- records_foreach(&dbr->dbr_recs, record_probe_cb, pac);
+ records_foreach(r, &dbr->dbr_recs) {
+ dr = record_getparent(r);
+ if (dr->dr_flags & DR_PROBING)
+ dbr_probe_del(dr);
+ if (dr->dr_flags & DR_ANNOUNCE)
+ dbr_an_del(dr);
+ if (!(dr->dr_flags & DR_SHARED))
+ dbr_probe_add(pac, dr);
+ }
+ RW_UNLOCK(dbr, dbr_lock);
dbr_probe_start(pac);
}
@@ -1880,40 +2030,40 @@
dbr_pac_start(pac, PAC_PROBE, delay_time, probe_step);
}
-/*
- * Helper function to probe_step(), adds the given record to the
- * specified packet chain.
- */
-static inline void
-probe_add_rec(struct mdns_pkgchain *pc, struct dbr_rec *dr, int step)
+/* Create probe packet to a specific class */
+static inline int
+probe_add_rec_class(struct mdns_pkgchain *pc, struct record_class *rc, int step)
{
- struct mdns_qset *qs;
- struct mdns_rrset *rs;
struct record *r;
struct record_type *rt;
struct record_res *rr;
+ struct mdns_qset *qs;
+ struct mdns_rrset *rs;
struct dbr_res *ds;
struct dbr_ident_res *dir;
struct mdns_rrset rstmp;
- int error;
+ int error, retval;
- MDNS_INIT_ASSERT(dr, dr_magic);
- r = &dr->dr_rec;
-
+ r = record_get_record(rc);
qs = mdns_pkg_getqset();
+ if (qs == NULL)
+ return (-1);
mdns_qset_name(qs, r->r_name);
- qs->q_class = mdns_c_in;
- qs->q_type = mdns_in_any;
+ qs->q_class = rc->rc_class;
+ qs->q_type = mdns_t_any;
/* unicast on the first 2 steps only */
qs->q_unicast = (step < 2) ? 1 : 0;
-redo:
mdns_pkg_addquestion(pc, qs, 0);
- record_foreach(rt, r) {
+ record_class_foreach(rt, rc) {
record_type_foreach(rr, rt) {
ds = record_res_getparent(rr);
dir = ds->ds_dir;
rs = mdns_pkg_getrrset();
+ if (rs == NULL) {
+ retval = -1;
+ goto probe_add_rec_class_fail;
+ }
mdns_rrset_name(rs, r->r_name);
rs->r_class = dir->dir_class;
rs->r_type = dir->dir_type;
@@ -1922,33 +2072,55 @@
rs->r_datalen = rr->rr_len;
rs->r_data = rr->rr_data;
error = mdns_pkg_addauth(pc, rs, MDNS_PKG_NOAE);
- if (error == 0)
- continue;
- /*
- * Out of space in packet.
- * Undo everything and re-start with a fresh packet.
- */
- mdns_pkg_delquestion(pc, qs);
- record_foreach(rt, r) {
- record_type_foreach(rr, rt) {
- ds = record_res_getparent(rr);
- dir = ds->ds_dir;
- mdns_rrset_name(&rstmp, r->r_name);
- rstmp.r_class = dir->dir_class;
- rstmp.r_type = dir->dir_type;
- rstmp.r_ttl = dir->dir_ttl;
- rstmp.r_cflush = 0;
- rstmp.r_datalen = rr->rr_len;
- rstmp.r_data = rr->rr_data;
- rs = mdns_pkg_delauth(pc, &rstmp);
- if (rs != NULL)
- mdns_pkg_freeset(rs);
- }
+ if (error != 0) {
+ retval = 1;
+ goto probe_add_rec_class_fail;
}
+ }
+ }
+ return (0);
+probe_add_rec_class_fail:
+ mdns_pkg_delquestion(pc, qs);
+ record_class_foreach(rt, rc) {
+ record_type_foreach(rr, rt) {
+ ds = record_res_getparent(rr);
+ dir = ds->ds_dir;
+ mdns_rrset_name(&rstmp, r->r_name);
+ rstmp.r_class = dir->dir_class;
+ rstmp.r_type = dir->dir_type;
+ rstmp.r_ttl = dir->dir_ttl;
+ rstmp.r_cflush = 0;
+ rstmp.r_datalen = rr->rr_len;
+ rstmp.r_data = rr->rr_data;
+ rs = mdns_pkg_delauth(pc, &rstmp);
+ if (rs != NULL)
+ mdns_pkg_freeset(rs);
+ }
+ }
+ return (1);
+}
+/*
+ * Helper function to probe_step(), adds the given record to the
+ * specified packet chain.
+ */
+static inline void
+probe_add_rec(struct mdns_pkgchain *pc, struct dbr_rec *dr, int step)
+{
+ struct record *r;
+ struct record_class *rc;
+ int error;
+
+ MDNS_INIT_ASSERT(dr, dr_magic);
+ r = &dr->dr_rec;
+
+ record_foreach(rc, r) {
+ error = probe_add_rec_class(pc, rc, step);
+ /* Out of space, re-try */
+ if (error > 0) {
mdns_pkgchain_expand(pc);
mdns_pkg_sethdr(pc, 0, MDNS_HEAD_RESP | MDNS_HEAD_AA);
- goto redo;
+ probe_add_rec_class(pc, rc, step);
}
}
}
@@ -2019,6 +2191,7 @@
count++;
}
+ /* FIXME Must read-lock dbr or keep each ds locked while on queue */
if (count) {
oq_enqueue(&mif->mif_oq, &pc, AF_INET, NULL, 0);
#ifdef INET6
@@ -2124,10 +2297,14 @@
*/
TAILQ_FOREACH_SAFE(dr, &pac->pac_head, dr_pac_next, dr2) {
MDNS_INIT_ASSERT(dr, dr_magic);
+ r = &dr->dr_rec;
TAILQ_FOREACH(ds, &dr->dr_resh, ds_next) {
+ MDNS_INIT_ASSERT(ds, ds_magic);
dir = ds->ds_dir;
- MDNS_INIT_ASSERT(ds, ds_magic);
rs = mdns_pkg_getrrset();
+ if (rs == NULL)
+ break;
+ rr = &ds->ds_res;
mdns_rrset_name(rs, r->r_name);
rs->r_class = dir->dir_class;
rs->r_type = dir->dir_type;
==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/dbrec.h#5 (text+ko) ====
@@ -42,11 +42,11 @@
MAGIC(dbr_magic);
DEF_MTX(dbr_mtx);
DEF_RW(dbr_lock);
- void *dbr_ctx; /* context specific back-pointer */
- struct records dbr_recs; /* record subsystem */
- struct vars dbr_vars; /* variable subsystem */
- struct hashtbl dbr_ident;
- TAILQ_HEAD(, dbr_ident) dbr_ilist;
+ void *dbr_ctx; /* Context specific back-pointer */
+ struct records dbr_recs; /* Record subsystem */
+ struct vars dbr_vars; /* Variable subsystem */
+ struct hashtbl dbr_ident; /* Identifier lookup */
+ TAILQ_HEAD(, dbr_ident) dbr_ilist; /* Identifier list */
};
/*
@@ -59,7 +59,7 @@
MAGIC(dbi_magic);
DEF_MTX(dbi_mtx);
TAILQ_ENTRY(dbr_ident) dbi_next;
- struct dbr *dbi_dbr; /* back-pointer */
+ struct dbr *dbi_dbr; /* Back pointer */
char *dbi_ident; /* Unique identifier string */
wchar_t **dbi_names; /* Array of alternative record names */
int dbi_curnam; /* Current name in use */
@@ -177,50 +177,67 @@
struct dbr_pac {
MAGIC(pac_magic);
DEF_MTX(pac_mtx);
- struct dbr *pac_dbr;
- int pac_step; /* step counter */
- int pac_tmr; /* timer id of next step */
- int pac_flags;
+ struct dbr *pac_dbr;
+ int pac_step; /* step counter */
+ int pac_tmr; /* timer id of next step */
+ int pac_flags;
#define PAC_RUNNING 0x01
-#define PAC_PROBE 0x02
-#define PAC_ANNOUNCE 0x04
+#define PAC_PROBE 0x02 /* This is a probe context */
+#define PAC_ANNOUNCE 0x04 /* This is an announce context */
TAILQ_HEAD(, dbr_rec) pac_head;
};
-void dbr_init(struct dbr *, void *);
-void dbr_destroy(struct dbr *);
-struct dbr_rec * dbr_add(struct dbr *, char *, wchar_t **, int);
-void dbr_del(struct dbr_rec *);
-struct dbr_rec * dbr_find(struct dbr *, char *);
-struct dbr_type * dbr_find_type(struct dbr *, char *, uint16_t);
-struct dbr_res * dbr_find_res(struct dbr *, char *, uint16_t, char *, size_t);
+/* Initialize record database */
+int dbr_init(struct dbr *, void *);
+void dbr_destroy(struct dbr *);
+
+/* Create/remove a record resource identifier */
+int dbr_ident_add(struct dbr *, char *, int);
+int dbr_ident_del(struct dbr *, char *);
+
+/* Create/remove a name on an identifier */
+int dbr_name_add(struct dbr *, char *, wchar_t *);
+int dbr_name_del(struct dbr *, char *, wchar_t *);
+
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list