Home | History | Annotate | Download | only in mDNSPosix
      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