Date: Wed, 3 Oct 2007 21:11:14 GMT From: Fredrik Lindberg <fli@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 127144 for review Message-ID: <200710032111.l93LBE5K096114@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=127144 Change 127144 by fli@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) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200710032111.l93LBE5K096114>