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.

562 lines
18 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/mDNSPosix/PosixDaemon.c b/mDNSPosix/PosixDaemon.c
  12. index 88b3292..e86a6c7 100644
  13. --- a/mDNSPosix/PosixDaemon.c
  14. +++ b/mDNSPosix/PosixDaemon.c
  15. @@ -37,6 +37,11 @@
  16. #include <fcntl.h>
  17. #include <pwd.h>
  18. #include <sys/types.h>
  19. +#ifdef __linux__
  20. +#include <sys/capability.h> /* !!! We require libcap-dev for this. Oh well. */
  21. +/* prctl is required to enable inheriting of capabilities across setuid */
  22. +#include <sys/prctl.h>
  23. +#endif /* __linux__ */
  24. #if __APPLE__
  25. #undef daemon
  26. @@ -184,16 +189,50 @@ int main(int argc, char **argv)
  27. Reconfigure(&mDNSStorage);
  28. +#ifdef __linux__
  29. + /*
  30. + * SO_BINDTODEVICE is privileged operation; however, we can get
  31. + * around it using capabilities instead of remaining root.
  32. + */
  33. + if (mStatus_NoError == err)
  34. + {
  35. + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
  36. + perror("prctl PR_SET_KEEPCAPS");
  37. + }
  38. +#endif /* __linux__ */
  39. +
  40. // Now that we're finished with anything privileged, switch over to running as "nobody"
  41. if (mStatus_NoError == err)
  42. {
  43. const struct passwd *pw = getpwnam("nobody");
  44. if (pw != NULL)
  45. + {
  46. setuid(pw->pw_uid);
  47. +#ifdef __linux__
  48. + struct __user_cap_header_struct ch;
  49. + struct __user_cap_data_struct cd[_LINUX_CAPABILITY_U32S_3];
  50. +
  51. + memset(&ch, 0, sizeof(ch));
  52. + ch.version = _LINUX_CAPABILITY_VERSION_3;
  53. + ch.pid = getpid();
  54. + memset(&cd[0], 0, sizeof(cd));
  55. + /* CAP_NET_RAW is required to use SO_BINDTODEVICE */
  56. + int caps = CAP_TO_MASK(CAP_NET_RAW);
  57. + cd[0].permitted = caps;
  58. + cd[0].effective = caps;
  59. + if (capset(&ch, &cd[0]) < 0)
  60. + perror("capset");
  61. +#endif /* __linux__ */
  62. + }
  63. else
  64. LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
  65. }
  66. +#ifdef __linux__
  67. + if (mStatus_NoError == err)
  68. + err = mDNSPlatformPosixRefreshInterfaceList(&mDNSStorage);
  69. +#endif /* __linux__ */
  70. +
  71. if (mStatus_NoError == err)
  72. err = MainLoop(&mDNSStorage);
  73. diff --git a/mDNSPosix/Responder.c b/mDNSPosix/Responder.c
  74. index 3996b7b..e58d8eb 100755
  75. --- a/mDNSPosix/Responder.c
  76. +++ b/mDNSPosix/Responder.c
  77. @@ -603,7 +603,8 @@ static mStatus RegisterServicesInFile(const char *filePath)
  78. status = mStatus_UnknownErr;
  79. }
  80. - assert(0 == fclose(fp));
  81. + int rv = fclose(fp);
  82. + assert(0 == rv);
  83. return status;
  84. }
  85. diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c
  86. index 953bf64..4e481ea 100755
  87. --- a/mDNSPosix/mDNSPosix.c
  88. +++ b/mDNSPosix/mDNSPosix.c
  89. @@ -136,7 +136,7 @@ mDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipA
  90. // mDNS core calls this routine when it needs to send a packet.
  91. mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
  92. - mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
  93. + mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
  94. mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass)
  95. {
  96. int err = 0;
  97. @@ -574,9 +574,17 @@ mDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf)
  98. {
  99. assert(intf != NULL);
  100. if (intf->intfName != NULL) free((void *)intf->intfName);
  101. - if (intf->multicastSocket4 != -1) assert(close(intf->multicastSocket4) == 0);
  102. + if (intf->multicastSocket4 != -1)
  103. + {
  104. + int rv = close(intf->multicastSocket4);
  105. + assert(rv == 0);
  106. + }
  107. #if HAVE_IPV6
  108. - if (intf->multicastSocket6 != -1) assert(close(intf->multicastSocket6) == 0);
  109. + if (intf->multicastSocket6 != -1)
  110. + {
  111. + int rv = close(intf->multicastSocket6);
  112. + assert(rv == 0);
  113. + }
  114. #endif
  115. free(intf);
  116. }
  117. @@ -703,6 +711,29 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
  118. if (err < 0) { err = errno; perror("setsockopt - IP_MULTICAST_TTL"); }
  119. }
  120. +#ifdef __linux__
  121. +#ifdef SO_BINDTODEVICE
  122. + if (err == 0 && interfaceIndex)
  123. + {
  124. + char ifname[IFNAMSIZ];
  125. + if (if_indextoname(interfaceIndex, ifname))
  126. + {
  127. + err = setsockopt(*sktPtr, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
  128. + if (err < 0)
  129. + {
  130. + err = errno;
  131. + perror("setsockopt - SO_BINDTODEVICE");
  132. + }
  133. + }
  134. + else
  135. + {
  136. + err = errno;
  137. + perror("if_indextoname");
  138. + }
  139. + }
  140. +#endif /* SO_BINDTODEVICE */
  141. +#endif /* __linux__ */
  142. +
  143. // And start listening for packets
  144. if (err == 0)
  145. {
  146. @@ -784,6 +815,29 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
  147. if (err < 0) { err = errno; perror("setsockopt - IPV6_MULTICAST_HOPS"); }
  148. }
  149. +#ifdef __linux__
  150. +#ifdef SO_BINDTODEVICE
  151. + if (err == 0 && interfaceIndex)
  152. + {
  153. + char ifname[IFNAMSIZ];
  154. + if (if_indextoname(interfaceIndex, ifname))
  155. + {
  156. + err = setsockopt(*sktPtr, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
  157. + if (err < 0)
  158. + {
  159. + err = errno;
  160. + perror("setsockopt - SO_BINDTODEVICE");
  161. + }
  162. + }
  163. + else
  164. + {
  165. + err = errno;
  166. + perror("if_indextoname");
  167. + }
  168. + }
  169. +#endif /* SO_BINDTODEVICE */
  170. +#endif /* __linux__ */
  171. +
  172. // And start listening for packets
  173. if (err == 0)
  174. {
  175. @@ -815,7 +869,12 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
  176. }
  177. // Clean up
  178. - if (err != 0 && *sktPtr != -1) { assert(close(*sktPtr) == 0); *sktPtr = -1; }
  179. + if (err != 0 && *sktPtr != -1)
  180. + {
  181. + int rv = close(*sktPtr);
  182. + assert(rv == 0);
  183. + *sktPtr = -1;
  184. + }
  185. assert((err == 0) == (*sktPtr != -1));
  186. return err;
  187. }
  188. @@ -994,7 +1053,7 @@ mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
  189. /* Subscribe the socket to Link & IP addr notifications. */
  190. mDNSPlatformMemZero(&snl, sizeof snl);
  191. snl.nl_family = AF_NETLINK;
  192. - snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
  193. + snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
  194. ret = bind(sock, (struct sockaddr *) &snl, sizeof snl);
  195. if (0 == ret)
  196. *pFD = sock;
  197. @@ -1072,11 +1131,18 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd)
  198. PrintNetLinkMsg(pNLMsg);
  199. #endif
  200. + // this result isn't used anywhere as a number, just as
  201. + // non-zero - however, I have seen devices with more than 32
  202. + // interfaces at some point..
  203. + // (on Linux, every tunnel increases index for example)
  204. +
  205. // Process the NetLink message
  206. if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK)
  207. - result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
  208. + result |= 1;
  209. + // << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
  210. else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR)
  211. - result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
  212. + result |= 1;
  213. + // << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
  214. // Advance pNLMsg to the next message in the buffer
  215. if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE)
  216. @@ -1247,8 +1313,12 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
  217. if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket6);
  218. #endif
  219. + // In Linux case, we can't set up sockets with different owner -
  220. + // it blows up SO_REUSEPORT. So we do this step bit later.
  221. +#ifndef __linux__
  222. // Tell mDNS core about the network interfaces on this machine.
  223. if (err == mStatus_NoError) err = SetupInterfaceList(m);
  224. +#endif /* !__linux__ */
  225. // Tell mDNS core about DNS Servers
  226. mDNS_Lock(m);
  227. @@ -1281,9 +1351,17 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
  228. {
  229. assert(m != NULL);
  230. ClearInterfaceList(m);
  231. - if (m->p->unicastSocket4 != -1) assert(close(m->p->unicastSocket4) == 0);
  232. + if (m->p->unicastSocket4 != -1)
  233. + {
  234. + int rv = close(m->p->unicastSocket4);
  235. + assert(rv == 0);
  236. + }
  237. #if HAVE_IPV6
  238. - if (m->p->unicastSocket6 != -1) assert(close(m->p->unicastSocket6) == 0);
  239. + if (m->p->unicastSocket6 != -1)
  240. + {
  241. + int rv = close(m->p->unicastSocket6);
  242. + assert(rv == 0);
  243. + }
  244. #endif
  245. }
  246. @@ -1533,14 +1611,14 @@ mDNSexport mStatus mDNSPlatformClearSPSMACAddr(void)
  247. mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
  248. {
  249. (void) sock; // unused
  250. -
  251. +
  252. return (mDNSu16)-1;
  253. }
  254. mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
  255. {
  256. (void) InterfaceID; // unused
  257. -
  258. +
  259. return mDNSfalse;
  260. }
  261. diff --git a/mDNSPosix/mDNSUNP.c b/mDNSPosix/mDNSUNP.c
  262. index b392fc7..9f85e0e 100755
  263. --- a/mDNSPosix/mDNSUNP.c
  264. +++ b/mDNSPosix/mDNSUNP.c
  265. @@ -61,154 +61,86 @@
  266. #endif
  267. #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
  268. -#include <netdb.h>
  269. -#include <arpa/inet.h>
  270. -
  271. -/* Converts a prefix length to IPv6 network mask */
  272. -void plen_to_mask(int plen, char *addr) {
  273. - int i;
  274. - int colons=7; /* Number of colons in IPv6 address */
  275. - int bits_in_block=16; /* Bits per IPv6 block */
  276. - for(i=0; i<=colons; i++) {
  277. - int block, ones=0xffff, ones_in_block;
  278. - if (plen>bits_in_block) ones_in_block=bits_in_block;
  279. - else ones_in_block=plen;
  280. - block = ones & (ones << (bits_in_block-ones_in_block));
  281. - i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
  282. - plen -= ones_in_block;
  283. - }
  284. -}
  285. +#include <sys/types.h>
  286. +#include <ifaddrs.h>
  287. +
  288. -/* Gets IPv6 interface information from the /proc filesystem in linux*/
  289. -struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
  290. +/* Correct way to deal with this is just to use getifaddrs (glibc
  291. + * 2.3.3+ and various BSDs, but BSDs are 'slightly different' just to
  292. + * make life interesting). We assume Linux getifaddrs is available,
  293. + * and if not, please upgrade. */
  294. +struct ifi_info *get_ifi_info_linuxv6(int doaliases)
  295. {
  296. - struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
  297. - FILE *fp;
  298. - char addr[8][5];
  299. - int flags, myflags, index, plen, scope;
  300. - char ifname[9], lastname[IFNAMSIZ];
  301. - char addr6[32+7+1]; /* don't forget the seven ':' */
  302. - struct addrinfo hints, *res0;
  303. - struct sockaddr_in6 *sin6;
  304. - struct in6_addr *addrptr;
  305. - int err;
  306. - int sockfd = -1;
  307. - struct ifreq ifr;
  308. -
  309. - res0=NULL;
  310. - ifihead = NULL;
  311. - ifipnext = &ifihead;
  312. - lastname[0] = 0;
  313. + struct ifaddrs *ifap, *ifa;
  314. + struct ifi_info *ifi = NULL, *head = NULL;
  315. - if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
  316. - sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
  317. - if (sockfd < 0) {
  318. - goto gotError;
  319. + /* doaliases seems always true in the calls in current code */
  320. + assert(doaliases);
  321. +
  322. + if (getifaddrs(&ifap) < 0)
  323. + {
  324. + return NULL;
  325. + }
  326. + for (ifa = ifap ; ifa ; ifa = ifa->ifa_next)
  327. + {
  328. + /* Care only about IPv6 addresses on non-point-to-point links. */
  329. + if (!ifa->ifa_addr
  330. + || ifa->ifa_addr->sa_family != AF_INET6)
  331. + continue;
  332. + ifi = calloc(1, sizeof(*ifi));
  333. + if (!ifi)
  334. + break;
  335. + strncpy(ifi->ifi_name, ifa->ifa_name, IFI_NAME);
  336. + /* We ignore ifi_{haddr,hlen}, everyone else does too */
  337. + ifi->ifi_flags = ifa->ifa_flags;
  338. + /* We ignore ifi_myflags; IFI_ALIAS isn't used anywhere */
  339. + ifi->ifi_index = if_nametoindex(ifa->ifa_name);
  340. + if (!(ifi->ifi_addr = malloc(sizeof(struct sockaddr_in6))))
  341. + break;
  342. + memcpy(ifi->ifi_addr, ifa->ifa_addr, sizeof(struct sockaddr_in6));
  343. +
  344. + if (ifa->ifa_netmask)
  345. + {
  346. + if (!(ifi->ifi_netmask = malloc(sizeof(struct sockaddr_in6))))
  347. + break;
  348. + memcpy(ifi->ifi_netmask, ifa->ifa_netmask,
  349. + sizeof(struct sockaddr_in6));
  350. }
  351. - while (fscanf(fp,
  352. - "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
  353. - addr[0],addr[1],addr[2],addr[3],
  354. - addr[4],addr[5],addr[6],addr[7],
  355. - &index, &plen, &scope, &flags, ifname) != EOF) {
  356. -
  357. - myflags = 0;
  358. - if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
  359. - if (doaliases == 0)
  360. - continue; /* already processed this interface */
  361. - myflags = IFI_ALIAS;
  362. - }
  363. - memcpy(lastname, ifname, IFNAMSIZ);
  364. - ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
  365. - if (ifi == NULL) {
  366. - goto gotError;
  367. - }
  368. - ifipold = *ifipnext; /* need this later */
  369. - ifiptr = ifipnext;
  370. - *ifipnext = ifi; /* prev points to this new one */
  371. - ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
  372. -
  373. - sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
  374. - addr[0],addr[1],addr[2],addr[3],
  375. - addr[4],addr[5],addr[6],addr[7]);
  376. -
  377. - /* Add address of the interface */
  378. - memset(&hints, 0, sizeof(hints));
  379. - hints.ai_family = AF_INET6;
  380. - hints.ai_flags = AI_NUMERICHOST;
  381. - err = getaddrinfo(addr6, NULL, &hints, &res0);
  382. - if (err) {
  383. - goto gotError;
  384. - }
  385. - ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
  386. - if (ifi->ifi_addr == NULL) {
  387. - goto gotError;
  388. - }
  389. - memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
  390. + if (!(ifi->ifi_addr = malloc(sizeof(struct sockaddr_in6))))
  391. + break;
  392. + memcpy(ifi->ifi_addr, ifa->ifa_addr, sizeof(struct sockaddr_in6));
  393. - /* Add netmask of the interface */
  394. - char ipv6addr[INET6_ADDRSTRLEN];
  395. - plen_to_mask(plen, ipv6addr);
  396. - ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
  397. - if (ifi->ifi_addr == NULL) {
  398. - goto gotError;
  399. - }
  400. - sin6=calloc(1, sizeof(struct sockaddr_in6));
  401. - addrptr=calloc(1, sizeof(struct in6_addr));
  402. - inet_pton(family, ipv6addr, addrptr);
  403. - sin6->sin6_family=family;
  404. - sin6->sin6_addr=*addrptr;
  405. - sin6->sin6_scope_id=scope;
  406. - memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6));
  407. - free(sin6);
  408. -
  409. -
  410. - /* Add interface name */
  411. - memcpy(ifi->ifi_name, ifname, IFI_NAME);
  412. -
  413. - /* Add interface index */
  414. - ifi->ifi_index = index;
  415. -
  416. - /* Add interface flags*/
  417. - memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  418. - if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
  419. - if (errno == EADDRNOTAVAIL) {
  420. - /*
  421. - * If the main interface is configured with no IP address but
  422. - * an alias interface exists with an IP address, you get
  423. - * EADDRNOTAVAIL for the main interface
  424. - */
  425. - free(ifi->ifi_addr);
  426. - free(ifi);
  427. - ifipnext = ifiptr;
  428. - *ifipnext = ifipold;
  429. - continue;
  430. - } else {
  431. - goto gotError;
  432. - }
  433. - }
  434. - ifi->ifi_flags = ifr.ifr_flags;
  435. - freeaddrinfo(res0);
  436. - res0=NULL;
  437. - }
  438. - }
  439. - goto done;
  440. -gotError:
  441. - if (ifihead != NULL) {
  442. - free_ifi_info(ifihead);
  443. - ifihead = NULL;
  444. - }
  445. - if (res0 != NULL) {
  446. - freeaddrinfo(res0);
  447. - res0=NULL;
  448. - }
  449. -done:
  450. - if (sockfd != -1) {
  451. - assert(close(sockfd) == 0);
  452. + if (ifa->ifa_flags & IFF_POINTOPOINT && ifa->ifa_dstaddr)
  453. + {
  454. + if (!(ifi->ifi_dstaddr = malloc(sizeof(struct sockaddr_in6))))
  455. + break;
  456. + memcpy(ifi->ifi_dstaddr, ifa->ifa_dstaddr,
  457. + sizeof(struct sockaddr_in6));
  458. + }
  459. + else if (ifa->ifa_broadaddr)
  460. + {
  461. + if (!(ifi->ifi_brdaddr = malloc(sizeof(struct sockaddr_in6))))
  462. + break;
  463. + memcpy(ifi->ifi_brdaddr, ifa->ifa_broadaddr,
  464. + sizeof(struct sockaddr_in6));
  465. + }
  466. + ifi->ifi_next = head;
  467. + head = ifi;
  468. + ifi = NULL;
  469. + };
  470. + if (ifi)
  471. + {
  472. + /* An error occurred. Let's bail out. */
  473. + ifi->ifi_next = head;
  474. + free_ifi_info(head);
  475. + return NULL;
  476. }
  477. - return(ifihead); /* pointer to first structure in linked list */
  478. + freeifaddrs(ifap);
  479. + return head;
  480. }
  481. +
  482. #endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
  483. struct ifi_info *get_ifi_info(int family, int doaliases)
  484. @@ -229,7 +161,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
  485. #endif
  486. #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
  487. - if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
  488. + if (family == AF_INET6) return get_ifi_info_linuxv6(doaliases);
  489. #endif
  490. sockfd = -1;
  491. diff --git a/mDNSPosix/mDNSUNP.h b/mDNSPosix/mDNSUNP.h
  492. index cc81b7d..e710087 100755
  493. --- a/mDNSPosix/mDNSUNP.h
  494. +++ b/mDNSPosix/mDNSUNP.h
  495. @@ -97,8 +97,7 @@ struct ifi_info {
  496. };
  497. #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
  498. -#define PROC_IFINET6_PATH "/proc/net/if_inet6"
  499. -extern struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases);
  500. +extern struct ifi_info *get_ifi_info_linuxv6(int doaliases);
  501. #endif
  502. #if defined(AF_INET6) && HAVE_IPV6
  503. diff --git a/mDNSShared/dnsextd_parser.y b/mDNSShared/dnsextd_parser.y
  504. index 18c5990..d4b63ce 100644
  505. --- a/mDNSShared/dnsextd_parser.y
  506. +++ b/mDNSShared/dnsextd_parser.y
  507. @@ -15,6 +15,8 @@
  508. * limitations under the License.
  509. */
  510. +%parse-param { void *context }
  511. +
  512. %{
  513. #include <stdio.h>
  514. #include <stdlib.h>
  515. @@ -23,7 +25,7 @@
  516. #include "DebugServices.h"
  517. #include "dnsextd.h"
  518. -void yyerror( const char* error );
  519. +void yyerror( void *context, const char* error );
  520. int yylex(void);
  521. @@ -378,7 +380,7 @@ int yywrap(void);
  522. extern int yylineno;
  523. -void yyerror( const char *str )
  524. +void yyerror( void *context, const char *str )
  525. {
  526. fprintf( stderr,"%s:%d: error: %s\n", g_filename, yylineno, str );
  527. }