react-native-zeroconf 0.13.7 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/NOTICE +49 -0
  2. package/README.md +473 -65
  3. package/android/build.gradle +28 -22
  4. package/android/src/main/AndroidManifest.xml +1 -2
  5. package/android/src/main/java/com/balthazargronon/RCTZeroconf/ZeroconfModule.java +5 -5
  6. package/android/src/main/java/com/balthazargronon/RCTZeroconf/rx2dnssd/DnssdImpl.java +19 -3
  7. package/android/src/main/java/com/github/druk/dnssd/BaseListener.java +33 -0
  8. package/android/src/main/java/com/github/druk/dnssd/BrowseListener.java +67 -0
  9. package/android/src/main/java/com/github/druk/dnssd/DNSRecord.java +47 -0
  10. package/android/src/main/java/com/github/druk/dnssd/DNSSD.java +650 -0
  11. package/android/src/main/java/com/github/druk/dnssd/DNSSDBindable.java +67 -0
  12. package/android/src/main/java/com/github/druk/dnssd/DNSSDEmbedded.java +135 -0
  13. package/android/src/main/java/com/github/druk/dnssd/DNSSDException.java +66 -0
  14. package/android/src/main/java/com/github/druk/dnssd/DNSSDRecordRegistrar.java +55 -0
  15. package/android/src/main/java/com/github/druk/dnssd/DNSSDRegistration.java +54 -0
  16. package/android/src/main/java/com/github/druk/dnssd/DNSSDService.java +35 -0
  17. package/android/src/main/java/com/github/druk/dnssd/DomainListener.java +57 -0
  18. package/android/src/main/java/com/github/druk/dnssd/InternalBrowseListener.java +76 -0
  19. package/android/src/main/java/com/github/druk/dnssd/InternalDNSSD.java +870 -0
  20. package/android/src/main/java/com/github/druk/dnssd/InternalDNSSDRecordRegistrar.java +30 -0
  21. package/android/src/main/java/com/github/druk/dnssd/InternalDNSSDRegistration.java +34 -0
  22. package/android/src/main/java/com/github/druk/dnssd/InternalDNSSDService.java +29 -0
  23. package/android/src/main/java/com/github/druk/dnssd/InternalDomainListener.java +62 -0
  24. package/android/src/main/java/com/github/druk/dnssd/InternalQueryListener.java +61 -0
  25. package/android/src/main/java/com/github/druk/dnssd/InternalRegisterListener.java +51 -0
  26. package/android/src/main/java/com/github/druk/dnssd/InternalResolveListener.java +58 -0
  27. package/android/src/main/java/com/github/druk/dnssd/NSClass.java +16 -0
  28. package/android/src/main/java/com/github/druk/dnssd/NSType.java +58 -0
  29. package/android/src/main/java/com/github/druk/dnssd/QueryListener.java +54 -0
  30. package/android/src/main/java/com/github/druk/dnssd/RegisterListener.java +46 -0
  31. package/android/src/main/java/com/github/druk/dnssd/RegisterRecordListener.java +35 -0
  32. package/android/src/main/java/com/github/druk/dnssd/ResolveListener.java +55 -0
  33. package/android/src/main/java/com/github/druk/dnssd/TXTRecord.java +293 -0
  34. package/android/src/main/java/com/github/druk/rx2dnssd/BonjourService.java +400 -0
  35. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2BrowseListener.java +55 -0
  36. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2Dnssd.java +127 -0
  37. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2DnssdBindable.java +35 -0
  38. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2DnssdCommon.java +280 -0
  39. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2DnssdEmbedded.java +31 -0
  40. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2QueryListener.java +70 -0
  41. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2RegisterListener.java +47 -0
  42. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2ResolveListener.java +51 -0
  43. package/android/src/main/jni/Android.mk +95 -0
  44. package/android/src/main/jni/Application.mk +3 -0
  45. package/android/src/main/jni/DNSSD.java.h +290 -0
  46. package/android/src/main/jni/JNISupport.c +1140 -0
  47. package/android/src/main/jni/mdnsresponder/Android.bp +215 -0
  48. package/android/src/main/jni/mdnsresponder/Clients/ClientCommon.c +75 -0
  49. package/android/src/main/jni/mdnsresponder/Clients/ClientCommon.h +41 -0
  50. package/android/src/main/jni/mdnsresponder/Clients/Makefile +54 -0
  51. package/android/src/main/jni/mdnsresponder/Clients/ReadMe.txt +25 -0
  52. package/android/src/main/jni/mdnsresponder/Clients/dns-sd.c +1351 -0
  53. package/android/src/main/jni/mdnsresponder/LICENSE +13 -0
  54. package/android/src/main/jni/mdnsresponder/MODULE_LICENSE_APACHE2 +0 -0
  55. package/android/src/main/jni/mdnsresponder/Makefile +41 -0
  56. package/android/src/main/jni/mdnsresponder/NOTICE +13 -0
  57. package/android/src/main/jni/mdnsresponder/PrivateDNS.txt +275 -0
  58. package/android/src/main/jni/mdnsresponder/README.txt +166 -0
  59. package/android/src/main/jni/mdnsresponder/README.version +3 -0
  60. package/android/src/main/jni/mdnsresponder/android/caseMapping/Iphlpapi.h +1 -0
  61. package/android/src/main/jni/mdnsresponder/android/caseMapping/README +3 -0
  62. package/android/src/main/jni/mdnsresponder/android/caseMapping/Resource.h +1 -0
  63. package/android/src/main/jni/mdnsresponder/android/caseMapping/Ws2tcpip.h +1 -0
  64. package/android/src/main/jni/mdnsresponder/android/caseMapping/ipExport.h +1 -0
  65. package/android/src/main/jni/mdnsresponder/android/windows_firewall_dummy.c +10 -0
  66. package/android/src/main/jni/mdnsresponder/mDNSCore/DNSCommon.c +3157 -0
  67. package/android/src/main/jni/mdnsresponder/mDNSCore/DNSCommon.h +292 -0
  68. package/android/src/main/jni/mdnsresponder/mDNSCore/DNSDigest.c +1579 -0
  69. package/android/src/main/jni/mdnsresponder/mDNSCore/Implementer Notes.txt +66 -0
  70. package/android/src/main/jni/mdnsresponder/mDNSCore/mDNS.c +11469 -0
  71. package/android/src/main/jni/mdnsresponder/mDNSCore/mDNSDebug.h +164 -0
  72. package/android/src/main/jni/mdnsresponder/mDNSCore/mDNSEmbeddedAPI.h +2974 -0
  73. package/android/src/main/jni/mdnsresponder/mDNSCore/uDNS.c +4969 -0
  74. package/android/src/main/jni/mdnsresponder/mDNSCore/uDNS.h +132 -0
  75. package/android/src/main/jni/mdnsresponder/mDNSPosix/Client.c +223 -0
  76. package/android/src/main/jni/mdnsresponder/mDNSPosix/ExampleClientApp.c +91 -0
  77. package/android/src/main/jni/mdnsresponder/mDNSPosix/ExampleClientApp.h +18 -0
  78. package/android/src/main/jni/mdnsresponder/mDNSPosix/Identify.c +378 -0
  79. package/android/src/main/jni/mdnsresponder/mDNSPosix/Makefile +520 -0
  80. package/android/src/main/jni/mdnsresponder/mDNSPosix/NetMonitor.c +1010 -0
  81. package/android/src/main/jni/mdnsresponder/mDNSPosix/PosixDaemon.c +329 -0
  82. package/android/src/main/jni/mdnsresponder/mDNSPosix/ProxyResponder.c +300 -0
  83. package/android/src/main/jni/mdnsresponder/mDNSPosix/ReadMe.txt +314 -0
  84. package/android/src/main/jni/mdnsresponder/mDNSPosix/Responder.c +792 -0
  85. package/android/src/main/jni/mdnsresponder/mDNSPosix/Services.txt +36 -0
  86. package/android/src/main/jni/mdnsresponder/mDNSPosix/libnss_mdns.8 +148 -0
  87. package/android/src/main/jni/mdnsresponder/mDNSPosix/mDNSPosix.c +1685 -0
  88. package/android/src/main/jni/mdnsresponder/mDNSPosix/mDNSPosix.h +88 -0
  89. package/android/src/main/jni/mdnsresponder/mDNSPosix/mDNSUNP.c +726 -0
  90. package/android/src/main/jni/mdnsresponder/mDNSPosix/mDNSUNP.h +130 -0
  91. package/android/src/main/jni/mdnsresponder/mDNSPosix/mdnsd.sh +73 -0
  92. package/android/src/main/jni/mdnsresponder/mDNSPosix/nss_ReadMe.txt +125 -0
  93. package/android/src/main/jni/mdnsresponder/mDNSPosix/nss_mdns.c +2723 -0
  94. package/android/src/main/jni/mdnsresponder/mDNSPosix/nss_mdns.conf +13 -0
  95. package/android/src/main/jni/mdnsresponder/mDNSPosix/nss_mdns.conf.5 +135 -0
  96. package/android/src/main/jni/mdnsresponder/mDNSPosix/parselog.py +247 -0
  97. package/android/src/main/jni/mdnsresponder/mDNSResponder.sln +400 -0
  98. package/android/src/main/jni/mdnsresponder/mDNSShared/CommonServices.h +1537 -0
  99. package/android/src/main/jni/mdnsresponder/mDNSShared/DebugServices.c +3075 -0
  100. package/android/src/main/jni/mdnsresponder/mDNSShared/DebugServices.h +1607 -0
  101. package/android/src/main/jni/mdnsresponder/mDNSShared/GenLinkedList.c +319 -0
  102. package/android/src/main/jni/mdnsresponder/mDNSShared/GenLinkedList.h +90 -0
  103. package/android/src/main/jni/mdnsresponder/mDNSShared/PlatformCommon.c +220 -0
  104. package/android/src/main/jni/mdnsresponder/mDNSShared/PlatformCommon.h +18 -0
  105. package/android/src/main/jni/mdnsresponder/mDNSShared/dns-sd.1 +194 -0
  106. package/android/src/main/jni/mdnsresponder/mDNSShared/dns_sd.h +2452 -0
  107. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd.8 +69 -0
  108. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd.c +3146 -0
  109. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd.conf +60 -0
  110. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd.h +163 -0
  111. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd_lexer.l +84 -0
  112. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd_parser.y +585 -0
  113. package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_clientlib.c +368 -0
  114. package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_clientshim.c +802 -0
  115. package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_clientstub.c +1988 -0
  116. package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_ipc.c +161 -0
  117. package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_ipc.h +219 -0
  118. package/android/src/main/jni/mdnsresponder/mDNSShared/mDNS.1 +198 -0
  119. package/android/src/main/jni/mdnsresponder/mDNSShared/mDNSDebug.c +93 -0
  120. package/android/src/main/jni/mdnsresponder/mDNSShared/mDNSResponder.8 +116 -0
  121. package/android/src/main/jni/mdnsresponder/mDNSShared/uds_daemon.c +4758 -0
  122. package/android/src/main/jni/mdnsresponder/mDNSShared/uds_daemon.h +80 -0
  123. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/BrowsingPage.cpp +441 -0
  124. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/BrowsingPage.h +156 -0
  125. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ConfigDialog.cpp +59 -0
  126. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ConfigDialog.h +48 -0
  127. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp +301 -0
  128. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ConfigPropertySheet.h +105 -0
  129. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanel.cpp +380 -0
  130. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanel.def +20 -0
  131. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanel.h +84 -0
  132. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanel.rc +141 -0
  133. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanel.vcproj +727 -0
  134. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelDll.rc +123 -0
  135. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelExe.cpp +373 -0
  136. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelExe.h +48 -0
  137. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelExe.rc +123 -0
  138. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelExe.vcproj +764 -0
  139. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelLocRes.rc +270 -0
  140. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelLocRes.vcproj +487 -0
  141. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelRes.rc +134 -0
  142. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelRes.vcproj +518 -0
  143. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/FourthPage.cpp +197 -0
  144. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/FourthPage.h +87 -0
  145. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/RegistrationPage.cpp +387 -0
  146. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/RegistrationPage.h +75 -0
  147. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/SecondPage.cpp +544 -0
  148. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/SecondPage.h +107 -0
  149. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ServicesPage.cpp +273 -0
  150. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ServicesPage.h +123 -0
  151. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/SharedSecret.cpp +115 -0
  152. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/SharedSecret.h +54 -0
  153. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/ControlPanel.dll.manifest +10 -0
  154. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/ControlPanel.exe.manifest +17 -0
  155. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/ControlPanel.manifest +17 -0
  156. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/ControlPanel.rc2 +13 -0
  157. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/ControlPanel64.manifest +17 -0
  158. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/EnergySaver.ico +0 -0
  159. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/controlpanel.ico +0 -0
  160. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/failure.ico +0 -0
  161. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/success.ico +0 -0
  162. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/resource.h +56 -0
  163. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/stdafx.cpp +20 -0
  164. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/stdafx.h +64 -0
  165. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/dll.aps +0 -0
  166. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/dll.rc +102 -0
  167. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/dllmain.c +112 -0
  168. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/dnssd.def +48 -0
  169. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/dnssd.vcproj +472 -0
  170. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/resource.h +27 -0
  171. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/AssemblyInfo.cpp +84 -0
  172. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/PString.h +70 -0
  173. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/Stdafx.cpp +22 -0
  174. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/Stdafx.h +33 -0
  175. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/dnssd_NET.cpp +1234 -0
  176. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/dnssd_NET.h +1392 -0
  177. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/dnssd_NET.ico +0 -0
  178. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/dnssd_NET.rc +113 -0
  179. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/dnssd_NET.vcproj +446 -0
  180. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/resource.h +3 -0
  181. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLStub/DLLStub.cpp +693 -0
  182. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLStub/DLLStub.h +52 -0
  183. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLStub/DLLStub.vcproj +324 -0
  184. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.cpp +208 -0
  185. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.def +35 -0
  186. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.idl +491 -0
  187. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.rc +126 -0
  188. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.rgs +11 -0
  189. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.vcproj +625 -0
  190. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSD.cpp +892 -0
  191. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDEventManager.cpp +31 -0
  192. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDEventManager.h +133 -0
  193. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDEventManager.rgs +27 -0
  194. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDRecord.cpp +101 -0
  195. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDRecord.h +185 -0
  196. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDRecord.rgs +27 -0
  197. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDService.cpp +2095 -0
  198. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDService.h +429 -0
  199. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDService.rgs +27 -0
  200. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/StringServices.cpp +344 -0
  201. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/StringServices.h +102 -0
  202. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/TXTRecord.cpp +381 -0
  203. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/TXTRecord.h +203 -0
  204. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/TXTRecord.rgs +27 -0
  205. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/_IDNSSDEvents_CP.h +358 -0
  206. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/dlldatax.c +51 -0
  207. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/dlldatax.h +49 -0
  208. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/resource.h +30 -0
  209. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/stdafx.h +88 -0
  210. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/ApplicationVS2002.sln +21 -0
  211. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/ApplicationVS2002.vcproj +253 -0
  212. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/ApplicationVS2003.sln +21 -0
  213. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/ApplicationVS2003.vcproj +267 -0
  214. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Resources/Application.ico +0 -0
  215. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Resources/Application.rc +323 -0
  216. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Resources/Application.rc2 +20 -0
  217. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Resources/Resource.h +53 -0
  218. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.cpp +71 -0
  219. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.h +62 -0
  220. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/Application.cpp +111 -0
  221. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/Application.h +68 -0
  222. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp +1426 -0
  223. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.h +131 -0
  224. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/LoginDialog.cpp +109 -0
  225. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/LoginDialog.h +53 -0
  226. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/StdAfx.cpp +18 -0
  227. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/StdAfx.h +48 -0
  228. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Application.vcc +37 -0
  229. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Application.vcp +868 -0
  230. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Application.vcw +29 -0
  231. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/Application.ico +0 -0
  232. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/Application.rc +194 -0
  233. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/Application.rc2 +13 -0
  234. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/newres.h +28 -0
  235. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/resource.h +22 -0
  236. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/Application.cpp +92 -0
  237. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/Application.h +57 -0
  238. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp +394 -0
  239. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.h +84 -0
  240. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/StdAfx.cpp +18 -0
  241. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/StdAfx.h +46 -0
  242. package/android/src/main/jni/mdnsresponder/mDNSWindows/Java/Java.vcproj +111 -0
  243. package/android/src/main/jni/mdnsresponder/mDNSWindows/Java/jdns_sd.rc +62 -0
  244. package/android/src/main/jni/mdnsresponder/mDNSWindows/Java/makefile +143 -0
  245. package/android/src/main/jni/mdnsresponder/mDNSWindows/Java/makefile64 +143 -0
  246. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/NSPTool.aps +0 -0
  247. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/NSPTool.c +581 -0
  248. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/NSPTool.rc +103 -0
  249. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/NSPTool.vcproj +409 -0
  250. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/Prefix.h +28 -0
  251. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/resource.h +27 -0
  252. package/android/src/main/jni/mdnsresponder/mDNSWindows/PosixCompat.c +128 -0
  253. package/android/src/main/jni/mdnsresponder/mDNSWindows/PosixCompat.h +70 -0
  254. package/android/src/main/jni/mdnsresponder/mDNSWindows/README.txt +85 -0
  255. package/android/src/main/jni/mdnsresponder/mDNSWindows/RegNames.h +57 -0
  256. package/android/src/main/jni/mdnsresponder/mDNSWindows/Secret.c +338 -0
  257. package/android/src/main/jni/mdnsresponder/mDNSWindows/Secret.h +42 -0
  258. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/EventLog.mc +11 -0
  259. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/EventLogMessages.bin +0 -0
  260. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Firewall.cpp +484 -0
  261. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Firewall.h +79 -0
  262. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Prefix.h +30 -0
  263. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.aps +0 -0
  264. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.c +2669 -0
  265. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.h +30 -0
  266. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.mcp +0 -0
  267. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.rc +114 -0
  268. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.vcproj +562 -0
  269. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/main.c +32 -0
  270. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/res/mDNSResponder.manifest +12 -0
  271. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/res/mDNSResponder64.manifest +12 -0
  272. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/resource.h +17 -0
  273. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/resrc1.h +15 -0
  274. package/android/src/main/jni/mdnsresponder/mDNSWindows/VPCDetect.cpp +165 -0
  275. package/android/src/main/jni/mdnsresponder/mDNSWindows/VPCDetect.h +36 -0
  276. package/android/src/main/jni/mdnsresponder/mDNSWindows/WinServices.cpp +93 -0
  277. package/android/src/main/jni/mdnsresponder/mDNSWindows/WinServices.h +34 -0
  278. package/android/src/main/jni/mdnsresponder/mDNSWindows/WinVersRes.h +35 -0
  279. package/android/src/main/jni/mdnsresponder/mDNSWindows/isocode.h +135 -0
  280. package/android/src/main/jni/mdnsresponder/mDNSWindows/loclibrary.c +268 -0
  281. package/android/src/main/jni/mdnsresponder/mDNSWindows/loclibrary.h +54 -0
  282. package/android/src/main/jni/mdnsresponder/mDNSWindows/mDNSWin32.c +5200 -0
  283. package/android/src/main/jni/mdnsresponder/mDNSWindows/mDNSWin32.h +208 -0
  284. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/ReadMe.txt +15 -0
  285. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/mdnsNSP.aps +0 -0
  286. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/mdnsNSP.c +2430 -0
  287. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/mdnsNSP.def +24 -0
  288. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/mdnsNSP.rc +104 -0
  289. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/mdnsNSP.vcproj +457 -0
  290. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/resource.h +27 -0
  291. package/android/src/main/jni/mdnsresponder/mdnsd.rc +7 -0
  292. package/android/src/main/jni/nameser.h +588 -0
  293. package/dist/index.js +148 -1
  294. package/package.json +23 -17
  295. package/src/index.js +166 -0
