1 ReadMe About mDNSPosix 2 ---------------------- 3 4 mDNSPosix is a port of Apple's Multicast DNS and DNS Service Discovery 5 code to Posix platforms. 6 7 Multicast DNS and DNS Service Discovery are technologies that allow you 8 to register IP-based services and browse the network for those services. 9 For more information about mDNS, see the mDNS web site. 10 11 <http://www.multicastdns.org/> 12 13 Multicast DNS is part of a family of technologies resulting from the 14 efforts of the IETF Zeroconf working group. For information about 15 other Zeroconf technologies, see the Zeroconf web site. 16 17 <http://www.zeroconf.org/> 18 19 Apple uses the trade mark "Bonjour" to describe our implementation of 20 Zeroconf technologies. This sample is designed to show how easy it is 21 to make a device "Bonjour compatible". 22 23 The "Bonjour" trade mark can also be licensed at no charge for 24 inclusion on your own products, packaging, manuals, promotional 25 materials, or web site. For details and licensing terms, see 26 27 <http://developer.apple.com/bonjour/> 28 29 The code in this sample was compiled and tested on Mac OS X (10.1.x, 30 10.2, 10.3), Solaris (SunOS 5.8), Linux (Redhat 2.4.9-21, Fedora Core 1), 31 and OpenBSD (2.9). YMMV. 32 33 34 Packing List 35 ------------ 36 37 The sample uses the following directories: 38 39 o mDNSCore -- A directory containing the core mDNS code. This code 40 is written in pure ANSI C and has proved to be very portable. 41 Every platform needs this core protocol engine code. 42 43 o mDNSShared -- A directory containing useful code that's not core to 44 the main protocol engine itself, but nonetheless useful, and used by 45 more than one (but not necessarily all) platforms. 46 47 o mDNSPosix -- The files that are specific to Posix platforms: Linux, 48 Solaris, FreeBSD, NetBSD, OpenBSD, etc. This code will also work on 49 OS X, though that's not its primary purpose. 50 51 o Clients -- Example client code showing how to use the API to the 52 services provided by the daemon. 53 54 55 Building the Code 56 ----------------- 57 58 The sample does not use autoconf technology, primarily because I didn't 59 want to delay shipping while I learnt how to use it. Thus the code 60 builds using a very simple make file. To build the sample you should 61 cd to the mDNSPosix directory and type "make os=myos", e.g. 62 63 make os=panther 64 65 For Linux you would change that to: 66 67 make os=linux 68 69 There are definitions for each of the platforms I ported to. If you're 70 porting to any other platform please add appropriate definitions for it 71 and send us the diffs so they can be incorporated into the main 72 distribution. 73 74 75 Using the Sample 76 ---------------- 77 When you compile, you will get: 78 79 o Main products for general-purpose use (e.g. on a desktop computer): 80 - mdnsd 81 - libmdns 82 - nss_mdns (See nss_ReadMe.txt for important information about nss_mdns) 83 84 o Standalone products for dedicated devices (printer, network camera, etc.) 85 - mDNSClientPosix 86 - mDNSResponderPosix 87 - mDNSProxyResponderPosix 88 89 o Testing and Debugging tools 90 - dns-sd command-line tool (from the "Clients" folder) 91 - mDNSNetMonitor 92 - mDNSIdentify 93 94 As root type "make install" to install eight things: 95 o mdnsd (usually in /usr/sbin) 96 o libmdns (usually in /usr/lib) 97 o dns_sd.h (usually in /usr/include) 98 o startup scripts (e.g. in /etc/rc.d) 99 o manual pages (usually in /usr/share/man) 100 o dns-sd tool (usually in /usr/bin) 101 o nss_mdns (usually in /lib) 102 o nss configuration files (usually in /etc) 103 104 The "make install" concludes by executing the startup script 105 (usually "/etc/init.d/mdns start") to start the daemon running. 106 You shouldn't need to reboot unless you really want to. 107 108 Once the daemon is running, you can use the dns-sd test tool 109 to exercise all the major functionality of the daemon. Running 110 "dns-sd" with no arguments gives a summary of the available options. 111 This test tool is also described in detail, with several examples, 112 in Chapter 6 of the O'Reilly "Zero Configuration Networking" book. 113 114 115 How It Works 116 ------------ 117 +--------------------+ 118 | Client Application | 119 +----------------+ +--------------------+ 120 | uds_daemon.c | <--- Unix Domain Socket ---> | libmdns | 121 +----------------+ +--------------------+ 122 | mDNSCore | 123 +----------------+ 124 | mDNSPosix.c | 125 +----------------+ 126 127 mdnsd is divided into three sections. 128 129 o mDNSCore is the main protocol engine 130 o mDNSPosix.c provides the glue it needs to run on a Posix OS 131 o uds_daemon.c exports a Unix Domain Socket interface to 132 the services provided by mDNSCore 133 134 Client applications link with the libmdns, which implements the functions 135 defined in the dns_sd.h header file, and implements the IPC protocol 136 used to communicate over the Unix Domain Socket interface to the daemon. 137 138 Note that, strictly speaking, nss_mdns could be just another client of 139 mdnsd, linking with libmdns just like any other client. However, because 140 of its central role in the normal operation of multicast DNS, it is built 141 and installed along with the other essential system support components. 142 143 144 Clients for Embedded Systems 145 ---------------------------- 146 147 For small devices with very constrained resources, with a single address 148 space and (typically) no virtual memory, the uds_daemon.c/UDS/libmdns 149 layer may be eliminated, and the Client Application may live directly 150 on top of mDNSCore: 151 152 +--------------------+ 153 | Client Application | 154 +--------------------+ 155 | mDNSCore | 156 +--------------------+ 157 | mDNSPosix.c | 158 +--------------------+ 159 160 Programming to this model is more work, so using the daemon and its 161 library is recommended if your platform is capable of that. 162 163 The runtime behaviour when using the embedded model is as follows: 164 165 1. The application calls mDNS_Init, which in turns calls the platform 166 (mDNSPlatformInit). 167 168 2. mDNSPlatformInit gets a list of interfaces (get_ifi_info) and registers 169 each one with the core (mDNS_RegisterInterface). For each interface 170 it also creates a multicast socket (SetupSocket). 171 172 3. The application then calls select() repeatedly to handle file descriptor 173 events. Before calling select() each time, the application calls 174 mDNSPosixGetFDSet() to give mDNSPosix.c a chance to add its own file 175 descriptors to the set, and then after select() returns, it calls 176 mDNSPosixProcessFDSet() to give mDNSPosix.c a chance to receive and 177 process any packets that may have arrived. 178 179 4. When the core needs to send a UDP packet it calls 180 mDNSPlatformSendUDP. That routines finds the interface that 181 corresponds to the source address requested by the core, and 182 sends the datagram using the UDP socket created for the 183 interface. If the socket is flow send-side controlled it just 184 drops the packet. 185 186 5. When SocketDataReady runs it uses a complex routine, 187 "recvfrom_flags", to actually receive the packet. This is required 188 because the core needs information about the packet that is 189 only available via the "recvmsg" call, and that call is complex 190 to implement in a portable way. I got my implementation of 191 "recvfrom_flags" from Stevens' "UNIX Network Programming", but 192 I had to modify it further to work with Linux. 193 194 One thing to note is that the Posix platform code is very deliberately 195 not multi-threaded. I do everything from a main loop that calls 196 "select()". This is good because it avoids all the problems that often 197 accompany multi-threaded code. If you decide to use threads in your 198 platform, you will have to implement the mDNSPlatformLock() and 199 mDNSPlatformUnlock() calls which are currently no-ops in mDNSPosix.c. 200 201 202 Once you've built the embedded samples you can test them by first 203 running the client, as shown below. 204 205 quinn% build/mDNSClientPosix 206 Hit ^C when you're bored waiting for responses. 207 208 By default the client starts a search for AppleShare servers and then 209 sits and waits, printing a message when services appear and disappear. 210 211 To continue with the test you should start the responder in another 212 shell window. 213 214 quinn% build/mDNSResponderPosix -n Foo 215 216 This will start the responder and tell it to advertise a AppleShare 217 service "Foo". In the client window you will see the client print out 218 the following as the service shows up on the network. 219 220 quinn% build/mDNSClientPosix 221 Hit ^C when you're bored waiting for responses. 222 *** Found name = 'Foo', type = '_afpovertcp._tcp.', domain = 'local.' 223 224 Back in the responder window you can quit the responder cleanly using 225 SIGINT (typically ^C). 226 227 quinn% build/mDNSResponderPosix -n Foo 228 ^C 229 quinn% 230 231 As the responder quits it will multicast that the "Foo" service is 232 disappearing and the client will see that notification and print a 233 message to that effect (shown below). Finally, when you're done with 234 the client you can use SIGINT to quit it. 235 236 quinn% build/mDNSClientPosix 237 Hit ^C when you're bored waiting for responses. 238 *** Found name = 'Foo', type = '_afpovertcp._tcp.', domain = 'local.' 239 *** Lost name = 'Foo', type = '_afpovertcp._tcp.', domain = 'local.' 240 ^C 241 quinn% 242 243 If things don't work, try starting each program in verbose mode (using 244 the "-v 1" option, or very verbose mode with "-v 2") to see if there's 245 an obvious cause. 246 247 That's it for the core functionality. Each program supports a variety 248 of other options. For example, you can advertise and browse for a 249 different service type using the "-t type" option. Use the "-?" option 250 on each program for more user-level information. 251 252 253 Caveats 254 ------- 255 Currently the program uses a simple make file. 256 257 The Multicast DNS protocol can also operate locally over the loopback 258 interface, but this exposed some problems with the underlying network 259 stack in early versions of Mac OS X and may expose problems with other 260 network stacks too. 261 262 o On Mac OS X 10.1.x the code failed to start on the loopback interface 263 because the IP_ADD_MEMBERSHIP option returns ENOBUFS. 264 265 o On Mac OS X 10.2 the loopback-only case failed because 266 "sendto" calls fails with error EHOSTUNREACH. (3016042) 267 268 Consequently, the code will attempt service discovery on the loopback 269 interface only if no other interfaces are available. 270 271 I haven't been able to test the loopback-only case on other platforms 272 because I don't have access to the physical machine. 273 274 275 Licencing 276 --------- 277 This source code is Open Source; for details see the "LICENSE" file. 278 279 Credits and Version History 280 --------------------------- 281 If you find any problems with this sample, mail <dts (a] apple.com> and I 282 will try to fix them up. 283 284 1.0a1 (Jul 2002) was a prerelease version that was distributed 285 internally at Apple. 286 287 1.0a2 (Jul 2002) was a prerelease version that was distributed 288 internally at Apple. 289 290 1.0a3 (Aug 2002) was the first shipping version. The core mDNS code is 291 the code from Mac OS 10.2 (Jaguar) GM. 292 293 Share and Enjoy 294 295 Apple Developer Technical Support 296 Networking, Communications, Hardware 297 298 6 Aug 2002 299 300 Impact: A local network user may cause a denial of the Bonjour service 301 Description: An error handling issue exists in the Bonjour Namespace 302 Provider. A local network user may send a maliciously crafted multicast 303 DNS packet leading to an unexpected termination of the Bonjour service. 304 This update addresses the issue by performing additional validation of 305 multicast DNS packets. This issue does not affect systems running Mac OS 306 X or Windows. 307 CVE-ID 308 CVE-2011-0220 : JaeSeung Song of the Department of Computing at Imperial 309 College London 310 311 To Do List 312 ---------- 313 port to a System V that's not Solaris 314 use sig_atomic_t for signal to main thread flags 315