X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=mdnsd.h;h=90ae20c112c028da6c31a0b5773b3e98beb79b22;hb=refs%2Fheads%2Fmdnsd-cleanup;hp=bc86df680e7c31562826aba8d430baa98ecb95b3;hpb=6970b746b2b0c4b4e37cb2e3cf1b9446edb9bc9c;p=mdnsd.git diff --git a/mdnsd.h b/mdnsd.h index bc86df6..90ae20c 100644 --- a/mdnsd.h +++ b/mdnsd.h @@ -1,89 +1,240 @@ -#ifndef mdnsd_h -#define mdnsd_h -#include "1035.h" +#ifndef _MDNSD_H_ +#define _MDNSD_H_ + +/* + * Copyright (C) 2003 Jeremie Miller + * Copyright (c) 2009 Simon Budig + * Copyright (C) 2013 Ole Reinhardt + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * For additional information see http://www.ethernut.de/ + */ + +/* This code is based on + * Based on BSD licensed mdnsd implementation by Jer + * http://dotlocal.org/mdnsd/ + * + * Unfortunately this site is now longer alive. You can still find it at: + * http://web.archive.org/web/20080705131510/http://dotlocal.org/mdnsd/ + * + * mdnsd - embeddable Multicast DNS Daemon + * ======================================= + * + * "mdnsd" is a very lightweight, simple, portable, and easy to integrate + * open source implementation of Multicast DNS (part of Zeroconf, also called + * Rendezvous by Apple) for developers. It supports both acting as a Query and + * a Responder, allowing any software to participate fully on the .localnetwork + * just by including a few files and calling a few functions. All of the + * complexity of handling the Multicast DNS retransmit timing, duplicate + * suppression, probing, conflict detection, and other facets of the DNS + * protocol is hidden behind a very simple and very easy to use interface, + * described in the header file. The single small c source file has almost no + * dependencies, and is portable to almost any embedded platform. + * Multiple example applications and usages are included in the download, + * including a simple persistent query browser and a tool to advertise .local + * web sites. + * + * The code is licensed under both the GPL and BSD licenses, for use in any + * free software or commercial application. If there is a licensing need not + * covered by either of those, alternative licensing is available upon request. + * + */ + +/*! + * \file include/pro/mdnsd.h + * \brief Multicast DNS Deamon + * + * \verbatim + * + * $Id$ + * + * \endverbatim + */ + +#include "rfc1035.h" #include +#include +#include + +#ifdef UNUSED +#elif defined(__GNUC__) +# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) +#elif defined(__LCLINT__) +# define UNUSED(x) /*@unused@*/ x +#else +# define UNUSED(x) x +#endif + +#define MDNS_PORT 5353 +#define MDNS_MULTICAST_IP "224.0.0.251" + +/* Size of query/publish hashes */ +#define SPRIME 108 + +/* size of cache hash */ +#define LPRIME 1009 + +/* brute force garbage cleanup frequency, rarely needed (daily default) */ +#define GC 86400 + + +/*! + * \brief MDNS answer data + */ +typedef struct _mdnsda_struct TMdnsdAnswer; +struct _mdnsda_struct +{ + char *name; + uint16_t type; + uint32_t ttl; + uint16_t rdlen; + char *rdata; + struct in_addr ip; // A + uint8_t *rdname; // NS/CNAME/PTR/SRV + struct { + uint16_t priority; + uint16_t weight; + uint16_t port; + } srv; // SRV +}; + + +/*! + * \brief MDNS record entry + */ +typedef struct _mdnsdr_struct TMdnsdRecord; +struct _mdnsdr_struct +{ + TMdnsdAnswer rr; + int8_t unique; // # of checks performed to ensure + int tries; + void (*conflict)(TMdnsdRecord *record,char *name, int type, void *arg); + void *arg; + TMdnsdRecord *next; + TMdnsdRecord *list; +}; + + +/*! + * \brief MDNS query struct + */ +typedef struct _query_struct TQuery; +struct _query_struct +{ + char *name; + int type; + uint32_t nexttry; + int tries; + int (*answer)(TMdnsdAnswer *answer, void *arg); + void *arg; + TQuery *next; + TQuery *list; +}; + + +/*! + * \brief Unicast record data + */ +typedef struct _unicast_struct TUnicast; +struct _unicast_struct +{ + int id; + struct in_addr to; + uint16_t port; + TMdnsdRecord *record; + TUnicast *next; +}; + -typedef struct mdnsd_struct *mdnsd; // main daemon data -typedef struct mdnsdr_struct *mdnsdr; // record entry -// answer data -typedef struct mdnsda_struct +/*! + * \brief Cached record entry struct + */ +typedef struct _cached_struct TCached; +struct _cached_struct { - unsigned char *name; - unsigned short int type; - unsigned long int ttl; - unsigned short int rdlen; - unsigned char *rdata; - unsigned long int ip; // A - unsigned char *rdname; // NS/CNAME/PTR/SRV - struct { unsigned short int priority, weight, port; } srv; // SRV -} *mdnsda; - -/////////// -// Global functions -// -// create a new mdns daemon for the given class of names (usually 1) and maximum frame size -mdnsd mdnsd_new(int class, int frame); -// -// gracefully shutdown the daemon, use mdnsd_out() to get the last packets -void mdnsd_shutdown(mdnsd d); -// -// flush all cached records (network/interface changed) -void mdnsd_flush(mdnsd d); -// -// free given mdnsd (should have used mdnsd_shutdown() first!) -void mdnsd_free(mdnsd d); -// -/////////// - -/////////// -// I/O functions -// -// incoming message from host (to be cached/processed) -void mdnsd_in(mdnsd d, struct message *m, unsigned long int ip, unsigned short int port); -// -// outgoing messge to be delivered to host, returns >0 if one was returned and m/ip/port set -int mdnsd_out(mdnsd d, struct message *m, unsigned long int *ip, unsigned short int *port); -// -// returns the max wait-time until mdnsd_out() needs to be called again -struct timeval *mdnsd_sleep(mdnsd d); -// -//////////// - -/////////// -// Q/A functions -// -// register a new query -// answer(record, arg) is called whenever one is found/changes/expires (immediate or anytime after, mdnsda valid until ->ttl==0) -// either answer returns -1, or another mdnsd_query with a NULL answer will remove/unregister this query -void mdnsd_query(mdnsd d, char *host, int type, int (*answer)(mdnsda a, void *arg), void *arg); -// -// returns the first (if last == NULL) or next answer after last from the cache -// mdnsda only valid until an I/O function is called -mdnsda mdnsd_list(mdnsd d, char *host, int type, mdnsda last); -// -/////////// - -/////////// -// Publishing functions -// -// create a new unique record (try mdnsda_list first to make sure it's not used) -// conflict(arg) called at any point when one is detected and unable to recover -// after the first data is set_*(), any future changes effectively expire the old one and attempt to create a new unique record -mdnsdr mdnsd_unique(mdnsd d, char *host, int type, long int ttl, void (*conflict)(char *host, int type, void *arg), void *arg); -// -// create a new shared record -mdnsdr mdnsd_shared(mdnsd d, char *host, int type, long int ttl); -// -// de-list the given record -void mdnsd_done(mdnsd d, mdnsdr r); -// -// these all set/update the data for the given record, nothing is published until they are called -void mdnsd_set_raw(mdnsd d, mdnsdr r, char *data, int len); -void mdnsd_set_host(mdnsd d, mdnsdr r, char *name); -void mdnsd_set_ip(mdnsd d, mdnsdr r, unsigned long int ip); -void mdnsd_set_srv(mdnsd d, mdnsdr r, int priority, int weight, int port, char *name); -// -/////////// + TMdnsdAnswer rr; + TQuery *query; + TCached *next; +}; + + +/*! + * \brief Main MDNS deamon data + */ +typedef struct _mdnsd_struct TMdnsd; +struct _mdnsd_struct +{ + int8_t shutdown; + uint32_t expireall, checkqlist; + struct timeval now; + struct timeval sleep; + struct timeval pause; + struct timeval probe; + struct timeval publish; + int class; + int frame; + TCached *cache[LPRIME]; + TMdnsdRecord *published[SPRIME]; + TMdnsdRecord *probing; + TMdnsdRecord *a_now; + TMdnsdRecord *a_pause; + TMdnsdRecord *a_publish; + TUnicast *uanswers; + TQuery *queries[SPRIME]; + TQuery *qlist; +}; + +/* Global functions */ +TMdnsd *MdnsdNew(int class, int frame); +void MdnsdShutdown(TMdnsd *mdnsd); +void MdnsdFlush(TMdnsd *mdnsd); +void MdnsdFree(TMdnsd *mdnsd); + +/* I/O functions */ +void MdnsdInput(TMdnsd *mdnsd, DNSMESSAGE *m, struct in_addr ip, uint16_t port); +int MdnsdOutput(TMdnsd *mdnsd, DNSMESSAGE *m, struct in_addr *ip, uint16_t *port); +struct timeval *MdnsdGetMaxSleepTime(TMdnsd *mdnsd); + +/* Qery / Answer functions */ +void MdnsdQuery(TMdnsd *mdnsd, char *host, int type, int (*answer)(TMdnsdAnswer *a, void *arg), void *arg); +TMdnsdAnswer *MdnsdListCachedAnswers(TMdnsd *mdnsd, char *host, int type, TMdnsdAnswer *last); + +/* Publishing functions */ +TMdnsdRecord *MdnsdAllocUnique(TMdnsd *mdnsd, char *host, int type, uint32_t ttl, void (*conflict)(TMdnsdRecord *record, char *host, int type, void *arg), void *arg); +TMdnsdRecord *MdnsdAllocShared(TMdnsd *mdnsd, char *host, int type, uint32_t ttl); +void MdnsdDone(TMdnsd *mdnsd, TMdnsdRecord *record); +/* These all set/update the data for the given record, nothing is published until they are called */ +void MdnsdSetRaw(TMdnsd *mdnsd, TMdnsdRecord *record, uint8_t *data, int len); +void MdnsdSetHost(TMdnsd *mdnsd, TMdnsdRecord *record, char *name); +void MdnsdSetIp(TMdnsd *mdnsd, TMdnsdRecord *record, struct in_addr ip); +void MdnsdSetSrv(TMdnsd *mdnsd, TMdnsdRecord *record, int priority, int weight, uint16_t port, char *name); #endif