react-native-zeroconf 0.13.8 → 0.15.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 (300) hide show
  1. package/NOTICE +49 -0
  2. package/README.md +489 -65
  3. package/android/build.gradle +23 -24
  4. package/android/src/main/AndroidManifest.xml +5 -2
  5. package/android/src/main/java/com/balthazargronon/RCTZeroconf/ZeroConfImplFactory.java +10 -3
  6. package/android/src/main/java/com/balthazargronon/RCTZeroconf/ZeroconfModule.java +3 -2
  7. package/android/src/main/java/com/balthazargronon/RCTZeroconf/nsd/NsdServiceImpl.java +83 -22
  8. package/android/src/main/java/com/balthazargronon/RCTZeroconf/rx2dnssd/DnssdImpl.java +61 -16
  9. package/android/src/main/java/com/github/druk/dnssd/BaseListener.java +33 -0
  10. package/android/src/main/java/com/github/druk/dnssd/BrowseListener.java +67 -0
  11. package/android/src/main/java/com/github/druk/dnssd/DNSRecord.java +47 -0
  12. package/android/src/main/java/com/github/druk/dnssd/DNSSD.java +650 -0
  13. package/android/src/main/java/com/github/druk/dnssd/DNSSDBindable.java +67 -0
  14. package/android/src/main/java/com/github/druk/dnssd/DNSSDEmbedded.java +135 -0
  15. package/android/src/main/java/com/github/druk/dnssd/DNSSDException.java +66 -0
  16. package/android/src/main/java/com/github/druk/dnssd/DNSSDRecordRegistrar.java +55 -0
  17. package/android/src/main/java/com/github/druk/dnssd/DNSSDRegistration.java +54 -0
  18. package/android/src/main/java/com/github/druk/dnssd/DNSSDService.java +35 -0
  19. package/android/src/main/java/com/github/druk/dnssd/DomainListener.java +57 -0
  20. package/android/src/main/java/com/github/druk/dnssd/InternalBrowseListener.java +76 -0
  21. package/android/src/main/java/com/github/druk/dnssd/InternalDNSSD.java +870 -0
  22. package/android/src/main/java/com/github/druk/dnssd/InternalDNSSDRecordRegistrar.java +30 -0
  23. package/android/src/main/java/com/github/druk/dnssd/InternalDNSSDRegistration.java +34 -0
  24. package/android/src/main/java/com/github/druk/dnssd/InternalDNSSDService.java +29 -0
  25. package/android/src/main/java/com/github/druk/dnssd/InternalDomainListener.java +62 -0
  26. package/android/src/main/java/com/github/druk/dnssd/InternalQueryListener.java +61 -0
  27. package/android/src/main/java/com/github/druk/dnssd/InternalRegisterListener.java +51 -0
  28. package/android/src/main/java/com/github/druk/dnssd/InternalResolveListener.java +58 -0
  29. package/android/src/main/java/com/github/druk/dnssd/NSClass.java +16 -0
  30. package/android/src/main/java/com/github/druk/dnssd/NSType.java +58 -0
  31. package/android/src/main/java/com/github/druk/dnssd/QueryListener.java +54 -0
  32. package/android/src/main/java/com/github/druk/dnssd/RegisterListener.java +46 -0
  33. package/android/src/main/java/com/github/druk/dnssd/RegisterRecordListener.java +35 -0
  34. package/android/src/main/java/com/github/druk/dnssd/ResolveListener.java +55 -0
  35. package/android/src/main/java/com/github/druk/dnssd/TXTRecord.java +293 -0
  36. package/android/src/main/java/com/github/druk/rx2dnssd/BonjourService.java +400 -0
  37. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2BrowseListener.java +55 -0
  38. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2Dnssd.java +127 -0
  39. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2DnssdBindable.java +35 -0
  40. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2DnssdCommon.java +280 -0
  41. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2DnssdEmbedded.java +31 -0
  42. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2QueryListener.java +70 -0
  43. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2RegisterListener.java +47 -0
  44. package/android/src/main/java/com/github/druk/rx2dnssd/Rx2ResolveListener.java +51 -0
  45. package/android/src/main/jni/Android.mk +95 -0
  46. package/android/src/main/jni/Application.mk +3 -0
  47. package/android/src/main/jni/DNSSD.java.h +290 -0
  48. package/android/src/main/jni/JNISupport.c +1140 -0
  49. package/android/src/main/jni/mdnsresponder/Android.bp +215 -0
  50. package/android/src/main/jni/mdnsresponder/Clients/ClientCommon.c +75 -0
  51. package/android/src/main/jni/mdnsresponder/Clients/ClientCommon.h +41 -0
  52. package/android/src/main/jni/mdnsresponder/Clients/Makefile +54 -0
  53. package/android/src/main/jni/mdnsresponder/Clients/ReadMe.txt +25 -0
  54. package/android/src/main/jni/mdnsresponder/Clients/dns-sd.c +1351 -0
  55. package/android/src/main/jni/mdnsresponder/LICENSE +13 -0
  56. package/android/src/main/jni/mdnsresponder/MODULE_LICENSE_APACHE2 +0 -0
  57. package/android/src/main/jni/mdnsresponder/Makefile +41 -0
  58. package/android/src/main/jni/mdnsresponder/NOTICE +13 -0
  59. package/android/src/main/jni/mdnsresponder/PrivateDNS.txt +275 -0
  60. package/android/src/main/jni/mdnsresponder/README.txt +166 -0
  61. package/android/src/main/jni/mdnsresponder/README.version +3 -0
  62. package/android/src/main/jni/mdnsresponder/android/caseMapping/Iphlpapi.h +1 -0
  63. package/android/src/main/jni/mdnsresponder/android/caseMapping/README +3 -0
  64. package/android/src/main/jni/mdnsresponder/android/caseMapping/Resource.h +1 -0
  65. package/android/src/main/jni/mdnsresponder/android/caseMapping/Ws2tcpip.h +1 -0
  66. package/android/src/main/jni/mdnsresponder/android/caseMapping/ipExport.h +1 -0
  67. package/android/src/main/jni/mdnsresponder/android/windows_firewall_dummy.c +10 -0
  68. package/android/src/main/jni/mdnsresponder/mDNSCore/DNSCommon.c +3157 -0
  69. package/android/src/main/jni/mdnsresponder/mDNSCore/DNSCommon.h +292 -0
  70. package/android/src/main/jni/mdnsresponder/mDNSCore/DNSDigest.c +1579 -0
  71. package/android/src/main/jni/mdnsresponder/mDNSCore/Implementer Notes.txt +66 -0
  72. package/android/src/main/jni/mdnsresponder/mDNSCore/mDNS.c +11469 -0
  73. package/android/src/main/jni/mdnsresponder/mDNSCore/mDNSDebug.h +164 -0
  74. package/android/src/main/jni/mdnsresponder/mDNSCore/mDNSEmbeddedAPI.h +2974 -0
  75. package/android/src/main/jni/mdnsresponder/mDNSCore/uDNS.c +4969 -0
  76. package/android/src/main/jni/mdnsresponder/mDNSCore/uDNS.h +132 -0
  77. package/android/src/main/jni/mdnsresponder/mDNSPosix/Client.c +223 -0
  78. package/android/src/main/jni/mdnsresponder/mDNSPosix/ExampleClientApp.c +91 -0
  79. package/android/src/main/jni/mdnsresponder/mDNSPosix/ExampleClientApp.h +18 -0
  80. package/android/src/main/jni/mdnsresponder/mDNSPosix/Identify.c +378 -0
  81. package/android/src/main/jni/mdnsresponder/mDNSPosix/Makefile +520 -0
  82. package/android/src/main/jni/mdnsresponder/mDNSPosix/NetMonitor.c +1010 -0
  83. package/android/src/main/jni/mdnsresponder/mDNSPosix/PosixDaemon.c +329 -0
  84. package/android/src/main/jni/mdnsresponder/mDNSPosix/ProxyResponder.c +300 -0
  85. package/android/src/main/jni/mdnsresponder/mDNSPosix/ReadMe.txt +314 -0
  86. package/android/src/main/jni/mdnsresponder/mDNSPosix/Responder.c +792 -0
  87. package/android/src/main/jni/mdnsresponder/mDNSPosix/Services.txt +36 -0
  88. package/android/src/main/jni/mdnsresponder/mDNSPosix/libnss_mdns.8 +148 -0
  89. package/android/src/main/jni/mdnsresponder/mDNSPosix/mDNSPosix.c +1685 -0
  90. package/android/src/main/jni/mdnsresponder/mDNSPosix/mDNSPosix.h +88 -0
  91. package/android/src/main/jni/mdnsresponder/mDNSPosix/mDNSUNP.c +726 -0
  92. package/android/src/main/jni/mdnsresponder/mDNSPosix/mDNSUNP.h +130 -0
  93. package/android/src/main/jni/mdnsresponder/mDNSPosix/mdnsd.sh +73 -0
  94. package/android/src/main/jni/mdnsresponder/mDNSPosix/nss_ReadMe.txt +125 -0
  95. package/android/src/main/jni/mdnsresponder/mDNSPosix/nss_mdns.c +2723 -0
  96. package/android/src/main/jni/mdnsresponder/mDNSPosix/nss_mdns.conf +13 -0
  97. package/android/src/main/jni/mdnsresponder/mDNSPosix/nss_mdns.conf.5 +135 -0
  98. package/android/src/main/jni/mdnsresponder/mDNSPosix/parselog.py +247 -0
  99. package/android/src/main/jni/mdnsresponder/mDNSResponder.sln +400 -0
  100. package/android/src/main/jni/mdnsresponder/mDNSShared/CommonServices.h +1537 -0
  101. package/android/src/main/jni/mdnsresponder/mDNSShared/DebugServices.c +3075 -0
  102. package/android/src/main/jni/mdnsresponder/mDNSShared/DebugServices.h +1607 -0
  103. package/android/src/main/jni/mdnsresponder/mDNSShared/GenLinkedList.c +319 -0
  104. package/android/src/main/jni/mdnsresponder/mDNSShared/GenLinkedList.h +90 -0
  105. package/android/src/main/jni/mdnsresponder/mDNSShared/PlatformCommon.c +220 -0
  106. package/android/src/main/jni/mdnsresponder/mDNSShared/PlatformCommon.h +18 -0
  107. package/android/src/main/jni/mdnsresponder/mDNSShared/dns-sd.1 +194 -0
  108. package/android/src/main/jni/mdnsresponder/mDNSShared/dns_sd.h +2452 -0
  109. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd.8 +69 -0
  110. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd.c +3146 -0
  111. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd.conf +60 -0
  112. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd.h +163 -0
  113. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd_lexer.l +84 -0
  114. package/android/src/main/jni/mdnsresponder/mDNSShared/dnsextd_parser.y +585 -0
  115. package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_clientlib.c +368 -0
  116. package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_clientshim.c +802 -0
  117. package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_clientstub.c +1988 -0
  118. package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_ipc.c +161 -0
  119. package/android/src/main/jni/mdnsresponder/mDNSShared/dnssd_ipc.h +219 -0
  120. package/android/src/main/jni/mdnsresponder/mDNSShared/mDNS.1 +198 -0
  121. package/android/src/main/jni/mdnsresponder/mDNSShared/mDNSDebug.c +93 -0
  122. package/android/src/main/jni/mdnsresponder/mDNSShared/mDNSResponder.8 +116 -0
  123. package/android/src/main/jni/mdnsresponder/mDNSShared/uds_daemon.c +4758 -0
  124. package/android/src/main/jni/mdnsresponder/mDNSShared/uds_daemon.h +80 -0
  125. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/BrowsingPage.cpp +441 -0
  126. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/BrowsingPage.h +156 -0
  127. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ConfigDialog.cpp +59 -0
  128. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ConfigDialog.h +48 -0
  129. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp +301 -0
  130. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ConfigPropertySheet.h +105 -0
  131. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanel.cpp +380 -0
  132. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanel.def +20 -0
  133. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanel.h +84 -0
  134. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanel.rc +141 -0
  135. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanel.vcproj +727 -0
  136. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelDll.rc +123 -0
  137. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelExe.cpp +373 -0
  138. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelExe.h +48 -0
  139. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelExe.rc +123 -0
  140. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelExe.vcproj +764 -0
  141. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelLocRes.rc +270 -0
  142. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelLocRes.vcproj +487 -0
  143. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelRes.rc +134 -0
  144. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ControlPanelRes.vcproj +518 -0
  145. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/FourthPage.cpp +197 -0
  146. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/FourthPage.h +87 -0
  147. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/RegistrationPage.cpp +387 -0
  148. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/RegistrationPage.h +75 -0
  149. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/SecondPage.cpp +544 -0
  150. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/SecondPage.h +107 -0
  151. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ServicesPage.cpp +273 -0
  152. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/ServicesPage.h +123 -0
  153. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/SharedSecret.cpp +115 -0
  154. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/SharedSecret.h +54 -0
  155. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/ControlPanel.dll.manifest +10 -0
  156. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/ControlPanel.exe.manifest +17 -0
  157. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/ControlPanel.manifest +17 -0
  158. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/ControlPanel.rc2 +13 -0
  159. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/ControlPanel64.manifest +17 -0
  160. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/EnergySaver.ico +0 -0
  161. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/controlpanel.ico +0 -0
  162. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/failure.ico +0 -0
  163. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/res/success.ico +0 -0
  164. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/resource.h +56 -0
  165. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/stdafx.cpp +20 -0
  166. package/android/src/main/jni/mdnsresponder/mDNSWindows/ControlPanel/stdafx.h +64 -0
  167. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/dll.aps +0 -0
  168. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/dll.rc +102 -0
  169. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/dllmain.c +112 -0
  170. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/dnssd.def +48 -0
  171. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/dnssd.vcproj +472 -0
  172. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL/resource.h +27 -0
  173. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/AssemblyInfo.cpp +84 -0
  174. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/PString.h +70 -0
  175. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/Stdafx.cpp +22 -0
  176. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/Stdafx.h +33 -0
  177. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/dnssd_NET.cpp +1234 -0
  178. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/dnssd_NET.h +1392 -0
  179. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/dnssd_NET.ico +0 -0
  180. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/dnssd_NET.rc +113 -0
  181. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/dnssd_NET.vcproj +446 -0
  182. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLL.NET/resource.h +3 -0
  183. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLStub/DLLStub.cpp +693 -0
  184. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLStub/DLLStub.h +52 -0
  185. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLStub/DLLStub.vcproj +324 -0
  186. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.cpp +208 -0
  187. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.def +35 -0
  188. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.idl +491 -0
  189. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.rc +126 -0
  190. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.rgs +11 -0
  191. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DLLX.vcproj +625 -0
  192. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSD.cpp +892 -0
  193. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDEventManager.cpp +31 -0
  194. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDEventManager.h +133 -0
  195. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDEventManager.rgs +27 -0
  196. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDRecord.cpp +101 -0
  197. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDRecord.h +185 -0
  198. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDRecord.rgs +27 -0
  199. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDService.cpp +2095 -0
  200. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDService.h +429 -0
  201. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/DNSSDService.rgs +27 -0
  202. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/StringServices.cpp +344 -0
  203. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/StringServices.h +102 -0
  204. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/TXTRecord.cpp +381 -0
  205. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/TXTRecord.h +203 -0
  206. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/TXTRecord.rgs +27 -0
  207. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/_IDNSSDEvents_CP.h +358 -0
  208. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/dlldatax.c +51 -0
  209. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/dlldatax.h +49 -0
  210. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/resource.h +30 -0
  211. package/android/src/main/jni/mdnsresponder/mDNSWindows/DLLX/stdafx.h +88 -0
  212. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/ApplicationVS2002.sln +21 -0
  213. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/ApplicationVS2002.vcproj +253 -0
  214. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/ApplicationVS2003.sln +21 -0
  215. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/ApplicationVS2003.vcproj +267 -0
  216. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Resources/Application.ico +0 -0
  217. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Resources/Application.rc +323 -0
  218. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Resources/Application.rc2 +20 -0
  219. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Resources/Resource.h +53 -0
  220. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.cpp +71 -0
  221. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.h +62 -0
  222. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/Application.cpp +111 -0
  223. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/Application.h +68 -0
  224. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp +1426 -0
  225. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.h +131 -0
  226. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/LoginDialog.cpp +109 -0
  227. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/LoginDialog.h +53 -0
  228. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/StdAfx.cpp +18 -0
  229. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/StdAfx.h +48 -0
  230. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Application.vcc +37 -0
  231. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Application.vcp +868 -0
  232. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Application.vcw +29 -0
  233. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/Application.ico +0 -0
  234. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/Application.rc +194 -0
  235. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/Application.rc2 +13 -0
  236. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/newres.h +28 -0
  237. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/resource.h +22 -0
  238. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/Application.cpp +92 -0
  239. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/Application.h +57 -0
  240. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp +394 -0
  241. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.h +84 -0
  242. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/StdAfx.cpp +18 -0
  243. package/android/src/main/jni/mdnsresponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/StdAfx.h +46 -0
  244. package/android/src/main/jni/mdnsresponder/mDNSWindows/Java/Java.vcproj +111 -0
  245. package/android/src/main/jni/mdnsresponder/mDNSWindows/Java/jdns_sd.rc +62 -0
  246. package/android/src/main/jni/mdnsresponder/mDNSWindows/Java/makefile +143 -0
  247. package/android/src/main/jni/mdnsresponder/mDNSWindows/Java/makefile64 +143 -0
  248. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/NSPTool.aps +0 -0
  249. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/NSPTool.c +581 -0
  250. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/NSPTool.rc +103 -0
  251. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/NSPTool.vcproj +409 -0
  252. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/Prefix.h +28 -0
  253. package/android/src/main/jni/mdnsresponder/mDNSWindows/NSPTool/resource.h +27 -0
  254. package/android/src/main/jni/mdnsresponder/mDNSWindows/PosixCompat.c +128 -0
  255. package/android/src/main/jni/mdnsresponder/mDNSWindows/PosixCompat.h +70 -0
  256. package/android/src/main/jni/mdnsresponder/mDNSWindows/README.txt +85 -0
  257. package/android/src/main/jni/mdnsresponder/mDNSWindows/RegNames.h +57 -0
  258. package/android/src/main/jni/mdnsresponder/mDNSWindows/Secret.c +338 -0
  259. package/android/src/main/jni/mdnsresponder/mDNSWindows/Secret.h +42 -0
  260. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/EventLog.mc +11 -0
  261. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/EventLogMessages.bin +0 -0
  262. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Firewall.cpp +484 -0
  263. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Firewall.h +79 -0
  264. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Prefix.h +30 -0
  265. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.aps +0 -0
  266. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.c +2669 -0
  267. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.h +30 -0
  268. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.mcp +0 -0
  269. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.rc +114 -0
  270. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/Service.vcproj +562 -0
  271. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/main.c +32 -0
  272. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/res/mDNSResponder.manifest +12 -0
  273. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/res/mDNSResponder64.manifest +12 -0
  274. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/resource.h +17 -0
  275. package/android/src/main/jni/mdnsresponder/mDNSWindows/SystemService/resrc1.h +15 -0
  276. package/android/src/main/jni/mdnsresponder/mDNSWindows/VPCDetect.cpp +165 -0
  277. package/android/src/main/jni/mdnsresponder/mDNSWindows/VPCDetect.h +36 -0
  278. package/android/src/main/jni/mdnsresponder/mDNSWindows/WinServices.cpp +93 -0
  279. package/android/src/main/jni/mdnsresponder/mDNSWindows/WinServices.h +34 -0
  280. package/android/src/main/jni/mdnsresponder/mDNSWindows/WinVersRes.h +35 -0
  281. package/android/src/main/jni/mdnsresponder/mDNSWindows/isocode.h +135 -0
  282. package/android/src/main/jni/mdnsresponder/mDNSWindows/loclibrary.c +268 -0
  283. package/android/src/main/jni/mdnsresponder/mDNSWindows/loclibrary.h +54 -0
  284. package/android/src/main/jni/mdnsresponder/mDNSWindows/mDNSWin32.c +5200 -0
  285. package/android/src/main/jni/mdnsresponder/mDNSWindows/mDNSWin32.h +208 -0
  286. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/ReadMe.txt +15 -0
  287. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/mdnsNSP.aps +0 -0
  288. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/mdnsNSP.c +2430 -0
  289. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/mdnsNSP.def +24 -0
  290. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/mdnsNSP.rc +104 -0
  291. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/mdnsNSP.vcproj +457 -0
  292. package/android/src/main/jni/mdnsresponder/mDNSWindows/mdnsNSP/resource.h +27 -0
  293. package/android/src/main/jni/mdnsresponder/mdnsd.rc +7 -0
  294. package/android/src/main/jni/nameser.h +588 -0
  295. package/dist/index.js +160 -1
  296. package/index.d.ts +91 -0
  297. package/ios/RNZeroconf/RNNetServiceSerializer.m +7 -3
  298. package/ios/RNZeroconf/RNZeroconf.m +8 -0
  299. package/package.json +25 -17
  300. package/src/index.js +183 -0
