You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

403 lines
13 KiB

  1. diff --git a/.gitignore b/.gitignore
  2. new file mode 100644
  3. index 0000000..920cdfc
  4. --- /dev/null
  5. +++ b/.gitignore
  6. @@ -0,0 +1,4 @@
  7. +Clients/build
  8. +mDNSPosix/build
  9. +mDNSPosix/objects
  10. +
  11. diff --git a/Clients/Makefile b/Clients/Makefile
  12. index 383af31..925c20e 100755
  13. --- a/Clients/Makefile
  14. +++ b/Clients/Makefile
  15. @@ -34,7 +34,7 @@ TARGETS = build/dns-sd build/dns-sd64
  16. LIBS =
  17. else
  18. TARGETS = build/dns-sd
  19. -LIBS = -L../mDNSPosix/build/prod/ -ldns_sd
  20. +LIBS ?= -L../mDNSPosix/build/prod/ -ldns_sd
  21. endif
  22. all: $(TARGETS)
  23. diff --git a/mDNSPosix/PosixDaemon.c b/mDNSPosix/PosixDaemon.c
  24. index 88b3292..e86a6c7 100644
  25. --- a/mDNSPosix/PosixDaemon.c
  26. +++ b/mDNSPosix/PosixDaemon.c
  27. @@ -37,6 +37,11 @@
  28. #include <fcntl.h>
  29. #include <pwd.h>
  30. #include <sys/types.h>
  31. +#ifdef __linux__
  32. +#include <sys/capability.h> /* !!! We require libcap-dev for this. Oh well. */
  33. +/* prctl is required to enable inheriting of capabilities across setuid */
  34. +#include <sys/prctl.h>
  35. +#endif /* __linux__ */
  36. #if __APPLE__
  37. #undef daemon
  38. @@ -184,16 +189,50 @@ int main(int argc, char **argv)
  39. Reconfigure(&mDNSStorage);
  40. +#ifdef __linux__
  41. + /*
  42. + * SO_BINDTODEVICE is privileged operation; however, we can get
  43. + * around it using capabilities instead of remaining root.
  44. + */
  45. + if (mStatus_NoError == err)
  46. + {
  47. + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
  48. + perror("prctl PR_SET_KEEPCAPS");
  49. + }
  50. +#endif /* __linux__ */
  51. +
  52. // Now that we're finished with anything privileged, switch over to running as "nobody"
  53. if (mStatus_NoError == err)
  54. {
  55. const struct passwd *pw = getpwnam("nobody");
  56. if (pw != NULL)
  57. + {
  58. setuid(pw->pw_uid);
  59. +#ifdef __linux__
  60. + struct __user_cap_header_struct ch;
  61. + struct __user_cap_data_struct cd[_LINUX_CAPABILITY_U32S_3];
  62. +
  63. + memset(&ch, 0, sizeof(ch));
  64. + ch.version = _LINUX_CAPABILITY_VERSION_3;
  65. + ch.pid = getpid();
  66. + memset(&cd[0], 0, sizeof(cd));
  67. + /* CAP_NET_RAW is required to use SO_BINDTODEVICE */
  68. + int caps = CAP_TO_MASK(CAP_NET_RAW);
  69. + cd[0].permitted = caps;
  70. + cd[0].effective = caps;
  71. + if (capset(&ch, &cd[0]) < 0)
  72. + perror("capset");
  73. +#endif /* __linux__ */
  74. + }
  75. else
  76. LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
  77. }
  78. +#ifdef __linux__
  79. + if (mStatus_NoError == err)
  80. + err = mDNSPlatformPosixRefreshInterfaceList(&mDNSStorage);
  81. +#endif /* __linux__ */
  82. +
  83. if (mStatus_NoError == err)
  84. err = MainLoop(&mDNSStorage);
  85. diff --git a/mDNSPosix/Responder.c b/mDNSPosix/Responder.c
  86. index 3996b7b..e58d8eb 100755
  87. --- a/mDNSPosix/Responder.c
  88. +++ b/mDNSPosix/Responder.c
  89. @@ -603,7 +603,8 @@ static mStatus RegisterServicesInFile(const char *filePath)
  90. status = mStatus_UnknownErr;
  91. }
  92. - assert(0 == fclose(fp));
  93. + int rv = fclose(fp);
  94. + assert(0 == rv);
  95. return status;
  96. }
  97. diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c
  98. index 6effa12..7c1d6eb 100755
  99. --- a/mDNSPosix/mDNSPosix.c
  100. +++ b/mDNSPosix/mDNSPosix.c
  101. @@ -138,7 +138,7 @@ mDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipA
  102. // mDNS core calls this routine when it needs to send a packet.
  103. mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
  104. - mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
  105. + mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
  106. mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass)
  107. {
  108. int err = 0;
  109. @@ -583,9 +583,17 @@ mDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf)
  110. {
  111. assert(intf != NULL);
  112. if (intf->intfName != NULL) free((void *)intf->intfName);
  113. - if (intf->multicastSocket4 != -1) assert(close(intf->multicastSocket4) == 0);
  114. + if (intf->multicastSocket4 != -1)
  115. + {
  116. + int rv = close(intf->multicastSocket4);
  117. + assert(rv == 0);
  118. + }
  119. #if HAVE_IPV6
  120. - if (intf->multicastSocket6 != -1) assert(close(intf->multicastSocket6) == 0);
  121. + if (intf->multicastSocket6 != -1)
  122. + {
  123. + int rv = close(intf->multicastSocket6);
  124. + assert(rv == 0);
  125. + }
  126. #endif
  127. // Move interface to the RecentInterfaces list for a minute
  128. @@ -724,6 +732,29 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
  129. if (err < 0) { err = errno; perror("setsockopt - IP_MULTICAST_TTL"); }
  130. }
  131. +#ifdef __linux__
  132. +#ifdef SO_BINDTODEVICE
  133. + if (err == 0 && interfaceIndex)
  134. + {
  135. + char ifname[IFNAMSIZ];
  136. + if (if_indextoname(interfaceIndex, ifname))
  137. + {
  138. + err = setsockopt(*sktPtr, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
  139. + if (err < 0)
  140. + {
  141. + err = errno;
  142. + perror("setsockopt - SO_BINDTODEVICE");
  143. + }
  144. + }
  145. + else
  146. + {
  147. + err = errno;
  148. + perror("if_indextoname");
  149. + }
  150. + }
  151. +#endif /* SO_BINDTODEVICE */
  152. +#endif /* __linux__ */
  153. +
  154. // And start listening for packets
  155. if (err == 0)
  156. {
  157. @@ -805,6 +836,29 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
  158. if (err < 0) { err = errno; perror("setsockopt - IPV6_MULTICAST_HOPS"); }
  159. }
  160. +#ifdef __linux__
  161. +#ifdef SO_BINDTODEVICE
  162. + if (err == 0 && interfaceIndex)
  163. + {
  164. + char ifname[IFNAMSIZ];
  165. + if (if_indextoname(interfaceIndex, ifname))
  166. + {
  167. + err = setsockopt(*sktPtr, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
  168. + if (err < 0)
  169. + {
  170. + err = errno;
  171. + perror("setsockopt - SO_BINDTODEVICE");
  172. + }
  173. + }
  174. + else
  175. + {
  176. + err = errno;
  177. + perror("if_indextoname");
  178. + }
  179. + }
  180. +#endif /* SO_BINDTODEVICE */
  181. +#endif /* __linux__ */
  182. +
  183. // And start listening for packets
  184. if (err == 0)
  185. {
  186. @@ -836,7 +890,12 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
  187. }
  188. // Clean up
  189. - if (err != 0 && *sktPtr != -1) { assert(close(*sktPtr) == 0); *sktPtr = -1; }
  190. + if (err != 0 && *sktPtr != -1)
  191. + {
  192. + int rv = close(*sktPtr);
  193. + assert(rv == 0);
  194. + *sktPtr = -1;
  195. + }
  196. assert((err == 0) == (*sktPtr != -1));
  197. return err;
  198. }
  199. @@ -938,19 +997,14 @@ mDNSlocal int SetupInterfaceList(mDNS *const m)
  200. int err = 0;
  201. struct ifi_info *intfList = get_ifi_info(AF_INET, mDNStrue);
  202. struct ifi_info *firstLoopback = NULL;
  203. + struct ifi_info **p = &intfList;
  204. assert(m != NULL);
  205. debugf("SetupInterfaceList");
  206. - if (intfList == NULL) err = ENOENT;
  207. -
  208. #if HAVE_IPV6
  209. - if (err == 0) /* Link the IPv6 list to the end of the IPv4 list */
  210. - {
  211. - struct ifi_info **p = &intfList;
  212. - while (*p) p = &(*p)->ifi_next;
  213. - *p = get_ifi_info(AF_INET6, mDNStrue);
  214. - }
  215. + while (*p) p = &(*p)->ifi_next;
  216. + *p = get_ifi_info(AF_INET6, mDNStrue);
  217. #endif
  218. if (err == 0)
  219. @@ -1026,7 +1080,7 @@ mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
  220. /* Subscribe the socket to Link & IP addr notifications. */
  221. mDNSPlatformMemZero(&snl, sizeof snl);
  222. snl.nl_family = AF_NETLINK;
  223. - snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
  224. + snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
  225. ret = bind(sock, (struct sockaddr *) &snl, sizeof snl);
  226. if (0 == ret)
  227. *pFD = sock;
  228. @@ -1104,11 +1158,18 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd)
  229. PrintNetLinkMsg(pNLMsg);
  230. #endif
  231. + // this result isn't used anywhere as a number, just as
  232. + // non-zero - however, I have seen devices with more than 32
  233. + // interfaces at some point..
  234. + // (on Linux, every tunnel increases index for example)
  235. +
  236. // Process the NetLink message
  237. if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK)
  238. - result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
  239. + result |= 1;
  240. + // << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
  241. else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR)
  242. - result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
  243. + result |= 1;
  244. + // << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
  245. // Advance pNLMsg to the next message in the buffer
  246. if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE)
  247. @@ -1279,8 +1340,12 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
  248. if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket6);
  249. #endif
  250. + // In Linux case, we can't set up sockets with different owner -
  251. + // it blows up SO_REUSEPORT. So we do this step bit later.
  252. +#ifndef __linux__
  253. // Tell mDNS core about the network interfaces on this machine.
  254. if (err == mStatus_NoError) err = SetupInterfaceList(m);
  255. +#endif /* !__linux__ */
  256. // Tell mDNS core about DNS Servers
  257. mDNS_Lock(m);
  258. @@ -1313,9 +1378,17 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
  259. {
  260. assert(m != NULL);
  261. ClearInterfaceList(m);
  262. - if (m->p->unicastSocket4 != -1) assert(close(m->p->unicastSocket4) == 0);
  263. + if (m->p->unicastSocket4 != -1)
  264. + {
  265. + int rv = close(m->p->unicastSocket4);
  266. + assert(rv == 0);
  267. + }
  268. #if HAVE_IPV6
  269. - if (m->p->unicastSocket6 != -1) assert(close(m->p->unicastSocket6) == 0);
  270. + if (m->p->unicastSocket6 != -1)
  271. + {
  272. + int rv = close(m->p->unicastSocket6);
  273. + assert(rv == 0);
  274. + }
  275. #endif
  276. }
  277. @@ -1571,14 +1644,14 @@ mDNSexport mStatus mDNSPlatformClearSPSMACAddr(void)
  278. mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
  279. {
  280. (void) sock; // unused
  281. -
  282. +
  283. return (mDNSu16)-1;
  284. }
  285. mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
  286. {
  287. (void) InterfaceID; // unused
  288. -
  289. +
  290. return mDNSfalse;
  291. }
  292. diff --git a/mDNSPosix/mDNSUNP.c b/mDNSPosix/mDNSUNP.c
  293. index b392fc7..f551ad5 100755
  294. --- a/mDNSPosix/mDNSUNP.c
  295. +++ b/mDNSPosix/mDNSUNP.c
  296. @@ -63,6 +63,7 @@
  297. #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
  298. #include <netdb.h>
  299. #include <arpa/inet.h>
  300. +#include <linux/if_addr.h>
  301. /* Converts a prefix length to IPv6 network mask */
  302. void plen_to_mask(int plen, char *addr) {
  303. @@ -86,7 +87,7 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
  304. FILE *fp;
  305. char addr[8][5];
  306. int flags, myflags, index, plen, scope;
  307. - char ifname[9], lastname[IFNAMSIZ];
  308. + char ifname[IFNAMSIZ], lastname[IFNAMSIZ];
  309. char addr6[32+7+1]; /* don't forget the seven ':' */
  310. struct addrinfo hints, *res0;
  311. struct sockaddr_in6 *sin6;
  312. @@ -94,7 +95,8 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
  313. int err;
  314. int sockfd = -1;
  315. struct ifreq ifr;
  316. -
  317. + char mask[64] = "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %";
  318. + sprintf(mask+strlen(mask), "%ds\n", IFNAMSIZ);
  319. res0=NULL;
  320. ifihead = NULL;
  321. ifipnext = &ifihead;
  322. @@ -106,11 +108,12 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
  323. goto gotError;
  324. }
  325. while (fscanf(fp,
  326. - "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
  327. + mask,
  328. addr[0],addr[1],addr[2],addr[3],
  329. addr[4],addr[5],addr[6],addr[7],
  330. &index, &plen, &scope, &flags, ifname) != EOF) {
  331. + if (flags & IFA_F_DEPRECATED) continue;
  332. myflags = 0;
  333. if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
  334. if (doaliases == 0)
  335. @@ -204,8 +207,11 @@ gotError:
  336. res0=NULL;
  337. }
  338. done:
  339. + if (fp)
  340. + fclose(fp);
  341. if (sockfd != -1) {
  342. - assert(close(sockfd) == 0);
  343. + int rv = close(sockfd);
  344. + assert(rv == 0);
  345. }
  346. return(ifihead); /* pointer to first structure in linked list */
  347. }
  348. diff --git a/mDNSShared/dnsextd_parser.y b/mDNSShared/dnsextd_parser.y
  349. index 18c5990..d4b63ce 100644
  350. --- a/mDNSShared/dnsextd_parser.y
  351. +++ b/mDNSShared/dnsextd_parser.y
  352. @@ -15,6 +15,8 @@
  353. * limitations under the License.
  354. */
  355. +%parse-param { void *context }
  356. +
  357. %{
  358. #include <stdio.h>
  359. #include <stdlib.h>
  360. @@ -23,7 +25,7 @@
  361. #include "DebugServices.h"
  362. #include "dnsextd.h"
  363. -void yyerror( const char* error );
  364. +void yyerror( void *context, const char* error );
  365. int yylex(void);
  366. @@ -378,7 +380,7 @@ int yywrap(void);
  367. extern int yylineno;
  368. -void yyerror( const char *str )
  369. +void yyerror( void *context, const char *str )
  370. {
  371. fprintf( stderr,"%s:%d: error: %s\n", g_filename, yylineno, str );
  372. }