| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 | /* * tinysvcmdns - a tiny MDNS implementation for publishing services * Copyright (C) 2011 Darell Tan * 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. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */#ifndef __MDNS_H__#define __MDNS_H__#include <stdint.h>#include <stdlib.h>#include <string.h>#include <stdbool.h>#ifdef _WIN32#include <winsock.h>#else#include <arpa/inet.h>#endif#define MALLOC_ZERO_STRUCT(x, type) \	x = malloc(sizeof(struct type)); \	memset(x, 0, sizeof(struct type));#define DECL_MALLOC_ZERO_STRUCT(x, type) \	struct type * MALLOC_ZERO_STRUCT(x, type)#define DECL_STRUCT(x, type) \	struct type * x;#define DEFAULT_TTL_FOR_RECORD_WITH_HOSTNAME 120#define DEFAULT_TTL 4500#ifndef NDEBUG#define DEBUG_PRINTF(fmt, ...) mdnsd_log(false, fmt, ##__VA_ARGS__)#else#define DEBUG_PRINTF(...) ((void) 0)#endifstruct rr_data_srv {	uint16_t priority;	uint16_t weight;	uint16_t port;	uint8_t *target;	// host};struct rr_data_txt {	struct rr_data_txt *next;	uint8_t *txt;};struct rr_data_nsec {	//uint8_t *name;	// same as record	// NSEC occupies the 47th bit, 5 bytes	//uint8_t bitmap_len;	// = 5	uint8_t bitmap[5];	// network order: first byte contains LSB};struct rr_data_ptr {	uint8_t *name;		// NULL if entry is to be used	struct rr_entry *entry;};struct rr_data_a {	uint32_t addr;};struct rr_data_aaaa {	struct in6_addr *addr;};typedef enum rr_type {	RR_A		= 0x01,	RR_PTR		= 0x0C,	RR_TXT		= 0x10,	RR_AAAA		= 0x1C,	RR_SRV		= 0x21,	RR_NSEC		= 0x2F,	RR_ANY		= 0xFF,} type;struct rr_entry {	uint8_t *name;	enum rr_type type;	uint32_t ttl;	char unicast_query;		// for use in Answers only	char cache_flush;	uint16_t rr_class;	// RR data	union {		struct rr_data_nsec NSEC;		struct rr_data_srv  SRV;		struct rr_data_txt  TXT;		struct rr_data_ptr  PTR;		struct rr_data_a    A;		struct rr_data_aaaa AAAA;	} data;};struct rr_list {	struct rr_entry *e;	struct rr_list *next;};struct rr_group {	uint8_t *name;	struct rr_list *rr;	struct rr_group *next;};#define MDNS_FLAG_RESP 	(1 << 15)	// Query=0 / Response=1#define MDNS_FLAG_AA	(1 << 10)	// Authoritative#define MDNS_FLAG_TC	(1 <<  9)	// TrunCation#define MDNS_FLAG_RD	(1 <<  8)	// Recursion Desired#define MDNS_FLAG_RA	(1 <<  7)	// Recursion Available#define MDNS_FLAG_Z		(1 <<  6)	// Reserved (zero)#define MDNS_FLAG_GET_RCODE(x)	(x & 0x0F)#define MDNS_FLAG_GET_OPCODE(x)	((x >> 11) & 0x0F)// gets the PTR target name, either from "name" member or "entry" member#define MDNS_RR_GET_PTR_NAME(rr)  (rr->data.PTR.name != NULL ? rr->data.PTR.name : rr->data.PTR.entry->name)struct mdns_pkt {	uint16_t id;	// transaction ID	uint16_t flags;	uint16_t num_qn;	uint16_t num_ans_rr;	uint16_t num_auth_rr;	uint16_t num_add_rr;	char unicast;	struct rr_list *rr_qn;		// questions	struct rr_list *rr_ans;		// answer RRs	struct rr_list *rr_auth;	// authority RRs	struct rr_list *rr_add;		// additional RRs};void mdnsd_log(bool force, char* fmt, ...);struct mdns_pkt *mdns_parse_pkt(uint8_t *pkt_buf, size_t pkt_len);void mdns_init_reply(struct mdns_pkt *pkt, uint16_t id);size_t mdns_encode_pkt(struct mdns_pkt *answer, uint8_t *pkt_buf, size_t pkt_len);void mdns_pkt_destroy(struct mdns_pkt *p);void rr_group_destroy(struct rr_group *group);struct rr_group *rr_group_find(struct rr_group *g, uint8_t *name);struct rr_entry *rr_entry_find(struct rr_list *rr_list, uint8_t *name, uint16_t type);struct rr_entry *rr_entry_match(struct rr_list *rr_list, struct rr_entry *entry);void rr_entry_destroy(struct rr_entry *rr);struct rr_entry *rr_entry_remove(struct rr_group *group, struct rr_entry *entry, enum rr_type type);void rr_group_add(struct rr_group **group, struct rr_entry *rr);void rr_group_clean(struct rr_group **head);int rr_list_count(struct rr_list *rr);int rr_list_append(struct rr_list **rr_head, struct rr_entry *rr);struct rr_entry *rr_list_remove(struct rr_list **rr_head, struct rr_entry *rr);void rr_list_destroy(struct rr_list *rr, char destroy_items);struct rr_entry *rr_create_ptr(uint8_t *name, struct rr_entry *d_rr);struct rr_entry *rr_create_srv(uint8_t *name, uint16_t port, uint8_t *target);struct rr_entry *rr_create_aaaa(uint8_t *name, struct in6_addr *addr);struct rr_entry *rr_create_a(uint8_t *name, struct in_addr addr);struct rr_entry *rr_create(uint8_t *name, enum rr_type type);void rr_set_nsec(struct rr_entry *rr_nsec, enum rr_type type);void rr_add_txt(struct rr_entry *rr_txt, const char *txt);const char *rr_get_type_name(enum rr_type type);uint8_t *create_label(const char *txt);uint8_t *create_nlabel(const char *name);char *nlabel_to_str(const uint8_t *name);uint8_t *dup_label(const uint8_t *label);uint8_t *dup_nlabel(const uint8_t *n);uint8_t *join_nlabel(const uint8_t *n1, const uint8_t *n2);// compares 2 namesstatic inline int cmp_nlabel(const uint8_t *L1, const uint8_t *L2) {	return strcmp((char *) L1, (char *) L2);}#endif /*!__MDNS_H__*/
 |