@@ -0,0 +1,4758 @@
1
+ /* -*- Mode: C; tab-width: 4 -*-
2
+ *
3
+ * Copyright (c) 2003-2006 Apple Computer, Inc. All rights reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #if defined(_WIN32)
19
+ #include <process.h>
20
+ #define usleep(X) Sleep(((X)+999)/1000)
21
+ #else
22
+ #include <fcntl.h>
23
+ #include <errno.h>
24
+ #include <sys/ioctl.h>
25
+ #include <sys/types.h>
26
+ #include <sys/time.h>
27
+ #include <sys/resource.h>
28
+ #endif
29
+
30
+ #include <stdlib.h>
31
+ #include <stdio.h>
32
+
33
+ #include "mDNSEmbeddedAPI.h"
34
+ #include "DNSCommon.h"
35
+ #include "uDNS.h"
36
+ #include "uds_daemon.h"
37
+
38
+ #ifndef EMBEDDED
39
+ #ifdef __ANDROID__
40
+ #include "cutils/sockets.h"
41
+ #endif
42
+ #endif
43
+
44
+ // Normally we append search domains only for queries with a single label that are not
45
+ // fully qualified. This can be overridden to apply search domains for queries (that are
46
+ // not fully qualified) with any number of labels e.g., moon, moon.cs, moon.cs.be, etc.
47
+ mDNSBool AlwaysAppendSearchDomains = mDNSfalse;
48
+
49
+ // Apple-specific functionality, not required for other platforms
50
+ #if APPLE_OSX_mDNSResponder
51
+ #include <sys/ucred.h>
52
+ #ifndef PID_FILE
53
+ #define PID_FILE ""
54
+ #endif
55
+ #endif
56
+
57
+ #if APPLE_OSX_mDNSResponder
58
+ #include <WebFilterDNS/WebFilterDNS.h>
59
+
60
+ #if ! NO_WCF
61
+
62
+ int WCFIsServerRunning(WCFConnection *conn) __attribute__((weak_import));
63
+ int WCFNameResolvesToAddr(WCFConnection *conn, char* domainName, struct sockaddr* address, uid_t userid) __attribute__((weak_import));
64
+ int WCFNameResolvesToName(WCFConnection *conn, char* fromName, char* toName, uid_t userid) __attribute__((weak_import));
65
+
66
+ // Do we really need to define a macro for "if"?
67
+ #define CHECK_WCF_FUNCTION(X) if (X)
68
+ #endif // ! NO_WCF
69
+
70
+ #else
71
+ #define NO_WCF 1
72
+ #endif // APPLE_OSX_mDNSResponder
73
+
74
+ // User IDs 0-500 are system-wide processes, not actual users in the usual sense
75
+ // User IDs for real user accounts start at 501 and count up from there
76
+ #define SystemUID(X) ((X) <= 500)
77
+
78
+ // ***************************************************************************
79
+ #if COMPILER_LIKES_PRAGMA_MARK
80
+ #pragma mark -
81
+ #pragma mark - Types and Data Structures
82
+ #endif
83
+
84
+ typedef enum
85
+ {
86
+ t_uninitialized,
87
+ t_morecoming,
88
+ t_complete,
89
+ t_error,
90
+ t_terminated
91
+ } transfer_state;
92
+
93
+ typedef struct request_state request_state;
94
+
95
+ typedef void (*req_termination_fn)(request_state *request);
96
+
97
+ typedef struct registered_record_entry
98
+ {
99
+ struct registered_record_entry *next;
100
+ mDNSu32 key;
101
+ client_context_t regrec_client_context;
102
+ request_state *request;
103
+ mDNSBool external_advertise;
104
+ mDNSInterfaceID origInterfaceID;
105
+ AuthRecord *rr; // Pointer to variable-sized AuthRecord (Why a pointer? Why not just embed it here?)
106
+ } registered_record_entry;
107
+
108
+ // A single registered service: ServiceRecordSet + bookkeeping
109
+ // Note that we duplicate some fields from parent service_info object
110
+ // to facilitate cleanup, when instances and parent may be deallocated at different times.
111
+ typedef struct service_instance
112
+ {
113
+ struct service_instance *next;
114
+ request_state *request;
115
+ AuthRecord *subtypes;
116
+ mDNSBool renameonmemfree; // Set on config change when we deregister original name
117
+ mDNSBool clientnotified; // Has client been notified of successful registration yet?
118
+ mDNSBool default_local; // is this the "local." from an empty-string registration?
119
+ mDNSBool external_advertise; // is this is being advertised externally?
120
+ domainname domain;
121
+ ServiceRecordSet srs; // note -- variable-sized object -- must be last field in struct
122
+ } service_instance;
123
+
124
+ // for multi-domain default browsing
125
+ typedef struct browser_t
126
+ {
127
+ struct browser_t *next;
128
+ domainname domain;
129
+ DNSQuestion q;
130
+ } browser_t;
131
+
132
+ struct request_state
133
+ {
134
+ request_state *next;
135
+ request_state *primary; // If this operation is on a shared socket, pointer to primary
136
+ // request_state for the original DNSServiceCreateConnection() operation
137
+ dnssd_sock_t sd;
138
+ dnssd_sock_t errsd;
139
+ mDNSu32 uid;
140
+ void * platform_data;
141
+
142
+ // Note: On a shared connection these fields in the primary structure, including hdr, are re-used
143
+ // for each new request. This is because, until we've read the ipc_msg_hdr to find out what the
144
+ // operation is, we don't know if we're going to need to allocate a new request_state or not.
145
+ transfer_state ts;
146
+ mDNSu32 hdr_bytes; // bytes of header already read
147
+ ipc_msg_hdr hdr;
148
+ mDNSu32 data_bytes; // bytes of message data already read
149
+ char *msgbuf; // pointer to data storage to pass to free()
150
+ const char *msgptr; // pointer to data to be read from (may be modified)
151
+ char *msgend; // pointer to byte after last byte of message
152
+
153
+ // reply, termination, error, and client context info
154
+ int no_reply; // don't send asynchronous replies to client
155
+ mDNSs32 time_blocked; // record time of a blocked client
156
+ int unresponsiveness_reports;
157
+ struct reply_state *replies; // corresponding (active) reply list
158
+ req_termination_fn terminate;
159
+ DNSServiceFlags flags;
160
+
161
+ union
162
+ {
163
+ registered_record_entry *reg_recs; // list of registrations for a connection-oriented request
164
+ struct
165
+ {
166
+ mDNSInterfaceID interface_id;
167
+ mDNSBool default_domain;
168
+ mDNSBool ForceMCast;
169
+ domainname regtype;
170
+ browser_t *browsers;
171
+ } browser;
172
+ struct
173
+ {
174
+ mDNSInterfaceID InterfaceID;
175
+ mDNSu16 txtlen;
176
+ void *txtdata;
177
+ mDNSIPPort port;
178
+ domainlabel name;
179
+ char type_as_string[MAX_ESCAPED_DOMAIN_NAME];
180
+ domainname type;
181
+ mDNSBool default_domain;
182
+ domainname host;
183
+ mDNSBool autoname; // Set if this name is tied to the Computer Name
184
+ mDNSBool autorename; // Set if this client wants us to automatically rename on conflict
185
+ mDNSBool allowremotequery; // Respond to unicast queries from outside the local link?
186
+ int num_subtypes;
187
+ service_instance *instances;
188
+ } servicereg;
189
+ struct
190
+ {
191
+ mDNSInterfaceID interface_id;
192
+ mDNSu32 flags;
193
+ mDNSu32 protocol;
194
+ DNSQuestion q4;
195
+ DNSQuestion *q42;
196
+ DNSQuestion q6;
197
+ DNSQuestion *q62;
198
+ } addrinfo;
199
+ struct
200
+ {
201
+ mDNSIPPort ReqExt; // External port we originally requested, for logging purposes
202
+ NATTraversalInfo NATinfo;
203
+ } pm;
204
+ struct
205
+ {
206
+ #if 0
207
+ DNSServiceFlags flags;
208
+ #endif
209
+ DNSQuestion q_all;
210
+ DNSQuestion q_default;
211
+ } enumeration;
212
+ struct
213
+ {
214
+ DNSQuestion q;
215
+ DNSQuestion *q2;
216
+ } queryrecord;
217
+ struct
218
+ {
219
+ DNSQuestion qtxt;
220
+ DNSQuestion qsrv;
221
+ const ResourceRecord *txt;
222
+ const ResourceRecord *srv;
223
+ mDNSs32 ReportTime;
224
+ mDNSBool external_advertise;
225
+ } resolve;
226
+ } u;
227
+ };
228
+
229
+ // struct physically sits between ipc message header and call-specific fields in the message buffer
230
+ typedef struct
231
+ {
232
+ DNSServiceFlags flags; // Note: This field is in NETWORK byte order
233
+ mDNSu32 ifi; // Note: This field is in NETWORK byte order
234
+ DNSServiceErrorType error; // Note: This field is in NETWORK byte order
235
+ } reply_hdr;
236
+
237
+ typedef struct reply_state
238
+ {
239
+ struct reply_state *next; // If there are multiple unsent replies
240
+ mDNSu32 totallen;
241
+ mDNSu32 nwriten;
242
+ ipc_msg_hdr mhdr[1];
243
+ reply_hdr rhdr[1];
244
+ } reply_state;
245
+
246
+ // ***************************************************************************
247
+ #if COMPILER_LIKES_PRAGMA_MARK
248
+ #pragma mark -
249
+ #pragma mark - Globals
250
+ #endif
251
+
252
+ // globals
253
+ mDNSexport mDNS mDNSStorage;
254
+ mDNSexport const char ProgramName[] = "mDNSResponder";
255
+
256
+ static dnssd_sock_t listenfd = dnssd_InvalidSocket;
257
+ static request_state *all_requests = NULL;
258
+
259
+ // Note asymmetry here between registration and browsing.
260
+ // For service registrations we only automatically register in domains that explicitly appear in local configuration data
261
+ // (so AutoRegistrationDomains could equally well be called SCPrefRegDomains)
262
+ // For service browsing we also learn automatic browsing domains from the network, so for that case we have:
263
+ // 1. SCPrefBrowseDomains (local configuration data)
264
+ // 2. LocalDomainEnumRecords (locally-generated local-only PTR records -- equivalent to slElem->AuthRecs in uDNS.c)
265
+ // 3. AutoBrowseDomains, which is populated by tracking add/rmv events in AutomaticBrowseDomainChange, the callback function for our mDNS_GetDomains call.
266
+ // By creating and removing our own LocalDomainEnumRecords, we trigger AutomaticBrowseDomainChange callbacks just like domains learned from the network would.
267
+
268
+ mDNSexport DNameListElem *AutoRegistrationDomains; // Domains where we automatically register for empty-string registrations
269
+
270
+ static DNameListElem *SCPrefBrowseDomains; // List of automatic browsing domains read from SCPreferences for "empty string" browsing
271
+ static ARListElem *LocalDomainEnumRecords; // List of locally-generated PTR records to augment those we learn from the network
272
+ mDNSexport DNameListElem *AutoBrowseDomains; // List created from those local-only PTR records plus records we get from the network
273
+
274
+ #define MSG_PAD_BYTES 5 // pad message buffer (read from client) with n zero'd bytes to guarantee
275
+ // n get_string() calls w/o buffer overrun
276
+ // initialization, setup/teardown functions
277
+
278
+ // If a platform specifies its own PID file name, we use that
279
+ #ifndef PID_FILE
280
+ #define PID_FILE "/var/run/mDNSResponder.pid"
281
+ #endif
282
+
283
+ // ***************************************************************************
284
+ #if COMPILER_LIKES_PRAGMA_MARK
285
+ #pragma mark -
286
+ #pragma mark - General Utility Functions
287
+ #endif
288
+
289
+ mDNSlocal void FatalError(char *errmsg)
290
+ {
291
+ LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno));
292
+ *(volatile long*)0 = 0; // On OS X abort() doesn't generate a crash log, but writing to zero does
293
+ abort(); // On platforms where writing to zero doesn't generate an exception, abort instead
294
+ }
295
+
296
+ mDNSlocal mDNSu32 dnssd_htonl(mDNSu32 l)
297
+ {
298
+ mDNSu32 ret;
299
+ char *data = (char*) &ret;
300
+ put_uint32(l, &data);
301
+ return ret;
302
+ }
303
+
304
+ // hack to search-replace perror's to LogMsg's
305
+ mDNSlocal void my_perror(char *errmsg)
306
+ {
307
+ LogMsg("%s: %d (%s)", errmsg, dnssd_errno, dnssd_strerror(dnssd_errno));
308
+ }
309
+
310
+ mDNSlocal void abort_request(request_state *req)
311
+ {
312
+ if (req->terminate == (req_termination_fn)~0)
313
+ { LogMsg("abort_request: ERROR: Attempt to abort operation %p with req->terminate %p", req, req->terminate); return; }
314
+
315
+ // First stop whatever mDNSCore operation we were doing
316
+ // If this is actually a shared connection operation, then its req->terminate function will scan
317
+ // the all_requests list and terminate any subbordinate operations sharing this file descriptor
318
+ if (req->terminate) req->terminate(req);
319
+
320
+ if (!dnssd_SocketValid(req->sd))
321
+ { LogMsg("abort_request: ERROR: Attempt to abort operation %p with invalid fd %d", req, req->sd); return; }
322
+
323
+ // Now, if this request_state is not subordinate to some other primary, close file descriptor and discard replies
324
+ if (!req->primary)
325
+ {
326
+ if (req->errsd != req->sd) LogOperation("%3d: Removing FD and closing errsd %d", req->sd, req->errsd);
327
+ else LogOperation("%3d: Removing FD", req->sd);
328
+ udsSupportRemoveFDFromEventLoop(req->sd, req->platform_data); // Note: This also closes file descriptor req->sd for us
329
+ if (req->errsd != req->sd) { dnssd_close(req->errsd); req->errsd = req->sd; }
330
+
331
+ while (req->replies) // free pending replies
332
+ {
333
+ reply_state *ptr = req->replies;
334
+ req->replies = req->replies->next;
335
+ freeL("reply_state (abort)", ptr);
336
+ }
337
+ }
338
+
339
+ // Set req->sd to something invalid, so that udsserver_idle knows to unlink and free this structure
340
+ #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING
341
+ // Don't use dnssd_InvalidSocket (-1) because that's the sentinel value MACOSX_MDNS_MALLOC_DEBUGGING uses
342
+ // for detecting when the memory for an object is inadvertently freed while the object is still on some list
343
+ req->sd = req->errsd = -2;
344
+ #else
345
+ req->sd = req->errsd = dnssd_InvalidSocket;
346
+ #endif
347
+ // We also set req->terminate to a bogus value so we know if abort_request() gets called again for this request
348
+ req->terminate = (req_termination_fn)~0;
349
+ }
350
+
351
+ mDNSlocal void AbortUnlinkAndFree(request_state *req)
352
+ {
353
+ request_state **p = &all_requests;
354
+ abort_request(req);
355
+ while (*p && *p != req) p=&(*p)->next;
356
+ if (*p) { *p = req->next; freeL("request_state/AbortUnlinkAndFree", req); }
357
+ else LogMsg("AbortUnlinkAndFree: ERROR: Attempt to abort operation %p not in list", req);
358
+ }
359
+
360
+ mDNSlocal reply_state *create_reply(const reply_op_t op, const size_t datalen, request_state *const request)
361
+ {
362
+ reply_state *reply;
363
+
364
+ if ((unsigned)datalen < sizeof(reply_hdr))
365
+ {
366
+ LogMsg("ERROR: create_reply - data length less than length of required fields");
367
+ return NULL;
368
+ }
369
+
370
+ reply = mallocL("reply_state", sizeof(reply_state) + datalen - sizeof(reply_hdr));
371
+ if (!reply) FatalError("ERROR: malloc");
372
+
373
+ reply->next = mDNSNULL;
374
+ reply->totallen = (mDNSu32)datalen + sizeof(ipc_msg_hdr);
375
+ reply->nwriten = 0;
376
+
377
+ reply->mhdr->version = VERSION;
378
+ reply->mhdr->datalen = (mDNSu32)datalen;
379
+ reply->mhdr->ipc_flags = 0;
380
+ reply->mhdr->op = op;
381
+ reply->mhdr->client_context = request->hdr.client_context;
382
+ reply->mhdr->reg_index = 0;
383
+
384
+ return reply;
385
+ }
386
+
387
+ // Append a reply to the list in a request object
388
+ // If our request is sharing a connection, then we append our reply_state onto the primary's list
389
+ mDNSlocal void append_reply(request_state *req, reply_state *rep)
390
+ {
391
+ request_state *r = req->primary ? req->primary : req;
392
+ reply_state **ptr = &r->replies;
393
+ while (*ptr) ptr = &(*ptr)->next;
394
+ *ptr = rep;
395
+ rep->next = NULL;
396
+ }
397
+
398
+ // Generates a response message giving name, type, domain, plus interface index,
399
+ // suitable for a browse result or service registration result.
400
+ // On successful completion rep is set to point to a malloc'd reply_state struct
401
+ mDNSlocal mStatus GenerateNTDResponse(const domainname *const servicename, const mDNSInterfaceID id,
402
+ request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err)
403
+ {
404
+ domainlabel name;
405
+ domainname type, dom;
406
+ *rep = NULL;
407
+ if (!DeconstructServiceName(servicename, &name, &type, &dom))
408
+ return kDNSServiceErr_Invalid;
409
+ else
410
+ {
411
+ char namestr[MAX_DOMAIN_LABEL+1];
412
+ char typestr[MAX_ESCAPED_DOMAIN_NAME];
413
+ char domstr [MAX_ESCAPED_DOMAIN_NAME];
414
+ int len;
415
+ char *data;
416
+
417
+ ConvertDomainLabelToCString_unescaped(&name, namestr);
418
+ ConvertDomainNameToCString(&type, typestr);
419
+ ConvertDomainNameToCString(&dom, domstr);
420
+
421
+ // Calculate reply data length
422
+ len = sizeof(DNSServiceFlags);
423
+ len += sizeof(mDNSu32); // if index
424
+ len += sizeof(DNSServiceErrorType);
425
+ len += (int) (strlen(namestr) + 1);
426
+ len += (int) (strlen(typestr) + 1);
427
+ len += (int) (strlen(domstr) + 1);
428
+
429
+ // Build reply header
430
+ *rep = create_reply(op, len, request);
431
+ (*rep)->rhdr->flags = dnssd_htonl(flags);
432
+ (*rep)->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, id, mDNSfalse));
433
+ (*rep)->rhdr->error = dnssd_htonl(err);
434
+
435
+ // Build reply body
436
+ data = (char *)&(*rep)->rhdr[1];
437
+ put_string(namestr, &data);
438
+ put_string(typestr, &data);
439
+ put_string(domstr, &data);
440
+
441
+ return mStatus_NoError;
442
+ }
443
+ }
444
+
445
+ // Special support to enable the DNSServiceBrowse call made by Bonjour Browser
446
+ // Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
447
+ mDNSlocal void GenerateBonjourBrowserResponse(const domainname *const servicename, const mDNSInterfaceID id,
448
+ request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err)
449
+ {
450
+ char namestr[MAX_DOMAIN_LABEL+1];
451
+ char typestr[MAX_ESCAPED_DOMAIN_NAME];
452
+ static const char domstr[] = ".";
453
+ int len;
454
+ char *data;
455
+
456
+ *rep = NULL;
457
+
458
+ // 1. Put first label in namestr
459
+ ConvertDomainLabelToCString_unescaped((const domainlabel *)servicename, namestr);
460
+
461
+ // 2. Put second label and "local" into typestr
462
+ mDNS_snprintf(typestr, sizeof(typestr), "%#s.local.", SecondLabel(servicename));
463
+
464
+ // Calculate reply data length
465
+ len = sizeof(DNSServiceFlags);
466
+ len += sizeof(mDNSu32); // if index
467
+ len += sizeof(DNSServiceErrorType);
468
+ len += (int) (strlen(namestr) + 1);
469
+ len += (int) (strlen(typestr) + 1);
470
+ len += (int) (strlen(domstr) + 1);
471
+
472
+ // Build reply header
473
+ *rep = create_reply(op, len, request);
474
+ (*rep)->rhdr->flags = dnssd_htonl(flags);
475
+ (*rep)->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, id, mDNSfalse));
476
+ (*rep)->rhdr->error = dnssd_htonl(err);
477
+
478
+ // Build reply body
479
+ data = (char *)&(*rep)->rhdr[1];
480
+ put_string(namestr, &data);
481
+ put_string(typestr, &data);
482
+ put_string(domstr, &data);
483
+ }
484
+
485
+ // Returns a resource record (allocated w/ malloc) containing the data found in an IPC message
486
+ // Data must be in the following format: flags, interfaceIndex, name, rrtype, rrclass, rdlen, rdata, (optional) ttl
487
+ // (ttl only extracted/set if ttl argument is non-zero). Returns NULL for a bad-parameter error
488
+ mDNSlocal AuthRecord *read_rr_from_ipc_msg(request_state *request, int GetTTL, int validate_flags)
489
+ {
490
+ DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
491
+ mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
492
+ char name[256];
493
+ int str_err = get_string(&request->msgptr, request->msgend, name, sizeof(name));
494
+ mDNSu16 type = get_uint16(&request->msgptr, request->msgend);
495
+ mDNSu16 class = get_uint16(&request->msgptr, request->msgend);
496
+ mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
497
+ const char *rdata = get_rdata (&request->msgptr, request->msgend, rdlen);
498
+ mDNSu32 ttl = GetTTL ? get_uint32(&request->msgptr, request->msgend) : 0;
499
+ int storage_size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
500
+ AuthRecord *rr;
501
+ mDNSInterfaceID InterfaceID;
502
+ AuthRecType artype;
503
+
504
+ request->flags = flags;
505
+
506
+ if (str_err) { LogMsg("ERROR: read_rr_from_ipc_msg - get_string"); return NULL; }
507
+
508
+ if (!request->msgptr) { LogMsg("Error reading Resource Record from client"); return NULL; }
509
+
510
+ if (validate_flags &&
511
+ !((flags & kDNSServiceFlagsShared) == kDNSServiceFlagsShared) &&
512
+ !((flags & kDNSServiceFlagsUnique) == kDNSServiceFlagsUnique))
513
+ {
514
+ LogMsg("ERROR: Bad resource record flags (must be kDNSServiceFlagsShared or kDNSServiceFlagsUnique)");
515
+ return NULL;
516
+ }
517
+
518
+ rr = mallocL("AuthRecord/read_rr_from_ipc_msg", sizeof(AuthRecord) - sizeof(RDataBody) + storage_size);
519
+ if (!rr) FatalError("ERROR: malloc");
520
+
521
+ InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
522
+ if (InterfaceID == mDNSInterface_LocalOnly)
523
+ artype = AuthRecordLocalOnly;
524
+ else if (InterfaceID == mDNSInterface_P2P)
525
+ artype = AuthRecordP2P;
526
+ else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P))
527
+ artype = AuthRecordAnyIncludeP2P;
528
+ else
529
+ artype = AuthRecordAny;
530
+
531
+ mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, type, 0,
532
+ (mDNSu8) ((flags & kDNSServiceFlagsShared) ? kDNSRecordTypeShared : kDNSRecordTypeUnique), artype, mDNSNULL, mDNSNULL);
533
+
534
+ if (!MakeDomainNameFromDNSNameString(&rr->namestorage, name))
535
+ {
536
+ LogMsg("ERROR: bad name: %s", name);
537
+ freeL("AuthRecord/read_rr_from_ipc_msg", rr);
538
+ return NULL;
539
+ }
540
+
541
+ if (flags & kDNSServiceFlagsAllowRemoteQuery) rr->AllowRemoteQuery = mDNStrue;
542
+ rr->resrec.rrclass = class;
543
+ rr->resrec.rdlength = rdlen;
544
+ rr->resrec.rdata->MaxRDLength = rdlen;
545
+ mDNSPlatformMemCopy(rr->resrec.rdata->u.data, rdata, rdlen);
546
+ if (GetTTL) rr->resrec.rroriginalttl = ttl;
547
+ rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
548
+ SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rr->rdatahash for us
549
+ return rr;
550
+ }
551
+
552
+ mDNSlocal int build_domainname_from_strings(domainname *srv, char *name, char *regtype, char *domain)
553
+ {
554
+ domainlabel n;
555
+ domainname d, t;
556
+
557
+ if (!MakeDomainLabelFromLiteralString(&n, name)) return -1;
558
+ if (!MakeDomainNameFromDNSNameString(&t, regtype)) return -1;
559
+ if (!MakeDomainNameFromDNSNameString(&d, domain)) return -1;
560
+ if (!ConstructServiceName(srv, &n, &t, &d)) return -1;
561
+ return 0;
562
+ }
563
+
564
+ mDNSlocal void send_all(dnssd_sock_t s, const char *ptr, int len)
565
+ {
566
+ int n = send(s, ptr, len, 0);
567
+ // On a freshly-created Unix Domain Socket, the kernel should *never* fail to buffer a small write for us
568
+ // (four bytes for a typical error code return, 12 bytes for DNSServiceGetProperty(DaemonVersion)).
569
+ // If it does fail, we don't attempt to handle this failure, but we do log it so we know something is wrong.
570
+ if (n < len)
571
+ LogMsg("ERROR: send_all(%d) wrote %d of %d errno %d (%s)",
572
+ s, n, len, dnssd_errno, dnssd_strerror(dnssd_errno));
573
+ }
574
+
575
+ #if 0
576
+ mDNSlocal mDNSBool AuthorizedDomain(const request_state * const request, const domainname * const d, const DNameListElem * const doms)
577
+ {
578
+ const DNameListElem *delem = mDNSNULL;
579
+ int bestDelta = -1; // the delta of the best match, lower is better
580
+ int dLabels = 0;
581
+ mDNSBool allow = mDNSfalse;
582
+
583
+ if (SystemUID(request->uid)) return mDNStrue;
584
+
585
+ dLabels = CountLabels(d);
586
+ for (delem = doms; delem; delem = delem->next)
587
+ {
588
+ if (delem->uid)
589
+ {
590
+ int delemLabels = CountLabels(&delem->name);
591
+ int delta = dLabels - delemLabels;
592
+ if ((bestDelta == -1 || delta <= bestDelta) && SameDomainName(&delem->name, SkipLeadingLabels(d, delta)))
593
+ {
594
+ bestDelta = delta;
595
+ allow = (allow || (delem->uid == request->uid));
596
+ }
597
+ }
598
+ }
599
+
600
+ return bestDelta == -1 ? mDNStrue : allow;
601
+ }
602
+ #endif
603
+
604
+ // ***************************************************************************
605
+ #if COMPILER_LIKES_PRAGMA_MARK
606
+ #pragma mark -
607
+ #pragma mark - external helpers
608
+ #endif
609
+
610
+ mDNSlocal void external_start_advertising_helper(service_instance *const instance)
611
+ {
612
+ AuthRecord *st = instance->subtypes;
613
+ ExtraResourceRecord *e;
614
+ int i;
615
+
616
+ if (mDNSIPPortIsZero(instance->request->u.servicereg.port))
617
+ {
618
+ LogInfo("external_start_advertising_helper: Not registering service with port number zero");
619
+ return;
620
+ }
621
+
622
+ #if APPLE_OSX_mDNSResponder
623
+ // Update packet filter if p2p interface already exists, otherwise,
624
+ // if will be updated when we get the KEV_DL_IF_ATTACHED event for
625
+ // the interface. Called here since we don't call external_start_advertising_service()
626
+ // with the SRV record when advertising a service.
627
+ mDNSInitPacketFilter();
628
+ #endif // APPLE_OSX_mDNSResponder
629
+
630
+ if (instance->external_advertise) LogMsg("external_start_advertising_helper: external_advertise already set!");
631
+
632
+ for ( i = 0; i < instance->request->u.servicereg.num_subtypes; i++)
633
+ external_start_advertising_service(&st[i].resrec);
634
+
635
+ external_start_advertising_service(&instance->srs.RR_PTR.resrec);
636
+ external_start_advertising_service(&instance->srs.RR_TXT.resrec);
637
+
638
+ for (e = instance->srs.Extras; e; e = e->next)
639
+ external_start_advertising_service(&e->r.resrec);
640
+
641
+ instance->external_advertise = mDNStrue;
642
+ }
643
+
644
+ mDNSlocal void external_stop_advertising_helper(service_instance *const instance)
645
+ {
646
+ AuthRecord *st = instance->subtypes;
647
+ ExtraResourceRecord *e;
648
+ int i;
649
+
650
+ if (!instance->external_advertise) return;
651
+
652
+ LogInfo("external_stop_advertising_helper: calling external_stop_advertising_service");
653
+
654
+ for ( i = 0; i < instance->request->u.servicereg.num_subtypes; i++)
655
+ external_stop_advertising_service(&st[i].resrec);
656
+
657
+ external_stop_advertising_service(&instance->srs.RR_PTR.resrec);
658
+ external_stop_advertising_service(&instance->srs.RR_TXT.resrec);
659
+
660
+ for (e = instance->srs.Extras; e; e = e->next)
661
+ external_stop_advertising_service(&e->r.resrec);
662
+
663
+ instance->external_advertise = mDNSfalse;
664
+ }
665
+
666
+ // ***************************************************************************
667
+ #if COMPILER_LIKES_PRAGMA_MARK
668
+ #pragma mark -
669
+ #pragma mark - DNSServiceRegister
670
+ #endif
671
+
672
+ mDNSexport void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result)
673
+ {
674
+ ExtraResourceRecord *extra = (ExtraResourceRecord *)rr->RecordContext;
675
+ (void)m; // Unused
676
+
677
+ if (result != mStatus_MemFree) { LogMsg("Error: FreeExtraRR invoked with unexpected error %d", result); return; }
678
+
679
+ LogInfo(" FreeExtraRR %s", RRDisplayString(m, &rr->resrec));
680
+
681
+ if (rr->resrec.rdata != &rr->rdatastorage)
682
+ freeL("Extra RData", rr->resrec.rdata);
683
+ freeL("ExtraResourceRecord/FreeExtraRR", extra);
684
+ }
685
+
686
+ mDNSlocal void unlink_and_free_service_instance(service_instance *srv)
687
+ {
688
+ ExtraResourceRecord *e = srv->srs.Extras, *tmp;
689
+
690
+ external_stop_advertising_helper(srv);
691
+
692
+ // clear pointers from parent struct
693
+ if (srv->request)
694
+ {
695
+ service_instance **p = &srv->request->u.servicereg.instances;
696
+ while (*p)
697
+ {
698
+ if (*p == srv) { *p = (*p)->next; break; }
699
+ p = &(*p)->next;
700
+ }
701
+ }
702
+
703
+ while (e)
704
+ {
705
+ e->r.RecordContext = e;
706
+ tmp = e;
707
+ e = e->next;
708
+ FreeExtraRR(&mDNSStorage, &tmp->r, mStatus_MemFree);
709
+ }
710
+
711
+ if (srv->srs.RR_TXT.resrec.rdata != &srv->srs.RR_TXT.rdatastorage)
712
+ freeL("TXT RData", srv->srs.RR_TXT.resrec.rdata);
713
+
714
+ if (srv->subtypes) { freeL("ServiceSubTypes", srv->subtypes); srv->subtypes = NULL; }
715
+ freeL("service_instance", srv);
716
+ }
717
+
718
+ // Count how many other service records we have locally with the same name, but different rdata.
719
+ // For auto-named services, we can have at most one per machine -- if we allowed two auto-named services of
720
+ // the same type on the same machine, we'd get into an infinite autoimmune-response loop of continuous renaming.
721
+ mDNSexport int CountPeerRegistrations(mDNS *const m, ServiceRecordSet *const srs)
722
+ {
723
+ int count = 0;
724
+ ResourceRecord *r = &srs->RR_SRV.resrec;
725
+ AuthRecord *rr;
726
+
727
+ for (rr = m->ResourceRecords; rr; rr=rr->next)
728
+ if (rr->resrec.rrtype == kDNSType_SRV && SameDomainName(rr->resrec.name, r->name) && !IdenticalSameNameRecord(&rr->resrec, r))
729
+ count++;
730
+
731
+ verbosedebugf("%d peer registrations for %##s", count, r->name->c);
732
+ return(count);
733
+ }
734
+
735
+ mDNSexport int CountExistingRegistrations(domainname *srv, mDNSIPPort port)
736
+ {
737
+ int count = 0;
738
+ AuthRecord *rr;
739
+ for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
740
+ if (rr->resrec.rrtype == kDNSType_SRV &&
741
+ mDNSSameIPPort(rr->resrec.rdata->u.srv.port, port) &&
742
+ SameDomainName(rr->resrec.name, srv))
743
+ count++;
744
+ return(count);
745
+ }
746
+
747
+ mDNSlocal void SendServiceRemovalNotification(ServiceRecordSet *const srs)
748
+ {
749
+ reply_state *rep;
750
+ service_instance *instance = srs->ServiceContext;
751
+ if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, 0, mStatus_NoError) != mStatus_NoError)
752
+ LogMsg("%3d: SendServiceRemovalNotification: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
753
+ else { append_reply(instance->request, rep); instance->clientnotified = mDNSfalse; }
754
+ }
755
+
756
+ // service registration callback performs three duties - frees memory for deregistered services,
757
+ // handles name conflicts, and delivers completed registration information to the client
758
+ mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
759
+ {
760
+ mStatus err;
761
+ mDNSBool SuppressError = mDNSfalse;
762
+ service_instance *instance;
763
+ reply_state *rep;
764
+ (void)m; // Unused
765
+
766
+ if (!srs) { LogMsg("regservice_callback: srs is NULL %d", result); return; }
767
+
768
+ instance = srs->ServiceContext;
769
+ if (!instance) { LogMsg("regservice_callback: srs->ServiceContext is NULL %d", result); return; }
770
+
771
+ // don't send errors up to client for wide-area, empty-string registrations
772
+ if (instance->request &&
773
+ instance->request->u.servicereg.default_domain &&
774
+ !instance->default_local)
775
+ SuppressError = mDNStrue;
776
+
777
+ if (mDNS_LoggingEnabled)
778
+ {
779
+ const char *const fmt =
780
+ (result == mStatus_NoError) ? "%s DNSServiceRegister(%##s, %u) REGISTERED" :
781
+ (result == mStatus_MemFree) ? "%s DNSServiceRegister(%##s, %u) DEREGISTERED" :
782
+ (result == mStatus_NameConflict) ? "%s DNSServiceRegister(%##s, %u) NAME CONFLICT" :
783
+ "%s DNSServiceRegister(%##s, %u) %s %d";
784
+ char prefix[16] = "---:";
785
+ if (instance->request) mDNS_snprintf(prefix, sizeof(prefix), "%3d:", instance->request->sd);
786
+ LogOperation(fmt, prefix, srs->RR_SRV.resrec.name->c, mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port),
787
+ SuppressError ? "suppressed error" : "CALLBACK", result);
788
+ }
789
+
790
+ if (!instance->request && result != mStatus_MemFree) { LogMsg("regservice_callback: instance->request is NULL %d", result); return; }
791
+
792
+ if (result == mStatus_NoError)
793
+ {
794
+ if (instance->request->u.servicereg.allowremotequery)
795
+ {
796
+ ExtraResourceRecord *e;
797
+ srs->RR_ADV.AllowRemoteQuery = mDNStrue;
798
+ srs->RR_PTR.AllowRemoteQuery = mDNStrue;
799
+ srs->RR_SRV.AllowRemoteQuery = mDNStrue;
800
+ srs->RR_TXT.AllowRemoteQuery = mDNStrue;
801
+ for (e = instance->srs.Extras; e; e = e->next) e->r.AllowRemoteQuery = mDNStrue;
802
+ }
803
+
804
+ if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
805
+ LogMsg("%3d: regservice_callback: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
806
+ else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
807
+
808
+ if (instance->request->u.servicereg.InterfaceID == mDNSInterface_P2P || (!instance->request->u.servicereg.InterfaceID && SameDomainName(&instance->domain, &localdomain) && (instance->request->flags & kDNSServiceFlagsIncludeP2P)))
809
+ {
810
+ LogInfo("regservice_callback: calling external_start_advertising_helper()");
811
+ external_start_advertising_helper(instance);
812
+ }
813
+ if (instance->request->u.servicereg.autoname && CountPeerRegistrations(m, srs) == 0)
814
+ RecordUpdatedNiceLabel(m, 0); // Successfully got new name, tell user immediately
815
+ }
816
+ else if (result == mStatus_MemFree)
817
+ {
818
+ if (instance->request && instance->renameonmemfree)
819
+ {
820
+ external_stop_advertising_helper(instance);
821
+ instance->renameonmemfree = 0;
822
+ err = mDNS_RenameAndReregisterService(m, srs, &instance->request->u.servicereg.name);
823
+ if (err) LogMsg("ERROR: regservice_callback - RenameAndReregisterService returned %d", err);
824
+ // error should never happen - safest to log and continue
825
+ }
826
+ else
827
+ unlink_and_free_service_instance(instance);
828
+ }
829
+ else if (result == mStatus_NameConflict)
830
+ {
831
+ if (instance->request->u.servicereg.autorename)
832
+ {
833
+ external_stop_advertising_helper(instance);
834
+ if (instance->request->u.servicereg.autoname && CountPeerRegistrations(m, srs) == 0)
835
+ {
836
+ // On conflict for an autoname service, rename and reregister *all* autoname services
837
+ IncrementLabelSuffix(&m->nicelabel, mDNStrue);
838
+ mDNS_ConfigChanged(m); // Will call back into udsserver_handle_configchange()
839
+ }
840
+ else // On conflict for a non-autoname service, rename and reregister just that one service
841
+ {
842
+ if (instance->clientnotified) SendServiceRemovalNotification(srs);
843
+ mDNS_RenameAndReregisterService(m, srs, mDNSNULL);
844
+ }
845
+ }
846
+ else
847
+ {
848
+ if (!SuppressError)
849
+ {
850
+ if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
851
+ LogMsg("%3d: regservice_callback: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
852
+ else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
853
+ }
854
+ unlink_and_free_service_instance(instance);
855
+ }
856
+ }
857
+ else // Not mStatus_NoError, mStatus_MemFree, or mStatus_NameConflict
858
+ {
859
+ if (!SuppressError)
860
+ {
861
+ if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
862
+ LogMsg("%3d: regservice_callback: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
863
+ else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
864
+ }
865
+ }
866
+ }
867
+
868
+ mDNSlocal void regrecord_callback(mDNS *const m, AuthRecord *rr, mStatus result)
869
+ {
870
+ (void)m; // Unused
871
+ if (!rr->RecordContext) // parent struct already freed by termination callback
872
+ {
873
+ if (result == mStatus_NoError)
874
+ LogMsg("Error: regrecord_callback: successful registration of orphaned record %s", ARDisplayString(m, rr));
875
+ else
876
+ {
877
+ if (result != mStatus_MemFree) LogMsg("regrecord_callback: error %d received after parent termination", result);
878
+
879
+ // We come here when the record is being deregistered either from DNSServiceRemoveRecord or connection_termination.
880
+ // If the record has been updated, we need to free the rdata. Everytime we call mDNS_Update, it calls update_callback
881
+ // with the old rdata (so that we can free it) and stores the new rdata in "rr->resrec.rdata". This means, we need
882
+ // to free the latest rdata for which the update_callback was never called with.
883
+ if (rr->resrec.rdata != &rr->rdatastorage) freeL("RData/regrecord_callback", rr->resrec.rdata);
884
+ freeL("AuthRecord/regrecord_callback", rr);
885
+ }
886
+ }
887
+ else
888
+ {
889
+ registered_record_entry *re = rr->RecordContext;
890
+ request_state *request = re->request;
891
+
892
+ if (mDNS_LoggingEnabled)
893
+ {
894
+ char *fmt = (result == mStatus_NoError) ? "%3d: DNSServiceRegisterRecord(%u %s) REGISTERED" :
895
+ (result == mStatus_MemFree) ? "%3d: DNSServiceRegisterRecord(%u %s) DEREGISTERED" :
896
+ (result == mStatus_NameConflict) ? "%3d: DNSServiceRegisterRecord(%u %s) NAME CONFLICT" :
897
+ "%3d: DNSServiceRegisterRecord(%u %s) %d";
898
+ LogOperation(fmt, request->sd, re->key, RRDisplayString(m, &rr->resrec), result);
899
+ }
900
+
901
+ if (result != mStatus_MemFree)
902
+ {
903
+ int len = sizeof(DNSServiceFlags) + sizeof(mDNSu32) + sizeof(DNSServiceErrorType);
904
+ reply_state *reply = create_reply(reg_record_reply_op, len, request);
905
+ reply->mhdr->client_context = re->regrec_client_context;
906
+ reply->rhdr->flags = dnssd_htonl(0);
907
+ reply->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, rr->resrec.InterfaceID, mDNSfalse));
908
+ reply->rhdr->error = dnssd_htonl(result);
909
+ append_reply(request, reply);
910
+ }
911
+
912
+ if (result)
913
+ {
914
+ // unlink from list, free memory
915
+ registered_record_entry **ptr = &request->u.reg_recs;
916
+ while (*ptr && (*ptr) != re) ptr = &(*ptr)->next;
917
+ if (!*ptr) { LogMsg("regrecord_callback - record not in list!"); return; }
918
+ *ptr = (*ptr)->next;
919
+ freeL("registered_record_entry AuthRecord regrecord_callback", re->rr);
920
+ freeL("registered_record_entry regrecord_callback", re);
921
+ }
922
+ else
923
+ {
924
+ if (re->external_advertise) LogMsg("regrecord_callback: external_advertise already set!");
925
+
926
+ if (re->origInterfaceID == mDNSInterface_P2P || (!re->origInterfaceID && IsLocalDomain(&rr->namestorage) && (request->flags & kDNSServiceFlagsIncludeP2P)))
927
+ {
928
+ LogInfo("regrecord_callback: calling external_start_advertising_service");
929
+ external_start_advertising_service(&rr->resrec);
930
+ re->external_advertise = mDNStrue;
931
+ }
932
+ }
933
+ }
934
+ }
935
+
936
+ mDNSlocal void connection_termination(request_state *request)
937
+ {
938
+ // When terminating a shared connection, we need to scan the all_requests list
939
+ // and terminate any subbordinate operations sharing this file descriptor
940
+ request_state **req = &all_requests;
941
+
942
+ LogOperation("%3d: DNSServiceCreateConnection STOP", request->sd);
943
+
944
+ while (*req)
945
+ {
946
+ if ((*req)->primary == request)
947
+ {
948
+ // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
949
+ request_state *tmp = *req;
950
+ if (tmp->primary == tmp) LogMsg("connection_termination ERROR (*req)->primary == *req for %p %d", tmp, tmp->sd);
951
+ if (tmp->replies) LogMsg("connection_termination ERROR How can subordinate req %p %d have replies queued?", tmp, tmp->sd);
952
+ abort_request(tmp);
953
+ *req = tmp->next;
954
+ freeL("request_state/connection_termination", tmp);
955
+ }
956
+ else
957
+ req = &(*req)->next;
958
+ }
959
+
960
+ while (request->u.reg_recs)
961
+ {
962
+ registered_record_entry *ptr = request->u.reg_recs;
963
+ LogOperation("%3d: DNSServiceRegisterRecord(%u %s) STOP", request->sd, ptr->key, RRDisplayString(&mDNSStorage, &ptr->rr->resrec));
964
+ request->u.reg_recs = request->u.reg_recs->next;
965
+ ptr->rr->RecordContext = NULL;
966
+ if (ptr->external_advertise)
967
+ {
968
+ ptr->external_advertise = mDNSfalse;
969
+ external_stop_advertising_service(&ptr->rr->resrec);
970
+ }
971
+ mDNS_Deregister(&mDNSStorage, ptr->rr); // Will free ptr->rr for us
972
+ freeL("registered_record_entry/connection_termination", ptr);
973
+ }
974
+ }
975
+
976
+ mDNSlocal void handle_cancel_request(request_state *request)
977
+ {
978
+ request_state **req = &all_requests;
979
+ LogOperation("%3d: Cancel %08X %08X", request->sd, request->hdr.client_context.u32[1], request->hdr.client_context.u32[0]);
980
+ while (*req)
981
+ {
982
+ if ((*req)->primary == request &&
983
+ (*req)->hdr.client_context.u32[0] == request->hdr.client_context.u32[0] &&
984
+ (*req)->hdr.client_context.u32[1] == request->hdr.client_context.u32[1])
985
+ {
986
+ // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
987
+ request_state *tmp = *req;
988
+ abort_request(tmp);
989
+ *req = tmp->next;
990
+ freeL("request_state/handle_cancel_request", tmp);
991
+ }
992
+ else
993
+ req = &(*req)->next;
994
+ }
995
+ }
996
+
997
+ mDNSlocal mStatus handle_regrecord_request(request_state *request)
998
+ {
999
+ mStatus err = mStatus_BadParamErr;
1000
+ AuthRecord *rr = read_rr_from_ipc_msg(request, 1, 1);
1001
+ if (rr)
1002
+ {
1003
+ registered_record_entry *re;
1004
+ // Don't allow non-local domains to be regsitered as LocalOnly. Allowing this would permit
1005
+ // clients to register records such as www.bigbank.com A w.x.y.z to redirect Safari.
1006
+ if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly && !IsLocalDomain(rr->resrec.name) &&
1007
+ rr->resrec.rrclass == kDNSClass_IN && (rr->resrec.rrtype == kDNSType_A || rr->resrec.rrtype == kDNSType_AAAA ||
1008
+ rr->resrec.rrtype == kDNSType_CNAME))
1009
+ {
1010
+ freeL("AuthRecord/handle_regrecord_request", rr);
1011
+ return (mStatus_BadParamErr);
1012
+ }
1013
+ // allocate registration entry, link into list
1014
+ re = mallocL("registered_record_entry", sizeof(registered_record_entry));
1015
+ if (!re) FatalError("ERROR: malloc");
1016
+ re->key = request->hdr.reg_index;
1017
+ re->rr = rr;
1018
+ re->regrec_client_context = request->hdr.client_context;
1019
+ re->request = request;
1020
+ re->external_advertise = mDNSfalse;
1021
+ rr->RecordContext = re;
1022
+ rr->RecordCallback = regrecord_callback;
1023
+
1024
+ re->origInterfaceID = rr->resrec.InterfaceID;
1025
+ if (rr->resrec.InterfaceID == mDNSInterface_P2P) rr->resrec.InterfaceID = mDNSInterface_Any;
1026
+ #if 0
1027
+ if (!AuthorizedDomain(request, rr->resrec.name, AutoRegistrationDomains)) return (mStatus_NoError);
1028
+ #endif
1029
+ if (rr->resrec.rroriginalttl == 0)
1030
+ rr->resrec.rroriginalttl = DefaultTTLforRRType(rr->resrec.rrtype);
1031
+
1032
+ LogOperation("%3d: DNSServiceRegisterRecord(%u %s) START", request->sd, re->key, RRDisplayString(&mDNSStorage, &rr->resrec));
1033
+ err = mDNS_Register(&mDNSStorage, rr);
1034
+ if (err)
1035
+ {
1036
+ LogOperation("%3d: DNSServiceRegisterRecord(%u %s) ERROR (%d)", request->sd, re->key, RRDisplayString(&mDNSStorage, &rr->resrec), err);
1037
+ freeL("registered_record_entry", re);
1038
+ freeL("registered_record_entry/AuthRecord", rr);
1039
+ }
1040
+ else
1041
+ {
1042
+ re->next = request->u.reg_recs;
1043
+ request->u.reg_recs = re;
1044
+ }
1045
+ }
1046
+ return(err);
1047
+ }
1048
+
1049
+ mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m);
1050
+
1051
+ mDNSlocal void regservice_termination_callback(request_state *request)
1052
+ {
1053
+ if (!request) { LogMsg("regservice_termination_callback context is NULL"); return; }
1054
+ while (request->u.servicereg.instances)
1055
+ {
1056
+ service_instance *p = request->u.servicereg.instances;
1057
+ request->u.servicereg.instances = request->u.servicereg.instances->next;
1058
+ // only safe to free memory if registration is not valid, i.e. deregister fails (which invalidates p)
1059
+ LogOperation("%3d: DNSServiceRegister(%##s, %u) STOP",
1060
+ request->sd, p->srs.RR_SRV.resrec.name->c, mDNSVal16(p->srs.RR_SRV.resrec.rdata->u.srv.port));
1061
+
1062
+ external_stop_advertising_helper(p);
1063
+
1064
+ // Clear backpointer *before* calling mDNS_DeregisterService/unlink_and_free_service_instance
1065
+ // We don't need unlink_and_free_service_instance to cut its element from the list, because we're already advancing
1066
+ // request->u.servicereg.instances as we work our way through the list, implicitly cutting one element at a time
1067
+ // We can't clear p->request *after* the calling mDNS_DeregisterService/unlink_and_free_service_instance
1068
+ // because by then we might have already freed p
1069
+ p->request = NULL;
1070
+ if (mDNS_DeregisterService(&mDNSStorage, &p->srs)) unlink_and_free_service_instance(p);
1071
+ // Don't touch service_instance *p after this -- it's likely to have been freed already
1072
+ }
1073
+ if (request->u.servicereg.txtdata)
1074
+ { freeL("service_info txtdata", request->u.servicereg.txtdata); request->u.servicereg.txtdata = NULL; }
1075
+ if (request->u.servicereg.autoname)
1076
+ {
1077
+ // Clear autoname before calling UpdateDeviceInfoRecord() so it doesn't mistakenly include this in its count of active autoname registrations
1078
+ request->u.servicereg.autoname = mDNSfalse;
1079
+ UpdateDeviceInfoRecord(&mDNSStorage);
1080
+ }
1081
+ }
1082
+
1083
+ mDNSlocal request_state *LocateSubordinateRequest(request_state *request)
1084
+ {
1085
+ request_state *req;
1086
+ for (req = all_requests; req; req = req->next)
1087
+ if (req->primary == request &&
1088
+ req->hdr.client_context.u32[0] == request->hdr.client_context.u32[0] &&
1089
+ req->hdr.client_context.u32[1] == request->hdr.client_context.u32[1]) return(req);
1090
+ return(request);
1091
+ }
1092
+
1093
+ mDNSlocal mStatus add_record_to_service(request_state *request, service_instance *instance, mDNSu16 rrtype, mDNSu16 rdlen, const char *rdata, mDNSu32 ttl)
1094
+ {
1095
+ ServiceRecordSet *srs = &instance->srs;
1096
+ mStatus result;
1097
+ int size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
1098
+ ExtraResourceRecord *extra = mallocL("ExtraResourceRecord", sizeof(*extra) - sizeof(RDataBody) + size);
1099
+ if (!extra) { my_perror("ERROR: malloc"); return mStatus_NoMemoryErr; }
1100
+
1101
+ mDNSPlatformMemZero(extra, sizeof(ExtraResourceRecord)); // OK if oversized rdata not zero'd
1102
+ extra->r.resrec.rrtype = rrtype;
1103
+ extra->r.rdatastorage.MaxRDLength = (mDNSu16) size;
1104
+ extra->r.resrec.rdlength = rdlen;
1105
+ mDNSPlatformMemCopy(&extra->r.rdatastorage.u.data, rdata, rdlen);
1106
+
1107
+ result = mDNS_AddRecordToService(&mDNSStorage, srs, extra, &extra->r.rdatastorage, ttl,
1108
+ (request->flags & kDNSServiceFlagsIncludeP2P) ? 1: 0);
1109
+ if (result) { freeL("ExtraResourceRecord/add_record_to_service", extra); return result; }
1110
+
1111
+ extra->ClientID = request->hdr.reg_index;
1112
+ if (instance->external_advertise && (instance->request->u.servicereg.InterfaceID == mDNSInterface_P2P || (!instance->request->u.servicereg.InterfaceID && SameDomainName(&instance->domain, &localdomain) && (instance->request->flags & kDNSServiceFlagsIncludeP2P))))
1113
+ {
1114
+ LogInfo("add_record_to_service: calling external_start_advertising_service");
1115
+ external_start_advertising_service(&extra->r.resrec);
1116
+ }
1117
+ return result;
1118
+ }
1119
+
1120
+ mDNSlocal mStatus handle_add_request(request_state *request)
1121
+ {
1122
+ service_instance *i;
1123
+ mStatus result = mStatus_UnknownErr;
1124
+ DNSServiceFlags flags = get_flags (&request->msgptr, request->msgend);
1125
+ mDNSu16 rrtype = get_uint16(&request->msgptr, request->msgend);
1126
+ mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
1127
+ const char *rdata = get_rdata (&request->msgptr, request->msgend, rdlen);
1128
+ mDNSu32 ttl = get_uint32(&request->msgptr, request->msgend);
1129
+ if (!ttl) ttl = DefaultTTLforRRType(rrtype);
1130
+ (void)flags; // Unused
1131
+
1132
+ if (!request->msgptr) { LogMsg("%3d: DNSServiceAddRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
1133
+
1134
+ // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
1135
+ if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
1136
+
1137
+ if (request->terminate != regservice_termination_callback)
1138
+ { LogMsg("%3d: DNSServiceAddRecord(not a registered service ref)", request->sd); return(mStatus_BadParamErr); }
1139
+
1140
+ // For a service registered with zero port, don't allow adding records. This mostly happens due to a bug
1141
+ // in the application. See radar://9165807.
1142
+ if (mDNSIPPortIsZero(request->u.servicereg.port))
1143
+ { LogMsg("%3d: DNSServiceAddRecord: adding record to a service registered with zero port", request->sd); return(mStatus_BadParamErr); }
1144
+
1145
+ LogOperation("%3d: DNSServiceAddRecord(%X, %##s, %s, %d)", request->sd, flags,
1146
+ (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL, DNSTypeName(rrtype), rdlen);
1147
+
1148
+ for (i = request->u.servicereg.instances; i; i = i->next)
1149
+ {
1150
+ result = add_record_to_service(request, i, rrtype, rdlen, rdata, ttl);
1151
+ if (result && i->default_local) break;
1152
+ else result = mStatus_NoError; // suppress non-local default errors
1153
+ }
1154
+
1155
+ return(result);
1156
+ }
1157
+
1158
+ mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd, mDNSu16 oldrdlen)
1159
+ {
1160
+ mDNSBool external_advertise = (rr->UpdateContext) ? *((mDNSBool *)rr->UpdateContext) : mDNSfalse;
1161
+ (void)m; // Unused
1162
+
1163
+ // There are three cases.
1164
+ //
1165
+ // 1. We have updated the primary TXT record of the service
1166
+ // 2. We have updated the TXT record that was added to the service using DNSServiceAddRecord
1167
+ // 3. We have updated the TXT record that was registered using DNSServiceRegisterRecord
1168
+ //
1169
+ // external_advertise is set if we have advertised at least once during the initial addition
1170
+ // of the record in all of the three cases above. We should have checked for InterfaceID/LocalDomain
1171
+ // checks during the first time and hence we don't do any checks here
1172
+ if (external_advertise)
1173
+ {
1174
+ ResourceRecord ext = rr->resrec;
1175
+ if (ext.rdlength == oldrdlen && mDNSPlatformMemSame(&ext.rdata->u, &oldrd->u, oldrdlen)) goto exit;
1176
+ SetNewRData(&ext, oldrd, oldrdlen);
1177
+ external_stop_advertising_service(&ext);
1178
+ LogInfo("update_callback: calling external_start_advertising_service");
1179
+ external_start_advertising_service(&rr->resrec);
1180
+ }
1181
+ exit:
1182
+ if (oldrd != &rr->rdatastorage) freeL("RData/update_callback", oldrd);
1183
+ }
1184
+
1185
+ mDNSlocal mStatus update_record(AuthRecord *rr, mDNSu16 rdlen, const char *rdata, mDNSu32 ttl, const mDNSBool *const external_advertise)
1186
+ {
1187
+ mStatus result;
1188
+ const int rdsize = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
1189
+ RData *newrd = mallocL("RData/update_record", sizeof(RData) - sizeof(RDataBody) + rdsize);
1190
+ if (!newrd) FatalError("ERROR: malloc");
1191
+ newrd->MaxRDLength = (mDNSu16) rdsize;
1192
+ mDNSPlatformMemCopy(&newrd->u, rdata, rdlen);
1193
+
1194
+ // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
1195
+ // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
1196
+ // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
1197
+ if (rr->resrec.rrtype == kDNSType_TXT && rdlen == 0) { rdlen = 1; newrd->u.txt.c[0] = 0; }
1198
+
1199
+ if (external_advertise) rr->UpdateContext = (void *)external_advertise;
1200
+
1201
+ result = mDNS_Update(&mDNSStorage, rr, ttl, rdlen, newrd, update_callback);
1202
+ if (result) { LogMsg("update_record: Error %d for %s", (int)result, ARDisplayString(&mDNSStorage, rr)); freeL("RData/update_record", newrd); }
1203
+ return result;
1204
+ }
1205
+
1206
+ mDNSlocal mStatus handle_update_request(request_state *request)
1207
+ {
1208
+ const ipc_msg_hdr *const hdr = &request->hdr;
1209
+ mStatus result = mStatus_BadReferenceErr;
1210
+ service_instance *i;
1211
+ AuthRecord *rr = NULL;
1212
+
1213
+ // get the message data
1214
+ DNSServiceFlags flags = get_flags (&request->msgptr, request->msgend); // flags unused
1215
+ mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
1216
+ const char *rdata = get_rdata (&request->msgptr, request->msgend, rdlen);
1217
+ mDNSu32 ttl = get_uint32(&request->msgptr, request->msgend);
1218
+ (void)flags; // Unused
1219
+
1220
+ if (!request->msgptr) { LogMsg("%3d: DNSServiceUpdateRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
1221
+
1222
+ // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
1223
+ if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
1224
+
1225
+ if (request->terminate == connection_termination)
1226
+ {
1227
+ // update an individually registered record
1228
+ registered_record_entry *reptr;
1229
+ for (reptr = request->u.reg_recs; reptr; reptr = reptr->next)
1230
+ {
1231
+ if (reptr->key == hdr->reg_index)
1232
+ {
1233
+ result = update_record(reptr->rr, rdlen, rdata, ttl, &reptr->external_advertise);
1234
+ LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s)",
1235
+ request->sd, reptr->rr->resrec.name->c, reptr->rr ? DNSTypeName(reptr->rr->resrec.rrtype) : "<NONE>");
1236
+ goto end;
1237
+ }
1238
+ }
1239
+ result = mStatus_BadReferenceErr;
1240
+ goto end;
1241
+ }
1242
+
1243
+ if (request->terminate != regservice_termination_callback)
1244
+ { LogMsg("%3d: DNSServiceUpdateRecord(not a registered service ref)", request->sd); return(mStatus_BadParamErr); }
1245
+
1246
+ // For a service registered with zero port, only SRV record is initialized. Don't allow any updates.
1247
+ if (mDNSIPPortIsZero(request->u.servicereg.port))
1248
+ { LogMsg("%3d: DNSServiceUpdateRecord: updating the record of a service registered with zero port", request->sd); return(mStatus_BadParamErr); }
1249
+
1250
+ // update the saved off TXT data for the service
1251
+ if (hdr->reg_index == TXT_RECORD_INDEX)
1252
+ {
1253
+ if (request->u.servicereg.txtdata)
1254
+ { freeL("service_info txtdata", request->u.servicereg.txtdata); request->u.servicereg.txtdata = NULL; }
1255
+ if (rdlen > 0)
1256
+ {
1257
+ request->u.servicereg.txtdata = mallocL("service_info txtdata", rdlen);
1258
+ if (!request->u.servicereg.txtdata) FatalError("ERROR: handle_update_request - malloc");
1259
+ mDNSPlatformMemCopy(request->u.servicereg.txtdata, rdata, rdlen);
1260
+ }
1261
+ request->u.servicereg.txtlen = rdlen;
1262
+ }
1263
+
1264
+ // update a record from a service record set
1265
+ for (i = request->u.servicereg.instances; i; i = i->next)
1266
+ {
1267
+ if (hdr->reg_index == TXT_RECORD_INDEX) rr = &i->srs.RR_TXT;
1268
+ else
1269
+ {
1270
+ ExtraResourceRecord *e;
1271
+ for (e = i->srs.Extras; e; e = e->next)
1272
+ if (e->ClientID == hdr->reg_index) { rr = &e->r; break; }
1273
+ }
1274
+
1275
+ if (!rr) { result = mStatus_BadReferenceErr; goto end; }
1276
+ result = update_record(rr, rdlen, rdata, ttl, &i->external_advertise);
1277
+ if (result && i->default_local) goto end;
1278
+ else result = mStatus_NoError; // suppress non-local default errors
1279
+ }
1280
+
1281
+ end:
1282
+ if (request->terminate == regservice_termination_callback)
1283
+ LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s)", request->sd,
1284
+ (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL,
1285
+ rr ? DNSTypeName(rr->resrec.rrtype) : "<NONE>");
1286
+
1287
+ return(result);
1288
+ }
1289
+
1290
+ // remove a resource record registered via DNSServiceRegisterRecord()
1291
+ mDNSlocal mStatus remove_record(request_state *request)
1292
+ {
1293
+ mStatus err = mStatus_UnknownErr;
1294
+ registered_record_entry *e, **ptr = &request->u.reg_recs;
1295
+
1296
+ while (*ptr && (*ptr)->key != request->hdr.reg_index) ptr = &(*ptr)->next;
1297
+ if (!*ptr) { LogMsg("%3d: DNSServiceRemoveRecord(%u) not found", request->sd, request->hdr.reg_index); return mStatus_BadReferenceErr; }
1298
+ e = *ptr;
1299
+ *ptr = e->next; // unlink
1300
+
1301
+ LogOperation("%3d: DNSServiceRemoveRecord(%u %s)", request->sd, e->key, RRDisplayString(&mDNSStorage, &e->rr->resrec));
1302
+ e->rr->RecordContext = NULL;
1303
+ if (e->external_advertise)
1304
+ {
1305
+ external_stop_advertising_service(&e->rr->resrec);
1306
+ e->external_advertise = mDNSfalse;
1307
+ }
1308
+ err = mDNS_Deregister(&mDNSStorage, e->rr); // Will free e->rr for us; we're responsible for freeing e
1309
+ if (err)
1310
+ {
1311
+ LogMsg("ERROR: remove_record, mDNS_Deregister: %d", err);
1312
+ freeL("registered_record_entry AuthRecord remove_record", e->rr);
1313
+ }
1314
+
1315
+ freeL("registered_record_entry remove_record", e);
1316
+ return err;
1317
+ }
1318
+
1319
+ mDNSlocal mStatus remove_extra(const request_state *const request, service_instance *const serv, mDNSu16 *const rrtype)
1320
+ {
1321
+ mStatus err = mStatus_BadReferenceErr;
1322
+ ExtraResourceRecord *ptr;
1323
+
1324
+ for (ptr = serv->srs.Extras; ptr; ptr = ptr->next)
1325
+ {
1326
+ if (ptr->ClientID == request->hdr.reg_index) // found match
1327
+ {
1328
+ *rrtype = ptr->r.resrec.rrtype;
1329
+ if (serv->external_advertise) external_stop_advertising_service(&ptr->r.resrec);
1330
+ err = mDNS_RemoveRecordFromService(&mDNSStorage, &serv->srs, ptr, FreeExtraRR, ptr);
1331
+ break;
1332
+ }
1333
+ }
1334
+ return err;
1335
+ }
1336
+
1337
+ mDNSlocal mStatus handle_removerecord_request(request_state *request)
1338
+ {
1339
+ mStatus err = mStatus_BadReferenceErr;
1340
+ get_flags(&request->msgptr, request->msgend); // flags unused
1341
+
1342
+ if (!request->msgptr) { LogMsg("%3d: DNSServiceRemoveRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
1343
+
1344
+ // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
1345
+ if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
1346
+
1347
+ if (request->terminate == connection_termination)
1348
+ err = remove_record(request); // remove individually registered record
1349
+ else if (request->terminate != regservice_termination_callback)
1350
+ { LogMsg("%3d: DNSServiceRemoveRecord(not a registered service ref)", request->sd); return(mStatus_BadParamErr); }
1351
+ else
1352
+ {
1353
+ service_instance *i;
1354
+ mDNSu16 rrtype = 0;
1355
+ LogOperation("%3d: DNSServiceRemoveRecord(%##s, %s)", request->sd,
1356
+ (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL,
1357
+ rrtype ? DNSTypeName(rrtype) : "<NONE>");
1358
+ for (i = request->u.servicereg.instances; i; i = i->next)
1359
+ {
1360
+ err = remove_extra(request, i, &rrtype);
1361
+ if (err && i->default_local) break;
1362
+ else err = mStatus_NoError; // suppress non-local default errors
1363
+ }
1364
+ }
1365
+
1366
+ return(err);
1367
+ }
1368
+
1369
+ // If there's a comma followed by another character,
1370
+ // FindFirstSubType overwrites the comma with a nul and returns the pointer to the next character.
1371
+ // Otherwise, it returns a pointer to the final nul at the end of the string
1372
+ mDNSlocal char *FindFirstSubType(char *p)
1373
+ {
1374
+ while (*p)
1375
+ {
1376
+ if (p[0] == '\\' && p[1]) p += 2;
1377
+ else if (p[0] == ',' && p[1]) { *p++ = 0; return(p); }
1378
+ else p++;
1379
+ }
1380
+ return(p);
1381
+ }
1382
+
1383
+ // If there's a comma followed by another character,
1384
+ // FindNextSubType overwrites the comma with a nul and returns the pointer to the next character.
1385
+ // If it finds an illegal unescaped dot in the subtype name, it returns mDNSNULL
1386
+ // Otherwise, it returns a pointer to the final nul at the end of the string
1387
+ mDNSlocal char *FindNextSubType(char *p)
1388
+ {
1389
+ while (*p)
1390
+ {
1391
+ if (p[0] == '\\' && p[1]) // If escape character
1392
+ p += 2; // ignore following character
1393
+ else if (p[0] == ',') // If we found a comma
1394
+ {
1395
+ if (p[1]) *p++ = 0;
1396
+ return(p);
1397
+ }
1398
+ else if (p[0] == '.')
1399
+ return(mDNSNULL);
1400
+ else p++;
1401
+ }
1402
+ return(p);
1403
+ }
1404
+
1405
+ // Returns -1 if illegal subtype found
1406
+ mDNSexport mDNSs32 ChopSubTypes(char *regtype)
1407
+ {
1408
+ mDNSs32 NumSubTypes = 0;
1409
+ char *stp = FindFirstSubType(regtype);
1410
+ while (stp && *stp) // If we found a comma...
1411
+ {
1412
+ if (*stp == ',') return(-1);
1413
+ NumSubTypes++;
1414
+ stp = FindNextSubType(stp);
1415
+ }
1416
+ if (!stp) return(-1);
1417
+ return(NumSubTypes);
1418
+ }
1419
+
1420
+ mDNSexport AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p)
1421
+ {
1422
+ AuthRecord *st = mDNSNULL;
1423
+ if (NumSubTypes)
1424
+ {
1425
+ mDNSs32 i;
1426
+ st = mallocL("ServiceSubTypes", NumSubTypes * sizeof(AuthRecord));
1427
+ if (!st) return(mDNSNULL);
1428
+ for (i = 0; i < NumSubTypes; i++)
1429
+ {
1430
+ mDNS_SetupResourceRecord(&st[i], mDNSNULL, mDNSInterface_Any, kDNSQType_ANY, kStandardTTL, 0, AuthRecordAny, mDNSNULL, mDNSNULL);
1431
+ while (*p) p++;
1432
+ p++;
1433
+ if (!MakeDomainNameFromDNSNameString(&st[i].namestorage, p))
1434
+ { freeL("ServiceSubTypes", st); return(mDNSNULL); }
1435
+ }
1436
+ }
1437
+ return(st);
1438
+ }
1439
+
1440
+ mDNSlocal mStatus register_service_instance(request_state *request, const domainname *domain)
1441
+ {
1442
+ service_instance **ptr, *instance;
1443
+ const int extra_size = (request->u.servicereg.txtlen > sizeof(RDataBody)) ? (request->u.servicereg.txtlen - sizeof(RDataBody)) : 0;
1444
+ const mDNSBool DomainIsLocal = SameDomainName(domain, &localdomain);
1445
+ mStatus result;
1446
+ mDNSInterfaceID interfaceID = request->u.servicereg.InterfaceID;
1447
+ mDNSu32 regFlags = 0;
1448
+
1449
+ if (interfaceID == mDNSInterface_P2P)
1450
+ {
1451
+ interfaceID = mDNSInterface_Any;
1452
+ regFlags |= regFlagIncludeP2P;
1453
+ }
1454
+ else if (request->flags & kDNSServiceFlagsIncludeP2P)
1455
+ regFlags |= regFlagIncludeP2P;
1456
+
1457
+ // client guarantees that record names are unique
1458
+ if (request->flags & kDNSServiceFlagsForce)
1459
+ regFlags |= regFlagKnownUnique;
1460
+
1461
+ // If the client specified an interface, but no domain, then we honor the specified interface for the "local" (mDNS)
1462
+ // registration but for the wide-area registrations we don't (currently) have any concept of a wide-area unicast
1463
+ // registrations scoped to a specific interface, so for the automatic domains we add we must *not* specify an interface.
1464
+ // (Specifying an interface with an apparently wide-area domain (i.e. something other than "local")
1465
+ // currently forces the registration to use mDNS multicast despite the apparently wide-area domain.)
1466
+ if (request->u.servicereg.default_domain && !DomainIsLocal) interfaceID = mDNSInterface_Any;
1467
+
1468
+ for (ptr = &request->u.servicereg.instances; *ptr; ptr = &(*ptr)->next)
1469
+ {
1470
+ if (SameDomainName(&(*ptr)->domain, domain))
1471
+ {
1472
+ LogMsg("register_service_instance: domain %##s already registered for %#s.%##s",
1473
+ domain->c, &request->u.servicereg.name, &request->u.servicereg.type);
1474
+ return mStatus_AlreadyRegistered;
1475
+ }
1476
+ }
1477
+
1478
+ if (mDNSStorage.KnownBugs & mDNS_KnownBug_LimitedIPv6)
1479
+ {
1480
+ // Special-case hack: On Mac OS X 10.6.x and earlier we don't advertise SMB service in AutoTunnel domains,
1481
+ // because AutoTunnel services have to support IPv6, and in Mac OS X 10.6.x the SMB server does not.
1482
+ // <rdar://problem/5482322> BTMM: Don't advertise SMB with BTMM because it doesn't support IPv6
1483
+ if (SameDomainName(&request->u.servicereg.type, (const domainname *) "\x4" "_smb" "\x4" "_tcp"))
1484
+ {
1485
+ DomainAuthInfo *AuthInfo = GetAuthInfoForName(&mDNSStorage, domain);
1486
+ if (AuthInfo && AuthInfo->AutoTunnel) return(kDNSServiceErr_Unsupported);
1487
+ }
1488
+ }
1489
+
1490
+ instance = mallocL("service_instance", sizeof(*instance) + extra_size);
1491
+ if (!instance) { my_perror("ERROR: malloc"); return mStatus_NoMemoryErr; }
1492
+
1493
+ instance->next = mDNSNULL;
1494
+ instance->request = request;
1495
+ instance->subtypes = AllocateSubTypes(request->u.servicereg.num_subtypes, request->u.servicereg.type_as_string);
1496
+ instance->renameonmemfree = 0;
1497
+ instance->clientnotified = mDNSfalse;
1498
+ instance->default_local = (request->u.servicereg.default_domain && DomainIsLocal);
1499
+ instance->external_advertise = mDNSfalse;
1500
+ AssignDomainName(&instance->domain, domain);
1501
+
1502
+ if (request->u.servicereg.num_subtypes && !instance->subtypes)
1503
+ { unlink_and_free_service_instance(instance); instance = NULL; FatalError("ERROR: malloc"); }
1504
+
1505
+ result = mDNS_RegisterService(&mDNSStorage, &instance->srs,
1506
+ &request->u.servicereg.name, &request->u.servicereg.type, domain,
1507
+ request->u.servicereg.host.c[0] ? &request->u.servicereg.host : NULL,
1508
+ request->u.servicereg.port,
1509
+ request->u.servicereg.txtdata, request->u.servicereg.txtlen,
1510
+ instance->subtypes, request->u.servicereg.num_subtypes,
1511
+ interfaceID, regservice_callback, instance, regFlags);
1512
+
1513
+ if (!result)
1514
+ {
1515
+ *ptr = instance; // Append this to the end of our request->u.servicereg.instances list
1516
+ LogOperation("%3d: DNSServiceRegister(%##s, %u) ADDED",
1517
+ instance->request->sd, instance->srs.RR_SRV.resrec.name->c, mDNSVal16(request->u.servicereg.port));
1518
+ }
1519
+ else
1520
+ {
1521
+ LogMsg("register_service_instance %#s.%##s%##s error %d",
1522
+ &request->u.servicereg.name, &request->u.servicereg.type, domain->c, result);
1523
+ unlink_and_free_service_instance(instance);
1524
+ }
1525
+
1526
+ return result;
1527
+ }
1528
+
1529
+ mDNSlocal void udsserver_default_reg_domain_changed(const DNameListElem *const d, const mDNSBool add)
1530
+ {
1531
+ request_state *request;
1532
+
1533
+ #if APPLE_OSX_mDNSResponder
1534
+ machserver_automatic_registration_domain_changed(&d->name, add);
1535
+ #endif // APPLE_OSX_mDNSResponder
1536
+
1537
+ LogMsg("%s registration domain %##s", add ? "Adding" : "Removing", d->name.c);
1538
+ for (request = all_requests; request; request = request->next)
1539
+ {
1540
+ if (request->terminate != regservice_termination_callback) continue;
1541
+ if (!request->u.servicereg.default_domain) continue;
1542
+ if (!d->uid || SystemUID(request->uid) || request->uid == d->uid)
1543
+ {
1544
+ service_instance **ptr = &request->u.servicereg.instances;
1545
+ while (*ptr && !SameDomainName(&(*ptr)->domain, &d->name)) ptr = &(*ptr)->next;
1546
+ if (add)
1547
+ {
1548
+ // If we don't already have this domain in our list for this registration, add it now
1549
+ if (!*ptr) register_service_instance(request, &d->name);
1550
+ else debugf("udsserver_default_reg_domain_changed %##s already in list, not re-adding", &d->name);
1551
+ }
1552
+ else
1553
+ {
1554
+ // Normally we should not fail to find the specified instance
1555
+ // One case where this can happen is if a uDNS update fails for some reason,
1556
+ // and regservice_callback then calls unlink_and_free_service_instance and disposes of that instance.
1557
+ if (!*ptr)
1558
+ LogMsg("udsserver_default_reg_domain_changed domain %##s not found for service %#s type %s",
1559
+ &d->name, request->u.servicereg.name.c, request->u.servicereg.type_as_string);
1560
+ else
1561
+ {
1562
+ DNameListElem *p;
1563
+ for (p = AutoRegistrationDomains; p; p=p->next)
1564
+ if (!p->uid || SystemUID(request->uid) || request->uid == p->uid)
1565
+ if (SameDomainName(&d->name, &p->name)) break;
1566
+ if (p) debugf("udsserver_default_reg_domain_changed %##s still in list, not removing", &d->name);
1567
+ else
1568
+ {
1569
+ mStatus err;
1570
+ service_instance *si = *ptr;
1571
+ *ptr = si->next;
1572
+ if (si->clientnotified) SendServiceRemovalNotification(&si->srs); // Do this *before* clearing si->request backpointer
1573
+ // Now that we've cut this service_instance from the list, we MUST clear the si->request backpointer.
1574
+ // Otherwise what can happen is this: While our mDNS_DeregisterService is in the
1575
+ // process of completing asynchronously, the client cancels the entire operation, so
1576
+ // regservice_termination_callback then runs through the whole list deregistering each
1577
+ // instance, clearing the backpointers, and then disposing the parent request_state object.
1578
+ // However, because this service_instance isn't in the list any more, regservice_termination_callback
1579
+ // has no way to find it and clear its backpointer, and then when our mDNS_DeregisterService finally
1580
+ // completes later with a mStatus_MemFree message, it calls unlink_and_free_service_instance() with
1581
+ // a service_instance with a stale si->request backpointer pointing to memory that's already been freed.
1582
+ si->request = NULL;
1583
+ err = mDNS_DeregisterService(&mDNSStorage, &si->srs);
1584
+ if (err) { LogMsg("udsserver_default_reg_domain_changed err %d", err); unlink_and_free_service_instance(si); }
1585
+ }
1586
+ }
1587
+ }
1588
+ }
1589
+ }
1590
+ }
1591
+
1592
+ mDNSlocal mStatus handle_regservice_request(request_state *request)
1593
+ {
1594
+ char name[256]; // Lots of spare space for extra-long names that we'll auto-truncate down to 63 bytes
1595
+ char domain[MAX_ESCAPED_DOMAIN_NAME], host[MAX_ESCAPED_DOMAIN_NAME];
1596
+ char type_as_string[MAX_ESCAPED_DOMAIN_NAME];
1597
+ domainname d, srv;
1598
+ mStatus err;
1599
+ const char *msgTXTData;
1600
+
1601
+ DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
1602
+ mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
1603
+ mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
1604
+ if (interfaceIndex && !InterfaceID)
1605
+ { LogMsg("ERROR: handle_regservice_request - Couldn't find interfaceIndex %d", interfaceIndex); return(mStatus_BadParamErr); }
1606
+
1607
+ if (get_string(&request->msgptr, request->msgend, name, sizeof(name)) < 0 ||
1608
+ get_string(&request->msgptr, request->msgend, type_as_string, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
1609
+ get_string(&request->msgptr, request->msgend, domain, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
1610
+ get_string(&request->msgptr, request->msgend, host, MAX_ESCAPED_DOMAIN_NAME) < 0)
1611
+ { LogMsg("ERROR: handle_regservice_request - Couldn't read name/regtype/domain"); return(mStatus_BadParamErr); }
1612
+
1613
+ request->flags = flags;
1614
+ request->u.servicereg.InterfaceID = InterfaceID;
1615
+ request->u.servicereg.instances = NULL;
1616
+ request->u.servicereg.txtlen = 0;
1617
+ request->u.servicereg.txtdata = NULL;
1618
+ mDNSPlatformStrLCopy(request->u.servicereg.type_as_string, type_as_string, sizeof(request->u.servicereg.type_as_string));
1619
+
1620
+ if (request->msgptr + 2 > request->msgend) request->msgptr = NULL;
1621
+ else
1622
+ {
1623
+ request->u.servicereg.port.b[0] = *request->msgptr++;
1624
+ request->u.servicereg.port.b[1] = *request->msgptr++;
1625
+ }
1626
+
1627
+ request->u.servicereg.txtlen = get_uint16(&request->msgptr, request->msgend);
1628
+ msgTXTData = get_rdata(&request->msgptr, request->msgend, request->u.servicereg.txtlen);
1629
+ if (!request->msgptr)
1630
+ {
1631
+ LogMsg("%3d: DNSServiceRegister(unreadable parameters)", request->sd);
1632
+ return(mStatus_BadParamErr);
1633
+ }
1634
+
1635
+ if (request->u.servicereg.txtlen)
1636
+ {
1637
+ request->u.servicereg.txtdata = mallocL("service_info txtdata", request->u.servicereg.txtlen);
1638
+ if (!request->u.servicereg.txtdata) FatalError("ERROR: handle_regservice_request - malloc");
1639
+ mDNSPlatformMemCopy(request->u.servicereg.txtdata, msgTXTData, request->u.servicereg.txtlen);
1640
+ }
1641
+
1642
+ // Check for sub-types after the service type
1643
+ request->u.servicereg.num_subtypes = ChopSubTypes(request->u.servicereg.type_as_string); // Note: Modifies regtype string to remove trailing subtypes
1644
+ if (request->u.servicereg.num_subtypes < 0)
1645
+ { LogMsg("ERROR: handle_regservice_request - ChopSubTypes failed %s", request->u.servicereg.type_as_string); return(mStatus_BadParamErr); }
1646
+
1647
+ // Don't try to construct "domainname t" until *after* ChopSubTypes has worked its magic
1648
+ if (!*request->u.servicereg.type_as_string || !MakeDomainNameFromDNSNameString(&request->u.servicereg.type, request->u.servicereg.type_as_string))
1649
+ { LogMsg("ERROR: handle_regservice_request - type_as_string bad %s", request->u.servicereg.type_as_string); return(mStatus_BadParamErr); }
1650
+
1651
+ if (!name[0])
1652
+ {
1653
+ request->u.servicereg.name = mDNSStorage.nicelabel;
1654
+ request->u.servicereg.autoname = mDNStrue;
1655
+ }
1656
+ else
1657
+ {
1658
+ // If the client is allowing AutoRename, then truncate name to legal length before converting it to a DomainLabel
1659
+ if ((flags & kDNSServiceFlagsNoAutoRename) == 0)
1660
+ {
1661
+ int newlen = TruncateUTF8ToLength((mDNSu8*)name, mDNSPlatformStrLen(name), MAX_DOMAIN_LABEL);
1662
+ name[newlen] = 0;
1663
+ }
1664
+ if (!MakeDomainLabelFromLiteralString(&request->u.servicereg.name, name))
1665
+ { LogMsg("ERROR: handle_regservice_request - name bad %s", name); return(mStatus_BadParamErr); }
1666
+ request->u.servicereg.autoname = mDNSfalse;
1667
+ }
1668
+
1669
+ if (*domain)
1670
+ {
1671
+ request->u.servicereg.default_domain = mDNSfalse;
1672
+ if (!MakeDomainNameFromDNSNameString(&d, domain))
1673
+ { LogMsg("ERROR: handle_regservice_request - domain bad %s", domain); return(mStatus_BadParamErr); }
1674
+ }
1675
+ else
1676
+ {
1677
+ request->u.servicereg.default_domain = mDNStrue;
1678
+ MakeDomainNameFromDNSNameString(&d, "local.");
1679
+ }
1680
+
1681
+ if (!ConstructServiceName(&srv, &request->u.servicereg.name, &request->u.servicereg.type, &d))
1682
+ {
1683
+ LogMsg("ERROR: handle_regservice_request - Couldn't ConstructServiceName from, “%#s” “%##s” “%##s”",
1684
+ request->u.servicereg.name.c, request->u.servicereg.type.c, d.c); return(mStatus_BadParamErr);
1685
+ }
1686
+
1687
+ if (!MakeDomainNameFromDNSNameString(&request->u.servicereg.host, host))
1688
+ { LogMsg("ERROR: handle_regservice_request - host bad %s", host); return(mStatus_BadParamErr); }
1689
+ request->u.servicereg.autorename = (flags & kDNSServiceFlagsNoAutoRename ) == 0;
1690
+ request->u.servicereg.allowremotequery = (flags & kDNSServiceFlagsAllowRemoteQuery) != 0;
1691
+
1692
+ // Some clients use mDNS for lightweight copy protection, registering a pseudo-service with
1693
+ // a port number of zero. When two instances of the protected client are allowed to run on one
1694
+ // machine, we don't want to see misleading "Bogus client" messages in syslog and the console.
1695
+ if (!mDNSIPPortIsZero(request->u.servicereg.port))
1696
+ {
1697
+ int count = CountExistingRegistrations(&srv, request->u.servicereg.port);
1698
+ if (count)
1699
+ LogMsg("Client application registered %d identical instances of service %##s port %u.",
1700
+ count+1, srv.c, mDNSVal16(request->u.servicereg.port));
1701
+ }
1702
+
1703
+ LogOperation("%3d: DNSServiceRegister(%X, %d, \"%s\", \"%s\", \"%s\", \"%s\", %u) START",
1704
+ request->sd, flags, interfaceIndex, name, request->u.servicereg.type_as_string, domain, host, mDNSVal16(request->u.servicereg.port));
1705
+
1706
+ // We need to unconditionally set request->terminate, because even if we didn't successfully
1707
+ // start any registrations right now, subsequent configuration changes may cause successful
1708
+ // registrations to be added, and we'll need to cancel them before freeing this memory.
1709
+ // We also need to set request->terminate first, before adding additional service instances,
1710
+ // because the uds_validatelists uses the request->terminate function pointer to determine
1711
+ // what kind of request this is, and therefore what kind of list validation is required.
1712
+ request->terminate = regservice_termination_callback;
1713
+
1714
+ err = register_service_instance(request, &d);
1715
+
1716
+ #if 0
1717
+ err = AuthorizedDomain(request, &d, AutoRegistrationDomains) ? register_service_instance(request, &d) : mStatus_NoError;
1718
+ #endif
1719
+ if (!err)
1720
+ {
1721
+ if (request->u.servicereg.autoname) UpdateDeviceInfoRecord(&mDNSStorage);
1722
+
1723
+ if (!*domain)
1724
+ {
1725
+ DNameListElem *ptr;
1726
+ // Note that we don't report errors for non-local, non-explicit domains
1727
+ for (ptr = AutoRegistrationDomains; ptr; ptr = ptr->next)
1728
+ if (!ptr->uid || SystemUID(request->uid) || request->uid == ptr->uid)
1729
+ register_service_instance(request, &ptr->name);
1730
+ }
1731
+ }
1732
+
1733
+ return(err);
1734
+ }
1735
+
1736
+ // ***************************************************************************
1737
+ #if COMPILER_LIKES_PRAGMA_MARK
1738
+ #pragma mark -
1739
+ #pragma mark - DNSServiceBrowse
1740
+ #endif
1741
+
1742
+ mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
1743
+ {
1744
+ const DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : 0;
1745
+ request_state *req = question->QuestionContext;
1746
+ reply_state *rep;
1747
+ (void)m; // Unused
1748
+
1749
+ if (answer->rrtype != kDNSType_PTR)
1750
+ { LogMsg("%3d: FoundInstance: Should not be called with rrtype %d (not a PTR record)", req->sd, answer->rrtype); return; }
1751
+
1752
+ if (GenerateNTDResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError) != mStatus_NoError)
1753
+ {
1754
+ if (SameDomainName(&req->u.browser.regtype, (const domainname*)"\x09_services\x07_dns-sd\x04_udp"))
1755
+ {
1756
+ // Special support to enable the DNSServiceBrowse call made by Bonjour Browser
1757
+ // Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
1758
+ GenerateBonjourBrowserResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError);
1759
+ goto bonjourbrowserhack;
1760
+ }
1761
+
1762
+ LogMsg("%3d: FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
1763
+ req->sd, answer->name->c, answer->rdata->u.name.c);
1764
+ return;
1765
+ }
1766
+
1767
+ bonjourbrowserhack:
1768
+
1769
+ LogOperation("%3d: DNSServiceBrowse(%##s, %s) RESULT %s %d: %s",
1770
+ req->sd, question->qname.c, DNSTypeName(question->qtype), AddRecord ? "Add" : "Rmv",
1771
+ mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse), RRDisplayString(m, answer));
1772
+
1773
+ append_reply(req, rep);
1774
+ }
1775
+
1776
+ mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d)
1777
+ {
1778
+ browser_t *b, *p;
1779
+ mStatus err;
1780
+
1781
+ for (p = info->u.browser.browsers; p; p = p->next)
1782
+ {
1783
+ if (SameDomainName(&p->domain, d))
1784
+ { debugf("add_domain_to_browser %##s already in list", d->c); return mStatus_AlreadyRegistered; }
1785
+ }
1786
+
1787
+ b = mallocL("browser_t", sizeof(*b));
1788
+ if (!b) return mStatus_NoMemoryErr;
1789
+ AssignDomainName(&b->domain, d);
1790
+ err = mDNS_StartBrowse(&mDNSStorage, &b->q,
1791
+ &info->u.browser.regtype, d, info->u.browser.interface_id, info->u.browser.ForceMCast, FoundInstance, info);
1792
+ if (err)
1793
+ {
1794
+ LogMsg("mDNS_StartBrowse returned %d for type %##s domain %##s", err, info->u.browser.regtype.c, d->c);
1795
+ freeL("browser_t/add_domain_to_browser", b);
1796
+ }
1797
+ else
1798
+ {
1799
+ b->next = info->u.browser.browsers;
1800
+ info->u.browser.browsers = b;
1801
+ LogOperation("%3d: DNSServiceBrowse(%##s) START", info->sd, b->q.qname.c);
1802
+ if (info->u.browser.interface_id == mDNSInterface_P2P || (!info->u.browser.interface_id && SameDomainName(&b->domain, &localdomain) && (info->flags & kDNSServiceFlagsIncludeP2P)))
1803
+ {
1804
+ domainname tmp;
1805
+ ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &b->domain);
1806
+ LogInfo("add_domain_to_browser: calling external_start_browsing_for_service()");
1807
+ external_start_browsing_for_service(&mDNSStorage, &tmp, kDNSType_PTR);
1808
+ }
1809
+ }
1810
+ return err;
1811
+ }
1812
+
1813
+ mDNSlocal void browse_termination_callback(request_state *info)
1814
+ {
1815
+ while (info->u.browser.browsers)
1816
+ {
1817
+ browser_t *ptr = info->u.browser.browsers;
1818
+
1819
+ if (info->u.browser.interface_id == mDNSInterface_P2P || (!info->u.browser.interface_id && SameDomainName(&ptr->domain, &localdomain) && (info->flags & kDNSServiceFlagsIncludeP2P)))
1820
+ {
1821
+ domainname tmp;
1822
+ ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &ptr->domain);
1823
+ LogInfo("browse_termination_callback: calling external_stop_browsing_for_service()");
1824
+ external_stop_browsing_for_service(&mDNSStorage, &tmp, kDNSType_PTR);
1825
+ }
1826
+
1827
+ info->u.browser.browsers = ptr->next;
1828
+ LogOperation("%3d: DNSServiceBrowse(%##s) STOP", info->sd, ptr->q.qname.c);
1829
+ mDNS_StopBrowse(&mDNSStorage, &ptr->q); // no need to error-check result
1830
+ freeL("browser_t/browse_termination_callback", ptr);
1831
+ }
1832
+ }
1833
+
1834
+ mDNSlocal void udsserver_automatic_browse_domain_changed(const DNameListElem *const d, const mDNSBool add)
1835
+ {
1836
+ request_state *request;
1837
+ debugf("udsserver_automatic_browse_domain_changed: %s default browse domain %##s", add ? "Adding" : "Removing", d->name.c);
1838
+
1839
+ #if APPLE_OSX_mDNSResponder
1840
+ machserver_automatic_browse_domain_changed(&d->name, add);
1841
+ #endif // APPLE_OSX_mDNSResponder
1842
+
1843
+ for (request = all_requests; request; request = request->next)
1844
+ {
1845
+ if (request->terminate != browse_termination_callback) continue; // Not a browse operation
1846
+ if (!request->u.browser.default_domain) continue; // Not an auto-browse operation
1847
+ if (!d->uid || SystemUID(request->uid) || request->uid == d->uid)
1848
+ {
1849
+ browser_t **ptr = &request->u.browser.browsers;
1850
+ while (*ptr && !SameDomainName(&(*ptr)->domain, &d->name)) ptr = &(*ptr)->next;
1851
+ if (add)
1852
+ {
1853
+ // If we don't already have this domain in our list for this browse operation, add it now
1854
+ if (!*ptr) add_domain_to_browser(request, &d->name);
1855
+ else debugf("udsserver_automatic_browse_domain_changed %##s already in list, not re-adding", &d->name);
1856
+ }
1857
+ else
1858
+ {
1859
+ if (!*ptr) LogMsg("udsserver_automatic_browse_domain_changed ERROR %##s not found", &d->name);
1860
+ else
1861
+ {
1862
+ DNameListElem *p;
1863
+ for (p = AutoBrowseDomains; p; p=p->next)
1864
+ if (!p->uid || SystemUID(request->uid) || request->uid == p->uid)
1865
+ if (SameDomainName(&d->name, &p->name)) break;
1866
+ if (p) debugf("udsserver_automatic_browse_domain_changed %##s still in list, not removing", &d->name);
1867
+ else
1868
+ {
1869
+ browser_t *rem = *ptr;
1870
+ *ptr = (*ptr)->next;
1871
+ mDNS_StopQueryWithRemoves(&mDNSStorage, &rem->q);
1872
+ freeL("browser_t/udsserver_automatic_browse_domain_changed", rem);
1873
+ }
1874
+ }
1875
+ }
1876
+ }
1877
+ }
1878
+ }
1879
+
1880
+ mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
1881
+ {
1882
+ (void)m; // unused
1883
+ if (result == mStatus_MemFree)
1884
+ {
1885
+ // On shutdown, mDNS_Close automatically deregisters all records
1886
+ // Since in this case no one has called DeregisterLocalOnlyDomainEnumPTR to cut the record
1887
+ // from the LocalDomainEnumRecords list, we do this here before we free the memory.
1888
+ // (This should actually no longer be necessary, now that we do the proper cleanup in
1889
+ // udsserver_exit. To confirm this, we'll log an error message if we do find a record that
1890
+ // hasn't been cut from the list yet. If these messages don't appear, we can delete this code.)
1891
+ ARListElem **ptr = &LocalDomainEnumRecords;
1892
+ while (*ptr && &(*ptr)->ar != rr) ptr = &(*ptr)->next;
1893
+ if (*ptr) { *ptr = (*ptr)->next; LogMsg("FreeARElemCallback: Have to cut %s", ARDisplayString(m, rr)); }
1894
+ mDNSPlatformMemFree(rr->RecordContext);
1895
+ }
1896
+ }
1897
+
1898
+ // RegisterLocalOnlyDomainEnumPTR and DeregisterLocalOnlyDomainEnumPTR largely duplicate code in
1899
+ // "FoundDomain" in uDNS.c for creating and destroying these special mDNSInterface_LocalOnly records.
1900
+ // We may want to turn the common code into a subroutine.
1901
+
1902
+ mDNSlocal void RegisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int type)
1903
+ {
1904
+ // allocate/register legacy and non-legacy _browse PTR record
1905
+ mStatus err;
1906
+ ARListElem *ptr = mDNSPlatformMemAllocate(sizeof(*ptr));
1907
+
1908
+ debugf("Incrementing %s refcount for %##s",
1909
+ (type == mDNS_DomainTypeBrowse ) ? "browse domain " :
1910
+ (type == mDNS_DomainTypeRegistration ) ? "registration dom" :
1911
+ (type == mDNS_DomainTypeBrowseAutomatic) ? "automatic browse" : "?", d->c);
1912
+
1913
+ mDNS_SetupResourceRecord(&ptr->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, AuthRecordLocalOnly, FreeARElemCallback, ptr);
1914
+ MakeDomainNameFromDNSNameString(&ptr->ar.namestorage, mDNS_DomainTypeNames[type]);
1915
+ AppendDNSNameString (&ptr->ar.namestorage, "local");
1916
+ AssignDomainName(&ptr->ar.resrec.rdata->u.name, d);
1917
+ err = mDNS_Register(m, &ptr->ar);
1918
+ if (err)
1919
+ {
1920
+ LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err);
1921
+ mDNSPlatformMemFree(ptr);
1922
+ }
1923
+ else
1924
+ {
1925
+ ptr->next = LocalDomainEnumRecords;
1926
+ LocalDomainEnumRecords = ptr;
1927
+ }
1928
+ }
1929
+
1930
+ mDNSlocal void DeregisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int type)
1931
+ {
1932
+ ARListElem **ptr = &LocalDomainEnumRecords;
1933
+ domainname lhs; // left-hand side of PTR, for comparison
1934
+
1935
+ debugf("Decrementing %s refcount for %##s",
1936
+ (type == mDNS_DomainTypeBrowse ) ? "browse domain " :
1937
+ (type == mDNS_DomainTypeRegistration ) ? "registration dom" :
1938
+ (type == mDNS_DomainTypeBrowseAutomatic) ? "automatic browse" : "?", d->c);
1939
+
1940
+ MakeDomainNameFromDNSNameString(&lhs, mDNS_DomainTypeNames[type]);
1941
+ AppendDNSNameString (&lhs, "local");
1942
+
1943
+ while (*ptr)
1944
+ {
1945
+ if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, d) && SameDomainName((*ptr)->ar.resrec.name, &lhs))
1946
+ {
1947
+ ARListElem *rem = *ptr;
1948
+ *ptr = (*ptr)->next;
1949
+ mDNS_Deregister(m, &rem->ar);
1950
+ return;
1951
+ }
1952
+ else ptr = &(*ptr)->next;
1953
+ }
1954
+ }
1955
+
1956
+ mDNSlocal void AddAutoBrowseDomain(const mDNSu32 uid, const domainname *const name)
1957
+ {
1958
+ DNameListElem *new = mDNSPlatformMemAllocate(sizeof(DNameListElem));
1959
+ if (!new) { LogMsg("ERROR: malloc"); return; }
1960
+ AssignDomainName(&new->name, name);
1961
+ new->uid = uid;
1962
+ new->next = AutoBrowseDomains;
1963
+ AutoBrowseDomains = new;
1964
+ udsserver_automatic_browse_domain_changed(new, mDNStrue);
1965
+ }
1966
+
1967
+ mDNSlocal void RmvAutoBrowseDomain(const mDNSu32 uid, const domainname *const name)
1968
+ {
1969
+ DNameListElem **p = &AutoBrowseDomains;
1970
+ while (*p && (!SameDomainName(&(*p)->name, name) || (*p)->uid != uid)) p = &(*p)->next;
1971
+ if (!*p) LogMsg("RmvAutoBrowseDomain: Got remove event for domain %##s not in list", name->c);
1972
+ else
1973
+ {
1974
+ DNameListElem *ptr = *p;
1975
+ *p = ptr->next;
1976
+ udsserver_automatic_browse_domain_changed(ptr, mDNSfalse);
1977
+ mDNSPlatformMemFree(ptr);
1978
+ }
1979
+ }
1980
+
1981
+ mDNSlocal void SetPrefsBrowseDomains(mDNS *m, DNameListElem *browseDomains, mDNSBool add)
1982
+ {
1983
+ DNameListElem *d;
1984
+ for (d = browseDomains; d; d = d->next)
1985
+ {
1986
+ if (add)
1987
+ {
1988
+ RegisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowse);
1989
+ AddAutoBrowseDomain(d->uid, &d->name);
1990
+ }
1991
+ else
1992
+ {
1993
+ DeregisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowse);
1994
+ RmvAutoBrowseDomain(d->uid, &d->name);
1995
+ }
1996
+ }
1997
+ }
1998
+
1999
+ mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m)
2000
+ {
2001
+ int num_autoname = 0;
2002
+ request_state *req;
2003
+ for (req = all_requests; req; req = req->next)
2004
+ if (req->terminate == regservice_termination_callback && req->u.servicereg.autoname)
2005
+ num_autoname++;
2006
+
2007
+ // If DeviceInfo record is currently registered, see if we need to deregister it
2008
+ if (m->DeviceInfo.resrec.RecordType != kDNSRecordTypeUnregistered)
2009
+ if (num_autoname == 0 || !SameDomainLabelCS(m->DeviceInfo.resrec.name->c, m->nicelabel.c))
2010
+ {
2011
+ LogOperation("UpdateDeviceInfoRecord Deregister %##s", m->DeviceInfo.resrec.name);
2012
+ mDNS_Deregister(m, &m->DeviceInfo);
2013
+ }
2014
+
2015
+ // If DeviceInfo record is not currently registered, see if we need to register it
2016
+ if (m->DeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered)
2017
+ if (num_autoname > 0)
2018
+ {
2019
+ mDNSu8 len = m->HIHardware.c[0] < 255 - 6 ? m->HIHardware.c[0] : 255 - 6;
2020
+ mDNS_SetupResourceRecord(&m->DeviceInfo, mDNSNULL, mDNSNULL, kDNSType_TXT, kStandardTTL, kDNSRecordTypeAdvisory, AuthRecordAny, mDNSNULL, mDNSNULL);
2021
+ ConstructServiceName(&m->DeviceInfo.namestorage, &m->nicelabel, &DeviceInfoName, &localdomain);
2022
+ mDNSPlatformMemCopy(m->DeviceInfo.resrec.rdata->u.data + 1, "model=", 6);
2023
+ mDNSPlatformMemCopy(m->DeviceInfo.resrec.rdata->u.data + 7, m->HIHardware.c + 1, len);
2024
+ m->DeviceInfo.resrec.rdata->u.data[0] = 6 + len; // "model=" plus the device string
2025
+ m->DeviceInfo.resrec.rdlength = 7 + len; // One extra for the length byte at the start of the string
2026
+ LogOperation("UpdateDeviceInfoRecord Register %##s", m->DeviceInfo.resrec.name);
2027
+ mDNS_Register(m, &m->DeviceInfo);
2028
+ }
2029
+ }
2030
+
2031
+ mDNSexport void udsserver_handle_configchange(mDNS *const m)
2032
+ {
2033
+ request_state *req;
2034
+ service_instance *ptr;
2035
+ DNameListElem *RegDomains = NULL;
2036
+ DNameListElem *BrowseDomains = NULL;
2037
+ DNameListElem *p;
2038
+
2039
+ UpdateDeviceInfoRecord(m);
2040
+
2041
+ // For autoname services, see if the default service name has changed, necessitating an automatic update
2042
+ for (req = all_requests; req; req = req->next)
2043
+ if (req->terminate == regservice_termination_callback)
2044
+ if (req->u.servicereg.autoname && !SameDomainLabelCS(req->u.servicereg.name.c, m->nicelabel.c))
2045
+ {
2046
+ req->u.servicereg.name = m->nicelabel;
2047
+ for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
2048
+ {
2049
+ ptr->renameonmemfree = 1;
2050
+ if (ptr->clientnotified) SendServiceRemovalNotification(&ptr->srs);
2051
+ LogInfo("udsserver_handle_configchange: Calling deregister for Service %##s", ptr->srs.RR_PTR.resrec.name->c);
2052
+ if (mDNS_DeregisterService_drt(m, &ptr->srs, mDNS_Dereg_rapid))
2053
+ regservice_callback(m, &ptr->srs, mStatus_MemFree); // If service deregistered already, we can re-register immediately
2054
+ }
2055
+ }
2056
+
2057
+ // Let the platform layer get the current DNS information
2058
+ mDNS_Lock(m);
2059
+ mDNSPlatformSetDNSConfig(m, mDNSfalse, mDNSfalse, mDNSNULL, &RegDomains, &BrowseDomains);
2060
+ mDNS_Unlock(m);
2061
+
2062
+ // Any automatic registration domains are also implicitly automatic browsing domains
2063
+ if (RegDomains) SetPrefsBrowseDomains(m, RegDomains, mDNStrue); // Add the new list first
2064
+ if (AutoRegistrationDomains) SetPrefsBrowseDomains(m, AutoRegistrationDomains, mDNSfalse); // Then clear the old list
2065
+
2066
+ // Add any new domains not already in our AutoRegistrationDomains list
2067
+ for (p=RegDomains; p; p=p->next)
2068
+ {
2069
+ DNameListElem **pp = &AutoRegistrationDomains;
2070
+ while (*pp && ((*pp)->uid != p->uid || !SameDomainName(&(*pp)->name, &p->name))) pp = &(*pp)->next;
2071
+ if (!*pp) // If not found in our existing list, this is a new default registration domain
2072
+ {
2073
+ RegisterLocalOnlyDomainEnumPTR(m, &p->name, mDNS_DomainTypeRegistration);
2074
+ udsserver_default_reg_domain_changed(p, mDNStrue);
2075
+ }
2076
+ else // else found same domainname in both old and new lists, so no change, just delete old copy
2077
+ {
2078
+ DNameListElem *del = *pp;
2079
+ *pp = (*pp)->next;
2080
+ mDNSPlatformMemFree(del);
2081
+ }
2082
+ }
2083
+
2084
+ // Delete any domains in our old AutoRegistrationDomains list that are now gone
2085
+ while (AutoRegistrationDomains)
2086
+ {
2087
+ DNameListElem *del = AutoRegistrationDomains;
2088
+ AutoRegistrationDomains = AutoRegistrationDomains->next; // Cut record from list FIRST,
2089
+ DeregisterLocalOnlyDomainEnumPTR(m, &del->name, mDNS_DomainTypeRegistration);
2090
+ udsserver_default_reg_domain_changed(del, mDNSfalse); // before calling udsserver_default_reg_domain_changed()
2091
+ mDNSPlatformMemFree(del);
2092
+ }
2093
+
2094
+ // Now we have our new updated automatic registration domain list
2095
+ AutoRegistrationDomains = RegDomains;
2096
+
2097
+ // Add new browse domains to internal list
2098
+ if (BrowseDomains) SetPrefsBrowseDomains(m, BrowseDomains, mDNStrue);
2099
+
2100
+ // Remove old browse domains from internal list
2101
+ if (SCPrefBrowseDomains)
2102
+ {
2103
+ SetPrefsBrowseDomains(m, SCPrefBrowseDomains, mDNSfalse);
2104
+ while (SCPrefBrowseDomains)
2105
+ {
2106
+ DNameListElem *fptr = SCPrefBrowseDomains;
2107
+ SCPrefBrowseDomains = SCPrefBrowseDomains->next;
2108
+ mDNSPlatformMemFree(fptr);
2109
+ }
2110
+ }
2111
+
2112
+ // Replace the old browse domains array with the new array
2113
+ SCPrefBrowseDomains = BrowseDomains;
2114
+ }
2115
+
2116
+ mDNSlocal void AutomaticBrowseDomainChange(mDNS *const m, DNSQuestion *q, const ResourceRecord *const answer, QC_result AddRecord)
2117
+ {
2118
+ (void)m; // unused;
2119
+ (void)q; // unused
2120
+
2121
+ LogOperation("AutomaticBrowseDomainChange: %s automatic browse domain %##s",
2122
+ AddRecord ? "Adding" : "Removing", answer->rdata->u.name.c);
2123
+
2124
+ if (AddRecord) AddAutoBrowseDomain(0, &answer->rdata->u.name);
2125
+ else RmvAutoBrowseDomain(0, &answer->rdata->u.name);
2126
+ }
2127
+
2128
+ mDNSlocal mStatus handle_sethost_request(request_state *request)
2129
+ {
2130
+ get_flags(&request->msgptr, request->msgend);
2131
+ char hostName[MAX_DOMAIN_LABEL];
2132
+ int len = 0;
2133
+ if (get_string(&request->msgptr, request->msgend, hostName,
2134
+ MAX_DOMAIN_LABEL) < 0) return (mStatus_BadParamErr);
2135
+ LogOperation("%3d: DNSSetHostname(%X, %d, nonstr ) START",
2136
+ request->sd, request->flags);
2137
+ // if we start using this as a callback for notification when the
2138
+ // hostname changes we may need to cleanup from it
2139
+ // request->terminate = sethost_termination_callback;
2140
+ if(hostName[0] == 0) return mStatus_BadParamErr;
2141
+ while (len < MAX_DOMAIN_LABEL && hostName[len+1]
2142
+ && hostName[len+1] != '.') len++;
2143
+ strncpy(&(mDNSStorage.nicelabel.c[1]), hostName, len);
2144
+ mDNSStorage.nicelabel.c[0] = len;
2145
+ strncpy(&(mDNSStorage.hostlabel.c[1]), hostName, len);
2146
+ mDNSStorage.hostlabel.c[0] = len;
2147
+ mDNS_SetFQDN(&mDNSStorage);
2148
+ return mStatus_NoError;
2149
+ }
2150
+
2151
+ mDNSlocal mStatus handle_browse_request(request_state *request)
2152
+ {
2153
+ char regtype[MAX_ESCAPED_DOMAIN_NAME], domain[MAX_ESCAPED_DOMAIN_NAME];
2154
+ domainname typedn, d, temp;
2155
+ mDNSs32 NumSubTypes;
2156
+ mStatus err = mStatus_NoError;
2157
+
2158
+ DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
2159
+ mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
2160
+ mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
2161
+ if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr);
2162
+
2163
+ if (get_string(&request->msgptr, request->msgend, regtype, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
2164
+ get_string(&request->msgptr, request->msgend, domain, MAX_ESCAPED_DOMAIN_NAME) < 0) return(mStatus_BadParamErr);
2165
+
2166
+ if (!request->msgptr) { LogMsg("%3d: DNSServiceBrowse(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
2167
+
2168
+ if (domain[0] == '\0') uDNS_SetupSearchDomains(&mDNSStorage, UDNS_START_WAB_QUERY);
2169
+
2170
+ request->flags = flags;
2171
+ typedn.c[0] = 0;
2172
+ NumSubTypes = ChopSubTypes(regtype); // Note: Modifies regtype string to remove trailing subtypes
2173
+ if (NumSubTypes < 0 || NumSubTypes > 1) return(mStatus_BadParamErr);
2174
+ if (NumSubTypes == 1 && !AppendDNSNameString(&typedn, regtype + strlen(regtype) + 1)) return(mStatus_BadParamErr);
2175
+
2176
+ if (!regtype[0] || !AppendDNSNameString(&typedn, regtype)) return(mStatus_BadParamErr);
2177
+
2178
+ if (!MakeDomainNameFromDNSNameString(&temp, regtype)) return(mStatus_BadParamErr);
2179
+ // For over-long service types, we only allow domain "local"
2180
+ if (temp.c[0] > 15 && domain[0] == 0) mDNSPlatformStrLCopy(domain, "local.", sizeof(domain));
2181
+
2182
+ // Set up browser info
2183
+ request->u.browser.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0;
2184
+ request->u.browser.interface_id = InterfaceID;
2185
+ AssignDomainName(&request->u.browser.regtype, &typedn);
2186
+ request->u.browser.default_domain = !domain[0];
2187
+ request->u.browser.browsers = NULL;
2188
+
2189
+ LogOperation("%3d: DNSServiceBrowse(%X, %d, \"%##s\", \"%s\") START",
2190
+ request->sd, request->flags, interfaceIndex, request->u.browser.regtype.c, domain);
2191
+
2192
+ // We need to unconditionally set request->terminate, because even if we didn't successfully
2193
+ // start any browses right now, subsequent configuration changes may cause successful
2194
+ // browses to be added, and we'll need to cancel them before freeing this memory.
2195
+ request->terminate = browse_termination_callback;
2196
+
2197
+ if (domain[0])
2198
+ {
2199
+ if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
2200
+ err = add_domain_to_browser(request, &d);
2201
+ #if 0
2202
+ err = AuthorizedDomain(request, &d, AutoBrowseDomains) ? add_domain_to_browser(request, &d) : mStatus_NoError;
2203
+ #endif
2204
+ }
2205
+ else
2206
+ {
2207
+ DNameListElem *sdom;
2208
+ for (sdom = AutoBrowseDomains; sdom; sdom = sdom->next)
2209
+ if (!sdom->uid || SystemUID(request->uid) || request->uid == sdom->uid)
2210
+ {
2211
+ err = add_domain_to_browser(request, &sdom->name);
2212
+ if (err)
2213
+ {
2214
+ if (SameDomainName(&sdom->name, &localdomain)) break;
2215
+ else err = mStatus_NoError; // suppress errors for non-local "default" domains
2216
+ }
2217
+ }
2218
+ }
2219
+
2220
+ return(err);
2221
+ }
2222
+
2223
+ // ***************************************************************************
2224
+ #if COMPILER_LIKES_PRAGMA_MARK
2225
+ #pragma mark -
2226
+ #pragma mark - DNSServiceResolve
2227
+ #endif
2228
+
2229
+ mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
2230
+ {
2231
+ size_t len = 0;
2232
+ char fullname[MAX_ESCAPED_DOMAIN_NAME], target[MAX_ESCAPED_DOMAIN_NAME];
2233
+ char *data;
2234
+ reply_state *rep;
2235
+ request_state *req = question->QuestionContext;
2236
+ (void)m; // Unused
2237
+
2238
+ LogOperation("%3d: DNSServiceResolve(%##s) %s %s", req->sd, question->qname.c, AddRecord ? "ADD" : "RMV", RRDisplayString(m, answer));
2239
+
2240
+ if (!AddRecord)
2241
+ {
2242
+ if (req->u.resolve.srv == answer) req->u.resolve.srv = mDNSNULL;
2243
+ if (req->u.resolve.txt == answer) req->u.resolve.txt = mDNSNULL;
2244
+ return;
2245
+ }
2246
+
2247
+ if (answer->rrtype == kDNSType_SRV) req->u.resolve.srv = answer;
2248
+ if (answer->rrtype == kDNSType_TXT) req->u.resolve.txt = answer;
2249
+
2250
+ if (!req->u.resolve.txt || !req->u.resolve.srv) return; // only deliver result to client if we have both answers
2251
+
2252
+ ConvertDomainNameToCString(answer->name, fullname);
2253
+ ConvertDomainNameToCString(&req->u.resolve.srv->rdata->u.srv.target, target);
2254
+
2255
+ // calculate reply length
2256
+ len += sizeof(DNSServiceFlags);
2257
+ len += sizeof(mDNSu32); // interface index
2258
+ len += sizeof(DNSServiceErrorType);
2259
+ len += strlen(fullname) + 1;
2260
+ len += strlen(target) + 1;
2261
+ len += 2 * sizeof(mDNSu16); // port, txtLen
2262
+ len += req->u.resolve.txt->rdlength;
2263
+
2264
+ // allocate/init reply header
2265
+ rep = create_reply(resolve_reply_op, len, req);
2266
+ rep->rhdr->flags = dnssd_htonl(0);
2267
+ rep->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse));
2268
+ rep->rhdr->error = dnssd_htonl(kDNSServiceErr_NoError);
2269
+
2270
+ data = (char *)&rep->rhdr[1];
2271
+
2272
+ // write reply data to message
2273
+ put_string(fullname, &data);
2274
+ put_string(target, &data);
2275
+ *data++ = req->u.resolve.srv->rdata->u.srv.port.b[0];
2276
+ *data++ = req->u.resolve.srv->rdata->u.srv.port.b[1];
2277
+ put_uint16(req->u.resolve.txt->rdlength, &data);
2278
+ put_rdata (req->u.resolve.txt->rdlength, req->u.resolve.txt->rdata->u.data, &data);
2279
+
2280
+ LogOperation("%3d: DNSServiceResolve(%s) RESULT %s:%d", req->sd, fullname, target, mDNSVal16(req->u.resolve.srv->rdata->u.srv.port));
2281
+ append_reply(req, rep);
2282
+ }
2283
+
2284
+ mDNSlocal void resolve_termination_callback(request_state *request)
2285
+ {
2286
+ LogOperation("%3d: DNSServiceResolve(%##s) STOP", request->sd, request->u.resolve.qtxt.qname.c);
2287
+ mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qtxt);
2288
+ mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
2289
+ if (request->u.resolve.external_advertise) external_stop_resolving_service(&request->u.resolve.qsrv.qname);
2290
+ }
2291
+
2292
+ mDNSlocal mStatus handle_resolve_request(request_state *request)
2293
+ {
2294
+ char name[256], regtype[MAX_ESCAPED_DOMAIN_NAME], domain[MAX_ESCAPED_DOMAIN_NAME];
2295
+ domainname fqdn;
2296
+ mStatus err;
2297
+
2298
+ // extract the data from the message
2299
+ DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
2300
+ mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
2301
+ mDNSInterfaceID InterfaceID;
2302
+ mDNSBool wasP2P = (interfaceIndex == kDNSServiceInterfaceIndexP2P);
2303
+
2304
+
2305
+ request->flags = flags;
2306
+ if (wasP2P) interfaceIndex = kDNSServiceInterfaceIndexAny;
2307
+
2308
+ InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
2309
+ if (interfaceIndex && !InterfaceID)
2310
+ { LogMsg("ERROR: handle_resolve_request bad interfaceIndex %d", interfaceIndex); return(mStatus_BadParamErr); }
2311
+
2312
+ if (get_string(&request->msgptr, request->msgend, name, 256) < 0 ||
2313
+ get_string(&request->msgptr, request->msgend, regtype, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
2314
+ get_string(&request->msgptr, request->msgend, domain, MAX_ESCAPED_DOMAIN_NAME) < 0)
2315
+ { LogMsg("ERROR: handle_resolve_request - Couldn't read name/regtype/domain"); return(mStatus_BadParamErr); }
2316
+
2317
+ if (!request->msgptr) { LogMsg("%3d: DNSServiceResolve(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
2318
+
2319
+ if (build_domainname_from_strings(&fqdn, name, regtype, domain) < 0)
2320
+ { LogMsg("ERROR: handle_resolve_request bad “%s” “%s” “%s”", name, regtype, domain); return(mStatus_BadParamErr); }
2321
+
2322
+ mDNSPlatformMemZero(&request->u.resolve, sizeof(request->u.resolve));
2323
+
2324
+ // format questions
2325
+ request->u.resolve.qsrv.InterfaceID = InterfaceID;
2326
+ request->u.resolve.qsrv.Target = zeroAddr;
2327
+ AssignDomainName(&request->u.resolve.qsrv.qname, &fqdn);
2328
+ request->u.resolve.qsrv.qtype = kDNSType_SRV;
2329
+ request->u.resolve.qsrv.qclass = kDNSClass_IN;
2330
+ request->u.resolve.qsrv.LongLived = (flags & kDNSServiceFlagsLongLivedQuery ) != 0;
2331
+ request->u.resolve.qsrv.ExpectUnique = mDNStrue;
2332
+ request->u.resolve.qsrv.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
2333
+ request->u.resolve.qsrv.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
2334
+ request->u.resolve.qsrv.SuppressUnusable = mDNSfalse;
2335
+ request->u.resolve.qsrv.SearchListIndex = 0;
2336
+ request->u.resolve.qsrv.AppendSearchDomains = 0;
2337
+ request->u.resolve.qsrv.RetryWithSearchDomains = mDNSfalse;
2338
+ request->u.resolve.qsrv.TimeoutQuestion = 0;
2339
+ request->u.resolve.qsrv.WakeOnResolve = (flags & kDNSServiceFlagsWakeOnResolve) != 0;
2340
+ request->u.resolve.qsrv.qnameOrig = mDNSNULL;
2341
+ request->u.resolve.qsrv.QuestionCallback = resolve_result_callback;
2342
+ request->u.resolve.qsrv.QuestionContext = request;
2343
+
2344
+ request->u.resolve.qtxt.InterfaceID = InterfaceID;
2345
+ request->u.resolve.qtxt.Target = zeroAddr;
2346
+ AssignDomainName(&request->u.resolve.qtxt.qname, &fqdn);
2347
+ request->u.resolve.qtxt.qtype = kDNSType_TXT;
2348
+ request->u.resolve.qtxt.qclass = kDNSClass_IN;
2349
+ request->u.resolve.qtxt.LongLived = (flags & kDNSServiceFlagsLongLivedQuery ) != 0;
2350
+ request->u.resolve.qtxt.ExpectUnique = mDNStrue;
2351
+ request->u.resolve.qtxt.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
2352
+ request->u.resolve.qtxt.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
2353
+ request->u.resolve.qtxt.SuppressUnusable = mDNSfalse;
2354
+ request->u.resolve.qtxt.SearchListIndex = 0;
2355
+ request->u.resolve.qtxt.AppendSearchDomains = 0;
2356
+ request->u.resolve.qtxt.RetryWithSearchDomains = mDNSfalse;
2357
+ request->u.resolve.qtxt.TimeoutQuestion = 0;
2358
+ request->u.resolve.qtxt.WakeOnResolve = 0;
2359
+ request->u.resolve.qtxt.qnameOrig = mDNSNULL;
2360
+ request->u.resolve.qtxt.QuestionCallback = resolve_result_callback;
2361
+ request->u.resolve.qtxt.QuestionContext = request;
2362
+
2363
+ request->u.resolve.ReportTime = NonZeroTime(mDNS_TimeNow(&mDNSStorage) + 130 * mDNSPlatformOneSecond);
2364
+
2365
+ request->u.resolve.external_advertise = mDNSfalse;
2366
+
2367
+ #if 0
2368
+ if (!AuthorizedDomain(request, &fqdn, AutoBrowseDomains)) return(mStatus_NoError);
2369
+ #endif
2370
+
2371
+ // ask the questions
2372
+ LogOperation("%3d: DNSServiceResolve(%##s) START", request->sd, request->u.resolve.qsrv.qname.c);
2373
+ err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qsrv);
2374
+ if (!err)
2375
+ {
2376
+ err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qtxt);
2377
+ if (err) mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
2378
+ else
2379
+ {
2380
+ request->terminate = resolve_termination_callback;
2381
+ // If the user explicitly passed in P2P, we don't restrict the domain in which we resolve.
2382
+ if (wasP2P || (!InterfaceID && IsLocalDomain(&fqdn) && (request->flags & kDNSServiceFlagsIncludeP2P)))
2383
+ {
2384
+ request->u.resolve.external_advertise = mDNStrue;
2385
+ LogInfo("handle_resolve_request: calling external_start_resolving_service()");
2386
+ external_start_resolving_service(&fqdn);
2387
+ }
2388
+ }
2389
+ }
2390
+
2391
+ return(err);
2392
+ }
2393
+
2394
+ // ***************************************************************************
2395
+ #if COMPILER_LIKES_PRAGMA_MARK
2396
+ #pragma mark -
2397
+ #pragma mark - DNSServiceQueryRecord
2398
+ #endif
2399
+
2400
+ // mDNS operation functions. Each operation has 3 associated functions - a request handler that parses
2401
+ // the client's request and makes the appropriate mDNSCore call, a result handler (passed as a callback
2402
+ // to the mDNSCore routine) that sends results back to the client, and a termination routine that aborts
2403
+ // the mDNSCore operation if the client dies or closes its socket.
2404
+
2405
+ // Returns -1 to tell the caller that it should not try to reissue the query anymore
2406
+ // Returns 1 on successfully appending a search domain and the caller should reissue the new query
2407
+ // Returns 0 when there are no more search domains and the caller should reissue the query
2408
+ mDNSlocal int AppendNewSearchDomain(mDNS *const m, DNSQuestion *question)
2409
+ {
2410
+ domainname *sd;
2411
+ mStatus err;
2412
+
2413
+ // Sanity check: The caller already checks this. We use -1 to indicate that we have searched all
2414
+ // the domains and should try the single label query directly on the wire.
2415
+ if (question->SearchListIndex == -1)
2416
+ {
2417
+ LogMsg("AppendNewSearchDomain: question %##s (%s) SearchListIndex is -1", question->qname.c, DNSTypeName(question->qtype));
2418
+ return -1;
2419
+ }
2420
+
2421
+ if (!question->AppendSearchDomains)
2422
+ {
2423
+ LogMsg("AppendNewSearchDomain: question %##s (%s) AppendSearchDoamins is 0", question->qname.c, DNSTypeName(question->qtype));
2424
+ return -1;
2425
+ }
2426
+
2427
+ // Save the original name, before we modify them below.
2428
+ if (!question->qnameOrig)
2429
+ {
2430
+ question->qnameOrig = mallocL("AppendNewSearchDomain", sizeof(domainname));
2431
+ if (!question->qnameOrig) { LogMsg("AppendNewSearchDomain: ERROR!! malloc failure"); return -1; }
2432
+ question->qnameOrig->c[0] = 0;
2433
+ AssignDomainName(question->qnameOrig, &question->qname);
2434
+ LogInfo("AppendSearchDomain: qnameOrig %##s", question->qnameOrig->c);
2435
+ }
2436
+
2437
+ sd = uDNS_GetNextSearchDomain(m, question->InterfaceID, &question->SearchListIndex, !question->AppendLocalSearchDomains);
2438
+ // We use -1 to indicate that we have searched all the domains and should try the single label
2439
+ // query directly on the wire. uDNS_GetNextSearchDomain should never return a negative value
2440
+ if (question->SearchListIndex == -1)
2441
+ {
2442
+ LogMsg("AppendNewSearchDomain: ERROR!! uDNS_GetNextSearchDomain returned -1");
2443
+ return -1;
2444
+ }
2445
+
2446
+ // Not a common case. Perhaps, we should try the next search domain if it exceeds ?
2447
+ if (sd && (DomainNameLength(question->qnameOrig) + DomainNameLength(sd)) > MAX_DOMAIN_NAME)
2448
+ {
2449
+ LogMsg("AppendNewSearchDomain: ERROR!! exceeding max domain length for %##s (%s) SearchDomain %##s length %d, Question name length %d", question->qnameOrig->c, DNSTypeName(question->qtype), sd->c, DomainNameLength(question->qnameOrig), DomainNameLength(sd));
2450
+ return -1;
2451
+ }
2452
+
2453
+ // if there are no more search domains and we have already tried this question
2454
+ // without appending search domains, then we are done.
2455
+ if (!sd && !ApplySearchDomainsFirst(question))
2456
+ {
2457
+ LogInfo("AppnedNewSearchDomain: No more search domains for question with name %##s (%s), not trying anymore", question->qname.c, DNSTypeName(question->qtype));
2458
+ return -1;
2459
+ }
2460
+
2461
+ // Stop the question before changing the name as negative cache entries could be pointing at this question.
2462
+ // Even if we don't change the question in the case of returning 0, the caller is going to restart the
2463
+ // question.
2464
+ err = mDNS_StopQuery(&mDNSStorage, question);
2465
+ if (err) { LogMsg("AppendNewSearchDomain: ERROR!! %##s %s mDNS_StopQuery: %d, while retrying with search domains", question->qname.c, DNSTypeName(question->qtype), (int)err); }
2466
+
2467
+ AssignDomainName(&question->qname, question->qnameOrig);
2468
+ if (sd)
2469
+ {
2470
+ AppendDomainName(&question->qname, sd);
2471
+ LogInfo("AppnedNewSearchDomain: Returning question with name %##s, SearchListIndex %d", question->qname.c, question->SearchListIndex);
2472
+ return 1;
2473
+ }
2474
+
2475
+ // Try the question as single label
2476
+ LogInfo("AppnedNewSearchDomain: No more search domains for question with name %##s (%s), trying one last time", question->qname.c, DNSTypeName(question->qtype));
2477
+ return 0;
2478
+ }
2479
+
2480
+ #if APPLE_OSX_mDNSResponder
2481
+
2482
+ mDNSlocal mDNSBool DomainInSearchList(domainname *domain)
2483
+ {
2484
+ const SearchListElem *s;
2485
+ for (s=SearchList; s; s=s->next)
2486
+ if (SameDomainName(&s->domain, domain)) return mDNStrue;
2487
+ return mDNSfalse;
2488
+ }
2489
+
2490
+ // Workaround for networks using Microsoft Active Directory using "local" as a private internal
2491
+ // top-level domain
2492
+ mDNSlocal mStatus SendAdditionalQuery(DNSQuestion *q, request_state *request, mStatus err)
2493
+ {
2494
+ extern domainname ActiveDirectoryPrimaryDomain;
2495
+ DNSQuestion **question2;
2496
+ #define VALID_MSAD_SRV_TRANSPORT(T) (SameDomainLabel((T)->c, (const mDNSu8 *)"\x4_tcp") || SameDomainLabel((T)->c, (const mDNSu8 *)"\x4_udp"))
2497
+ #define VALID_MSAD_SRV(Q) ((Q)->qtype == kDNSType_SRV && VALID_MSAD_SRV_TRANSPORT(SecondLabel(&(Q)->qname)))
2498
+
2499
+ question2 = mDNSNULL;
2500
+ if (request->hdr.op == query_request)
2501
+ question2 = &request->u.queryrecord.q2;
2502
+ else if (request->hdr.op == addrinfo_request)
2503
+ {
2504
+ if (q->qtype == kDNSType_A)
2505
+ question2 = &request->u.addrinfo.q42;
2506
+ else if (q->qtype == kDNSType_AAAA)
2507
+ question2 = &request->u.addrinfo.q62;
2508
+ }
2509
+ if (!question2)
2510
+ {
2511
+ LogMsg("SendAdditionalQuery: question2 NULL for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
2512
+ return mStatus_BadParamErr;
2513
+ }
2514
+
2515
+ // Sanity check: If we already sent an additonal query, we don't need to send one more.
2516
+ //
2517
+ // 1. When the application calls DNSServiceQueryRecord or DNSServiceGetAddrInfo with a .local name, this function
2518
+ // is called to see whether a unicast query should be sent or not.
2519
+ //
2520
+ // 2. As a result of appending search domains, the question may be end up with a .local suffix even though it
2521
+ // was not a .local name to start with. In that case, queryrecord_result_callback calls this function to
2522
+ // send the additional query.
2523
+ //
2524
+ // Thus, it should not be called more than once.
2525
+ if (*question2)
2526
+ {
2527
+ LogInfo("SendAdditionalQuery: question2 already sent for %##s (%s), no more q2", q->qname.c, DNSTypeName(q->qtype));
2528
+ return err;
2529
+ }
2530
+
2531
+ if (!q->ForceMCast && SameDomainLabel(LastLabel(&q->qname), (const mDNSu8 *)&localdomain))
2532
+ if (q->qtype == kDNSType_A || q->qtype == kDNSType_AAAA || VALID_MSAD_SRV(q))
2533
+ {
2534
+ DNSQuestion *q2;
2535
+ int labels = CountLabels(&q->qname);
2536
+ q2 = mallocL("DNSQuestion", sizeof(DNSQuestion));
2537
+ if (!q2) FatalError("ERROR: SendAdditionalQuery malloc");
2538
+ *question2 = q2;
2539
+ *q2 = *q;
2540
+ q2->InterfaceID = mDNSInterface_Unicast;
2541
+ q2->ExpectUnique = mDNStrue;
2542
+ // If the query starts as a single label e.g., somehost, and we have search domains with .local,
2543
+ // queryrecord_result_callback calls this function when .local is appended to "somehost".
2544
+ // At that time, the name in "q" is pointing at somehost.local and its qnameOrig pointing at
2545
+ // "somehost". We need to copy that information so that when we retry with a different search
2546
+ // domain e.g., mycompany.local, we get "somehost.mycompany.local".
2547
+ if (q->qnameOrig)
2548
+ {
2549
+ (*question2)->qnameOrig = mallocL("SendAdditionalQuery", DomainNameLength(q->qnameOrig));
2550
+ if (!(*question2)->qnameOrig) { LogMsg("SendAdditionalQuery: ERROR!! malloc failure"); return mStatus_NoMemoryErr; }
2551
+ (*question2)->qnameOrig->c[0] = 0;
2552
+ AssignDomainName((*question2)->qnameOrig, q->qnameOrig);
2553
+ LogInfo("SendAdditionalQuery: qnameOrig %##s", (*question2)->qnameOrig->c);
2554
+ }
2555
+ // For names of the form "<one-or-more-labels>.bar.local." we always do a second unicast query in parallel.
2556
+ // For names of the form "<one-label>.local." it's less clear whether we should do a unicast query.
2557
+ // If the name being queried is exactly the same as the name in the DHCP "domain" option (e.g. the DHCP
2558
+ // "domain" is my-small-company.local, and the user types "my-small-company.local" into their web browser)
2559
+ // then that's a hint that it's worth doing a unicast query. Otherwise, we first check to see if the
2560
+ // site's DNS server claims there's an SOA record for "local", and if so, that's also a hint that queries
2561
+ // for names in the "local" domain will be safely answered privately before they hit the root name servers.
2562
+ // Note that in the "my-small-company.local" example above there will typically be an SOA record for
2563
+ // "my-small-company.local" but *not* for "local", which is why the "local SOA" check would fail in that case.
2564
+ // We need to check against both ActiveDirectoryPrimaryDomain and SearchList. If it matches against either
2565
+ // of those, we don't want do the SOA check for the local
2566
+ if (labels == 2 && !SameDomainName(&q->qname, &ActiveDirectoryPrimaryDomain) && !DomainInSearchList(&q->qname))
2567
+ {
2568
+ AssignDomainName(&q2->qname, &localdomain);
2569
+ q2->qtype = kDNSType_SOA;
2570
+ q2->LongLived = mDNSfalse;
2571
+ q2->ForceMCast = mDNSfalse;
2572
+ q2->ReturnIntermed = mDNStrue;
2573
+ // Don't append search domains for the .local SOA query
2574
+ q2->AppendSearchDomains = 0;
2575
+ q2->AppendLocalSearchDomains = 0;
2576
+ q2->RetryWithSearchDomains = mDNSfalse;
2577
+ q2->SearchListIndex = 0;
2578
+ q2->TimeoutQuestion = 0;
2579
+ }
2580
+ LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) unicast", request->sd, q2->qname.c, DNSTypeName(q2->qtype));
2581
+ err = mDNS_StartQuery(&mDNSStorage, q2);
2582
+ if (err) LogMsg("%3d: ERROR: DNSServiceQueryRecord %##s %s mDNS_StartQuery: %d", request->sd, q2->qname.c, DNSTypeName(q2->qtype), (int)err);
2583
+ }
2584
+ return(err);
2585
+ }
2586
+ #endif // APPLE_OSX_mDNSResponder
2587
+
2588
+ // This function tries to append a search domain if valid and possible. If so, returns true.
2589
+ mDNSlocal mDNSBool RetryQuestionWithSearchDomains(mDNS *const m, DNSQuestion *question, request_state *req)
2590
+ {
2591
+ int result;
2592
+ // RetryWithSearchDomains tells the core to call us back so that we can retry with search domains if there is no
2593
+ // answer in the cache or /etc/hosts. In the first call back from the core, we clear RetryWithSearchDomains so
2594
+ // that we don't get called back repeatedly. If we got an answer from the cache or /etc/hosts, we don't touch
2595
+ // RetryWithSearchDomains which may or may not be set.
2596
+ //
2597
+ // If we get e.g., NXDOMAIN and the query is neither suppressed nor exhausted the domain search list and
2598
+ // is a valid question for appending search domains, retry by appending domains
2599
+
2600
+ if (!question->SuppressQuery && question->SearchListIndex != -1 && question->AppendSearchDomains)
2601
+ {
2602
+ question->RetryWithSearchDomains = 0;
2603
+ result = AppendNewSearchDomain(m, question);
2604
+ // As long as the result is either zero or 1, we retry the question. If we exahaust the search
2605
+ // domains (result is zero) we try the original query (as it was before appending the search
2606
+ // domains) as such on the wire as a last resort if we have not tried them before. For queries
2607
+ // with more than one label, we have already tried them before appending search domains and
2608
+ // hence don't retry again
2609
+ if (result != -1)
2610
+ {
2611
+ mStatus err;
2612
+ err = mDNS_StartQuery(m, question);
2613
+ if (!err)
2614
+ {
2615
+ LogOperation("%3d: RetryQuestionWithSearchDomains(%##s, %s), retrying after appending search domain", req->sd, question->qname.c, DNSTypeName(question->qtype));
2616
+ // If the result was zero, it meant that there are no search domains and we just retried the question
2617
+ // as a single label and we should not retry with search domains anymore.
2618
+ if (!result) question->SearchListIndex = -1;
2619
+ return mDNStrue;
2620
+ }
2621
+ else
2622
+ {
2623
+ LogMsg("%3d: ERROR: RetryQuestionWithSearchDomains %##s %s mDNS_StartQuery: %d, while retrying with search domains", req->sd, question->qname.c, DNSTypeName(question->qtype), (int)err);
2624
+ // We have already stopped the query and could not restart. Reset the appropriate pointers
2625
+ // so that we don't call stop again when the question terminates
2626
+ question->QuestionContext = mDNSNULL;
2627
+ }
2628
+ }
2629
+ }
2630
+ else
2631
+ {
2632
+ LogInfo("%3d: RetryQuestionWithSearchDomains: Not appending search domains - SuppressQuery %d, SearchListIndex %d, AppendSearchDomains %d", req->sd, question->SuppressQuery, question->SearchListIndex, question->AppendSearchDomains);
2633
+ }
2634
+ return mDNSfalse;
2635
+ }
2636
+
2637
+ mDNSlocal void queryrecord_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
2638
+ {
2639
+ char name[MAX_ESCAPED_DOMAIN_NAME];
2640
+ request_state *req = question->QuestionContext;
2641
+ reply_state *rep;
2642
+ char *data;
2643
+ size_t len;
2644
+ DNSServiceErrorType error = kDNSServiceErr_NoError;
2645
+ DNSQuestion *q = mDNSNULL;
2646
+
2647
+ #if APPLE_OSX_mDNSResponder
2648
+ {
2649
+ // Sanity check: QuestionContext is set to NULL after we stop the question and hence we should not
2650
+ // get any callbacks from the core after this.
2651
+ if (!req)
2652
+ {
2653
+ LogMsg("queryrecord_result_callback: ERROR!! QuestionContext NULL for %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
2654
+ return;
2655
+ }
2656
+ if (req->hdr.op == query_request && question == req->u.queryrecord.q2)
2657
+ q = &req->u.queryrecord.q;
2658
+ else if (req->hdr.op == addrinfo_request && question == req->u.addrinfo.q42)
2659
+ q = &req->u.addrinfo.q4;
2660
+ else if (req->hdr.op == addrinfo_request && question == req->u.addrinfo.q62)
2661
+ q = &req->u.addrinfo.q6;
2662
+
2663
+ if (q && question->qtype != q->qtype && !SameDomainName(&question->qname, &q->qname))
2664
+ {
2665
+ mStatus err;
2666
+ domainname *orig = question->qnameOrig;
2667
+
2668
+ LogInfo("queryrecord_result_callback: Stopping q2 local %##s", question->qname.c);
2669
+ mDNS_StopQuery(m, question);
2670
+ question->QuestionContext = mDNSNULL;
2671
+
2672
+ // We got a negative response for the SOA record indicating that .local does not exist.
2673
+ // But we might have other search domains (that does not end in .local) that can be
2674
+ // appended to this question. In that case, we want to retry the question. Otherwise,
2675
+ // we don't want to try this question as unicast.
2676
+ if (answer->RecordType == kDNSRecordTypePacketNegative && !q->AppendSearchDomains)
2677
+ {
2678
+ LogInfo("queryrecord_result_callback: question %##s AppendSearchDomains zero", q->qname.c);
2679
+ return;
2680
+ }
2681
+
2682
+ // If we got a non-negative answer for our "local SOA" test query, start an additional parallel unicast query
2683
+ //
2684
+ // Note: When we copy the original question, we copy everything including the AppendSearchDomains,
2685
+ // RetryWithSearchDomains except for qnameOrig which can be non-NULL if the original question is
2686
+ // e.g., somehost and then we appended e.g., ".local" and retried that question. See comment in
2687
+ // SendAdditionalQuery as to how qnameOrig gets initialized.
2688
+ *question = *q;
2689
+ question->InterfaceID = mDNSInterface_Unicast;
2690
+ question->ExpectUnique = mDNStrue;
2691
+ question->qnameOrig = orig;
2692
+
2693
+ LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) unicast, context %p", req->sd, question->qname.c, DNSTypeName(question->qtype), question->QuestionContext);
2694
+
2695
+ // If the original question timed out, its QuestionContext would already be set to NULL and that's what we copied above.
2696
+ // Hence, we need to set it explicitly here.
2697
+ question->QuestionContext = req;
2698
+ err = mDNS_StartQuery(m, question);
2699
+ if (err) LogMsg("%3d: ERROR: queryrecord_result_callback %##s %s mDNS_StartQuery: %d", req->sd, question->qname.c, DNSTypeName(question->qtype), (int)err);
2700
+
2701
+ // If we got a positive response to local SOA, then try the .local question as unicast
2702
+ if (answer->RecordType != kDNSRecordTypePacketNegative) return;
2703
+
2704
+ // Fall through and get the next search domain. The question is pointing at .local
2705
+ // and we don't want to try that. Try the next search domain. Don't try with local
2706
+ // search domains for the unicast question anymore.
2707
+ //
2708
+ // Note: we started the question above which will be stopped immediately (never sent on the wire)
2709
+ // before we pick the next search domain below. RetryQuestionWithSearchDomains assumes that the
2710
+ // question has already started.
2711
+ question->AppendLocalSearchDomains = 0;
2712
+ }
2713
+
2714
+ if (q && AddRecord && (question->InterfaceID == mDNSInterface_Unicast) && !answer->rdlength)
2715
+ {
2716
+ // If we get a negative response to the unicast query that we sent above, retry after appending search domains
2717
+ // Note: We could have appended search domains below (where do it for regular unicast questions) instead of doing it here.
2718
+ // As we ignore negative unicast answers below, we would never reach the code where the search domains are appended.
2719
+ // To keep things simple, we handle unicast ".local" separately here.
2720
+ LogInfo("queryrecord_result_callback: Retrying .local question %##s (%s) as unicast after appending search domains", question->qname.c, DNSTypeName(question->qtype));
2721
+ if (RetryQuestionWithSearchDomains(m, question, req))
2722
+ return;
2723
+ if (question->AppendSearchDomains && !question->AppendLocalSearchDomains && IsLocalDomain(&question->qname))
2724
+ {
2725
+ // If "local" is the last search domain, we need to stop the question so that we don't send the "local"
2726
+ // question on the wire as we got a negative response for the local SOA. But, we can't stop the question
2727
+ // yet as we may have to timeout the question (done by the "core") for which we need to leave the question
2728
+ // in the list. We leave it disabled so that it does not hit the wire.
2729
+ LogInfo("queryrecord_result_callback: Disabling .local question %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
2730
+ question->ThisQInterval = 0;
2731
+ }
2732
+ }
2733
+ // If we are here it means that either "question" is not "q2" OR we got a positive response for "q2" OR we have no more search
2734
+ // domains to append for "q2". In all cases, fall through and deliver the response
2735
+ }
2736
+ #endif // APPLE_OSX_mDNSResponder
2737
+
2738
+ if (answer->RecordType == kDNSRecordTypePacketNegative)
2739
+ {
2740
+ // If this question needs to be timed out and we have reached the stop time, mark
2741
+ // the error as timeout. It is possible that we might get a negative response from an
2742
+ // external DNS server at the same time when this question reaches its stop time. We
2743
+ // can't tell the difference as there is no indication in the callback. This should
2744
+ // be okay as we will be timing out this query anyway.
2745
+ mDNS_Lock(m);
2746
+ if (question->TimeoutQuestion)
2747
+ {
2748
+ if ((m->timenow - question->StopTime) >= 0)
2749
+ {
2750
+ LogInfo("queryrecord_result_callback:Question %##s (%s) timing out, InterfaceID %p", question->qname.c, DNSTypeName(question->qtype), question->InterfaceID);
2751
+ error = kDNSServiceErr_Timeout;
2752
+ }
2753
+ }
2754
+ mDNS_Unlock(m);
2755
+ // When we're doing parallel unicast and multicast queries for dot-local names (for supporting Microsoft
2756
+ // Active Directory sites) we need to ignore negative unicast answers. Otherwise we'll generate negative
2757
+ // answers for just about every single multicast name we ever look up, since the Microsoft Active Directory
2758
+ // server is going to assert that pretty much every single multicast name doesn't exist.
2759
+ //
2760
+ // If we are timing out this query, we need to deliver the negative answer to the application
2761
+ if (error != kDNSServiceErr_Timeout)
2762
+ {
2763
+ if (!answer->InterfaceID && IsLocalDomain(answer->name))
2764
+ {
2765
+ LogInfo("queryrecord_result_callback:Question %##s (%s) answering local with unicast", question->qname.c, DNSTypeName(question->qtype));
2766
+ return;
2767
+ }
2768
+ error = kDNSServiceErr_NoSuchRecord;
2769
+ }
2770
+ AddRecord = mDNStrue;
2771
+ }
2772
+ // If we get a negative answer, try appending search domains. Don't append search domains
2773
+ // - if we are timing out this question
2774
+ // - if the negative response was received as a result of a multicast query
2775
+ // - if this is an additional query (q2), we already appended search domains above (indicated by "!q" below)
2776
+ if (error != kDNSServiceErr_Timeout)
2777
+ {
2778
+ if (!q && !answer->InterfaceID && !answer->rdlength && AddRecord)
2779
+ {
2780
+ // If the original question did not end in .local, we did not send an SOA query
2781
+ // to figure out whether we should send an additional unicast query or not. If we just
2782
+ // appended .local, we need to see if we need to send an additional query. This should
2783
+ // normally happen just once because after we append .local, we ignore all negative
2784
+ // responses for .local above.
2785
+ LogInfo("queryrecord_result_callback: Retrying question %##s (%s) after appending search domains", question->qname.c, DNSTypeName(question->qtype));
2786
+ if (RetryQuestionWithSearchDomains(m, question, req))
2787
+ {
2788
+ // Note: We need to call SendAdditionalQuery every time after appending a search domain as .local could
2789
+ // be anywhere in the search domain list.
2790
+ #if APPLE_OSX_mDNSResponder
2791
+ mStatus err = mStatus_NoError;
2792
+ err = SendAdditionalQuery(question, req, err);
2793
+ if (err) LogMsg("queryrecord_result_callback: Sending .local SOA query failed, after appending domains");
2794
+ #endif // APPLE_OSX_mDNSResponder
2795
+ return;
2796
+ }
2797
+ }
2798
+ }
2799
+
2800
+ ConvertDomainNameToCString(answer->name, name);
2801
+
2802
+ LogOperation("%3d: %s(%##s, %s) %s %s", req->sd,
2803
+ req->hdr.op == query_request ? "DNSServiceQueryRecord" : "DNSServiceGetAddrInfo",
2804
+ question->qname.c, DNSTypeName(question->qtype), AddRecord ? "ADD" : "RMV", RRDisplayString(m, answer));
2805
+
2806
+ len = sizeof(DNSServiceFlags); // calculate reply data length
2807
+ len += sizeof(mDNSu32); // interface index
2808
+ len += sizeof(DNSServiceErrorType);
2809
+ len += strlen(name) + 1;
2810
+ len += 3 * sizeof(mDNSu16); // type, class, rdlen
2811
+ len += answer->rdlength;
2812
+ len += sizeof(mDNSu32); // TTL
2813
+
2814
+ rep = create_reply(req->hdr.op == query_request ? query_reply_op : addrinfo_reply_op, len, req);
2815
+
2816
+ rep->rhdr->flags = dnssd_htonl(AddRecord ? kDNSServiceFlagsAdd : 0);
2817
+ // Call mDNSPlatformInterfaceIndexfromInterfaceID, but suppressNetworkChange (last argument). Otherwise, if the
2818
+ // InterfaceID is not valid, then it simulates a "NetworkChanged" which in turn makes questions
2819
+ // to be stopped and started including *this* one. Normally the InterfaceID is valid. But when we
2820
+ // are using the /etc/hosts entries to answer a question, the InterfaceID may not be known to the
2821
+ // mDNS core . Eventually, we should remove the calls to "NetworkChanged" in
2822
+ // mDNSPlatformInterfaceIndexfromInterfaceID when it can't find InterfaceID as ResourceRecords
2823
+ // should not have existed to answer this question if the corresponding interface is not valid.
2824
+ rep->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNStrue));
2825
+ rep->rhdr->error = dnssd_htonl(error);
2826
+
2827
+ data = (char *)&rep->rhdr[1];
2828
+
2829
+ put_string(name, &data);
2830
+ put_uint16(answer->rrtype, &data);
2831
+ put_uint16(answer->rrclass, &data);
2832
+ put_uint16(answer->rdlength, &data);
2833
+ // We need to use putRData here instead of the crude put_rdata function, because the crude put_rdata
2834
+ // function just does a blind memory copy without regard to structures that may have holes in them.
2835
+ if (answer->rdlength)
2836
+ if (!putRData(mDNSNULL, (mDNSu8 *)data, (mDNSu8 *)rep->rhdr + len, answer))
2837
+ LogMsg("queryrecord_result_callback putRData failed %d", (mDNSu8 *)rep->rhdr + len - (mDNSu8 *)data);
2838
+ data += answer->rdlength;
2839
+ put_uint32(AddRecord ? answer->rroriginalttl : 0, &data);
2840
+
2841
+ append_reply(req, rep);
2842
+ // Stop the question, if we just timed out
2843
+ if (error == kDNSServiceErr_Timeout)
2844
+ {
2845
+ mDNS_StopQuery(m, question);
2846
+ // Reset the pointers so that we don't call stop on termination
2847
+ question->QuestionContext = mDNSNULL;
2848
+ }
2849
+ #if APPLE_OSX_mDNSResponder
2850
+ #if ! NO_WCF
2851
+ CHECK_WCF_FUNCTION(WCFIsServerRunning)
2852
+ {
2853
+ struct xucred x;
2854
+ socklen_t xucredlen = sizeof(x);
2855
+
2856
+ if (WCFIsServerRunning((WCFConnection *)m->WCF) && answer->rdlength != 0)
2857
+ {
2858
+ if (getsockopt(req->sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 &&
2859
+ (x.cr_version == XUCRED_VERSION))
2860
+ {
2861
+ struct sockaddr_storage addr;
2862
+ const RDataBody2 *const rdb = (RDataBody2 *)answer->rdata->u.data;
2863
+ addr.ss_len = 0;
2864
+ if (answer->rrtype == kDNSType_A || answer->rrtype == kDNSType_AAAA)
2865
+ {
2866
+ if (answer->rrtype == kDNSType_A)
2867
+ {
2868
+ struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
2869
+ sin->sin_port = 0;
2870
+ if (!putRData(mDNSNULL, (mDNSu8 *)&sin->sin_addr, (mDNSu8 *)(&sin->sin_addr + sizeof(rdb->ipv4)), answer))
2871
+ LogMsg("queryrecord_result_callback: WCF AF_INET putRData failed");
2872
+ else
2873
+ {
2874
+ addr.ss_len = sizeof (struct sockaddr_in);
2875
+ addr.ss_family = AF_INET;
2876
+ }
2877
+ }
2878
+ else if (answer->rrtype == kDNSType_AAAA)
2879
+ {
2880
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
2881
+ sin6->sin6_port = 0;
2882
+ if (!putRData(mDNSNULL, (mDNSu8 *)&sin6->sin6_addr, (mDNSu8 *)(&sin6->sin6_addr + sizeof(rdb->ipv6)), answer))
2883
+ LogMsg("queryrecord_result_callback: WCF AF_INET6 putRData failed");
2884
+ else
2885
+ {
2886
+ addr.ss_len = sizeof (struct sockaddr_in6);
2887
+ addr.ss_family = AF_INET6;
2888
+ }
2889
+ }
2890
+ if (addr.ss_len)
2891
+ {
2892
+ debugf("queryrecord_result_callback: Name %s, uid %u, addr length %d", name, x.cr_uid, addr.ss_len);
2893
+ CHECK_WCF_FUNCTION((WCFConnection *)WCFNameResolvesToAddr)
2894
+ {
2895
+ WCFNameResolvesToAddr(m->WCF, name, (struct sockaddr *)&addr, x.cr_uid);
2896
+ }
2897
+ }
2898
+ }
2899
+ else if (answer->rrtype == kDNSType_CNAME)
2900
+ {
2901
+ domainname cname;
2902
+ char cname_cstr[MAX_ESCAPED_DOMAIN_NAME];
2903
+ if (!putRData(mDNSNULL, cname.c, (mDNSu8 *)(cname.c + MAX_DOMAIN_NAME), answer))
2904
+ LogMsg("queryrecord_result_callback: WCF CNAME putRData failed");
2905
+ else
2906
+ {
2907
+ ConvertDomainNameToCString(&cname, cname_cstr);
2908
+ CHECK_WCF_FUNCTION((WCFConnection *)WCFNameResolvesToAddr)
2909
+ {
2910
+ WCFNameResolvesToName(m->WCF, name, cname_cstr, x.cr_uid);
2911
+ }
2912
+ }
2913
+ }
2914
+ }
2915
+ else my_perror("queryrecord_result_callback: ERROR: getsockopt LOCAL_PEERCRED");
2916
+ }
2917
+ }
2918
+ #endif
2919
+ #endif
2920
+ }
2921
+
2922
+ mDNSlocal void queryrecord_termination_callback(request_state *request)
2923
+ {
2924
+ LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) STOP",
2925
+ request->sd, request->u.queryrecord.q.qname.c, DNSTypeName(request->u.queryrecord.q.qtype));
2926
+ if (request->u.queryrecord.q.QuestionContext)
2927
+ {
2928
+ mDNS_StopQuery(&mDNSStorage, &request->u.queryrecord.q); // no need to error check
2929
+ request->u.queryrecord.q.QuestionContext = mDNSNULL;
2930
+ }
2931
+ else
2932
+ {
2933
+ DNSQuestion *question = &request->u.queryrecord.q;
2934
+ LogInfo("queryrecord_termination_callback: question %##s (%s) already stopped, InterfaceID %p", question->qname.c, DNSTypeName(question->qtype), question->InterfaceID);
2935
+ }
2936
+
2937
+ if (request->u.queryrecord.q.qnameOrig)
2938
+ {
2939
+ freeL("QueryTermination", request->u.queryrecord.q.qnameOrig);
2940
+ request->u.queryrecord.q.qnameOrig = mDNSNULL;
2941
+ }
2942
+ if (request->u.queryrecord.q.InterfaceID == mDNSInterface_P2P || (!request->u.queryrecord.q.InterfaceID && SameDomainName((const domainname *)LastLabel(&request->u.queryrecord.q.qname), &localdomain) && (request->flags & kDNSServiceFlagsIncludeP2P)))
2943
+ {
2944
+ LogInfo("queryrecord_termination_callback: calling external_stop_browsing_for_service()");
2945
+ external_stop_browsing_for_service(&mDNSStorage, &request->u.queryrecord.q.qname, request->u.queryrecord.q.qtype);
2946
+ }
2947
+ if (request->u.queryrecord.q2)
2948
+ {
2949
+ if (request->u.queryrecord.q2->QuestionContext)
2950
+ {
2951
+ LogInfo("queryrecord_termination_callback: Stopping q2 %##s", request->u.queryrecord.q2->qname.c);
2952
+ mDNS_StopQuery(&mDNSStorage, request->u.queryrecord.q2);
2953
+ }
2954
+ else
2955
+ {
2956
+ DNSQuestion *question = request->u.queryrecord.q2;
2957
+ LogInfo("queryrecord_termination_callback: q2 %##s (%s) already stopped, InterfaceID %p", question->qname.c, DNSTypeName(question->qtype), question->InterfaceID);
2958
+ }
2959
+ if (request->u.queryrecord.q2->qnameOrig)
2960
+ {
2961
+ LogInfo("queryrecord_termination_callback: freeing q2 qnameOrig %##s", request->u.queryrecord.q2->qnameOrig->c);
2962
+ freeL("QueryTermination q2", request->u.queryrecord.q2->qnameOrig);
2963
+ request->u.queryrecord.q2->qnameOrig = mDNSNULL;
2964
+ }
2965
+ freeL("queryrecord Q2", request->u.queryrecord.q2);
2966
+ request->u.queryrecord.q2 = mDNSNULL;
2967
+ }
2968
+ }
2969
+
2970
+ mDNSlocal mStatus handle_queryrecord_request(request_state *request)
2971
+ {
2972
+ DNSQuestion *const q = &request->u.queryrecord.q;
2973
+ char name[256];
2974
+ mDNSu16 rrtype, rrclass;
2975
+ mStatus err;
2976
+
2977
+ DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
2978
+ mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
2979
+ mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
2980
+ if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr);
2981
+
2982
+ if (get_string(&request->msgptr, request->msgend, name, 256) < 0) return(mStatus_BadParamErr);
2983
+ rrtype = get_uint16(&request->msgptr, request->msgend);
2984
+ rrclass = get_uint16(&request->msgptr, request->msgend);
2985
+
2986
+ if (!request->msgptr)
2987
+ { LogMsg("%3d: DNSServiceQueryRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
2988
+
2989
+ request->flags = flags;
2990
+ mDNSPlatformMemZero(&request->u.queryrecord, sizeof(request->u.queryrecord));
2991
+
2992
+ q->InterfaceID = InterfaceID;
2993
+ q->Target = zeroAddr;
2994
+ if (!MakeDomainNameFromDNSNameString(&q->qname, name)) return(mStatus_BadParamErr);
2995
+ #if 0
2996
+ if (!AuthorizedDomain(request, &q->qname, AutoBrowseDomains)) return (mStatus_NoError);
2997
+ #endif
2998
+ q->qtype = rrtype;
2999
+ q->qclass = rrclass;
3000
+ q->LongLived = (flags & kDNSServiceFlagsLongLivedQuery ) != 0;
3001
+ q->ExpectUnique = mDNSfalse;
3002
+ q->ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
3003
+ q->ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
3004
+ q->SuppressUnusable = (flags & kDNSServiceFlagsSuppressUnusable ) != 0;
3005
+ q->TimeoutQuestion = (flags & kDNSServiceFlagsTimeout ) != 0;
3006
+ q->WakeOnResolve = 0;
3007
+ q->QuestionCallback = queryrecord_result_callback;
3008
+ q->QuestionContext = request;
3009
+ q->SearchListIndex = 0;
3010
+
3011
+ // Don't append search domains for fully qualified domain names including queries
3012
+ // such as e.g., "abc." that has only one label. We convert all names to FQDNs as internally
3013
+ // we only deal with FQDNs. Hence, we cannot look at qname to figure out whether we should
3014
+ // append search domains or not. So, we record that information in AppendSearchDomains.
3015
+ //
3016
+ // We append search domains only for queries that are a single label. If overriden using
3017
+ // command line argument "AlwaysAppendSearchDomains", then we do it for any query which
3018
+ // is not fully qualified.
3019
+
3020
+ if ((rrtype == kDNSType_A || rrtype == kDNSType_AAAA) && name[strlen(name) - 1] != '.' &&
3021
+ (AlwaysAppendSearchDomains || CountLabels(&q->qname) == 1))
3022
+ {
3023
+ q->AppendSearchDomains = 1;
3024
+ q->AppendLocalSearchDomains = 1;
3025
+ }
3026
+ else
3027
+ {
3028
+ q->AppendSearchDomains = 0;
3029
+ q->AppendLocalSearchDomains = 0;
3030
+ }
3031
+
3032
+ // For single label queries that are not fully qualified, look at /etc/hosts, cache and try
3033
+ // search domains before trying them on the wire as a single label query. RetryWithSearchDomains
3034
+ // tell the core to call back into the UDS layer if there is no valid response in /etc/hosts or
3035
+ // the cache
3036
+ q->RetryWithSearchDomains = ApplySearchDomainsFirst(q) ? 1 : 0;
3037
+ q->qnameOrig = mDNSNULL;
3038
+
3039
+ LogOperation("%3d: DNSServiceQueryRecord(%X, %d, %##s, %s) START", request->sd, flags, interfaceIndex, q->qname.c, DNSTypeName(q->qtype));
3040
+ err = mDNS_StartQuery(&mDNSStorage, q);
3041
+ if (err) LogMsg("%3d: ERROR: DNSServiceQueryRecord %##s %s mDNS_StartQuery: %d", request->sd, q->qname.c, DNSTypeName(q->qtype), (int)err);
3042
+ else
3043
+ {
3044
+ request->terminate = queryrecord_termination_callback;
3045
+ if (q->InterfaceID == mDNSInterface_P2P || (!q->InterfaceID && SameDomainName((const domainname *)LastLabel(&q->qname), &localdomain) && (flags & kDNSServiceFlagsIncludeP2P)))
3046
+ {
3047
+ LogInfo("handle_queryrecord_request: calling external_start_browsing_for_service()");
3048
+ external_start_browsing_for_service(&mDNSStorage, &q->qname, q->qtype);
3049
+ }
3050
+ }
3051
+
3052
+ #if APPLE_OSX_mDNSResponder
3053
+ err = SendAdditionalQuery(q, request, err);
3054
+ #endif // APPLE_OSX_mDNSResponder
3055
+
3056
+ return(err);
3057
+ }
3058
+
3059
+ // ***************************************************************************
3060
+ #if COMPILER_LIKES_PRAGMA_MARK
3061
+ #pragma mark -
3062
+ #pragma mark - DNSServiceEnumerateDomains
3063
+ #endif
3064
+
3065
+ mDNSlocal reply_state *format_enumeration_reply(request_state *request,
3066
+ const char *domain, DNSServiceFlags flags, mDNSu32 ifi, DNSServiceErrorType err)
3067
+ {
3068
+ size_t len;
3069
+ reply_state *reply;
3070
+ char *data;
3071
+
3072
+ len = sizeof(DNSServiceFlags);
3073
+ len += sizeof(mDNSu32);
3074
+ len += sizeof(DNSServiceErrorType);
3075
+ len += strlen(domain) + 1;
3076
+
3077
+ reply = create_reply(enumeration_reply_op, len, request);
3078
+ reply->rhdr->flags = dnssd_htonl(flags);
3079
+ reply->rhdr->ifi = dnssd_htonl(ifi);
3080
+ reply->rhdr->error = dnssd_htonl(err);
3081
+ data = (char *)&reply->rhdr[1];
3082
+ put_string(domain, &data);
3083
+ return reply;
3084
+ }
3085
+
3086
+ mDNSlocal void enum_termination_callback(request_state *request)
3087
+ {
3088
+ mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
3089
+ mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_default);
3090
+ }
3091
+
3092
+ mDNSlocal void enum_result_callback(mDNS *const m,
3093
+ DNSQuestion *const question, const ResourceRecord *const answer, QC_result AddRecord)
3094
+ {
3095
+ char domain[MAX_ESCAPED_DOMAIN_NAME];
3096
+ request_state *request = question->QuestionContext;
3097
+ DNSServiceFlags flags = 0;
3098
+ reply_state *reply;
3099
+ (void)m; // Unused
3100
+
3101
+ if (answer->rrtype != kDNSType_PTR) return;
3102
+
3103
+ #if 0
3104
+ if (!AuthorizedDomain(request, &answer->rdata->u.name, request->u.enumeration.flags ? AutoRegistrationDomains : AutoBrowseDomains)) return;
3105
+ #endif
3106
+
3107
+ // We only return add/remove events for the browse and registration lists
3108
+ // For the default browse and registration answers, we only give an "ADD" event
3109
+ if (question == &request->u.enumeration.q_default && !AddRecord) return;
3110
+
3111
+ if (AddRecord)
3112
+ {
3113
+ flags |= kDNSServiceFlagsAdd;
3114
+ if (question == &request->u.enumeration.q_default) flags |= kDNSServiceFlagsDefault;
3115
+ }
3116
+
3117
+ ConvertDomainNameToCString(&answer->rdata->u.name, domain);
3118
+ // Note that we do NOT propagate specific interface indexes to the client - for example, a domain we learn from
3119
+ // a machine's system preferences may be discovered on the LocalOnly interface, but should be browsed on the
3120
+ // network, so we just pass kDNSServiceInterfaceIndexAny
3121
+ reply = format_enumeration_reply(request, domain, flags, kDNSServiceInterfaceIndexAny, kDNSServiceErr_NoError);
3122
+ if (!reply) { LogMsg("ERROR: enum_result_callback, format_enumeration_reply"); return; }
3123
+
3124
+ LogOperation("%3d: DNSServiceEnumerateDomains(%#2s) RESULT %s: %s", request->sd, question->qname.c, AddRecord ? "Add" : "Rmv", domain);
3125
+
3126
+ append_reply(request, reply);
3127
+ }
3128
+
3129
+ mDNSlocal mStatus handle_enum_request(request_state *request)
3130
+ {
3131
+ mStatus err;
3132
+ DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
3133
+ DNSServiceFlags reg = flags & kDNSServiceFlagsRegistrationDomains;
3134
+ mDNS_DomainType t_all = reg ? mDNS_DomainTypeRegistration : mDNS_DomainTypeBrowse;
3135
+ mDNS_DomainType t_default = reg ? mDNS_DomainTypeRegistrationDefault : mDNS_DomainTypeBrowseDefault;
3136
+ mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
3137
+ mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
3138
+ if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr);
3139
+
3140
+ if (!request->msgptr)
3141
+ { LogMsg("%3d: DNSServiceEnumerateDomains(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
3142
+
3143
+ // allocate context structures
3144
+ uDNS_SetupSearchDomains(&mDNSStorage, UDNS_START_WAB_QUERY);
3145
+
3146
+ #if 0
3147
+ // mark which kind of enumeration we're doing so we can (de)authorize certain domains
3148
+ request->u.enumeration.flags = reg;
3149
+ #endif
3150
+
3151
+ // enumeration requires multiple questions, so we must link all the context pointers so that
3152
+ // necessary context can be reached from the callbacks
3153
+ request->u.enumeration.q_all .QuestionContext = request;
3154
+ request->u.enumeration.q_default.QuestionContext = request;
3155
+
3156
+ // if the caller hasn't specified an explicit interface, we use local-only to get the system-wide list.
3157
+ if (!InterfaceID) InterfaceID = mDNSInterface_LocalOnly;
3158
+
3159
+ // make the calls
3160
+ LogOperation("%3d: DNSServiceEnumerateDomains(%X=%s)", request->sd, flags,
3161
+ (flags & kDNSServiceFlagsBrowseDomains ) ? "kDNSServiceFlagsBrowseDomains" :
3162
+ (flags & kDNSServiceFlagsRegistrationDomains) ? "kDNSServiceFlagsRegistrationDomains" : "<<Unknown>>");
3163
+ err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_all, t_all, NULL, InterfaceID, enum_result_callback, request);
3164
+ if (!err)
3165
+ {
3166
+ err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_default, t_default, NULL, InterfaceID, enum_result_callback, request);
3167
+ if (err) mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
3168
+ else request->terminate = enum_termination_callback;
3169
+ }
3170
+
3171
+ return(err);
3172
+ }
3173
+
3174
+ // ***************************************************************************
3175
+ #if COMPILER_LIKES_PRAGMA_MARK
3176
+ #pragma mark -
3177
+ #pragma mark - DNSServiceReconfirmRecord & Misc
3178
+ #endif
3179
+
3180
+ mDNSlocal mStatus handle_reconfirm_request(request_state *request)
3181
+ {
3182
+ mStatus status = mStatus_BadParamErr;
3183
+ AuthRecord *rr = read_rr_from_ipc_msg(request, 0, 0);
3184
+ if (rr)
3185
+ {
3186
+ status = mDNS_ReconfirmByValue(&mDNSStorage, &rr->resrec);
3187
+ LogOperation(
3188
+ (status == mStatus_NoError) ?
3189
+ "%3d: DNSServiceReconfirmRecord(%s) interface %d initiated" :
3190
+ "%3d: DNSServiceReconfirmRecord(%s) interface %d failed: %d",
3191
+ request->sd, RRDisplayString(&mDNSStorage, &rr->resrec),
3192
+ mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, rr->resrec.InterfaceID, mDNSfalse), status);
3193
+ freeL("AuthRecord/handle_reconfirm_request", rr);
3194
+ }
3195
+ return(status);
3196
+ }
3197
+
3198
+ mDNSlocal mStatus handle_setdomain_request(request_state *request)
3199
+ {
3200
+ char domainstr[MAX_ESCAPED_DOMAIN_NAME];
3201
+ domainname domain;
3202
+ DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
3203
+ (void)flags; // Unused
3204
+ if (get_string(&request->msgptr, request->msgend, domainstr, MAX_ESCAPED_DOMAIN_NAME) < 0 ||
3205
+ !MakeDomainNameFromDNSNameString(&domain, domainstr))
3206
+ { LogMsg("%3d: DNSServiceSetDefaultDomainForUser(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
3207
+
3208
+ LogOperation("%3d: DNSServiceSetDefaultDomainForUser(%##s)", request->sd, domain.c);
3209
+ return(mStatus_NoError);
3210
+ }
3211
+
3212
+ typedef packedstruct
3213
+ {
3214
+ mStatus err;
3215
+ mDNSu32 len;
3216
+ mDNSu32 vers;
3217
+ } DaemonVersionReply;
3218
+
3219
+ mDNSlocal void handle_getproperty_request(request_state *request)
3220
+ {
3221
+ const mStatus BadParamErr = dnssd_htonl((mDNSu32)mStatus_BadParamErr);
3222
+ char prop[256];
3223
+ if (get_string(&request->msgptr, request->msgend, prop, sizeof(prop)) >= 0)
3224
+ {
3225
+ LogOperation("%3d: DNSServiceGetProperty(%s)", request->sd, prop);
3226
+ if (!strcmp(prop, kDNSServiceProperty_DaemonVersion))
3227
+ {
3228
+ DaemonVersionReply x = { 0, dnssd_htonl(4), dnssd_htonl(_DNS_SD_H) };
3229
+ send_all(request->sd, (const char *)&x, sizeof(x));
3230
+ return;
3231
+ }
3232
+ }
3233
+
3234
+ // If we didn't recogize the requested property name, return BadParamErr
3235
+ send_all(request->sd, (const char *)&BadParamErr, sizeof(BadParamErr));
3236
+ }
3237
+
3238
+ // ***************************************************************************
3239
+ #if COMPILER_LIKES_PRAGMA_MARK
3240
+ #pragma mark -
3241
+ #pragma mark - DNSServiceNATPortMappingCreate
3242
+ #endif
3243
+
3244
+ #define DNSServiceProtocol(X) ((X) == NATOp_AddrRequest ? 0 : (X) == NATOp_MapUDP ? kDNSServiceProtocol_UDP : kDNSServiceProtocol_TCP)
3245
+
3246
+ mDNSlocal void port_mapping_termination_callback(request_state *request)
3247
+ {
3248
+ LogOperation("%3d: DNSServiceNATPortMappingCreate(%X, %u, %u, %d) STOP", request->sd,
3249
+ DNSServiceProtocol(request->u.pm.NATinfo.Protocol),
3250
+ mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease);
3251
+ mDNS_StopNATOperation(&mDNSStorage, &request->u.pm.NATinfo);
3252
+ }
3253
+
3254
+ // Called via function pointer when we get a NAT-PMP address request or port mapping response
3255
+ mDNSlocal void port_mapping_create_request_callback(mDNS *m, NATTraversalInfo *n)
3256
+ {
3257
+ request_state *request = (request_state *)n->clientContext;
3258
+ reply_state *rep;
3259
+ int replyLen;
3260
+ char *data;
3261
+
3262
+ if (!request) { LogMsg("port_mapping_create_request_callback called with unknown request_state object"); return; }
3263
+
3264
+ // calculate reply data length
3265
+ replyLen = sizeof(DNSServiceFlags);
3266
+ replyLen += 3 * sizeof(mDNSu32); // if index + addr + ttl
3267
+ replyLen += sizeof(DNSServiceErrorType);
3268
+ replyLen += 2 * sizeof(mDNSu16); // Internal Port + External Port
3269
+ replyLen += sizeof(mDNSu8); // protocol
3270
+
3271
+ rep = create_reply(port_mapping_reply_op, replyLen, request);
3272
+
3273
+ rep->rhdr->flags = dnssd_htonl(0);
3274
+ rep->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, n->InterfaceID, mDNSfalse));
3275
+ rep->rhdr->error = dnssd_htonl(n->Result);
3276
+
3277
+ data = (char *)&rep->rhdr[1];
3278
+
3279
+ *data++ = request->u.pm.NATinfo.ExternalAddress.b[0];
3280
+ *data++ = request->u.pm.NATinfo.ExternalAddress.b[1];
3281
+ *data++ = request->u.pm.NATinfo.ExternalAddress.b[2];
3282
+ *data++ = request->u.pm.NATinfo.ExternalAddress.b[3];
3283
+ *data++ = DNSServiceProtocol(request->u.pm.NATinfo.Protocol);
3284
+ *data++ = request->u.pm.NATinfo.IntPort.b[0];
3285
+ *data++ = request->u.pm.NATinfo.IntPort.b[1];
3286
+ *data++ = request->u.pm.NATinfo.ExternalPort.b[0];
3287
+ *data++ = request->u.pm.NATinfo.ExternalPort.b[1];
3288
+ put_uint32(request->u.pm.NATinfo.Lifetime, &data);
3289
+
3290
+ LogOperation("%3d: DNSServiceNATPortMappingCreate(%X, %u, %u, %d) RESULT %.4a:%u TTL %u", request->sd,
3291
+ DNSServiceProtocol(request->u.pm.NATinfo.Protocol),
3292
+ mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease,
3293
+ &request->u.pm.NATinfo.ExternalAddress, mDNSVal16(request->u.pm.NATinfo.ExternalPort), request->u.pm.NATinfo.Lifetime);
3294
+
3295
+ append_reply(request, rep);
3296
+ }
3297
+
3298
+ mDNSlocal mStatus handle_port_mapping_request(request_state *request)
3299
+ {
3300
+ mDNSu32 ttl = 0;
3301
+ mStatus err = mStatus_NoError;
3302
+
3303
+ DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
3304
+ mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
3305
+ mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
3306
+ mDNSu8 protocol = (mDNSu8)get_uint32(&request->msgptr, request->msgend);
3307
+ (void)flags; // Unused
3308
+ if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr);
3309
+ if (request->msgptr + 8 > request->msgend) request->msgptr = NULL;
3310
+ else
3311
+ {
3312
+ request->u.pm.NATinfo.IntPort.b[0] = *request->msgptr++;
3313
+ request->u.pm.NATinfo.IntPort.b[1] = *request->msgptr++;
3314
+ request->u.pm.ReqExt.b[0] = *request->msgptr++;
3315
+ request->u.pm.ReqExt.b[1] = *request->msgptr++;
3316
+ ttl = get_uint32(&request->msgptr, request->msgend);
3317
+ }
3318
+
3319
+ if (!request->msgptr)
3320
+ { LogMsg("%3d: DNSServiceNATPortMappingCreate(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
3321
+
3322
+ if (protocol == 0) // If protocol == 0 (i.e. just request public address) then IntPort, ExtPort, ttl must be zero too
3323
+ {
3324
+ if (!mDNSIPPortIsZero(request->u.pm.NATinfo.IntPort) || !mDNSIPPortIsZero(request->u.pm.ReqExt) || ttl) return(mStatus_BadParamErr);
3325
+ }
3326
+ else
3327
+ {
3328
+ if (mDNSIPPortIsZero(request->u.pm.NATinfo.IntPort)) return(mStatus_BadParamErr);
3329
+ if (!(protocol & (kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP))) return(mStatus_BadParamErr);
3330
+ }
3331
+
3332
+ request->u.pm.NATinfo.Protocol = !protocol ? NATOp_AddrRequest : (protocol == kDNSServiceProtocol_UDP) ? NATOp_MapUDP : NATOp_MapTCP;
3333
+ // u.pm.NATinfo.IntPort = already set above
3334
+ request->u.pm.NATinfo.RequestedPort = request->u.pm.ReqExt;
3335
+ request->u.pm.NATinfo.NATLease = ttl;
3336
+ request->u.pm.NATinfo.clientCallback = port_mapping_create_request_callback;
3337
+ request->u.pm.NATinfo.clientContext = request;
3338
+
3339
+ LogOperation("%3d: DNSServiceNATPortMappingCreate(%X, %u, %u, %d) START", request->sd,
3340
+ protocol, mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease);
3341
+ err = mDNS_StartNATOperation(&mDNSStorage, &request->u.pm.NATinfo);
3342
+ if (err) LogMsg("ERROR: mDNS_StartNATOperation: %d", (int)err);
3343
+ else request->terminate = port_mapping_termination_callback;
3344
+
3345
+ return(err);
3346
+ }
3347
+
3348
+ // ***************************************************************************
3349
+ #if COMPILER_LIKES_PRAGMA_MARK
3350
+ #pragma mark -
3351
+ #pragma mark - DNSServiceGetAddrInfo
3352
+ #endif
3353
+
3354
+ mDNSlocal void addrinfo_termination_callback(request_state *request)
3355
+ {
3356
+ LogOperation("%3d: DNSServiceGetAddrInfo(%##s) STOP", request->sd, request->u.addrinfo.q4.qname.c);
3357
+
3358
+ if (request->u.addrinfo.q4.QuestionContext)
3359
+ {
3360
+ mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q4);
3361
+ request->u.addrinfo.q4.QuestionContext = mDNSNULL;
3362
+ }
3363
+ if (request->u.addrinfo.q4.qnameOrig)
3364
+ {
3365
+ freeL("QueryTermination", request->u.addrinfo.q4.qnameOrig);
3366
+ request->u.addrinfo.q4.qnameOrig = mDNSNULL;
3367
+ }
3368
+ if (request->u.addrinfo.q42)
3369
+ {
3370
+ if (request->u.addrinfo.q42->QuestionContext)
3371
+ {
3372
+ LogInfo("addrinfo_termination_callback: Stopping q42 %##s", request->u.addrinfo.q42->qname.c);
3373
+ mDNS_StopQuery(&mDNSStorage, request->u.addrinfo.q42);
3374
+ }
3375
+ if (request->u.addrinfo.q42->qnameOrig)
3376
+ {
3377
+ LogInfo("addrinfo_termination_callback: freeing q42 qnameOrig %##s", request->u.addrinfo.q42->qnameOrig->c);
3378
+ freeL("QueryTermination q42", request->u.addrinfo.q42->qnameOrig);
3379
+ request->u.addrinfo.q42->qnameOrig = mDNSNULL;
3380
+ }
3381
+ freeL("addrinfo Q42", request->u.addrinfo.q42);
3382
+ request->u.addrinfo.q42 = mDNSNULL;
3383
+ }
3384
+
3385
+ if (request->u.addrinfo.q6.QuestionContext)
3386
+ {
3387
+ mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q6);
3388
+ request->u.addrinfo.q6.QuestionContext = mDNSNULL;
3389
+ }
3390
+ if (request->u.addrinfo.q6.qnameOrig)
3391
+ {
3392
+ freeL("QueryTermination", request->u.addrinfo.q6.qnameOrig);
3393
+ request->u.addrinfo.q6.qnameOrig = mDNSNULL;
3394
+ }
3395
+ if (request->u.addrinfo.q62)
3396
+ {
3397
+ if (request->u.addrinfo.q62->QuestionContext)
3398
+ {
3399
+ LogInfo("addrinfo_termination_callback: Stopping q62 %##s", request->u.addrinfo.q62->qname.c);
3400
+ mDNS_StopQuery(&mDNSStorage, request->u.addrinfo.q62);
3401
+ }
3402
+ if (request->u.addrinfo.q62->qnameOrig)
3403
+ {
3404
+ LogInfo("addrinfo_termination_callback: freeing q62 qnameOrig %##s", request->u.addrinfo.q62->qnameOrig->c);
3405
+ freeL("QueryTermination q62", request->u.addrinfo.q62->qnameOrig);
3406
+ request->u.addrinfo.q62->qnameOrig = mDNSNULL;
3407
+ }
3408
+ freeL("addrinfo Q62", request->u.addrinfo.q62);
3409
+ request->u.addrinfo.q62 = mDNSNULL;
3410
+ }
3411
+ }
3412
+
3413
+ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
3414
+ {
3415
+ char hostname[256];
3416
+ domainname d;
3417
+ mStatus err = 0;
3418
+
3419
+ DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
3420
+ mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
3421
+
3422
+ mDNSPlatformMemZero(&request->u.addrinfo, sizeof(request->u.addrinfo));
3423
+ request->u.addrinfo.interface_id = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
3424
+ request->u.addrinfo.flags = flags;
3425
+ request->u.addrinfo.protocol = get_uint32(&request->msgptr, request->msgend);
3426
+
3427
+ if (interfaceIndex && !request->u.addrinfo.interface_id) return(mStatus_BadParamErr);
3428
+ if (request->u.addrinfo.protocol > (kDNSServiceProtocol_IPv4|kDNSServiceProtocol_IPv6)) return(mStatus_BadParamErr);
3429
+
3430
+ if (get_string(&request->msgptr, request->msgend, hostname, 256) < 0) return(mStatus_BadParamErr);
3431
+
3432
+ if (!request->msgptr) { LogMsg("%3d: DNSServiceGetAddrInfo(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
3433
+
3434
+ if (!MakeDomainNameFromDNSNameString(&d, hostname))
3435
+ { LogMsg("ERROR: handle_addrinfo_request: bad hostname: %s", hostname); return(mStatus_BadParamErr); }
3436
+
3437
+ #if 0
3438
+ if (!AuthorizedDomain(request, &d, AutoBrowseDomains)) return (mStatus_NoError);
3439
+ #endif
3440
+
3441
+ if (!request->u.addrinfo.protocol)
3442
+ {
3443
+ flags |= kDNSServiceFlagsSuppressUnusable;
3444
+ request->u.addrinfo.protocol = (kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6);
3445
+ }
3446
+
3447
+ request->u.addrinfo.q4.InterfaceID = request->u.addrinfo.q6.InterfaceID = request->u.addrinfo.interface_id;
3448
+ request->u.addrinfo.q4.Target = request->u.addrinfo.q6.Target = zeroAddr;
3449
+ request->u.addrinfo.q4.qname = request->u.addrinfo.q6.qname = d;
3450
+ request->u.addrinfo.q4.qclass = request->u.addrinfo.q6.qclass = kDNSServiceClass_IN;
3451
+ request->u.addrinfo.q4.LongLived = request->u.addrinfo.q6.LongLived = (flags & kDNSServiceFlagsLongLivedQuery ) != 0;
3452
+ request->u.addrinfo.q4.ExpectUnique = request->u.addrinfo.q6.ExpectUnique = mDNSfalse;
3453
+ request->u.addrinfo.q4.ForceMCast = request->u.addrinfo.q6.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
3454
+ request->u.addrinfo.q4.ReturnIntermed = request->u.addrinfo.q6.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
3455
+ request->u.addrinfo.q4.SuppressUnusable = request->u.addrinfo.q6.SuppressUnusable = (flags & kDNSServiceFlagsSuppressUnusable ) != 0;
3456
+ request->u.addrinfo.q4.TimeoutQuestion = request->u.addrinfo.q6.TimeoutQuestion = (flags & kDNSServiceFlagsTimeout ) != 0;
3457
+ request->u.addrinfo.q4.WakeOnResolve = request->u.addrinfo.q6.WakeOnResolve = 0;
3458
+ request->u.addrinfo.q4.qnameOrig = request->u.addrinfo.q6.qnameOrig = mDNSNULL;
3459
+
3460
+ if (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv4)
3461
+ {
3462
+ request->u.addrinfo.q4.qtype = kDNSServiceType_A;
3463
+ request->u.addrinfo.q4.SearchListIndex = 0;
3464
+
3465
+ // We append search domains only for queries that are a single label. If overriden using
3466
+ // command line argument "AlwaysAppendSearchDomains", then we do it for any query which
3467
+ // is not fully qualified.
3468
+ if (hostname[strlen(hostname) - 1] != '.' && (AlwaysAppendSearchDomains || CountLabels(&d) == 1))
3469
+ {
3470
+ request->u.addrinfo.q4.AppendSearchDomains = 1;
3471
+ request->u.addrinfo.q4.AppendLocalSearchDomains = 1;
3472
+ }
3473
+ else
3474
+ {
3475
+ request->u.addrinfo.q4.AppendSearchDomains = 0;
3476
+ request->u.addrinfo.q4.AppendLocalSearchDomains = 0;
3477
+ }
3478
+ request->u.addrinfo.q4.RetryWithSearchDomains = (ApplySearchDomainsFirst(&request->u.addrinfo.q4) ? 1 : 0);
3479
+ request->u.addrinfo.q4.QuestionCallback = queryrecord_result_callback;
3480
+ request->u.addrinfo.q4.QuestionContext = request;
3481
+ err = mDNS_StartQuery(&mDNSStorage, &request->u.addrinfo.q4);
3482
+ if (err != mStatus_NoError)
3483
+ {
3484
+ LogMsg("ERROR: mDNS_StartQuery: %d", (int)err);
3485
+ request->u.addrinfo.q4.QuestionContext = mDNSNULL;
3486
+ }
3487
+ #if APPLE_OSX_mDNSResponder
3488
+ err = SendAdditionalQuery(&request->u.addrinfo.q4, request, err);
3489
+ #endif // APPLE_OSX_mDNSResponder
3490
+ }
3491
+
3492
+ if (!err && (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv6))
3493
+ {
3494
+ request->u.addrinfo.q6.qtype = kDNSServiceType_AAAA;
3495
+ request->u.addrinfo.q6.SearchListIndex = 0;
3496
+ if (hostname[strlen(hostname) - 1] != '.' && (AlwaysAppendSearchDomains || CountLabels(&d) == 1))
3497
+ {
3498
+ request->u.addrinfo.q6.AppendSearchDomains = 1;
3499
+ request->u.addrinfo.q6.AppendLocalSearchDomains = 1;
3500
+ }
3501
+ else
3502
+ {
3503
+ request->u.addrinfo.q6.AppendSearchDomains = 0;
3504
+ request->u.addrinfo.q6.AppendLocalSearchDomains = 0;
3505
+ }
3506
+ request->u.addrinfo.q6.RetryWithSearchDomains = (ApplySearchDomainsFirst(&request->u.addrinfo.q6) ? 1 : 0);
3507
+ request->u.addrinfo.q6.QuestionCallback = queryrecord_result_callback;
3508
+ request->u.addrinfo.q6.QuestionContext = request;
3509
+ err = mDNS_StartQuery(&mDNSStorage, &request->u.addrinfo.q6);
3510
+ if (err != mStatus_NoError)
3511
+ {
3512
+ LogMsg("ERROR: mDNS_StartQuery: %d", (int)err);
3513
+ request->u.addrinfo.q6.QuestionContext = mDNSNULL;
3514
+ if (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv4)
3515
+ {
3516
+ // If we started a query for IPv4, we need to cancel it
3517
+ mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q4);
3518
+ request->u.addrinfo.q4.QuestionContext = mDNSNULL;
3519
+ }
3520
+ }
3521
+ #if APPLE_OSX_mDNSResponder
3522
+ err = SendAdditionalQuery(&request->u.addrinfo.q6, request, err);
3523
+ #endif // APPLE_OSX_mDNSResponder
3524
+ }
3525
+
3526
+ LogOperation("%3d: DNSServiceGetAddrInfo(%X, %d, %d, %##s) START",
3527
+ request->sd, flags, interfaceIndex, request->u.addrinfo.protocol, d.c);
3528
+
3529
+ if (!err) request->terminate = addrinfo_termination_callback;
3530
+
3531
+ return(err);
3532
+ }
3533
+
3534
+ // ***************************************************************************
3535
+ #if COMPILER_LIKES_PRAGMA_MARK
3536
+ #pragma mark -
3537
+ #pragma mark - Main Request Handler etc.
3538
+ #endif
3539
+
3540
+ mDNSlocal request_state *NewRequest(void)
3541
+ {
3542
+ request_state **p = &all_requests;
3543
+ while (*p) p=&(*p)->next;
3544
+ *p = mallocL("request_state", sizeof(request_state));
3545
+ if (!*p) FatalError("ERROR: malloc");
3546
+ mDNSPlatformMemZero(*p, sizeof(request_state));
3547
+ return(*p);
3548
+ }
3549
+
3550
+ // read_msg may be called any time when the transfer state (req->ts) is t_morecoming.
3551
+ // if there is no data on the socket, the socket will be closed and t_terminated will be returned
3552
+ mDNSlocal void read_msg(request_state *req)
3553
+ {
3554
+ if (req->ts == t_terminated || req->ts == t_error)
3555
+ { LogMsg("%3d: ERROR: read_msg called with transfer state terminated or error", req->sd); req->ts = t_error; return; }
3556
+
3557
+ if (req->ts == t_complete) // this must be death or something is wrong
3558
+ {
3559
+ char buf[4]; // dummy for death notification
3560
+ int nread = udsSupportReadFD(req->sd, buf, 4, 0, req->platform_data);
3561
+ if (!nread) { req->ts = t_terminated; return; }
3562
+ if (nread < 0) goto rerror;
3563
+ LogMsg("%3d: ERROR: read data from a completed request", req->sd);
3564
+ req->ts = t_error;
3565
+ return;
3566
+ }
3567
+
3568
+ if (req->ts != t_morecoming)
3569
+ { LogMsg("%3d: ERROR: read_msg called with invalid transfer state (%d)", req->sd, req->ts); req->ts = t_error; return; }
3570
+
3571
+ if (req->hdr_bytes < sizeof(ipc_msg_hdr))
3572
+ {
3573
+ mDNSu32 nleft = sizeof(ipc_msg_hdr) - req->hdr_bytes;
3574
+ int nread = udsSupportReadFD(req->sd, (char *)&req->hdr + req->hdr_bytes, nleft, 0, req->platform_data);
3575
+ if (nread == 0) { req->ts = t_terminated; return; }
3576
+ if (nread < 0) goto rerror;
3577
+ req->hdr_bytes += nread;
3578
+ if (req->hdr_bytes > sizeof(ipc_msg_hdr))
3579
+ { LogMsg("%3d: ERROR: read_msg - read too many header bytes", req->sd); req->ts = t_error; return; }
3580
+
3581
+ // only read data if header is complete
3582
+ if (req->hdr_bytes == sizeof(ipc_msg_hdr))
3583
+ {
3584
+ ConvertHeaderBytes(&req->hdr);
3585
+ if (req->hdr.version != VERSION)
3586
+ { LogMsg("%3d: ERROR: client version 0x%08X daemon version 0x%08X", req->sd, req->hdr.version, VERSION); req->ts = t_error; return; }
3587
+
3588
+ // Largest conceivable single request is a DNSServiceRegisterRecord() or DNSServiceAddRecord()
3589
+ // with 64kB of rdata. Adding 1009 byte for a maximal domain name, plus a safety margin
3590
+ // for other overhead, this means any message above 70kB is definitely bogus.
3591
+ if (req->hdr.datalen > 70000)
3592
+ { LogMsg("%3d: ERROR: read_msg: hdr.datalen %u (0x%X) > 70000", req->sd, req->hdr.datalen, req->hdr.datalen); req->ts = t_error; return; }
3593
+ req->msgbuf = mallocL("request_state msgbuf", req->hdr.datalen + MSG_PAD_BYTES);
3594
+ if (!req->msgbuf) { my_perror("ERROR: malloc"); req->ts = t_error; return; }
3595
+ req->msgptr = req->msgbuf;
3596
+ req->msgend = req->msgbuf + req->hdr.datalen;
3597
+ mDNSPlatformMemZero(req->msgbuf, req->hdr.datalen + MSG_PAD_BYTES);
3598
+ }
3599
+ }
3600
+
3601
+ // If our header is complete, but we're still needing more body data, then try to read it now
3602
+ // Note: For cancel_request req->hdr.datalen == 0, but there's no error return socket for cancel_request
3603
+ // Any time we need to get the error return socket we know we'll have at least one data byte
3604
+ // (even if only the one-byte empty C string placeholder for the old ctrl_path parameter)
3605
+ if (req->hdr_bytes == sizeof(ipc_msg_hdr) && req->data_bytes < req->hdr.datalen)
3606
+ {
3607
+ mDNSu32 nleft = req->hdr.datalen - req->data_bytes;
3608
+ int nread;
3609
+ #if !defined(_WIN32)
3610
+ struct iovec vec = { req->msgbuf + req->data_bytes, nleft }; // Tell recvmsg where we want the bytes put
3611
+ struct msghdr msg;
3612
+ struct cmsghdr *cmsg;
3613
+ char cbuf[CMSG_SPACE(sizeof(dnssd_sock_t))];
3614
+ msg.msg_name = 0;
3615
+ msg.msg_namelen = 0;
3616
+ msg.msg_iov = &vec;
3617
+ msg.msg_iovlen = 1;
3618
+ msg.msg_control = cbuf;
3619
+ msg.msg_controllen = sizeof(cbuf);
3620
+ msg.msg_flags = 0;
3621
+ nread = recvmsg(req->sd, &msg, 0);
3622
+ #else
3623
+ nread = udsSupportReadFD(req->sd, (char *)req->msgbuf + req->data_bytes, nleft, 0, req->platform_data);
3624
+ #endif
3625
+ if (nread == 0) { req->ts = t_terminated; return; }
3626
+ if (nread < 0) goto rerror;
3627
+ req->data_bytes += nread;
3628
+ if (req->data_bytes > req->hdr.datalen)
3629
+ { LogMsg("%3d: ERROR: read_msg - read too many data bytes", req->sd); req->ts = t_error; return; }
3630
+ #if !defined(_WIN32)
3631
+ cmsg = CMSG_FIRSTHDR(&msg);
3632
+ #if DEBUG_64BIT_SCM_RIGHTS
3633
+ LogMsg("%3d: Expecting %d %d %d %d", req->sd, sizeof(cbuf), sizeof(cbuf), SOL_SOCKET, SCM_RIGHTS);
3634
+ LogMsg("%3d: Got %d %d %d %d", req->sd, msg.msg_controllen, cmsg->cmsg_len, cmsg->cmsg_level, cmsg->cmsg_type);
3635
+ #endif // DEBUG_64BIT_SCM_RIGHTS
3636
+ if (msg.msg_controllen == sizeof(cbuf) &&
3637
+ cmsg->cmsg_len == CMSG_LEN(sizeof(dnssd_sock_t)) &&
3638
+ cmsg->cmsg_level == SOL_SOCKET &&
3639
+ cmsg->cmsg_type == SCM_RIGHTS)
3640
+ {
3641
+ #if APPLE_OSX_mDNSResponder
3642
+ // Strictly speaking BPF_fd belongs solely in the platform support layer, but because
3643
+ // of privilege separation on Mac OS X we need to get BPF_fd from mDNSResponderHelper,
3644
+ // and it's convenient to repurpose the existing fd-passing code here for that task
3645
+ if (req->hdr.op == send_bpf)
3646
+ {
3647
+ dnssd_sock_t x = *(dnssd_sock_t *)CMSG_DATA(cmsg);
3648
+ LogOperation("%3d: Got BPF %d", req->sd, x);
3649
+ mDNSPlatformReceiveBPF_fd(&mDNSStorage, x);
3650
+ }
3651
+ else
3652
+ #endif // APPLE_OSX_mDNSResponder
3653
+ req->errsd = *(dnssd_sock_t *)CMSG_DATA(cmsg);
3654
+ #if DEBUG_64BIT_SCM_RIGHTS
3655
+ LogMsg("%3d: read req->errsd %d", req->sd, req->errsd);
3656
+ #endif // DEBUG_64BIT_SCM_RIGHTS
3657
+ if (req->data_bytes < req->hdr.datalen)
3658
+ {
3659
+ LogMsg("%3d: Client sent error socket %d via SCM_RIGHTS with req->data_bytes %d < req->hdr.datalen %d",
3660
+ req->sd, req->errsd, req->data_bytes, req->hdr.datalen);
3661
+ req->ts = t_error;
3662
+ return;
3663
+ }
3664
+ }
3665
+ #endif
3666
+ }
3667
+
3668
+ // If our header and data are both complete, see if we need to make our separate error return socket
3669
+ if (req->hdr_bytes == sizeof(ipc_msg_hdr) && req->data_bytes == req->hdr.datalen)
3670
+ {
3671
+ if (req->terminate && req->hdr.op != cancel_request)
3672
+ {
3673
+ dnssd_sockaddr_t cliaddr;
3674
+ #if defined(USE_TCP_LOOPBACK)
3675
+ mDNSOpaque16 port;
3676
+ u_long opt = 1;
3677
+ port.b[0] = req->msgptr[0];
3678
+ port.b[1] = req->msgptr[1];
3679
+ req->msgptr += 2;
3680
+ cliaddr.sin_family = AF_INET;
3681
+ cliaddr.sin_port = port.NotAnInteger;
3682
+ cliaddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
3683
+ #else
3684
+ char ctrl_path[MAX_CTLPATH];
3685
+ get_string(&req->msgptr, req->msgend, ctrl_path, MAX_CTLPATH); // path is first element in message buffer
3686
+ mDNSPlatformMemZero(&cliaddr, sizeof(cliaddr));
3687
+ cliaddr.sun_family = AF_LOCAL;
3688
+ mDNSPlatformStrCopy(cliaddr.sun_path, ctrl_path);
3689
+ // If the error return path UDS name is empty string, that tells us
3690
+ // that this is a new version of the library that's going to pass us
3691
+ // the error return path socket via sendmsg/recvmsg
3692
+ if (ctrl_path[0] == 0)
3693
+ {
3694
+ if (req->errsd == req->sd)
3695
+ { LogMsg("%3d: read_msg: ERROR failed to get errsd via SCM_RIGHTS", req->sd); req->ts = t_error; return; }
3696
+ goto got_errfd;
3697
+ }
3698
+ #endif
3699
+
3700
+ req->errsd = socket(AF_DNSSD, SOCK_STREAM, 0);
3701
+ if (!dnssd_SocketValid(req->errsd)) { my_perror("ERROR: socket"); req->ts = t_error; return; }
3702
+
3703
+ if (connect(req->errsd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0)
3704
+ {
3705
+ #if !defined(USE_TCP_LOOPBACK)
3706
+ struct stat sb;
3707
+ LogMsg("%3d: read_msg: Couldn't connect to error return path socket “%s” errno %d (%s)",
3708
+ req->sd, cliaddr.sun_path, dnssd_errno, dnssd_strerror(dnssd_errno));
3709
+ if (stat(cliaddr.sun_path, &sb) < 0)
3710
+ LogMsg("%3d: read_msg: stat failed “%s” errno %d (%s)", req->sd, cliaddr.sun_path, dnssd_errno, dnssd_strerror(dnssd_errno));
3711
+ else
3712
+ LogMsg("%3d: read_msg: file “%s” mode %o (octal) uid %d gid %d", req->sd, cliaddr.sun_path, sb.st_mode, sb.st_uid, sb.st_gid);
3713
+ #endif
3714
+ req->ts = t_error;
3715
+ return;
3716
+ }
3717
+
3718
+ #if !defined(USE_TCP_LOOPBACK)
3719
+ got_errfd:
3720
+ #endif
3721
+ LogOperation("%3d: Error socket %d created %08X %08X", req->sd, req->errsd, req->hdr.client_context.u32[1], req->hdr.client_context.u32[0]);
3722
+ #if defined(_WIN32)
3723
+ if (ioctlsocket(req->errsd, FIONBIO, &opt) != 0)
3724
+ #else
3725
+ if (fcntl(req->errsd, F_SETFL, fcntl(req->errsd, F_GETFL, 0) | O_NONBLOCK) != 0)
3726
+ #endif
3727
+ {
3728
+ LogMsg("%3d: ERROR: could not set control socket to non-blocking mode errno %d (%s)",
3729
+ req->sd, dnssd_errno, dnssd_strerror(dnssd_errno));
3730
+ req->ts = t_error;
3731
+ return;
3732
+ }
3733
+ }
3734
+
3735
+ req->ts = t_complete;
3736
+ }
3737
+
3738
+ return;
3739
+
3740
+ rerror:
3741
+ if (dnssd_errno == dnssd_EWOULDBLOCK || dnssd_errno == dnssd_EINTR) return;
3742
+ LogMsg("%3d: ERROR: read_msg errno %d (%s)", req->sd, dnssd_errno, dnssd_strerror(dnssd_errno));
3743
+ req->ts = t_error;
3744
+ }
3745
+
3746
+ #define RecordOrientedOp(X) \
3747
+ ((X) == reg_record_request || (X) == add_record_request || (X) == update_record_request || (X) == remove_record_request)
3748
+
3749
+ // The lightweight operations are the ones that don't need a dedicated request_state structure allocated for them
3750
+ #define LightweightOp(X) (RecordOrientedOp(X) || (X) == cancel_request)
3751
+
3752
+ mDNSlocal void request_callback(int fd, short filter, void *info)
3753
+ {
3754
+ mStatus err = 0;
3755
+ request_state *req = info;
3756
+ mDNSs32 min_size = sizeof(DNSServiceFlags);
3757
+ (void)fd; // Unused
3758
+ (void)filter; // Unused
3759
+
3760
+ for (;;)
3761
+ {
3762
+ read_msg(req);
3763
+ if (req->ts == t_morecoming) return;
3764
+ if (req->ts == t_terminated || req->ts == t_error) { AbortUnlinkAndFree(req); return; }
3765
+ if (req->ts != t_complete) { LogMsg("req->ts %d != t_complete", req->ts); AbortUnlinkAndFree(req); return; }
3766
+
3767
+ if (req->hdr.version != VERSION)
3768
+ {
3769
+ LogMsg("ERROR: client version %d incompatible with daemon version %d", req->hdr.version, VERSION);
3770
+ AbortUnlinkAndFree(req);
3771
+ return;
3772
+ }
3773
+
3774
+ switch(req->hdr.op) // Interface + other data
3775
+ {
3776
+ case connection_request: min_size = 0; break;
3777
+ case reg_service_request: min_size += sizeof(mDNSu32) + 4 /* name, type, domain, host */ + 4 /* port, textlen */; break;
3778
+ case add_record_request: min_size += 4 /* type, rdlen */ + 4 /* ttl */; break;
3779
+ case update_record_request: min_size += 2 /* rdlen */ + 4 /* ttl */; break;
3780
+ case remove_record_request: break;
3781
+ case browse_request: min_size += sizeof(mDNSu32) + 2 /* type, domain */; break;
3782
+ case resolve_request: min_size += sizeof(mDNSu32) + 3 /* type, type, domain */; break;
3783
+ case query_request: min_size += sizeof(mDNSu32) + 1 /* name */ + 4 /* type, class*/; break;
3784
+ case enumeration_request: min_size += sizeof(mDNSu32); break;
3785
+ case reg_record_request: min_size += sizeof(mDNSu32) + 1 /* name */ + 6 /* type, class, rdlen */ + 4 /* ttl */; break;
3786
+ case reconfirm_record_request: min_size += sizeof(mDNSu32) + 1 /* name */ + 6 /* type, class, rdlen */; break;
3787
+ case setdomain_request: min_size += 1 /* domain */; break;
3788
+ case getproperty_request: min_size = 2; break;
3789
+ case port_mapping_request: min_size += sizeof(mDNSu32) + 4 /* udp/tcp */ + 4 /* int/ext port */ + 4 /* ttl */; break;
3790
+ case addrinfo_request: min_size += sizeof(mDNSu32) + 4 /* v4/v6 */ + 1 /* hostname */; break;
3791
+ case send_bpf: // Same as cancel_request below
3792
+ case cancel_request: min_size = 0; break;
3793
+ case sethost_request: min_size = sizeof(mDNSu32) + 1 /* hostname */; break;
3794
+ default: LogMsg("ERROR: validate_message - unsupported req type: %d", req->hdr.op); min_size = -1; break;
3795
+ }
3796
+
3797
+ if ((mDNSs32)req->data_bytes < min_size)
3798
+ { LogMsg("Invalid message %d bytes; min for %d is %d", req->data_bytes, req->hdr.op, min_size); AbortUnlinkAndFree(req); return; }
3799
+
3800
+ if (LightweightOp(req->hdr.op) && !req->terminate)
3801
+ { LogMsg("Reg/Add/Update/Remove %d require existing connection", req->hdr.op); AbortUnlinkAndFree(req); return; }
3802
+
3803
+ // check if client wants silent operation
3804
+ if (req->hdr.ipc_flags & IPC_FLAGS_NOREPLY) req->no_reply = 1;
3805
+
3806
+ // If req->terminate is already set, this means this operation is sharing an existing connection
3807
+ if (req->terminate && !LightweightOp(req->hdr.op))
3808
+ {
3809
+ request_state *newreq = NewRequest();
3810
+ newreq->primary = req;
3811
+ newreq->sd = req->sd;
3812
+ newreq->errsd = req->errsd;
3813
+ newreq->uid = req->uid;
3814
+ newreq->hdr = req->hdr;
3815
+ newreq->msgbuf = req->msgbuf;
3816
+ newreq->msgptr = req->msgptr;
3817
+ newreq->msgend = req->msgend;
3818
+ req = newreq;
3819
+ }
3820
+
3821
+ // If we're shutting down, don't allow new client requests
3822
+ // We do allow "cancel" and "getproperty" during shutdown
3823
+ if (mDNSStorage.ShutdownTime && req->hdr.op != cancel_request && req->hdr.op != getproperty_request)
3824
+ {
3825
+ err = mStatus_ServiceNotRunning;
3826
+ }
3827
+ else switch(req->hdr.op)
3828
+ {
3829
+ // These are all operations that have their own first-class request_state object
3830
+ case connection_request: LogOperation("%3d: DNSServiceCreateConnection START", req->sd);
3831
+ req->terminate = connection_termination; break;
3832
+ case resolve_request: err = handle_resolve_request (req); break;
3833
+ case query_request: err = handle_queryrecord_request (req); break;
3834
+ case browse_request: err = handle_browse_request (req); break;
3835
+ case reg_service_request: err = handle_regservice_request (req); break;
3836
+ case enumeration_request: err = handle_enum_request (req); break;
3837
+ case reconfirm_record_request: err = handle_reconfirm_request (req); break;
3838
+ case setdomain_request: err = handle_setdomain_request (req); break;
3839
+ case getproperty_request: handle_getproperty_request (req); break;
3840
+ case port_mapping_request: err = handle_port_mapping_request(req); break;
3841
+ case addrinfo_request: err = handle_addrinfo_request (req); break;
3842
+ case send_bpf: /* Do nothing for send_bpf */ break;
3843
+
3844
+ // These are all operations that work with an existing request_state object
3845
+ case reg_record_request: err = handle_regrecord_request (req); break;
3846
+ case add_record_request: err = handle_add_request (req); break;
3847
+ case update_record_request: err = handle_update_request (req); break;
3848
+ case remove_record_request: err = handle_removerecord_request(req); break;
3849
+ case cancel_request: handle_cancel_request (req); break;
3850
+ case sethost_request: err = handle_sethost_request (req); break;
3851
+ default: LogMsg("%3d: ERROR: Unsupported UDS req: %d", req->sd, req->hdr.op);
3852
+ }
3853
+
3854
+ // req->msgbuf may be NULL, e.g. for connection_request or remove_record_request
3855
+ if (req->msgbuf) freeL("request_state msgbuf", req->msgbuf);
3856
+
3857
+ // There's no return data for a cancel request (DNSServiceRefDeallocate returns no result)
3858
+ // For a DNSServiceGetProperty call, the handler already generated the response, so no need to do it again here
3859
+ if (req->hdr.op != cancel_request && req->hdr.op != getproperty_request && req->hdr.op != send_bpf)
3860
+ {
3861
+ const mStatus err_netorder = dnssd_htonl(err);
3862
+ send_all(req->errsd, (const char *)&err_netorder, sizeof(err_netorder));
3863
+ if (req->errsd != req->sd)
3864
+ {
3865
+ LogOperation("%3d: Error socket %d closed %08X %08X (%d)",
3866
+ req->sd, req->errsd, req->hdr.client_context.u32[1], req->hdr.client_context.u32[0], err);
3867
+ dnssd_close(req->errsd);
3868
+ req->errsd = req->sd;
3869
+ // Also need to reset the parent's errsd, if this is a subordinate operation
3870
+ if (req->primary) req->primary->errsd = req->primary->sd;
3871
+ }
3872
+ }
3873
+
3874
+ // Reset ready to accept the next req on this pipe
3875
+ if (req->primary) req = req->primary;
3876
+ req->ts = t_morecoming;
3877
+ req->hdr_bytes = 0;
3878
+ req->data_bytes = 0;
3879
+ req->msgbuf = mDNSNULL;
3880
+ req->msgptr = mDNSNULL;
3881
+ req->msgend = 0;
3882
+ }
3883
+ }
3884
+
3885
+ mDNSlocal void connect_callback(int fd, short filter, void *info)
3886
+ {
3887
+ dnssd_sockaddr_t cliaddr;
3888
+ dnssd_socklen_t len = (dnssd_socklen_t) sizeof(cliaddr);
3889
+ dnssd_sock_t sd = accept(fd, (struct sockaddr*) &cliaddr, &len);
3890
+ #if defined(SO_NOSIGPIPE) || defined(_WIN32)
3891
+ unsigned long optval = 1;
3892
+ #endif
3893
+
3894
+ (void)filter; // Unused
3895
+ (void)info; // Unused
3896
+
3897
+ if (!dnssd_SocketValid(sd))
3898
+ {
3899
+ if (dnssd_errno != dnssd_EWOULDBLOCK) my_perror("ERROR: accept");
3900
+ return;
3901
+ }
3902
+
3903
+ #ifdef SO_NOSIGPIPE
3904
+ // Some environments (e.g. OS X) support turning off SIGPIPE for a socket
3905
+ if (setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
3906
+ LogMsg("%3d: WARNING: setsockopt - SO_NOSIGPIPE %d (%s)", sd, dnssd_errno, dnssd_strerror(dnssd_errno));
3907
+ #endif
3908
+
3909
+ #if defined(_WIN32)
3910
+ if (ioctlsocket(sd, FIONBIO, &optval) != 0)
3911
+ #else
3912
+ if (fcntl(sd, F_SETFL, fcntl(sd, F_GETFL, 0) | O_NONBLOCK) != 0)
3913
+ #endif
3914
+ {
3915
+ my_perror("ERROR: fcntl(sd, F_SETFL, O_NONBLOCK) - aborting client");
3916
+ dnssd_close(sd);
3917
+ return;
3918
+ }
3919
+ else
3920
+ {
3921
+ request_state *request = NewRequest();
3922
+ request->ts = t_morecoming;
3923
+ request->sd = sd;
3924
+ request->errsd = sd;
3925
+ #if APPLE_OSX_mDNSResponder
3926
+ struct xucred x;
3927
+ socklen_t xucredlen = sizeof(x);
3928
+ if (getsockopt(sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 && x.cr_version == XUCRED_VERSION) request->uid = x.cr_uid;
3929
+ else my_perror("ERROR: getsockopt, LOCAL_PEERCRED");
3930
+ debugf("LOCAL_PEERCRED %d %u %u %d", xucredlen, x.cr_version, x.cr_uid, x.cr_ngroups);
3931
+ #endif // APPLE_OSX_mDNSResponder
3932
+ LogOperation("%3d: Adding FD for uid %u", request->sd, request->uid);
3933
+ udsSupportAddFDToEventLoop(sd, request_callback, request, &request->platform_data);
3934
+ }
3935
+ }
3936
+
3937
+ mDNSlocal mDNSBool uds_socket_setup(dnssd_sock_t skt)
3938
+ {
3939
+ #if defined(SO_NP_EXTENSIONS)
3940
+ struct so_np_extensions sonpx;
3941
+ socklen_t optlen = sizeof(struct so_np_extensions);
3942
+ sonpx.npx_flags = SONPX_SETOPTSHUT;
3943
+ sonpx.npx_mask = SONPX_SETOPTSHUT;
3944
+ if (setsockopt(skt, SOL_SOCKET, SO_NP_EXTENSIONS, &sonpx, optlen) < 0)
3945
+ my_perror("WARNING: could not set sockopt - SO_NP_EXTENSIONS");
3946
+ #endif
3947
+ #if defined(_WIN32)
3948
+ // SEH: do we even need to do this on windows?
3949
+ // This socket will be given to WSAEventSelect which will automatically set it to non-blocking
3950
+ u_long opt = 1;
3951
+ if (ioctlsocket(skt, FIONBIO, &opt) != 0)
3952
+ #else
3953
+ if (fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK) != 0)
3954
+ #endif
3955
+ {
3956
+ my_perror("ERROR: could not set listen socket to non-blocking mode");
3957
+ return mDNSfalse;
3958
+ }
3959
+
3960
+ if (listen(skt, LISTENQ) != 0)
3961
+ {
3962
+ my_perror("ERROR: could not listen on listen socket");
3963
+ return mDNSfalse;
3964
+ }
3965
+
3966
+ if (mStatus_NoError != udsSupportAddFDToEventLoop(skt, connect_callback, (void *) NULL, (void **) NULL))
3967
+ {
3968
+ my_perror("ERROR: could not add listen socket to event loop");
3969
+ return mDNSfalse;
3970
+ }
3971
+ else LogOperation("%3d: Listening for incoming Unix Domain Socket client requests", skt);
3972
+
3973
+ return mDNStrue;
3974
+ }
3975
+
3976
+ mDNSexport int udsserver_init(dnssd_sock_t skts[], mDNSu32 count)
3977
+ {
3978
+ dnssd_sockaddr_t laddr;
3979
+ int ret;
3980
+ mDNSu32 i = 0;
3981
+
3982
+ LogInfo("udsserver_init");
3983
+
3984
+ // If a particular platform wants to opt out of having a PID file, define PID_FILE to be ""
3985
+ if (PID_FILE[0])
3986
+ {
3987
+ FILE *fp = fopen(PID_FILE, "w");
3988
+ if (fp != NULL)
3989
+ {
3990
+ fprintf(fp, "%d\n", getpid());
3991
+ fclose(fp);
3992
+ }
3993
+ }
3994
+
3995
+ if (skts)
3996
+ {
3997
+ for (i = 0; i < count; i++)
3998
+ if (dnssd_SocketValid(skts[i]) && !uds_socket_setup(skts[i]))
3999
+ goto error;
4000
+ }
4001
+ else
4002
+ {
4003
+ listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
4004
+ if (!dnssd_SocketValid(listenfd))
4005
+ {
4006
+ my_perror("ERROR: socket(AF_DNSSD, SOCK_STREAM, 0); failed");
4007
+ goto error;
4008
+ }
4009
+
4010
+ mDNSPlatformMemZero(&laddr, sizeof(laddr));
4011
+
4012
+ #if defined(USE_TCP_LOOPBACK)
4013
+ {
4014
+ laddr.sin_family = AF_INET;
4015
+ laddr.sin_port = htons(MDNS_TCP_SERVERPORT);
4016
+ laddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
4017
+ ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
4018
+ if (ret < 0)
4019
+ {
4020
+ my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
4021
+ goto error;
4022
+ }
4023
+ }
4024
+ #else
4025
+ {
4026
+ mode_t mask = umask(0);
4027
+ unlink(MDNS_UDS_SERVERPATH); // OK if this fails
4028
+ laddr.sun_family = AF_LOCAL;
4029
+ #ifndef NOT_HAVE_SA_LEN
4030
+ // According to Stevens (section 3.2), there is no portable way to
4031
+ // determine whether sa_len is defined on a particular platform.
4032
+ laddr.sun_len = sizeof(struct sockaddr_un);
4033
+ #endif
4034
+ if (strlen(MDNS_UDS_SERVERPATH) >= sizeof(laddr.sun_path))
4035
+ {
4036
+ LogMsg("ERROR: MDNS_UDS_SERVERPATH must be < %d characters", (int)sizeof(laddr.sun_path));
4037
+ goto error;
4038
+ }
4039
+ mDNSPlatformStrCopy(laddr.sun_path, MDNS_UDS_SERVERPATH);
4040
+ ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
4041
+ umask(mask);
4042
+ if (ret < 0)
4043
+ {
4044
+ my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
4045
+ goto error;
4046
+ }
4047
+ }
4048
+ #endif
4049
+
4050
+ if (!uds_socket_setup(listenfd)) goto error;
4051
+ }
4052
+
4053
+ #if !defined(PLATFORM_NO_RLIMIT)
4054
+ {
4055
+ // Set maximum number of open file descriptors
4056
+ #define MIN_OPENFILES 10240
4057
+ struct rlimit maxfds, newfds;
4058
+
4059
+ // Due to bugs in OS X (<rdar://problem/2941095>, <rdar://problem/3342704>, <rdar://problem/3839173>)
4060
+ // you have to get and set rlimits once before getrlimit will return sensible values
4061
+ if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
4062
+ if (setrlimit(RLIMIT_NOFILE, &maxfds) < 0) my_perror("ERROR: Unable to set maximum file descriptor limit");
4063
+
4064
+ if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
4065
+ newfds.rlim_max = (maxfds.rlim_max > MIN_OPENFILES) ? maxfds.rlim_max : MIN_OPENFILES;
4066
+ newfds.rlim_cur = (maxfds.rlim_cur > MIN_OPENFILES) ? maxfds.rlim_cur : MIN_OPENFILES;
4067
+ if (newfds.rlim_max != maxfds.rlim_max || newfds.rlim_cur != maxfds.rlim_cur)
4068
+ if (setrlimit(RLIMIT_NOFILE, &newfds) < 0) my_perror("ERROR: Unable to set maximum file descriptor limit");
4069
+
4070
+ if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
4071
+ debugf("maxfds.rlim_max %d", (long)maxfds.rlim_max);
4072
+ debugf("maxfds.rlim_cur %d", (long)maxfds.rlim_cur);
4073
+ }
4074
+ #endif
4075
+
4076
+ // We start a "LocalOnly" query looking for Automatic Browse Domain records.
4077
+ // When Domain Enumeration in uDNS.c finds an "lb" record from the network, its "FoundDomain" routine
4078
+ // creates a "LocalOnly" record, which results in our AutomaticBrowseDomainChange callback being invoked
4079
+ mDNS_GetDomains(&mDNSStorage, &mDNSStorage.AutomaticBrowseDomainQ, mDNS_DomainTypeBrowseAutomatic,
4080
+ mDNSNULL, mDNSInterface_LocalOnly, AutomaticBrowseDomainChange, mDNSNULL);
4081
+
4082
+ // Add "local" as recommended registration domain ("dns-sd -E"), recommended browsing domain ("dns-sd -F"), and automatic browsing domain
4083
+ RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeRegistration);
4084
+ RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeBrowse);
4085
+ AddAutoBrowseDomain(0, &localdomain);
4086
+
4087
+ udsserver_handle_configchange(&mDNSStorage);
4088
+ return 0;
4089
+
4090
+ error:
4091
+
4092
+ my_perror("ERROR: udsserver_init");
4093
+ return -1;
4094
+ }
4095
+
4096
+ mDNSexport int udsserver_exit(void)
4097
+ {
4098
+ // Cancel all outstanding client requests
4099
+ while (all_requests) AbortUnlinkAndFree(all_requests);
4100
+
4101
+ // Clean up any special mDNSInterface_LocalOnly records we created, both the entries for "local" we
4102
+ // created in udsserver_init, and others we created as a result of reading local configuration data
4103
+ while (LocalDomainEnumRecords)
4104
+ {
4105
+ ARListElem *rem = LocalDomainEnumRecords;
4106
+ LocalDomainEnumRecords = LocalDomainEnumRecords->next;
4107
+ mDNS_Deregister(&mDNSStorage, &rem->ar);
4108
+ }
4109
+
4110
+ // If the launching environment created no listening socket,
4111
+ // that means we created it ourselves, so we should clean it up on exit
4112
+ if (dnssd_SocketValid(listenfd))
4113
+ {
4114
+ dnssd_close(listenfd);
4115
+ #if !defined(USE_TCP_LOOPBACK)
4116
+ // Currently, we're unable to remove /var/run/mdnsd because we've changed to userid "nobody"
4117
+ // to give up unnecessary privilege, but we need to be root to remove this Unix Domain Socket.
4118
+ // It would be nice if we could find a solution to this problem
4119
+ if (unlink(MDNS_UDS_SERVERPATH))
4120
+ debugf("Unable to remove %s", MDNS_UDS_SERVERPATH);
4121
+ #endif
4122
+ }
4123
+
4124
+ if (PID_FILE[0]) unlink(PID_FILE);
4125
+
4126
+ return 0;
4127
+ }
4128
+
4129
+ mDNSlocal void LogClientInfo(mDNS *const m, const request_state *req)
4130
+ {
4131
+ char prefix[16];
4132
+ if (req->primary) mDNS_snprintf(prefix, sizeof(prefix), " -> ");
4133
+ else mDNS_snprintf(prefix, sizeof(prefix), "%3d:", req->sd);
4134
+
4135
+ usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
4136
+
4137
+ if (!req->terminate)
4138
+ LogMsgNoIdent("%s No operation yet on this socket", prefix);
4139
+ else if (req->terminate == connection_termination)
4140
+ {
4141
+ int num_records = 0, num_ops = 0;
4142
+ const registered_record_entry *p;
4143
+ const request_state *r;
4144
+ for (p = req->u.reg_recs; p; p=p->next) num_records++;
4145
+ for (r = req->next; r; r=r->next) if (r->primary == req) num_ops++;
4146
+ LogMsgNoIdent("%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s", prefix,
4147
+ num_records, num_records != 1 ? "s" : "",
4148
+ num_ops, num_ops != 1 ? "s" : "");
4149
+ for (p = req->u.reg_recs; p; p=p->next)
4150
+ LogMsgNoIdent(" -> DNSServiceRegisterRecord %3d %s", p->key, ARDisplayString(m, p->rr));
4151
+ for (r = req->next; r; r=r->next) if (r->primary == req) LogClientInfo(m, r);
4152
+ }
4153
+ else if (req->terminate == regservice_termination_callback)
4154
+ {
4155
+ service_instance *ptr;
4156
+ for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
4157
+ LogMsgNoIdent("%s DNSServiceRegister %##s %u/%u",
4158
+ (ptr == req->u.servicereg.instances) ? prefix : " ",
4159
+ ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(req->u.servicereg.port), SRS_PORT(&ptr->srs));
4160
+ }
4161
+ else if (req->terminate == browse_termination_callback)
4162
+ {
4163
+ browser_t *blist;
4164
+ for (blist = req->u.browser.browsers; blist; blist = blist->next)
4165
+ LogMsgNoIdent("%s DNSServiceBrowse %##s", (blist == req->u.browser.browsers) ? prefix : " ", blist->q.qname.c);
4166
+ }
4167
+ else if (req->terminate == resolve_termination_callback)
4168
+ LogMsgNoIdent("%s DNSServiceResolve %##s", prefix, req->u.resolve.qsrv.qname.c);
4169
+ else if (req->terminate == queryrecord_termination_callback)
4170
+ LogMsgNoIdent("%s DNSServiceQueryRecord %##s (%s)", prefix, req->u.queryrecord.q.qname.c, DNSTypeName(req->u.queryrecord.q.qtype));
4171
+ else if (req->terminate == enum_termination_callback)
4172
+ LogMsgNoIdent("%s DNSServiceEnumerateDomains %##s", prefix, req->u.enumeration.q_all.qname.c);
4173
+ else if (req->terminate == port_mapping_termination_callback)
4174
+ LogMsgNoIdent("%s DNSServiceNATPortMapping %.4a %s%s Int %d Req %d Ext %d Req TTL %d Granted TTL %d",
4175
+ prefix,
4176
+ &req->u.pm.NATinfo.ExternalAddress,
4177
+ req->u.pm.NATinfo.Protocol & NATOp_MapTCP ? "TCP" : " ",
4178
+ req->u.pm.NATinfo.Protocol & NATOp_MapUDP ? "UDP" : " ",
4179
+ mDNSVal16(req->u.pm.NATinfo.IntPort),
4180
+ mDNSVal16(req->u.pm.ReqExt),
4181
+ mDNSVal16(req->u.pm.NATinfo.ExternalPort),
4182
+ req->u.pm.NATinfo.NATLease,
4183
+ req->u.pm.NATinfo.Lifetime);
4184
+ else if (req->terminate == addrinfo_termination_callback)
4185
+ LogMsgNoIdent("%s DNSServiceGetAddrInfo %s%s %##s", prefix,
4186
+ req->u.addrinfo.protocol & kDNSServiceProtocol_IPv4 ? "v4" : " ",
4187
+ req->u.addrinfo.protocol & kDNSServiceProtocol_IPv6 ? "v6" : " ",
4188
+ req->u.addrinfo.q4.qname.c);
4189
+ else
4190
+ LogMsgNoIdent("%s Unrecognized operation %p", prefix, req->terminate);
4191
+ }
4192
+
4193
+ mDNSlocal char *RecordTypeName(mDNSu8 rtype)
4194
+ {
4195
+ switch (rtype)
4196
+ {
4197
+ case kDNSRecordTypeUnregistered: return ("Unregistered ");
4198
+ case kDNSRecordTypeDeregistering: return ("Deregistering");
4199
+ case kDNSRecordTypeUnique: return ("Unique ");
4200
+ case kDNSRecordTypeAdvisory: return ("Advisory ");
4201
+ case kDNSRecordTypeShared: return ("Shared ");
4202
+ case kDNSRecordTypeVerified: return ("Verified ");
4203
+ case kDNSRecordTypeKnownUnique: return ("KnownUnique ");
4204
+ default: return("Unknown");
4205
+ }
4206
+ }
4207
+
4208
+ mDNSlocal void LogEtcHosts(mDNS *const m)
4209
+ {
4210
+ mDNSBool showheader = mDNStrue;
4211
+ const AuthRecord *ar;
4212
+ mDNSu32 slot;
4213
+ AuthGroup *ag;
4214
+ int count = 0;
4215
+ int authslot = 0;
4216
+ mDNSBool truncated = 0;
4217
+
4218
+ for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
4219
+ {
4220
+ if (m->rrauth.rrauth_hash[slot]) authslot++;
4221
+ for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
4222
+ for (ar = ag->members; ar; ar = ar->next)
4223
+ {
4224
+ if (ar->RecordCallback != FreeEtcHosts) continue;
4225
+ if (showheader) { showheader = mDNSfalse; LogMsgNoIdent(" State Interface"); }
4226
+
4227
+ // Print a maximum of 50 records
4228
+ if (count++ >= 50) { truncated = mDNStrue; continue; }
4229
+ if (ar->ARType == AuthRecordLocalOnly)
4230
+ {
4231
+ if (ar->resrec.InterfaceID == mDNSInterface_LocalOnly)
4232
+ LogMsgNoIdent(" %s LO %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
4233
+ else
4234
+ {
4235
+ mDNSu32 scopeid = (mDNSu32)(uintptr_t)ar->resrec.InterfaceID;
4236
+ LogMsgNoIdent(" %s %u %s", RecordTypeName(ar->resrec.RecordType), scopeid, ARDisplayString(m, ar));
4237
+ }
4238
+ }
4239
+ usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
4240
+ }
4241
+ }
4242
+
4243
+ if (showheader) LogMsgNoIdent("<None>");
4244
+ else if (truncated) LogMsgNoIdent("<Truncated: to 50 records, Total records %d, Total Auth Groups %d, Auth Slots %d>", count, m->rrauth.rrauth_totalused, authslot);
4245
+ }
4246
+
4247
+ mDNSlocal void LogLocalOnlyAuthRecords(mDNS *const m)
4248
+ {
4249
+ mDNSBool showheader = mDNStrue;
4250
+ const AuthRecord *ar;
4251
+ mDNSu32 slot;
4252
+ AuthGroup *ag;
4253
+
4254
+ for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
4255
+ {
4256
+ for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
4257
+ for (ar = ag->members; ar; ar = ar->next)
4258
+ {
4259
+ if (ar->RecordCallback == FreeEtcHosts) continue;
4260
+ if (showheader) { showheader = mDNSfalse; LogMsgNoIdent(" State Interface"); }
4261
+
4262
+ // Print a maximum of 400 records
4263
+ if (ar->ARType == AuthRecordLocalOnly)
4264
+ LogMsgNoIdent(" %s LO %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
4265
+ else if (ar->ARType == AuthRecordP2P)
4266
+ LogMsgNoIdent(" %s PP %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
4267
+ usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
4268
+ }
4269
+ }
4270
+
4271
+ if (showheader) LogMsgNoIdent("<None>");
4272
+ }
4273
+
4274
+ mDNSlocal void LogAuthRecords(mDNS *const m, const mDNSs32 now, AuthRecord *ResourceRecords, int *proxy)
4275
+ {
4276
+ mDNSBool showheader = mDNStrue;
4277
+ const AuthRecord *ar;
4278
+ OwnerOptData owner = zeroOwner;
4279
+ for (ar = ResourceRecords; ar; ar=ar->next)
4280
+ {
4281
+ const char *const ifname = InterfaceNameForID(m, ar->resrec.InterfaceID);
4282
+ if ((ar->WakeUp.HMAC.l[0] != 0) == (proxy != mDNSNULL))
4283
+ {
4284
+ if (showheader) { showheader = mDNSfalse; LogMsgNoIdent(" Int Next Expire State"); }
4285
+ if (proxy) (*proxy)++;
4286
+ if (!mDNSPlatformMemSame(&owner, &ar->WakeUp, sizeof(owner)))
4287
+ {
4288
+ owner = ar->WakeUp;
4289
+ if (owner.password.l[0])
4290
+ LogMsgNoIdent("Proxying for H-MAC %.6a I-MAC %.6a Password %.6a seq %d", &owner.HMAC, &owner.IMAC, &owner.password, owner.seq);
4291
+ else if (!mDNSSameEthAddress(&owner.HMAC, &owner.IMAC))
4292
+ LogMsgNoIdent("Proxying for H-MAC %.6a I-MAC %.6a seq %d", &owner.HMAC, &owner.IMAC, owner.seq);
4293
+ else
4294
+ LogMsgNoIdent("Proxying for %.6a seq %d", &owner.HMAC, owner.seq);
4295
+ }
4296
+ if (AuthRecord_uDNS(ar))
4297
+ LogMsgNoIdent("%7d %7d %7d %7d %s",
4298
+ ar->ThisAPInterval / mDNSPlatformOneSecond,
4299
+ (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
4300
+ ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
4301
+ ar->state, ARDisplayString(m, ar));
4302
+ else if (ar->ARType == AuthRecordLocalOnly)
4303
+ LogMsgNoIdent(" LO %s", ARDisplayString(m, ar));
4304
+ else if (ar->ARType == AuthRecordP2P)
4305
+ LogMsgNoIdent(" PP %s", ARDisplayString(m, ar));
4306
+ else
4307
+ LogMsgNoIdent("%7d %7d %7d %7s %s",
4308
+ ar->ThisAPInterval / mDNSPlatformOneSecond,
4309
+ ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0,
4310
+ ar->TimeExpire ? (ar->TimeExpire - now) / mDNSPlatformOneSecond : 0,
4311
+ ifname ? ifname : "ALL",
4312
+ ARDisplayString(m, ar));
4313
+ usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
4314
+ }
4315
+ }
4316
+ if (showheader) LogMsgNoIdent("<None>");
4317
+ }
4318
+
4319
+ mDNSexport void udsserver_info(mDNS *const m)
4320
+ {
4321
+ const mDNSs32 now = mDNS_TimeNow(m);
4322
+ mDNSu32 CacheUsed = 0, CacheActive = 0, slot;
4323
+ int ProxyA = 0, ProxyD = 0;
4324
+ const CacheGroup *cg;
4325
+ const CacheRecord *cr;
4326
+ const DNSQuestion *q;
4327
+ const DNameListElem *d;
4328
+ const SearchListElem *s;
4329
+
4330
+ LogMsgNoIdent("Timenow 0x%08lX (%d)", (mDNSu32)now, now);
4331
+
4332
+ LogMsgNoIdent("------------ Cache -------------");
4333
+ LogMsgNoIdent("Slt Q TTL if U Type rdlen");
4334
+ for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
4335
+ for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
4336
+ {
4337
+ CacheUsed++; // Count one cache entity for the CacheGroup object
4338
+ for (cr = cg->members; cr; cr=cr->next)
4339
+ {
4340
+ const mDNSs32 remain = cr->resrec.rroriginalttl - (now - cr->TimeRcvd) / mDNSPlatformOneSecond;
4341
+ const char *ifname;
4342
+ mDNSInterfaceID InterfaceID = cr->resrec.InterfaceID;
4343
+ if (!InterfaceID && cr->resrec.rDNSServer)
4344
+ InterfaceID = cr->resrec.rDNSServer->interface;
4345
+ ifname = InterfaceNameForID(m, InterfaceID);
4346
+ CacheUsed++;
4347
+ if (cr->CRActiveQuestion) CacheActive++;
4348
+ LogMsgNoIdent("%3d %s%8ld %-7s%s %-6s%s",
4349
+ slot,
4350
+ cr->CRActiveQuestion ? "*" : " ",
4351
+ remain,
4352
+ ifname ? ifname : "-U-",
4353
+ (cr->resrec.RecordType == kDNSRecordTypePacketNegative) ? "-" :
4354
+ (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? " " : "+",
4355
+ DNSTypeName(cr->resrec.rrtype),
4356
+ CRDisplayString(m, cr));
4357
+ usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
4358
+ }
4359
+ }
4360
+
4361
+ if (m->rrcache_totalused != CacheUsed)
4362
+ LogMsgNoIdent("Cache use mismatch: rrcache_totalused is %lu, true count %lu", m->rrcache_totalused, CacheUsed);
4363
+ if (m->rrcache_active != CacheActive)
4364
+ LogMsgNoIdent("Cache use mismatch: rrcache_active is %lu, true count %lu", m->rrcache_active, CacheActive);
4365
+ LogMsgNoIdent("Cache currently contains %lu entities; %lu referenced by active questions", CacheUsed, CacheActive);
4366
+
4367
+ LogMsgNoIdent("--------- Auth Records ---------");
4368
+ LogAuthRecords(m, now, m->ResourceRecords, mDNSNULL);
4369
+
4370
+ LogMsgNoIdent("--------- LocalOnly, P2P Auth Records ---------");
4371
+ LogLocalOnlyAuthRecords(m);
4372
+
4373
+ LogMsgNoIdent("--------- /etc/hosts ---------");
4374
+ LogEtcHosts(m);
4375
+
4376
+ LogMsgNoIdent("------ Duplicate Records -------");
4377
+ LogAuthRecords(m, now, m->DuplicateRecords, mDNSNULL);
4378
+
4379
+ LogMsgNoIdent("----- Auth Records Proxied -----");
4380
+ LogAuthRecords(m, now, m->ResourceRecords, &ProxyA);
4381
+
4382
+ LogMsgNoIdent("-- Duplicate Records Proxied ---");
4383
+ LogAuthRecords(m, now, m->DuplicateRecords, &ProxyD);
4384
+
4385
+ LogMsgNoIdent("---------- Questions -----------");
4386
+ if (!m->Questions) LogMsgNoIdent("<None>");
4387
+ else
4388
+ {
4389
+ CacheUsed = 0;
4390
+ CacheActive = 0;
4391
+ LogMsgNoIdent(" Int Next if T NumAns VDNS Qptr DupOf SU SQ Type Name");
4392
+ for (q = m->Questions; q; q=q->next)
4393
+ {
4394
+ mDNSs32 i = q->ThisQInterval / mDNSPlatformOneSecond;
4395
+ mDNSs32 n = (NextQSendTime(q) - now) / mDNSPlatformOneSecond;
4396
+ char *ifname = InterfaceNameForID(m, q->InterfaceID);
4397
+ CacheUsed++;
4398
+ if (q->ThisQInterval) CacheActive++;
4399
+ LogMsgNoIdent("%6d%6d %-7s%s%s %5d 0x%x%x 0x%p 0x%p %1d %2d %-5s%##s%s",
4400
+ i, n,
4401
+ ifname ? ifname : mDNSOpaque16IsZero(q->TargetQID) ? "" : "-U-",
4402
+ mDNSOpaque16IsZero(q->TargetQID) ? (q->LongLived ? "l" : " ") : (q->LongLived ? "L" : "O"),
4403
+ PrivateQuery(q) ? "P" : " ",
4404
+ q->CurrentAnswers, q->validDNSServers.l[1], q->validDNSServers.l[0], q, q->DuplicateOf,
4405
+ q->SuppressUnusable, q->SuppressQuery, DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : "");
4406
+ usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
4407
+ }
4408
+ LogMsgNoIdent("%lu question%s; %lu active", CacheUsed, CacheUsed > 1 ? "s" : "", CacheActive);
4409
+ }
4410
+
4411
+ LogMsgNoIdent("----- Local-Only Questions -----");
4412
+ if (!m->LocalOnlyQuestions) LogMsgNoIdent("<None>");
4413
+ else for (q = m->LocalOnlyQuestions; q; q=q->next)
4414
+ LogMsgNoIdent(" %5d %-6s%##s%s",
4415
+ q->CurrentAnswers, DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : "");
4416
+
4417
+ LogMsgNoIdent("---- Active Client Requests ----");
4418
+ if (!all_requests) LogMsgNoIdent("<None>");
4419
+ else
4420
+ {
4421
+ const request_state *req, *r;
4422
+ for (req = all_requests; req; req=req->next)
4423
+ {
4424
+ if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
4425
+ {
4426
+ for (r = all_requests; r && r != req; r=r->next) if (r == req->primary) goto foundparent;
4427
+ LogMsgNoIdent("%3d: Orhpan operation %p; parent %p not found in request list", req->sd);
4428
+ }
4429
+ // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
4430
+ LogClientInfo(m, req);
4431
+ foundparent:;
4432
+ }
4433
+ }
4434
+
4435
+ LogMsgNoIdent("-------- NAT Traversals --------");
4436
+ if (!m->NATTraversals) LogMsgNoIdent("<None>");
4437
+ else
4438
+ {
4439
+ const NATTraversalInfo *nat;
4440
+ for (nat = m->NATTraversals; nat; nat=nat->next)
4441
+ {
4442
+ if (nat->Protocol)
4443
+ LogMsgNoIdent("%p %s Int %5d Ext %5d Err %d Retry %5d Interval %5d Expire %5d",
4444
+ nat, nat->Protocol == NATOp_MapTCP ? "TCP" : "UDP",
4445
+ mDNSVal16(nat->IntPort), mDNSVal16(nat->ExternalPort), nat->Result,
4446
+ nat->retryPortMap ? (nat->retryPortMap - now) / mDNSPlatformOneSecond : 0,
4447
+ nat->retryInterval / mDNSPlatformOneSecond,
4448
+ nat->ExpiryTime ? (nat->ExpiryTime - now) / mDNSPlatformOneSecond : 0);
4449
+ else
4450
+ LogMsgNoIdent("%p Address Request Retry %5d Interval %5d", nat,
4451
+ (m->retryGetAddr - now) / mDNSPlatformOneSecond,
4452
+ m->retryIntervalGetAddr / mDNSPlatformOneSecond);
4453
+ usleep((m->KnownBugs & mDNS_KnownBug_LossySyslog) ? 3333 : 1000);
4454
+ }
4455
+ }
4456
+
4457
+ LogMsgNoIdent("--------- AuthInfoList ---------");
4458
+ if (!m->AuthInfoList) LogMsgNoIdent("<None>");
4459
+ else
4460
+ {
4461
+ const DomainAuthInfo *a;
4462
+ for (a = m->AuthInfoList; a; a = a->next)
4463
+ LogMsgNoIdent("%##s %##s %##s %d %s", a->domain.c, a->keyname.c, a->hostname.c, (a->port.b[0] << 8 | a->port.b[1]), a->AutoTunnel ? a->AutoTunnel : "");
4464
+ }
4465
+
4466
+ #if APPLE_OSX_mDNSResponder
4467
+ LogMsgNoIdent("--------- TunnelClients --------");
4468
+ if (!m->TunnelClients) LogMsgNoIdent("<None>");
4469
+ else
4470
+ {
4471
+ const ClientTunnel *c;
4472
+ for (c = m->TunnelClients; c; c = c->next)
4473
+ LogMsgNoIdent("%s %##s local %.16a %.4a %.16a remote %.16a %.4a %5d %.16a interval %d",
4474
+ c->prefix, c->dstname.c, &c->loc_inner, &c->loc_outer, &c->loc_outer6, &c->rmt_inner, &c->rmt_outer, mDNSVal16(c->rmt_outer_port), &c->rmt_outer6, c->q.ThisQInterval);
4475
+ }
4476
+ #endif // APPLE_OSX_mDNSResponder
4477
+
4478
+ LogMsgNoIdent("---------- Misc State ----------");
4479
+
4480
+ LogMsgNoIdent("PrimaryMAC: %.6a", &m->PrimaryMAC);
4481
+
4482
+ LogMsgNoIdent("m->SleepState %d (%s) seq %d",
4483
+ m->SleepState,
4484
+ m->SleepState == SleepState_Awake ? "Awake" :
4485
+ m->SleepState == SleepState_Transferring ? "Transferring" :
4486
+ m->SleepState == SleepState_Sleeping ? "Sleeping" : "?",
4487
+ m->SleepSeqNum);
4488
+
4489
+ if (!m->SPSSocket) LogMsgNoIdent("Not offering Sleep Proxy Service");
4490
+ else LogMsgNoIdent("Offering Sleep Proxy Service: %#s", m->SPSRecords.RR_SRV.resrec.name->c);
4491
+
4492
+ if (m->ProxyRecords == ProxyA + ProxyD) LogMsgNoIdent("ProxyRecords: %d + %d = %d", ProxyA, ProxyD, ProxyA + ProxyD);
4493
+ else LogMsgNoIdent("ProxyRecords: MISMATCH %d + %d = %d ≠ %d", ProxyA, ProxyD, ProxyA + ProxyD, m->ProxyRecords);
4494
+
4495
+ LogMsgNoIdent("------ Auto Browse Domains -----");
4496
+ if (!AutoBrowseDomains) LogMsgNoIdent("<None>");
4497
+ else for (d=AutoBrowseDomains; d; d=d->next) LogMsgNoIdent("%##s", d->name.c);
4498
+
4499
+ LogMsgNoIdent("--- Auto Registration Domains --");
4500
+ if (!AutoRegistrationDomains) LogMsgNoIdent("<None>");
4501
+ else for (d=AutoRegistrationDomains; d; d=d->next) LogMsgNoIdent("%##s", d->name.c);
4502
+
4503
+ LogMsgNoIdent("--- Search Domains --");
4504
+ if (!SearchList) LogMsgNoIdent("<None>");
4505
+ else
4506
+ {
4507
+ for (s=SearchList; s; s=s->next)
4508
+ {
4509
+ char *ifname = InterfaceNameForID(m, s->InterfaceID);
4510
+ LogMsgNoIdent("%##s %s", s->domain.c, ifname ? ifname : "");
4511
+ }
4512
+ }
4513
+
4514
+ LogMsgNoIdent("---- Task Scheduling Timers ----");
4515
+
4516
+ if (!m->NewQuestions)
4517
+ LogMsgNoIdent("NewQuestion <NONE>");
4518
+ else
4519
+ LogMsgNoIdent("NewQuestion DelayAnswering %d %d %##s (%s)",
4520
+ m->NewQuestions->DelayAnswering, m->NewQuestions->DelayAnswering-now,
4521
+ m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype));
4522
+
4523
+ if (!m->NewLocalOnlyQuestions)
4524
+ LogMsgNoIdent("NewLocalOnlyQuestions <NONE>");
4525
+ else
4526
+ LogMsgNoIdent("NewLocalOnlyQuestions %##s (%s)",
4527
+ m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype));
4528
+
4529
+ if (!m->NewLocalRecords)
4530
+ LogMsgNoIdent("NewLocalRecords <NONE>");
4531
+ else
4532
+ LogMsgNoIdent("NewLocalRecords %02X %s", m->NewLocalRecords->resrec.RecordType, ARDisplayString(m, m->NewLocalRecords));
4533
+
4534
+ LogMsgNoIdent("SPSProxyListChanged%s", m->SPSProxyListChanged ? "" : " <NONE>");
4535
+ LogMsgNoIdent("LocalRemoveEvents%s", m->LocalRemoveEvents ? "" : " <NONE>");
4536
+ LogMsgNoIdent("m->RegisterAutoTunnel6 %08X", m->RegisterAutoTunnel6);
4537
+ LogMsgNoIdent("m->AutoTunnelRelayAddrIn %.16a", &m->AutoTunnelRelayAddrIn);
4538
+ LogMsgNoIdent("m->AutoTunnelRelayAddrOut %.16a", &m->AutoTunnelRelayAddrOut);
4539
+
4540
+ #define LogTimer(MSG,T) LogMsgNoIdent( MSG " %08X %11d %08X %11d", (T), (T), (T)-now, (T)-now)
4541
+
4542
+ LogMsgNoIdent(" ABS (hex) ABS (dec) REL (hex) REL (dec)");
4543
+ LogMsgNoIdent("m->timenow %08X %11d", now, now);
4544
+ LogMsgNoIdent("m->timenow_adjust %08X %11d", m->timenow_adjust, m->timenow_adjust);
4545
+ LogTimer("m->NextScheduledEvent ", m->NextScheduledEvent);
4546
+
4547
+ #ifndef UNICAST_DISABLED
4548
+ LogTimer("m->NextuDNSEvent ", m->NextuDNSEvent);
4549
+ LogTimer("m->NextSRVUpdate ", m->NextSRVUpdate);
4550
+ LogTimer("m->NextScheduledNATOp ", m->NextScheduledNATOp);
4551
+ LogTimer("m->retryGetAddr ", m->retryGetAddr);
4552
+ #endif
4553
+
4554
+ LogTimer("m->NextCacheCheck ", m->NextCacheCheck);
4555
+ LogTimer("m->NextScheduledSPS ", m->NextScheduledSPS);
4556
+ LogTimer("m->NextScheduledSPRetry ", m->NextScheduledSPRetry);
4557
+ LogTimer("m->DelaySleep ", m->DelaySleep);
4558
+
4559
+ LogTimer("m->NextScheduledQuery ", m->NextScheduledQuery);
4560
+ LogTimer("m->NextScheduledProbe ", m->NextScheduledProbe);
4561
+ LogTimer("m->NextScheduledResponse", m->NextScheduledResponse);
4562
+
4563
+ LogTimer("m->SuppressSending ", m->SuppressSending);
4564
+ LogTimer("m->SuppressProbes ", m->SuppressProbes);
4565
+ LogTimer("m->ProbeFailTime ", m->ProbeFailTime);
4566
+ LogTimer("m->DelaySleep ", m->DelaySleep);
4567
+ LogTimer("m->SleepLimit ", m->SleepLimit);
4568
+ LogTimer("m->NextScheduledStopTime ", m->NextScheduledStopTime);
4569
+ }
4570
+
4571
+ #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING
4572
+ mDNSexport void uds_validatelists(void)
4573
+ {
4574
+ const request_state *req, *p;
4575
+ for (req = all_requests; req; req=req->next)
4576
+ {
4577
+ if (req->next == (request_state *)~0 || (req->sd < 0 && req->sd != -2))
4578
+ LogMemCorruption("UDS request list: %p is garbage (%d)", req, req->sd);
4579
+
4580
+ if (req->primary == req)
4581
+ LogMemCorruption("UDS request list: req->primary should not point to self %p/%d", req, req->sd);
4582
+
4583
+ if (req->primary && req->replies)
4584
+ LogMemCorruption("UDS request list: Subordinate request %p/%d/%p should not have replies (%p)",
4585
+ req, req->sd, req->primary && req->replies);
4586
+
4587
+ p = req->primary;
4588
+ if ((long)p & 3)
4589
+ LogMemCorruption("UDS request list: req %p primary %p is misaligned (%d)", req, p, req->sd);
4590
+ else if (p && (p->next == (request_state *)~0 || (p->sd < 0 && p->sd != -2)))
4591
+ LogMemCorruption("UDS request list: req %p primary %p is garbage (%d)", req, p, p->sd);
4592
+
4593
+ reply_state *rep;
4594
+ for (rep = req->replies; rep; rep=rep->next)
4595
+ if (rep->next == (reply_state *)~0)
4596
+ LogMemCorruption("UDS req->replies: %p is garbage", rep);
4597
+
4598
+ if (req->terminate == connection_termination)
4599
+ {
4600
+ registered_record_entry *r;
4601
+ for (r = req->u.reg_recs; r; r=r->next)
4602
+ if (r->next == (registered_record_entry *)~0)
4603
+ LogMemCorruption("UDS req->u.reg_recs: %p is garbage", r);
4604
+ }
4605
+ else if (req->terminate == regservice_termination_callback)
4606
+ {
4607
+ service_instance *s;
4608
+ for (s = req->u.servicereg.instances; s; s=s->next)
4609
+ if (s->next == (service_instance *)~0)
4610
+ LogMemCorruption("UDS req->u.servicereg.instances: %p is garbage", s);
4611
+ }
4612
+ else if (req->terminate == browse_termination_callback)
4613
+ {
4614
+ browser_t *b;
4615
+ for (b = req->u.browser.browsers; b; b=b->next)
4616
+ if (b->next == (browser_t *)~0)
4617
+ LogMemCorruption("UDS req->u.browser.browsers: %p is garbage", b);
4618
+ }
4619
+ }
4620
+
4621
+ DNameListElem *d;
4622
+ for (d = SCPrefBrowseDomains; d; d=d->next)
4623
+ if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
4624
+ LogMemCorruption("SCPrefBrowseDomains: %p is garbage (%d)", d, d->name.c[0]);
4625
+
4626
+ ARListElem *b;
4627
+ for (b = LocalDomainEnumRecords; b; b=b->next)
4628
+ if (b->next == (ARListElem *)~0 || b->ar.resrec.name->c[0] > 63)
4629
+ LogMemCorruption("LocalDomainEnumRecords: %p is garbage (%d)", b, b->ar.resrec.name->c[0]);
4630
+
4631
+ for (d = AutoBrowseDomains; d; d=d->next)
4632
+ if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
4633
+ LogMemCorruption("AutoBrowseDomains: %p is garbage (%d)", d, d->name.c[0]);
4634
+
4635
+ for (d = AutoRegistrationDomains; d; d=d->next)
4636
+ if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
4637
+ LogMemCorruption("AutoRegistrationDomains: %p is garbage (%d)", d, d->name.c[0]);
4638
+ }
4639
+ #endif // APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING
4640
+
4641
+ mDNSlocal int send_msg(request_state *const req)
4642
+ {
4643
+ reply_state *const rep = req->replies; // Send the first waiting reply
4644
+ ssize_t nwriten;
4645
+ if (req->no_reply) return(t_complete);
4646
+
4647
+ ConvertHeaderBytes(rep->mhdr);
4648
+ nwriten = send(req->sd, (char *)&rep->mhdr + rep->nwriten, rep->totallen - rep->nwriten, 0);
4649
+ ConvertHeaderBytes(rep->mhdr);
4650
+
4651
+ if (nwriten < 0)
4652
+ {
4653
+ if (dnssd_errno == dnssd_EINTR || dnssd_errno == dnssd_EWOULDBLOCK) nwriten = 0;
4654
+ else
4655
+ {
4656
+ #if !defined(PLATFORM_NO_EPIPE)
4657
+ if (dnssd_errno == EPIPE)
4658
+ return(req->ts = t_terminated);
4659
+ else
4660
+ #endif
4661
+ {
4662
+ LogMsg("send_msg ERROR: failed to write %d of %d bytes to fd %d errno %d (%s)",
4663
+ rep->totallen - rep->nwriten, rep->totallen, req->sd, dnssd_errno, dnssd_strerror(dnssd_errno));
4664
+ return(t_error);
4665
+ }
4666
+ }
4667
+ }
4668
+ rep->nwriten += nwriten;
4669
+ return (rep->nwriten == rep->totallen) ? t_complete : t_morecoming;
4670
+ }
4671
+
4672
+ mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent)
4673
+ {
4674
+ mDNSs32 now = mDNS_TimeNow(&mDNSStorage);
4675
+ request_state **req = &all_requests;
4676
+
4677
+ while (*req)
4678
+ {
4679
+ request_state *const r = *req;
4680
+
4681
+ if (r->terminate == resolve_termination_callback)
4682
+ if (r->u.resolve.ReportTime && now - r->u.resolve.ReportTime >= 0)
4683
+ {
4684
+ r->u.resolve.ReportTime = 0;
4685
+ LogMsgNoIdent("Client application bug: DNSServiceResolve(%##s) active for over two minutes. "
4686
+ "This places considerable burden on the network.", r->u.resolve.qsrv.qname.c);
4687
+ }
4688
+
4689
+ // Note: Only primary req's have reply lists, not subordinate req's.
4690
+ while (r->replies) // Send queued replies
4691
+ {
4692
+ transfer_state result;
4693
+ if (r->replies->next) r->replies->rhdr->flags |= dnssd_htonl(kDNSServiceFlagsMoreComing);
4694
+ result = send_msg(r); // Returns t_morecoming if buffer full because client is not reading
4695
+ if (result == t_complete)
4696
+ {
4697
+ reply_state *fptr = r->replies;
4698
+ r->replies = r->replies->next;
4699
+ freeL("reply_state/udsserver_idle", fptr);
4700
+ r->time_blocked = 0; // reset failure counter after successful send
4701
+ r->unresponsiveness_reports = 0;
4702
+ continue;
4703
+ }
4704
+ else if (result == t_terminated || result == t_error)
4705
+ {
4706
+ LogMsg("%3d: Could not write data to client because of error - aborting connection", r->sd);
4707
+ LogClientInfo(&mDNSStorage, r);
4708
+ abort_request(r);
4709
+ }
4710
+ break;
4711
+ }
4712
+
4713
+ if (r->replies) // If we failed to send everything, check our time_blocked timer
4714
+ {
4715
+ if (nextevent - now > mDNSPlatformOneSecond) nextevent = now + mDNSPlatformOneSecond;
4716
+
4717
+ if (mDNSStorage.SleepState != SleepState_Awake) r->time_blocked = 0;
4718
+ else if (!r->time_blocked) r->time_blocked = NonZeroTime(now);
4719
+ else if (now - r->time_blocked >= 10 * mDNSPlatformOneSecond * (r->unresponsiveness_reports+1))
4720
+ {
4721
+ int num = 0;
4722
+ struct reply_state *x = r->replies;
4723
+ while (x) { num++; x=x->next; }
4724
+ LogMsg("%3d: Could not write data to client after %ld seconds, %d repl%s waiting",
4725
+ r->sd, (now - r->time_blocked) / mDNSPlatformOneSecond, num, num == 1 ? "y" : "ies");
4726
+ if (++r->unresponsiveness_reports >= 60)
4727
+ {
4728
+ LogMsg("%3d: Client unresponsive; aborting connection", r->sd);
4729
+ LogClientInfo(&mDNSStorage, r);
4730
+ abort_request(r);
4731
+ }
4732
+ }
4733
+ }
4734
+
4735
+ if (!dnssd_SocketValid(r->sd)) // If this request is finished, unlink it from the list and free the memory
4736
+ {
4737
+ // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
4738
+ *req = r->next;
4739
+ freeL("request_state/udsserver_idle", r);
4740
+ }
4741
+ else
4742
+ req = &r->next;
4743
+ }
4744
+ return nextevent;
4745
+ }
4746
+
4747
+ struct CompileTimeAssertionChecks_uds_daemon
4748
+ {
4749
+ // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
4750
+ // other overly-large structures instead of having a pointer to them, can inadvertently
4751
+ // cause structure sizes (and therefore memory usage) to balloon unreasonably.
4752
+ char sizecheck_request_state [(sizeof(request_state) <= 1784) ? 1 : -1];
4753
+ char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <= 60) ? 1 : -1];
4754
+ char sizecheck_service_instance [(sizeof(service_instance) <= 6552) ? 1 : -1];
4755
+ char sizecheck_browser_t [(sizeof(browser_t) <= 1050) ? 1 : -1];
4756
+ char sizecheck_reply_hdr [(sizeof(reply_hdr) <= 12) ? 1 : -1];
4757
+ char sizecheck_reply_state [(sizeof(reply_state) <= 64) ? 1 : -1];
4758
+ };