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