@@ -0,0 +1,3146 @@
1
+ /* -*- Mode: C; tab-width: 4 -*-
2
+ *
3
+ * Copyright (c) 2002-2004 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 __APPLE__
19
+ // In Mac OS X 10.5 and later trying to use the daemon function gives a “‘daemon’ is deprecated”
20
+ // error, which prevents compilation because we build with "-Werror".
21
+ // Since this is supposed to be portable cross-platform code, we don't care that daemon is
22
+ // deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
23
+ #define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
24
+ #endif
25
+
26
+ #include <signal.h>
27
+ #include <pthread.h>
28
+ #include <stdlib.h>
29
+ #include <unistd.h>
30
+ #include <sys/types.h>
31
+ #include <sys/socket.h>
32
+ #include <netinet/in.h>
33
+ #include <arpa/inet.h>
34
+ #include <stdio.h>
35
+ #include <syslog.h>
36
+ #include <string.h>
37
+ #include <sys/time.h>
38
+ #include <sys/resource.h>
39
+ #include <time.h>
40
+ #include <errno.h>
41
+
42
+ #if __APPLE__
43
+ #undef daemon
44
+ extern int daemon(int, int);
45
+ #endif
46
+
47
+ // Solaris doesn't have daemon(), so we define it here
48
+ #ifdef NOT_HAVE_DAEMON
49
+ #include "../mDNSPosix/mDNSUNP.h" // For daemon()
50
+ #endif // NOT_HAVE_DAEMON
51
+
52
+ #include "dnsextd.h"
53
+ #include "../mDNSShared/uds_daemon.h"
54
+ #include "../mDNSShared/dnssd_ipc.h"
55
+ #include "../mDNSCore/uDNS.h"
56
+ #include "../mDNSShared/DebugServices.h"
57
+
58
+ // Compatibility workaround
59
+ #ifndef AF_LOCAL
60
+ #define AF_LOCAL AF_UNIX
61
+ #endif
62
+
63
+ //
64
+ // Constants
65
+ //
66
+ mDNSexport const char ProgramName[] = "dnsextd";
67
+
68
+ #define LOOPBACK "127.0.0.1"
69
+ #if !defined(LISTENQ)
70
+ # define LISTENQ 128 // tcp connection backlog
71
+ #endif
72
+ #define RECV_BUFLEN 9000
73
+ #define LEASETABLE_INIT_NBUCKETS 256 // initial hashtable size (doubles as table fills)
74
+ #define EXPIRATION_INTERVAL 300 // check for expired records every 5 minutes
75
+ #define SRV_TTL 7200 // TTL For _dns-update SRV records
76
+ #define CONFIG_FILE "/etc/dnsextd.conf"
77
+ #define TCP_SOCKET_FLAGS kTCPSocketFlags_UseTLS
78
+
79
+ // LLQ Lease bounds (seconds)
80
+ #define LLQ_MIN_LEASE (15 * 60)
81
+ #define LLQ_MAX_LEASE (120 * 60)
82
+ #define LLQ_LEASE_FUDGE 60
83
+
84
+ // LLQ SOA poll interval (microseconds)
85
+ #define LLQ_MONITOR_ERR_INTERVAL (60 * 1000000)
86
+ #define LLQ_MONITOR_INTERVAL 250000
87
+ #ifdef SIGINFO
88
+ #define INFO_SIGNAL SIGINFO
89
+ #else
90
+ #define INFO_SIGNAL SIGUSR1
91
+ #endif
92
+
93
+ #define SAME_INADDR(x,y) (*((mDNSu32 *)&x) == *((mDNSu32 *)&y))
94
+
95
+ //
96
+ // Data Structures
97
+ // Structs/fields that must be locked for thread safety are explicitly commented
98
+ //
99
+
100
+ // args passed to UDP request handler thread as void*
101
+
102
+ typedef struct
103
+ {
104
+ PktMsg pkt;
105
+ struct sockaddr_in cliaddr;
106
+ DaemonInfo *d;
107
+ int sd;
108
+ } UDPContext;
109
+
110
+ // args passed to TCP request handler thread as void*
111
+ typedef struct
112
+ {
113
+ PktMsg pkt;
114
+ struct sockaddr_in cliaddr;
115
+ TCPSocket *sock; // socket connected to client
116
+ DaemonInfo *d;
117
+ } TCPContext;
118
+
119
+ // args passed to UpdateAnswerList thread as void*
120
+ typedef struct
121
+ {
122
+ DaemonInfo *d;
123
+ AnswerListElem *a;
124
+ } UpdateAnswerListArgs;
125
+
126
+ //
127
+ // Global Variables
128
+ //
129
+
130
+ // booleans to determine runtime output
131
+ // read-only after initialization (no mutex protection)
132
+ static mDNSBool foreground = 0;
133
+ static mDNSBool verbose = 0;
134
+
135
+ // globals set via signal handler (accessed exclusively by main select loop and signal handler)
136
+ static mDNSBool terminate = 0;
137
+ static mDNSBool dumptable = 0;
138
+ static mDNSBool hangup = 0;
139
+
140
+ // global for config file location
141
+ static char * cfgfile = NULL;
142
+
143
+ //
144
+ // Logging Routines
145
+ // Log messages are delivered to syslog unless -f option specified
146
+ //
147
+
148
+ // common message logging subroutine
149
+ mDNSlocal void PrintLog(const char *buffer)
150
+ {
151
+ if (foreground)
152
+ {
153
+ fprintf(stderr,"%s\n", buffer);
154
+ fflush(stderr);
155
+ }
156
+ else
157
+ {
158
+ openlog("dnsextd", LOG_CONS, LOG_DAEMON);
159
+ syslog(LOG_ERR, "%s", buffer);
160
+ closelog();
161
+ }
162
+ }
163
+
164
+ // Verbose Logging (conditional on -v option)
165
+ mDNSlocal void VLog(const char *format, ...)
166
+ {
167
+ char buffer[512];
168
+ va_list ptr;
169
+
170
+ if (!verbose) return;
171
+ va_start(ptr,format);
172
+ buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
173
+ va_end(ptr);
174
+ PrintLog(buffer);
175
+ }
176
+
177
+ // Unconditional Logging
178
+ mDNSlocal void Log(const char *format, ...)
179
+ {
180
+ char buffer[512];
181
+ va_list ptr;
182
+
183
+ va_start(ptr,format);
184
+ buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
185
+ va_end(ptr);
186
+ PrintLog(buffer);
187
+ }
188
+
189
+ // Error Logging
190
+ // prints message "dnsextd <function>: <operation> - <error message>"
191
+ // must be compiled w/ -D_REENTRANT for thread-safe errno usage
192
+ mDNSlocal void LogErr(const char *fn, const char *operation)
193
+ {
194
+ char buf[512], errbuf[256];
195
+ strerror_r(errno, errbuf, sizeof(errbuf));
196
+ snprintf(buf, sizeof(buf), "%s: %s - %s", fn, operation, errbuf);
197
+ PrintLog(buf);
198
+ }
199
+
200
+ //
201
+ // Networking Utility Routines
202
+ //
203
+
204
+ // Convert DNS Message Header from Network to Host byte order
205
+ mDNSlocal void HdrNToH(PktMsg *pkt)
206
+ {
207
+ // Read the integer parts which are in IETF byte-order (MSB first, LSB second)
208
+ mDNSu8 *ptr = (mDNSu8 *)&pkt->msg.h.numQuestions;
209
+ pkt->msg.h.numQuestions = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]);
210
+ pkt->msg.h.numAnswers = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]);
211
+ pkt->msg.h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]);
212
+ pkt->msg.h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]);
213
+ }
214
+
215
+ // Convert DNS Message Header from Host to Network byte order
216
+ mDNSlocal void HdrHToN(PktMsg *pkt)
217
+ {
218
+ mDNSu16 numQuestions = pkt->msg.h.numQuestions;
219
+ mDNSu16 numAnswers = pkt->msg.h.numAnswers;
220
+ mDNSu16 numAuthorities = pkt->msg.h.numAuthorities;
221
+ mDNSu16 numAdditionals = pkt->msg.h.numAdditionals;
222
+ mDNSu8 *ptr = (mDNSu8 *)&pkt->msg.h.numQuestions;
223
+
224
+ // Put all the integer values in IETF byte-order (MSB first, LSB second)
225
+ *ptr++ = (mDNSu8)(numQuestions >> 8);
226
+ *ptr++ = (mDNSu8)(numQuestions & 0xFF);
227
+ *ptr++ = (mDNSu8)(numAnswers >> 8);
228
+ *ptr++ = (mDNSu8)(numAnswers & 0xFF);
229
+ *ptr++ = (mDNSu8)(numAuthorities >> 8);
230
+ *ptr++ = (mDNSu8)(numAuthorities & 0xFF);
231
+ *ptr++ = (mDNSu8)(numAdditionals >> 8);
232
+ *ptr++ = (mDNSu8)(numAdditionals & 0xFF);
233
+ }
234
+
235
+
236
+ // Add socket to event loop
237
+
238
+ mDNSlocal mStatus AddSourceToEventLoop( DaemonInfo * self, TCPSocket *sock, EventCallback callback, void *context )
239
+ {
240
+ EventSource * newSource;
241
+ mStatus err = mStatus_NoError;
242
+
243
+ if ( self->eventSources.LinkOffset == 0 )
244
+ {
245
+ InitLinkedList( &self->eventSources, offsetof( EventSource, next));
246
+ }
247
+
248
+ newSource = ( EventSource*) malloc( sizeof *newSource );
249
+ if ( newSource == NULL )
250
+ {
251
+ err = mStatus_NoMemoryErr;
252
+ goto exit;
253
+ }
254
+
255
+ newSource->callback = callback;
256
+ newSource->context = context;
257
+ newSource->sock = sock;
258
+ newSource->fd = mDNSPlatformTCPGetFD( sock );
259
+
260
+ AddToTail( &self->eventSources, newSource );
261
+
262
+ exit:
263
+
264
+ return err;
265
+ }
266
+
267
+
268
+ // Remove socket from event loop
269
+
270
+ mDNSlocal mStatus RemoveSourceFromEventLoop( DaemonInfo * self, TCPSocket *sock )
271
+ {
272
+ EventSource * source;
273
+ mStatus err;
274
+
275
+ for ( source = ( EventSource* ) self->eventSources.Head; source; source = source->next )
276
+ {
277
+ if ( source->sock == sock )
278
+ {
279
+ RemoveFromList( &self->eventSources, source );
280
+
281
+ free( source );
282
+ err = mStatus_NoError;
283
+ goto exit;
284
+ }
285
+ }
286
+
287
+ err = mStatus_NoSuchNameErr;
288
+
289
+ exit:
290
+
291
+ return err;
292
+ }
293
+
294
+ // create a socket connected to nameserver
295
+ // caller terminates connection via close()
296
+ mDNSlocal TCPSocket *ConnectToServer(DaemonInfo *d)
297
+ {
298
+ int ntries = 0, retry = 0;
299
+
300
+ while (1)
301
+ {
302
+ mDNSIPPort port = zeroIPPort;
303
+ int fd;
304
+
305
+ TCPSocket *sock = mDNSPlatformTCPSocket( NULL, 0, &port );
306
+ if ( !sock ) { LogErr("ConnectToServer", "socket"); return NULL; }
307
+ fd = mDNSPlatformTCPGetFD( sock );
308
+ if (!connect( fd, (struct sockaddr *)&d->ns_addr, sizeof(d->ns_addr))) return sock;
309
+ mDNSPlatformTCPCloseConnection( sock );
310
+ if (++ntries < 10)
311
+ {
312
+ LogErr("ConnectToServer", "connect");
313
+ Log("ConnectToServer - retrying connection");
314
+ if (!retry) retry = 500000 + random() % 500000;
315
+ usleep(retry);
316
+ retry *= 2;
317
+ }
318
+ else { Log("ConnectToServer - %d failed attempts. Aborting.", ntries); return NULL; }
319
+ }
320
+ }
321
+
322
+ // send an entire block of data over a connected socket
323
+ mDNSlocal int MySend(TCPSocket *sock, const void *msg, int len)
324
+ {
325
+ int selectval, n, nsent = 0;
326
+ fd_set wset;
327
+ struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short
328
+
329
+ while (nsent < len)
330
+ {
331
+ int fd;
332
+
333
+ FD_ZERO(&wset);
334
+
335
+ fd = mDNSPlatformTCPGetFD( sock );
336
+
337
+ FD_SET( fd, &wset );
338
+ selectval = select( fd+1, NULL, &wset, NULL, &timeout);
339
+ if (selectval < 0) { LogErr("MySend", "select"); return -1; }
340
+ if (!selectval || !FD_ISSET(fd, &wset)) { Log("MySend - timeout"); return -1; }
341
+
342
+ n = mDNSPlatformWriteTCP( sock, ( char* ) msg + nsent, len - nsent);
343
+
344
+ if (n < 0) { LogErr("MySend", "send"); return -1; }
345
+ nsent += n;
346
+ }
347
+ return 0;
348
+ }
349
+
350
+ // Transmit a DNS message, prefixed by its length, over TCP, blocking if necessary
351
+ mDNSlocal int SendPacket(TCPSocket *sock, PktMsg *pkt)
352
+ {
353
+ // send the lenth, in network byte order
354
+ mDNSu16 len = htons((mDNSu16)pkt->len);
355
+ if (MySend(sock, &len, sizeof(len)) < 0) return -1;
356
+
357
+ // send the message
358
+ VLog("SendPacket Q:%d A:%d A:%d A:%d ",
359
+ ntohs(pkt->msg.h.numQuestions),
360
+ ntohs(pkt->msg.h.numAnswers),
361
+ ntohs(pkt->msg.h.numAuthorities),
362
+ ntohs(pkt->msg.h.numAdditionals));
363
+ return MySend(sock, &pkt->msg, pkt->len);
364
+ }
365
+
366
+ // Receive len bytes, waiting until we have all of them.
367
+ // Returns number of bytes read (which should always be the number asked for).
368
+ static int my_recv(TCPSocket *sock, void *const buf, const int len, mDNSBool * closed)
369
+ {
370
+ // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions;
371
+ // use an explicit while() loop instead.
372
+ // Also, don't try to do '+=' arithmetic on the original "void *" pointer --
373
+ // arithmetic on "void *" pointers is compiler-dependent.
374
+
375
+ fd_set rset;
376
+ struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short
377
+ int selectval, remaining = len;
378
+ char *ptr = (char *)buf;
379
+ ssize_t num_read;
380
+
381
+ while (remaining)
382
+ {
383
+ int fd;
384
+
385
+ fd = mDNSPlatformTCPGetFD( sock );
386
+
387
+ FD_ZERO(&rset);
388
+ FD_SET(fd, &rset);
389
+ selectval = select(fd+1, &rset, NULL, NULL, &timeout);
390
+ if (selectval < 0) { LogErr("my_recv", "select"); return -1; }
391
+ if (!selectval || !FD_ISSET(fd, &rset))
392
+ {
393
+ Log("my_recv - timeout");
394
+ return -1;
395
+ }
396
+
397
+ num_read = mDNSPlatformReadTCP( sock, ptr, remaining, closed );
398
+
399
+ if (((num_read == 0) && *closed) || (num_read < 0) || (num_read > remaining)) return -1;
400
+ if (num_read == 0) return 0;
401
+ ptr += num_read;
402
+ remaining -= num_read;
403
+ }
404
+ return(len);
405
+ }
406
+
407
+ // Return a DNS Message read off of a TCP socket, or NULL on failure
408
+ // If storage is non-null, result is placed in that buffer. Otherwise,
409
+ // returned value is allocated with Malloc, and contains sufficient extra
410
+ // storage for a Lease OPT RR
411
+
412
+ mDNSlocal PktMsg*
413
+ RecvPacket
414
+ (
415
+ TCPSocket * sock,
416
+ PktMsg * storage,
417
+ mDNSBool * closed
418
+ )
419
+ {
420
+ int nread;
421
+ int allocsize;
422
+ mDNSu16 msglen = 0;
423
+ PktMsg * pkt = NULL;
424
+ unsigned int srclen;
425
+ int fd;
426
+ mStatus err = 0;
427
+
428
+ fd = mDNSPlatformTCPGetFD( sock );
429
+
430
+ nread = my_recv( sock, &msglen, sizeof( msglen ), closed );
431
+
432
+ require_action_quiet( nread != -1, exit, err = mStatus_UnknownErr );
433
+ require_action_quiet( nread > 0, exit, err = mStatus_NoError );
434
+
435
+ msglen = ntohs( msglen );
436
+ require_action_quiet( nread == sizeof( msglen ), exit, err = mStatus_UnknownErr; Log( "Could not read length field of message") );
437
+
438
+ if ( storage )
439
+ {
440
+ require_action_quiet( msglen <= sizeof( storage->msg ), exit, err = mStatus_UnknownErr; Log( "RecvPacket: provided buffer too small." ) );
441
+ pkt = storage;
442
+ }
443
+ else
444
+ {
445
+ // buffer extra space to add an OPT RR
446
+
447
+ if ( msglen > sizeof(DNSMessage))
448
+ {
449
+ allocsize = sizeof(PktMsg) - sizeof(DNSMessage) + msglen;
450
+ }
451
+ else
452
+ {
453
+ allocsize = sizeof(PktMsg);
454
+ }
455
+
456
+ pkt = malloc(allocsize);
457
+ require_action_quiet( pkt, exit, err = mStatus_NoMemoryErr; LogErr( "RecvPacket", "malloc" ) );
458
+ mDNSPlatformMemZero( pkt, sizeof( *pkt ) );
459
+ }
460
+
461
+ pkt->len = msglen;
462
+ srclen = sizeof(pkt->src);
463
+
464
+ if ( getpeername( fd, ( struct sockaddr* ) &pkt->src, &srclen ) || ( srclen != sizeof( pkt->src ) ) )
465
+ {
466
+ LogErr("RecvPacket", "getpeername");
467
+ mDNSPlatformMemZero(&pkt->src, sizeof(pkt->src));
468
+ }
469
+
470
+ nread = my_recv(sock, &pkt->msg, msglen, closed );
471
+ require_action_quiet( nread >= 0, exit, err = mStatus_UnknownErr ; LogErr( "RecvPacket", "recv" ) );
472
+ require_action_quiet( nread == msglen, exit, err = mStatus_UnknownErr ; Log( "Could not read entire message" ) );
473
+ require_action_quiet( pkt->len >= sizeof( DNSMessageHeader ), exit, err = mStatus_UnknownErr ; Log( "RecvPacket: Message too short (%d bytes)", pkt->len ) );
474
+
475
+ exit:
476
+
477
+ if ( err && pkt )
478
+ {
479
+ if ( pkt != storage )
480
+ {
481
+ free(pkt);
482
+ }
483
+
484
+ pkt = NULL;
485
+ }
486
+
487
+ return pkt;
488
+ }
489
+
490
+
491
+ mDNSlocal DNSZone*
492
+ FindZone
493
+ (
494
+ DaemonInfo * self,
495
+ domainname * name
496
+ )
497
+ {
498
+ DNSZone * zone;
499
+
500
+ for ( zone = self->zones; zone; zone = zone->next )
501
+ {
502
+ if ( SameDomainName( &zone->name, name ) )
503
+ {
504
+ break;
505
+ }
506
+ }
507
+
508
+ return zone;
509
+ }
510
+
511
+
512
+ mDNSlocal mDNSBool
513
+ ZoneHandlesName
514
+ (
515
+ const domainname * zname,
516
+ const domainname * dname
517
+ )
518
+ {
519
+ mDNSu16 i = DomainNameLength( zname );
520
+ mDNSu16 j = DomainNameLength( dname );
521
+
522
+ if ( ( i == ( MAX_DOMAIN_NAME + 1 ) ) || ( j == ( MAX_DOMAIN_NAME + 1 ) ) || ( i > j ) || ( memcmp( zname->c, dname->c + ( j - i ), i ) != 0 ) )
523
+ {
524
+ return mDNSfalse;
525
+ }
526
+
527
+ return mDNStrue;
528
+ }
529
+
530
+
531
+ mDNSlocal mDNSBool IsQuery( PktMsg * pkt )
532
+ {
533
+ return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery );
534
+ }
535
+
536
+
537
+ mDNSlocal mDNSBool IsUpdate( PktMsg * pkt )
538
+ {
539
+ return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_OP_Update );
540
+ }
541
+
542
+
543
+ mDNSlocal mDNSBool IsNotify(PktMsg *pkt)
544
+ {
545
+ return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == ( mDNSu8) ( kDNSFlag0_OP_Notify );
546
+ }
547
+
548
+
549
+ mDNSlocal mDNSBool IsLLQRequest(PktMsg *pkt)
550
+ {
551
+ const mDNSu8 *ptr = NULL, *end = (mDNSu8 *)&pkt->msg + pkt->len;
552
+ LargeCacheRecord lcr;
553
+ int i;
554
+ mDNSBool result = mDNSfalse;
555
+
556
+ HdrNToH(pkt);
557
+ if ((mDNSu8)(pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (mDNSu8)(kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery)) goto end;
558
+
559
+ if (!pkt->msg.h.numAdditionals) goto end;
560
+ ptr = LocateAdditionals(&pkt->msg, end);
561
+ if (!ptr) goto end;
562
+
563
+ // find last Additional info.
564
+ for (i = 0; i < pkt->msg.h.numAdditionals; i++)
565
+ {
566
+ ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr);
567
+ if (!ptr) { Log("Unable to read additional record"); goto end; }
568
+ }
569
+
570
+ if ( lcr.r.resrec.rrtype == kDNSType_OPT && lcr.r.resrec.rdlength >= DNSOpt_LLQData_Space && lcr.r.resrec.rdata->u.opt[0].opt == kDNSOpt_LLQ )
571
+ {
572
+ result = mDNStrue;
573
+ }
574
+
575
+ end:
576
+ HdrHToN(pkt);
577
+ return result;
578
+ }
579
+
580
+ // !!!KRS implement properly
581
+ mDNSlocal mDNSBool IsLLQAck(PktMsg *pkt)
582
+ {
583
+ if ((pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery ) &&
584
+ pkt->msg.h.numQuestions && !pkt->msg.h.numAnswers && !pkt->msg.h.numAuthorities) return mDNStrue;
585
+ return mDNSfalse;
586
+ }
587
+
588
+
589
+ mDNSlocal mDNSBool
590
+ IsPublicSRV
591
+ (
592
+ DaemonInfo * self,
593
+ DNSQuestion * q
594
+ )
595
+ {
596
+ DNameListElem * elem;
597
+ mDNSBool ret = mDNSfalse;
598
+ int i = ( int ) DomainNameLength( &q->qname ) - 1;
599
+
600
+ for ( elem = self->public_names; elem; elem = elem->next )
601
+ {
602
+ int j = ( int ) DomainNameLength( &elem->name ) - 1;
603
+
604
+ if ( i > j )
605
+ {
606
+ for ( ; i >= 0; i--, j-- )
607
+ {
608
+ if ( q->qname.c[ i ] != elem->name.c[ j ] )
609
+ {
610
+ ret = mDNStrue;
611
+ goto exit;
612
+ }
613
+ }
614
+ }
615
+ }
616
+
617
+ exit:
618
+
619
+ return ret;
620
+ }
621
+
622
+
623
+ mDNSlocal void
624
+ SetZone
625
+ (
626
+ DaemonInfo * self,
627
+ PktMsg * pkt
628
+ )
629
+ {
630
+ domainname zname;
631
+ mDNSu8 QR_OP;
632
+ const mDNSu8 * ptr = pkt->msg.data;
633
+ mDNSBool exception = mDNSfalse;
634
+
635
+ // Initialize
636
+
637
+ pkt->zone = NULL;
638
+ pkt->isZonePublic = mDNStrue;
639
+ zname.c[0] = '\0';
640
+
641
+ // Figure out what type of packet this is
642
+
643
+ QR_OP = ( mDNSu8 ) ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask );
644
+
645
+ if ( IsQuery( pkt ) )
646
+ {
647
+ DNSQuestion question;
648
+
649
+ // It's a query
650
+
651
+ ptr = getQuestion( &pkt->msg, ptr, ( ( mDNSu8* ) &pkt->msg ) + pkt->len, NULL, &question );
652
+
653
+ AppendDomainName( &zname, &question.qname );
654
+
655
+ exception = ( ( question.qtype == kDNSType_SOA ) || ( question.qtype == kDNSType_NS ) || ( ( question.qtype == kDNSType_SRV ) && IsPublicSRV( self, &question ) ) );
656
+ }
657
+ else if ( IsUpdate( pkt ) )
658
+ {
659
+ DNSQuestion question;
660
+
661
+ // It's an update. The format of the zone section is the same as the format for the question section
662
+ // according to RFC 2136, so we'll just treat this as a question so we can get at the zone.
663
+
664
+ ptr = getQuestion( &pkt->msg, ptr, ( ( mDNSu8* ) &pkt->msg ) + pkt->len, NULL, &question );
665
+
666
+ AppendDomainName( &zname, &question.qname );
667
+
668
+ exception = mDNSfalse;
669
+ }
670
+
671
+ if ( zname.c[0] != '\0' )
672
+ {
673
+ // Find the right zone
674
+
675
+ for ( pkt->zone = self->zones; pkt->zone; pkt->zone = pkt->zone->next )
676
+ {
677
+ if ( ZoneHandlesName( &pkt->zone->name, &zname ) )
678
+ {
679
+ VLog( "found correct zone %##s for query", pkt->zone->name.c );
680
+
681
+ pkt->isZonePublic = ( ( pkt->zone->type == kDNSZonePublic ) || exception );
682
+
683
+ VLog( "zone %##s is %s", pkt->zone->name.c, ( pkt->isZonePublic ) ? "public" : "private" );
684
+
685
+ break;
686
+ }
687
+ }
688
+ }
689
+ }
690
+
691
+
692
+ mDNSlocal int
693
+ UDPServerTransaction(const DaemonInfo *d, const PktMsg *request, PktMsg *reply, mDNSBool *trunc)
694
+ {
695
+ fd_set rset;
696
+ struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short
697
+ int sd;
698
+ int res;
699
+ mStatus err = mStatus_NoError;
700
+
701
+ // Initialize
702
+
703
+ *trunc = mDNSfalse;
704
+
705
+ // Create a socket
706
+
707
+ sd = socket( AF_INET, SOCK_DGRAM, 0 );
708
+ require_action( sd >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "socket" ) );
709
+
710
+ // Send the packet to the nameserver
711
+
712
+ VLog("UDPServerTransaction Q:%d A:%d A:%d A:%d ",
713
+ ntohs(request->msg.h.numQuestions),
714
+ ntohs(request->msg.h.numAnswers),
715
+ ntohs(request->msg.h.numAuthorities),
716
+ ntohs(request->msg.h.numAdditionals));
717
+ res = sendto( sd, (char *)&request->msg, request->len, 0, ( struct sockaddr* ) &d->ns_addr, sizeof( d->ns_addr ) );
718
+ require_action( res == (int) request->len, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "sendto" ) );
719
+
720
+ // Wait for reply
721
+
722
+ FD_ZERO( &rset );
723
+ FD_SET( sd, &rset );
724
+ res = select( sd + 1, &rset, NULL, NULL, &timeout );
725
+ require_action( res >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "select" ) );
726
+ require_action( ( res > 0 ) && FD_ISSET( sd, &rset ), exit, err = mStatus_UnknownErr; Log( "UDPServerTransaction - timeout" ) );
727
+
728
+ // Receive reply
729
+
730
+ reply->len = recvfrom( sd, &reply->msg, sizeof(reply->msg), 0, NULL, NULL );
731
+ require_action( ( ( int ) reply->len ) >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "recvfrom" ) );
732
+ require_action( reply->len >= sizeof( DNSMessageHeader ), exit, err = mStatus_UnknownErr; Log( "UDPServerTransaction - Message too short (%d bytes)", reply->len ) );
733
+
734
+ // Check for truncation bit
735
+
736
+ if ( reply->msg.h.flags.b[0] & kDNSFlag0_TC )
737
+ {
738
+ *trunc = mDNStrue;
739
+ }
740
+
741
+ exit:
742
+
743
+ if ( sd >= 0 )
744
+ {
745
+ close( sd );
746
+ }
747
+
748
+ return err;
749
+ }
750
+
751
+ //
752
+ // Dynamic Update Utility Routines
753
+ //
754
+
755
+ // check if a request and server response complete a successful dynamic update
756
+ mDNSlocal mDNSBool SuccessfulUpdateTransaction(PktMsg *request, PktMsg *reply)
757
+ {
758
+ char buf[32];
759
+ char *vlogmsg = NULL;
760
+
761
+ // check messages
762
+ if (!request || !reply) { vlogmsg = "NULL message"; goto failure; }
763
+ if (request->len < sizeof(DNSMessageHeader) || reply->len < sizeof(DNSMessageHeader)) { vlogmsg = "Malformatted message"; goto failure; }
764
+
765
+ // check request operation
766
+ if ((request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask))
767
+ { vlogmsg = "Request opcode not an update"; goto failure; }
768
+
769
+ // check result
770
+ if ((reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask)) { vlogmsg = "Reply contains non-zero rcode"; goto failure; }
771
+ if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_OP_Update | kDNSFlag0_QR_Response))
772
+ { vlogmsg = "Reply opcode not an update response"; goto failure; }
773
+
774
+ VLog("Successful update from %s", inet_ntop(AF_INET, &request->src.sin_addr, buf, 32));
775
+ return mDNStrue;
776
+
777
+ failure:
778
+ VLog("Request %s: %s", inet_ntop(AF_INET, &request->src.sin_addr, buf, 32), vlogmsg);
779
+ return mDNSfalse;
780
+ }
781
+
782
+ // Allocate an appropriately sized CacheRecord and copy data from original.
783
+ // Name pointer in CacheRecord object is set to point to the name specified
784
+ //
785
+ mDNSlocal CacheRecord *CopyCacheRecord(const CacheRecord *orig, domainname *name)
786
+ {
787
+ CacheRecord *cr;
788
+ size_t size = sizeof(*cr);
789
+ if (orig->resrec.rdlength > InlineCacheRDSize) size += orig->resrec.rdlength - InlineCacheRDSize;
790
+ cr = malloc(size);
791
+ if (!cr) { LogErr("CopyCacheRecord", "malloc"); return NULL; }
792
+ memcpy(cr, orig, size);
793
+ cr->resrec.rdata = (RData*)&cr->smallrdatastorage;
794
+ cr->resrec.name = name;
795
+
796
+ return cr;
797
+ }
798
+
799
+
800
+ //
801
+ // Lease Hashtable Utility Routines
802
+ //
803
+
804
+ // double hash table size
805
+ // caller must lock table prior to invocation
806
+ mDNSlocal void RehashTable(DaemonInfo *d)
807
+ {
808
+ RRTableElem *ptr, *tmp, **new;
809
+ int i, bucket, newnbuckets = d->nbuckets * 2;
810
+
811
+ VLog("Rehashing lease table (new size %d buckets)", newnbuckets);
812
+ new = malloc(sizeof(RRTableElem *) * newnbuckets);
813
+ if (!new) { LogErr("RehashTable", "malloc"); return; }
814
+ mDNSPlatformMemZero(new, newnbuckets * sizeof(RRTableElem *));
815
+
816
+ for (i = 0; i < d->nbuckets; i++)
817
+ {
818
+ ptr = d->table[i];
819
+ while (ptr)
820
+ {
821
+ bucket = ptr->rr.resrec.namehash % newnbuckets;
822
+ tmp = ptr;
823
+ ptr = ptr->next;
824
+ tmp->next = new[bucket];
825
+ new[bucket] = tmp;
826
+ }
827
+ }
828
+ d->nbuckets = newnbuckets;
829
+ free(d->table);
830
+ d->table = new;
831
+ }
832
+
833
+ // print entire contents of hashtable, invoked via SIGINFO
834
+ mDNSlocal void PrintLeaseTable(DaemonInfo *d)
835
+ {
836
+ int i;
837
+ RRTableElem *ptr;
838
+ char rrbuf[MaxMsg], addrbuf[16];
839
+ struct timeval now;
840
+ int hr, min, sec;
841
+
842
+ if (gettimeofday(&now, NULL)) { LogErr("PrintTable", "gettimeofday"); return; }
843
+ if (pthread_mutex_lock(&d->tablelock)) { LogErr("PrintTable", "pthread_mutex_lock"); return; }
844
+
845
+ Log("Dumping Lease Table Contents (table contains %d resource records)", d->nelems);
846
+ for (i = 0; i < d->nbuckets; i++)
847
+ {
848
+ for (ptr = d->table[i]; ptr; ptr = ptr->next)
849
+ {
850
+ hr = ((ptr->expire - now.tv_sec) / 60) / 60;
851
+ min = ((ptr->expire - now.tv_sec) / 60) % 60;
852
+ sec = (ptr->expire - now.tv_sec) % 60;
853
+ Log("Update from %s, Expires in %d:%d:%d\n\t%s", inet_ntop(AF_INET, &ptr->cli.sin_addr, addrbuf, 16), hr, min, sec,
854
+ GetRRDisplayString_rdb(&ptr->rr.resrec, &ptr->rr.resrec.rdata->u, rrbuf));
855
+ }
856
+ }
857
+ pthread_mutex_unlock(&d->tablelock);
858
+ }
859
+
860
+ //
861
+ // Startup SRV Registration Routines
862
+ // Register _dns-update._udp/_tcp.<zone> SRV records indicating the port on which
863
+ // the daemon accepts requests
864
+ //
865
+
866
+ // delete all RRS of a given name/type
867
+ mDNSlocal mDNSu8 *putRRSetDeletion(DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit, ResourceRecord *rr)
868
+ {
869
+ ptr = putDomainNameAsLabels(msg, ptr, limit, rr->name);
870
+ if (!ptr || ptr + 10 >= limit) return NULL; // out of space
871
+ ptr[0] = (mDNSu8)(rr->rrtype >> 8);
872
+ ptr[1] = (mDNSu8)(rr->rrtype & 0xFF);
873
+ ptr[2] = (mDNSu8)((mDNSu16)kDNSQClass_ANY >> 8);
874
+ ptr[3] = (mDNSu8)((mDNSu16)kDNSQClass_ANY & 0xFF);
875
+ mDNSPlatformMemZero(ptr+4, sizeof(rr->rroriginalttl) + sizeof(rr->rdlength)); // zero ttl/rdata
876
+ msg->h.mDNS_numUpdates++;
877
+ return ptr + 10;
878
+ }
879
+
880
+ mDNSlocal mDNSu8 *PutUpdateSRV(DaemonInfo *d, DNSZone * zone, PktMsg *pkt, mDNSu8 *ptr, char *regtype, mDNSIPPort port, mDNSBool registration)
881
+ {
882
+ AuthRecord rr;
883
+ char hostname[1024], buf[MaxMsg];
884
+ mDNSu8 *end = (mDNSu8 *)&pkt->msg + sizeof(DNSMessage);
885
+
886
+ ( void ) d;
887
+
888
+ mDNS_SetupResourceRecord(&rr, NULL, 0, kDNSType_SRV, SRV_TTL, kDNSRecordTypeUnique, AuthRecordAny, NULL, NULL);
889
+ rr.resrec.rrclass = kDNSClass_IN;
890
+ rr.resrec.rdata->u.srv.priority = 0;
891
+ rr.resrec.rdata->u.srv.weight = 0;
892
+ rr.resrec.rdata->u.srv.port = port;
893
+ if (gethostname(hostname, 1024) < 0 || !MakeDomainNameFromDNSNameString(&rr.resrec.rdata->u.srv.target, hostname))
894
+ rr.resrec.rdata->u.srv.target.c[0] = '\0';
895
+
896
+ MakeDomainNameFromDNSNameString(&rr.namestorage, regtype);
897
+ AppendDomainName(&rr.namestorage, &zone->name);
898
+ VLog("%s %s", registration ? "Registering SRV record" : "Deleting existing RRSet",
899
+ GetRRDisplayString_rdb(&rr.resrec, &rr.resrec.rdata->u, buf));
900
+ if (registration) ptr = PutResourceRecord(&pkt->msg, ptr, &pkt->msg.h.mDNS_numUpdates, &rr.resrec);
901
+ else ptr = putRRSetDeletion(&pkt->msg, ptr, end, &rr.resrec);
902
+ return ptr;
903
+ }
904
+
905
+
906
+ // perform dynamic update.
907
+ // specify deletion by passing false for the register parameter, otherwise register the records.
908
+ mDNSlocal int UpdateSRV(DaemonInfo *d, mDNSBool registration)
909
+ {
910
+ TCPSocket *sock = NULL;
911
+ DNSZone * zone;
912
+ int err = mStatus_NoError;
913
+
914
+ sock = ConnectToServer( d );
915
+ require_action( sock, exit, err = mStatus_UnknownErr; Log( "UpdateSRV: ConnectToServer failed" ) );
916
+
917
+ for ( zone = d->zones; zone; zone = zone->next )
918
+ {
919
+ PktMsg pkt;
920
+ mDNSu8 *ptr = pkt.msg.data;
921
+ mDNSu8 *end = (mDNSu8 *)&pkt.msg + sizeof(DNSMessage);
922
+ PktMsg *reply = NULL;
923
+ mDNSBool closed;
924
+ mDNSBool ok;
925
+
926
+ // Initialize message
927
+ InitializeDNSMessage(&pkt.msg.h, zeroID, UpdateReqFlags);
928
+ pkt.src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // address field set solely for verbose logging in subroutines
929
+ pkt.src.sin_family = AF_INET;
930
+
931
+ // format message body
932
+ ptr = putZone(&pkt.msg, ptr, end, &zone->name, mDNSOpaque16fromIntVal(kDNSClass_IN));
933
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
934
+
935
+ if ( zone->type == kDNSZonePrivate )
936
+ {
937
+ ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update-tls._tcp.", d->private_port, registration);
938
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
939
+ ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-query-tls._tcp.", d->private_port, registration);
940
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
941
+ ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq-tls._tcp.", d->private_port, registration);
942
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
943
+
944
+ if ( !registration )
945
+ {
946
+ ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update._udp.", d->llq_port, registration);
947
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
948
+ ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq._udp.", d->llq_port, registration);
949
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
950
+ }
951
+ }
952
+ else
953
+ {
954
+ if ( !registration )
955
+ {
956
+ ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update-tls.", d->private_port, registration);
957
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
958
+ ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-query-tls.", d->private_port, registration);
959
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
960
+ ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq-tls.", d->private_port, registration);
961
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
962
+ }
963
+
964
+ ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update._udp.", d->llq_port, registration);
965
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
966
+ ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq._udp.", d->llq_port, registration);
967
+ require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
968
+ }
969
+
970
+ HdrHToN(&pkt);
971
+
972
+ if ( zone->updateKeys )
973
+ {
974
+ DNSDigest_SignMessage( &pkt.msg, &ptr, zone->updateKeys, 0 );
975
+ require_action( ptr, exit, Log("UpdateSRV: Error constructing lease expiration update" ) );
976
+ }
977
+
978
+ pkt.len = ptr - (mDNSu8 *)&pkt.msg;
979
+
980
+ // send message, receive reply
981
+
982
+ err = SendPacket( sock, &pkt );
983
+ require_action( !err, exit, Log( "UpdateSRV: SendPacket failed" ) );
984
+
985
+ reply = RecvPacket( sock, NULL, &closed );
986
+ require_action( reply, exit, err = mStatus_UnknownErr; Log( "UpdateSRV: RecvPacket returned NULL" ) );
987
+
988
+ ok = SuccessfulUpdateTransaction( &pkt, reply );
989
+
990
+ if ( !ok )
991
+ {
992
+ Log("SRV record registration failed with rcode %d", reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask);
993
+ }
994
+
995
+ free( reply );
996
+ }
997
+
998
+ exit:
999
+
1000
+ if ( sock )
1001
+ {
1002
+ mDNSPlatformTCPCloseConnection( sock );
1003
+ }
1004
+
1005
+ return err;
1006
+ }
1007
+
1008
+ // wrapper routines/macros
1009
+ #define ClearUpdateSRV(d) UpdateSRV(d, 0)
1010
+
1011
+ // clear any existing records prior to registration
1012
+ mDNSlocal int SetUpdateSRV(DaemonInfo *d)
1013
+ {
1014
+ int err;
1015
+
1016
+ err = ClearUpdateSRV(d); // clear any existing record
1017
+ if (!err) err = UpdateSRV(d, 1);
1018
+ return err;
1019
+ }
1020
+
1021
+ //
1022
+ // Argument Parsing and Configuration
1023
+ //
1024
+
1025
+ mDNSlocal void PrintUsage(void)
1026
+ {
1027
+ fprintf(stderr, "Usage: dnsextd [-f <config file>] [-vhd] ...\n"
1028
+ "Use \"dnsextd -h\" for help\n");
1029
+ }
1030
+
1031
+ mDNSlocal void PrintHelp(void)
1032
+ {
1033
+ fprintf(stderr, "\n\n");
1034
+ PrintUsage();
1035
+
1036
+ fprintf(stderr,
1037
+ "dnsextd is a daemon that implements DNS extensions supporting Dynamic DNS Update Leases\n"
1038
+ "and Long Lived Queries, used in Wide-Area DNS Service Discovery, on behalf of name servers\n"
1039
+ "that do not natively support these extensions. (See dns-sd.org for more info on DNS Service\n"
1040
+ "Discovery, Update Leases, and Long Lived Queries.)\n\n"
1041
+
1042
+ "dnsextd requires one argument,the zone, which is the domain for which Update Leases\n"
1043
+ "and Long Lived Queries are to be administered. dnsextd communicates directly with the\n"
1044
+ "primary master server for this zone.\n\n"
1045
+
1046
+ "The options are as follows:\n\n"
1047
+
1048
+ "-f Specify configuration file. The default is /etc/dnsextd.conf.\n\n"
1049
+
1050
+ "-d Run daemon in foreground.\n\n"
1051
+
1052
+ "-h Print help.\n\n"
1053
+
1054
+ "-v Verbose output.\n\n"
1055
+ );
1056
+ }
1057
+
1058
+
1059
+ // Note: ProcessArgs called before process is daemonized, and therefore must open no descriptors
1060
+ // returns 0 (success) if program is to continue execution
1061
+ // output control arguments (-f, -v) do not affect this routine
1062
+ mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d)
1063
+ {
1064
+ DNSZone * zone;
1065
+ int opt;
1066
+ int err = 0;
1067
+
1068
+ cfgfile = strdup( CONFIG_FILE );
1069
+ require_action( cfgfile, arg_error, err = mStatus_NoMemoryErr );
1070
+
1071
+ // defaults, may be overriden by command option
1072
+
1073
+ // setup our sockaddr
1074
+
1075
+ mDNSPlatformMemZero( &d->addr, sizeof( d->addr ) );
1076
+ d->addr.sin_addr.s_addr = zerov4Addr.NotAnInteger;
1077
+ d->addr.sin_port = UnicastDNSPort.NotAnInteger;
1078
+ d->addr.sin_family = AF_INET;
1079
+ #ifndef NOT_HAVE_SA_LEN
1080
+ d->addr.sin_len = sizeof( d->addr );
1081
+ #endif
1082
+
1083
+ // setup nameserver's sockaddr
1084
+
1085
+ mDNSPlatformMemZero(&d->ns_addr, sizeof(d->ns_addr));
1086
+ d->ns_addr.sin_family = AF_INET;
1087
+ inet_pton( AF_INET, LOOPBACK, &d->ns_addr.sin_addr );
1088
+ d->ns_addr.sin_port = NSIPCPort.NotAnInteger;
1089
+ #ifndef NOT_HAVE_SA_LEN
1090
+ d->ns_addr.sin_len = sizeof( d->ns_addr );
1091
+ #endif
1092
+
1093
+ // setup our ports
1094
+
1095
+ d->private_port = PrivateDNSPort;
1096
+ d->llq_port = DNSEXTPort;
1097
+
1098
+ while ((opt = getopt(argc, argv, "f:hdv")) != -1)
1099
+ {
1100
+ switch(opt)
1101
+ {
1102
+ case 'f': free( cfgfile ); cfgfile = strdup( optarg ); require_action( cfgfile, arg_error, err = mStatus_NoMemoryErr ); break;
1103
+ case 'h': PrintHelp(); return -1;
1104
+ case 'd': foreground = 1; break; // Also used when launched via OS X's launchd mechanism
1105
+ case 'v': verbose = 1; break;
1106
+ default: goto arg_error;
1107
+ }
1108
+ }
1109
+
1110
+ err = ParseConfig( d, cfgfile );
1111
+ require_noerr( err, arg_error );
1112
+
1113
+ // Make sure we've specified some zones
1114
+
1115
+ require_action( d->zones, arg_error, err = mStatus_UnknownErr );
1116
+
1117
+ // if we have a shared secret, use it for the entire zone
1118
+
1119
+ for ( zone = d->zones; zone; zone = zone->next )
1120
+ {
1121
+ if ( zone->updateKeys )
1122
+ {
1123
+ AssignDomainName( &zone->updateKeys->domain, &zone->name );
1124
+ }
1125
+ }
1126
+
1127
+ return 0;
1128
+
1129
+ arg_error:
1130
+
1131
+ PrintUsage();
1132
+ return -1;
1133
+ }
1134
+
1135
+
1136
+ //
1137
+ // Initialization Routines
1138
+ //
1139
+
1140
+ // Allocate memory, initialize locks and bookkeeping variables
1141
+ mDNSlocal int InitLeaseTable(DaemonInfo *d)
1142
+ {
1143
+ if (pthread_mutex_init(&d->tablelock, NULL)) { LogErr("InitLeaseTable", "pthread_mutex_init"); return -1; }
1144
+ d->nbuckets = LEASETABLE_INIT_NBUCKETS;
1145
+ d->nelems = 0;
1146
+ d->table = malloc(sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS);
1147
+ if (!d->table) { LogErr("InitLeaseTable", "malloc"); return -1; }
1148
+ mDNSPlatformMemZero(d->table, sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS);
1149
+ return 0;
1150
+ }
1151
+
1152
+
1153
+ mDNSlocal int
1154
+ SetupSockets
1155
+ (
1156
+ DaemonInfo * self
1157
+ )
1158
+ {
1159
+ static const int kOn = 1;
1160
+ int sockpair[2];
1161
+ mDNSBool private = mDNSfalse;
1162
+ struct sockaddr_in daddr;
1163
+ DNSZone * zone;
1164
+ mStatus err = 0;
1165
+
1166
+ // set up sockets on which we all ns requests
1167
+
1168
+ self->tcpsd = socket( AF_INET, SOCK_STREAM, 0 );
1169
+ require_action( dnssd_SocketValid(self->tcpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
1170
+
1171
+ #if defined(SO_REUSEADDR)
1172
+ err = setsockopt(self->tcpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
1173
+ require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->tcpsd" ) );
1174
+ #endif
1175
+
1176
+ err = bind( self->tcpsd, ( struct sockaddr* ) &self->addr, sizeof( self->addr ) );
1177
+ require_action( !err, exit, LogErr( "SetupSockets", "bind self->tcpsd" ) );
1178
+
1179
+ err = listen( self->tcpsd, LISTENQ );
1180
+ require_action( !err, exit, LogErr( "SetupSockets", "listen" ) );
1181
+
1182
+ self->udpsd = socket( AF_INET, SOCK_DGRAM, 0 );
1183
+ require_action( dnssd_SocketValid(self->udpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
1184
+
1185
+ #if defined(SO_REUSEADDR)
1186
+ err = setsockopt(self->udpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
1187
+ require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->udpsd" ) );
1188
+ #endif
1189
+
1190
+ err = bind( self->udpsd, ( struct sockaddr* ) &self->addr, sizeof( self->addr ) );
1191
+ require_action( !err, exit, LogErr( "SetupSockets", "bind self->udpsd" ) );
1192
+
1193
+ // set up sockets on which we receive llq requests
1194
+
1195
+ mDNSPlatformMemZero(&self->llq_addr, sizeof(self->llq_addr));
1196
+ self->llq_addr.sin_family = AF_INET;
1197
+ self->llq_addr.sin_addr.s_addr = zerov4Addr.NotAnInteger;
1198
+ self->llq_addr.sin_port = ( self->llq_port.NotAnInteger ) ? self->llq_port.NotAnInteger : DNSEXTPort.NotAnInteger;
1199
+
1200
+ if (self->llq_addr.sin_port == self->addr.sin_port)
1201
+ {
1202
+ self->llq_tcpsd = self->tcpsd;
1203
+ self->llq_udpsd = self->udpsd;
1204
+ }
1205
+ else
1206
+ {
1207
+ self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 );
1208
+ require_action( dnssd_SocketValid(self->llq_tcpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
1209
+
1210
+ #if defined(SO_REUSEADDR)
1211
+ err = setsockopt(self->llq_tcpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
1212
+ require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_tcpsd" ) );
1213
+ #endif
1214
+
1215
+ err = bind( self->llq_tcpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) );
1216
+ require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_tcpsd" ) );
1217
+
1218
+ err = listen( self->llq_tcpsd, LISTENQ );
1219
+ require_action( !err, exit, LogErr( "SetupSockets", "listen" ) );
1220
+
1221
+ self->llq_udpsd = socket( AF_INET, SOCK_DGRAM, 0 );
1222
+ require_action( dnssd_SocketValid(self->llq_udpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
1223
+
1224
+ #if defined(SO_REUSEADDR)
1225
+ err = setsockopt(self->llq_udpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
1226
+ require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_udpsd" ) );
1227
+ #endif
1228
+
1229
+ err = bind(self->llq_udpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) );
1230
+ require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_udpsd" ) );
1231
+ }
1232
+
1233
+ // set up Unix domain socket pair for LLQ polling thread to signal main thread that a change to the zone occurred
1234
+
1235
+ err = socketpair( AF_LOCAL, SOCK_STREAM, 0, sockpair );
1236
+ require_action( !err, exit, LogErr( "SetupSockets", "socketpair" ) );
1237
+
1238
+ self->LLQEventListenSock = sockpair[0];
1239
+ self->LLQEventNotifySock = sockpair[1];
1240
+
1241
+ // set up socket on which we receive private requests
1242
+
1243
+ self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 );
1244
+ require_action( dnssd_SocketValid(self->tlssd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
1245
+ mDNSPlatformMemZero(&daddr, sizeof(daddr));
1246
+ daddr.sin_family = AF_INET;
1247
+ daddr.sin_addr.s_addr = zerov4Addr.NotAnInteger;
1248
+ daddr.sin_port = ( self->private_port.NotAnInteger ) ? self->private_port.NotAnInteger : PrivateDNSPort.NotAnInteger;
1249
+
1250
+ self->tlssd = socket( AF_INET, SOCK_STREAM, 0 );
1251
+ require_action( dnssd_SocketValid(self->tlssd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
1252
+
1253
+ #if defined(SO_REUSEADDR)
1254
+ err = setsockopt(self->tlssd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
1255
+ require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->tlssd" ) );
1256
+ #endif
1257
+
1258
+ err = bind( self->tlssd, ( struct sockaddr* ) &daddr, sizeof( daddr ) );
1259
+ require_action( !err, exit, LogErr( "SetupSockets", "bind self->tlssd" ) );
1260
+
1261
+ err = listen( self->tlssd, LISTENQ );
1262
+ require_action( !err, exit, LogErr( "SetupSockets", "listen" ) );
1263
+
1264
+ // Do we have any private zones?
1265
+
1266
+ for ( zone = self->zones; zone; zone = zone->next )
1267
+ {
1268
+ if ( zone->type == kDNSZonePrivate )
1269
+ {
1270
+ private = mDNStrue;
1271
+ break;
1272
+ }
1273
+ }
1274
+
1275
+ if ( private )
1276
+ {
1277
+ err = mDNSPlatformTLSSetupCerts();
1278
+ require_action( !err, exit, LogErr( "SetupSockets", "mDNSPlatformTLSSetupCerts" ) );
1279
+ }
1280
+
1281
+ exit:
1282
+
1283
+ return err;
1284
+ }
1285
+
1286
+ //
1287
+ // periodic table updates
1288
+ //
1289
+
1290
+ // Delete a resource record from the nameserver via a dynamic update
1291
+ // sd is a socket already connected to the server
1292
+ mDNSlocal void DeleteOneRecord(DaemonInfo *d, CacheRecord *rr, domainname *zname, TCPSocket *sock)
1293
+ {
1294
+ DNSZone * zone;
1295
+ PktMsg pkt;
1296
+ mDNSu8 *ptr = pkt.msg.data;
1297
+ mDNSu8 *end = (mDNSu8 *)&pkt.msg + sizeof(DNSMessage);
1298
+ char buf[MaxMsg];
1299
+ mDNSBool closed;
1300
+ PktMsg *reply = NULL;
1301
+
1302
+ VLog("Expiring record %s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, buf));
1303
+
1304
+ InitializeDNSMessage(&pkt.msg.h, zeroID, UpdateReqFlags);
1305
+
1306
+ ptr = putZone(&pkt.msg, ptr, end, zname, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
1307
+ if (!ptr) goto end;
1308
+ ptr = putDeletionRecord(&pkt.msg, ptr, &rr->resrec);
1309
+ if (!ptr) goto end;
1310
+
1311
+ HdrHToN(&pkt);
1312
+
1313
+ zone = FindZone( d, zname );
1314
+
1315
+ if ( zone && zone->updateKeys)
1316
+ {
1317
+ DNSDigest_SignMessage(&pkt.msg, &ptr, zone->updateKeys, 0 );
1318
+ if (!ptr) goto end;
1319
+ }
1320
+
1321
+ pkt.len = ptr - (mDNSu8 *)&pkt.msg;
1322
+ pkt.src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // address field set solely for verbose logging in subroutines
1323
+ pkt.src.sin_family = AF_INET;
1324
+ if (SendPacket( sock, &pkt)) { Log("DeleteOneRecord: SendPacket failed"); }
1325
+ reply = RecvPacket( sock, NULL, &closed );
1326
+ if (reply) HdrNToH(reply);
1327
+ require_action( reply, end, Log( "DeleteOneRecord: RecvPacket returned NULL" ) );
1328
+
1329
+ if (!SuccessfulUpdateTransaction(&pkt, reply))
1330
+ Log("Expiration update failed with rcode %d", reply ? reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask : -1);
1331
+
1332
+ end:
1333
+ if (!ptr) { Log("DeleteOneRecord: Error constructing lease expiration update"); }
1334
+ if (reply) free(reply);
1335
+ }
1336
+
1337
+ // iterate over table, deleting expired records (or all records if DeleteAll is true)
1338
+ mDNSlocal void DeleteRecords(DaemonInfo *d, mDNSBool DeleteAll)
1339
+ {
1340
+ struct timeval now;
1341
+ int i;
1342
+ TCPSocket *sock = ConnectToServer(d);
1343
+ if (!sock) { Log("DeleteRecords: ConnectToServer failed"); return; }
1344
+ if (gettimeofday(&now, NULL)) { LogErr("DeleteRecords ", "gettimeofday"); return; }
1345
+ if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteRecords", "pthread_mutex_lock"); return; }
1346
+
1347
+ for (i = 0; i < d->nbuckets; i++)
1348
+ {
1349
+ RRTableElem **ptr = &d->table[i];
1350
+ while (*ptr)
1351
+ {
1352
+ if (DeleteAll || (*ptr)->expire - now.tv_sec < 0)
1353
+ {
1354
+ RRTableElem *fptr;
1355
+ // delete record from server
1356
+ DeleteOneRecord(d, &(*ptr)->rr, &(*ptr)->zone, sock);
1357
+ fptr = *ptr;
1358
+ *ptr = (*ptr)->next;
1359
+ free(fptr);
1360
+ d->nelems--;
1361
+ }
1362
+ else ptr = &(*ptr)->next;
1363
+ }
1364
+ }
1365
+ pthread_mutex_unlock(&d->tablelock);
1366
+ mDNSPlatformTCPCloseConnection( sock );
1367
+ }
1368
+
1369
+ //
1370
+ // main update request handling
1371
+ //
1372
+
1373
+ // Add, delete, or refresh records in table based on contents of a successfully completed dynamic update
1374
+ mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease)
1375
+ {
1376
+ RRTableElem **rptr, *tmp;
1377
+ int i, allocsize, bucket;
1378
+ LargeCacheRecord lcr;
1379
+ ResourceRecord *rr = &lcr.r.resrec;
1380
+ const mDNSu8 *ptr, *end;
1381
+ struct timeval tv;
1382
+ DNSQuestion zone;
1383
+ char buf[MaxMsg];
1384
+
1385
+ if (pthread_mutex_lock(&d->tablelock)) { LogErr("UpdateLeaseTable", "pthread_mutex_lock"); return; }
1386
+ HdrNToH(pkt);
1387
+ ptr = pkt->msg.data;
1388
+ end = (mDNSu8 *)&pkt->msg + pkt->len;
1389
+ ptr = getQuestion(&pkt->msg, ptr, end, 0, &zone);
1390
+ if (!ptr) { Log("UpdateLeaseTable: cannot read zone"); goto cleanup; }
1391
+ ptr = LocateAuthorities(&pkt->msg, end);
1392
+ if (!ptr) { Log("UpdateLeaseTable: Format error"); goto cleanup; }
1393
+
1394
+ for (i = 0; i < pkt->msg.h.mDNS_numUpdates; i++)
1395
+ {
1396
+ mDNSBool DeleteAllRRSets = mDNSfalse, DeleteOneRRSet = mDNSfalse, DeleteOneRR = mDNSfalse;
1397
+
1398
+ ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
1399
+ if (!ptr || lcr.r.resrec.RecordType == kDNSRecordTypePacketNegative) { Log("UpdateLeaseTable: GetLargeResourceRecord failed"); goto cleanup; }
1400
+ bucket = rr->namehash % d->nbuckets;
1401
+ rptr = &d->table[bucket];
1402
+
1403
+ // handle deletions
1404
+ if (rr->rrtype == kDNSQType_ANY && !rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength)
1405
+ DeleteAllRRSets = mDNStrue; // delete all rrsets for a name
1406
+ else if (!rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength)
1407
+ DeleteOneRRSet = mDNStrue;
1408
+ else if (!rr->rroriginalttl && rr->rrclass == kDNSClass_NONE)
1409
+ DeleteOneRR = mDNStrue;
1410
+
1411
+ if (DeleteAllRRSets || DeleteOneRRSet || DeleteOneRR)
1412
+ {
1413
+ while (*rptr)
1414
+ {
1415
+ if (SameDomainName((*rptr)->rr.resrec.name, rr->name) &&
1416
+ (DeleteAllRRSets ||
1417
+ (DeleteOneRRSet && (*rptr)->rr.resrec.rrtype == rr->rrtype) ||
1418
+ (DeleteOneRR && IdenticalResourceRecord(&(*rptr)->rr.resrec, rr))))
1419
+ {
1420
+ tmp = *rptr;
1421
+ VLog("Received deletion update for %s", GetRRDisplayString_rdb(&tmp->rr.resrec, &tmp->rr.resrec.rdata->u, buf));
1422
+ *rptr = (*rptr)->next;
1423
+ free(tmp);
1424
+ d->nelems--;
1425
+ }
1426
+ else rptr = &(*rptr)->next;
1427
+ }
1428
+ }
1429
+ else if (lease > 0)
1430
+ {
1431
+ // see if add or refresh
1432
+ while (*rptr && !IdenticalResourceRecord(&(*rptr)->rr.resrec, rr)) rptr = &(*rptr)->next;
1433
+ if (*rptr)
1434
+ {
1435
+ // refresh
1436
+ if (gettimeofday(&tv, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
1437
+ (*rptr)->expire = tv.tv_sec + (unsigned)lease;
1438
+ VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
1439
+ }
1440
+ else
1441
+ {
1442
+ // New record - add to table
1443
+ if (d->nelems > d->nbuckets)
1444
+ {
1445
+ RehashTable(d);
1446
+ bucket = rr->namehash % d->nbuckets;
1447
+ rptr = &d->table[bucket];
1448
+ }
1449
+ if (gettimeofday(&tv, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
1450
+ allocsize = sizeof(RRTableElem);
1451
+ if (rr->rdlength > InlineCacheRDSize) allocsize += (rr->rdlength - InlineCacheRDSize);
1452
+ tmp = malloc(allocsize);
1453
+ if (!tmp) { LogErr("UpdateLeaseTable", "malloc"); goto cleanup; }
1454
+ memcpy(&tmp->rr, &lcr.r, sizeof(CacheRecord) + rr->rdlength - InlineCacheRDSize);
1455
+ tmp->rr.resrec.rdata = (RData *)&tmp->rr.smallrdatastorage;
1456
+ AssignDomainName(&tmp->name, rr->name);
1457
+ tmp->rr.resrec.name = &tmp->name;
1458
+ tmp->expire = tv.tv_sec + (unsigned)lease;
1459
+ tmp->cli.sin_addr = pkt->src.sin_addr;
1460
+ AssignDomainName(&tmp->zone, &zone.qname);
1461
+ tmp->next = d->table[bucket];
1462
+ d->table[bucket] = tmp;
1463
+ d->nelems++;
1464
+ VLog("Adding update for %s to lease table", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
1465
+ }
1466
+ }
1467
+ }
1468
+
1469
+ cleanup:
1470
+ pthread_mutex_unlock(&d->tablelock);
1471
+ HdrHToN(pkt);
1472
+ }
1473
+
1474
+ // Given a successful reply from a server, create a new reply that contains lease information
1475
+ // Replies are currently not signed !!!KRS change this
1476
+ mDNSlocal PktMsg *FormatLeaseReply(DaemonInfo *d, PktMsg *orig, mDNSu32 lease)
1477
+ {
1478
+ PktMsg *reply;
1479
+ mDNSu8 *ptr, *end;
1480
+ mDNSOpaque16 flags;
1481
+
1482
+ (void)d; //unused
1483
+ reply = malloc(sizeof(*reply));
1484
+ if (!reply) { LogErr("FormatLeaseReply", "malloc"); return NULL; }
1485
+ flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update;
1486
+ flags.b[1] = 0;
1487
+
1488
+ InitializeDNSMessage(&reply->msg.h, orig->msg.h.id, flags);
1489
+ reply->src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // unused except for log messages
1490
+ reply->src.sin_family = AF_INET;
1491
+ ptr = reply->msg.data;
1492
+ end = (mDNSu8 *)&reply->msg + sizeof(DNSMessage);
1493
+ ptr = putUpdateLease(&reply->msg, ptr, lease);
1494
+ if (!ptr) { Log("FormatLeaseReply: putUpdateLease failed"); free(reply); return NULL; }
1495
+ reply->len = ptr - (mDNSu8 *)&reply->msg;
1496
+ HdrHToN(reply);
1497
+ return reply;
1498
+ }
1499
+
1500
+
1501
+ // pkt is thread-local, not requiring locking
1502
+
1503
+ mDNSlocal PktMsg*
1504
+ HandleRequest
1505
+ (
1506
+ DaemonInfo * self,
1507
+ PktMsg * request
1508
+ )
1509
+ {
1510
+ PktMsg * reply = NULL;
1511
+ PktMsg * leaseReply;
1512
+ PktMsg buf;
1513
+ char addrbuf[32];
1514
+ TCPSocket * sock = NULL;
1515
+ mStatus err;
1516
+ mDNSs32 lease = 0;
1517
+ if ((request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) == kDNSFlag0_OP_Update)
1518
+ {
1519
+ int i, adds = 0, dels = 0;
1520
+ const mDNSu8 *ptr, *end = (mDNSu8 *)&request->msg + request->len;
1521
+ HdrNToH(request);
1522
+ lease = GetPktLease(&mDNSStorage, &request->msg, end);
1523
+ ptr = LocateAuthorities(&request->msg, end);
1524
+ for (i = 0; i < request->msg.h.mDNS_numUpdates; i++)
1525
+ {
1526
+ LargeCacheRecord lcr;
1527
+ ptr = GetLargeResourceRecord(NULL, &request->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
1528
+ if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rroriginalttl) adds++; else dels++;
1529
+ }
1530
+ HdrHToN(request);
1531
+ if (adds && !lease)
1532
+ {
1533
+ static const mDNSOpaque16 UpdateRefused = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_Update, kDNSFlag1_RC_Refused } };
1534
+ Log("Rejecting Update Request with %d additions but no lease", adds);
1535
+ reply = malloc(sizeof(*reply));
1536
+ mDNSPlatformMemZero(&reply->src, sizeof(reply->src));
1537
+ reply->len = sizeof(DNSMessageHeader);
1538
+ reply->zone = NULL;
1539
+ reply->isZonePublic = 0;
1540
+ InitializeDNSMessage(&reply->msg.h, request->msg.h.id, UpdateRefused);
1541
+ return(reply);
1542
+ }
1543
+ if (lease > 7200) // Don't allow lease greater than two hours; typically 90-minute renewal period
1544
+ lease = 7200;
1545
+ }
1546
+ // Send msg to server, read reply
1547
+
1548
+ if ( request->len <= 512 )
1549
+ {
1550
+ mDNSBool trunc;
1551
+
1552
+ if ( UDPServerTransaction( self, request, &buf, &trunc) < 0 )
1553
+ {
1554
+ Log("HandleRequest - UDPServerTransaction failed. Trying TCP");
1555
+ }
1556
+ else if ( trunc )
1557
+ {
1558
+ VLog("HandleRequest - answer truncated. Using TCP");
1559
+ }
1560
+ else
1561
+ {
1562
+ reply = &buf; // success
1563
+ }
1564
+ }
1565
+
1566
+ if ( !reply )
1567
+ {
1568
+ mDNSBool closed;
1569
+ int res;
1570
+
1571
+ sock = ConnectToServer( self );
1572
+ require_action_quiet( sock, exit, err = mStatus_UnknownErr ; Log( "Discarding request from %s due to connection errors", inet_ntop( AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) );
1573
+
1574
+ res = SendPacket( sock, request );
1575
+ require_action_quiet( res >= 0, exit, err = mStatus_UnknownErr ; Log( "Couldn't relay message from %s to server. Discarding.", inet_ntop(AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) );
1576
+
1577
+ reply = RecvPacket( sock, &buf, &closed );
1578
+ }
1579
+
1580
+ // IMPORTANT: reply is in network byte order at this point in the code
1581
+ // We keep it this way because we send it back to the client in the same form
1582
+
1583
+ // Is it an update?
1584
+
1585
+ if ( reply && ( ( reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == ( kDNSFlag0_OP_Update | kDNSFlag0_QR_Response ) ) )
1586
+ {
1587
+ char pingmsg[4];
1588
+ mDNSBool ok = SuccessfulUpdateTransaction( request, reply );
1589
+ require_action( ok, exit, err = mStatus_UnknownErr; VLog( "Message from %s not a successful update.", inet_ntop(AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) );
1590
+
1591
+ UpdateLeaseTable( request, self, lease );
1592
+
1593
+ if ( lease > 0 )
1594
+ {
1595
+ leaseReply = FormatLeaseReply( self, reply, lease );
1596
+
1597
+ if ( !leaseReply )
1598
+ {
1599
+ Log("HandleRequest - unable to format lease reply");
1600
+ }
1601
+
1602
+ // %%% Looks like a potential memory leak -- who frees the original reply?
1603
+ reply = leaseReply;
1604
+ }
1605
+
1606
+ // tell the main thread there was an update so it can send LLQs
1607
+
1608
+ if ( send( self->LLQEventNotifySock, pingmsg, sizeof( pingmsg ), 0 ) != sizeof( pingmsg ) )
1609
+ {
1610
+ LogErr("HandleRequest", "send");
1611
+ }
1612
+ }
1613
+
1614
+ exit:
1615
+
1616
+ if ( sock )
1617
+ {
1618
+ mDNSPlatformTCPCloseConnection( sock );
1619
+ }
1620
+
1621
+ if ( reply == &buf )
1622
+ {
1623
+ reply = malloc( sizeof( *reply ) );
1624
+
1625
+ if ( reply )
1626
+ {
1627
+ reply->len = buf.len;
1628
+ memcpy(&reply->msg, &buf.msg, buf.len);
1629
+ }
1630
+ else
1631
+ {
1632
+ LogErr("HandleRequest", "malloc");
1633
+ }
1634
+ }
1635
+
1636
+ return reply;
1637
+ }
1638
+
1639
+
1640
+ //
1641
+ // LLQ Support Routines
1642
+ //
1643
+
1644
+ // Set fields of an LLQ OPT Resource Record
1645
+ mDNSlocal void FormatLLQOpt(AuthRecord *opt, int opcode, const mDNSOpaque64 *const id, mDNSs32 lease)
1646
+ {
1647
+ mDNSPlatformMemZero(opt, sizeof(*opt));
1648
+ mDNS_SetupResourceRecord(opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
1649
+ opt->resrec.rrclass = NormalMaxDNSMessageData;
1650
+ opt->resrec.rdlength = sizeof(rdataOPT); // One option in this OPT record
1651
+ opt->resrec.rdestimate = sizeof(rdataOPT);
1652
+ opt->resrec.rdata->u.opt[0].opt = kDNSOpt_LLQ;
1653
+ opt->resrec.rdata->u.opt[0].u.llq.vers = kLLQ_Vers;
1654
+ opt->resrec.rdata->u.opt[0].u.llq.llqOp = opcode;
1655
+ opt->resrec.rdata->u.opt[0].u.llq.err = LLQErr_NoError;
1656
+ opt->resrec.rdata->u.opt[0].u.llq.id = *id;
1657
+ opt->resrec.rdata->u.opt[0].u.llq.llqlease = lease;
1658
+ }
1659
+
1660
+ // Calculate effective remaining lease of an LLQ
1661
+ mDNSlocal mDNSu32 LLQLease(LLQEntry *e)
1662
+ {
1663
+ struct timeval t;
1664
+
1665
+ gettimeofday(&t, NULL);
1666
+ if (e->expire < t.tv_sec) return 0;
1667
+ else return e->expire - t.tv_sec;
1668
+ }
1669
+
1670
+ mDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e)
1671
+ {
1672
+ int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE;
1673
+ LLQEntry **ptr = &d->LLQTable[bucket];
1674
+ AnswerListElem *a = e->AnswerList;
1675
+ char addr[32];
1676
+
1677
+ inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
1678
+ VLog("Deleting LLQ table entry for %##s client %s", e->qname.c, addr);
1679
+
1680
+ if (a && !(--a->refcount) && d->AnswerTableCount >= LLQ_TABLESIZE)
1681
+ {
1682
+ // currently, generating initial answers blocks the main thread, so we keep the answer list
1683
+ // even if the ref count drops to zero. To prevent unbounded table growth, we free shared answers
1684
+ // if the ref count drops to zero AND there are more table elements than buckets
1685
+ // !!!KRS update this when we make the table dynamically growable
1686
+
1687
+ CacheRecord *cr = a->KnownAnswers, *tmp;
1688
+ AnswerListElem **tbl = &d->AnswerTable[bucket];
1689
+
1690
+ while (cr)
1691
+ {
1692
+ tmp = cr;
1693
+ cr = cr->next;
1694
+ free(tmp);
1695
+ }
1696
+
1697
+ while (*tbl && *tbl != a) tbl = &(*tbl)->next;
1698
+ if (*tbl) { *tbl = (*tbl)->next; free(a); d->AnswerTableCount--; }
1699
+ else Log("Error: DeleteLLQ - AnswerList not found in table");
1700
+ }
1701
+
1702
+ // remove LLQ from table, free memory
1703
+ while(*ptr && *ptr != e) ptr = &(*ptr)->next;
1704
+ if (!*ptr) { Log("Error: DeleteLLQ - LLQ not in table"); return; }
1705
+ *ptr = (*ptr)->next;
1706
+ free(e);
1707
+ }
1708
+
1709
+ mDNSlocal int SendLLQ(DaemonInfo *d, PktMsg *pkt, struct sockaddr_in dst, TCPSocket *sock)
1710
+ {
1711
+ char addr[32];
1712
+ int err = -1;
1713
+
1714
+ HdrHToN(pkt);
1715
+
1716
+ if ( sock )
1717
+ {
1718
+ if ( SendPacket( sock, pkt ) != 0 )
1719
+ {
1720
+ LogErr("DaemonInfo", "MySend");
1721
+ Log("Could not send response to client %s", inet_ntop(AF_INET, &dst.sin_addr, addr, 32));
1722
+ }
1723
+ }
1724
+ else
1725
+ {
1726
+ if (sendto(d->llq_udpsd, &pkt->msg, pkt->len, 0, (struct sockaddr *)&dst, sizeof(dst)) != (int)pkt->len)
1727
+ {
1728
+ LogErr("DaemonInfo", "sendto");
1729
+ Log("Could not send response to client %s", inet_ntop(AF_INET, &dst.sin_addr, addr, 32));
1730
+ }
1731
+ }
1732
+
1733
+ err = 0;
1734
+ HdrNToH(pkt);
1735
+ return err;
1736
+ }
1737
+
1738
+ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e)
1739
+ {
1740
+ PktMsg q;
1741
+ int i;
1742
+ TCPSocket *sock = NULL;
1743
+ const mDNSu8 *ansptr;
1744
+ mDNSu8 *end = q.msg.data;
1745
+ PktMsg buf, *reply = NULL;
1746
+ LargeCacheRecord lcr;
1747
+ CacheRecord *AnswerList = NULL;
1748
+ mDNSu8 rcode;
1749
+
1750
+ VLog("Querying server for %##s type %d", e->name.c, e->type);
1751
+
1752
+ InitializeDNSMessage(&q.msg.h, zeroID, uQueryFlags);
1753
+
1754
+ end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->name, e->type, kDNSClass_IN);
1755
+ if (!end) { Log("Error: AnswerQuestion - putQuestion returned NULL"); goto end; }
1756
+ q.len = (int)(end - (mDNSu8 *)&q.msg);
1757
+
1758
+ HdrHToN(&q);
1759
+
1760
+ if (!e->UseTCP)
1761
+ {
1762
+ mDNSBool trunc;
1763
+
1764
+ if (UDPServerTransaction(d, &q, &buf, &trunc) < 0)
1765
+ Log("AnswerQuestion %##s - UDPServerTransaction failed. Trying TCP", e->name.c);
1766
+ else if (trunc)
1767
+ { VLog("AnswerQuestion %##s - answer truncated. Using TCP", e->name.c); e->UseTCP = mDNStrue; }
1768
+ else reply = &buf; // success
1769
+ }
1770
+
1771
+ if (!reply)
1772
+ {
1773
+ mDNSBool closed;
1774
+
1775
+ sock = ConnectToServer(d);
1776
+ if (!sock) { Log("AnswerQuestion: ConnectToServer failed"); goto end; }
1777
+ if (SendPacket( sock, &q)) { Log("AnswerQuestion: SendPacket failed"); mDNSPlatformTCPCloseConnection( sock ); goto end; }
1778
+ reply = RecvPacket( sock, NULL, &closed );
1779
+ mDNSPlatformTCPCloseConnection( sock );
1780
+ require_action( reply, end, Log( "AnswerQuestion: RecvPacket returned NULL" ) );
1781
+ }
1782
+
1783
+ HdrNToH(&q);
1784
+ if (reply) HdrNToH(reply);
1785
+
1786
+ if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery))
1787
+ { Log("AnswerQuestion: %##s type %d - Invalid response flags from server"); goto end; }
1788
+ rcode = (mDNSu8)(reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask);
1789
+ if (rcode && rcode != kDNSFlag1_RC_NXDomain) { Log("AnswerQuestion: %##s type %d - non-zero rcode %d from server", e->name.c, e->type, rcode); goto end; }
1790
+
1791
+ end = (mDNSu8 *)&reply->msg + reply->len;
1792
+ ansptr = LocateAnswers(&reply->msg, end);
1793
+ if (!ansptr) { Log("Error: AnswerQuestion - LocateAnswers returned NULL"); goto end; }
1794
+
1795
+ for (i = 0; i < reply->msg.h.numAnswers; i++)
1796
+ {
1797
+ ansptr = GetLargeResourceRecord(NULL, &reply->msg, ansptr, end, 0, kDNSRecordTypePacketAns, &lcr);
1798
+ if (!ansptr) { Log("AnswerQuestions: GetLargeResourceRecord returned NULL"); goto end; }
1799
+ if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative)
1800
+ {
1801
+ if (lcr.r.resrec.rrtype != e->type || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->name))
1802
+ {
1803
+ Log("AnswerQuestion: response %##s type #d does not answer question %##s type #d. Discarding",
1804
+ lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->name.c, e->type);
1805
+ }
1806
+ else
1807
+ {
1808
+ CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->name);
1809
+ if (!cr) { Log("Error: AnswerQuestion - CopyCacheRecord returned NULL"); goto end; }
1810
+ cr->next = AnswerList;
1811
+ AnswerList = cr;
1812
+ }
1813
+ }
1814
+ }
1815
+
1816
+ end:
1817
+ if (reply && reply != &buf) free(reply);
1818
+ return AnswerList;
1819
+ }
1820
+
1821
+ // Routine forks a thread to set EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list
1822
+ mDNSlocal void *UpdateAnswerList(void *args)
1823
+ {
1824
+ CacheRecord *cr, *NewAnswers, **na, **ka; // "new answer", "known answer"
1825
+ DaemonInfo *d = ((UpdateAnswerListArgs *)args)->d;
1826
+ AnswerListElem *a = ((UpdateAnswerListArgs *)args)->a;
1827
+
1828
+ free(args);
1829
+ args = NULL;
1830
+
1831
+ // get up to date answers
1832
+ NewAnswers = AnswerQuestion(d, a);
1833
+
1834
+ // first pass - mark all answers for deletion
1835
+ for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
1836
+ (*ka)->resrec.rroriginalttl = (unsigned)-1; // -1 means delete
1837
+
1838
+ // second pass - mark answers pre-existent
1839
+ for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
1840
+ {
1841
+ for (na = &NewAnswers; *na; na = &(*na)->next)
1842
+ {
1843
+ if (IdenticalResourceRecord(&(*ka)->resrec, &(*na)->resrec))
1844
+ { (*ka)->resrec.rroriginalttl = 0; break; } // 0 means no change
1845
+ }
1846
+ }
1847
+
1848
+ // third pass - add new records to Event list
1849
+ na = &NewAnswers;
1850
+ while (*na)
1851
+ {
1852
+ for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
1853
+ if (IdenticalResourceRecord(&(*ka)->resrec, &(*na)->resrec)) break;
1854
+ if (!*ka)
1855
+ {
1856
+ // answer is not in list - splice from NewAnswers list, add to Event list
1857
+ cr = *na;
1858
+ *na = (*na)->next; // splice from list
1859
+ cr->next = a->EventList; // add spliced record to event list
1860
+ a->EventList = cr;
1861
+ cr->resrec.rroriginalttl = 1; // 1 means add
1862
+ }
1863
+ else na = &(*na)->next;
1864
+ }
1865
+
1866
+ // move all the removes from the answer list to the event list
1867
+ ka = &a->KnownAnswers;
1868
+ while (*ka)
1869
+ {
1870
+ if ((*ka)->resrec.rroriginalttl == (unsigned)-1)
1871
+ {
1872
+ cr = *ka;
1873
+ *ka = (*ka)->next;
1874
+ cr->next = a->EventList;
1875
+ a->EventList = cr;
1876
+ }
1877
+ else ka = &(*ka)->next;
1878
+ }
1879
+
1880
+ // lastly, free the remaining records (known answers) in NewAnswers list
1881
+ while (NewAnswers)
1882
+ {
1883
+ cr = NewAnswers;
1884
+ NewAnswers = NewAnswers->next;
1885
+ free(cr);
1886
+ }
1887
+
1888
+ return NULL;
1889
+ }
1890
+
1891
+ mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e)
1892
+ {
1893
+ PktMsg response;
1894
+ CacheRecord *cr;
1895
+ mDNSu8 *end = (mDNSu8 *)&response.msg.data;
1896
+ mDNSOpaque16 msgID;
1897
+ char rrbuf[MaxMsg], addrbuf[32];
1898
+ AuthRecord opt;
1899
+
1900
+ // Should this really be random? Do we use the msgID on the receiving end?
1901
+ msgID.NotAnInteger = random();
1902
+ if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32);
1903
+ InitializeDNSMessage(&response.msg.h, msgID, ResponseFlags);
1904
+ end = putQuestion(&response.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
1905
+ if (!end) { Log("Error: SendEvents - putQuestion returned NULL"); return; }
1906
+
1907
+ // put adds/removes in packet
1908
+ for (cr = e->AnswerList->EventList; cr; cr = cr->next)
1909
+ {
1910
+ if (verbose) GetRRDisplayString_rdb(&cr->resrec, &cr->resrec.rdata->u, rrbuf);
1911
+ VLog("%s (%s): %s", addrbuf, (mDNSs32)cr->resrec.rroriginalttl < 0 ? "Remove": "Add", rrbuf);
1912
+ end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &cr->resrec, cr->resrec.rroriginalttl);
1913
+ if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo returned NULL"); return; }
1914
+ }
1915
+
1916
+ FormatLLQOpt(&opt, kLLQOp_Event, &e->id, LLQLease(e));
1917
+ end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAdditionals, &opt.resrec, 0);
1918
+ if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo"); return; }
1919
+
1920
+ response.len = (int)(end - (mDNSu8 *)&response.msg);
1921
+ if (SendLLQ(d, &response, e->cli, NULL ) < 0) LogMsg("Error: SendEvents - SendLLQ");
1922
+ }
1923
+
1924
+ mDNSlocal void PrintLLQAnswers(DaemonInfo *d)
1925
+ {
1926
+ int i;
1927
+ char rrbuf[MaxMsg];
1928
+
1929
+ Log("Printing LLQ Answer Table contents");
1930
+
1931
+ for (i = 0; i < LLQ_TABLESIZE; i++)
1932
+ {
1933
+ AnswerListElem *a = d->AnswerTable[i];
1934
+ while(a)
1935
+ {
1936
+ int ancount = 0;
1937
+ const CacheRecord *rr = a->KnownAnswers;
1938
+ while (rr) { ancount++; rr = rr->next; }
1939
+ Log("%p : Question %##s; type %d; referenced by %d LLQs; %d answers:", a, a->name.c, a->type, a->refcount, ancount);
1940
+ for (rr = a->KnownAnswers; rr; rr = rr->next) Log("\t%s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, rrbuf));
1941
+ a = a->next;
1942
+ }
1943
+ }
1944
+ }
1945
+
1946
+ mDNSlocal void PrintLLQTable(DaemonInfo *d)
1947
+ {
1948
+ LLQEntry *e;
1949
+ char addr[32];
1950
+ int i;
1951
+
1952
+ Log("Printing LLQ table contents");
1953
+
1954
+ for (i = 0; i < LLQ_TABLESIZE; i++)
1955
+ {
1956
+ e = d->LLQTable[i];
1957
+ while(e)
1958
+ {
1959
+ char *state;
1960
+
1961
+ switch (e->state)
1962
+ {
1963
+ case RequestReceived: state = "RequestReceived"; break;
1964
+ case ChallengeSent: state = "ChallengeSent"; break;
1965
+ case Established: state = "Established"; break;
1966
+ default: state = "unknown";
1967
+ }
1968
+ inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
1969
+
1970
+ Log("LLQ from %s in state %s; %##s; type %d; orig lease %d; remaining lease %d; AnswerList %p)",
1971
+ addr, state, e->qname.c, e->qtype, e->lease, LLQLease(e), e->AnswerList);
1972
+ e = e->next;
1973
+ }
1974
+ }
1975
+ }
1976
+
1977
+ // Send events to clients as a result of a change in the zone
1978
+ mDNSlocal void GenLLQEvents(DaemonInfo *d)
1979
+ {
1980
+ LLQEntry **e;
1981
+ int i;
1982
+ struct timeval t;
1983
+ UpdateAnswerListArgs *args;
1984
+
1985
+ VLog("Generating LLQ Events");
1986
+
1987
+ gettimeofday(&t, NULL);
1988
+
1989
+ // get all answers up to date
1990
+ for (i = 0; i < LLQ_TABLESIZE; i++)
1991
+ {
1992
+ AnswerListElem *a = d->AnswerTable[i];
1993
+ while(a)
1994
+ {
1995
+ args = malloc(sizeof(*args));
1996
+ if (!args) { LogErr("GenLLQEvents", "malloc"); return; }
1997
+ args->d = d;
1998
+ args->a = a;
1999
+ if (pthread_create(&a->tid, NULL, UpdateAnswerList, args) < 0) { LogErr("GenLLQEvents", "pthread_create"); return; }
2000
+ usleep(1);
2001
+ a = a->next;
2002
+ }
2003
+ }
2004
+
2005
+ for (i = 0; i < LLQ_TABLESIZE; i++)
2006
+ {
2007
+ AnswerListElem *a = d->AnswerTable[i];
2008
+ while(a)
2009
+ {
2010
+ if (pthread_join(a->tid, NULL)) LogErr("GenLLQEvents", "pthread_join");
2011
+ a = a->next;
2012
+ }
2013
+ }
2014
+
2015
+ // for each established LLQ, send events
2016
+ for (i = 0; i < LLQ_TABLESIZE; i++)
2017
+ {
2018
+ e = &d->LLQTable[i];
2019
+ while(*e)
2020
+ {
2021
+ if ((*e)->expire < t.tv_sec) DeleteLLQ(d, *e);
2022
+ else
2023
+ {
2024
+ if ((*e)->state == Established && (*e)->AnswerList->EventList) SendEvents(d, *e);
2025
+ e = &(*e)->next;
2026
+ }
2027
+ }
2028
+ }
2029
+
2030
+ // now that all LLQs are updated, we move Add events from the Event list to the Known Answer list, and free Removes
2031
+ for (i = 0; i < LLQ_TABLESIZE; i++)
2032
+ {
2033
+ AnswerListElem *a = d->AnswerTable[i];
2034
+ while(a)
2035
+ {
2036
+ if (a->EventList)
2037
+ {
2038
+ CacheRecord *cr = a->EventList, *tmp;
2039
+ while (cr)
2040
+ {
2041
+ tmp = cr;
2042
+ cr = cr->next;
2043
+ if ((signed)tmp->resrec.rroriginalttl < 0) free(tmp);
2044
+ else
2045
+ {
2046
+ tmp->next = a->KnownAnswers;
2047
+ a->KnownAnswers = tmp;
2048
+ tmp->resrec.rroriginalttl = 0;
2049
+ }
2050
+ }
2051
+ a->EventList = NULL;
2052
+ }
2053
+ a = a->next;
2054
+ }
2055
+ }
2056
+ }
2057
+
2058
+ mDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e)
2059
+ {
2060
+ int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE;
2061
+ AnswerListElem *a = d->AnswerTable[bucket];
2062
+ while (a && (a->type != e->qtype ||!SameDomainName(&a->name, &e->qname))) a = a->next;
2063
+ if (!a)
2064
+ {
2065
+ a = malloc(sizeof(*a));
2066
+ if (!a) { LogErr("SetAnswerList", "malloc"); return; }
2067
+ AssignDomainName(&a->name, &e->qname);
2068
+ a->type = e->qtype;
2069
+ a->refcount = 0;
2070
+ a->EventList = NULL;
2071
+ a->UseTCP = mDNSfalse;
2072
+ a->next = d->AnswerTable[bucket];
2073
+ d->AnswerTable[bucket] = a;
2074
+ d->AnswerTableCount++;
2075
+ a->KnownAnswers = AnswerQuestion(d, a);
2076
+ }
2077
+
2078
+ e->AnswerList = a;
2079
+ a->refcount ++;
2080
+ }
2081
+
2082
+ // Allocate LLQ entry, insert into table
2083
+ mDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, mDNSu32 lease )
2084
+ {
2085
+ char addr[32];
2086
+ struct timeval t;
2087
+ int bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE;
2088
+ LLQEntry *e;
2089
+
2090
+ e = malloc(sizeof(*e));
2091
+ if (!e) { LogErr("NewLLQ", "malloc"); return NULL; }
2092
+
2093
+ inet_ntop(AF_INET, &cli.sin_addr, addr, 32);
2094
+ VLog("Allocating LLQ entry for client %s question %##s type %d", addr, qname->c, qtype);
2095
+
2096
+ // initialize structure
2097
+ e->cli = cli;
2098
+ AssignDomainName(&e->qname, qname);
2099
+ e->qtype = qtype;
2100
+ e->id = zeroOpaque64;
2101
+ e->state = RequestReceived;
2102
+ e->AnswerList = NULL;
2103
+
2104
+ if (lease < LLQ_MIN_LEASE) lease = LLQ_MIN_LEASE;
2105
+ else if (lease > LLQ_MAX_LEASE) lease = LLQ_MAX_LEASE;
2106
+
2107
+ gettimeofday(&t, NULL);
2108
+ e->expire = t.tv_sec + (int)lease;
2109
+ e->lease = lease;
2110
+
2111
+ // add to table
2112
+ e->next = d->LLQTable[bucket];
2113
+ d->LLQTable[bucket] = e;
2114
+
2115
+ return e;
2116
+ }
2117
+
2118
+ // Handle a refresh request from client
2119
+ mDNSlocal void LLQRefresh(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock )
2120
+ {
2121
+ AuthRecord opt;
2122
+ PktMsg ack;
2123
+ mDNSu8 *end = (mDNSu8 *)&ack.msg.data;
2124
+ char addr[32];
2125
+
2126
+ inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
2127
+ VLog("%s LLQ for %##s from %s", llq->llqlease ? "Refreshing" : "Deleting", e->qname.c, addr);
2128
+
2129
+ if (llq->llqlease)
2130
+ {
2131
+ struct timeval t;
2132
+ if (llq->llqlease < LLQ_MIN_LEASE) llq->llqlease = LLQ_MIN_LEASE;
2133
+ else if (llq->llqlease > LLQ_MAX_LEASE) llq->llqlease = LLQ_MIN_LEASE;
2134
+ gettimeofday(&t, NULL);
2135
+ e->expire = t.tv_sec + llq->llqlease;
2136
+ }
2137
+
2138
+ ack.src.sin_addr.s_addr = 0; // unused
2139
+ InitializeDNSMessage(&ack.msg.h, msgID, ResponseFlags);
2140
+ end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
2141
+ if (!end) { Log("Error: putQuestion"); return; }
2142
+
2143
+ FormatLLQOpt(&opt, kLLQOp_Refresh, &e->id, llq->llqlease ? LLQLease(e) : 0);
2144
+ end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAdditionals, &opt.resrec, 0);
2145
+ if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; }
2146
+
2147
+ ack.len = (int)(end - (mDNSu8 *)&ack.msg);
2148
+ if (SendLLQ(d, &ack, e->cli, sock)) Log("Error: LLQRefresh");
2149
+
2150
+ if (llq->llqlease) e->state = Established;
2151
+ else DeleteLLQ(d, e);
2152
+ }
2153
+
2154
+ // Complete handshake with Ack an initial answers
2155
+ mDNSlocal void LLQCompleteHandshake(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock)
2156
+ {
2157
+ char addr[32];
2158
+ CacheRecord *ptr;
2159
+ AuthRecord opt;
2160
+ PktMsg ack;
2161
+ mDNSu8 *end = (mDNSu8 *)&ack.msg.data;
2162
+ char rrbuf[MaxMsg], addrbuf[32];
2163
+
2164
+ inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
2165
+
2166
+ if (!mDNSSameOpaque64(&llq->id, &e->id) ||
2167
+ llq->vers != kLLQ_Vers ||
2168
+ llq->llqOp != kLLQOp_Setup ||
2169
+ llq->err != LLQErr_NoError ||
2170
+ llq->llqlease > e->lease + LLQ_LEASE_FUDGE ||
2171
+ llq->llqlease < e->lease - LLQ_LEASE_FUDGE)
2172
+ {
2173
+ Log("Incorrect challenge response from %s", addr);
2174
+ return;
2175
+ }
2176
+
2177
+ if (e->state == Established) VLog("Retransmitting LLQ ack + answers for %##s", e->qname.c);
2178
+ else VLog("Delivering LLQ ack + answers for %##s", e->qname.c);
2179
+
2180
+ // format ack + answers
2181
+ ack.src.sin_addr.s_addr = 0; // unused
2182
+ InitializeDNSMessage(&ack.msg.h, msgID, ResponseFlags);
2183
+ end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
2184
+ if (!end) { Log("Error: putQuestion"); return; }
2185
+
2186
+ if (e->state != Established) { SetAnswerList(d, e); e->state = Established; }
2187
+
2188
+ if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32);
2189
+ for (ptr = e->AnswerList->KnownAnswers; ptr; ptr = ptr->next)
2190
+ {
2191
+ if (verbose) GetRRDisplayString_rdb(&ptr->resrec, &ptr->resrec.rdata->u, rrbuf);
2192
+ VLog("%s Intitial Answer - %s", addr, rrbuf);
2193
+ end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAnswers, &ptr->resrec, 1);
2194
+ if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; }
2195
+ }
2196
+
2197
+ FormatLLQOpt(&opt, kLLQOp_Setup, &e->id, LLQLease(e));
2198
+ end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAdditionals, &opt.resrec, 0);
2199
+ if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; }
2200
+
2201
+ ack.len = (int)(end - (mDNSu8 *)&ack.msg);
2202
+ if (SendLLQ(d, &ack, e->cli, sock)) Log("Error: LLQCompleteHandshake");
2203
+ }
2204
+
2205
+ mDNSlocal void LLQSetupChallenge(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID)
2206
+ {
2207
+ struct timeval t;
2208
+ PktMsg challenge;
2209
+ mDNSu8 *end = challenge.msg.data;
2210
+ AuthRecord opt;
2211
+
2212
+ if (e->state == ChallengeSent) VLog("Retransmitting LLQ setup challenge for %##s", e->qname.c);
2213
+ else VLog("Sending LLQ setup challenge for %##s", e->qname.c);
2214
+
2215
+ if (!mDNSOpaque64IsZero(&llq->id)) { Log("Error: LLQSetupChallenge - nonzero ID"); return; } // server bug
2216
+ if (llq->llqOp != kLLQOp_Setup) { Log("LLQSetupChallenge - incorrrect operation from client"); return; } // client error
2217
+
2218
+ if (mDNSOpaque64IsZero(&e->id)) // don't regenerate random ID for retransmissions
2219
+ {
2220
+ // construct ID <time><random>
2221
+ gettimeofday(&t, NULL);
2222
+ e->id.l[0] = t.tv_sec;
2223
+ e->id.l[1] = random();
2224
+ }
2225
+
2226
+ // format response (query + LLQ opt rr)
2227
+ challenge.src.sin_addr.s_addr = 0; // unused
2228
+ InitializeDNSMessage(&challenge.msg.h, msgID, ResponseFlags);
2229
+ end = putQuestion(&challenge.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
2230
+ if (!end) { Log("Error: putQuestion"); return; }
2231
+ FormatLLQOpt(&opt, kLLQOp_Setup, &e->id, LLQLease(e));
2232
+ end = PutResourceRecordTTLJumbo(&challenge.msg, end, &challenge.msg.h.numAdditionals, &opt.resrec, 0);
2233
+ if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; }
2234
+ challenge.len = (int)(end - (mDNSu8 *)&challenge.msg);
2235
+ if (SendLLQ(d, &challenge, e->cli, NULL)) { Log("Error: LLQSetupChallenge"); return; }
2236
+ e->state = ChallengeSent;
2237
+ }
2238
+
2239
+ // Take action on an LLQ message from client. Entry must be initialized and in table
2240
+ mDNSlocal void UpdateLLQ(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock )
2241
+ {
2242
+ switch(e->state)
2243
+ {
2244
+ case RequestReceived:
2245
+ if ( sock )
2246
+ {
2247
+ struct timeval t;
2248
+ gettimeofday(&t, NULL);
2249
+ e->id.l[0] = t.tv_sec; // construct ID <time><random>
2250
+ e->id.l[1] = random();
2251
+ llq->id = e->id;
2252
+ LLQCompleteHandshake( d, e, llq, msgID, sock );
2253
+
2254
+ // Set the state to established because we've just set the LLQ up using TCP
2255
+ e->state = Established;
2256
+ }
2257
+ else
2258
+ {
2259
+ LLQSetupChallenge(d, e, llq, msgID);
2260
+ }
2261
+ return;
2262
+ case ChallengeSent:
2263
+ if (mDNSOpaque64IsZero(&llq->id)) LLQSetupChallenge(d, e, llq, msgID); // challenge sent and lost
2264
+ else LLQCompleteHandshake(d, e, llq, msgID, sock );
2265
+ return;
2266
+ case Established:
2267
+ if (mDNSOpaque64IsZero(&llq->id))
2268
+ {
2269
+ // client started over. reset state.
2270
+ LLQEntry *newe = NewLLQ(d, e->cli, &e->qname, e->qtype, llq->llqlease );
2271
+ if (!newe) return;
2272
+ DeleteLLQ(d, e);
2273
+ LLQSetupChallenge(d, newe, llq, msgID);
2274
+ return;
2275
+ }
2276
+ else if (llq->llqOp == kLLQOp_Setup)
2277
+ { LLQCompleteHandshake(d, e, llq, msgID, sock); return; } // Ack lost
2278
+ else if (llq->llqOp == kLLQOp_Refresh)
2279
+ { LLQRefresh(d, e, llq, msgID, sock); return; }
2280
+ else { Log("Unhandled message for established LLQ"); return; }
2281
+ }
2282
+ }
2283
+
2284
+ mDNSlocal LLQEntry *LookupLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, const mDNSOpaque64 *const id)
2285
+ {
2286
+ int bucket = bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE;
2287
+ LLQEntry *ptr = d->LLQTable[bucket];
2288
+
2289
+ while(ptr)
2290
+ {
2291
+ if (((ptr->state == ChallengeSent && mDNSOpaque64IsZero(id) && (cli.sin_port == ptr->cli.sin_port)) || // zero-id due to packet loss OK in state ChallengeSent
2292
+ mDNSSameOpaque64(id, &ptr->id)) && // id match
2293
+ (cli.sin_addr.s_addr == ptr->cli.sin_addr.s_addr) && (qtype == ptr->qtype) && SameDomainName(&ptr->qname, qname)) // same source, type, qname
2294
+ return ptr;
2295
+ ptr = ptr->next;
2296
+ }
2297
+ return NULL;
2298
+ }
2299
+
2300
+ mDNSlocal int
2301
+ RecvNotify
2302
+ (
2303
+ DaemonInfo * d,
2304
+ PktMsg * pkt
2305
+ )
2306
+ {
2307
+ int res;
2308
+ int err = 0;
2309
+
2310
+ pkt->msg.h.flags.b[0] |= kDNSFlag0_QR_Response;
2311
+
2312
+ res = sendto( d->udpsd, &pkt->msg, pkt->len, 0, ( struct sockaddr* ) &pkt->src, sizeof( pkt->src ) );
2313
+ require_action( res == ( int ) pkt->len, exit, err = mStatus_UnknownErr; LogErr( "RecvNotify", "sendto" ) );
2314
+
2315
+ exit:
2316
+
2317
+ return err;
2318
+ }
2319
+
2320
+
2321
+ mDNSlocal int RecvLLQ( DaemonInfo *d, PktMsg *pkt, TCPSocket *sock )
2322
+ {
2323
+ DNSQuestion q;
2324
+ LargeCacheRecord opt;
2325
+ int i, err = -1;
2326
+ char addr[32];
2327
+ const mDNSu8 *qptr = pkt->msg.data;
2328
+ const mDNSu8 *end = (mDNSu8 *)&pkt->msg + pkt->len;
2329
+ const mDNSu8 *aptr;
2330
+ LLQOptData *llq = NULL;
2331
+ LLQEntry *e = NULL;
2332
+
2333
+ HdrNToH(pkt);
2334
+ aptr = LocateAdditionals(&pkt->msg, end); // Can't do this until after HdrNToH(pkt);
2335
+ inet_ntop(AF_INET, &pkt->src.sin_addr, addr, 32);
2336
+
2337
+ VLog("Received LLQ msg from %s", addr);
2338
+ // sanity-check packet
2339
+ if (!pkt->msg.h.numQuestions || !pkt->msg.h.numAdditionals)
2340
+ {
2341
+ Log("Malformatted LLQ from %s with %d questions, %d additionals", addr, pkt->msg.h.numQuestions, pkt->msg.h.numAdditionals);
2342
+ goto end;
2343
+ }
2344
+
2345
+ // Locate the OPT record.
2346
+ // According to RFC 2671, "One OPT pseudo-RR can be added to the additional data section of either a request or a response."
2347
+ // This implies that there may be *at most* one OPT record per DNS message, in the Additional Section,
2348
+ // but not necessarily the *last* entry in the Additional Section.
2349
+ for (i = 0; i < pkt->msg.h.numAdditionals; i++)
2350
+ {
2351
+ aptr = GetLargeResourceRecord(NULL, &pkt->msg, aptr, end, 0, kDNSRecordTypePacketAdd, &opt);
2352
+ if (!aptr) { Log("Malformatted LLQ from %s: could not get Additional record %d", addr, i); goto end; }
2353
+ if (opt.r.resrec.RecordType != kDNSRecordTypePacketNegative && opt.r.resrec.rrtype == kDNSType_OPT) break;
2354
+ }
2355
+
2356
+ // validate OPT
2357
+ if (opt.r.resrec.rrtype != kDNSType_OPT) { Log("Malformatted LLQ from %s: last Additional not an OPT RR", addr); goto end; }
2358
+ if (opt.r.resrec.rdlength < pkt->msg.h.numQuestions * DNSOpt_LLQData_Space) { Log("Malformatted LLQ from %s: OPT RR to small (%d bytes for %d questions)", addr, opt.r.resrec.rdlength, pkt->msg.h.numQuestions); }
2359
+
2360
+ // dispatch each question
2361
+ for (i = 0; i < pkt->msg.h.numQuestions; i++)
2362
+ {
2363
+ qptr = getQuestion(&pkt->msg, qptr, end, 0, &q);
2364
+ if (!qptr) { Log("Malformatted LLQ from %s: cannot read question %d", addr, i); goto end; }
2365
+ llq = (LLQOptData *)&opt.r.resrec.rdata->u.opt[0].u.llq + i; // point into OptData at index i
2366
+ if (llq->vers != kLLQ_Vers) { Log("LLQ from %s contains bad version %d (expected %d)", addr, llq->vers, kLLQ_Vers); goto end; }
2367
+
2368
+ e = LookupLLQ(d, pkt->src, &q.qname, q.qtype, &llq->id);
2369
+ if (!e)
2370
+ {
2371
+ // no entry - if zero ID, create new
2372
+ e = NewLLQ(d, pkt->src, &q.qname, q.qtype, llq->llqlease );
2373
+ if (!e) goto end;
2374
+ }
2375
+ UpdateLLQ(d, e, llq, pkt->msg.h.id, sock);
2376
+ }
2377
+ err = 0;
2378
+
2379
+ end:
2380
+ HdrHToN(pkt);
2381
+ return err;
2382
+ }
2383
+
2384
+
2385
+ mDNSlocal mDNSBool IsAuthorized( DaemonInfo * d, PktMsg * pkt, DomainAuthInfo ** key, mDNSu16 * rcode, mDNSu16 * tcode )
2386
+ {
2387
+ const mDNSu8 * lastPtr = NULL;
2388
+ const mDNSu8 * ptr = NULL;
2389
+ DomainAuthInfo * keys;
2390
+ mDNSu8 * end = ( mDNSu8* ) &pkt->msg + pkt->len;
2391
+ LargeCacheRecord lcr;
2392
+ mDNSBool hasTSIG = mDNSfalse;
2393
+ mDNSBool strip = mDNSfalse;
2394
+ mDNSBool ok = mDNSfalse;
2395
+ int i;
2396
+
2397
+ // Unused parameters
2398
+
2399
+ ( void ) d;
2400
+
2401
+ HdrNToH(pkt);
2402
+
2403
+ *key = NULL;
2404
+
2405
+ if ( pkt->msg.h.numAdditionals )
2406
+ {
2407
+ ptr = LocateAdditionals(&pkt->msg, end);
2408
+ if (ptr)
2409
+ {
2410
+ for (i = 0; i < pkt->msg.h.numAdditionals; i++)
2411
+ {
2412
+ lastPtr = ptr;
2413
+ ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr);
2414
+ if (!ptr)
2415
+ {
2416
+ Log("Unable to read additional record");
2417
+ lastPtr = NULL;
2418
+ break;
2419
+ }
2420
+ }
2421
+
2422
+ hasTSIG = ( ptr && lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rrtype == kDNSType_TSIG );
2423
+ }
2424
+ else
2425
+ {
2426
+ LogMsg( "IsAuthorized: unable to find Additional section" );
2427
+ }
2428
+ }
2429
+
2430
+ // If we don't know what zone this is, then it's authorized.
2431
+
2432
+ if ( !pkt->zone )
2433
+ {
2434
+ ok = mDNStrue;
2435
+ strip = mDNSfalse;
2436
+ goto exit;
2437
+ }
2438
+
2439
+ if ( IsQuery( pkt ) )
2440
+ {
2441
+ keys = pkt->zone->queryKeys;
2442
+ strip = mDNStrue;
2443
+ }
2444
+ else if ( IsUpdate( pkt ) )
2445
+ {
2446
+ keys = pkt->zone->updateKeys;
2447
+ strip = mDNSfalse;
2448
+ }
2449
+ else
2450
+ {
2451
+ ok = mDNStrue;
2452
+ strip = mDNSfalse;
2453
+ goto exit;
2454
+ }
2455
+
2456
+ if ( pkt->isZonePublic )
2457
+ {
2458
+ ok = mDNStrue;
2459
+ goto exit;
2460
+ }
2461
+
2462
+ // If there are no keys, then we're authorized
2463
+
2464
+ if ( ( hasTSIG && !keys ) || ( !hasTSIG && keys ) )
2465
+ {
2466
+ Log( "Invalid TSIG spec %##s for zone %##s", lcr.r.resrec.name->c, pkt->zone->name.c );
2467
+ *rcode = kDNSFlag1_RC_NotAuth;
2468
+ *tcode = TSIG_ErrBadKey;
2469
+ strip = mDNStrue;
2470
+ ok = mDNSfalse;
2471
+ goto exit;
2472
+ }
2473
+
2474
+ // Find the right key
2475
+
2476
+ for ( *key = keys; *key; *key = (*key)->next )
2477
+ {
2478
+ if ( SameDomainName( lcr.r.resrec.name, &(*key)->keyname ) )
2479
+ {
2480
+ break;
2481
+ }
2482
+ }
2483
+
2484
+ if ( !(*key) )
2485
+ {
2486
+ Log( "Invalid TSIG name %##s for zone %##s", lcr.r.resrec.name->c, pkt->zone->name.c );
2487
+ *rcode = kDNSFlag1_RC_NotAuth;
2488
+ *tcode = TSIG_ErrBadKey;
2489
+ strip = mDNStrue;
2490
+ ok = mDNSfalse;
2491
+ goto exit;
2492
+ }
2493
+
2494
+ // Okay, we have the correct key and a TSIG record. DNSDigest_VerifyMessage does the heavy
2495
+ // lifting of message verification
2496
+
2497
+ pkt->msg.h.numAdditionals--;
2498
+
2499
+ HdrHToN( pkt );
2500
+
2501
+ ok = DNSDigest_VerifyMessage( &pkt->msg, ( mDNSu8* ) lastPtr, &lcr, (*key), rcode, tcode );
2502
+
2503
+ HdrNToH( pkt );
2504
+
2505
+ pkt->msg.h.numAdditionals++;
2506
+
2507
+ exit:
2508
+
2509
+ if ( hasTSIG && strip )
2510
+ {
2511
+ // Strip the TSIG from the message
2512
+
2513
+ pkt->msg.h.numAdditionals--;
2514
+ pkt->len = lastPtr - ( mDNSu8* ) ( &pkt->msg );
2515
+ }
2516
+
2517
+ HdrHToN(pkt);
2518
+
2519
+ return ok;
2520
+ }
2521
+
2522
+ // request handler wrappers for TCP and UDP requests
2523
+ // (read message off socket, fork thread that invokes main processing routine and handles cleanup)
2524
+
2525
+ mDNSlocal void*
2526
+ UDPMessageHandler
2527
+ (
2528
+ void * vptr
2529
+ )
2530
+ {
2531
+ UDPContext * context = ( UDPContext* ) vptr;
2532
+ PktMsg * reply = NULL;
2533
+ int res;
2534
+ mStatus err;
2535
+
2536
+ // !!!KRS strictly speaking, we shouldn't use TCP for a UDP request because the server
2537
+ // may give us a long answer that would require truncation for UDP delivery to client
2538
+
2539
+ reply = HandleRequest( context->d, &context->pkt );
2540
+ require_action( reply, exit, err = mStatus_UnknownErr );
2541
+
2542
+ res = sendto( context->sd, &reply->msg, reply->len, 0, ( struct sockaddr* ) &context->pkt.src, sizeof( context->pkt.src ) );
2543
+ require_action_quiet( res == ( int ) reply->len, exit, LogErr( "UDPMessageHandler", "sendto" ) );
2544
+
2545
+ exit:
2546
+
2547
+ if ( reply )
2548
+ {
2549
+ free( reply );
2550
+ }
2551
+
2552
+ free( context );
2553
+
2554
+ pthread_exit( NULL );
2555
+
2556
+ return NULL;
2557
+ }
2558
+
2559
+
2560
+ mDNSlocal int
2561
+ RecvUDPMessage
2562
+ (
2563
+ DaemonInfo * self,
2564
+ int sd
2565
+ )
2566
+ {
2567
+ UDPContext * context = NULL;
2568
+ pthread_t tid;
2569
+ mDNSu16 rcode;
2570
+ mDNSu16 tcode;
2571
+ DomainAuthInfo * key;
2572
+ unsigned int clisize = sizeof( context->cliaddr );
2573
+ int res;
2574
+ mStatus err = mStatus_NoError;
2575
+
2576
+ context = malloc( sizeof( UDPContext ) );
2577
+ require_action( context, exit, err = mStatus_NoMemoryErr ; LogErr( "RecvUDPMessage", "malloc" ) );
2578
+
2579
+ mDNSPlatformMemZero( context, sizeof( *context ) );
2580
+ context->d = self;
2581
+ context->sd = sd;
2582
+
2583
+ res = recvfrom(sd, &context->pkt.msg, sizeof(context->pkt.msg), 0, (struct sockaddr *)&context->cliaddr, &clisize);
2584
+
2585
+ require_action( res >= 0, exit, err = mStatus_UnknownErr ; LogErr( "RecvUDPMessage", "recvfrom" ) );
2586
+ context->pkt.len = res;
2587
+ require_action( clisize == sizeof( context->cliaddr ), exit, err = mStatus_UnknownErr ; Log( "Client address of unknown size %d", clisize ) );
2588
+ context->pkt.src = context->cliaddr;
2589
+
2590
+ // Set the zone in the packet
2591
+
2592
+ SetZone( context->d, &context->pkt );
2593
+
2594
+ // Notify messages handled by main thread
2595
+
2596
+ if ( IsNotify( &context->pkt ) )
2597
+ {
2598
+ int e = RecvNotify( self, &context->pkt );
2599
+ free(context);
2600
+ return e;
2601
+ }
2602
+ else if ( IsAuthorized( context->d, &context->pkt, &key, &rcode, &tcode ) )
2603
+ {
2604
+ if ( IsLLQRequest( &context->pkt ) )
2605
+ {
2606
+ // LLQ messages handled by main thread
2607
+ int e = RecvLLQ( self, &context->pkt, NULL );
2608
+ free(context);
2609
+ return e;
2610
+ }
2611
+
2612
+ if ( IsLLQAck(&context->pkt ) )
2613
+ {
2614
+ // !!!KRS need to do acks + retrans
2615
+
2616
+ free(context);
2617
+ return 0;
2618
+ }
2619
+
2620
+ err = pthread_create( &tid, NULL, UDPMessageHandler, context );
2621
+ require_action( !err, exit, LogErr( "RecvUDPMessage", "pthread_create" ) );
2622
+
2623
+ pthread_detach(tid);
2624
+ }
2625
+ else
2626
+ {
2627
+ PktMsg reply;
2628
+ int e;
2629
+
2630
+ memcpy( &reply, &context->pkt, sizeof( PktMsg ) );
2631
+
2632
+ reply.msg.h.flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_AA | kDNSFlag0_RD;
2633
+ reply.msg.h.flags.b[1] = kDNSFlag1_RA | kDNSFlag1_RC_NXDomain;
2634
+
2635
+ e = sendto( sd, &reply.msg, reply.len, 0, ( struct sockaddr* ) &context->pkt.src, sizeof( context->pkt.src ) );
2636
+ require_action_quiet( e == ( int ) reply.len, exit, LogErr( "RecvUDPMessage", "sendto" ) );
2637
+
2638
+ err = mStatus_NoAuth;
2639
+ }
2640
+
2641
+ exit:
2642
+
2643
+ if ( err && context )
2644
+ {
2645
+ free( context );
2646
+ }
2647
+
2648
+ return err;
2649
+ }
2650
+
2651
+
2652
+ mDNSlocal void
2653
+ FreeTCPContext
2654
+ (
2655
+ TCPContext * context
2656
+ )
2657
+ {
2658
+ if ( context )
2659
+ {
2660
+ if ( context->sock )
2661
+ {
2662
+ mDNSPlatformTCPCloseConnection( context->sock );
2663
+ }
2664
+
2665
+ free( context );
2666
+ }
2667
+ }
2668
+
2669
+
2670
+ mDNSlocal void*
2671
+ TCPMessageHandler
2672
+ (
2673
+ void * vptr
2674
+ )
2675
+ {
2676
+ TCPContext * context = ( TCPContext* ) vptr;
2677
+ PktMsg * reply = NULL;
2678
+ int res;
2679
+ char buf[32];
2680
+
2681
+ //!!!KRS if this read blocks indefinitely, we can run out of threads
2682
+ // read the request
2683
+
2684
+ reply = HandleRequest( context->d, &context->pkt );
2685
+ require_action_quiet( reply, exit, LogMsg( "TCPMessageHandler: No reply for client %s", inet_ntop( AF_INET, &context->cliaddr.sin_addr, buf, 32 ) ) );
2686
+
2687
+ // deliver reply to client
2688
+
2689
+ res = SendPacket( context->sock, reply );
2690
+ require_action( res >= 0, exit, LogMsg("TCPMessageHandler: Unable to send reply to client %s", inet_ntop(AF_INET, &context->cliaddr.sin_addr, buf, 32 ) ) );
2691
+
2692
+ exit:
2693
+
2694
+ FreeTCPContext( context );
2695
+
2696
+ if ( reply )
2697
+ {
2698
+ free( reply );
2699
+ }
2700
+
2701
+ pthread_exit(NULL);
2702
+ }
2703
+
2704
+
2705
+ mDNSlocal void
2706
+ RecvTCPMessage
2707
+ (
2708
+ void * param
2709
+ )
2710
+ {
2711
+ TCPContext * context = ( TCPContext* ) param;
2712
+ mDNSu16 rcode;
2713
+ mDNSu16 tcode;
2714
+ pthread_t tid;
2715
+ DomainAuthInfo * key;
2716
+ PktMsg * pkt;
2717
+ mDNSBool closed;
2718
+ mDNSBool freeContext = mDNStrue;
2719
+ mStatus err = mStatus_NoError;
2720
+
2721
+ // Receive a packet. It's okay if we don't actually read a packet, as long as the closed flag is
2722
+ // set to false. This is because SSL/TLS layer might gobble up the first packet that we read off the
2723
+ // wire. We'll let it do that, and wait for the next packet which will be ours.
2724
+
2725
+ pkt = RecvPacket( context->sock, &context->pkt, &closed );
2726
+ if (pkt) HdrNToH(pkt);
2727
+ require_action( pkt || !closed, exit, err = mStatus_UnknownErr; LogMsg( "client disconnected" ) );
2728
+
2729
+ if ( pkt )
2730
+ {
2731
+ // Always do this, regardless of what kind of packet it is. If we wanted LLQ events to be sent over TCP,
2732
+ // we would change this line of code. As it is now, we will reply to an LLQ via TCP, but then events
2733
+ // are sent over UDP
2734
+
2735
+ RemoveSourceFromEventLoop( context->d, context->sock );
2736
+
2737
+ // Set's the DNS Zone that is associated with this message
2738
+
2739
+ SetZone( context->d, &context->pkt );
2740
+
2741
+ // IsAuthorized will make sure the message is authorized for the designated zone.
2742
+ // After verifying the signature, it will strip the TSIG from the message
2743
+
2744
+ if ( IsAuthorized( context->d, &context->pkt, &key, &rcode, &tcode ) )
2745
+ {
2746
+ if ( IsLLQRequest( &context->pkt ) )
2747
+ {
2748
+ // LLQ messages handled by main thread
2749
+ RecvLLQ( context->d, &context->pkt, context->sock);
2750
+ }
2751
+ else
2752
+ {
2753
+ err = pthread_create( &tid, NULL, TCPMessageHandler, context );
2754
+
2755
+ if ( err )
2756
+ {
2757
+ LogErr( "RecvTCPMessage", "pthread_create" );
2758
+ err = mStatus_NoError;
2759
+ goto exit;
2760
+ }
2761
+
2762
+ // Let the thread free the context
2763
+
2764
+ freeContext = mDNSfalse;
2765
+
2766
+ pthread_detach(tid);
2767
+ }
2768
+ }
2769
+ else
2770
+ {
2771
+ PktMsg reply;
2772
+
2773
+ LogMsg( "Client %s Not authorized for zone %##s", inet_ntoa( context->pkt.src.sin_addr ), pkt->zone->name.c );
2774
+
2775
+ memcpy( &reply, &context->pkt, sizeof( PktMsg ) );
2776
+
2777
+ reply.msg.h.flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_AA | kDNSFlag0_RD;
2778
+ reply.msg.h.flags.b[1] = kDNSFlag1_RA | kDNSFlag1_RC_Refused;
2779
+
2780
+ SendPacket( context->sock, &reply );
2781
+ }
2782
+ }
2783
+ else
2784
+ {
2785
+ freeContext = mDNSfalse;
2786
+ }
2787
+
2788
+ exit:
2789
+
2790
+ if ( err )
2791
+ {
2792
+ RemoveSourceFromEventLoop( context->d, context->sock );
2793
+ }
2794
+
2795
+ if ( freeContext )
2796
+ {
2797
+ FreeTCPContext( context );
2798
+ }
2799
+ }
2800
+
2801
+
2802
+ mDNSlocal int
2803
+ AcceptTCPConnection
2804
+ (
2805
+ DaemonInfo * self,
2806
+ int sd,
2807
+ TCPSocketFlags flags
2808
+ )
2809
+ {
2810
+ TCPContext * context = NULL;
2811
+ unsigned int clilen = sizeof( context->cliaddr);
2812
+ int newSock;
2813
+ mStatus err = mStatus_NoError;
2814
+
2815
+ context = ( TCPContext* ) malloc( sizeof( TCPContext ) );
2816
+ require_action( context, exit, err = mStatus_NoMemoryErr; LogErr( "AcceptTCPConnection", "malloc" ) );
2817
+ mDNSPlatformMemZero( context, sizeof( sizeof( TCPContext ) ) );
2818
+ context->d = self;
2819
+ newSock = accept( sd, ( struct sockaddr* ) &context->cliaddr, &clilen );
2820
+ require_action( newSock != -1, exit, err = mStatus_UnknownErr; LogErr( "AcceptTCPConnection", "accept" ) );
2821
+
2822
+ context->sock = mDNSPlatformTCPAccept( flags, newSock );
2823
+ require_action( context->sock, exit, err = mStatus_UnknownErr; LogErr( "AcceptTCPConnection", "mDNSPlatformTCPAccept" ) );
2824
+
2825
+ err = AddSourceToEventLoop( self, context->sock, RecvTCPMessage, context );
2826
+ require_action( !err, exit, LogErr( "AcceptTCPConnection", "AddSourceToEventLoop" ) );
2827
+
2828
+ exit:
2829
+
2830
+ if ( err && context )
2831
+ {
2832
+ free( context );
2833
+ context = NULL;
2834
+ }
2835
+
2836
+ return err;
2837
+ }
2838
+
2839
+
2840
+ // main event loop
2841
+ // listen for incoming requests, periodically check table for expired records, respond to signals
2842
+ mDNSlocal int Run(DaemonInfo *d)
2843
+ {
2844
+ int staticMaxFD, nfds;
2845
+ fd_set rset;
2846
+ struct timeval timenow, timeout, EventTS, tablecheck = { 0, 0 };
2847
+ mDNSBool EventsPending = mDNSfalse;
2848
+
2849
+ VLog("Listening for requests...");
2850
+
2851
+ staticMaxFD = 0;
2852
+
2853
+ if ( d->tcpsd + 1 > staticMaxFD ) staticMaxFD = d->tcpsd + 1;
2854
+ if ( d->udpsd + 1 > staticMaxFD ) staticMaxFD = d->udpsd + 1;
2855
+ if ( d->tlssd + 1 > staticMaxFD ) staticMaxFD = d->tlssd + 1;
2856
+ if ( d->llq_tcpsd + 1 > staticMaxFD ) staticMaxFD = d->llq_tcpsd + 1;
2857
+ if ( d->llq_udpsd + 1 > staticMaxFD ) staticMaxFD = d->llq_udpsd + 1;
2858
+ if ( d->LLQEventListenSock + 1 > staticMaxFD ) staticMaxFD = d->LLQEventListenSock + 1;
2859
+
2860
+ while(1)
2861
+ {
2862
+ EventSource * source;
2863
+ int maxFD;
2864
+
2865
+ // set timeout
2866
+ timeout.tv_sec = timeout.tv_usec = 0;
2867
+ if (gettimeofday(&timenow, NULL)) { LogErr("Run", "gettimeofday"); return -1; }
2868
+
2869
+ if (EventsPending)
2870
+ {
2871
+ if (timenow.tv_sec - EventTS.tv_sec >= 5) // if we've been waiting 5 seconds for a "quiet" period to send
2872
+ { GenLLQEvents(d); EventsPending = mDNSfalse; } // events, we go ahead and do it now
2873
+ else timeout.tv_usec = 500000; // else do events after 1/2 second with no new events or LLQs
2874
+ }
2875
+ if (!EventsPending)
2876
+ {
2877
+ // if no pending events, timeout when we need to check for expired records
2878
+ if (tablecheck.tv_sec && timenow.tv_sec - tablecheck.tv_sec >= 0)
2879
+ { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; } // table check overdue
2880
+ if (!tablecheck.tv_sec) tablecheck.tv_sec = timenow.tv_sec + EXPIRATION_INTERVAL;
2881
+ timeout.tv_sec = tablecheck.tv_sec - timenow.tv_sec;
2882
+ }
2883
+
2884
+ FD_ZERO(&rset);
2885
+ FD_SET( d->tcpsd, &rset );
2886
+ FD_SET( d->udpsd, &rset );
2887
+ FD_SET( d->tlssd, &rset );
2888
+ FD_SET( d->llq_tcpsd, &rset );
2889
+ FD_SET( d->llq_udpsd, &rset );
2890
+ FD_SET( d->LLQEventListenSock, &rset );
2891
+
2892
+ maxFD = staticMaxFD;
2893
+
2894
+ for ( source = ( EventSource* ) d->eventSources.Head; source; source = source->next )
2895
+ {
2896
+ FD_SET( source->fd, &rset );
2897
+
2898
+ if ( source->fd > maxFD )
2899
+ {
2900
+ maxFD = source->fd;
2901
+ }
2902
+ }
2903
+
2904
+ nfds = select( maxFD + 1, &rset, NULL, NULL, &timeout);
2905
+ if (nfds < 0)
2906
+ {
2907
+ if (errno == EINTR)
2908
+ {
2909
+ if (terminate)
2910
+ {
2911
+ // close sockets to prevent clients from making new requests during shutdown
2912
+ close( d->tcpsd );
2913
+ close( d->udpsd );
2914
+ close( d->tlssd );
2915
+ close( d->llq_tcpsd );
2916
+ close( d->llq_udpsd );
2917
+ d->tcpsd = d->udpsd = d->tlssd = d->llq_tcpsd = d->llq_udpsd = -1;
2918
+ DeleteRecords(d, mDNStrue);
2919
+ return 0;
2920
+ }
2921
+ else if (dumptable)
2922
+ {
2923
+ Log( "Received SIGINFO" );
2924
+
2925
+ PrintLeaseTable(d);
2926
+ PrintLLQTable(d);
2927
+ PrintLLQAnswers(d);
2928
+ dumptable = 0;
2929
+ }
2930
+ else if (hangup)
2931
+ {
2932
+ int err;
2933
+
2934
+ Log( "Received SIGHUP" );
2935
+
2936
+ err = ParseConfig( d, cfgfile );
2937
+
2938
+ if ( err )
2939
+ {
2940
+ LogErr( "Run", "ParseConfig" );
2941
+ return -1;
2942
+ }
2943
+
2944
+ hangup = 0;
2945
+ }
2946
+ else
2947
+ {
2948
+ Log("Received unhandled signal - continuing");
2949
+ }
2950
+ }
2951
+ else
2952
+ {
2953
+ LogErr("Run", "select"); return -1;
2954
+ }
2955
+ }
2956
+ else if (nfds)
2957
+ {
2958
+ if (FD_ISSET(d->udpsd, &rset)) RecvUDPMessage( d, d->udpsd );
2959
+ if (FD_ISSET(d->llq_udpsd, &rset)) RecvUDPMessage( d, d->llq_udpsd );
2960
+ if (FD_ISSET(d->tcpsd, &rset)) AcceptTCPConnection( d, d->tcpsd, 0 );
2961
+ if (FD_ISSET(d->llq_tcpsd, &rset)) AcceptTCPConnection( d, d->llq_tcpsd, 0 );
2962
+ if (FD_ISSET(d->tlssd, &rset)) AcceptTCPConnection( d, d->tlssd, TCP_SOCKET_FLAGS );
2963
+ if (FD_ISSET(d->LLQEventListenSock, &rset))
2964
+ {
2965
+ // clear signalling data off socket
2966
+ char buf[256];
2967
+ recv(d->LLQEventListenSock, buf, 256, 0);
2968
+ if (!EventsPending)
2969
+ {
2970
+ EventsPending = mDNStrue;
2971
+ if (gettimeofday(&EventTS, NULL)) { LogErr("Run", "gettimeofday"); return -1; }
2972
+ }
2973
+ }
2974
+
2975
+ for ( source = ( EventSource* ) d->eventSources.Head; source; source = source->next )
2976
+ {
2977
+ if ( FD_ISSET( source->fd, &rset ) )
2978
+ {
2979
+ source->callback( source->context );
2980
+ break; // in case we removed this guy from the event loop
2981
+ }
2982
+ }
2983
+ }
2984
+ else
2985
+ {
2986
+ // timeout
2987
+ if (EventsPending) { GenLLQEvents(d); EventsPending = mDNSfalse; }
2988
+ else { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; }
2989
+ }
2990
+ }
2991
+ return 0;
2992
+ }
2993
+
2994
+ // signal handler sets global variables, which are inspected by main event loop
2995
+ // (select automatically returns due to the handled signal)
2996
+ mDNSlocal void HndlSignal(int sig)
2997
+ {
2998
+ if (sig == SIGTERM || sig == SIGINT ) { terminate = 1; return; }
2999
+ if (sig == INFO_SIGNAL) { dumptable = 1; return; }
3000
+ if (sig == SIGHUP) { hangup = 1; return; }
3001
+ }
3002
+
3003
+ mDNSlocal mStatus
3004
+ SetPublicSRV
3005
+ (
3006
+ DaemonInfo * d,
3007
+ const char * name
3008
+ )
3009
+ {
3010
+ DNameListElem * elem;
3011
+ mStatus err = mStatus_NoError;
3012
+
3013
+ elem = ( DNameListElem* ) malloc( sizeof( DNameListElem ) );
3014
+ require_action( elem, exit, err = mStatus_NoMemoryErr );
3015
+ MakeDomainNameFromDNSNameString( &elem->name, name );
3016
+ elem->next = d->public_names;
3017
+ d->public_names = elem;
3018
+
3019
+ exit:
3020
+
3021
+ return err;
3022
+ }
3023
+
3024
+
3025
+ int main(int argc, char *argv[])
3026
+ {
3027
+ int started_via_launchd = 0;
3028
+ DaemonInfo *d;
3029
+ struct rlimit rlim;
3030
+
3031
+ Log("dnsextd starting");
3032
+
3033
+ d = malloc(sizeof(*d));
3034
+ if (!d) { LogErr("main", "malloc"); exit(1); }
3035
+ mDNSPlatformMemZero(d, sizeof(DaemonInfo));
3036
+
3037
+ // Setup the public SRV record names
3038
+
3039
+ SetPublicSRV(d, "_dns-update._udp.");
3040
+ SetPublicSRV(d, "_dns-llq._udp.");
3041
+ SetPublicSRV(d, "_dns-update-tls._tcp.");
3042
+ SetPublicSRV(d, "_dns-query-tls._tcp.");
3043
+ SetPublicSRV(d, "_dns-llq-tls._tcp.");
3044
+
3045
+ // Setup signal handling
3046
+
3047
+ if (signal(SIGHUP, HndlSignal) == SIG_ERR) perror("Can't catch SIGHUP");
3048
+ if (signal(SIGTERM, HndlSignal) == SIG_ERR) perror("Can't catch SIGTERM");
3049
+ if (signal(INFO_SIGNAL, HndlSignal) == SIG_ERR) perror("Can't catch SIGINFO");
3050
+ if (signal(SIGINT, HndlSignal) == SIG_ERR) perror("Can't catch SIGINT");
3051
+ if (signal(SIGPIPE, SIG_IGN ) == SIG_ERR) perror("Can't ignore SIGPIPE");
3052
+
3053
+ // remove open file limit
3054
+ rlim.rlim_max = RLIM_INFINITY;
3055
+ rlim.rlim_cur = RLIM_INFINITY;
3056
+ if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
3057
+ {
3058
+ LogErr("main", "setrlimit");
3059
+ Log("Using default file descriptor resource limit");
3060
+ }
3061
+
3062
+ if (argc > 1 && !strcasecmp(argv[1], "-launchd"))
3063
+ {
3064
+ Log("started_via_launchd");
3065
+ started_via_launchd = 1;
3066
+ argv++;
3067
+ argc--;
3068
+ }
3069
+ if (ProcessArgs(argc, argv, d) < 0) { LogErr("main", "ProcessArgs"); exit(1); }
3070
+
3071
+ if (!foreground && !started_via_launchd)
3072
+ {
3073
+ if (daemon(0,0))
3074
+ {
3075
+ LogErr("main", "daemon");
3076
+ foreground = 1;
3077
+ }
3078
+ }
3079
+
3080
+ if (InitLeaseTable(d) < 0) { LogErr("main", "InitLeaseTable"); exit(1); }
3081
+ if (SetupSockets(d) < 0) { LogErr("main", "SetupSockets"); exit(1); }
3082
+ if (SetUpdateSRV(d) < 0) { LogErr("main", "SetUpdateSRV"); exit(1); }
3083
+
3084
+ Run(d);
3085
+
3086
+ Log("dnsextd stopping");
3087
+
3088
+ if (ClearUpdateSRV(d) < 0) { LogErr("main", "ClearUpdateSRV"); exit(1); } // clear update srv's even if Run or pthread_create returns an error
3089
+ free(d);
3090
+ exit(0);
3091
+ }
3092
+
3093
+
3094
+ // These are stubbed out implementations of up-call routines that the various platform support layers
3095
+ // call. These routines are fully implemented in both mDNS.c and uDNS.c, but dnsextd doesn't
3096
+ // link this code in.
3097
+ //
3098
+ // It's an error for these routines to actually be called, so perhaps we should log any call
3099
+ // to them.
3100
+ void mDNSCoreInitComplete( mDNS * const m, mStatus result) { ( void ) m; ( void ) result; }
3101
+ void mDNS_ConfigChanged(mDNS *const m) { ( void ) m; }
3102
+ void mDNSCoreMachineSleep(mDNS * const m, mDNSBool wake) { ( void ) m; ( void ) wake; }
3103
+ void mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end,
3104
+ const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
3105
+ const mDNSAddr *const dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID iid)
3106
+ { ( void ) m; ( void ) msg; ( void ) end; ( void ) srcaddr; ( void ) srcport; ( void ) dstaddr; ( void ) dstport; ( void ) iid; }
3107
+ DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped, mDNSu32 timeout)
3108
+ { ( void ) m; ( void ) d; ( void ) interface; ( void ) addr; ( void ) port; ( void ) scoped; ( void ) timeout; return(NULL); }
3109
+ void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID) { (void)domain; (void) InterfaceID;}
3110
+ void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext)
3111
+ { ( void ) m; ( void ) fqdn; ( void ) StatusCallback; ( void ) StatusContext; }
3112
+ mDNSs32 mDNS_Execute (mDNS *const m) { ( void ) m; return 0; }
3113
+ mDNSs32 mDNS_TimeNow(const mDNS *const m) { ( void ) m; return 0; }
3114
+ mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr) { ( void ) m; ( void ) rr; return 0; }
3115
+ void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping)
3116
+ { ( void ) m; ( void ) set; ( void ) flapping; }
3117
+ const char * const mDNS_DomainTypeNames[1] = {};
3118
+ mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom,
3119
+ const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context)
3120
+ { ( void ) m; ( void ) question; ( void ) DomainType; ( void ) dom; ( void ) InterfaceID; ( void ) Callback; ( void ) Context; return 0; }
3121
+ mStatus mDNS_Register(mDNS *const m, AuthRecord *const rr) { ( void ) m; ( void ) rr; return 0; }
3122
+ mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping)
3123
+ { ( void ) m; ( void ) set; ( void ) flapping; return 0; }
3124
+ void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn) { ( void ) m; ( void ) fqdn; }
3125
+ void mDNS_SetFQDN(mDNS * const m) { ( void ) m; }
3126
+ void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const mDNSAddr *v6addr, const mDNSAddr *router)
3127
+ { ( void ) m; ( void ) v4addr; ( void ) v6addr; ( void ) router; }
3128
+ mStatus uDNS_SetupDNSConfig( mDNS *const m ) { ( void ) m; return 0; }
3129
+ mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
3130
+ const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port, const char *autoTunnelPrefix)
3131
+ { ( void ) m; ( void ) info; ( void ) domain; ( void ) keyname; ( void ) b64keydata; ( void ) hostname; (void) port; ( void ) autoTunnelPrefix; return 0; }
3132
+ mStatus mDNS_StopQuery(mDNS *const m, DNSQuestion *const question) { ( void ) m; ( void ) question; return 0; }
3133
+ void TriggerEventCompletion(void);
3134
+ void TriggerEventCompletion() {}
3135
+ mDNS mDNSStorage;
3136
+
3137
+
3138
+ // For convenience when using the "strings" command, this is the last thing in the file
3139
+ // The "@(#) " pattern is a special prefix the "what" command looks for
3140
+ const char mDNSResponderVersionString_SCCS[] = "@(#) dnsextd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
3141
+
3142
+ #if _BUILDING_XCODE_PROJECT_
3143
+ // If the process crashes, then this string will be magically included in the automatically-generated crash log
3144
+ const char *__crashreporter_info__ = mDNSResponderVersionString_SCCS + 5;
3145
+ asm(".desc ___crashreporter_info__, 0x10");
3146
+ #endif