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