1 /***************************************************************************** 2 * This file is part of libmicrodns. 3 * 4 * Copyright © 2014-2016 VideoLabs SAS 5 * 6 * Author: Jonathan Calmels <jbjcalmels@gmail.com> 7 * 8 ***************************************************************************** 9 * libmicrodns is released under LGPLv2.1 (or later) and is also available 10 * under a commercial license. 11 ***************************************************************************** 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU Lesser General Public License as published by 14 * the Free Software Foundation; either version 2.1 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU Lesser General Public License for more details. 21 * 22 * You should have received a copy of the GNU Lesser General Public License 23 * along with this program; if not, write to the Free Software Foundation, 24 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. 25 *****************************************************************************/ 26 27 #ifndef MICRODNS_MDNS_H 28 #define MICRODNS_MDNS_H 29 30 /** 31 * @file microdns.h 32 * @brief main functions to listen and announce services 33 */ 34 35 #include <stdbool.h> 36 37 #include "rr.h" 38 39 # ifdef __cplusplus 40 extern "C" { 41 # endif 42 43 #if defined(_MSC_VER) 44 #define MDNS_EXPORT __declspec(dllexport) extern 45 #else 46 #define MDNS_EXPORT extern 47 #endif 48 49 struct mdns_ctx; 50 51 #define MDNS_PORT 5353 52 #define MDNS_ADDR_IPV4 "224.0.0.251" 53 #define MDNS_ADDR_IPV6 "FF02::FB" 54 55 #define GET_RCODE(x) (x&0x000f) 56 #define SET_RCODE(x,c) (x|(c&0x000f)) 57 58 #define GET_OPCODE(x) (x&0x7800) 59 #define SET_OPCODE(x,c) (x|(c&0x7800)) 60 61 enum mdns_hdr_flag { 62 FLAG_QR = 1 << 15, // Question/Response 63 FLAG_AA = 1 << 10, // Authoritative Answer 64 FLAG_TC = 1 << 9, // Truncated Response 65 FLAG_RD = 1 << 8, // Recursion Desired 66 FLAG_RA = 1 << 7, // Recursion Available 67 FLAG_Z = 1 << 6, // Reserved 68 FLAG_AD = 1 << 5, // Authentic Data 69 FLAG_CD = 1 << 4, // Checking Disabled 70 }; 71 72 struct mdns_hdr { 73 uint16_t id; 74 uint16_t flags; 75 uint16_t num_qn; 76 uint16_t num_ans_rr; 77 uint16_t num_auth_rr; 78 uint16_t num_add_rr; 79 }; 80 81 enum mdns_announce_type { 82 MDNS_ANNOUNCE_INITIAL, // An initial announce needs to be sent 83 MDNS_ANNOUNCE_RESPONSE, // The application needs to respond to an MDNS question 84 MDNS_ANNOUNCE_GOODBYE, // A goodbye packet needs to be sent 85 }; 86 87 typedef void (*mdns_listen_callback)(void*, int, const struct rr_entry *); 88 89 /** 90 * @brief mdns_announce_callback Will be invoked for each received question 91 * 92 * @param cookie The pointer provided as last parameter to mdns_serve 93 * @param addr The address for which a probe was received 94 * @param service The service being probed or NULL when an initial discovery is requested 95 * @param type The type of announce that's expected from the application 96 * 97 * It is the application responsibility to filter which service it should respond 98 * to. 99 * This callback will be invoked with a NULL service upon startup so that the 100 * application can send a unsolicited announce. If there are more than a single 101 * network interface, this callback might be invoked multiple times for the same 102 * service, so that the application can announce itself as it sees fit (for 103 * instance it can announce both an A and AAAA records) 104 * This callback will also be invoked with a non-NULL service and 105 * MDNS_ANNOUNCE_INITIAL if the requests it through mdns_request_initial_announce 106 * In this case the application is responsible for knowing which service needs 107 * to be announced and announce it accordingly. 108 */ 109 typedef void (*mdns_announce_callback)(void* cookie, 110 const struct sockaddr *addr, 111 const char* service, 112 enum mdns_announce_type type ); 113 114 /** 115 * \return true if the listener should be stopped 116 */ 117 typedef bool (*mdns_stop_func)(void*); 118 119 /** 120 * @brief Allocates and initialize a new mdns context 121 * 122 * @param ctx Returns the allocated context for the library [OUT] 123 * @param addr Protocol specific address to listen to, or NULL to use both IPv4 and IPv6 124 * @param port Port to listen on 125 * 126 * @see use mdns_destroy() to clean 127 * 128 * @return 0 if success, negative in other cases 129 */ 130 MDNS_EXPORT int mdns_init(struct mdns_ctx **ctx, const char *addr, unsigned short port); 131 132 /** 133 * @brief Destroy an mdns context 134 * 135 * @param ctx The context created by mdns_init() 136 * 137 * @return 0 if success, negative in other cases 138 */ 139 MDNS_EXPORT int mdns_destroy(struct mdns_ctx *ctx); 140 141 142 /** 143 * @brief Send the entries on the network 144 * 145 * @param ctx A mdns context created by mdns_init() 146 * @param hdr A mdns_hdr header 147 * @param entries The entries to send 148 * 149 * @return 0 if successful, negative in other cases 150 */ 151 MDNS_EXPORT int mdns_entries_send(const struct mdns_ctx *ctx, const struct mdns_hdr *hdr, const struct rr_entry *entries); 152 153 /** 154 * @brief Print in human form an entry to debug 155 * 156 * @param entry The entry one wants to debug 157 */ 158 MDNS_EXPORT void mdns_entries_print(const struct rr_entry *); 159 160 /** 161 * @brief Wrapper around strerror to get strings from errors 162 * 163 * @param error The error number 164 * @param buf The buffer where the string can be written 165 * @param n The maximum of characters that can be written inside buf 166 * 167 * @return 0 if success, negative in other cases 168 */ 169 MDNS_EXPORT int mdns_strerror(int error, char *buf, size_t n); 170 171 /** 172 * @brief The main listening function for mDNS 173 * 174 * @param ctx A mdns context created by mdns_init() 175 * @param names The list of names of the services you are looking for 176 * @param nb_names The number of names in names list 177 * @param type The type of Record you want \see rr_type 178 * @param interval The refreshing interval to send a probe request (in seconds) 179 * @param stop The stop function to stop the discovery 180 * @param callback The callback function to receive the entries 181 * @param p_cookie user data for the callback 182 * 183 * @return 0 if success, negative in other cases 184 */ 185 MDNS_EXPORT int mdns_listen(const struct mdns_ctx *ctx, const char *const names[], 186 unsigned int nb_names, enum rr_type type, 187 unsigned int interval, mdns_stop_func stop, 188 mdns_listen_callback callback, void *p_cookie); 189 190 /** 191 * @brief Announce a new name to serve 192 * 193 * @param ctx A mdns context created by mdns_init() 194 * @param type The type of Record you want \see rr_type 195 * @param callback The callback function to send the entries 196 * @param p_cookie user data for the callback 197 * 198 * @return 0 if success, negative in other cases 199 */ 200 MDNS_EXPORT int mdns_announce(struct mdns_ctx *ctx, enum rr_type type, 201 mdns_announce_callback callback, void *p_cookie); 202 203 /** 204 * @brief The main serving function for mDNS 205 * mdns_announce() must be called before for each service you want to announce. 206 * 207 * @param ctx A mdns context created by mdns_init() 208 * @param stop The stop function to stop the discovery 209 * @param p_cookie user data for the callback 210 * 211 * @return 0 if success, negative in other cases 212 */ 213 214 MDNS_EXPORT int mdns_serve(struct mdns_ctx *ctx, mdns_stop_func stop, void *p_cookie); 215 216 /** 217 * @brief mdns_request_initial_announce Request an initial announce for the provided service 218 * @param ctx A mdns context created by mdns_init() 219 * @param service 220 */ 221 MDNS_EXPORT void mdns_request_initial_announce(struct mdns_ctx *ctx, const char* service); 222 223 # ifdef __cplusplus 224 } 225 # endif 226 227 #endif /* MICRODNS_MDNS_H */ 228