ssize_t Recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp, SA *sa, socklen_t *salenptr, void *dstaddrp) { ssize_t n; n = recvfrom_flags(fd, ptr, nbytes, flagsp, sa, salenptr, dstaddrp); if (n < 0) err_quit("recvfrom_flags error"); return(n); }
// This routine is called when the main loop detects that data is available on a socket. static void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int skt) { mDNSAddr senderAddr, destAddr; mDNSIPPort senderPort; ssize_t packetLen; DNSMessage packet; struct my_in_pktinfo packetInfo; struct sockaddr_storage from; socklen_t fromLen; int flags; mDNSBool reject; assert(m != NULL); assert(intf != NULL); assert(skt >= 0); fromLen = sizeof(from); flags = 0; packetLen = recvfrom_flags(skt, &packet, sizeof(packet), &flags, (struct sockaddr *) &from, &fromLen, &packetInfo); if (packetLen >= 0) { SockAddrTomDNSAddr((struct sockaddr*)&from, &senderAddr, &senderPort); SockAddrTomDNSAddr((struct sockaddr*)&packetInfo.ipi_addr, &destAddr, NULL); // If we have broken IP_RECVDSTADDR functionality (so far // I've only seen this on OpenBSD) then apply a hack to // convince mDNS Core that this isn't a spoof packet. // Basically what we do is check to see whether the // packet arrived as a multicast and, if so, set its // destAddr to the mDNS address. // // I must admit that I could just be doing something // wrong on OpenBSD and hence triggering this problem // but I'm at a loss as to how. // // If this platform doesn't have IP_PKTINFO or IP_RECVDSTADDR, then we have // no way to tell the destination address or interface this packet arrived on, // so all we can do is just assume it's a multicast #if HAVE_BROKEN_RECVDSTADDR || (!defined(IP_PKTINFO) && !defined(IP_RECVDSTADDR)) if ( (destAddr.NotAnInteger == 0) && (flags & MSG_MCAST) ) { destAddr.type == senderAddr.type; if (senderAddr.type == mDNSAddrType_IPv4) destAddr.ip.v4 = AllDNSLinkGroup; else if (senderAddr.type == mDNSAddrType_IPv6) destAddr.ip.v6 = AllDNSLinkGroupv6; } #endif // We only accept the packet if the interface on which it came // in matches the interface associated with this socket. // We do this match by name or by index, depending on which // information is available. recvfrom_flags sets the name // to "" if the name isn't available, or the index to -1 // if the index is available. This accomodates the various // different capabilities of our target platforms. reject = mDNSfalse; if ( packetInfo.ipi_ifname[0] != 0 ) reject = (strcmp(packetInfo.ipi_ifname, intf->intfName) != 0); else if ( packetInfo.ipi_ifindex != -1 ) reject = (packetInfo.ipi_ifindex != intf->index); if (reject) { verbosedebugf("SocketDataReady ignored a packet from %#a to %#a on interface %s/%d expecting %#a/%s/%d", &senderAddr, &destAddr, packetInfo.ipi_ifname, packetInfo.ipi_ifindex, &intf->coreIntf.ip, intf->intfName, intf->index); packetLen = -1; num_pkts_rejected++; if (num_pkts_rejected > (num_pkts_accepted + 1) * (num_registered_interfaces + 1) * 2) { fprintf(stderr, "*** WARNING: Received %d packets; Accepted %d packets; Rejected %d packets because of interface mismatch\n", num_pkts_accepted + num_pkts_rejected, num_pkts_accepted, num_pkts_rejected); num_pkts_accepted = 0; num_pkts_rejected = 0; } } else { verbosedebugf("SocketDataReady got a packet from %#a to %#a on interface %#a/%s/%d", &senderAddr, &destAddr, &intf->coreIntf.ip, intf->intfName, intf->index); num_pkts_accepted++; } } if (packetLen >= 0 && packetLen < (ssize_t)sizeof(DNSMessageHeader)) { debugf("SocketDataReady packet length (%d) too short", packetLen); packetLen = -1; } if (packetLen >= 0) mDNSCoreReceive(m, &packet, (mDNSu8 *)&packet + packetLen, &senderAddr, senderPort, &destAddr, MulticastDNSPort, intf->coreIntf.InterfaceID, 255); }