PERFORCE change 127156 for review
Fredrik Lindberg
fli at FreeBSD.org
Wed Oct 3 14:40:53 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=127156
Change 127156 by fli at fli_nexus on 2007/10/03 21:40:27
- Timers and _wcsdup have been moved to util.c, remove.
- Input processing have its own file now, remove.
- Cache structures and prototypes live in cache.h, remove.
- Check for subsystem failures during interface initialization.
Affected files ...
.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.c#7 edit
.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.h#7 edit
Differences ...
==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.c#7 (text+ko) ====
@@ -47,6 +47,7 @@
#include <unistd.h>
#include "mdnsd.h"
+#include "util.h"
#include "log.h"
#include "objalloc.h"
@@ -73,64 +74,61 @@
static void usage(char *);
-/*
- * Generic timer intialization
- */
-static int
-tmr_init(int what, struct event_tmr *ev, ev_arg arg)
+static inline void
+record2rrset(struct record *r, uint16_t class, uint16_t type,
+ struct record_res *rr, struct mdns_rrset *rs, int cflush)
{
- switch (what) {
- case EVENT_INIT_OPEN:
- ev->evtmr_timeout = arg.int32;
- break;
- case EVENT_INIT_CLOSE:
- break;
- }
- return (0);
-}
+ MDNS_INIT_ASSERT(r, r_magic);
+ MDNS_INIT_ASSERT(rr, rr_magic);
-static int
-tmr_init_oneshot(int what, struct event_tmr *ev, ev_arg arg)
-{
-
- switch (what) {
- case EVENT_INIT_OPEN:
- ev->evtmr_timeout = arg.int32;
- ev->evtmr_oneshot = 1;
- break;
- case EVENT_INIT_CLOSE:
- break;
- }
- return (0);
+ mdns_rrset_name(rs, r->r_name);
+ rs->r_type = type;
+ rs->r_class = class;
+ rs->r_cflush = cflush;
+ rs->r_datalen = rr->rr_len;
+ rs->r_data = rr->rr_data;
}
/*
- * Start a timer, returns a unique timer identifier
+ * Callback routine from aggregation queue, called when a data
+ * object is supposed to be added to the packet.
*/
-int
-tmr_start(struct md_glob *g, uint32_t timeout, ev_handler_tmr handler,
- void *arg, int oneshot)
+static void
+aggr_resp_engine(struct mdns_pkgchain *pc, void *data)
{
- int id;
- ev_arg eva, evai;
+ struct record *r;
+ struct record_class *rc;
+ struct record_type *rt;
+ struct record_res *rr;
+ struct dbr_res *ds;
+ struct mdns_rrset *mrs;
+
+ rr = data;
+ MDNS_INIT_ASSERT(rr, rr_magic);
+ ds = record_res_getparent(rr);
+ MDNS_INIT_ASSERT(ds, ds_magic);
+
+ rt = record_get_type(rr);
+ rc = record_get_class(rt);
+ r = record_get_record(rc);
- evai.int32 = timeout;
- eva.ptr = arg;
- if (oneshot)
- id = event_add(g->g_evl, EVENT_TYPE_TMR, handler, &eva,
- tmr_init_oneshot, &evai);
- else
- id = event_add(g->g_evl, EVENT_TYPE_TMR, handler, &eva,
- tmr_init, &evai);
- return (id);
+ mrs = mdns_pkg_getrrset();
+ record2rrset(r, rc->rc_class, rt->rt_type, rr, mrs, 0);
+ mrs->r_ttl = ds->ds_dir->dir_ttl;
+ clock_gettime(CLOCK_REALTIME, &ds->ds_time);
+ mdns_pkg_addanswer(pc, mrs, 0);
}
-void
-tmr_stop(struct md_glob *g, int timer)
+/*
+ * Initialize a response packet chain
+ */
+static void
+aggr_resp_pkgchain(struct md_if *mif, struct mdns_pkgchain *pc)
{
- event_del(g->g_evl, timer, NULL);
+ mdns_pkgchain_init(&mif->mif_stack, pc, MDNS_PC_NONE);
+ mdns_pkg_sethdr(pc, 0, MDNS_HEAD_RESP | MDNS_HEAD_AA);
}
/*
@@ -209,25 +207,6 @@
}
/*
- * Duplicate an wide character string
- * XXX: Move to a better place
- */
-wchar_t *
-_wcsdup(const wchar_t *s)
-{
- size_t len;
- wchar_t *d;
-
- len = (wcslen(s) + 1) * sizeof(wchar_t);
- d = malloc(len);
- if (d == NULL)
- return (NULL);
- memcpy(d, s, len);
- return (d);
-}
-
-
-/*
* Generic I/O read-ready event initializtion
*/
int
@@ -246,404 +225,6 @@
return (0);
}
-static inline void
-record2rrset(struct record *r, struct record_type *rt, struct record_res *rr,
- struct mdns_rrset *rs, int cflush)
-{
-
- MDNS_INIT_ASSERT(r, r_magic);
- MDNS_INIT_ASSERT(rt, rt_magic);
- MDNS_INIT_ASSERT(rr, rr_magic);
-
- mdns_rrset_name(rs, r->r_name);
- rs->r_type = rt->rt_type;
- rs->r_class = mdns_c_in;
- rs->r_cflush = cflush;
- rs->r_datalen = rr->rr_len;
- rs->r_data = rr->rr_data;
-}
-
-/*
- * Callback routine from aggregation queue, called when a data
- * object is supposed to be added to the packet.
- */
-static void
-aggr_resp_engine(struct mdns_pkgchain *pc, void *data)
-{
- struct record *r;
- struct record_type *rt;
- struct record_res *rr;
- struct dbr_res *ds;
- struct mdns_rrset *mrs;
-
- rr = data;
- MDNS_INIT_ASSERT(rr, rr_magic);
- ds = record_res_getparent(rr);
- MDNS_INIT_ASSERT(ds, ds_magic);
- rt = rr->rr_type;
- MDNS_INIT_ASSERT(rt, rt_magic);
- r = rt->rt_record;
- MDNS_INIT_ASSERT(r, r_magic);
-
- mrs = mdns_pkg_getrrset();
- record2rrset(r, rt, rr, mrs, 0);
- mrs->r_ttl = ds->ds_dir->dir_ttl;
- clock_gettime(CLOCK_REALTIME, &ds->ds_time);
- mdns_pkg_addanswer(pc, mrs, 0);
-}
-
-/*
- * Initialize a response packet chain
- */
-static void
-aggr_resp_pkgchain(struct md_if *mif, struct mdns_pkgchain *pc)
-{
-
- mdns_pkgchain_init(&mif->mif_stack, pc, MDNS_PC_NONE);
- mdns_pkg_sethdr(pc, 0, MDNS_HEAD_RESP | MDNS_HEAD_AA);
-}
-
-/*
- * Process a query packet
- */
-static void
-process_query(struct md_if *mif, struct mdns_packet *pkg,
- struct mdns_head *hdr, struct sockaddr *from, socklen_t fromlen, int legacy)
-{
- struct mdns_qset qs;
- struct mdns_rrset rs, *rsp;
- struct dbr_rec *dr;
- struct dbr_res *ds;
- struct cache_res *cr;
- struct record_res *rr;
- struct record_type *rt;
- struct record *r;
- int i, error, send_unicast;
- time_t min, min2, max;
- struct aqueue *aq;
- struct timespec ts;
- struct cache ac;
- struct records auth;
- struct mdns_pkgchain upc;
-
- clock_gettime(CLOCK_REALTIME, &ts);
-
- mdns_pkgchain_init(&mif->mif_stack, &upc, MDNS_PC_NONE);
- mdns_pkg_sethdr(&upc, hdr->h_id, MDNS_HEAD_RESP | MDNS_HEAD_AA);
- send_unicast = 0;
- if (from->sa_family == AF_INET)
- aq = &mif->mif_aq4;
-#ifdef INET6
- else if (from->sa_family == AF_INET6)
- aq = &mif->mif_aq6;
-#endif
-
- /*
- * Process the answer section first
- */
- if (hdr->h_canswer > 0)
- cache_init(&ac, NULL);
- for (i = 0; i < hdr->h_canswer; i++) {
- error = mdns_pkg_getanswer(pkg, i, &rs);
- if (error != 0)
- break;
- if (rs.r_class != mdns_c_in) {
- free(rs.r_data);
- continue;
- }
-
- /*
- * Check if this is a resource we might respond to.
- * If it is, check if it's on the output queue and
- * remove it if TTL rules match, otherwise add it
- * to answer suppression lookup cache.
- */
- ds = dbr_find_res(&mif->mif_dbr, rs.r_name, rs.r_type,
- rs.r_data, rs.r_datalen);
- if (ds != NULL && !(ds->ds_flags & DS_INVALID)) {
- rr = &ds->ds_res;
- if (aq_inqueue(aq, rr)) {
- if (rs.r_ttl > ds->ds_dir->dir_ttl / 2)
- aq_dequeue(aq, rr);
- }
- else if (rs.r_ttl > ds->ds_dir->dir_ttl / 2) {
- error = cache_add(&ac, &rs, NULL);
- if (error == 1)
- free(rs.r_data);
- }
- else
- free(rs.r_data);
- }
- else {
- free(rs.r_data);
- }
- }
-
- /*
- * Process the authority section, data in here is used
- * for probe tie breaking.
- */
- if (hdr->h_cauth > 0)
- records_init(&auth, mdns_c_in);
- for (i = 0; i < hdr->h_cauth; i++) {
- error = mdns_pkg_getauth(pkg, i, &rs);
- if (error != 0)
- break;
- if (rs.r_class != mdns_c_in) {
- free(rs.r_data);
- continue;
- }
- record_get(&auth, &r, 0, rs.r_name);
- record_res_add(r, &rr, 0, rs.r_type,
- rs.r_data, rs.r_datalen);
- }
-
- /*
- * TC bit set, min 400-500 ms delay
- * Questions > 1, min 20-120 ms delay
- * Other, 0 ms
- */
- if (hdr->h_flags & MDNS_HEAD_TC)
- min2 = (random() % 101) + 400;
- else if (hdr->h_cquestion > 1)
- min2 = (random() % 101) + 20;
- else
- min = 0;
-
- /*
- * Process the question section
- */
- for (i = 0; i < hdr->h_cquestion; i++) {
- error = mdns_pkg_getquestion(pkg, i, &qs);
- if (error != 0)
- break;
- if (qs.q_class != mdns_c_in)
- continue;
-
- dprintf(DEBUG_RECV,
- "question for %s, type=%d, unicast=%d, legacy=%d",
- qs.q_name, qs.q_type, qs.q_unicast, legacy);
-
- dr = dbr_find(&mif->mif_dbr, qs.q_name);
- if (dr == NULL)
- continue;
- MDNS_INIT_ASSERT(dr, dr_magic);
- /*
- * Simultanesous probe tie-breaking
- */
- if (dr->dr_flags & DR_PROBING && hdr->h_cauth > 0) {
- record_get(&auth, &r, RECORD_NOINIT, qs.q_name);
- dbr_tiebreak(&mif->mif_dbr, dr, r);
- continue;
- }
- else if (!(dr->dr_flags & DR_OK)) {
- dprintf(DEBUG_SEND, "Record %s found in "
- "database, but is not marked ok (%x)",
- qs.q_name, dr->dr_flags);
- continue;
- }
- /*
- * Fix delay time for if this record is
- * marked as shared
- */
- else if (dr->dr_flags & DR_SHARED && min2 == 0)
- min = (random() % 101) + 20;
- else
- min = min2;
-
- /* Allow additional 500ms if aggreation is possible */
- max = min + 500;
-
- dprintf(DEBUG_SEND, "Found %s in database, responding",
- qs.q_name);
- if (legacy)
- mdns_pkg_addquestion(&upc, &qs, MDNS_PKG_DUP);
-
- r = &dr->dr_rec;
- record_foreach(rt, r) {
- if (qs.q_type != rt->rt_type
- && qs.q_type != mdns_in_any)
- continue;
- record_type_foreach(rr, rt) {
- ds = record_res_getparent(rr);
- if (ds->ds_flags & DS_INVALID)
- continue;
- if (hdr->h_canswer > 0) {
- cr = cache_find(&ac, qs.q_name,
- qs.q_type);
- if (cr != NULL)
- continue;
- }
- /*
- * This clients needs/wants a unicast response,
- * we also schedule a multicast response in we
- * this resource hasn't been multicasted
- * "recently".
- */
- if (legacy || qs.q_unicast) {
- rsp = mdns_pkg_getrrset();
- record2rrset(r, rt, rr, rsp, 0);
- rsp->r_ttl = legacy ? 10 :
- ds->ds_dir->dir_ttl;
- mdns_pkg_addanswer(&upc, rsp, 0);
- send_unicast = 1;
- /*
- * Schedule a multicast response if
- * the time this resource last was
- * sent is greater than a quarter of
- * its ttl.
- */
- if ((ts.tv_sec - ds->ds_time.tv_sec) >
- (int32_t)(ds->ds_dir->dir_ttl / 4))
- aq_enqueue(aq, rr, min, max);
- }
- /*
- * Multicase response, only if not already in
- * aggregation queue and it's at least one
- * second since we last sent this resource.
- */
- else if (!aq_inqueue(aq, rr) &&
- ts.tv_sec > ds->ds_time.tv_sec)
- aq_enqueue(aq, rr, min, max);
- }
- }
- }
-
- if (send_unicast)
- oq_enqueue(&mif->mif_oq, &upc, from->sa_family,
- from, fromlen);
- if (hdr->h_canswer > 0)
- cache_destroy(&ac);
- if (hdr->h_cauth > 0)
- records_destroy(&auth);
-
- mdns_pkgchain_free(&upc);
-}
-
-/*
- * Process a response
- */
-static void
-process_resp(struct md_if *mif, struct mdns_packet *pkg, struct mdns_head *hdr,
- struct sockaddr *from, socklen_t fromlen __unused)
-{
- struct dbr_rec *dr;
- int i, error;
- struct mdns_rrset rs;
-
- for (i = 0; i < hdr->h_canswer; i++) {
- error = mdns_pkg_getanswer(pkg, i, &rs);
- if (error != 0)
- break;
- if (rs.r_class != mdns_c_in) {
- free(rs.r_data);
- continue;
- }
-
- dprintf(DEBUG_RECV, "response to %s, class=%d, type=%d",
- rs.r_name, rs.r_class, rs.r_type);
-
- dr = dbr_find(&mif->mif_dbr, rs.r_name);
- if (dr != NULL && !(dr->dr_flags & DR_SHARED)) {
- dprintf(DEBUG_SEND, "Conflicting name %s (dr=%x)",
- rs.r_name, dr);
- dbr_defend(&mif->mif_dbr, dr, &rs, from->sa_family);
- continue;
- }
-
- /* Notify pending consumers */
- query_notify(&mif->mif_q, &rs, mif->mif_index,
- from->sa_family, ((i + 1) < hdr->h_canswer));
-
- /* TODO: check for pending questions matching this */
- /* TODO: check for pending answers matching this */
-
- /*
- * Purge records older than 1 second if this is
- * supposed to be a unique rrset (cache flush bit set)
- */
- if (rs.r_cflush)
- cache_purge(&mif->mif_cache, 1, rs.r_name, rs.r_type);
- error = cache_add(&mif->mif_cache, &rs, NULL);
- if (error == 1)
- free(rs.r_data);
- }
-}
-
-/*
- * Process a mdns packet and generate appropriate responses
- * mif - Interface handle
- * pc - Packet chain
- * type - MDNS_{UDP,TCP} transport type used to receive pkg
- * from - Peer address information
- * fromlen - Socket address length
- */
-static int
-pkgprocess(struct md_if *mif, struct mdns_pkgchain *pc, int type __unused,
- struct sockaddr *from, socklen_t fromlen)
-{
- struct mdns_packet *pkg;
- struct mdns_head hdr;
- int sinaddr_len, legacy;
- in_port_t port;
- void *sinaddr = NULL;
- struct sockaddr_in *sin;
-#ifdef INET6
- struct sockaddr_in6 *sin6;
-#endif
-#ifdef DEBUG
- char addr[SOCK_MAXADDRLEN+1];
-#endif
- struct aqueue *aq;
-
- switch (from->sa_family) {
- case AF_INET:
- sin = (struct sockaddr_in *)from;
- port = sin->sin_port;
- sinaddr = &((struct sockaddr_in *)from)->sin_addr;
- sinaddr_len = sizeof(struct in_addr);
- aq = &mif->mif_aq4;
- break;
-#ifdef INET6
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *)from;
- port = sin6->sin6_port;
- sinaddr = &((struct sockaddr_in6 *)from)->sin6_addr;
- sinaddr_len = sizeof(struct in6_addr);
- aq = &mif->mif_aq6;
- break;
-#endif /* INET6 */
- }
-
-#ifdef DEBUG
- inet_ntop(from->sa_family, sinaddr, addr, SOCK_MAXADDRLEN);
- dprintf(DEBUG_RECV, "Packet received peer=%s, port=%d, if=%s",
- addr, port, mif->mif_ifnam);
-#endif /* DEBUG */
-
- pkg = mdns_pkgchain_curpkg(pc);
- mdns_pkg_gethdr(pkg, &hdr);
- dprintf(DEBUG_RECV, "type=%s, questions=%d, answers=%d, authority=%d",
- hdr.h_flags & MDNS_HEAD_QUERY ? "query" : "resp",
- hdr.h_cquestion, hdr.h_canswer, hdr.h_cauth);
-
- /*
- * We are processing a query
- */
- if (hdr.h_flags & MDNS_HEAD_QUERY) {
- legacy = (port != 5353) ? 1 : 0;
- process_query(mif, pkg, &hdr, from, fromlen, legacy);
- }
-
- /*
- * We are processing a response
- */
- else if (hdr.h_flags & MDNS_HEAD_RESP) {
- process_resp(mif, pkg, &hdr, from, fromlen);
- }
- return (0);
-}
-
/*
* UDP socket read-ready event handler
* Allocates a packet chain and reads data from mdns stack and passes
@@ -1013,27 +594,30 @@
MDNS_INIT_SET(mif, mif_magic);
mif->mif_index = if_nametoindex(ifnam);
if (mif->mif_index == 0)
- goto out;
+ goto if_new_fail;
strncpy(mif->mif_ifnam, ifnam, IFNAMSIZ);
/* Initialize low-level mdns stack on this interface */
error = mdns_init(&mif->mif_stack, g->g_bp, ifnam);
if (error != 0)
- goto out;
+ goto if_new_fail;
MTX_INIT(mif, mif_stack_mtx, NULL);
RW_INIT(mif, mif_lock, NULL);
- RW_WLOCK(mif, mif_lock);
mif->mif_glob = g;
TAILQ_INIT(&mif->mif_evlist);
if (get_linkstatus(ifnam) != LINK_STATE_DOWN)
mif->mif_flags |= MIF_LINKUP;
/* Client queries system */
- queries_init(&mif->mif_q, mif);
+ error = queries_init(&mif->mif_q, mif);
+ if (error != 0)
+ goto if_new_fail;
/* Initialize cache */
- cache_init(&mif->mif_cache, &mif->mif_q);
+ error = cache_init(&mif->mif_cache, &mif->mif_q);
+ if (error != 0)
+ goto if_new_fail;
/* Initialize output queue */
oq_init(&mif->mif_oq, mif);
@@ -1055,10 +639,10 @@
/*
* Read configuration file and create self-claimed records.
- * This is done after socket setup so probing is safe to start.
*/
cfg_read(&mif->mif_dbr, ifnam, g->g_cfgfile);
+ RW_WLOCK(mif, mif_lock);
RW_WLOCK(g, g_lock);
TAILQ_INSERT_TAIL(&g->g_ifs_head, mif, mif_next);
if (mif->mif_index >= g->g_ifs_max) {
@@ -1070,15 +654,15 @@
}
g->g_ifs[mif->mif_index] = mif;
RW_UNLOCK(g, g_lock);
-
RW_UNLOCK(mif, mif_lock);
logger(LOG_NOTICE, "Added interface %s", mif->mif_ifnam);
dbr_probe_all(&mif->mif_dbr);
return (mif);
-out:
+if_new_fail:
free(mif);
+ logger(LOG_ERR, "Failed to add interface %s", ifnam);
return (NULL);
}
==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.h#7 (text+ko) ====
@@ -33,13 +33,13 @@
#include "debug.h"
#include "dbrec.h"
#include "clisrv.h"
+#include "cache.h"
#include "event.h"
#include "hash.h"
#include "mdns.h"
#include "output.h"
#include "output_aggr.h"
#include "queries.h"
-#include "record.h"
#include "threads.h"
#include "var.h"
#include "wqueue.h"
@@ -64,27 +64,6 @@
struct clisrv g_cs; /* unix client pipe server */
};
-/*
- * Cache resouce record
- */
-struct cache_res {
- MAGIC(cr_magic);
- struct record_res cr_res;
- TAILQ_ENTRY(cache_res) cr_next;
- uint32_t cr_ttl_rel;
- uint32_t cr_ttl_abs;
- time_t cr_ctime;
-};
-
-/*
- * Cache record set
- */
-struct cache {
- struct records c_recs;
- struct queries *c_queries;
- TAILQ_HEAD(, cache_res) c_list; /* time delta list */
-};
-
/* Event identifier */
struct md_if_ev {
TAILQ_ENTRY(md_if_ev) ifev_next;
@@ -122,22 +101,9 @@
char mif_ifnam[IFNAMSIZ];
};
-/* mdsnd.c */
-int tmr_start(struct md_glob *, uint32_t, ev_handler_tmr, void *, int);
-void tmr_stop(struct md_glob *, int);
-wchar_t * _wcsdup(const wchar_t *);
-
-/* cache.c */
-void cache_init(struct cache *, struct queries *);
-void cache_destroy(struct cache *);
-int cache_add(struct cache *, struct mdns_rrset *, struct record_res **);
-int cache_del(struct cache *, struct record_res *);
-struct cache_res * cache_find(struct cache *, char *, uint16_t);
-struct cache_res * cache_find_next(struct cache_res *);
-void cache_purge(struct cache *, time_t, char *, uint16_t);
-void cache_clean(struct cache *);
-void cache_set_ttl(struct cache *, struct record_res *, uint32_t);
-void cache_flush(struct cache *);
+/* input.c */
+int pkgprocess(struct md_if *, struct mdns_pkgchain *, int,
+ struct sockaddr *, socklen_t);
/* parse.y */
int cfg_read(struct dbr *r, const char *, const char *);
More information about the p4-projects
mailing list