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