forked from qt-creator/qt-creator
Don't build mdnssd
This was enabled for Linux only, but Linux users should use Avahi, which is present on most modern distributions, and implements mDNS functionality. Change-Id: Ibb9d16c9fbd5c2571b98e1450276459d18eb65df Reviewed-by: Tobias Hunger <tobias.hunger@nokia.com> Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com>
This commit is contained in:
committed by
Fawzi Mohamed
parent
202ce8ad70
commit
272e9a37f3
@@ -73,7 +73,6 @@ Project {
|
||||
"src/plugins/valgrind/valgrind.qbs",
|
||||
"src/plugins/vcsbase/vcsbase.qbs",
|
||||
"src/plugins/welcome/welcome.qbs",
|
||||
"src/tools/mdnssd/mdnssd.qbs",
|
||||
"src/tools/qtcdebugger/qtcdebugger.qbs",
|
||||
"src/tools/qtpromaker/qtpromaker.qbs"
|
||||
]
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,292 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __DNSCOMMON_H_
|
||||
#define __DNSCOMMON_H_
|
||||
|
||||
#include "mDNSEmbeddedAPI.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//*************************************************************************************************************
|
||||
// Macros
|
||||
|
||||
// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
|
||||
// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
|
||||
// To expand "version" to its value before making the string, use STRINGIFY(version) instead
|
||||
#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) #s
|
||||
#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
|
||||
|
||||
// ***************************************************************************
|
||||
#if COMPILER_LIKES_PRAGMA_MARK
|
||||
#pragma mark - DNS Protocol Constants
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kDNSFlag0_QR_Mask = 0x80, // Query or response?
|
||||
kDNSFlag0_QR_Query = 0x00,
|
||||
kDNSFlag0_QR_Response = 0x80,
|
||||
|
||||
kDNSFlag0_OP_Mask = 0x78, // Operation type
|
||||
kDNSFlag0_OP_StdQuery = 0x00,
|
||||
kDNSFlag0_OP_Iquery = 0x08,
|
||||
kDNSFlag0_OP_Status = 0x10,
|
||||
kDNSFlag0_OP_Unused3 = 0x18,
|
||||
kDNSFlag0_OP_Notify = 0x20,
|
||||
kDNSFlag0_OP_Update = 0x28,
|
||||
|
||||
kDNSFlag0_QROP_Mask = kDNSFlag0_QR_Mask | kDNSFlag0_OP_Mask,
|
||||
|
||||
kDNSFlag0_AA = 0x04, // Authoritative Answer?
|
||||
kDNSFlag0_TC = 0x02, // Truncated?
|
||||
kDNSFlag0_RD = 0x01, // Recursion Desired?
|
||||
kDNSFlag1_RA = 0x80, // Recursion Available?
|
||||
|
||||
kDNSFlag1_Zero = 0x40, // Reserved; must be zero
|
||||
kDNSFlag1_AD = 0x20, // Authentic Data [RFC 2535]
|
||||
kDNSFlag1_CD = 0x10, // Checking Disabled [RFC 2535]
|
||||
|
||||
kDNSFlag1_RC_Mask = 0x0F, // Response code
|
||||
kDNSFlag1_RC_NoErr = 0x00,
|
||||
kDNSFlag1_RC_FormErr = 0x01,
|
||||
kDNSFlag1_RC_ServFail = 0x02,
|
||||
kDNSFlag1_RC_NXDomain = 0x03,
|
||||
kDNSFlag1_RC_NotImpl = 0x04,
|
||||
kDNSFlag1_RC_Refused = 0x05,
|
||||
kDNSFlag1_RC_YXDomain = 0x06,
|
||||
kDNSFlag1_RC_YXRRSet = 0x07,
|
||||
kDNSFlag1_RC_NXRRSet = 0x08,
|
||||
kDNSFlag1_RC_NotAuth = 0x09,
|
||||
kDNSFlag1_RC_NotZone = 0x0A
|
||||
} DNS_Flags;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TSIG_ErrBadSig = 16,
|
||||
TSIG_ErrBadKey = 17,
|
||||
TSIG_ErrBadTime = 18
|
||||
} TSIG_ErrorCode;
|
||||
|
||||
// ***************************************************************************
|
||||
#if COMPILER_LIKES_PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#pragma mark - General Utility Functions
|
||||
#endif
|
||||
|
||||
extern NetworkInterfaceInfo *GetFirstActiveInterface(NetworkInterfaceInfo *intf);
|
||||
extern mDNSInterfaceID GetNextActiveInterfaceID(const NetworkInterfaceInfo *intf);
|
||||
|
||||
extern mDNSu32 mDNSRandom(mDNSu32 max); // Returns pseudo-random result from zero to max inclusive
|
||||
|
||||
// ***************************************************************************
|
||||
#if COMPILER_LIKES_PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#pragma mark - Domain Name Utility Functions
|
||||
#endif
|
||||
|
||||
#define mDNSIsDigit(X) ((X) >= '0' && (X) <= '9')
|
||||
#define mDNSIsUpperCase(X) ((X) >= 'A' && (X) <= 'Z')
|
||||
#define mDNSIsLowerCase(X) ((X) >= 'a' && (X) <= 'z')
|
||||
#define mDNSIsLetter(X) (mDNSIsUpperCase(X) || mDNSIsLowerCase(X))
|
||||
|
||||
#define mDNSValidHostChar(X, notfirst, notlast) (mDNSIsLetter(X) || mDNSIsDigit(X) || ((notfirst) && (notlast) && (X) == '-') )
|
||||
|
||||
extern mDNSu16 CompressedDomainNameLength(const domainname *const name, const domainname *parent);
|
||||
extern int CountLabels(const domainname *d);
|
||||
extern const domainname *SkipLeadingLabels(const domainname *d, int skip);
|
||||
|
||||
extern mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max);
|
||||
extern mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText);
|
||||
extern mDNSu32 RemoveLabelSuffix(domainlabel *name, mDNSBool RichText);
|
||||
extern void AppendLabelSuffix(domainlabel *const name, mDNSu32 val, const mDNSBool RichText);
|
||||
#define ValidateDomainName(N) (DomainNameLength(N) <= MAX_DOMAIN_NAME)
|
||||
|
||||
// ***************************************************************************
|
||||
#if COMPILER_LIKES_PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#pragma mark - Resource Record Utility Functions
|
||||
#endif
|
||||
|
||||
// IdenticalResourceRecord returns true if two resources records have
|
||||
// the same name, type, class, and identical rdata (InterfaceID and TTL may differ)
|
||||
|
||||
// IdenticalSameNameRecord is the same, except it skips the expensive SameDomainName() check,
|
||||
// which is at its most expensive and least useful in cases where we know in advance that the names match
|
||||
|
||||
// Note: The dominant use of IdenticalResourceRecord is from ProcessQuery(), handling known-answer lists. In this case
|
||||
// it's common to have a whole bunch or records with exactly the same name (e.g. "_http._tcp.local") but different RDATA.
|
||||
// The SameDomainName() check is expensive when the names match, and in this case *all* the names match, so we
|
||||
// used to waste a lot of CPU time verifying that the names match, only then to find that the RDATA is different.
|
||||
// We observed mDNSResponder spending 30% of its total CPU time on this single task alone.
|
||||
// By swapping the checks so that we check the RDATA first, we can quickly detect when it's different
|
||||
// (99% of the time) and then bail out before we waste time on the expensive SameDomainName() check.
|
||||
|
||||
#define IdenticalResourceRecord(r1,r2) ( \
|
||||
(r1)->rrtype == (r2)->rrtype && \
|
||||
(r1)->rrclass == (r2)->rrclass && \
|
||||
(r1)->namehash == (r2)->namehash && \
|
||||
(r1)->rdlength == (r2)->rdlength && \
|
||||
(r1)->rdatahash == (r2)->rdatahash && \
|
||||
SameRDataBody((r1), &(r2)->rdata->u, SameDomainName) && \
|
||||
SameDomainName((r1)->name, (r2)->name))
|
||||
|
||||
#define IdenticalSameNameRecord(r1,r2) ( \
|
||||
(r1)->rrtype == (r2)->rrtype && \
|
||||
(r1)->rrclass == (r2)->rrclass && \
|
||||
(r1)->rdlength == (r2)->rdlength && \
|
||||
(r1)->rdatahash == (r2)->rdatahash && \
|
||||
SameRDataBody((r1), &(r2)->rdata->u, SameDomainName))
|
||||
|
||||
// A given RRType answers a QuestionType if RRType is CNAME, or types match, or QuestionType is ANY,
|
||||
// or the RRType is NSEC and positively asserts the nonexistence of the type being requested
|
||||
#define RRTypeAnswersQuestionType(R,Q) ((R)->rrtype == kDNSType_CNAME || (R)->rrtype == (Q) || (Q) == kDNSQType_ANY || RRAssertsNonexistence((R),(Q)))
|
||||
#define RRAssertsNonexistence(R,T) ((R)->rrtype == kDNSType_NSEC && (T) < kDNSQType_ANY && !((R)->rdata->u.nsec.bitmap[(T)>>3] & (128 >> ((T)&7))))
|
||||
|
||||
extern mDNSu32 RDataHashValue(const ResourceRecord *const rr);
|
||||
extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2, DomainNameComparisonFn *samename);
|
||||
extern mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSBool AnyTypeRecordAnswersQuestion (const ResourceRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSBool ResourceRecordAnswersUnicastResponse(const ResourceRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSBool LocalOnlyRecordAnswersQuestion(AuthRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate);
|
||||
extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
|
||||
|
||||
#define GetRRDomainNameTarget(RR) ( \
|
||||
((RR)->rrtype == kDNSType_NS || (RR)->rrtype == kDNSType_CNAME || (RR)->rrtype == kDNSType_PTR || (RR)->rrtype == kDNSType_DNAME) ? &(RR)->rdata->u.name : \
|
||||
((RR)->rrtype == kDNSType_MX || (RR)->rrtype == kDNSType_AFSDB || (RR)->rrtype == kDNSType_RT || (RR)->rrtype == kDNSType_KX ) ? &(RR)->rdata->u.mx.exchange : \
|
||||
((RR)->rrtype == kDNSType_SRV ) ? &(RR)->rdata->u.srv.target : mDNSNULL )
|
||||
|
||||
#define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique)
|
||||
|
||||
// ***************************************************************************
|
||||
#if COMPILER_LIKES_PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#pragma mark - DNS Message Creation Functions
|
||||
#endif
|
||||
|
||||
extern void InitializeDNSMessage(DNSMessageHeader *h, mDNSOpaque16 id, mDNSOpaque16 flags);
|
||||
extern const mDNSu8 *FindCompressionPointer(const mDNSu8 *const base, const mDNSu8 *const end, const mDNSu8 *const domname);
|
||||
extern mDNSu8 *putDomainNameAsLabels(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name);
|
||||
extern mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const ResourceRecord *const rr);
|
||||
|
||||
// If we have a single large record to put in the packet, then we allow the packet to be up to 9K bytes,
|
||||
// but in the normal case we try to keep the packets below 1500 to avoid IP fragmentation on standard Ethernet
|
||||
|
||||
#define AllowedRRSpace(msg) (((msg)->h.numAnswers || (msg)->h.numAuthorities || (msg)->h.numAdditionals) ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData)
|
||||
|
||||
extern mDNSu8 *PutResourceRecordTTLWithLimit(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 ttl, const mDNSu8 *limit);
|
||||
|
||||
#define PutResourceRecordTTL(msg, ptr, count, rr, ttl) \
|
||||
PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), (msg)->data + AllowedRRSpace(msg))
|
||||
|
||||
#define PutResourceRecordTTLJumbo(msg, ptr, count, rr, ttl) \
|
||||
PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), (msg)->data + AbsoluteMaxDNSMessageData)
|
||||
|
||||
#define PutResourceRecord(MSG, P, C, RR) PutResourceRecordTTL((MSG), (P), (C), (RR), (RR)->rroriginalttl)
|
||||
|
||||
// The PutRR_OS variants assume a local variable 'm', put build the packet at m->omsg,
|
||||
// and assume a local variable 'OwnerRecordSpace' indicating how many bytes (if any) to reserve to add an OWNER option at the end
|
||||
#define PutRR_OS_TTL(ptr, count, rr, ttl) \
|
||||
PutResourceRecordTTLWithLimit(&m->omsg, (ptr), (count), (rr), (ttl), m->omsg.data + AllowedRRSpace(&m->omsg) - OwnerRecordSpace)
|
||||
|
||||
#define PutRR_OS(P, C, RR) PutRR_OS_TTL((P), (C), (RR), (RR)->rroriginalttl)
|
||||
|
||||
extern mDNSu8 *putQuestion(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name, mDNSu16 rrtype, mDNSu16 rrclass);
|
||||
extern mDNSu8 *putZone(DNSMessage *const msg, mDNSu8 *ptr, mDNSu8 *limit, const domainname *zone, mDNSOpaque16 zoneClass);
|
||||
extern mDNSu8 *putPrereqNameNotInUse(const domainname *const name, DNSMessage *const msg, mDNSu8 *const ptr, mDNSu8 *const end);
|
||||
extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr);
|
||||
extern mDNSu8 *putDeletionRecordWithLimit(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr, mDNSu8 *limit);
|
||||
extern mDNSu8 *putDeleteRRSetWithLimit(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype, mDNSu8 *limit);
|
||||
extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name);
|
||||
extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease);
|
||||
extern mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit);
|
||||
|
||||
extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *ptr, DomainAuthInfo *authInfo, mDNSu8 *limit);
|
||||
|
||||
// ***************************************************************************
|
||||
#if COMPILER_LIKES_PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#pragma mark - DNS Message Parsing Functions
|
||||
#endif
|
||||
|
||||
#define AuthHashSlot(X) (DomainNameHashValue(X) % AUTH_HASH_SLOTS)
|
||||
#define HashSlot(X) (DomainNameHashValue(X) % CACHE_HASH_SLOTS)
|
||||
extern mDNSu32 DomainNameHashValue(const domainname *const name);
|
||||
extern void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 rdlength);
|
||||
extern const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end);
|
||||
extern const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end,
|
||||
domainname *const name);
|
||||
extern const mDNSu8 *skipResourceRecord(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end);
|
||||
extern const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage * const msg, const mDNSu8 *ptr,
|
||||
const mDNSu8 * end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *const largecr);
|
||||
extern const mDNSu8 *skipQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end);
|
||||
extern const mDNSu8 *getQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end, const mDNSInterfaceID InterfaceID,
|
||||
DNSQuestion *question);
|
||||
extern const mDNSu8 *LocateAnswers(const DNSMessage *const msg, const mDNSu8 *const end);
|
||||
extern const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8 *const end);
|
||||
extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end);
|
||||
extern const mDNSu8 *LocateOptRR(const DNSMessage *const msg, const mDNSu8 *const end, int minsize);
|
||||
extern const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end);
|
||||
extern mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end);
|
||||
extern void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *transport,
|
||||
const mDNSAddr *srcaddr, mDNSIPPort srcport,
|
||||
const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end);
|
||||
|
||||
// ***************************************************************************
|
||||
#if COMPILER_LIKES_PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#pragma mark - Packet Sending Functions
|
||||
#endif
|
||||
|
||||
extern mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end,
|
||||
mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo);
|
||||
|
||||
// ***************************************************************************
|
||||
#if COMPILER_LIKES_PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#pragma mark - RR List Management & Task Management
|
||||
#endif
|
||||
|
||||
extern void ShowTaskSchedulingError(mDNS *const m);
|
||||
extern void mDNS_Lock_(mDNS *const m, const char * const functionname);
|
||||
extern void mDNS_Unlock_(mDNS *const m, const char * const functionname);
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#define mDNS_Lock(X) mDNS_Lock_((X), __func__)
|
||||
|
||||
#define mDNS_Unlock(X) mDNS_Unlock_((X), __func__)
|
||||
|
||||
#define mDNS_DropLockBeforeCallback() do { m->mDNS_reentrancy++; \
|
||||
if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Locking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \
|
||||
} while (0)
|
||||
|
||||
#define mDNS_ReclaimLockAfterCallback() do { \
|
||||
if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Unlocking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \
|
||||
m->mDNS_reentrancy--; } while (0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __DNSCOMMON_H_
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
||||
MessageIdTypedef=WORD
|
||||
LanguageNames=(English=0x409:MSG00409)
|
||||
|
||||
MessageId=100
|
||||
SymbolicName=MDNSRESPONDER_LOG
|
||||
Severity=Success
|
||||
Facility=Application
|
||||
Language=English
|
||||
%1
|
||||
.
|
||||
|
@@ -1,484 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// <rdar://problem/4278931> Doesn't compile correctly with latest Platform SDK
|
||||
|
||||
#if !defined(_WIN32_DCOM)
|
||||
# define _WIN32_DCOM
|
||||
#endif
|
||||
|
||||
|
||||
#include "Firewall.h"
|
||||
#include <windows.h>
|
||||
#include <crtdbg.h>
|
||||
#include <netfw.h>
|
||||
#include <objbase.h>
|
||||
#include <oleauto.h>
|
||||
|
||||
|
||||
static const int kMaxTries = 30;
|
||||
static const int kRetrySleepPeriod = 1 * 1000; // 1 second
|
||||
|
||||
|
||||
static OSStatus
|
||||
mDNSFirewallInitialize(OUT INetFwProfile ** fwProfile)
|
||||
{
|
||||
INetFwMgr * fwMgr = NULL;
|
||||
INetFwPolicy * fwPolicy = NULL;
|
||||
int numRetries = 0;
|
||||
HRESULT err = kNoErr;
|
||||
|
||||
_ASSERT(fwProfile != NULL);
|
||||
|
||||
*fwProfile = NULL;
|
||||
|
||||
// Use COM to get a reference to the firewall settings manager. This
|
||||
// call will fail on anything other than XP SP2
|
||||
|
||||
err = CoCreateInstance( __uuidof(NetFwMgr), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwMgr), (void**)&fwMgr );
|
||||
require(SUCCEEDED(err) && ( fwMgr != NULL ), exit);
|
||||
|
||||
// Use the reference to get the local firewall policy
|
||||
|
||||
err = fwMgr->get_LocalPolicy(&fwPolicy);
|
||||
require(SUCCEEDED(err) && ( fwPolicy != NULL ), exit);
|
||||
|
||||
// Use the reference to get the extant profile. Empirical evidence
|
||||
// suggests that there is the potential for a race condition when a system
|
||||
// service whose startup type is automatic calls this method.
|
||||
// This is true even when the service declares itself to be dependent
|
||||
// on the firewall service. Re-trying the method will succeed within
|
||||
// a few seconds.
|
||||
|
||||
do
|
||||
{
|
||||
err = fwPolicy->get_CurrentProfile(fwProfile);
|
||||
|
||||
if (err)
|
||||
{
|
||||
Sleep(kRetrySleepPeriod);
|
||||
}
|
||||
}
|
||||
while (err && (numRetries++ < kMaxTries));
|
||||
|
||||
require(SUCCEEDED(err), exit);
|
||||
|
||||
err = kNoErr;
|
||||
|
||||
exit:
|
||||
|
||||
// Release temporary COM objects
|
||||
|
||||
if (fwPolicy != NULL)
|
||||
{
|
||||
fwPolicy->Release();
|
||||
}
|
||||
|
||||
if (fwMgr != NULL)
|
||||
{
|
||||
fwMgr->Release();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mDNSFirewallCleanup
|
||||
(
|
||||
IN INetFwProfile * fwProfile
|
||||
)
|
||||
{
|
||||
// Call Release on the COM reference.
|
||||
|
||||
if (fwProfile != NULL)
|
||||
{
|
||||
fwProfile->Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static OSStatus
|
||||
mDNSFirewallAppIsEnabled
|
||||
(
|
||||
IN INetFwProfile * fwProfile,
|
||||
IN const wchar_t * fwProcessImageFileName,
|
||||
OUT BOOL * fwAppEnabled
|
||||
)
|
||||
{
|
||||
BSTR fwBstrProcessImageFileName = NULL;
|
||||
VARIANT_BOOL fwEnabled;
|
||||
INetFwAuthorizedApplication * fwApp = NULL;
|
||||
INetFwAuthorizedApplications* fwApps = NULL;
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
_ASSERT(fwProfile != NULL);
|
||||
_ASSERT(fwProcessImageFileName != NULL);
|
||||
_ASSERT(fwAppEnabled != NULL);
|
||||
|
||||
*fwAppEnabled = FALSE;
|
||||
|
||||
// Get the list of authorized applications
|
||||
|
||||
err = fwProfile->get_AuthorizedApplications(&fwApps);
|
||||
require(SUCCEEDED(err) && ( fwApps != NULL ), exit);
|
||||
|
||||
fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
|
||||
require_action( ( fwProcessImageFileName != NULL ) && ( SysStringLen(fwBstrProcessImageFileName) > 0 ), exit, err = kNoMemoryErr);
|
||||
|
||||
// Look for us
|
||||
|
||||
err = fwApps->Item(fwBstrProcessImageFileName, &fwApp);
|
||||
|
||||
if (SUCCEEDED(err) && ( fwApp != NULL ) )
|
||||
{
|
||||
// It's listed, but is it enabled?
|
||||
|
||||
err = fwApp->get_Enabled(&fwEnabled);
|
||||
require(SUCCEEDED(err), exit);
|
||||
|
||||
if (fwEnabled != VARIANT_FALSE)
|
||||
{
|
||||
// Yes, it's enabled
|
||||
|
||||
*fwAppEnabled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
err = kNoErr;
|
||||
|
||||
exit:
|
||||
|
||||
// Deallocate the BSTR
|
||||
|
||||
if ( fwBstrProcessImageFileName != NULL )
|
||||
{
|
||||
SysFreeString(fwBstrProcessImageFileName);
|
||||
}
|
||||
|
||||
// Release the COM objects
|
||||
|
||||
if (fwApp != NULL)
|
||||
{
|
||||
fwApp->Release();
|
||||
}
|
||||
|
||||
if (fwApps != NULL)
|
||||
{
|
||||
fwApps->Release();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static OSStatus
|
||||
mDNSFirewallAddApp
|
||||
(
|
||||
IN INetFwProfile * fwProfile,
|
||||
IN const wchar_t * fwProcessImageFileName,
|
||||
IN const wchar_t * fwName
|
||||
)
|
||||
{
|
||||
BOOL fwAppEnabled;
|
||||
BSTR fwBstrName = NULL;
|
||||
BSTR fwBstrProcessImageFileName = NULL;
|
||||
INetFwAuthorizedApplication * fwApp = NULL;
|
||||
INetFwAuthorizedApplications* fwApps = NULL;
|
||||
OSStatus err = S_OK;
|
||||
|
||||
_ASSERT(fwProfile != NULL);
|
||||
_ASSERT(fwProcessImageFileName != NULL);
|
||||
_ASSERT(fwName != NULL);
|
||||
|
||||
// First check to see if the application is already authorized.
|
||||
err = mDNSFirewallAppIsEnabled( fwProfile, fwProcessImageFileName, &fwAppEnabled );
|
||||
require_noerr(err, exit);
|
||||
|
||||
// Only add the application if it isn't enabled
|
||||
|
||||
if (!fwAppEnabled)
|
||||
{
|
||||
// Get the list of authorized applications
|
||||
|
||||
err = fwProfile->get_AuthorizedApplications(&fwApps);
|
||||
require(SUCCEEDED(err) && ( fwApps != NULL ), exit);
|
||||
|
||||
// Create an instance of an authorized application.
|
||||
|
||||
err = CoCreateInstance( __uuidof(NetFwAuthorizedApplication), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwAuthorizedApplication), (void**)&fwApp );
|
||||
require(SUCCEEDED(err) && ( fwApp != NULL ), exit);
|
||||
|
||||
fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
|
||||
require_action(( fwProcessImageFileName != NULL ) && ( SysStringLen(fwBstrProcessImageFileName) > 0 ), exit, err = kNoMemoryErr);
|
||||
|
||||
// Set the executable file name
|
||||
|
||||
err = fwApp->put_ProcessImageFileName(fwBstrProcessImageFileName);
|
||||
require(SUCCEEDED(err), exit);
|
||||
|
||||
fwBstrName = SysAllocString(fwName);
|
||||
require_action( ( fwBstrName != NULL ) && ( SysStringLen(fwBstrName) > 0 ), exit, err = kNoMemoryErr);
|
||||
|
||||
// Set the friendly name
|
||||
|
||||
err = fwApp->put_Name(fwBstrName);
|
||||
require(SUCCEEDED(err), exit);
|
||||
|
||||
// Now add the application
|
||||
|
||||
err = fwApps->Add(fwApp);
|
||||
require(SUCCEEDED(err), exit);
|
||||
}
|
||||
|
||||
err = kNoErr;
|
||||
|
||||
exit:
|
||||
|
||||
// Deallocate the BSTR objects
|
||||
|
||||
if ( fwBstrName != NULL )
|
||||
{
|
||||
SysFreeString(fwBstrName);
|
||||
}
|
||||
|
||||
if ( fwBstrProcessImageFileName != NULL )
|
||||
{
|
||||
SysFreeString(fwBstrProcessImageFileName);
|
||||
}
|
||||
|
||||
// Release the COM objects
|
||||
|
||||
if (fwApp != NULL)
|
||||
{
|
||||
fwApp->Release();
|
||||
}
|
||||
|
||||
if (fwApps != NULL)
|
||||
{
|
||||
fwApps->Release();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static OSStatus
|
||||
|
||||
mDNSFirewallIsFileAndPrintSharingEnabled
|
||||
|
||||
(
|
||||
|
||||
IN INetFwProfile * fwProfile,
|
||||
|
||||
OUT BOOL * fwServiceEnabled
|
||||
|
||||
)
|
||||
|
||||
{
|
||||
|
||||
VARIANT_BOOL fwEnabled;
|
||||
|
||||
INetFwService* fwService = NULL;
|
||||
|
||||
INetFwServices* fwServices = NULL;
|
||||
|
||||
OSStatus err = S_OK;
|
||||
|
||||
|
||||
|
||||
_ASSERT(fwProfile != NULL);
|
||||
|
||||
_ASSERT(fwServiceEnabled != NULL);
|
||||
|
||||
|
||||
|
||||
*fwServiceEnabled = FALSE;
|
||||
|
||||
|
||||
|
||||
// Retrieve the globally open ports collection.
|
||||
|
||||
err = fwProfile->get_Services(&fwServices);
|
||||
|
||||
require( SUCCEEDED( err ), exit );
|
||||
|
||||
|
||||
|
||||
// Attempt to retrieve the globally open port.
|
||||
|
||||
err = fwServices->Item(NET_FW_SERVICE_FILE_AND_PRINT, &fwService);
|
||||
|
||||
require( SUCCEEDED( err ), exit );
|
||||
|
||||
|
||||
|
||||
// Find out if the globally open port is enabled.
|
||||
|
||||
err = fwService->get_Enabled(&fwEnabled);
|
||||
|
||||
require( SUCCEEDED( err ), exit );
|
||||
|
||||
if (fwEnabled != VARIANT_FALSE)
|
||||
|
||||
{
|
||||
|
||||
*fwServiceEnabled = TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
exit:
|
||||
|
||||
|
||||
|
||||
// Release the globally open port.
|
||||
|
||||
if (fwService != NULL)
|
||||
|
||||
{
|
||||
|
||||
fwService->Release();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Release the globally open ports collection.
|
||||
|
||||
if (fwServices != NULL)
|
||||
|
||||
{
|
||||
|
||||
fwServices->Release();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
|
||||
OSStatus
|
||||
mDNSAddToFirewall
|
||||
(
|
||||
LPWSTR executable,
|
||||
LPWSTR name
|
||||
)
|
||||
{
|
||||
INetFwProfile * fwProfile = NULL;
|
||||
HRESULT comInit = E_FAIL;
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
// Initialize COM.
|
||||
|
||||
comInit = CoInitializeEx( 0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
|
||||
|
||||
// Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
|
||||
// initialized with a different mode.
|
||||
|
||||
if (comInit != RPC_E_CHANGED_MODE)
|
||||
{
|
||||
err = comInit;
|
||||
require(SUCCEEDED(err), exit);
|
||||
}
|
||||
|
||||
// Connect to the firewall
|
||||
|
||||
err = mDNSFirewallInitialize(&fwProfile);
|
||||
require( SUCCEEDED( err ) && ( fwProfile != NULL ), exit);
|
||||
|
||||
// Add us to the list of exempt programs
|
||||
|
||||
err = mDNSFirewallAddApp( fwProfile, executable, name );
|
||||
require_noerr(err, exit);
|
||||
|
||||
exit:
|
||||
|
||||
// Disconnect from the firewall
|
||||
|
||||
if ( fwProfile != NULL )
|
||||
{
|
||||
mDNSFirewallCleanup(fwProfile);
|
||||
}
|
||||
|
||||
// De-initialize COM
|
||||
|
||||
if (SUCCEEDED(comInit))
|
||||
{
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
mDNSIsFileAndPrintSharingEnabled( BOOL * retry )
|
||||
{
|
||||
INetFwProfile * fwProfile = NULL;
|
||||
HRESULT comInit = E_FAIL;
|
||||
BOOL enabled = FALSE;
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
// Initialize COM.
|
||||
|
||||
*retry = FALSE;
|
||||
comInit = CoInitializeEx( 0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
|
||||
|
||||
// Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
|
||||
// initialized with a different mode.
|
||||
|
||||
if (comInit != RPC_E_CHANGED_MODE)
|
||||
{
|
||||
*retry = TRUE;
|
||||
err = comInit;
|
||||
require(SUCCEEDED(err), exit);
|
||||
}
|
||||
|
||||
// Connect to the firewall
|
||||
|
||||
err = mDNSFirewallInitialize(&fwProfile);
|
||||
require( SUCCEEDED( err ) && ( fwProfile != NULL ), exit);
|
||||
|
||||
err = mDNSFirewallIsFileAndPrintSharingEnabled( fwProfile, &enabled );
|
||||
require_noerr( err, exit );
|
||||
|
||||
exit:
|
||||
|
||||
// Disconnect from the firewall
|
||||
|
||||
if ( fwProfile != NULL )
|
||||
{
|
||||
mDNSFirewallCleanup(fwProfile);
|
||||
}
|
||||
|
||||
// De-initialize COM
|
||||
|
||||
if (SUCCEEDED(comInit))
|
||||
{
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
@@ -1,79 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _Firewall_h
|
||||
|
||||
#define _Firewall_h
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "CommonServices.h"
|
||||
|
||||
#include "DebugServices.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
extern "C"
|
||||
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
OSStatus
|
||||
|
||||
mDNSAddToFirewall
|
||||
|
||||
(
|
||||
|
||||
LPWSTR executable,
|
||||
|
||||
LPWSTR name
|
||||
|
||||
);
|
||||
|
||||
|
||||
BOOL
|
||||
mDNSIsFileAndPrintSharingEnabled( BOOL * retry );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -1,319 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
File: GenLinkedList.c
|
||||
|
||||
Contains: implementation of generic linked lists.
|
||||
|
||||
Version: 1.0
|
||||
Tabs: 4 spaces
|
||||
*/
|
||||
|
||||
#include "GenLinkedList.h"
|
||||
|
||||
|
||||
// Return the link pointer contained within element e at offset o.
|
||||
#define GETLINK( e, o) ( *(void**)((char*) (e) + (o)) )
|
||||
|
||||
// Assign the link pointer l to element e at offset o.
|
||||
#define ASSIGNLINK( e, l, o) ( *((void**)((char*) (e) + (o))) = (l))
|
||||
|
||||
|
||||
// GenLinkedList /////////////////////////////////////////////////////////////
|
||||
|
||||
void InitLinkedList( GenLinkedList *pList, size_t linkOffset)
|
||||
/* Initialize the block of memory pointed to by pList as a linked list. */
|
||||
{
|
||||
pList->Head = NULL;
|
||||
pList->Tail = NULL;
|
||||
pList->LinkOffset = linkOffset;
|
||||
}
|
||||
|
||||
|
||||
void AddToTail( GenLinkedList *pList, void *elem)
|
||||
/* Add a linked list element to the tail of the list. */
|
||||
{
|
||||
if ( pList->Tail) {
|
||||
ASSIGNLINK( pList->Tail, elem, pList->LinkOffset);
|
||||
} else
|
||||
pList->Head = elem;
|
||||
ASSIGNLINK( elem, NULL, pList->LinkOffset);
|
||||
|
||||
pList->Tail = elem;
|
||||
}
|
||||
|
||||
|
||||
void AddToHead( GenLinkedList *pList, void *elem)
|
||||
/* Add a linked list element to the head of the list. */
|
||||
{
|
||||
ASSIGNLINK( elem, pList->Head, pList->LinkOffset);
|
||||
if ( pList->Tail == NULL)
|
||||
pList->Tail = elem;
|
||||
|
||||
pList->Head = elem;
|
||||
}
|
||||
|
||||
|
||||
int RemoveFromList( GenLinkedList *pList, void *elem)
|
||||
/* Remove a linked list element from the list. Return 0 if it was not found. */
|
||||
/* If the element is removed, its link will be set to NULL. */
|
||||
{
|
||||
void *iElem, *lastElem;
|
||||
|
||||
for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset)) {
|
||||
if ( iElem == elem) {
|
||||
if ( lastElem) { // somewhere past the head
|
||||
ASSIGNLINK( lastElem, GETLINK( elem, pList->LinkOffset), pList->LinkOffset);
|
||||
} else { // at the head
|
||||
pList->Head = GETLINK( elem, pList->LinkOffset);
|
||||
}
|
||||
if ( pList->Tail == elem)
|
||||
pList->Tail = lastElem ? lastElem : NULL;
|
||||
ASSIGNLINK( elem, NULL, pList->LinkOffset); // maybe catch a stale reference bug.
|
||||
return 1;
|
||||
}
|
||||
lastElem = iElem;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ReplaceElem( GenLinkedList *pList, void *elemInList, void *newElem)
|
||||
/* Replace an element in the list with a new element, in the same position. */
|
||||
{
|
||||
void *iElem, *lastElem;
|
||||
|
||||
if ( elemInList == NULL || newElem == NULL)
|
||||
return 0;
|
||||
|
||||
for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset))
|
||||
{
|
||||
if ( iElem == elemInList)
|
||||
{
|
||||
ASSIGNLINK( newElem, GETLINK( elemInList, pList->LinkOffset), pList->LinkOffset);
|
||||
if ( lastElem) // somewhere past the head
|
||||
{
|
||||
ASSIGNLINK( lastElem, newElem, pList->LinkOffset);
|
||||
}
|
||||
else // at the head
|
||||
{
|
||||
pList->Head = newElem;
|
||||
}
|
||||
if ( pList->Tail == elemInList)
|
||||
pList->Tail = newElem;
|
||||
return 1;
|
||||
}
|
||||
lastElem = iElem;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// GenDoubleLinkedList /////////////////////////////////////////////////////////
|
||||
|
||||
void InitDoubleLinkedList( GenDoubleLinkedList *pList, size_t fwdLinkOffset,
|
||||
size_t backLinkOffset)
|
||||
/* Initialize the block of memory pointed to by pList as a double linked list. */
|
||||
{
|
||||
pList->Head = NULL;
|
||||
pList->Tail = NULL;
|
||||
pList->FwdLinkOffset = fwdLinkOffset;
|
||||
pList->BackLinkOffset = backLinkOffset;
|
||||
}
|
||||
|
||||
|
||||
void DLLAddToHead( GenDoubleLinkedList *pList, void *elem)
|
||||
/* Add a linked list element to the head of the list. */
|
||||
{
|
||||
void *pNext;
|
||||
|
||||
pNext = pList->Head;
|
||||
|
||||
// fix up the forward links
|
||||
ASSIGNLINK( elem, pList->Head, pList->FwdLinkOffset);
|
||||
pList->Head = elem;
|
||||
|
||||
// fix up the backward links
|
||||
if ( pNext) {
|
||||
ASSIGNLINK( pNext, elem, pList->BackLinkOffset);
|
||||
} else
|
||||
pList->Tail = elem;
|
||||
ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
|
||||
}
|
||||
|
||||
|
||||
void DLLRemoveFromList( GenDoubleLinkedList *pList, void *elem)
|
||||
/* Remove a linked list element from the list. */
|
||||
/* When the element is removed, its link will be set to NULL. */
|
||||
{
|
||||
void *pNext, *pPrev;
|
||||
|
||||
pNext = GETLINK( elem, pList->FwdLinkOffset);
|
||||
pPrev = GETLINK( elem, pList->BackLinkOffset);
|
||||
|
||||
// fix up the forward links
|
||||
if ( pPrev)
|
||||
ASSIGNLINK( pPrev, pNext, pList->FwdLinkOffset);
|
||||
else
|
||||
pList->Head = pNext;
|
||||
|
||||
// fix up the backward links
|
||||
if ( pNext)
|
||||
ASSIGNLINK( pNext, pPrev, pList->BackLinkOffset);
|
||||
else
|
||||
pList->Tail = pPrev;
|
||||
|
||||
ASSIGNLINK( elem, NULL, pList->FwdLinkOffset);
|
||||
ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
|
||||
}
|
||||
|
||||
|
||||
// GenLinkedOffsetList /////////////////////////////////////////////////////
|
||||
|
||||
// Extract the Next offset from element
|
||||
#define GETOFFSET( e, o) ( *(size_t*)((char*) (e) + (o)) )
|
||||
|
||||
static void AssignOffsetLink( void *elem, void *link, size_t linkOffset);
|
||||
|
||||
|
||||
static void AssignOffsetLink( void *elem, void *link, size_t linkOffset)
|
||||
// Assign link to elem as an offset from elem. Assign 0 to elem if link is NULL.
|
||||
{
|
||||
GETOFFSET( elem, linkOffset) = link ? (size_t) link - (size_t) elem : 0;
|
||||
}
|
||||
|
||||
|
||||
void *GetHeadPtr( GenLinkedOffsetList *pList)
|
||||
/* Return a pointer to the head element of a list, or NULL if none. */
|
||||
{
|
||||
return pList->Head ? ( (char*) (pList) + pList->Head) : NULL;
|
||||
}
|
||||
|
||||
|
||||
void *GetTailPtr( GenLinkedOffsetList *pList)
|
||||
/* Return a pointer to the tail element of a list, or NULL if none. */
|
||||
{
|
||||
return pList->Tail ? ( (char*) (pList) + pList->Tail) : NULL;
|
||||
}
|
||||
|
||||
|
||||
void *GetOffsetLink( GenLinkedOffsetList *pList, void *elem)
|
||||
/* Return the link pointer contained within element e for pList, or NULL if it is 0. */
|
||||
{
|
||||
size_t nextOffset;
|
||||
|
||||
nextOffset = GETOFFSET( elem, pList->LinkOffset);
|
||||
|
||||
return nextOffset ? (char*) elem + nextOffset : NULL;
|
||||
}
|
||||
|
||||
|
||||
void InitLinkedOffsetList( GenLinkedOffsetList *pList, size_t linkOffset)
|
||||
/* Initialize the block of memory pointed to by pList as a linked list. */
|
||||
{
|
||||
pList->Head = 0;
|
||||
pList->Tail = 0;
|
||||
pList->LinkOffset = linkOffset;
|
||||
}
|
||||
|
||||
|
||||
void OffsetAddToTail( GenLinkedOffsetList *pList, void *elem)
|
||||
/* Add a linked list element to the tail of the list. */
|
||||
{
|
||||
if ( pList->Tail) {
|
||||
AssignOffsetLink( GetTailPtr( pList), elem, pList->LinkOffset);
|
||||
} else
|
||||
pList->Head = (size_t) elem - (size_t) pList;
|
||||
AssignOffsetLink( elem, NULL, pList->LinkOffset);
|
||||
|
||||
pList->Tail = (size_t) elem - (size_t) pList;
|
||||
}
|
||||
|
||||
|
||||
void OffsetAddToHead( GenLinkedOffsetList *pList, void *elem)
|
||||
/* Add a linked list element to the head of the list. */
|
||||
{
|
||||
AssignOffsetLink( elem, GetHeadPtr( pList), pList->LinkOffset);
|
||||
if ( pList->Tail == 0)
|
||||
pList->Tail = (size_t) elem - (size_t) pList;
|
||||
|
||||
pList->Head = (size_t) elem - (size_t) pList;
|
||||
}
|
||||
|
||||
|
||||
int OffsetRemoveFromList( GenLinkedOffsetList *pList, void *elem)
|
||||
/* Remove a linked list element from the list. Return 0 if it was not found. */
|
||||
/* If the element is removed, its link will be set to NULL. */
|
||||
{
|
||||
void *iElem, *lastElem;
|
||||
|
||||
for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
|
||||
iElem = GetOffsetLink( pList, iElem))
|
||||
{
|
||||
if ( iElem == elem) {
|
||||
if ( lastElem) { // somewhere past the head
|
||||
AssignOffsetLink( lastElem, GetOffsetLink( pList, elem), pList->LinkOffset);
|
||||
} else { // at the head
|
||||
iElem = GetOffsetLink( pList, elem);
|
||||
pList->Head = iElem ? (size_t) iElem - (size_t) pList : 0;
|
||||
}
|
||||
if ( GetTailPtr( pList) == elem)
|
||||
pList->Tail = lastElem ? (size_t) lastElem - (size_t) pList : 0;
|
||||
AssignOffsetLink( elem, NULL, pList->LinkOffset); // maybe catch a stale reference bug.
|
||||
return 1;
|
||||
}
|
||||
lastElem = iElem;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int OffsetReplaceElem( GenLinkedOffsetList *pList, void *elemInList, void *newElem)
|
||||
/* Replace an element in the list with a new element, in the same position. */
|
||||
{
|
||||
void *iElem, *lastElem;
|
||||
|
||||
if ( elemInList == NULL || newElem == NULL)
|
||||
return 0;
|
||||
|
||||
for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
|
||||
iElem = GetOffsetLink( pList, iElem))
|
||||
{
|
||||
if ( iElem == elemInList)
|
||||
{
|
||||
AssignOffsetLink( newElem, GetOffsetLink( pList, elemInList), pList->LinkOffset);
|
||||
if ( lastElem) // somewhere past the head
|
||||
{
|
||||
AssignOffsetLink( lastElem, newElem, pList->LinkOffset);
|
||||
}
|
||||
else // at the head
|
||||
{
|
||||
pList->Head = (size_t) newElem - (size_t) pList;
|
||||
}
|
||||
if ( GetTailPtr( pList) == elemInList)
|
||||
pList->Tail = (size_t) newElem - (size_t) pList;
|
||||
return 1;
|
||||
}
|
||||
lastElem = iElem;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -1,90 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __GenLinkedList__
|
||||
#define __GenLinkedList__
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
struct GenLinkedList
|
||||
{
|
||||
void *Head,
|
||||
*Tail;
|
||||
size_t LinkOffset;
|
||||
};
|
||||
typedef struct GenLinkedList GenLinkedList;
|
||||
|
||||
|
||||
void InitLinkedList( GenLinkedList *pList, size_t linkOffset);
|
||||
|
||||
void AddToHead( GenLinkedList *pList, void *elem);
|
||||
void AddToTail( GenLinkedList *pList, void *elem);
|
||||
|
||||
int RemoveFromList( GenLinkedList *pList, void *elem);
|
||||
|
||||
int ReplaceElem( GenLinkedList *pList, void *elemInList, void *newElem);
|
||||
|
||||
|
||||
|
||||
struct GenDoubleLinkedList
|
||||
{
|
||||
void *Head,
|
||||
*Tail;
|
||||
size_t FwdLinkOffset,
|
||||
BackLinkOffset;
|
||||
};
|
||||
typedef struct GenDoubleLinkedList GenDoubleLinkedList;
|
||||
|
||||
|
||||
void InitDoubleLinkedList( GenDoubleLinkedList *pList, size_t fwdLinkOffset,
|
||||
size_t backLinkOffset);
|
||||
|
||||
void DLLAddToHead( GenDoubleLinkedList *pList, void *elem);
|
||||
|
||||
void DLLRemoveFromList( GenDoubleLinkedList *pList, void *elem);
|
||||
|
||||
|
||||
|
||||
/* A GenLinkedOffsetList is like a GenLinkedList that stores the *Next field as a signed */
|
||||
/* offset from the address of the beginning of the element, rather than as a pointer. */
|
||||
|
||||
struct GenLinkedOffsetList
|
||||
{
|
||||
size_t Head,
|
||||
Tail;
|
||||
size_t LinkOffset;
|
||||
};
|
||||
typedef struct GenLinkedOffsetList GenLinkedOffsetList;
|
||||
|
||||
|
||||
void InitLinkedOffsetList( GenLinkedOffsetList *pList, size_t linkOffset);
|
||||
|
||||
void *GetHeadPtr( GenLinkedOffsetList *pList);
|
||||
void *GetTailPtr( GenLinkedOffsetList *pList);
|
||||
void *GetOffsetLink( GenLinkedOffsetList *pList, void *elem);
|
||||
|
||||
void OffsetAddToHead( GenLinkedOffsetList *pList, void *elem);
|
||||
void OffsetAddToTail( GenLinkedOffsetList *pList, void *elem);
|
||||
|
||||
int OffsetRemoveFromList( GenLinkedOffsetList *pList, void *elem);
|
||||
|
||||
int OffsetReplaceElem( GenLinkedOffsetList *pList, void *elemInList, void *newElem);
|
||||
|
||||
|
||||
#endif // __GenLinkedList__
|
@@ -1,906 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef _LEGACY_NAT_TRAVERSAL_
|
||||
|
||||
#include "stdlib.h" // For strtol()
|
||||
#include "string.h" // For strlcpy(), For strncpy(), strncasecmp()
|
||||
|
||||
#if defined( WIN32 )
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
# define strcasecmp _stricmp
|
||||
# define strncasecmp _strnicmp
|
||||
# define mDNSASLLog( UUID, SUBDOMAIN, RESULT, SIGNATURE, FORMAT, ... ) ;
|
||||
|
||||
static int
|
||||
inet_pton( int family, const char * addr, void * dst )
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
int sslen = sizeof( ss );
|
||||
|
||||
ZeroMemory( &ss, sizeof( ss ) );
|
||||
ss.ss_family = (ADDRESS_FAMILY)family;
|
||||
|
||||
if ( WSAStringToAddressA( (LPSTR)addr, family, NULL, ( struct sockaddr* ) &ss, &sslen ) == 0 )
|
||||
{
|
||||
if ( family == AF_INET ) { memcpy( dst, &( ( struct sockaddr_in* ) &ss)->sin_addr, sizeof( IN_ADDR ) ); return 1; }
|
||||
else if ( family == AF_INET6 ) { memcpy( dst, &( ( struct sockaddr_in6* ) &ss)->sin6_addr, sizeof( IN6_ADDR ) ); return 1; }
|
||||
else return 0;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
#else
|
||||
# include <arpa/inet.h> // For inet_pton()
|
||||
#endif
|
||||
|
||||
#include "mDNSEmbeddedAPI.h"
|
||||
#include "uDNS.h" // For natTraversalHandleAddressReply() etc.
|
||||
|
||||
// used to format SOAP port mapping arguments
|
||||
typedef struct Property_struct
|
||||
{
|
||||
char *name;
|
||||
char *type;
|
||||
char *value;
|
||||
} Property;
|
||||
|
||||
// All of the text parsing in this file is intentionally transparent so that we know exactly
|
||||
// what's being done to the text, with an eye towards preventing security problems.
|
||||
|
||||
// This is an evolving list of useful acronyms to know. Please add to it at will.
|
||||
// ST Service Type
|
||||
// NT Notification Type
|
||||
// USN Unique Service Name
|
||||
// UDN Unique Device Name
|
||||
// UUID Universally Unique Identifier
|
||||
// URN/urn Universal Resource Name
|
||||
|
||||
// Forward declaration because of circular reference:
|
||||
// SendPortMapRequest -> SendSOAPMsgControlAction -> MakeTCPConnection -> tcpConnectionCallback -> handleLNTPortMappingResponse
|
||||
// In the event of a port conflict, handleLNTPortMappingResponse then increments tcpInfo->retries and calls back to SendPortMapRequest to try again
|
||||
mDNSlocal mStatus SendPortMapRequest(mDNS *m, NATTraversalInfo *n);
|
||||
|
||||
#define RequestedPortNum(n) (mDNSVal16(mDNSIPPortIsZero((n)->RequestedPort) ? (n)->IntPort : (n)->RequestedPort) + (mDNSu16)(n)->tcpInfo.retries)
|
||||
|
||||
// Note that this function assumes src is already NULL terminated
|
||||
mDNSlocal void AllocAndCopy(mDNSu8 **const dst, const mDNSu8 *const src)
|
||||
{
|
||||
if (src == mDNSNULL) return;
|
||||
if ((*dst = mDNSPlatformMemAllocate((mDNSu32)strlen((char*)src) + 1)) == mDNSNULL)
|
||||
{ LogMsg("AllocAndCopy: can't allocate string"); return; }
|
||||
strcpy((char*)*dst, (char*)src);
|
||||
}
|
||||
|
||||
// This function does a simple parse of an HTTP URL that may include a hostname, port, and path
|
||||
// If found in the URL, addressAndPort and path out params will point to newly allocated space (and will leak if they were previously pointing at allocated space)
|
||||
mDNSlocal mStatus ParseHttpUrl(const mDNSu8 *ptr, const mDNSu8 *const end, mDNSu8 **const addressAndPort, mDNSIPPort *const port, mDNSu8 **const path)
|
||||
{
|
||||
// if the data begins with "http://", we assume there is a hostname and possibly a port number
|
||||
if (end - ptr >= 7 && strncasecmp((char*)ptr, "http://", 7) == 0)
|
||||
{
|
||||
int i;
|
||||
const mDNSu8 *stop = end;
|
||||
const mDNSu8 *addrPtr = mDNSNULL;
|
||||
|
||||
ptr += 7; //skip over "http://"
|
||||
if (ptr >= end) { LogInfo("ParseHttpUrl: past end of buffer parsing host:port"); return mStatus_BadParamErr; }
|
||||
|
||||
// find the end of the host:port
|
||||
addrPtr = ptr;
|
||||
for (i = 0; addrPtr && addrPtr != end; i++, addrPtr++) if (*addrPtr == '/') break;
|
||||
|
||||
// allocate the buffer (len i+1 so we have space to terminate the string)
|
||||
if ((*addressAndPort = mDNSPlatformMemAllocate(i+1)) == mDNSNULL)
|
||||
{ LogMsg("ParseHttpUrl: can't allocate address string"); return mStatus_NoMemoryErr; }
|
||||
strncpy((char*)*addressAndPort, (char*)ptr, i);
|
||||
(*addressAndPort)[i] = '\0';
|
||||
|
||||
// find the port number in the string, by looking backwards for the ':'
|
||||
stop = ptr; // can't go back farther than the original start
|
||||
ptr = addrPtr; // move ptr to the path part
|
||||
|
||||
for (addrPtr--; addrPtr>stop; addrPtr--)
|
||||
{
|
||||
if (*addrPtr == ':')
|
||||
{
|
||||
addrPtr++; // skip over ':'
|
||||
*port = mDNSOpaque16fromIntVal((mDNSu16)strtol((char*)addrPtr, mDNSNULL, 10)); // store it properly converted
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ptr should now point to the first character we haven't yet processed
|
||||
// everything that remains is the path
|
||||
if (path && ptr < end)
|
||||
{
|
||||
if ((*path = mDNSPlatformMemAllocate((mDNSu32)(end - ptr) + 1)) == mDNSNULL)
|
||||
{ LogMsg("ParseHttpUrl: can't mDNSPlatformMemAllocate path"); return mStatus_NoMemoryErr; }
|
||||
strncpy((char*)*path, (char*)ptr, end - ptr);
|
||||
(*path)[end - ptr] = '\0';
|
||||
}
|
||||
|
||||
return mStatus_NoError;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
HTTPCode_NeedMoreData = -1, // No code found in stream
|
||||
HTTPCode_Other = -2, // Valid code other than those below found in stream
|
||||
HTTPCode_Bad = -3,
|
||||
HTTPCode_200 = 200,
|
||||
HTTPCode_404 = 404,
|
||||
HTTPCode_500 = 500,
|
||||
};
|
||||
|
||||
mDNSlocal mDNSs16 ParseHTTPResponseCode(const mDNSu8 **const data, const mDNSu8 *const end)
|
||||
{
|
||||
const mDNSu8 *ptr = *data;
|
||||
const mDNSu8 *code;
|
||||
|
||||
if (end - ptr < 5) return HTTPCode_NeedMoreData;
|
||||
if (strncasecmp((char*)ptr, "HTTP/", 5) != 0) return HTTPCode_Bad;
|
||||
ptr += 5;
|
||||
// should we care about the HTTP protocol version?
|
||||
|
||||
// look for first space, which must come before first LF
|
||||
while (ptr && ptr != end)
|
||||
{
|
||||
if (*ptr == '\n') return HTTPCode_Bad;
|
||||
if (*ptr == ' ') break;
|
||||
ptr++;
|
||||
}
|
||||
if (ptr == end) return HTTPCode_NeedMoreData;
|
||||
ptr++;
|
||||
|
||||
if (end - ptr < 3) return HTTPCode_NeedMoreData;
|
||||
|
||||
code = ptr;
|
||||
ptr += 3;
|
||||
while (ptr && ptr != end)
|
||||
{
|
||||
if (*ptr == '\n') break;
|
||||
ptr++;
|
||||
}
|
||||
if (ptr == end) return HTTPCode_NeedMoreData;
|
||||
*data = ++ptr;
|
||||
|
||||
if (memcmp((char*)code, "200", 3) == 0) return HTTPCode_200;
|
||||
if (memcmp((char*)code, "404", 3) == 0) return HTTPCode_404;
|
||||
if (memcmp((char*)code, "500", 3) == 0) return HTTPCode_500;
|
||||
|
||||
LogInfo("ParseHTTPResponseCode found unexpected result code: %c%c%c", code[0], code[1], code[2]);
|
||||
return HTTPCode_Other;
|
||||
}
|
||||
|
||||
// This function parses the xml body of the device description response from the router. Basically, we look to
|
||||
// make sure this is a response referencing a service we care about (WANIPConnection or WANPPPConnection),
|
||||
// look for the "controlURL" header immediately following, and copy the addressing and URL info we need
|
||||
mDNSlocal void handleLNTDeviceDescriptionResponse(tcpLNTInfo *tcpInfo)
|
||||
{
|
||||
mDNS *m = tcpInfo->m;
|
||||
const mDNSu8 *ptr = tcpInfo->Reply;
|
||||
const mDNSu8 *end = tcpInfo->Reply + tcpInfo->nread;
|
||||
const mDNSu8 *stop;
|
||||
mDNSs16 http_result;
|
||||
|
||||
if (!mDNSIPPortIsZero(m->UPnPSOAPPort)) return; // already have the info we need
|
||||
|
||||
http_result = ParseHTTPResponseCode(&ptr, end); // Note: modifies ptr
|
||||
if (http_result == HTTPCode_404) LNT_ClearState(m);
|
||||
if (http_result != HTTPCode_200)
|
||||
{
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "noop", "HTTP Result", "HTTP code: %d", http_result);
|
||||
return;
|
||||
}
|
||||
|
||||
// Always reset our flag to use WANIPConnection. We'll use WANPPPConnection if we find it and don't find WANIPConnection.
|
||||
m->UPnPWANPPPConnection = mDNSfalse;
|
||||
|
||||
// find either service we care about
|
||||
while (ptr && ptr < end)
|
||||
{
|
||||
if ((*ptr & 0xDF) == 'W' && (strncasecmp((char*)ptr, "WANIPConnection:1", 17) == 0)) break;
|
||||
ptr++;
|
||||
}
|
||||
if (ptr == end)
|
||||
{
|
||||
ptr = tcpInfo->Reply;
|
||||
while (ptr && ptr < end)
|
||||
{
|
||||
if ((*ptr & 0xDF) == 'W' && (strncasecmp((char*)ptr, "WANPPPConnection:1", 18) == 0))
|
||||
{
|
||||
m->UPnPWANPPPConnection = mDNStrue;
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
if (ptr == mDNSNULL || ptr == end) { LogInfo("handleLNTDeviceDescriptionResponse: didn't find WANIPConnection:1 or WANPPPConnection:1 string"); return; }
|
||||
|
||||
// find "controlURL", starting from where we left off
|
||||
while (ptr && ptr < end)
|
||||
{
|
||||
if ((*ptr & 0xDF) == 'C' && (strncasecmp((char*)ptr, "controlURL", 10) == 0)) break; // find the first 'c'; is this controlURL? if not, keep looking
|
||||
ptr++;
|
||||
}
|
||||
if (ptr == mDNSNULL || ptr == end) { LogInfo("handleLNTDeviceDescriptionResponse: didn't find controlURL string"); return; }
|
||||
ptr += 11; // skip over "controlURL>"
|
||||
if (ptr >= end) { LogInfo("handleLNTDeviceDescriptionResponse: past end of buffer and no body!"); return; } // check ptr again in case we skipped over the end of the buffer
|
||||
|
||||
// find the end of the controlURL element
|
||||
for (stop = ptr; stop < end; stop++) { if (*stop == '<') { end = stop; break; } }
|
||||
|
||||
// fill in default port
|
||||
m->UPnPSOAPPort = m->UPnPRouterPort;
|
||||
|
||||
// free string pointers and set to NULL
|
||||
if (m->UPnPSOAPAddressString != mDNSNULL)
|
||||
{
|
||||
mDNSPlatformMemFree(m->UPnPSOAPAddressString);
|
||||
m->UPnPSOAPAddressString = mDNSNULL;
|
||||
}
|
||||
if (m->UPnPSOAPURL != mDNSNULL)
|
||||
{
|
||||
mDNSPlatformMemFree(m->UPnPSOAPURL);
|
||||
m->UPnPSOAPURL = mDNSNULL;
|
||||
}
|
||||
|
||||
if (ParseHttpUrl(ptr, end, &m->UPnPSOAPAddressString, &m->UPnPSOAPPort, &m->UPnPSOAPURL) != mStatus_NoError) return;
|
||||
// the SOAPURL should look something like "/uuid:0013-108c-4b3f0000f3dc"
|
||||
|
||||
if (m->UPnPSOAPAddressString == mDNSNULL)
|
||||
{
|
||||
ptr = tcpInfo->Reply;
|
||||
while (ptr && ptr < end)
|
||||
{
|
||||
if ((*ptr & 0xDF) == 'U' && (strncasecmp((char*)ptr, "URLBase", 7) == 0)) break;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (ptr < end) // found URLBase
|
||||
{
|
||||
LogInfo("handleLNTDeviceDescriptionResponse: found URLBase");
|
||||
ptr += 8; // skip over "URLBase>"
|
||||
// find the end of the URLBase element
|
||||
for (stop = ptr; stop < end; stop++) { if (*stop == '<') { end = stop; break; } }
|
||||
if (ParseHttpUrl(ptr, end, &m->UPnPSOAPAddressString, &m->UPnPSOAPPort, mDNSNULL) != mStatus_NoError)
|
||||
{
|
||||
LogInfo("handleLNTDeviceDescriptionResponse: failed to parse URLBase");
|
||||
}
|
||||
}
|
||||
|
||||
// if all else fails, use the router address string
|
||||
if (m->UPnPSOAPAddressString == mDNSNULL) AllocAndCopy(&m->UPnPSOAPAddressString, m->UPnPRouterAddressString);
|
||||
}
|
||||
if (m->UPnPSOAPAddressString == mDNSNULL) LogMsg("handleLNTDeviceDescriptionResponse: UPnPSOAPAddressString is NULL");
|
||||
else LogInfo("handleLNTDeviceDescriptionResponse: SOAP address string [%s]", m->UPnPSOAPAddressString);
|
||||
|
||||
if (m->UPnPSOAPURL == mDNSNULL) AllocAndCopy(&m->UPnPSOAPURL, m->UPnPRouterURL);
|
||||
if (m->UPnPSOAPURL == mDNSNULL) LogMsg("handleLNTDeviceDescriptionResponse: UPnPSOAPURL is NULL");
|
||||
else LogInfo("handleLNTDeviceDescriptionResponse: SOAP URL [%s]", m->UPnPSOAPURL);
|
||||
}
|
||||
|
||||
mDNSlocal void handleLNTGetExternalAddressResponse(tcpLNTInfo *tcpInfo)
|
||||
{
|
||||
mDNS *m = tcpInfo->m;
|
||||
mDNSu16 err = NATErr_None;
|
||||
mDNSv4Addr ExtAddr;
|
||||
const mDNSu8 *ptr = tcpInfo->Reply;
|
||||
const mDNSu8 *end = tcpInfo->Reply + tcpInfo->nread;
|
||||
mDNSu8 *addrend;
|
||||
static char tagname[20] = { 'N','e','w','E','x','t','e','r','n','a','l','I','P','A','d','d','r','e','s','s' };
|
||||
// Array NOT including a terminating nul
|
||||
|
||||
// LogInfo("handleLNTGetExternalAddressResponse: %s", ptr);
|
||||
|
||||
mDNSs16 http_result = ParseHTTPResponseCode(&ptr, end); // Note: modifies ptr
|
||||
if (http_result == HTTPCode_404) LNT_ClearState(m);
|
||||
if (http_result != HTTPCode_200)
|
||||
{
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.AddressRequest", "noop", "HTTP Result", "HTTP code: %d", http_result);
|
||||
return;
|
||||
}
|
||||
|
||||
while (ptr < end && strncasecmp((char*)ptr, tagname, sizeof(tagname))) ptr++;
|
||||
ptr += sizeof(tagname); // Skip over "NewExternalIPAddress"
|
||||
while (ptr < end && *ptr != '>') ptr++;
|
||||
ptr += 1; // Skip over ">"
|
||||
|
||||
// Find the end of the address and terminate the string so inet_pton() can convert it
|
||||
// (Might be better to copy this to a local string here -- this is overwriting tcpInfo->Reply in-place
|
||||
addrend = (mDNSu8*)ptr;
|
||||
while (addrend < end && (mDNSIsDigit(*addrend) || *addrend == '.')) addrend++;
|
||||
if (addrend >= end) return;
|
||||
*addrend = 0;
|
||||
|
||||
if (inet_pton(AF_INET, (char*)ptr, &ExtAddr) <= 0)
|
||||
{
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.AddressRequest", "noop", "inet_pton", "");
|
||||
LogMsg("handleLNTGetExternalAddressResponse: Router returned bad address %s", ptr);
|
||||
err = NATErr_NetFail;
|
||||
ExtAddr = zerov4Addr;
|
||||
}
|
||||
if (!err) LogInfo("handleLNTGetExternalAddressResponse: External IP address is %.4a", &ExtAddr);
|
||||
|
||||
natTraversalHandleAddressReply(m, err, ExtAddr);
|
||||
}
|
||||
|
||||
mDNSlocal void handleLNTPortMappingResponse(tcpLNTInfo *tcpInfo)
|
||||
{
|
||||
mDNS *m = tcpInfo->m;
|
||||
mDNSIPPort extport = zeroIPPort;
|
||||
const mDNSu8 *ptr = tcpInfo->Reply;
|
||||
const mDNSu8 *const end = tcpInfo->Reply + tcpInfo->nread;
|
||||
NATTraversalInfo *natInfo;
|
||||
mDNSs16 http_result;
|
||||
|
||||
for (natInfo = m->NATTraversals; natInfo; natInfo=natInfo->next) { if (natInfo == tcpInfo->parentNATInfo) break; }
|
||||
|
||||
if (!natInfo) { LogInfo("handleLNTPortMappingResponse: can't find matching tcpInfo in NATTraversals!"); return; }
|
||||
|
||||
http_result = ParseHTTPResponseCode(&ptr, end); // Note: modifies ptr
|
||||
if (http_result == HTTPCode_200)
|
||||
{
|
||||
LogInfo("handleLNTPortMappingResponse: got a valid response, sending reply to natTraversalHandlePortMapReply(internal %d external %d retries %d)",
|
||||
mDNSVal16(natInfo->IntPort), RequestedPortNum(natInfo), tcpInfo->retries);
|
||||
|
||||
// Make sure to compute extport *before* we zero tcpInfo->retries
|
||||
extport = mDNSOpaque16fromIntVal(RequestedPortNum(natInfo));
|
||||
tcpInfo->retries = 0;
|
||||
natTraversalHandlePortMapReply(m, natInfo, m->UPnPInterfaceID, mStatus_NoError, extport, NATMAP_DEFAULT_LEASE);
|
||||
}
|
||||
else if (http_result == HTTPCode_500)
|
||||
{
|
||||
while (ptr && ptr != end)
|
||||
{
|
||||
if (((*ptr & 0xDF) == 'C' && end - ptr >= 8 && strncasecmp((char*)ptr, "Conflict", 8) == 0) ||
|
||||
(*ptr == '>' && end - ptr >= 15 && strncasecmp((char*)ptr, ">718</errorCode", 15) == 0))
|
||||
{
|
||||
if (tcpInfo->retries < 100)
|
||||
{
|
||||
tcpInfo->retries++; SendPortMapRequest(tcpInfo->m, natInfo);
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", "noop", "Conflict", "Retry %d", tcpInfo->retries);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMsg("handleLNTPortMappingResponse too many conflict retries %d %d", mDNSVal16(natInfo->IntPort), mDNSVal16(natInfo->RequestedPort));
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", "noop", "Conflict - too many retries", "Retries: %d", tcpInfo->retries);
|
||||
natTraversalHandlePortMapReply(m, natInfo, m->UPnPInterfaceID, NATErr_Res, zeroIPPort, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
else if (http_result == HTTPCode_Bad) LogMsg("handleLNTPortMappingResponse got data that was not a valid HTTP response");
|
||||
else if (http_result == HTTPCode_Other) LogMsg("handleLNTPortMappingResponse got unexpected response code");
|
||||
else if (http_result == HTTPCode_404) LNT_ClearState(m);
|
||||
if (http_result != HTTPCode_200 && http_result != HTTPCode_500)
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", "noop", "HTTP Result", "HTTP code: %d", http_result);
|
||||
}
|
||||
|
||||
mDNSlocal void DisposeInfoFromUnmapList(mDNS *m, tcpLNTInfo *tcpInfo)
|
||||
{
|
||||
tcpLNTInfo **ptr = &m->tcpInfoUnmapList;
|
||||
while (*ptr && *ptr != tcpInfo) ptr = &(*ptr)->next;
|
||||
if (*ptr) { *ptr = (*ptr)->next; mDNSPlatformMemFree(tcpInfo); } // If we found it, cut it from our list and free the memory
|
||||
}
|
||||
|
||||
mDNSlocal void tcpConnectionCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err)
|
||||
{
|
||||
mStatus status = mStatus_NoError;
|
||||
tcpLNTInfo *tcpInfo = (tcpLNTInfo *)context;
|
||||
mDNSBool closed = mDNSfalse;
|
||||
long n = 0;
|
||||
long nsent = 0;
|
||||
|
||||
if (tcpInfo == mDNSNULL) { LogInfo("tcpConnectionCallback: no tcpInfo context"); status = mStatus_Invalid; goto exit; }
|
||||
|
||||
// The handlers below expect to be called with the lock held
|
||||
mDNS_Lock(tcpInfo->m);
|
||||
|
||||
if (err) { LogInfo("tcpConnectionCallback: received error"); goto exit; }
|
||||
|
||||
if (ConnectionEstablished) // connection is established - send the message
|
||||
{
|
||||
LogInfo("tcpConnectionCallback: connection established, sending message");
|
||||
nsent = mDNSPlatformWriteTCP(sock, (char*)tcpInfo->Request, tcpInfo->requestLen);
|
||||
if (nsent != (long)tcpInfo->requestLen) { LogMsg("tcpConnectionCallback: error writing"); status = mStatus_UnknownErr; goto exit; }
|
||||
}
|
||||
else
|
||||
{
|
||||
n = mDNSPlatformReadTCP(sock, (char*)tcpInfo->Reply + tcpInfo->nread, tcpInfo->replyLen - tcpInfo->nread, &closed);
|
||||
LogInfo("tcpConnectionCallback: mDNSPlatformReadTCP read %d bytes", n);
|
||||
|
||||
if (n < 0) { LogInfo("tcpConnectionCallback - read returned %d", n); status = mStatus_ConnFailed; goto exit; }
|
||||
else if (closed) { LogInfo("tcpConnectionCallback: socket closed by remote end %d", tcpInfo->nread); status = mStatus_ConnFailed; goto exit; }
|
||||
|
||||
tcpInfo->nread += n;
|
||||
LogInfo("tcpConnectionCallback tcpInfo->nread %d", tcpInfo->nread);
|
||||
if (tcpInfo->nread > LNT_MAXBUFSIZE)
|
||||
{
|
||||
LogInfo("result truncated...");
|
||||
tcpInfo->nread = LNT_MAXBUFSIZE;
|
||||
}
|
||||
|
||||
switch (tcpInfo->op)
|
||||
{
|
||||
case LNTDiscoveryOp: handleLNTDeviceDescriptionResponse (tcpInfo); break;
|
||||
case LNTExternalAddrOp: handleLNTGetExternalAddressResponse(tcpInfo); break;
|
||||
case LNTPortMapOp: handleLNTPortMappingResponse (tcpInfo); break;
|
||||
case LNTPortMapDeleteOp: status = mStatus_ConfigChanged; break;
|
||||
default: LogMsg("tcpConnectionCallback: bad tcp operation! %d", tcpInfo->op); status = mStatus_Invalid; break;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
if (err || status)
|
||||
{
|
||||
mDNS *m = tcpInfo->m;
|
||||
switch (tcpInfo->op)
|
||||
{
|
||||
case LNTDiscoveryOp: if (m->UPnPSOAPAddressString == mDNSNULL)
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "failure", "SOAP Address", "");
|
||||
if (m->UPnPSOAPURL == mDNSNULL)
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "failure", "SOAP path", "");
|
||||
if (m->UPnPSOAPAddressString && m->UPnPSOAPURL)
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "success", "success", "");
|
||||
break;
|
||||
case LNTExternalAddrOp: mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.AddressRequest",
|
||||
mDNSIPv4AddressIsZero(m->ExternalAddress) ? "failure" : "success",
|
||||
mDNSIPv4AddressIsZero(m->ExternalAddress) ? "failure" : "success", "");
|
||||
break;
|
||||
case LNTPortMapOp: if (tcpInfo->parentNATInfo)
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", (tcpInfo->parentNATInfo->Result) ? "failure" : "success",
|
||||
(tcpInfo->parentNATInfo->Result) ? "failure" : "success", "Result: %d", tcpInfo->parentNATInfo->Result);
|
||||
break;
|
||||
case LNTPortMapDeleteOp: break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
mDNSPlatformTCPCloseConnection(tcpInfo->sock);
|
||||
tcpInfo->sock = mDNSNULL;
|
||||
if (tcpInfo->Request) { mDNSPlatformMemFree(tcpInfo->Request); tcpInfo->Request = mDNSNULL; }
|
||||
if (tcpInfo->Reply ) { mDNSPlatformMemFree(tcpInfo->Reply); tcpInfo->Reply = mDNSNULL; }
|
||||
}
|
||||
|
||||
if (tcpInfo) mDNS_Unlock(tcpInfo->m);
|
||||
|
||||
if (status == mStatus_ConfigChanged) DisposeInfoFromUnmapList(tcpInfo->m, tcpInfo);
|
||||
}
|
||||
|
||||
mDNSlocal mStatus MakeTCPConnection(mDNS *const m, tcpLNTInfo *info, const mDNSAddr *const Addr, const mDNSIPPort Port, LNTOp_t op)
|
||||
{
|
||||
mStatus err = mStatus_NoError;
|
||||
mDNSIPPort srcport = zeroIPPort;
|
||||
|
||||
if (mDNSIPv4AddressIsZero(Addr->ip.v4) || mDNSIPPortIsZero(Port))
|
||||
{ LogMsg("LNT MakeTCPConnection: bad address/port %#a:%d", Addr, mDNSVal16(Port)); return(mStatus_Invalid); }
|
||||
info->m = m;
|
||||
info->Address = *Addr;
|
||||
info->Port = Port;
|
||||
info->op = op;
|
||||
info->nread = 0;
|
||||
info->replyLen = LNT_MAXBUFSIZE;
|
||||
if (info->Reply != mDNSNULL) mDNSPlatformMemZero(info->Reply, LNT_MAXBUFSIZE); // reuse previously allocated buffer
|
||||
else if ((info->Reply = mDNSPlatformMemAllocate(LNT_MAXBUFSIZE)) == mDNSNULL) { LogInfo("can't allocate reply buffer"); return (mStatus_NoMemoryErr); }
|
||||
|
||||
if (info->sock) { LogInfo("MakeTCPConnection: closing previous open connection"); mDNSPlatformTCPCloseConnection(info->sock); info->sock = mDNSNULL; }
|
||||
info->sock = mDNSPlatformTCPSocket(m, kTCPSocketFlags_Zero, &srcport);
|
||||
if (!info->sock) { LogMsg("LNT MakeTCPConnection: unable to create TCP socket"); mDNSPlatformMemFree(info->Reply); info->Reply = mDNSNULL; return(mStatus_NoMemoryErr); }
|
||||
LogInfo("MakeTCPConnection: connecting to %#a:%d", &info->Address, mDNSVal16(info->Port));
|
||||
err = mDNSPlatformTCPConnect(info->sock, Addr, Port, mDNSNULL, 0, tcpConnectionCallback, info);
|
||||
|
||||
if (err == mStatus_ConnPending) err = mStatus_NoError;
|
||||
else if (err == mStatus_ConnEstablished)
|
||||
{
|
||||
mDNS_DropLockBeforeCallback();
|
||||
tcpConnectionCallback(info->sock, info, mDNStrue, mStatus_NoError);
|
||||
mDNS_ReclaimLockAfterCallback();
|
||||
err = mStatus_NoError;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't need to log this in customer builds -- it happens quite often during sleep, wake, configuration changes, etc.
|
||||
LogInfo("LNT MakeTCPConnection: connection failed");
|
||||
mDNSPlatformTCPCloseConnection(info->sock); // Dispose the socket we created with mDNSPlatformTCPSocket() above
|
||||
info->sock = mDNSNULL;
|
||||
mDNSPlatformMemFree(info->Reply);
|
||||
info->Reply = mDNSNULL;
|
||||
}
|
||||
return(err);
|
||||
}
|
||||
|
||||
mDNSlocal unsigned int AddSOAPArguments(char *const buf, const unsigned int maxlen, const int numArgs, const Property *const a)
|
||||
{
|
||||
static const char f1[] = "<%s>%s</%s>";
|
||||
static const char f2[] = "<%s xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"%s\">%s</%s>";
|
||||
int i, len = 0;
|
||||
*buf = 0;
|
||||
for (i = 0; i < numArgs; i++)
|
||||
{
|
||||
if (a[i].type) len += mDNS_snprintf(buf + len, maxlen - len, f2, a[i].name, a[i].type, a[i].value, a[i].name);
|
||||
else len += mDNS_snprintf(buf + len, maxlen - len, f1, a[i].name, a[i].value, a[i].name);
|
||||
}
|
||||
return(len);
|
||||
}
|
||||
|
||||
mDNSlocal mStatus SendSOAPMsgControlAction(mDNS *m, tcpLNTInfo *info, const char *const Action, const int numArgs, const Property *const Arguments, const LNTOp_t op)
|
||||
{
|
||||
// SOAP message header format -
|
||||
// - control URL
|
||||
// - action (string)
|
||||
// - router's host/port ("host:port")
|
||||
// - content-length
|
||||
static const char header[] =
|
||||
"POST %s HTTP/1.1\r\n"
|
||||
"Content-Type: text/xml; charset=\"utf-8\"\r\n"
|
||||
"SOAPAction: \"urn:schemas-upnp-org:service:WAN%sConnection:1#%s\"\r\n"
|
||||
"User-Agent: Mozilla/4.0 (compatible; UPnP/1.0; Windows 9x)\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Pragma: no-cache\r\n"
|
||||
"\r\n"
|
||||
"%s\r\n";
|
||||
|
||||
static const char body1[] =
|
||||
"<?xml version=\"1.0\"?>\r\n"
|
||||
"<SOAP-ENV:Envelope"
|
||||
" xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\""
|
||||
" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
"<SOAP-ENV:Body>"
|
||||
"<m:%s xmlns:m=\"urn:schemas-upnp-org:service:WAN%sConnection:1\">";
|
||||
|
||||
static const char body2[] =
|
||||
"</m:%s>"
|
||||
"</SOAP-ENV:Body>"
|
||||
"</SOAP-ENV:Envelope>\r\n";
|
||||
|
||||
mStatus err;
|
||||
char *body = (char*)&m->omsg; // Typically requires 1110-1122 bytes; m->omsg is 8952 bytes, which is plenty
|
||||
int bodyLen;
|
||||
|
||||
if (mDNSIPPortIsZero(m->UPnPSOAPPort) || m->UPnPSOAPURL == mDNSNULL || m->UPnPSOAPAddressString == mDNSNULL) // if no SOAP URL or address exists get out here
|
||||
{ LogInfo("SendSOAPMsgControlAction: no SOAP port, URL or address string"); return mStatus_Invalid; }
|
||||
|
||||
// Create body
|
||||
bodyLen = mDNS_snprintf (body, sizeof(m->omsg), body1, Action, m->UPnPWANPPPConnection ? "PPP" : "IP");
|
||||
bodyLen += AddSOAPArguments(body + bodyLen, sizeof(m->omsg) - bodyLen, numArgs, Arguments);
|
||||
bodyLen += mDNS_snprintf (body + bodyLen, sizeof(m->omsg) - bodyLen, body2, Action);
|
||||
|
||||
// Create info->Request; the header needs to contain the bodyLen in the "Content-Length" field
|
||||
if (!info->Request) info->Request = mDNSPlatformMemAllocate(LNT_MAXBUFSIZE);
|
||||
if (!info->Request) { LogMsg("SendSOAPMsgControlAction: Can't allocate info->Request"); return mStatus_NoMemoryErr; }
|
||||
info->requestLen = mDNS_snprintf((char*)info->Request, LNT_MAXBUFSIZE, header, m->UPnPSOAPURL, m->UPnPWANPPPConnection ? "PPP" : "IP", Action, m->UPnPSOAPAddressString, bodyLen, body);
|
||||
|
||||
err = MakeTCPConnection(m, info, &m->Router, m->UPnPSOAPPort, op);
|
||||
if (err) { mDNSPlatformMemFree(info->Request); info->Request = mDNSNULL; }
|
||||
return err;
|
||||
}
|
||||
|
||||
// Build port mapping request with new port (up to max) and send it
|
||||
mDNSlocal mStatus SendPortMapRequest(mDNS *m, NATTraversalInfo *n)
|
||||
{
|
||||
char externalPort[6];
|
||||
char internalPort[6];
|
||||
char localIPAddrString[30];
|
||||
char publicPortString[40];
|
||||
Property propArgs[8];
|
||||
mDNSu16 ReqPortNum = RequestedPortNum(n);
|
||||
NATTraversalInfo *n2 = m->NATTraversals;
|
||||
|
||||
// Scan our m->NATTraversals list to make sure the external port we're requesting is locally unique.
|
||||
// UPnP gateways will report conflicts if different devices request the same external port, but if two
|
||||
// clients on the same device request the same external port the second one just stomps over the first.
|
||||
// One way this can happen is like this:
|
||||
// 1. Client A binds local port 80
|
||||
// 2. Client A requests external port 80 -> internal port 80
|
||||
// 3. UPnP NAT gateway refuses external port 80 (some other client already has it)
|
||||
// 4. Client A tries again, and successfully gets external port 80 -> internal port 81
|
||||
// 5. Client B on same machine tries to bind local port 80, and fails
|
||||
// 6. Client B tries again, and successfully binds local port 81
|
||||
// 7. Client B now requests external port 81 -> internal port 81
|
||||
// 8. UPnP NAT gateway allows this, stomping over Client A's existing mapping
|
||||
|
||||
while (n2)
|
||||
{
|
||||
if (n2 == n || RequestedPortNum(n2) != ReqPortNum) n2=n2->next;
|
||||
else
|
||||
{
|
||||
if (n->tcpInfo.retries < 100)
|
||||
{
|
||||
n->tcpInfo.retries++;
|
||||
ReqPortNum = RequestedPortNum(n); // Pick a new port number
|
||||
n2 = m->NATTraversals; // And re-scan the list looking for conflicts
|
||||
}
|
||||
else
|
||||
{
|
||||
natTraversalHandlePortMapReply(m, n, m->UPnPInterfaceID, NATErr_Res, zeroIPPort, 0);
|
||||
return mStatus_NoError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create strings to use in the message
|
||||
mDNS_snprintf(externalPort, sizeof(externalPort), "%u", ReqPortNum);
|
||||
mDNS_snprintf(internalPort, sizeof(internalPort), "%u", mDNSVal16(n->IntPort));
|
||||
mDNS_snprintf(publicPortString, sizeof(publicPortString), "iC%u", ReqPortNum);
|
||||
mDNS_snprintf(localIPAddrString, sizeof(localIPAddrString), "%u.%u.%u.%u",
|
||||
m->AdvertisedV4.ip.v4.b[0], m->AdvertisedV4.ip.v4.b[1], m->AdvertisedV4.ip.v4.b[2], m->AdvertisedV4.ip.v4.b[3]);
|
||||
|
||||
// build the message
|
||||
mDNSPlatformMemZero(propArgs, sizeof(propArgs));
|
||||
propArgs[0].name = "NewRemoteHost";
|
||||
propArgs[0].type = "string";
|
||||
propArgs[0].value = "";
|
||||
propArgs[1].name = "NewExternalPort";
|
||||
propArgs[1].type = "ui2";
|
||||
propArgs[1].value = externalPort;
|
||||
propArgs[2].name = "NewProtocol";
|
||||
propArgs[2].type = "string";
|
||||
propArgs[2].value = (n->Protocol == NATOp_MapUDP) ? "UDP" : "TCP";
|
||||
propArgs[3].name = "NewInternalPort";
|
||||
propArgs[3].type = "ui2";
|
||||
propArgs[3].value = internalPort;
|
||||
propArgs[4].name = "NewInternalClient";
|
||||
propArgs[4].type = "string";
|
||||
propArgs[4].value = localIPAddrString;
|
||||
propArgs[5].name = "NewEnabled";
|
||||
propArgs[5].type = "boolean";
|
||||
propArgs[5].value = "1";
|
||||
propArgs[6].name = "NewPortMappingDescription";
|
||||
propArgs[6].type = "string";
|
||||
propArgs[6].value = publicPortString;
|
||||
propArgs[7].name = "NewLeaseDuration";
|
||||
propArgs[7].type = "ui4";
|
||||
propArgs[7].value = "0";
|
||||
|
||||
LogInfo("SendPortMapRequest: internal %u external %u", mDNSVal16(n->IntPort), ReqPortNum);
|
||||
return SendSOAPMsgControlAction(m, &n->tcpInfo, "AddPortMapping", 8, propArgs, LNTPortMapOp);
|
||||
}
|
||||
|
||||
mDNSexport mStatus LNT_MapPort(mDNS *m, NATTraversalInfo *const n)
|
||||
{
|
||||
LogInfo("LNT_MapPort");
|
||||
if (n->tcpInfo.sock) return(mStatus_NoError); // If we already have a connection up don't make another request for the same thing
|
||||
n->tcpInfo.parentNATInfo = n;
|
||||
n->tcpInfo.retries = 0;
|
||||
return SendPortMapRequest(m, n);
|
||||
}
|
||||
|
||||
mDNSexport mStatus LNT_UnmapPort(mDNS *m, NATTraversalInfo *const n)
|
||||
{
|
||||
char externalPort[10];
|
||||
Property propArgs[3];
|
||||
tcpLNTInfo *info;
|
||||
tcpLNTInfo **infoPtr = &m->tcpInfoUnmapList;
|
||||
mStatus err;
|
||||
|
||||
// If no NAT gateway to talk to, no need to do all this work for nothing
|
||||
if (mDNSIPPortIsZero(m->UPnPSOAPPort) || !m->UPnPSOAPURL || !m->UPnPSOAPAddressString) return mStatus_NoError;
|
||||
|
||||
mDNS_snprintf(externalPort, sizeof(externalPort), "%u", mDNSVal16(mDNSIPPortIsZero(n->RequestedPort) ? n->IntPort : n->RequestedPort));
|
||||
|
||||
mDNSPlatformMemZero(propArgs, sizeof(propArgs));
|
||||
propArgs[0].name = "NewRemoteHost";
|
||||
propArgs[0].type = "string";
|
||||
propArgs[0].value = "";
|
||||
propArgs[1].name = "NewExternalPort";
|
||||
propArgs[1].type = "ui2";
|
||||
propArgs[1].value = externalPort;
|
||||
propArgs[2].name = "NewProtocol";
|
||||
propArgs[2].type = "string";
|
||||
propArgs[2].value = (n->Protocol == NATOp_MapUDP) ? "UDP" : "TCP";
|
||||
|
||||
n->tcpInfo.parentNATInfo = n;
|
||||
|
||||
// clean up previous port mapping requests and allocations
|
||||
if (n->tcpInfo.sock) LogInfo("LNT_UnmapPort: closing previous open connection");
|
||||
if (n->tcpInfo.sock ) { mDNSPlatformTCPCloseConnection(n->tcpInfo.sock); n->tcpInfo.sock = mDNSNULL; }
|
||||
if (n->tcpInfo.Request) { mDNSPlatformMemFree(n->tcpInfo.Request); n->tcpInfo.Request = mDNSNULL; }
|
||||
if (n->tcpInfo.Reply ) { mDNSPlatformMemFree(n->tcpInfo.Reply); n->tcpInfo.Reply = mDNSNULL; }
|
||||
|
||||
// make a copy of the tcpInfo that we can clean up later (the one passed in will be destroyed by the client as soon as this returns)
|
||||
if ((info = mDNSPlatformMemAllocate(sizeof(tcpLNTInfo))) == mDNSNULL)
|
||||
{ LogInfo("LNT_UnmapPort: can't allocate tcpInfo"); return(mStatus_NoMemoryErr); }
|
||||
*info = n->tcpInfo;
|
||||
|
||||
while (*infoPtr) infoPtr = &(*infoPtr)->next; // find the end of the list
|
||||
*infoPtr = info; // append
|
||||
|
||||
err = SendSOAPMsgControlAction(m, info, "DeletePortMapping", 3, propArgs, LNTPortMapDeleteOp);
|
||||
if (err) DisposeInfoFromUnmapList(m, info);
|
||||
return err;
|
||||
}
|
||||
|
||||
mDNSexport mStatus LNT_GetExternalAddress(mDNS *m)
|
||||
{
|
||||
return SendSOAPMsgControlAction(m, &m->tcpAddrInfo, "GetExternalIPAddress", 0, mDNSNULL, LNTExternalAddrOp);
|
||||
}
|
||||
|
||||
mDNSlocal mStatus GetDeviceDescription(mDNS *m, tcpLNTInfo *info)
|
||||
{
|
||||
// Device description format -
|
||||
// - device description URL
|
||||
// - host/port
|
||||
static const char szSSDPMsgDescribeDeviceFMT[] =
|
||||
"GET %s HTTP/1.1\r\n"
|
||||
"Accept: text/xml, application/xml\r\n"
|
||||
"User-Agent: Mozilla/4.0 (compatible; UPnP/1.0; Windows NT/5.1)\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n";
|
||||
|
||||
if (!mDNSIPPortIsZero(m->UPnPSOAPPort)) return mStatus_NoError; // already have the info we need
|
||||
|
||||
if (m->UPnPRouterURL == mDNSNULL || m->UPnPRouterAddressString == mDNSNULL) { LogInfo("GetDeviceDescription: no router URL or address string!"); return (mStatus_Invalid); }
|
||||
|
||||
// build message
|
||||
if (info->Request != mDNSNULL) mDNSPlatformMemZero(info->Request, LNT_MAXBUFSIZE); // reuse previously allocated buffer
|
||||
else if ((info->Request = mDNSPlatformMemAllocate(LNT_MAXBUFSIZE)) == mDNSNULL) { LogInfo("can't allocate send buffer for discovery"); return (mStatus_NoMemoryErr); }
|
||||
info->requestLen = mDNS_snprintf((char*)info->Request, LNT_MAXBUFSIZE, szSSDPMsgDescribeDeviceFMT, m->UPnPRouterURL, m->UPnPRouterAddressString);
|
||||
LogInfo("Describe Device: [%s]", info->Request);
|
||||
return MakeTCPConnection(m, info, &m->Router, m->UPnPRouterPort, LNTDiscoveryOp);
|
||||
}
|
||||
|
||||
// This function parses the response to our SSDP discovery message. Basically, we look to make sure this is a response
|
||||
// referencing a service we care about (WANIPConnection or WANPPPConnection), then look for the "Location:" header and copy the addressing and
|
||||
// URL info we need.
|
||||
mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID InterfaceID, const mDNSu8 *const data, const mDNSu16 len)
|
||||
{
|
||||
const mDNSu8 *ptr = data;
|
||||
const mDNSu8 *end = data + len;
|
||||
const mDNSu8 *stop = ptr;
|
||||
|
||||
if (!mDNSIPPortIsZero(m->UPnPRouterPort)) return; // already have the info we need
|
||||
|
||||
// The formatting of the HTTP header is not always the same when it comes to the placement of
|
||||
// the service and location strings, so we just look for each of them from the beginning for every response
|
||||
|
||||
// figure out if this is a message from a service we care about
|
||||
while (ptr && ptr != end)
|
||||
{
|
||||
if ((*ptr & 0xDF) == 'W' && (strncasecmp((char*)ptr, "WANIPConnection:1", 17) == 0)) break;
|
||||
ptr++;
|
||||
}
|
||||
if (ptr == end)
|
||||
{
|
||||
ptr = data;
|
||||
while (ptr && ptr != end)
|
||||
{
|
||||
if ((*ptr & 0xDF) == 'W' && (strncasecmp((char*)ptr, "WANPPPConnection:1", 18) == 0)) break;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
if (ptr == mDNSNULL || ptr == end) return; // not a message we care about
|
||||
|
||||
// find "Location:", starting from the beginning
|
||||
ptr = data;
|
||||
while (ptr && ptr != end)
|
||||
{
|
||||
if ((*ptr & 0xDF) == 'L' && (strncasecmp((char*)ptr, "Location:", 9) == 0)) break; // find the first 'L'; is this Location? if not, keep looking
|
||||
ptr++;
|
||||
}
|
||||
if (ptr == mDNSNULL || ptr == end)
|
||||
{
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Location", "");
|
||||
return; // not a message we care about
|
||||
}
|
||||
ptr += 9; //Skip over 'Location:'
|
||||
while (*ptr == ' ' && ptr < end) ptr++; // skip over spaces
|
||||
if (ptr >= end) return;
|
||||
|
||||
// find the end of the line
|
||||
for (stop = ptr; stop != end; stop++) { if (*stop == '\r') { end = stop; break; } }
|
||||
|
||||
// fill in default port
|
||||
m->UPnPRouterPort = mDNSOpaque16fromIntVal(80);
|
||||
|
||||
// free string pointers and set to NULL
|
||||
if (m->UPnPRouterAddressString != mDNSNULL)
|
||||
{
|
||||
mDNSPlatformMemFree(m->UPnPRouterAddressString);
|
||||
m->UPnPRouterAddressString = mDNSNULL;
|
||||
}
|
||||
if (m->UPnPRouterURL != mDNSNULL)
|
||||
{
|
||||
mDNSPlatformMemFree(m->UPnPRouterURL);
|
||||
m->UPnPRouterURL = mDNSNULL;
|
||||
}
|
||||
|
||||
// the Router URL should look something like "/dyndev/uuid:0013-108c-4b3f0000f3dc"
|
||||
if (ParseHttpUrl(ptr, end, &m->UPnPRouterAddressString, &m->UPnPRouterPort, &m->UPnPRouterURL) != mStatus_NoError)
|
||||
{
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Parse URL", "");
|
||||
return;
|
||||
}
|
||||
|
||||
m->UPnPInterfaceID = InterfaceID;
|
||||
|
||||
if (m->UPnPRouterAddressString == mDNSNULL)
|
||||
{
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Router address", "");
|
||||
LogMsg("LNT_ConfigureRouterInfo: UPnPRouterAddressString is NULL");
|
||||
}
|
||||
else LogInfo("LNT_ConfigureRouterInfo: Router address string [%s]", m->UPnPRouterAddressString);
|
||||
|
||||
if (m->UPnPRouterURL == mDNSNULL)
|
||||
{
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Router path", "");
|
||||
LogMsg("LNT_ConfigureRouterInfo: UPnPRouterURL is NULL");
|
||||
}
|
||||
else LogInfo("LNT_ConfigureRouterInfo: Router URL [%s]", m->UPnPRouterURL);
|
||||
|
||||
LogInfo("LNT_ConfigureRouterInfo: Router port %d", mDNSVal16(m->UPnPRouterPort));
|
||||
LogInfo("LNT_ConfigureRouterInfo: Router interface %d", m->UPnPInterfaceID);
|
||||
|
||||
// Don't need the SSDP socket anymore
|
||||
if (m->SSDPSocket) { debugf("LNT_ConfigureRouterInfo destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
|
||||
|
||||
mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "success", "success", "");
|
||||
// now send message to get the device description
|
||||
GetDeviceDescription(m, &m->tcpDeviceInfo);
|
||||
}
|
||||
|
||||
mDNSexport void LNT_SendDiscoveryMsg(mDNS *m)
|
||||
{
|
||||
static const char msg[] =
|
||||
"M-SEARCH * HTTP/1.1\r\n"
|
||||
"Host:239.255.255.250:1900\r\n"
|
||||
"ST:urn:schemas-upnp-org:service:WAN%sConnection:1\r\n"
|
||||
"Man:\"ssdp:discover\"\r\n"
|
||||
"MX:3\r\n\r\n";
|
||||
static const mDNSAddr multicastDest = { mDNSAddrType_IPv4, { { { 239, 255, 255, 250 } } } };
|
||||
|
||||
mDNSu8 *buf = (mDNSu8*)&m->omsg; //m->omsg is 8952 bytes, which is plenty
|
||||
unsigned int bufLen;
|
||||
|
||||
if (!mDNSIPPortIsZero(m->UPnPRouterPort))
|
||||
{
|
||||
if (m->SSDPSocket) { debugf("LNT_SendDiscoveryMsg destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
|
||||
if (mDNSIPPortIsZero(m->UPnPSOAPPort) && !m->tcpDeviceInfo.sock) GetDeviceDescription(m, &m->tcpDeviceInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
// Always query for WANIPConnection in the first SSDP packet
|
||||
if (m->retryIntervalGetAddr <= NATMAP_INIT_RETRY) m->SSDPWANPPPConnection = mDNSfalse;
|
||||
|
||||
// Create message
|
||||
bufLen = mDNS_snprintf((char*)buf, sizeof(m->omsg), msg, m->SSDPWANPPPConnection ? "PPP" : "IP");
|
||||
|
||||
debugf("LNT_SendDiscoveryMsg Router %.4a Current External Address %.4a", &m->Router.ip.v4, &m->ExternalAddress);
|
||||
|
||||
if (!mDNSIPv4AddressIsZero(m->Router.ip.v4))
|
||||
{
|
||||
if (!m->SSDPSocket) { m->SSDPSocket = mDNSPlatformUDPSocket(m, zeroIPPort); debugf("LNT_SendDiscoveryMsg created SSDPSocket %p", &m->SSDPSocket); }
|
||||
mDNSPlatformSendUDP(m, buf, buf + bufLen, 0, m->SSDPSocket, &m->Router, SSDPPort);
|
||||
mDNSPlatformSendUDP(m, buf, buf + bufLen, 0, m->SSDPSocket, &multicastDest, SSDPPort);
|
||||
}
|
||||
|
||||
m->SSDPWANPPPConnection = !m->SSDPWANPPPConnection;
|
||||
}
|
||||
|
||||
mDNSexport void LNT_ClearState(mDNS *const m)
|
||||
{
|
||||
if (m->tcpAddrInfo.sock) { mDNSPlatformTCPCloseConnection(m->tcpAddrInfo.sock); m->tcpAddrInfo.sock = mDNSNULL; }
|
||||
if (m->tcpDeviceInfo.sock) { mDNSPlatformTCPCloseConnection(m->tcpDeviceInfo.sock); m->tcpDeviceInfo.sock = mDNSNULL; }
|
||||
m->UPnPSOAPPort = m->UPnPRouterPort = zeroIPPort; // Reset UPnP ports
|
||||
}
|
||||
|
||||
#endif /* _LEGACY_NAT_TRAVERSAL_ */
|
@@ -1,196 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h> // Needed for fopen() etc.
|
||||
#include <unistd.h> // Needed for close()
|
||||
#include <string.h> // Needed for strlen() etc.
|
||||
#include <errno.h> // Needed for errno etc.
|
||||
#include <sys/socket.h> // Needed for socket() etc.
|
||||
#include <netinet/in.h> // Needed for sockaddr_in
|
||||
#include <syslog.h>
|
||||
|
||||
#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
|
||||
#include "DNSCommon.h"
|
||||
#include "PlatformCommon.h"
|
||||
|
||||
#ifdef NOT_HAVE_SOCKLEN_T
|
||||
typedef unsigned int socklen_t;
|
||||
#endif
|
||||
|
||||
// Bind a UDP socket to find the source address to a destination
|
||||
mDNSexport void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst)
|
||||
{
|
||||
union { struct sockaddr s; struct sockaddr_in a4; struct sockaddr_in6 a6; } addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
socklen_t inner_len = 0;
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
src->type = mDNSAddrType_None;
|
||||
if (sock == -1) return;
|
||||
if (dst->type == mDNSAddrType_IPv4)
|
||||
{
|
||||
inner_len = sizeof(addr.a4);
|
||||
#ifndef NOT_HAVE_SA_LEN
|
||||
addr.a4.sin_len = inner_len;
|
||||
#endif
|
||||
addr.a4.sin_family = AF_INET;
|
||||
addr.a4.sin_port = 1; // Not important, any port will do
|
||||
addr.a4.sin_addr.s_addr = dst->ip.v4.NotAnInteger;
|
||||
}
|
||||
else if (dst->type == mDNSAddrType_IPv6)
|
||||
{
|
||||
inner_len = sizeof(addr.a6);
|
||||
#ifndef NOT_HAVE_SA_LEN
|
||||
addr.a6.sin6_len = inner_len;
|
||||
#endif
|
||||
addr.a6.sin6_family = AF_INET6;
|
||||
addr.a6.sin6_flowinfo = 0;
|
||||
addr.a6.sin6_port = 1; // Not important, any port will do
|
||||
addr.a6.sin6_addr = *(struct in6_addr*)&dst->ip.v6;
|
||||
addr.a6.sin6_scope_id = 0;
|
||||
}
|
||||
else return;
|
||||
|
||||
if ((connect(sock, &addr.s, inner_len)) < 0)
|
||||
{ LogMsg("mDNSPlatformSourceAddrForDest: connect %#a failed errno %d (%s)", dst, errno, strerror(errno)); goto exit; }
|
||||
|
||||
if ((getsockname(sock, &addr.s, &len)) < 0)
|
||||
{ LogMsg("mDNSPlatformSourceAddrForDest: getsockname failed errno %d (%s)", errno, strerror(errno)); goto exit; }
|
||||
|
||||
src->type = dst->type;
|
||||
if (dst->type == mDNSAddrType_IPv4) src->ip.v4.NotAnInteger = addr.a4.sin_addr.s_addr;
|
||||
else src->ip.v6 = *(mDNSv6Addr*)&addr.a6.sin6_addr;
|
||||
exit:
|
||||
close(sock);
|
||||
}
|
||||
|
||||
// dst must be at least MAX_ESCAPED_DOMAIN_NAME bytes, and option must be less than 32 bytes in length
|
||||
mDNSlocal mDNSBool GetConfigOption(char *dst, const char *option, FILE *f)
|
||||
{
|
||||
char buf[32+1+MAX_ESCAPED_DOMAIN_NAME]; // Option name, one space, option value
|
||||
unsigned int len = strlen(option);
|
||||
if (len + 1 + MAX_ESCAPED_DOMAIN_NAME > sizeof(buf)-1) { LogMsg("GetConfigOption: option %s too long", option); return mDNSfalse; }
|
||||
fseek(f, 0, SEEK_SET); // set position to beginning of stream
|
||||
while (fgets(buf, sizeof(buf), f)) // Read at most sizeof(buf)-1 bytes from file, and append '\0' C-string terminator
|
||||
{
|
||||
if (!strncmp(buf, option, len))
|
||||
{
|
||||
strncpy(dst, buf + len + 1, MAX_ESCAPED_DOMAIN_NAME-1);
|
||||
if (dst[MAX_ESCAPED_DOMAIN_NAME-1]) dst[MAX_ESCAPED_DOMAIN_NAME-1] = '\0';
|
||||
len = strlen(dst);
|
||||
if (len && dst[len-1] == '\n') dst[len-1] = '\0'; // chop newline
|
||||
return mDNStrue;
|
||||
}
|
||||
}
|
||||
debugf("Option %s not set", option);
|
||||
return mDNSfalse;
|
||||
}
|
||||
|
||||
mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled)
|
||||
{
|
||||
char buf[MAX_ESCAPED_DOMAIN_NAME] = "";
|
||||
mStatus err;
|
||||
FILE *f = fopen(filename, "r");
|
||||
|
||||
if (hostname) hostname->c[0] = 0;
|
||||
if (domain) domain->c[0] = 0;
|
||||
if (DomainDiscoveryDisabled) *DomainDiscoveryDisabled = mDNSfalse;
|
||||
|
||||
if (f)
|
||||
{
|
||||
if (DomainDiscoveryDisabled && GetConfigOption(buf, "DomainDiscoveryDisabled", f) && !strcasecmp(buf, "true")) *DomainDiscoveryDisabled = mDNStrue;
|
||||
if (hostname && GetConfigOption(buf, "hostname", f) && !MakeDomainNameFromDNSNameString(hostname, buf)) goto badf;
|
||||
if (domain && GetConfigOption(buf, "zone", f) && !MakeDomainNameFromDNSNameString(domain, buf)) goto badf;
|
||||
buf[0] = 0;
|
||||
GetConfigOption(buf, "secret-64", f); // failure means no authentication
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (errno != ENOENT) LogMsg("ERROR: Config file exists, but cannot be opened.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (domain && domain->c[0] && buf[0])
|
||||
{
|
||||
DomainAuthInfo *info = (DomainAuthInfo*)mDNSPlatformMemAllocate(sizeof(*info));
|
||||
// for now we assume keyname = service reg domain and we use same key for service and hostname registration
|
||||
err = mDNS_SetSecretForDomain(m, info, domain, domain, buf, NULL, 0, NULL);
|
||||
if (err) LogMsg("ERROR: mDNS_SetSecretForDomain returned %d for domain %##s", err, domain->c);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
badf:
|
||||
LogMsg("ERROR: malformatted config file");
|
||||
if (f) fclose(f);
|
||||
}
|
||||
|
||||
#if MDNS_DEBUGMSGS
|
||||
mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
|
||||
{
|
||||
fprintf(stderr,"%s\n", msg);
|
||||
fflush(stderr);
|
||||
}
|
||||
#endif
|
||||
|
||||
mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, mDNSLogLevel_t loglevel)
|
||||
{
|
||||
#if APPLE_OSX_mDNSResponder && LogTimeStamps
|
||||
extern mDNS mDNSStorage;
|
||||
extern mDNSu32 mDNSPlatformClockDivisor;
|
||||
mDNSs32 t = mDNSStorage.timenow ? mDNSStorage.timenow : mDNSPlatformClockDivisor ? mDNS_TimeNow_NoLock(&mDNSStorage) : 0;
|
||||
int ms = ((t < 0) ? -t : t) % 1000;
|
||||
#endif
|
||||
|
||||
if (mDNS_DebugMode) // In debug mode we write to stderr
|
||||
{
|
||||
#if APPLE_OSX_mDNSResponder && LogTimeStamps
|
||||
if (ident && ident[0] && mDNSPlatformClockDivisor)
|
||||
fprintf(stderr,"%8d.%03d: %s\n", (int)(t/1000), ms, buffer);
|
||||
else
|
||||
#endif
|
||||
fprintf(stderr,"%s\n", buffer);
|
||||
fflush(stderr);
|
||||
}
|
||||
else // else, in production mode, we write to syslog
|
||||
{
|
||||
static int log_inited = 0;
|
||||
|
||||
int syslog_level = LOG_ERR;
|
||||
switch (loglevel)
|
||||
{
|
||||
case MDNS_LOG_MSG: syslog_level = LOG_ERR; break;
|
||||
case MDNS_LOG_OPERATION: syslog_level = LOG_WARNING; break;
|
||||
case MDNS_LOG_SPS: syslog_level = LOG_NOTICE; break;
|
||||
case MDNS_LOG_INFO: syslog_level = LOG_INFO; break;
|
||||
case MDNS_LOG_DEBUG: syslog_level = LOG_DEBUG; break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
if (!log_inited) { openlog(ident, LOG_CONS, LOG_DAEMON); log_inited++; }
|
||||
|
||||
#if APPLE_OSX_mDNSResponder && LogTimeStamps
|
||||
if (ident && ident[0] && mDNSPlatformClockDivisor)
|
||||
syslog(syslog_level, "%8d.%03d: %s", (int)(t/1000), ms, buffer);
|
||||
else
|
||||
#endif
|
||||
syslog(syslog_level, "%s", buffer);
|
||||
}
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
extern void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled);
|
@@ -1,728 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Poll.h"
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include "GenLinkedList.h"
|
||||
#include "DebugServices.h"
|
||||
|
||||
|
||||
typedef struct PollSource_struct
|
||||
{
|
||||
SOCKET socket;
|
||||
HANDLE handle;
|
||||
void *context;
|
||||
|
||||
union
|
||||
{
|
||||
mDNSPollSocketCallback socket;
|
||||
mDNSPollEventCallback event;
|
||||
} callback;
|
||||
|
||||
struct Worker_struct *worker;
|
||||
struct PollSource_struct *next;
|
||||
|
||||
} PollSource;
|
||||
|
||||
|
||||
typedef struct Worker_struct
|
||||
{
|
||||
HANDLE thread; // NULL for main worker
|
||||
unsigned id; // 0 for main worker
|
||||
|
||||
HANDLE start; // NULL for main worker
|
||||
HANDLE stop; // NULL for main worker
|
||||
BOOL done; // Not used for main worker
|
||||
|
||||
DWORD numSources;
|
||||
PollSource *sources[ MAXIMUM_WAIT_OBJECTS ];
|
||||
HANDLE handles[ MAXIMUM_WAIT_OBJECTS ];
|
||||
DWORD result;
|
||||
struct Worker_struct *next;
|
||||
} Worker;
|
||||
|
||||
|
||||
typedef struct Poll_struct
|
||||
{
|
||||
mDNSBool setup;
|
||||
HANDLE wakeup;
|
||||
GenLinkedList sources;
|
||||
DWORD numSources;
|
||||
Worker main;
|
||||
GenLinkedList workers;
|
||||
HANDLE workerHandles[ MAXIMUM_WAIT_OBJECTS ];
|
||||
DWORD numWorkers;
|
||||
|
||||
} Poll;
|
||||
|
||||
|
||||
/*
|
||||
* Poll Methods
|
||||
*/
|
||||
|
||||
mDNSlocal mStatus PollSetup();
|
||||
mDNSlocal mStatus PollRegisterSource( PollSource *source );
|
||||
mDNSlocal void PollUnregisterSource( PollSource *source );
|
||||
mDNSlocal mStatus PollStartWorkers();
|
||||
mDNSlocal mStatus PollStopWorkers();
|
||||
mDNSlocal void PollRemoveWorker( Worker *worker );
|
||||
|
||||
|
||||
/*
|
||||
* Worker Methods
|
||||
*/
|
||||
|
||||
mDNSlocal mStatus WorkerInit( Worker *worker );
|
||||
mDNSlocal void WorkerFree( Worker *worker );
|
||||
mDNSlocal void WorkerRegisterSource( Worker *worker, PollSource *source );
|
||||
mDNSlocal int WorkerSourceToIndex( Worker *worker, PollSource *source );
|
||||
mDNSlocal void WorkerUnregisterSource( Worker *worker, PollSource *source );
|
||||
mDNSlocal void WorkerDispatch( Worker *worker);
|
||||
mDNSlocal void CALLBACK WorkerWakeupNotification( HANDLE event, void *context );
|
||||
mDNSlocal unsigned WINAPI WorkerMain( LPVOID inParam );
|
||||
|
||||
|
||||
static void
|
||||
ShiftDown( void * arr, size_t arraySize, size_t itemSize, int index )
|
||||
{
|
||||
memmove( ( ( unsigned char* ) arr ) + ( ( index - 1 ) * itemSize ), ( ( unsigned char* ) arr ) + ( index * itemSize ), ( arraySize - index ) * itemSize );
|
||||
}
|
||||
|
||||
|
||||
#define DEBUG_NAME "[mDNSWin32] "
|
||||
#define gMDNSRecord mDNSStorage
|
||||
mDNSlocal Poll gPoll = { mDNSfalse, NULL };
|
||||
|
||||
#define LogErr( err, FUNC ) LogMsg( "%s:%d - %s failed: %d\n", __FUNCTION__, __LINE__, FUNC, err );
|
||||
|
||||
|
||||
mStatus
|
||||
mDNSPollRegisterSocket( SOCKET socket, int networkEvents, mDNSPollSocketCallback callback, void *context )
|
||||
{
|
||||
PollSource *source = NULL;
|
||||
HANDLE event = INVALID_HANDLE_VALUE;
|
||||
mStatus err = mStatus_NoError;
|
||||
|
||||
if ( !gPoll.setup )
|
||||
{
|
||||
err = PollSetup();
|
||||
require_noerr( err, exit );
|
||||
}
|
||||
|
||||
source = malloc( sizeof( PollSource ) );
|
||||
require_action( source, exit, err = mStatus_NoMemoryErr );
|
||||
|
||||
event = WSACreateEvent();
|
||||
require_action( event, exit, err = mStatus_NoMemoryErr );
|
||||
|
||||
err = WSAEventSelect( socket, event, networkEvents );
|
||||
require_noerr( err, exit );
|
||||
|
||||
source->socket = socket;
|
||||
source->handle = event;
|
||||
source->callback.socket = callback;
|
||||
source->context = context;
|
||||
|
||||
err = PollRegisterSource( source );
|
||||
require_noerr( err, exit );
|
||||
|
||||
exit:
|
||||
|
||||
if ( err != mStatus_NoError )
|
||||
{
|
||||
if ( event != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
WSACloseEvent( event );
|
||||
}
|
||||
|
||||
if ( source != NULL )
|
||||
{
|
||||
free( source );
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mDNSPollUnregisterSocket( SOCKET socket )
|
||||
{
|
||||
PollSource *source;
|
||||
|
||||
for ( source = gPoll.sources.Head; source; source = source->next )
|
||||
{
|
||||
if ( source->socket == socket )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( source )
|
||||
{
|
||||
WSACloseEvent( source->handle );
|
||||
PollUnregisterSource( source );
|
||||
free( source );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mStatus
|
||||
mDNSPollRegisterEvent( HANDLE event, mDNSPollEventCallback callback, void *context )
|
||||
{
|
||||
PollSource *source = NULL;
|
||||
mStatus err = mStatus_NoError;
|
||||
|
||||
if ( !gPoll.setup )
|
||||
{
|
||||
err = PollSetup();
|
||||
require_noerr( err, exit );
|
||||
}
|
||||
|
||||
source = malloc( sizeof( PollSource ) );
|
||||
require_action( source, exit, err = mStatus_NoMemoryErr );
|
||||
|
||||
source->socket = INVALID_SOCKET;
|
||||
source->handle = event;
|
||||
source->callback.event = callback;
|
||||
source->context = context;
|
||||
|
||||
err = PollRegisterSource( source );
|
||||
require_noerr( err, exit );
|
||||
|
||||
exit:
|
||||
|
||||
if ( err != mStatus_NoError )
|
||||
{
|
||||
if ( source != NULL )
|
||||
{
|
||||
free( source );
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mDNSPollUnregisterEvent( HANDLE event )
|
||||
{
|
||||
PollSource *source;
|
||||
|
||||
for ( source = gPoll.sources.Head; source; source = source->next )
|
||||
{
|
||||
if ( source->handle == event )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( source )
|
||||
{
|
||||
PollUnregisterSource( source );
|
||||
free( source );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mStatus
|
||||
mDNSPoll( DWORD msec )
|
||||
{
|
||||
mStatus err = mStatus_NoError;
|
||||
|
||||
if ( gPoll.numWorkers > 0 )
|
||||
{
|
||||
err = PollStartWorkers();
|
||||
require_noerr( err, exit );
|
||||
}
|
||||
|
||||
gPoll.main.result = WaitForMultipleObjects( gPoll.main.numSources, gPoll.main.handles, FALSE, msec );
|
||||
err = translate_errno( ( gPoll.main.result != WAIT_FAILED ), ( mStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) LogErr( err, "WaitForMultipleObjects()" );
|
||||
require_action( gPoll.main.result != WAIT_FAILED, exit, err = ( mStatus ) GetLastError() );
|
||||
|
||||
if ( gPoll.numWorkers > 0 )
|
||||
{
|
||||
err = PollStopWorkers();
|
||||
require_noerr( err, exit );
|
||||
}
|
||||
|
||||
WorkerDispatch( &gPoll.main );
|
||||
|
||||
exit:
|
||||
|
||||
return ( err );
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal mStatus
|
||||
PollSetup()
|
||||
{
|
||||
mStatus err = mStatus_NoError;
|
||||
|
||||
if ( !gPoll.setup )
|
||||
{
|
||||
memset( &gPoll, 0, sizeof( gPoll ) );
|
||||
|
||||
InitLinkedList( &gPoll.sources, offsetof( PollSource, next ) );
|
||||
InitLinkedList( &gPoll.workers, offsetof( Worker, next ) );
|
||||
|
||||
gPoll.wakeup = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||||
require_action( gPoll.wakeup, exit, err = mStatus_NoMemoryErr );
|
||||
|
||||
err = WorkerInit( &gPoll.main );
|
||||
require_noerr( err, exit );
|
||||
|
||||
gPoll.setup = mDNStrue;
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal mStatus
|
||||
PollRegisterSource( PollSource *source )
|
||||
{
|
||||
Worker *worker = NULL;
|
||||
mStatus err = mStatus_NoError;
|
||||
|
||||
AddToTail( &gPoll.sources, source );
|
||||
gPoll.numSources++;
|
||||
|
||||
// First check our main worker. In most cases, we won't have to worry about threads
|
||||
|
||||
if ( gPoll.main.numSources < MAXIMUM_WAIT_OBJECTS )
|
||||
{
|
||||
WorkerRegisterSource( &gPoll.main, source );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to find a thread to use that we've already created
|
||||
|
||||
for ( worker = gPoll.workers.Head; worker; worker = worker->next )
|
||||
{
|
||||
if ( worker->numSources < MAXIMUM_WAIT_OBJECTS )
|
||||
{
|
||||
WorkerRegisterSource( worker, source );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If not, then create a worker and make a thread to run it in
|
||||
|
||||
if ( !worker )
|
||||
{
|
||||
worker = ( Worker* ) malloc( sizeof( Worker ) );
|
||||
require_action( worker, exit, err = mStatus_NoMemoryErr );
|
||||
|
||||
memset( worker, 0, sizeof( Worker ) );
|
||||
|
||||
worker->start = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||||
require_action( worker->start, exit, err = mStatus_NoMemoryErr );
|
||||
|
||||
worker->stop = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||||
require_action( worker->stop, exit, err = mStatus_NoMemoryErr );
|
||||
|
||||
err = WorkerInit( worker );
|
||||
require_noerr( err, exit );
|
||||
|
||||
// Create thread with _beginthreadex() instead of CreateThread() to avoid
|
||||
// memory leaks when using static run-time libraries.
|
||||
// See <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createthread.asp>.
|
||||
|
||||
worker->thread = ( HANDLE ) _beginthreadex_compat( NULL, 0, WorkerMain, worker, 0, &worker->id );
|
||||
err = translate_errno( worker->thread, ( mStatus ) GetLastError(), kUnknownErr );
|
||||
require_noerr( err, exit );
|
||||
|
||||
AddToTail( &gPoll.workers, worker );
|
||||
gPoll.workerHandles[ gPoll.numWorkers++ ] = worker->stop;
|
||||
|
||||
WorkerRegisterSource( worker, source );
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if ( err && worker )
|
||||
{
|
||||
WorkerFree( worker );
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal void
|
||||
PollUnregisterSource( PollSource *source )
|
||||
{
|
||||
RemoveFromList( &gPoll.sources, source );
|
||||
gPoll.numSources--;
|
||||
|
||||
WorkerUnregisterSource( source->worker, source );
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal mStatus
|
||||
PollStartWorkers()
|
||||
{
|
||||
Worker *worker;
|
||||
mStatus err = mStatus_NoError;
|
||||
BOOL ok;
|
||||
|
||||
dlog( kDebugLevelChatty, DEBUG_NAME "starting workers\n" );
|
||||
|
||||
worker = gPoll.workers.Head;
|
||||
|
||||
while ( worker )
|
||||
{
|
||||
Worker *next = worker->next;
|
||||
|
||||
if ( worker->numSources == 1 )
|
||||
{
|
||||
PollRemoveWorker( worker );
|
||||
}
|
||||
else
|
||||
{
|
||||
dlog( kDebugLevelChatty, DEBUG_NAME "waking up worker\n" );
|
||||
|
||||
ok = SetEvent( worker->start );
|
||||
err = translate_errno( ok, ( mStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) LogErr( err, "SetEvent()" );
|
||||
|
||||
if ( err )
|
||||
{
|
||||
PollRemoveWorker( worker );
|
||||
}
|
||||
}
|
||||
|
||||
worker = next;
|
||||
}
|
||||
|
||||
err = mStatus_NoError;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal mStatus
|
||||
PollStopWorkers()
|
||||
{
|
||||
DWORD result;
|
||||
Worker *worker;
|
||||
BOOL ok;
|
||||
mStatus err = mStatus_NoError;
|
||||
|
||||
dlog( kDebugLevelChatty, DEBUG_NAME "stopping workers\n" );
|
||||
|
||||
ok = SetEvent( gPoll.wakeup );
|
||||
err = translate_errno( ok, ( mStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) LogErr( err, "SetEvent()" );
|
||||
|
||||
// Wait For 5 seconds for all the workers to wake up
|
||||
|
||||
result = WaitForMultipleObjects( gPoll.numWorkers, gPoll.workerHandles, TRUE, 5000 );
|
||||
err = translate_errno( ( result != WAIT_FAILED ), ( mStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) LogErr( err, "WaitForMultipleObjects()" );
|
||||
|
||||
ok = ResetEvent( gPoll.wakeup );
|
||||
err = translate_errno( ok, ( mStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) LogErr( err, "ResetEvent()" );
|
||||
|
||||
for ( worker = gPoll.workers.Head; worker; worker = worker->next )
|
||||
{
|
||||
WorkerDispatch( worker );
|
||||
}
|
||||
|
||||
err = mStatus_NoError;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal void
|
||||
PollRemoveWorker( Worker *worker )
|
||||
{
|
||||
DWORD result;
|
||||
mStatus err;
|
||||
BOOL ok;
|
||||
DWORD i;
|
||||
|
||||
dlog( kDebugLevelChatty, DEBUG_NAME "removing worker %d\n", worker->id );
|
||||
|
||||
RemoveFromList( &gPoll.workers, worker );
|
||||
|
||||
// Remove handle from gPoll.workerHandles
|
||||
|
||||
for ( i = 0; i < gPoll.numWorkers; i++ )
|
||||
{
|
||||
if ( gPoll.workerHandles[ i ] == worker->stop )
|
||||
{
|
||||
ShiftDown( gPoll.workerHandles, gPoll.numWorkers, sizeof( gPoll.workerHandles[ 0 ] ), i + 1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
worker->done = TRUE;
|
||||
gPoll.numWorkers--;
|
||||
|
||||
// Cause the thread to exit.
|
||||
|
||||
ok = SetEvent( worker->start );
|
||||
err = translate_errno( ok, ( OSStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) LogErr( err, "SetEvent()" );
|
||||
|
||||
result = WaitForSingleObject( worker->thread, 5000 );
|
||||
err = translate_errno( result != WAIT_FAILED, ( OSStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) LogErr( err, "WaitForSingleObject()" );
|
||||
|
||||
if ( ( result == WAIT_FAILED ) || ( result == WAIT_TIMEOUT ) )
|
||||
{
|
||||
ok = TerminateThread( worker->thread, 0 );
|
||||
err = translate_errno( ok, ( OSStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) LogErr( err, "TerminateThread()" );
|
||||
}
|
||||
|
||||
CloseHandle( worker->thread );
|
||||
worker->thread = NULL;
|
||||
|
||||
WorkerFree( worker );
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal void
|
||||
WorkerRegisterSource( Worker *worker, PollSource *source )
|
||||
{
|
||||
source->worker = worker;
|
||||
worker->sources[ worker->numSources ] = source;
|
||||
worker->handles[ worker->numSources ] = source->handle;
|
||||
worker->numSources++;
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal int
|
||||
WorkerSourceToIndex( Worker *worker, PollSource *source )
|
||||
{
|
||||
int index;
|
||||
|
||||
for ( index = 0; index < ( int ) worker->numSources; index++ )
|
||||
{
|
||||
if ( worker->sources[ index ] == source )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( index == ( int ) worker->numSources )
|
||||
{
|
||||
index = -1;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal void
|
||||
WorkerUnregisterSource( Worker *worker, PollSource *source )
|
||||
{
|
||||
int sourceIndex = WorkerSourceToIndex( worker, source );
|
||||
DWORD delta;
|
||||
|
||||
if ( sourceIndex == -1 )
|
||||
{
|
||||
LogMsg( "WorkerUnregisterSource: source not found in list" );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
delta = ( worker->numSources - sourceIndex - 1 );
|
||||
|
||||
// If this source is not at the end of the list, then move memory
|
||||
|
||||
if ( delta > 0 )
|
||||
{
|
||||
ShiftDown( worker->sources, worker->numSources, sizeof( worker->sources[ 0 ] ), sourceIndex + 1 );
|
||||
ShiftDown( worker->handles, worker->numSources, sizeof( worker->handles[ 0 ] ), sourceIndex + 1 );
|
||||
}
|
||||
|
||||
worker->numSources--;
|
||||
|
||||
exit:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal void CALLBACK
|
||||
WorkerWakeupNotification( HANDLE event, void *context )
|
||||
{
|
||||
DEBUG_UNUSED( event );
|
||||
DEBUG_UNUSED( context );
|
||||
|
||||
dlog( kDebugLevelChatty, DEBUG_NAME "Worker thread wakeup\n" );
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal void
|
||||
WorkerDispatch( Worker *worker )
|
||||
{
|
||||
if ( worker->result == WAIT_FAILED )
|
||||
{
|
||||
/* What should we do here? */
|
||||
}
|
||||
else if ( worker->result == WAIT_TIMEOUT )
|
||||
{
|
||||
dlog( kDebugLevelChatty, DEBUG_NAME "timeout\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD waitItemIndex = ( DWORD )( ( ( int ) worker->result ) - WAIT_OBJECT_0 );
|
||||
PollSource *source = NULL;
|
||||
|
||||
// Sanity check
|
||||
|
||||
if ( waitItemIndex >= worker->numSources )
|
||||
{
|
||||
LogMsg( "WorkerDispatch: waitItemIndex (%d) is >= numSources (%d)", waitItemIndex, worker->numSources );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
source = worker->sources[ waitItemIndex ];
|
||||
|
||||
if ( source->socket != INVALID_SOCKET )
|
||||
{
|
||||
WSANETWORKEVENTS event;
|
||||
|
||||
if ( WSAEnumNetworkEvents( source->socket, source->handle, &event ) == 0 )
|
||||
{
|
||||
source->callback.socket( source->socket, &event, source->context );
|
||||
}
|
||||
else
|
||||
{
|
||||
source->callback.socket( source->socket, NULL, source->context );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
source->callback.event( source->handle, source->context );
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal mStatus
|
||||
WorkerInit( Worker *worker )
|
||||
{
|
||||
PollSource *source = NULL;
|
||||
mStatus err = mStatus_NoError;
|
||||
|
||||
require_action( worker, exit, err = mStatus_BadParamErr );
|
||||
|
||||
source = malloc( sizeof( PollSource ) );
|
||||
require_action( source, exit, err = mStatus_NoMemoryErr );
|
||||
|
||||
source->socket = INVALID_SOCKET;
|
||||
source->handle = gPoll.wakeup;
|
||||
source->callback.event = WorkerWakeupNotification;
|
||||
source->context = NULL;
|
||||
|
||||
WorkerRegisterSource( worker, source );
|
||||
|
||||
exit:
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal void
|
||||
WorkerFree( Worker *worker )
|
||||
{
|
||||
if ( worker->start )
|
||||
{
|
||||
CloseHandle( worker->start );
|
||||
worker->start = NULL;
|
||||
}
|
||||
|
||||
if ( worker->stop )
|
||||
{
|
||||
CloseHandle( worker->stop );
|
||||
worker->stop = NULL;
|
||||
}
|
||||
|
||||
free( worker );
|
||||
}
|
||||
|
||||
|
||||
mDNSlocal unsigned WINAPI
|
||||
WorkerMain( LPVOID inParam )
|
||||
{
|
||||
Worker *worker = ( Worker* ) inParam;
|
||||
mStatus err = mStatus_NoError;
|
||||
|
||||
require_action( worker, exit, err = mStatus_BadParamErr );
|
||||
|
||||
dlog( kDebugLevelVerbose, DEBUG_NAME, "entering WorkerMain()\n" );
|
||||
|
||||
while ( TRUE )
|
||||
{
|
||||
DWORD result;
|
||||
BOOL ok;
|
||||
|
||||
dlog( kDebugLevelChatty, DEBUG_NAME, "worker thread %d will wait on main loop\n", worker->id );
|
||||
|
||||
result = WaitForSingleObject( worker->start, INFINITE );
|
||||
err = translate_errno( ( result != WAIT_FAILED ), ( mStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) { LogErr( err, "WaitForSingleObject()" ); break; }
|
||||
if ( worker->done ) break;
|
||||
|
||||
dlog( kDebugLevelChatty, DEBUG_NAME "worker thread %d will wait on sockets\n", worker->id );
|
||||
|
||||
worker->result = WaitForMultipleObjects( worker->numSources, worker->handles, FALSE, INFINITE );
|
||||
err = translate_errno( ( worker->result != WAIT_FAILED ), ( mStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) { LogErr( err, "WaitForMultipleObjects()" ); break; }
|
||||
|
||||
dlog( kDebugLevelChatty, DEBUG_NAME "worker thread %d did wait on sockets: %d\n", worker->id, worker->result );
|
||||
|
||||
ok = SetEvent( gPoll.wakeup );
|
||||
err = translate_errno( ok, ( mStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) { LogErr( err, "SetEvent()" ); break; }
|
||||
|
||||
dlog( kDebugLevelChatty, DEBUG_NAME, "worker thread %d preparing to sleep\n", worker->id );
|
||||
|
||||
ok = SetEvent( worker->stop );
|
||||
err = translate_errno( ok, ( mStatus ) GetLastError(), kUnknownErr );
|
||||
if ( err ) { LogErr( err, "SetEvent()" ); break; }
|
||||
}
|
||||
|
||||
dlog( kDebugLevelVerbose, DEBUG_NAME "exiting WorkerMain()\n" );
|
||||
|
||||
exit:
|
||||
|
||||
return 0;
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _Poll_h
|
||||
#define _Poll_h
|
||||
|
||||
#include "CommonServices.h"
|
||||
#include <mswsock.h>
|
||||
#include "mDNSEmbeddedAPI.h"
|
||||
#include "uDNS.h"
|
||||
|
||||
|
||||
#if defined(__cplusplus )
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef void ( CALLBACK *mDNSPollSocketCallback )( SOCKET socket, LPWSANETWORKEVENTS event, void *context );
|
||||
typedef void ( CALLBACK *mDNSPollEventCallback )( HANDLE event, void *context );
|
||||
|
||||
|
||||
extern mStatus
|
||||
mDNSPollRegisterSocket( SOCKET socket, int networkEvents, mDNSPollSocketCallback callback, void *context );
|
||||
|
||||
|
||||
extern void
|
||||
mDNSPollUnregisterSocket( SOCKET socket );
|
||||
|
||||
|
||||
extern mStatus
|
||||
mDNSPollRegisterEvent( HANDLE event, mDNSPollEventCallback callback, void *context );
|
||||
|
||||
|
||||
extern void
|
||||
mDNSPollUnregisterEvent( HANDLE event );
|
||||
|
||||
|
||||
extern mStatus
|
||||
mDNSPoll( DWORD msec );
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@@ -1,386 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
File: daemon.c
|
||||
|
||||
Contains: main & associated Application layer for mDNSResponder on Linux.
|
||||
|
||||
*/
|
||||
|
||||
#if __APPLE__
|
||||
// In Mac OS X 10.5 and later trying to use the daemon function gives a "'daemon' is deprecated"
|
||||
// error, which prevents compilation because we build with "-Werror".
|
||||
// Since this is supposed to be portable cross-platform code, we don't care that daemon is
|
||||
// deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
|
||||
#define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#if __APPLE__
|
||||
#undef daemon
|
||||
extern int daemon(int, int);
|
||||
#endif
|
||||
|
||||
#include "mDNSEmbeddedAPI.h"
|
||||
#include "mDNSPosix.h"
|
||||
#include "mDNSUNP.h" // For daemon()
|
||||
#include "uds_daemon.h"
|
||||
#include "PlatformCommon.h"
|
||||
|
||||
#define CONFIG_FILE "/etc/mdnsd.conf"
|
||||
static domainname DynDNSZone; // Default wide-area zone for service registration
|
||||
static domainname DynDNSHostname;
|
||||
|
||||
#define RR_CACHE_SIZE 500
|
||||
static CacheEntity gRRCache[RR_CACHE_SIZE];
|
||||
static mDNS_PlatformSupport PlatformStorage;
|
||||
|
||||
mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
|
||||
{
|
||||
(void)m; // Unused
|
||||
if (result == mStatus_NoError)
|
||||
{
|
||||
// On successful registration of dot-local mDNS host name, daemon may want to check if
|
||||
// any name conflict and automatic renaming took place, and if so, record the newly negotiated
|
||||
// name in persistent storage for next time. It should also inform the user of the name change.
|
||||
// On Mac OS X we store the current dot-local mDNS host name in the SCPreferences store,
|
||||
// and notify the user with a CFUserNotification.
|
||||
}
|
||||
else if (result == mStatus_ConfigChanged)
|
||||
{
|
||||
udsserver_handle_configchange(m);
|
||||
}
|
||||
else if (result == mStatus_GrowCache)
|
||||
{
|
||||
// Allocate another chunk of cache storage
|
||||
CacheEntity *storage = malloc(sizeof(CacheEntity) * RR_CACHE_SIZE);
|
||||
if (storage) mDNS_GrowCache(m, storage, RR_CACHE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
// %%% Reconfigure() probably belongs in the platform support layer (mDNSPosix.c), not the daemon cde
|
||||
// -- all client layers running on top of mDNSPosix.c need to handle network configuration changes,
|
||||
// not only the Unix Domain Socket Daemon
|
||||
|
||||
static void Reconfigure(mDNS *m)
|
||||
{
|
||||
mDNSAddr DynDNSIP;
|
||||
const mDNSAddr dummy = { mDNSAddrType_IPv4, { { { 1, 1, 1, 1 } } } };;
|
||||
mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
|
||||
if (ParseDNSServers(m, uDNS_SERVERS_FILE) < 0)
|
||||
LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
|
||||
ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &DynDNSHostname, &DynDNSZone, NULL);
|
||||
mDNSPlatformSourceAddrForDest(&DynDNSIP, &dummy);
|
||||
if (DynDNSHostname.c[0]) mDNS_AddDynDNSHostName(m, &DynDNSHostname, NULL, NULL);
|
||||
if (DynDNSIP.type) mDNS_SetPrimaryInterfaceInfo(m, &DynDNSIP, NULL, NULL);
|
||||
mDNS_ConfigChanged(m);
|
||||
}
|
||||
|
||||
// Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
|
||||
mDNSlocal void ParseCmdLinArgs(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
if (0 == strcmp(argv[1], "-debug")) {
|
||||
mDNS_DebugMode = mDNStrue;
|
||||
stderr = fopen("/tmp/mdnssd.log", "w");
|
||||
stdout = stderr;
|
||||
}
|
||||
else printf("Usage: %s [-debug]\n", argv[0]);
|
||||
}
|
||||
|
||||
if (!mDNS_DebugMode)
|
||||
{
|
||||
int result = daemon(0, 0);
|
||||
if (result != 0) { LogMsg("Could not run as daemon - exiting"); exit(result); }
|
||||
#if __APPLE__
|
||||
LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
|
||||
exit(-1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
mDNSlocal void DumpStateLog(mDNS *const m)
|
||||
// Dump a little log of what we've been up to.
|
||||
{
|
||||
LogMsg("---- BEGIN STATE LOG ----");
|
||||
udsserver_info(m);
|
||||
LogMsg("---- END STATE LOG ----");
|
||||
}
|
||||
|
||||
mDNSlocal mStatus MainLoop(mDNS *m) // Loop until we quit.
|
||||
{
|
||||
sigset_t signals;
|
||||
mDNSBool gotData = mDNSfalse;
|
||||
|
||||
mDNSPosixListenForSignalInEventLoop(SIGINT);
|
||||
mDNSPosixListenForSignalInEventLoop(SIGTERM);
|
||||
mDNSPosixListenForSignalInEventLoop(SIGUSR1);
|
||||
mDNSPosixListenForSignalInEventLoop(SIGPIPE);
|
||||
mDNSPosixListenForSignalInEventLoop(SIGHUP) ;
|
||||
|
||||
for (; ;)
|
||||
{
|
||||
// Work out how long we expect to sleep before the next scheduled task
|
||||
struct timeval timeout;
|
||||
mDNSs32 ticks;
|
||||
|
||||
// Only idle if we didn't find any data the last time around
|
||||
if (!gotData)
|
||||
{
|
||||
mDNSs32 nextTimerEvent = mDNS_Execute(m);
|
||||
nextTimerEvent = udsserver_idle(nextTimerEvent);
|
||||
ticks = nextTimerEvent - mDNS_TimeNow(m);
|
||||
if (ticks < 1) ticks = 1;
|
||||
}
|
||||
else // otherwise call EventLoop again with 0 timemout
|
||||
ticks = 0;
|
||||
|
||||
timeout.tv_sec = ticks / mDNSPlatformOneSecond;
|
||||
timeout.tv_usec = (ticks % mDNSPlatformOneSecond) * 1000000 / mDNSPlatformOneSecond;
|
||||
|
||||
(void) mDNSPosixRunEventLoopOnce(m, &timeout, &signals, &gotData);
|
||||
|
||||
if (sigismember(&signals, SIGHUP )) Reconfigure(m);
|
||||
if (sigismember(&signals, SIGUSR1)) DumpStateLog(m);
|
||||
// SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
|
||||
if (sigismember(&signals, SIGPIPE)) LogMsg("Received SIGPIPE - ignoring");
|
||||
if (sigismember(&signals, SIGINT) || sigismember(&signals, SIGTERM)) break;
|
||||
}
|
||||
return EINTR;
|
||||
}
|
||||
|
||||
|
||||
static int kill_other()
|
||||
{
|
||||
// tries to kill other mdnssd instances
|
||||
enum { maxPath = 1024 };
|
||||
mStatus res = 0;
|
||||
const char * dirPath = "/proc";
|
||||
DIR *dirp;
|
||||
struct dirent *next;
|
||||
char filePath[maxPath];
|
||||
char *baseN = filePath;
|
||||
size_t maxName = maxPath;
|
||||
const char *dAtt = dirPath;
|
||||
pid_t myPid = getpid();
|
||||
char refPath[128];
|
||||
char refLine[128];
|
||||
char line[128];
|
||||
|
||||
snprintf(refPath, sizeof(refPath), "/proc/%lu/status",(unsigned long)myPid);
|
||||
FILE *f = fopen(refPath, "r");
|
||||
if (!f)
|
||||
{
|
||||
LogMsg("mdnssd kill_other failed to get ref line");
|
||||
return 1;
|
||||
}
|
||||
if (!fgets(refLine,sizeof(refLine),f)) {
|
||||
LogMsg("mdnssd kill_other got empty ref line");
|
||||
return 2;
|
||||
}
|
||||
if (strncmp("Name:", refLine, 5)) {
|
||||
LogMsg("mdnssd unexpected format of first line of /proc/*/status");
|
||||
return 4;
|
||||
}
|
||||
fclose(f);
|
||||
for (; maxName != 0; --maxName)
|
||||
{
|
||||
if ((*dAtt) == 0)
|
||||
break;
|
||||
*baseN++ = *dAtt++;
|
||||
}
|
||||
if (maxName>0)
|
||||
{
|
||||
--maxName;
|
||||
*baseN++ = '/';
|
||||
}
|
||||
const char *statusFile = "/status";
|
||||
size_t lenStatusFile = strlen(statusFile);
|
||||
maxName -= lenStatusFile;
|
||||
|
||||
dirp = opendir (dirPath);
|
||||
if (!dirp)
|
||||
{
|
||||
LogMsg("cannot open directory %s", dirPath);
|
||||
return 3;
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
size_t lenF;
|
||||
errno = 0;
|
||||
next = readdir (dirp);
|
||||
if (!next)
|
||||
{
|
||||
if (errno == EOVERFLOW)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (errno != 0)
|
||||
{
|
||||
char errStr[128];
|
||||
LogMsg("Error reading /proc directory, %s",strerror_r(errno, errStr, sizeof(errStr)));
|
||||
res=3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (next->d_type)
|
||||
{
|
||||
case DT_LNK:
|
||||
case DT_DIR:
|
||||
lenF=strlen(next->d_name);
|
||||
if (lenF < maxName)
|
||||
{
|
||||
char *endP = 0;
|
||||
unsigned long pidV = strtoul(next->d_name, &endP , 10);
|
||||
if ((size_t)(endP - next->d_name) == lenF)
|
||||
{
|
||||
pid_t pidAtt = (pid_t)pidV;
|
||||
if (pidAtt != myPid)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < lenF; ++ i)
|
||||
baseN[i] = next->d_name[i];
|
||||
for (i = 0; i <= lenStatusFile; ++i)
|
||||
baseN[i + lenF] = statusFile[i];
|
||||
f = fopen(filePath,"r");
|
||||
if (f)
|
||||
{
|
||||
if (fgets(line,sizeof(line),f) && strcmp(refLine, line) == 0)
|
||||
{
|
||||
LogMsg("killing old mdnssd process with pid %d\n", pidAtt);
|
||||
kill(pidAtt, 9);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (closedir (dirp) != 0)
|
||||
LogMsg("error closing directory %s", dirPath);
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
mStatus err;
|
||||
|
||||
kill_other();
|
||||
|
||||
ParseCmdLinArgs(argc, argv);
|
||||
|
||||
LogMsg("%s starting", mDNSResponderVersionString);
|
||||
|
||||
err = mDNS_Init(&mDNSStorage, &PlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses,
|
||||
mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext);
|
||||
|
||||
if (mStatus_NoError == err)
|
||||
err = udsserver_init(mDNSNULL, 0);
|
||||
|
||||
Reconfigure(&mDNSStorage);
|
||||
|
||||
// Now that we're finished with anything privileged, switch over to running as "nobody"
|
||||
if (mStatus_NoError == err)
|
||||
{
|
||||
const struct passwd *pw = getpwnam("nobody");
|
||||
if (pw != NULL)
|
||||
setuid(pw->pw_uid);
|
||||
else
|
||||
LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
|
||||
}
|
||||
|
||||
if (mStatus_NoError == err)
|
||||
err = MainLoop(&mDNSStorage);
|
||||
|
||||
LogMsg("%s stopping", mDNSResponderVersionString);
|
||||
|
||||
mDNS_Close(&mDNSStorage);
|
||||
|
||||
if (udsserver_exit() < 0)
|
||||
LogMsg("ExitCallback: udsserver_exit failed");
|
||||
|
||||
#if MDNS_DEBUGMSGS > 0
|
||||
printf("mDNSResponder exiting normally with %ld\n", err);
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
// uds_daemon support ////////////////////////////////////////////////////////////
|
||||
|
||||
mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context, void **platform_data)
|
||||
/* Support routine for uds_daemon.c */
|
||||
{
|
||||
// Depends on the fact that udsEventCallback == mDNSPosixEventCallback
|
||||
(void) platform_data;
|
||||
return mDNSPosixAddFDToEventLoop(fd, callback, context);
|
||||
}
|
||||
|
||||
int udsSupportReadFD(dnssd_sock_t fd, char *buf, int len, int flags, void *platform_data)
|
||||
{
|
||||
(void) platform_data;
|
||||
return recv(fd, buf, len, flags);
|
||||
}
|
||||
|
||||
mStatus udsSupportRemoveFDFromEventLoop(int fd, void *platform_data) // Note: This also CLOSES the file descriptor
|
||||
{
|
||||
mStatus err = mDNSPosixRemoveFDFromEventLoop(fd);
|
||||
(void) platform_data;
|
||||
close(fd);
|
||||
return err;
|
||||
}
|
||||
|
||||
mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
|
||||
{
|
||||
(void)m;
|
||||
(void)delay;
|
||||
// No-op, for now
|
||||
}
|
||||
|
||||
#if _BUILDING_XCODE_PROJECT_
|
||||
// If the process crashes, then this string will be magically included in the automatically-generated crash log
|
||||
const char *__crashreporter_info__ = mDNSResponderVersionString_SCCS + 5;
|
||||
asm(".desc ___crashreporter_info__, 0x10");
|
||||
#endif
|
||||
|
||||
// For convenience when using the "strings" command, this is the last thing in the file
|
||||
#if mDNSResponderVersion > 1
|
||||
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder-" STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
|
||||
#elif MDNS_VERSIONSTR_NODTS
|
||||
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder (Engineering Build)";
|
||||
#else
|
||||
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder (Engineering Build) (" __DATE__ " " __TIME__ ")";
|
||||
#endif
|
@@ -1,57 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// Registry Constants
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
#if defined(UNICODE)
|
||||
|
||||
# define kServiceParametersSoftware L"SOFTWARE"
|
||||
# define kServiceParametersAppleComputer L"Apple Computer, Inc."
|
||||
# define kServiceParametersBonjour L"BonjourFallback"
|
||||
# define kServiceParametersNode L"SOFTWARE\\Nokia\\Bonjour"
|
||||
# define kServiceName L"Bonjour Service"
|
||||
# define kServiceDynDNSBrowseDomains L"BrowseDomains"
|
||||
# define kServiceDynDNSHostNames L"HostNames"
|
||||
# define kServiceDynDNSRegistrationDomains L"RegistrationDomains"
|
||||
# define kServiceDynDNSDomains L"Domains" // value is comma separated list of domains
|
||||
# define kServiceDynDNSEnabled L"Enabled"
|
||||
# define kServiceDynDNSStatus L"Status"
|
||||
# define kServiceManageLLRouting L"ManageLLRouting"
|
||||
# define kServiceCacheEntryCount L"CacheEntryCount"
|
||||
# define kServiceManageFirewall L"ManageFirewall"
|
||||
# define kServiceAdvertisedServices L"Services"
|
||||
|
||||
# else
|
||||
|
||||
# define kServiceParametersSoftware "SOFTWARE"
|
||||
# define kServiceParametersAppleComputer "Apple Computer, Inc."
|
||||
# define kServiceParametersBonjour "BonjourFallback"
|
||||
# define kServiceParametersNode "SOFTWARE\\Nokia\\Bonjour"
|
||||
# define kServiceName "Bonjour Service"
|
||||
# define kServiceDynDNSBrowseDomains "BrowseDomains"
|
||||
# define kServiceDynDNSHostNames "HostNames"
|
||||
# define kServiceDynDNSRegistrationDomains "RegistrationDomains"
|
||||
# define kServiceDynDNSDomains "Domains" // value is comma separated list of domains
|
||||
# define kServiceDynDNSEnabled "Enabled"
|
||||
# define kServiceDynDNSStatus "Status"
|
||||
# define kServiceManageLLRouting "ManageLLRouting"
|
||||
# define kServiceCacheEntryCount "CacheEntryCount"
|
||||
# define kServiceManageFirewall "ManageFirewall"
|
||||
|
||||
#endif
|
@@ -1,338 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Secret.h"
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <ntsecapi.h>
|
||||
#include <lm.h>
|
||||
#include "DebugServices.h"
|
||||
|
||||
|
||||
mDNSlocal OSStatus MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input );
|
||||
mDNSlocal OSStatus MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input );
|
||||
|
||||
|
||||
BOOL
|
||||
LsaGetSecret( const char * inDomain, char * outDomain, unsigned outDomainSize, char * outKey, unsigned outKeySize, char * outSecret, unsigned outSecretSize )
|
||||
{
|
||||
PLSA_UNICODE_STRING domainLSA;
|
||||
PLSA_UNICODE_STRING keyLSA;
|
||||
PLSA_UNICODE_STRING secretLSA;
|
||||
size_t i;
|
||||
size_t dlen;
|
||||
LSA_OBJECT_ATTRIBUTES attrs;
|
||||
LSA_HANDLE handle = NULL;
|
||||
NTSTATUS res;
|
||||
OSStatus err;
|
||||
|
||||
check( inDomain );
|
||||
check( outDomain );
|
||||
check( outKey );
|
||||
check( outSecret );
|
||||
|
||||
// Initialize
|
||||
|
||||
domainLSA = NULL;
|
||||
keyLSA = NULL;
|
||||
secretLSA = NULL;
|
||||
|
||||
// Make sure we have enough space to add trailing dot
|
||||
|
||||
dlen = strlen( inDomain );
|
||||
err = strcpy_s( outDomain, outDomainSize - 2, inDomain );
|
||||
require_noerr( err, exit );
|
||||
|
||||
// If there isn't a trailing dot, add one because the mDNSResponder
|
||||
// presents names with the trailing dot.
|
||||
|
||||
if ( outDomain[ dlen - 1 ] != '.' )
|
||||
{
|
||||
outDomain[ dlen++ ] = '.';
|
||||
outDomain[ dlen ] = '\0';
|
||||
}
|
||||
|
||||
// Canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
|
||||
|
||||
for ( i = 0; i < dlen; i++ )
|
||||
{
|
||||
outDomain[i] = (char) tolower( outDomain[i] ); // canonicalize -> lower case
|
||||
}
|
||||
|
||||
// attrs are reserved, so initialize to zeroes.
|
||||
|
||||
ZeroMemory( &attrs, sizeof( attrs ) );
|
||||
|
||||
// Get a handle to the Policy object on the local system
|
||||
|
||||
res = LsaOpenPolicy( NULL, &attrs, POLICY_GET_PRIVATE_INFORMATION, &handle );
|
||||
err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
|
||||
require_noerr( err, exit );
|
||||
|
||||
// Get the encrypted data
|
||||
|
||||
domainLSA = ( PLSA_UNICODE_STRING ) malloc( sizeof( LSA_UNICODE_STRING ) );
|
||||
require_action( domainLSA != NULL, exit, err = mStatus_NoMemoryErr );
|
||||
err = MakeLsaStringFromUTF8String( domainLSA, outDomain );
|
||||
require_noerr( err, exit );
|
||||
|
||||
// Retrieve the key
|
||||
|
||||
res = LsaRetrievePrivateData( handle, domainLSA, &keyLSA );
|
||||
err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
|
||||
require_noerr_quiet( err, exit );
|
||||
|
||||
// <rdar://problem/4192119> Lsa secrets use a flat naming space. Therefore, we will prepend "$" to the keyname to
|
||||
// make sure it doesn't conflict with a zone name.
|
||||
// Strip off the "$" prefix.
|
||||
|
||||
err = MakeUTF8StringFromLsaString( outKey, outKeySize, keyLSA );
|
||||
require_noerr( err, exit );
|
||||
require_action( outKey[0] == '$', exit, err = kUnknownErr );
|
||||
memcpy( outKey, outKey + 1, strlen( outKey ) );
|
||||
|
||||
// Retrieve the secret
|
||||
|
||||
res = LsaRetrievePrivateData( handle, keyLSA, &secretLSA );
|
||||
err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
|
||||
require_noerr_quiet( err, exit );
|
||||
|
||||
// Convert the secret to UTF8 string
|
||||
|
||||
err = MakeUTF8StringFromLsaString( outSecret, outSecretSize, secretLSA );
|
||||
require_noerr( err, exit );
|
||||
|
||||
exit:
|
||||
|
||||
if ( domainLSA != NULL )
|
||||
{
|
||||
if ( domainLSA->Buffer != NULL )
|
||||
{
|
||||
free( domainLSA->Buffer );
|
||||
}
|
||||
|
||||
free( domainLSA );
|
||||
}
|
||||
|
||||
if ( keyLSA != NULL )
|
||||
{
|
||||
LsaFreeMemory( keyLSA );
|
||||
}
|
||||
|
||||
if ( secretLSA != NULL )
|
||||
{
|
||||
LsaFreeMemory( secretLSA );
|
||||
}
|
||||
|
||||
if ( handle )
|
||||
{
|
||||
LsaClose( handle );
|
||||
handle = NULL;
|
||||
}
|
||||
|
||||
return ( !err ) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
|
||||
mDNSBool
|
||||
LsaSetSecret( const char * inDomain, const char * inKey, const char * inSecret )
|
||||
{
|
||||
size_t inDomainLength;
|
||||
size_t inKeyLength;
|
||||
char domain[ 1024 ];
|
||||
char key[ 1024 ];
|
||||
LSA_OBJECT_ATTRIBUTES attrs;
|
||||
LSA_HANDLE handle = NULL;
|
||||
NTSTATUS res;
|
||||
LSA_UNICODE_STRING lucZoneName;
|
||||
LSA_UNICODE_STRING lucKeyName;
|
||||
LSA_UNICODE_STRING lucSecretName;
|
||||
BOOL ok = TRUE;
|
||||
OSStatus err;
|
||||
|
||||
require_action( inDomain != NULL, exit, ok = FALSE );
|
||||
require_action( inKey != NULL, exit, ok = FALSE );
|
||||
require_action( inSecret != NULL, exit, ok = FALSE );
|
||||
|
||||
// If there isn't a trailing dot, add one because the mDNSResponder
|
||||
// presents names with the trailing dot.
|
||||
|
||||
ZeroMemory( domain, sizeof( domain ) );
|
||||
inDomainLength = strlen( inDomain );
|
||||
require_action( inDomainLength > 0, exit, ok = FALSE );
|
||||
err = strcpy_s( domain, sizeof( domain ) - 2, inDomain );
|
||||
require_action( !err, exit, ok = FALSE );
|
||||
|
||||
if ( domain[ inDomainLength - 1 ] != '.' )
|
||||
{
|
||||
domain[ inDomainLength++ ] = '.';
|
||||
domain[ inDomainLength ] = '\0';
|
||||
}
|
||||
|
||||
// <rdar://problem/4192119>
|
||||
//
|
||||
// Prepend "$" to the key name, so that there will
|
||||
// be no conflict between the zone name and the key
|
||||
// name
|
||||
|
||||
ZeroMemory( key, sizeof( key ) );
|
||||
inKeyLength = strlen( inKey );
|
||||
require_action( inKeyLength > 0 , exit, ok = FALSE );
|
||||
key[ 0 ] = '$';
|
||||
err = strcpy_s( key + 1, sizeof( key ) - 3, inKey );
|
||||
require_action( !err, exit, ok = FALSE );
|
||||
inKeyLength++;
|
||||
|
||||
if ( key[ inKeyLength - 1 ] != '.' )
|
||||
{
|
||||
key[ inKeyLength++ ] = '.';
|
||||
key[ inKeyLength ] = '\0';
|
||||
}
|
||||
|
||||
// attrs are reserved, so initialize to zeroes.
|
||||
|
||||
ZeroMemory( &attrs, sizeof( attrs ) );
|
||||
|
||||
// Get a handle to the Policy object on the local system
|
||||
|
||||
res = LsaOpenPolicy( NULL, &attrs, POLICY_ALL_ACCESS, &handle );
|
||||
err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
|
||||
require_noerr( err, exit );
|
||||
|
||||
// Intializing PLSA_UNICODE_STRING structures
|
||||
|
||||
err = MakeLsaStringFromUTF8String( &lucZoneName, domain );
|
||||
require_noerr( err, exit );
|
||||
|
||||
err = MakeLsaStringFromUTF8String( &lucKeyName, key );
|
||||
require_noerr( err, exit );
|
||||
|
||||
err = MakeLsaStringFromUTF8String( &lucSecretName, inSecret );
|
||||
require_noerr( err, exit );
|
||||
|
||||
// Store the private data.
|
||||
|
||||
res = LsaStorePrivateData( handle, &lucZoneName, &lucKeyName );
|
||||
err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
|
||||
require_noerr( err, exit );
|
||||
|
||||
res = LsaStorePrivateData( handle, &lucKeyName, &lucSecretName );
|
||||
err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
|
||||
require_noerr( err, exit );
|
||||
|
||||
exit:
|
||||
|
||||
if ( handle )
|
||||
{
|
||||
LsaClose( handle );
|
||||
handle = NULL;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================================================================
|
||||
// MakeLsaStringFromUTF8String
|
||||
//===========================================================================================================================
|
||||
|
||||
mDNSlocal OSStatus
|
||||
MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input )
|
||||
{
|
||||
int size;
|
||||
OSStatus err;
|
||||
|
||||
check( input );
|
||||
check( output );
|
||||
|
||||
output->Buffer = NULL;
|
||||
|
||||
size = MultiByteToWideChar( CP_UTF8, 0, input, -1, NULL, 0 );
|
||||
err = translate_errno( size > 0, GetLastError(), kUnknownErr );
|
||||
require_noerr( err, exit );
|
||||
|
||||
output->Length = (USHORT)( size * sizeof( wchar_t ) );
|
||||
output->Buffer = (PWCHAR) malloc( output->Length );
|
||||
require_action( output->Buffer, exit, err = mStatus_NoMemoryErr );
|
||||
size = MultiByteToWideChar( CP_UTF8, 0, input, -1, output->Buffer, size );
|
||||
err = translate_errno( size > 0, GetLastError(), kUnknownErr );
|
||||
require_noerr( err, exit );
|
||||
|
||||
// We're going to subtrace one wchar_t from the size, because we didn't
|
||||
// include it when we encoded the string
|
||||
|
||||
output->MaximumLength = output->Length;
|
||||
output->Length -= sizeof( wchar_t );
|
||||
|
||||
exit:
|
||||
|
||||
if ( err && output->Buffer )
|
||||
{
|
||||
free( output->Buffer );
|
||||
output->Buffer = NULL;
|
||||
}
|
||||
|
||||
return( err );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===========================================================================================================================
|
||||
// MakeUTF8StringFromLsaString
|
||||
//===========================================================================================================================
|
||||
|
||||
mDNSlocal OSStatus
|
||||
MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input )
|
||||
{
|
||||
size_t size;
|
||||
OSStatus err = kNoErr;
|
||||
|
||||
// The Length field of this structure holds the number of bytes,
|
||||
// but WideCharToMultiByte expects the number of wchar_t's. So
|
||||
// we divide by sizeof(wchar_t) to get the correct number.
|
||||
|
||||
size = (size_t) WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), NULL, 0, NULL, NULL);
|
||||
err = translate_errno( size != 0, GetLastError(), kUnknownErr );
|
||||
require_noerr( err, exit );
|
||||
|
||||
// Ensure that we have enough space (Add one for trailing '\0')
|
||||
|
||||
require_action( ( size + 1 ) <= len, exit, err = mStatus_NoMemoryErr );
|
||||
|
||||
// Convert the string
|
||||
|
||||
size = (size_t) WideCharToMultiByte( CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), output, (int) size, NULL, NULL);
|
||||
err = translate_errno( size != 0, GetLastError(), kUnknownErr );
|
||||
require_noerr( err, exit );
|
||||
|
||||
// have to add the trailing 0 because WideCharToMultiByte doesn't do it,
|
||||
// although it does return the correct size
|
||||
|
||||
output[size] = '\0';
|
||||
|
||||
exit:
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@@ -1,42 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _Secret_h
|
||||
#define _Secret_h
|
||||
|
||||
#include "mDNSEmbeddedAPI.h"
|
||||
|
||||
|
||||
#if defined(__cplusplus )
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
extern mDNSBool
|
||||
LsaGetSecret( const char * inDomain, char * outDomain, unsigned outDomainLength, char * outKey, unsigned outKeyLength, char * outSecret, unsigned outSecretLength );
|
||||
|
||||
|
||||
extern mDNSBool
|
||||
LsaSetSecret( const char * inDomain, const char * inKey, const char * inSecret );
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@@ -1,30 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __MDNS_SERVICE_H__
|
||||
#define __MDNS_SERVICE_H__
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
extern int RunDirect( int argc, LPTSTR argv[] );
|
||||
extern int Main( int argc, LPTSTR argv[] );
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -1,115 +0,0 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
//#include "winres.h"
|
||||
//#include "WinVersRes.h"
|
||||
#include "windows.h"
|
||||
#include "EventLog.rc"
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,0
|
||||
PRODUCTVERSION 1,0,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Nokia Corporation and/or its subsidiary(-ies)\0"
|
||||
VALUE "FileDescription", "Bonjour Service Fallback\0"
|
||||
VALUE "FileVersion", 1,0,0,0
|
||||
VALUE "InternalName", "mdnssd.exe\0"
|
||||
VALUE "LegalCopyright", "Copyright(c)2003-2012, Apple Computer, 2012 Nokia Corporation and/or its subsidiary(-ies).\0"
|
||||
VALUE "OriginalFilename", "mdnssd.exe\0"
|
||||
VALUE "ProductName", "Bonjour Fallback\0"
|
||||
VALUE "ProductVersion", "1.0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"#include ""WinVersRes.h""\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_SERVICE_DESCRIPTION "Enables hardware devices and software services to automatically configure themselves on the network and advertise their presence, so that users can discover and use those services without any unnecessary manual setup or administration."
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,161 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "dnssd_ipc.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
char *win32_strerror(int inErrorCode)
|
||||
{
|
||||
static char buffer[1024];
|
||||
DWORD n;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
n = FormatMessageA(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
(DWORD) inErrorCode,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
NULL);
|
||||
if (n > 0)
|
||||
{
|
||||
// Remove any trailing CR's or LF's since some messages have them.
|
||||
while ((n > 0) && isspace(((unsigned char *) buffer)[n - 1]))
|
||||
buffer[--n] = '\0';
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void put_uint32(const uint32_t l, char **ptr)
|
||||
{
|
||||
(*ptr)[0] = (char)((l >> 24) & 0xFF);
|
||||
(*ptr)[1] = (char)((l >> 16) & 0xFF);
|
||||
(*ptr)[2] = (char)((l >> 8) & 0xFF);
|
||||
(*ptr)[3] = (char)((l ) & 0xFF);
|
||||
*ptr += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
uint32_t get_uint32(const char **ptr, const char *end)
|
||||
{
|
||||
if (!*ptr || *ptr + sizeof(uint32_t) > end)
|
||||
{
|
||||
*ptr = NULL;
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *p = (uint8_t*) *ptr;
|
||||
*ptr += sizeof(uint32_t);
|
||||
return((uint32_t) ((uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | p[3]));
|
||||
}
|
||||
}
|
||||
|
||||
void put_uint16(uint16_t s, char **ptr)
|
||||
{
|
||||
(*ptr)[0] = (char)((s >> 8) & 0xFF);
|
||||
(*ptr)[1] = (char)((s ) & 0xFF);
|
||||
*ptr += sizeof(uint16_t);
|
||||
}
|
||||
|
||||
uint16_t get_uint16(const char **ptr, const char *end)
|
||||
{
|
||||
if (!*ptr || *ptr + sizeof(uint16_t) > end)
|
||||
{
|
||||
*ptr = NULL;
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *p = (uint8_t*) *ptr;
|
||||
*ptr += sizeof(uint16_t);
|
||||
return((uint16_t) ((uint16_t)p[0] << 8 | p[1]));
|
||||
}
|
||||
}
|
||||
|
||||
int put_string(const char *str, char **ptr)
|
||||
{
|
||||
if (!str) str = "";
|
||||
strcpy(*ptr, str);
|
||||
*ptr += strlen(str) + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_string(const char **ptr, const char *const end, char *buffer, int buflen)
|
||||
{
|
||||
if (!*ptr)
|
||||
{
|
||||
*buffer = 0;
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *lim = buffer + buflen; // Calculate limit
|
||||
while (*ptr < end && buffer < lim)
|
||||
{
|
||||
char c = *buffer++ = *(*ptr)++;
|
||||
if (c == 0) return(0); // Success
|
||||
}
|
||||
if (buffer == lim) buffer--;
|
||||
*buffer = 0; // Failed, so terminate string,
|
||||
*ptr = NULL; // clear pointer,
|
||||
return(-1); // and return failure indication
|
||||
}
|
||||
}
|
||||
|
||||
void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr)
|
||||
{
|
||||
memcpy(*ptr, rdata, rdlen);
|
||||
*ptr += rdlen;
|
||||
}
|
||||
|
||||
const char *get_rdata(const char **ptr, const char *end, int rdlen)
|
||||
{
|
||||
if (!*ptr || *ptr + rdlen > end)
|
||||
{
|
||||
*ptr = NULL;
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *rd = *ptr;
|
||||
*ptr += rdlen;
|
||||
return rd;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertHeaderBytes(ipc_msg_hdr *hdr)
|
||||
{
|
||||
hdr->version = htonl(hdr->version);
|
||||
hdr->datalen = htonl(hdr->datalen);
|
||||
hdr->ipc_flags = htonl(hdr->ipc_flags);
|
||||
hdr->op = htonl(hdr->op );
|
||||
hdr->reg_index = htonl(hdr->reg_index);
|
||||
}
|
@@ -1,217 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DNSSD_IPC_H
|
||||
#define DNSSD_IPC_H
|
||||
|
||||
#include "dns_sd.h"
|
||||
|
||||
//
|
||||
// Common cross platform services
|
||||
//
|
||||
#if defined(WIN32)
|
||||
# include <winsock2.h>
|
||||
# define dnssd_InvalidSocket INVALID_SOCKET
|
||||
# define dnssd_SocketValid(s) ((s) != INVALID_SOCKET)
|
||||
# define dnssd_EWOULDBLOCK WSAEWOULDBLOCK
|
||||
# define dnssd_EINTR WSAEINTR
|
||||
# define dnssd_ECONNRESET WSAECONNRESET
|
||||
# define dnssd_sock_t SOCKET
|
||||
# define dnssd_socklen_t int
|
||||
# define dnssd_close(sock) closesocket(sock)
|
||||
# define dnssd_errno WSAGetLastError()
|
||||
# define dnssd_strerror(X) win32_strerror(X)
|
||||
# define ssize_t int
|
||||
# define getpid _getpid
|
||||
# define unlink _unlink
|
||||
extern char *win32_strerror(int inErrorCode);
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/un.h>
|
||||
# include <string.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
# define dnssd_InvalidSocket -1
|
||||
# define dnssd_SocketValid(s) ((s) >= 0)
|
||||
# define dnssd_EWOULDBLOCK EWOULDBLOCK
|
||||
# define dnssd_EINTR EINTR
|
||||
# define dnssd_ECONNRESET ECONNRESET
|
||||
# define dnssd_EPIPE EPIPE
|
||||
# define dnssd_sock_t int
|
||||
# define dnssd_socklen_t unsigned int
|
||||
# define dnssd_close(sock) close(sock)
|
||||
# define dnssd_errno errno
|
||||
# define dnssd_strerror(X) strerror(X)
|
||||
#endif
|
||||
|
||||
#if defined(USE_TCP_LOOPBACK)
|
||||
# define AF_DNSSD AF_INET
|
||||
# define MDNS_TCP_SERVERADDR "127.0.0.1"
|
||||
# define MDNS_TCP_SERVERPORT 5354
|
||||
# define LISTENQ 5
|
||||
# define dnssd_sockaddr_t struct sockaddr_in
|
||||
#else
|
||||
# define AF_DNSSD AF_LOCAL
|
||||
# ifndef MDNS_UDS_SERVERPATH
|
||||
# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder"
|
||||
# endif
|
||||
# define LISTENQ 100
|
||||
// longest legal control path length
|
||||
# define MAX_CTLPATH 256
|
||||
# define dnssd_sockaddr_t struct sockaddr_un
|
||||
#endif
|
||||
|
||||
// Compatibility workaround
|
||||
#ifndef AF_LOCAL
|
||||
#define AF_LOCAL AF_UNIX
|
||||
#endif
|
||||
|
||||
// General UDS constants
|
||||
#define TXT_RECORD_INDEX ((uint32_t)(-1)) // record index for default text record
|
||||
|
||||
// IPC data encoding constants and types
|
||||
#define VERSION 1
|
||||
#define IPC_FLAGS_NOREPLY 1 // set flag if no asynchronous replies are to be sent to client
|
||||
|
||||
// Structure packing macro. If we're not using GNUC, it's not fatal. Most compilers naturally pack the on-the-wire
|
||||
// structures correctly anyway, so a plain "struct" is usually fine. In the event that structures are not packed
|
||||
// correctly, our compile-time assertion checks will catch it and prevent inadvertent generation of non-working code.
|
||||
#ifndef packedstruct
|
||||
#if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
|
||||
#define packedstruct struct __attribute__((__packed__))
|
||||
#define packedunion union __attribute__((__packed__))
|
||||
#else
|
||||
#define packedstruct struct
|
||||
#define packedunion union
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
request_op_none = 0, // No request yet received on this connection
|
||||
connection_request = 1, // connected socket via DNSServiceConnect()
|
||||
reg_record_request, // reg/remove record only valid for connected sockets
|
||||
remove_record_request,
|
||||
enumeration_request,
|
||||
reg_service_request,
|
||||
browse_request,
|
||||
resolve_request,
|
||||
query_request,
|
||||
reconfirm_record_request,
|
||||
add_record_request,
|
||||
update_record_request,
|
||||
setdomain_request, // Up to here is in Tiger and B4W 1.0.3
|
||||
getproperty_request, // New in B4W 1.0.4
|
||||
port_mapping_request, // New in Leopard and B4W 2.0
|
||||
addrinfo_request,
|
||||
send_bpf, // New in SL
|
||||
|
||||
cancel_request = 63
|
||||
} request_op_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
enumeration_reply_op = 64,
|
||||
reg_service_reply_op,
|
||||
browse_reply_op,
|
||||
resolve_reply_op,
|
||||
query_reply_op,
|
||||
reg_record_reply_op, // Up to here is in Tiger and B4W 1.0.3
|
||||
getproperty_reply_op, // New in B4W 1.0.4
|
||||
port_mapping_reply_op, // New in Leopard and B4W 2.0
|
||||
addrinfo_reply_op
|
||||
} reply_op_t;
|
||||
|
||||
#if defined(_WIN64)
|
||||
# pragma pack(push,4)
|
||||
#endif
|
||||
|
||||
// Define context object big enough to hold a 64-bit pointer,
|
||||
// to accomodate 64-bit clients communicating with 32-bit daemon.
|
||||
// There's no reason for the daemon to ever be a 64-bit process, but its clients might be
|
||||
typedef packedunion
|
||||
{
|
||||
void *context;
|
||||
uint32_t u32[2];
|
||||
} client_context_t;
|
||||
|
||||
typedef packedstruct
|
||||
{
|
||||
uint32_t version;
|
||||
uint32_t datalen;
|
||||
uint32_t ipc_flags;
|
||||
uint32_t op; // request_op_t or reply_op_t
|
||||
client_context_t client_context; // context passed from client, returned by server in corresponding reply
|
||||
uint32_t reg_index; // identifier for a record registered via DNSServiceRegisterRecord() on a
|
||||
// socket connected by DNSServiceCreateConnection(). Must be unique in the scope of the connection, such that and
|
||||
// index/socket pair uniquely identifies a record. (Used to select records for removal by DNSServiceRemoveRecord())
|
||||
} ipc_msg_hdr;
|
||||
|
||||
#if defined(_WIN64)
|
||||
# pragma pack(pop)
|
||||
#endif
|
||||
|
||||
// routines to write to and extract data from message buffers.
|
||||
// caller responsible for bounds checking.
|
||||
// ptr is the address of the pointer to the start of the field.
|
||||
// it is advanced to point to the next field, or the end of the message
|
||||
|
||||
void put_uint32(const uint32_t l, char **ptr);
|
||||
uint32_t get_uint32(const char **ptr, const char *end);
|
||||
|
||||
void put_uint16(uint16_t s, char **ptr);
|
||||
uint16_t get_uint16(const char **ptr, const char *end);
|
||||
|
||||
#define put_flags put_uint32
|
||||
#define get_flags get_uint32
|
||||
|
||||
#define put_error_code put_uint32
|
||||
#define get_error_code get_uint32
|
||||
|
||||
int put_string(const char *str, char **ptr);
|
||||
int get_string(const char **ptr, const char *const end, char *buffer, int buflen);
|
||||
|
||||
void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr);
|
||||
const char *get_rdata(const char **ptr, const char *end, int rdlen); // return value is rdata pointed to by *ptr -
|
||||
// rdata is not copied from buffer.
|
||||
|
||||
void ConvertHeaderBytes(ipc_msg_hdr *hdr);
|
||||
|
||||
struct CompileTimeAssertionChecks_dnssd_ipc
|
||||
{
|
||||
// Check that the compiler generated our on-the-wire packet format structure definitions
|
||||
// properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
|
||||
char assert0[(sizeof(client_context_t) == 8) ? 1 : -1];
|
||||
char assert1[(sizeof(ipc_msg_hdr) == 28) ? 1 : -1];
|
||||
};
|
||||
|
||||
#endif // DNSSD_IPC_H
|
11521
src/tools/mdnssd/mDNS.c
11521
src/tools/mdnssd/mDNS.c
File diff suppressed because it is too large
Load Diff
@@ -1,93 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
File: mDNSDebug.c
|
||||
|
||||
Contains: Implementation of debugging utilities. Requires a POSIX environment.
|
||||
|
||||
Version: 1.0
|
||||
|
||||
*/
|
||||
|
||||
#include "mDNSDebug.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(WIN32) || defined(EFI32) || defined(EFI64) || defined(EFIX64)
|
||||
// Need to add Windows/EFI syslog support here
|
||||
#define LOG_PID 0x01
|
||||
#define LOG_CONS 0x02
|
||||
#define LOG_PERROR 0x20
|
||||
#else
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
#include "mDNSEmbeddedAPI.h"
|
||||
|
||||
mDNSexport int mDNS_LoggingEnabled = 0;
|
||||
mDNSexport int mDNS_PacketLoggingEnabled = 0;
|
||||
|
||||
#if MDNS_DEBUGMSGS
|
||||
mDNSexport int mDNS_DebugMode = mDNStrue;
|
||||
#else
|
||||
mDNSexport int mDNS_DebugMode = mDNSfalse;
|
||||
#endif
|
||||
|
||||
// Note, this uses mDNS_vsnprintf instead of standard "vsnprintf", because mDNS_vsnprintf knows
|
||||
// how to print special data types like IP addresses and length-prefixed domain names
|
||||
#if MDNS_DEBUGMSGS > 1
|
||||
mDNSexport void verbosedebugf_(const char *format, ...)
|
||||
{
|
||||
char buffer[512];
|
||||
va_list ptr;
|
||||
va_start(ptr,format);
|
||||
buffer[mDNS_vsnprintf(buffer, sizeof(buffer), format, ptr)] = 0;
|
||||
va_end(ptr);
|
||||
mDNSPlatformWriteDebugMsg(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Log message with default "mDNSResponder" ident string at the start
|
||||
mDNSlocal void LogMsgWithLevelv(mDNSLogLevel_t logLevel, const char *format, va_list ptr)
|
||||
{
|
||||
char buffer[512];
|
||||
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
|
||||
mDNSPlatformWriteLogMsg(ProgramName, buffer, logLevel);
|
||||
}
|
||||
|
||||
#define LOG_HELPER_BODY(L) \
|
||||
{ \
|
||||
va_list ptr; \
|
||||
va_start(ptr,format); \
|
||||
LogMsgWithLevelv(L, format, ptr); \
|
||||
va_end(ptr); \
|
||||
}
|
||||
|
||||
// see mDNSDebug.h
|
||||
#if !MDNS_HAS_VA_ARG_MACROS
|
||||
void LogMsg_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_MSG)
|
||||
void LogOperation_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_OPERATION)
|
||||
void LogSPS_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_SPS)
|
||||
void LogInfo_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_INFO)
|
||||
#endif
|
||||
|
||||
#if MDNS_DEBUGMSGS
|
||||
void debugf_(const char *format, ...) LOG_HELPER_BODY(MDNS_LOG_DEBUG)
|
||||
#endif
|
||||
|
||||
// Log message with default "mDNSResponder" ident string at the start
|
||||
mDNSexport void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *format, ...)
|
||||
LOG_HELPER_BODY(logLevel)
|
@@ -1,164 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __mDNSDebug_h
|
||||
#define __mDNSDebug_h
|
||||
|
||||
// Set MDNS_DEBUGMSGS to 0 to optimize debugf() calls out of the compiled code
|
||||
// Set MDNS_DEBUGMSGS to 1 to generate normal debugging messages
|
||||
// Set MDNS_DEBUGMSGS to 2 to generate verbose debugging messages
|
||||
// MDNS_DEBUGMSGS is normally set in the project options (or makefile) but can also be set here if desired
|
||||
// (If you edit the file here to turn on MDNS_DEBUGMSGS while you're debugging some code, be careful
|
||||
// not to accidentally check-in that change by mistake when you check in your other changes.)
|
||||
|
||||
//#undef MDNS_DEBUGMSGS
|
||||
//#define MDNS_DEBUGMSGS 2
|
||||
|
||||
// Set MDNS_CHECK_PRINTF_STYLE_FUNCTIONS to 1 to enable extra GCC compiler warnings
|
||||
// Note: You don't normally want to do this, because it generates a bunch of
|
||||
// spurious warnings for the following custom extensions implemented by mDNS_vsnprintf:
|
||||
// warning: `#' flag used with `%s' printf format (for %#s -- pascal string format)
|
||||
// warning: repeated `#' flag in format (for %##s -- DNS name string format)
|
||||
// warning: double format, pointer arg (arg 2) (for %.4a, %.16a, %#a -- IP address formats)
|
||||
#define MDNS_CHECK_PRINTF_STYLE_FUNCTIONS 0
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MDNS_LOG_MSG,
|
||||
MDNS_LOG_OPERATION,
|
||||
MDNS_LOG_SPS,
|
||||
MDNS_LOG_INFO,
|
||||
MDNS_LOG_DEBUG,
|
||||
} mDNSLogLevel_t;
|
||||
|
||||
// Set this symbol to 1 to answer remote queries for our Address, reverse mapping PTR, and HINFO records
|
||||
#define ANSWER_REMOTE_HOSTNAME_QUERIES 0
|
||||
|
||||
// Set this symbol to 1 to do extra debug checks on malloc() and free()
|
||||
// Set this symbol to 2 to write a log message for every malloc() and free()
|
||||
//#define MACOSX_MDNS_MALLOC_DEBUGGING 1
|
||||
|
||||
//#define ForceAlerts 1
|
||||
//#define LogTimeStamps 1
|
||||
|
||||
// Developer-settings section ends here
|
||||
|
||||
#if MDNS_CHECK_PRINTF_STYLE_FUNCTIONS
|
||||
#define IS_A_PRINTF_STYLE_FUNCTION(F,A) __attribute__ ((format(printf,F,A)))
|
||||
#else
|
||||
#define IS_A_PRINTF_STYLE_FUNCTION(F,A)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Variable argument macro support. Use ANSI C99 __VA_ARGS__ where possible. Otherwise, use the next best thing.
|
||||
|
||||
#if (defined(__GNUC__))
|
||||
#if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 2)))
|
||||
#define MDNS_C99_VA_ARGS 1
|
||||
#define MDNS_GNU_VA_ARGS 0
|
||||
#else
|
||||
#define MDNS_C99_VA_ARGS 0
|
||||
#define MDNS_GNU_VA_ARGS 1
|
||||
#endif
|
||||
#define MDNS_HAS_VA_ARG_MACROS 1
|
||||
#elif (_MSC_VER >= 1400) // Visual Studio 2005 and later
|
||||
#define MDNS_C99_VA_ARGS 1
|
||||
#define MDNS_GNU_VA_ARGS 0
|
||||
#define MDNS_HAS_VA_ARG_MACROS 1
|
||||
#elif (defined(__MWERKS__))
|
||||
#define MDNS_C99_VA_ARGS 1
|
||||
#define MDNS_GNU_VA_ARGS 0
|
||||
#define MDNS_HAS_VA_ARG_MACROS 1
|
||||
#else
|
||||
#define MDNS_C99_VA_ARGS 0
|
||||
#define MDNS_GNU_VA_ARGS 0
|
||||
#define MDNS_HAS_VA_ARG_MACROS 0
|
||||
#endif
|
||||
|
||||
#if (MDNS_HAS_VA_ARG_MACROS)
|
||||
#if (MDNS_C99_VA_ARGS)
|
||||
#define debug_noop( ... ) ((void)0)
|
||||
#define LogMsg( ... ) LogMsgWithLevel(MDNS_LOG_MSG, __VA_ARGS__)
|
||||
#define LogOperation( ... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_OPERATION, __VA_ARGS__); } while (0)
|
||||
#define LogSPS( ... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_SPS, __VA_ARGS__); } while (0)
|
||||
#define LogInfo( ... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_INFO, __VA_ARGS__); } while (0)
|
||||
#elif (MDNS_GNU_VA_ARGS)
|
||||
#define debug_noop( ARGS... ) ((void)0)
|
||||
#define LogMsg( ARGS... ) LogMsgWithLevel(MDNS_LOG_MSG, ARGS)
|
||||
#define LogOperation( ARGS... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_OPERATION, ARGS); } while (0)
|
||||
#define LogSPS( ARGS... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_SPS, ARGS); } while (0)
|
||||
#define LogInfo( ARGS... ) do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_INFO, ARGS); } while (0)
|
||||
#else
|
||||
#error Unknown variadic macros
|
||||
#endif
|
||||
#else
|
||||
// If your platform does not support variadic macros, you need to define the following variadic functions.
|
||||
// See mDNSShared/mDNSDebug.c for sample implementation
|
||||
#define debug_noop 1 ? (void)0 : (void)
|
||||
#define LogMsg LogMsg_
|
||||
#define LogOperation (mDNS_LoggingEnabled == 0) ? ((void)0) : LogOperation_
|
||||
#define LogSPS (mDNS_LoggingEnabled == 0) ? ((void)0) : LogSPS_
|
||||
#define LogInfo (mDNS_LoggingEnabled == 0) ? ((void)0) : LogInfo_
|
||||
extern void LogMsg_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
|
||||
extern void LogOperation_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
|
||||
extern void LogSPS_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
|
||||
extern void LogInfo_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
|
||||
#endif
|
||||
|
||||
#if MDNS_DEBUGMSGS
|
||||
#define debugf debugf_
|
||||
extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
|
||||
#else
|
||||
#define debugf debug_noop
|
||||
#endif
|
||||
|
||||
#if MDNS_DEBUGMSGS > 1
|
||||
#define verbosedebugf verbosedebugf_
|
||||
extern void verbosedebugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
|
||||
#else
|
||||
#define verbosedebugf debug_noop
|
||||
#endif
|
||||
|
||||
extern int mDNS_LoggingEnabled;
|
||||
extern int mDNS_PacketLoggingEnabled;
|
||||
extern int mDNS_DebugMode; // If non-zero, LogMsg() writes to stderr instead of syslog
|
||||
extern const char ProgramName[];
|
||||
|
||||
extern void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(2,3);
|
||||
// LogMsgNoIdent needs to be fixed so that it logs without the ident prefix like it used to
|
||||
// (or completely overhauled to use the new "log to a separate file" facility)
|
||||
#define LogMsgNoIdent LogMsg
|
||||
|
||||
#if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1
|
||||
extern void *mallocL(char *msg, unsigned int size);
|
||||
extern void freeL(char *msg, void *x);
|
||||
extern void LogMemCorruption(const char *format, ...);
|
||||
extern void uds_validatelists(void);
|
||||
extern void udns_validatelists(void *const v);
|
||||
#else
|
||||
#define mallocL(X,Y) malloc(Y)
|
||||
#define freeL(X,Y) free(Y)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,85 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __mDNSPlatformPosix_h
|
||||
#define __mDNSPlatformPosix_h
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// PosixNetworkInterface is a record extension of the core NetworkInterfaceInfo
|
||||
// type that supports extra fields needed by the Posix platform.
|
||||
//
|
||||
// IMPORTANT: coreIntf must be the first field in the structure because
|
||||
// we cast between pointers to the two different types regularly.
|
||||
|
||||
typedef struct PosixNetworkInterface PosixNetworkInterface;
|
||||
|
||||
struct PosixNetworkInterface
|
||||
{
|
||||
NetworkInterfaceInfo coreIntf;
|
||||
const char * intfName;
|
||||
PosixNetworkInterface * aliasIntf;
|
||||
int index;
|
||||
int multicastSocket4;
|
||||
#if HAVE_IPV6
|
||||
int multicastSocket6;
|
||||
#endif
|
||||
};
|
||||
|
||||
// This is a global because debugf_() needs to be able to check its value
|
||||
extern int gMDNSPlatformPosixVerboseLevel;
|
||||
|
||||
struct mDNS_PlatformSupport_struct
|
||||
{
|
||||
int unicastSocket4;
|
||||
#if HAVE_IPV6
|
||||
int unicastSocket6;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define uDNS_SERVERS_FILE "/etc/resolv.conf"
|
||||
extern int ParseDNSServers(mDNS *m, const char *filePath);
|
||||
extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m);
|
||||
// See comment in implementation.
|
||||
|
||||
// Call mDNSPosixGetFDSet before calling select(), to update the parameters
|
||||
// as may be necessary to meet the needs of the mDNSCore code.
|
||||
// The timeout pointer MUST NOT be NULL.
|
||||
// Set timeout->tv_sec to 0x3FFFFFFF if you want to have effectively no timeout
|
||||
// After calling mDNSPosixGetFDSet(), call select(nfds, &readfds, NULL, NULL, &timeout); as usual
|
||||
// After select() returns, call mDNSPosixProcessFDSet() to let mDNSCore do its work
|
||||
extern void mDNSPosixGetFDSet(mDNS *m, int *nfds, fd_set *readfds, struct timeval *timeout);
|
||||
extern void mDNSPosixProcessFDSet(mDNS *const m, fd_set *readfds);
|
||||
|
||||
typedef void (*mDNSPosixEventCallback)(int fd, short filter, void *context);
|
||||
|
||||
extern mStatus mDNSPosixAddFDToEventLoop( int fd, mDNSPosixEventCallback callback, void *context);
|
||||
extern mStatus mDNSPosixRemoveFDFromEventLoop( int fd);
|
||||
extern mStatus mDNSPosixListenForSignalInEventLoop( int signum);
|
||||
extern mStatus mDNSPosixIgnoreSignalInEventLoop( int signum);
|
||||
extern mStatus mDNSPosixRunEventLoopOnce( mDNS *m, const struct timeval *pTimeout, sigset_t *pSignalsReceived, mDNSBool *pDataDispatched);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -1,721 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "mDNSUNP.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Some weird platforms derived from 4.4BSD Lite (e.g. EFI) need the ALIGN(P)
|
||||
macro, usually defined in <sys/param.h> or someplace like that, to make sure the
|
||||
CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO
|
||||
should be set to the name of the header to include to get the ALIGN(P) macro.
|
||||
*/
|
||||
#ifdef NEED_ALIGN_MACRO
|
||||
#include NEED_ALIGN_MACRO
|
||||
#endif
|
||||
|
||||
/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
|
||||
other platforms don't even have that include file. So,
|
||||
if we haven't yet got a definition, let's try to find
|
||||
<sys/sockio.h>.
|
||||
*/
|
||||
|
||||
#ifndef SIOCGIFCONF
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
|
||||
/* sockaddr_dl is only referenced if we're using IP_RECVIF,
|
||||
so only include the header in that case.
|
||||
*/
|
||||
|
||||
#ifdef IP_RECVIF
|
||||
#include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
#if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX
|
||||
#include <net/if_var.h>
|
||||
#include <netinet/in_var.h>
|
||||
// Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
|
||||
#endif
|
||||
|
||||
#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/* Converts a prefix length to IPv6 network mask */
|
||||
void plen_to_mask(int plen, char *addr) {
|
||||
int i;
|
||||
int colons=7; /* Number of colons in IPv6 address */
|
||||
int bits_in_block=16; /* Bits per IPv6 block */
|
||||
for(i=0;i<=colons;i++) {
|
||||
int block, ones=0xffff, ones_in_block;
|
||||
if (plen>bits_in_block) ones_in_block=bits_in_block;
|
||||
else ones_in_block=plen;
|
||||
block = ones & (ones << (bits_in_block-ones_in_block));
|
||||
i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
|
||||
plen -= ones_in_block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Gets IPv6 interface information from the /proc filesystem in linux*/
|
||||
struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
|
||||
{
|
||||
struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
|
||||
FILE *fp;
|
||||
char addr[8][5];
|
||||
int flags, myflags, index, plen, scope;
|
||||
char ifname[9], lastname[IFNAMSIZ];
|
||||
char addr6[32+7+1]; /* don't forget the seven ':' */
|
||||
struct addrinfo hints, *res0;
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct in6_addr *addrptr;
|
||||
int err;
|
||||
int sockfd = -1;
|
||||
struct ifreq ifr;
|
||||
|
||||
res0=NULL;
|
||||
ifihead = NULL;
|
||||
ifipnext = &ifihead;
|
||||
lastname[0] = 0;
|
||||
|
||||
if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
|
||||
sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
if (sockfd < 0) {
|
||||
goto gotError;
|
||||
}
|
||||
while (fscanf(fp,
|
||||
"%4s%4s%4s%4s%4s%4s%4s%4s %x %x %x %x %s\n",
|
||||
addr[0],addr[1],addr[2],addr[3],
|
||||
addr[4],addr[5],addr[6],addr[7],
|
||||
&index, &plen, &scope, &flags, ifname) != EOF) {
|
||||
|
||||
myflags = 0;
|
||||
if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
|
||||
if (doaliases == 0)
|
||||
continue; /* already processed this interface */
|
||||
myflags = IFI_ALIAS;
|
||||
}
|
||||
memcpy(lastname, ifname, IFNAMSIZ);
|
||||
ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
|
||||
if (ifi == NULL) {
|
||||
goto gotError;
|
||||
}
|
||||
|
||||
ifipold = *ifipnext; /* need this later */
|
||||
ifiptr = ifipnext;
|
||||
*ifipnext = ifi; /* prev points to this new one */
|
||||
ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
|
||||
|
||||
sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
|
||||
addr[0],addr[1],addr[2],addr[3],
|
||||
addr[4],addr[5],addr[6],addr[7]);
|
||||
|
||||
/* Add address of the interface */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
err = getaddrinfo(addr6, NULL, &hints, &res0);
|
||||
if (err) {
|
||||
goto gotError;
|
||||
}
|
||||
ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
|
||||
if (ifi->ifi_addr == NULL) {
|
||||
goto gotError;
|
||||
}
|
||||
memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
|
||||
|
||||
/* Add netmask of the interface */
|
||||
char ipv6addr[INET6_ADDRSTRLEN];
|
||||
plen_to_mask(plen, ipv6addr);
|
||||
ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
|
||||
if (ifi->ifi_addr == NULL) {
|
||||
goto gotError;
|
||||
}
|
||||
sin6=calloc(1, sizeof(struct sockaddr_in6));
|
||||
addrptr=calloc(1, sizeof(struct in6_addr));
|
||||
inet_pton(family, ipv6addr, addrptr);
|
||||
sin6->sin6_family=family;
|
||||
sin6->sin6_addr=*addrptr;
|
||||
sin6->sin6_scope_id=scope;
|
||||
memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6));
|
||||
free(sin6);
|
||||
|
||||
|
||||
/* Add interface name */
|
||||
memcpy(ifi->ifi_name, ifname, IFI_NAME);
|
||||
|
||||
/* Add interface index */
|
||||
ifi->ifi_index = index;
|
||||
|
||||
/* Add interface flags*/
|
||||
memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
if (errno == EADDRNOTAVAIL) {
|
||||
/*
|
||||
* If the main interface is configured with no IP address but
|
||||
* an alias interface exists with an IP address, you get
|
||||
* EADDRNOTAVAIL for the main interface
|
||||
*/
|
||||
free(ifi->ifi_addr);
|
||||
free(ifi);
|
||||
ifipnext = ifiptr;
|
||||
*ifipnext = ifipold;
|
||||
continue;
|
||||
} else {
|
||||
goto gotError;
|
||||
}
|
||||
}
|
||||
ifi->ifi_flags = ifr.ifr_flags;
|
||||
freeaddrinfo(res0);
|
||||
res0=NULL;
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
|
||||
gotError:
|
||||
if (ifihead != NULL) {
|
||||
free_ifi_info(ifihead);
|
||||
ifihead = NULL;
|
||||
}
|
||||
if (res0 != NULL) {
|
||||
freeaddrinfo(res0);
|
||||
res0=NULL;
|
||||
}
|
||||
done:
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
if (sockfd != -1 && close(sockfd) != 0) {
|
||||
assert(1);
|
||||
}
|
||||
return(ifihead); /* pointer to first structure in linked list */
|
||||
}
|
||||
#endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
|
||||
|
||||
struct ifi_info *get_ifi_info(int family, int doaliases)
|
||||
{
|
||||
int junk;
|
||||
struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
|
||||
int sockfd, sockf6, len, lastlen, flags, myflags;
|
||||
#ifdef NOT_HAVE_IF_NAMETOINDEX
|
||||
int index = 200;
|
||||
#endif
|
||||
char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr, ifrcopy;
|
||||
struct sockaddr_in *sinptr;
|
||||
|
||||
#if defined(AF_INET6) && HAVE_IPV6
|
||||
struct sockaddr_in6 *sinptr6;
|
||||
#endif
|
||||
|
||||
#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
|
||||
if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
|
||||
#endif
|
||||
|
||||
sockfd = -1;
|
||||
sockf6 = -1;
|
||||
buf = NULL;
|
||||
ifihead = NULL;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd < 0) {
|
||||
goto gotError;
|
||||
}
|
||||
|
||||
lastlen = 0;
|
||||
len = 100 * sizeof(struct ifreq); /* initial buffer size guess */
|
||||
for ( ; ; ) {
|
||||
buf = (char*)malloc(len);
|
||||
if (buf == NULL) {
|
||||
goto gotError;
|
||||
}
|
||||
ifc.ifc_len = len;
|
||||
ifc.ifc_buf = buf;
|
||||
if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
|
||||
if (errno != EINVAL || lastlen != 0) {
|
||||
goto gotError;
|
||||
}
|
||||
} else {
|
||||
if (ifc.ifc_len == lastlen)
|
||||
break; /* success, len has not changed */
|
||||
lastlen = ifc.ifc_len;
|
||||
}
|
||||
len += 10 * sizeof(struct ifreq); /* increment */
|
||||
free(buf);
|
||||
}
|
||||
ifihead = NULL;
|
||||
ifipnext = &ifihead;
|
||||
lastname[0] = 0;
|
||||
/* end get_ifi_info1 */
|
||||
|
||||
/* include get_ifi_info2 */
|
||||
for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
|
||||
ifr = (struct ifreq *) ptr;
|
||||
|
||||
/* Advance to next one in buffer */
|
||||
if (sizeof(struct ifreq) > sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr))
|
||||
ptr += sizeof(struct ifreq);
|
||||
else
|
||||
ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr);
|
||||
|
||||
// fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
|
||||
|
||||
if (ifr->ifr_addr.sa_family != family)
|
||||
continue; /* ignore if not desired address family */
|
||||
|
||||
myflags = 0;
|
||||
if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL)
|
||||
*cptr = 0; /* replace colon will null */
|
||||
if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
|
||||
if (doaliases == 0)
|
||||
continue; /* already processed this interface */
|
||||
myflags = IFI_ALIAS;
|
||||
}
|
||||
memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
|
||||
|
||||
ifrcopy = *ifr;
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) {
|
||||
goto gotError;
|
||||
}
|
||||
|
||||
flags = ifrcopy.ifr_flags;
|
||||
if ((flags & IFF_UP) == 0)
|
||||
continue; /* ignore if interface not up */
|
||||
|
||||
ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
|
||||
if (ifi == NULL) {
|
||||
goto gotError;
|
||||
}
|
||||
ifipold = *ifipnext; /* need this later */
|
||||
ifiptr = ifipnext;
|
||||
*ifipnext = ifi; /* prev points to this new one */
|
||||
ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
|
||||
|
||||
ifi->ifi_flags = flags; /* IFF_xxx values */
|
||||
ifi->ifi_myflags = myflags; /* IFI_xxx values */
|
||||
#ifndef NOT_HAVE_IF_NAMETOINDEX
|
||||
ifi->ifi_index = if_nametoindex(ifr->ifr_name);
|
||||
#else
|
||||
ifrcopy = *ifr;
|
||||
#ifdef SIOCGIFINDEX
|
||||
if ( 0 >= ioctl(sockfd, SIOCGIFINDEX, &ifrcopy))
|
||||
ifi->ifi_index = ifrcopy.ifr_index;
|
||||
else
|
||||
#endif
|
||||
ifi->ifi_index = index++; /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
|
||||
#endif
|
||||
memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
|
||||
ifi->ifi_name[IFI_NAME-1] = '\0';
|
||||
/* end get_ifi_info2 */
|
||||
/* include get_ifi_info3 */
|
||||
switch (ifr->ifr_addr.sa_family) {
|
||||
case AF_INET:
|
||||
sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
|
||||
if (ifi->ifi_addr == NULL) {
|
||||
ifi->ifi_addr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
|
||||
if (ifi->ifi_addr == NULL) {
|
||||
goto gotError;
|
||||
}
|
||||
memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
|
||||
|
||||
#ifdef SIOCGIFNETMASK
|
||||
if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) {
|
||||
if (errno == EADDRNOTAVAIL) {
|
||||
/*
|
||||
* If the main interface is configured with no IP address but
|
||||
* an alias interface exists with an IP address, you get
|
||||
* EADDRNOTAVAIL for the main interface
|
||||
*/
|
||||
free(ifi->ifi_addr);
|
||||
free(ifi);
|
||||
ifipnext = ifiptr;
|
||||
*ifipnext = ifipold;
|
||||
continue;
|
||||
} else {
|
||||
goto gotError;
|
||||
}
|
||||
}
|
||||
|
||||
ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
|
||||
if (ifi->ifi_netmask == NULL) goto gotError;
|
||||
sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
|
||||
/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
|
||||
#ifndef NOT_HAVE_SA_LEN
|
||||
sinptr->sin_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
sinptr->sin_family = AF_INET;
|
||||
memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
|
||||
#endif
|
||||
|
||||
#ifdef SIOCGIFBRDADDR
|
||||
if (flags & IFF_BROADCAST) {
|
||||
if (ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
|
||||
goto gotError;
|
||||
}
|
||||
sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
|
||||
/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
|
||||
#ifndef NOT_HAVE_SA_LEN
|
||||
sinptr->sin_len = sizeof( struct sockaddr_in );
|
||||
#endif
|
||||
sinptr->sin_family = AF_INET;
|
||||
ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
|
||||
if (ifi->ifi_brdaddr == NULL) {
|
||||
goto gotError;
|
||||
}
|
||||
memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SIOCGIFDSTADDR
|
||||
if (flags & IFF_POINTOPOINT) {
|
||||
if (ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy) < 0) {
|
||||
goto gotError;
|
||||
}
|
||||
sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
|
||||
/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
|
||||
#ifndef NOT_HAVE_SA_LEN
|
||||
sinptr->sin_len = sizeof( struct sockaddr_in );
|
||||
#endif
|
||||
sinptr->sin_family = AF_INET;
|
||||
ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
|
||||
if (ifi->ifi_dstaddr == NULL) {
|
||||
goto gotError;
|
||||
}
|
||||
memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(AF_INET6) && HAVE_IPV6
|
||||
case AF_INET6:
|
||||
sinptr6 = (struct sockaddr_in6 *) &ifr->ifr_addr;
|
||||
if (ifi->ifi_addr == NULL) {
|
||||
ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
|
||||
if (ifi->ifi_addr == NULL) {
|
||||
goto gotError;
|
||||
}
|
||||
|
||||
/* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
|
||||
/* We need to strip that out */
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr))
|
||||
sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0;
|
||||
memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
|
||||
|
||||
#ifdef SIOCGIFNETMASK_IN6
|
||||
{
|
||||
struct in6_ifreq ifr6;
|
||||
if (sockf6 == -1)
|
||||
sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
memset(&ifr6, 0, sizeof(ifr6));
|
||||
memcpy(&ifr6.ifr_name, &ifr->ifr_name, sizeof(ifr6.ifr_name ));
|
||||
memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
|
||||
if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) {
|
||||
if (errno == EADDRNOTAVAIL) {
|
||||
/*
|
||||
* If the main interface is configured with no IP address but
|
||||
* an alias interface exists with an IP address, you get
|
||||
* EADDRNOTAVAIL for the main interface
|
||||
*/
|
||||
free(ifi->ifi_addr);
|
||||
free(ifi);
|
||||
ifipnext = ifiptr;
|
||||
*ifipnext = ifipold;
|
||||
continue;
|
||||
} else {
|
||||
goto gotError;
|
||||
}
|
||||
}
|
||||
ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6));
|
||||
if (ifi->ifi_netmask == NULL) goto gotError;
|
||||
sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr;
|
||||
memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
|
||||
gotError:
|
||||
if (ifihead != NULL) {
|
||||
free_ifi_info(ifihead);
|
||||
ifihead = NULL;
|
||||
}
|
||||
|
||||
done:
|
||||
if (buf != NULL) {
|
||||
free(buf);
|
||||
}
|
||||
if (sockfd != -1) {
|
||||
junk = close(sockfd);
|
||||
assert(junk == 0);
|
||||
}
|
||||
if (sockf6 != -1) {
|
||||
junk = close(sockf6);
|
||||
assert(junk == 0);
|
||||
}
|
||||
return(ifihead); /* pointer to first structure in linked list */
|
||||
}
|
||||
/* end get_ifi_info3 */
|
||||
|
||||
/* include free_ifi_info */
|
||||
void
|
||||
free_ifi_info(struct ifi_info *ifihead)
|
||||
{
|
||||
struct ifi_info *ifi, *ifinext;
|
||||
|
||||
for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
|
||||
if (ifi->ifi_addr != NULL)
|
||||
free(ifi->ifi_addr);
|
||||
if (ifi->ifi_netmask != NULL)
|
||||
free(ifi->ifi_netmask);
|
||||
if (ifi->ifi_brdaddr != NULL)
|
||||
free(ifi->ifi_brdaddr);
|
||||
if (ifi->ifi_dstaddr != NULL)
|
||||
free(ifi->ifi_dstaddr);
|
||||
ifinext = ifi->ifi_next; /* can't fetch ifi_next after free() */
|
||||
free(ifi); /* the ifi_info{} itself */
|
||||
}
|
||||
}
|
||||
/* end free_ifi_info */
|
||||
|
||||
ssize_t
|
||||
recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
|
||||
struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct iovec iov[1];
|
||||
ssize_t n;
|
||||
|
||||
#ifdef CMSG_FIRSTHDR
|
||||
struct cmsghdr *cmptr;
|
||||
union {
|
||||
struct cmsghdr cm;
|
||||
char control[1024];
|
||||
} control_un;
|
||||
|
||||
*ttl = 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be
|
||||
|
||||
msg.msg_control = control_un.control;
|
||||
msg.msg_controllen = sizeof(control_un.control);
|
||||
msg.msg_flags = 0;
|
||||
#else
|
||||
memset(&msg, 0, sizeof(msg)); /* make certain msg_accrightslen = 0 */
|
||||
#endif /* CMSG_FIRSTHDR */
|
||||
|
||||
msg.msg_name = (char *) sa;
|
||||
msg.msg_namelen = *salenptr;
|
||||
iov[0].iov_base = (char *)ptr;
|
||||
iov[0].iov_len = nbytes;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
if ( (n = recvmsg(fd, &msg, *flagsp)) < 0)
|
||||
return(n);
|
||||
|
||||
*salenptr = msg.msg_namelen; /* pass back results */
|
||||
if (pktp) {
|
||||
/* 0.0.0.0, i/f = -1 */
|
||||
/* We set the interface to -1 so that the caller can
|
||||
tell whether we returned a meaningful value or
|
||||
just some default. Previously this code just
|
||||
set the value to 0, but I'm concerned that 0
|
||||
might be a valid interface value.
|
||||
*/
|
||||
memset(pktp, 0, sizeof(struct my_in_pktinfo));
|
||||
pktp->ipi_ifindex = -1;
|
||||
}
|
||||
/* end recvfrom_flags1 */
|
||||
|
||||
/* include recvfrom_flags2 */
|
||||
#ifndef CMSG_FIRSTHDR
|
||||
#warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
|
||||
*flagsp = 0; /* pass back results */
|
||||
return(n);
|
||||
#else
|
||||
|
||||
*flagsp = msg.msg_flags; /* pass back results */
|
||||
if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) ||
|
||||
(msg.msg_flags & MSG_CTRUNC) || pktp == NULL)
|
||||
return(n);
|
||||
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
|
||||
cmptr = CMSG_NXTHDR(&msg, cmptr)) {
|
||||
|
||||
#ifdef IP_PKTINFO
|
||||
#if in_pktinfo_definition_is_missing
|
||||
struct in_pktinfo
|
||||
{
|
||||
int ipi_ifindex;
|
||||
struct in_addr ipi_spec_dst;
|
||||
struct in_addr ipi_addr;
|
||||
};
|
||||
#endif
|
||||
if (cmptr->cmsg_level == IPPROTO_IP &&
|
||||
cmptr->cmsg_type == IP_PKTINFO) {
|
||||
struct in_pktinfo *tmp;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
|
||||
|
||||
tmp = (struct in_pktinfo *) CMSG_DATA(cmptr);
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr = tmp->ipi_addr;
|
||||
sin->sin_port = 0;
|
||||
pktp->ipi_ifindex = tmp->ipi_ifindex;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IP_RECVDSTADDR
|
||||
if (cmptr->cmsg_level == IPPROTO_IP &&
|
||||
cmptr->cmsg_type == IP_RECVDSTADDR) {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
|
||||
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr);
|
||||
sin->sin_port = 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IP_RECVIF
|
||||
if (cmptr->cmsg_level == IPPROTO_IP &&
|
||||
cmptr->cmsg_type == IP_RECVIF) {
|
||||
struct sockaddr_dl *sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr);
|
||||
#ifndef HAVE_BROKEN_RECVIF_NAME
|
||||
int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1);
|
||||
strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen);
|
||||
#endif
|
||||
pktp->ipi_ifindex = sdl->sdl_index;
|
||||
#ifdef HAVE_BROKEN_RECVIF_NAME
|
||||
if (sdl->sdl_index == 0) {
|
||||
pktp->ipi_ifindex = *(uint_t*)sdl;
|
||||
}
|
||||
#endif
|
||||
assert(pktp->ipi_ifname[IFI_NAME - 1] == 0);
|
||||
// null terminated because of memset above
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IP_RECVTTL
|
||||
if (cmptr->cmsg_level == IPPROTO_IP &&
|
||||
cmptr->cmsg_type == IP_RECVTTL) {
|
||||
*ttl = *(u_char*)CMSG_DATA(cmptr);
|
||||
continue;
|
||||
}
|
||||
else if (cmptr->cmsg_level == IPPROTO_IP &&
|
||||
cmptr->cmsg_type == IP_TTL) { // some implementations seem to send IP_TTL instead of IP_RECVTTL
|
||||
*ttl = *(int*)CMSG_DATA(cmptr);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(IPV6_PKTINFO) && HAVE_IPV6
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
|
||||
cmptr->cmsg_type == IPV6_2292_PKTINFO) {
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
|
||||
struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
|
||||
|
||||
sin6->sin6_family = AF_INET6;
|
||||
#ifndef NOT_HAVE_SA_LEN
|
||||
sin6->sin6_len = sizeof(*sin6);
|
||||
#endif
|
||||
sin6->sin6_addr = ip6_info->ipi6_addr;
|
||||
sin6->sin6_flowinfo = 0;
|
||||
sin6->sin6_scope_id = 0;
|
||||
sin6->sin6_port = 0;
|
||||
pktp->ipi_ifindex = ip6_info->ipi6_ifindex;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(IPV6_HOPLIMIT) && HAVE_IPV6
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
|
||||
cmptr->cmsg_type == IPV6_2292_HOPLIMIT) {
|
||||
*ttl = *(int*)CMSG_DATA(cmptr);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
assert(0); // unknown ancillary data
|
||||
}
|
||||
return(n);
|
||||
#endif /* CMSG_FIRSTHDR */
|
||||
}
|
||||
|
||||
// **********************************************************************************************
|
||||
|
||||
// daemonize the process. Adapted from "Unix Network Programming" vol 1 by Stevens, section 12.4.
|
||||
// Returns 0 on success, -1 on failure.
|
||||
|
||||
#ifdef NOT_HAVE_DAEMON
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/signal.h>
|
||||
|
||||
int daemon(int nochdir, int noclose)
|
||||
{
|
||||
switch (fork())
|
||||
{
|
||||
case -1: return (-1); // Fork failed
|
||||
case 0: break; // Child -- continue
|
||||
default: _exit(0); // Parent -- exit
|
||||
}
|
||||
|
||||
if (setsid() == -1) return(-1);
|
||||
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
|
||||
switch (fork()) // Fork again, primarily for reasons of Unix trivia
|
||||
{
|
||||
case -1: return (-1); // Fork failed
|
||||
case 0: break; // Child -- continue
|
||||
default: _exit(0); // Parent -- exit
|
||||
}
|
||||
|
||||
if (!nochdir) (void)chdir("/");
|
||||
umask(0);
|
||||
|
||||
if (!noclose)
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR, 0);
|
||||
if (fd != -1)
|
||||
{
|
||||
// Avoid unnecessarily duplicating a file descriptor to itself
|
||||
if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO);
|
||||
if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO);
|
||||
if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO);
|
||||
if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
|
||||
(void)close (fd);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif /* NOT_HAVE_DAEMON */
|
@@ -1,130 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __mDNSUNP_h
|
||||
#define __mDNSUNP_h
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef HAVE_LINUX
|
||||
#include <linux/socket.h>
|
||||
#define IPV6_2292_PKTINFO IPV6_2292PKTINFO
|
||||
#define IPV6_2292_HOPLIMIT IPV6_2292HOPLIMIT
|
||||
#else
|
||||
// The following are the supported non-linux posix OSes -
|
||||
// netbsd, freebsd and openbsd.
|
||||
#if HAVE_IPV6
|
||||
#define IPV6_2292_PKTINFO 19
|
||||
#define IPV6_2292_HOPLIMIT 20
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef NOT_HAVE_SOCKLEN_T
|
||||
typedef unsigned int socklen_t;
|
||||
#endif
|
||||
|
||||
#if !defined(_SS_MAXSIZE)
|
||||
#if HAVE_IPV6
|
||||
#define sockaddr_storage sockaddr_in6
|
||||
#else
|
||||
#define sockaddr_storage sockaddr
|
||||
#endif // HAVE_IPV6
|
||||
#endif // !defined(_SS_MAXSIZE)
|
||||
|
||||
#ifndef NOT_HAVE_SA_LEN
|
||||
#define GET_SA_LEN(X) (sizeof(struct sockaddr) > ((struct sockaddr*)&(X))->sa_len ? \
|
||||
sizeof(struct sockaddr) : ((struct sockaddr*)&(X))->sa_len )
|
||||
#elif HAVE_IPV6
|
||||
#define GET_SA_LEN(X) (((struct sockaddr*)&(X))->sa_family == AF_INET ? sizeof(struct sockaddr_in) : \
|
||||
((struct sockaddr*)&(X))->sa_family == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr))
|
||||
#else
|
||||
#define GET_SA_LEN(X) (((struct sockaddr*)&(X))->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr))
|
||||
#endif
|
||||
|
||||
#define IFI_NAME 16 /* same as IFNAMSIZ in <net/if.h> */
|
||||
#define IFI_HADDR 8 /* allow for 64-bit EUI-64 in future */
|
||||
|
||||
// Renamed from my_in_pktinfo because in_pktinfo is used by Linux.
|
||||
|
||||
struct my_in_pktinfo {
|
||||
struct sockaddr_storage ipi_addr;
|
||||
int ipi_ifindex; /* received interface index */
|
||||
char ipi_ifname[IFI_NAME]; /* received interface name */
|
||||
};
|
||||
|
||||
/* From the text (Stevens, section 20.2): */
|
||||
/* 'As an example of recvmsg we will write a function named recvfrom_flags that */
|
||||
/* is similar to recvfrom but also returns: */
|
||||
/* 1. the returned msg_flags value, */
|
||||
/* 2. the destination addres of the received datagram (from the IP_RECVDSTADDR socket option, and */
|
||||
/* 3. the index of the interface on which the datagram was received (the IP_RECVIF socket option).' */
|
||||
extern ssize_t recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
|
||||
struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl);
|
||||
|
||||
struct ifi_info {
|
||||
char ifi_name[IFI_NAME]; /* interface name, null terminated */
|
||||
u_char ifi_haddr[IFI_HADDR]; /* hardware address */
|
||||
u_short ifi_hlen; /* #bytes in hardware address: 0, 6, 8 */
|
||||
short ifi_flags; /* IFF_xxx constants from <net/if.h> */
|
||||
short ifi_myflags; /* our own IFI_xxx flags */
|
||||
int ifi_index; /* interface index */
|
||||
struct sockaddr *ifi_addr; /* primary address */
|
||||
struct sockaddr *ifi_netmask;
|
||||
struct sockaddr *ifi_brdaddr;/* broadcast address */
|
||||
struct sockaddr *ifi_dstaddr;/* destination address */
|
||||
struct ifi_info *ifi_next; /* next of these structures */
|
||||
};
|
||||
|
||||
#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
|
||||
#define PROC_IFINET6_PATH "/proc/net/if_inet6"
|
||||
extern struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases);
|
||||
#endif
|
||||
|
||||
#if defined(AF_INET6) && HAVE_IPV6
|
||||
#define INET6_ADDRSTRLEN 46 /*Maximum length of IPv6 address */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define IFI_ALIAS 1 /* ifi_addr is an alias */
|
||||
|
||||
/* From the text (Stevens, section 16.6): */
|
||||
/* 'Since many programs need to know all the interfaces on a system, we will develop a */
|
||||
/* function of our own named get_ifi_info that returns a linked list of structures, one */
|
||||
/* for each interface that is currently "up."' */
|
||||
extern struct ifi_info *get_ifi_info(int family, int doaliases);
|
||||
|
||||
/* 'The free_ifi_info function, which takes a pointer that was */
|
||||
/* returned by get_ifi_info and frees all the dynamic memory.' */
|
||||
extern void free_ifi_info(struct ifi_info *);
|
||||
|
||||
#ifdef NOT_HAVE_DAEMON
|
||||
extern int daemon(int nochdir, int noclose);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@@ -1,163 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __MDNS_WIN32__
|
||||
#define __MDNS_WIN32__
|
||||
|
||||
#include "CommonServices.h"
|
||||
|
||||
#if( !defined( _WIN32_WCE ) )
|
||||
#include <mswsock.h>
|
||||
#endif
|
||||
|
||||
#include "mDNSEmbeddedAPI.h"
|
||||
#include "uDNS.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef void ( *TCPUserCallback )();
|
||||
|
||||
struct TCPSocket_struct
|
||||
{
|
||||
TCPSocketFlags flags; // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with TCPSocketFlags flags
|
||||
SOCKET fd;
|
||||
BOOL connected;
|
||||
TCPUserCallback userCallback;
|
||||
void * userContext;
|
||||
BOOL closed;
|
||||
mDNS * m;
|
||||
};
|
||||
|
||||
|
||||
struct UDPSocket_struct
|
||||
{
|
||||
mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
|
||||
mDNSAddr addr; // This is initialized by our code. If we don't get the
|
||||
// dstAddr from WSARecvMsg we use this value instead.
|
||||
SOCKET fd;
|
||||
LPFN_WSARECVMSG recvMsgPtr;
|
||||
DNSMessage packet;
|
||||
struct mDNSInterfaceData *ifd;
|
||||
UDPSocket *next;
|
||||
mDNS *m;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------
|
||||
/*! @struct mDNSInterfaceData
|
||||
|
||||
@abstract Structure containing interface-specific data.
|
||||
*/
|
||||
|
||||
typedef struct mDNSInterfaceData mDNSInterfaceData;
|
||||
struct mDNSInterfaceData
|
||||
{
|
||||
char name[ 128 ];
|
||||
uint32_t index;
|
||||
uint32_t scopeID;
|
||||
struct UDPSocket_struct sock;
|
||||
NetworkInterfaceInfo interfaceInfo;
|
||||
mDNSBool hostRegistered;
|
||||
mDNSInterfaceData * next;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------
|
||||
/*! @typedef ReportStatusFunc
|
||||
*/
|
||||
typedef void (*ReportStatusFunc)(int inType, const char *inFormat, ...);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------
|
||||
/*! @struct mDNS_PlatformSupport_struct
|
||||
|
||||
@abstract Structure containing platform-specific data.
|
||||
*/
|
||||
|
||||
struct mDNS_PlatformSupport_struct
|
||||
{
|
||||
HANDLE mainThread;
|
||||
HANDLE checkFileSharesTimer;
|
||||
mDNSs32 checkFileSharesTimeout;
|
||||
ReportStatusFunc reportStatusFunc;
|
||||
time_t nextDHCPLeaseExpires;
|
||||
char nbname[ 32 ];
|
||||
char nbdomain[ 32 ];
|
||||
mDNSBool smbFileSharing;
|
||||
mDNSBool smbPrintSharing;
|
||||
ServiceRecordSet smbSRS;
|
||||
AuthRecord smbSubTypes[ 2 ];
|
||||
mDNSBool registeredLoopback4;
|
||||
int interfaceCount;
|
||||
mDNSInterfaceData * interfaceList;
|
||||
mDNSInterfaceData * inactiveInterfaceList;
|
||||
struct UDPSocket_struct unicastSock4;
|
||||
struct UDPSocket_struct unicastSock6;
|
||||
DWORD osMajorVersion;
|
||||
DWORD osMinorVersion;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------
|
||||
/*! @struct ifaddrs
|
||||
|
||||
@abstract Interface information
|
||||
*/
|
||||
|
||||
struct ifaddrs
|
||||
{
|
||||
struct ifaddrs * ifa_next;
|
||||
char * ifa_name;
|
||||
u_int ifa_flags;
|
||||
struct sockaddr * ifa_addr;
|
||||
struct sockaddr * ifa_netmask;
|
||||
struct sockaddr * ifa_broadaddr;
|
||||
struct sockaddr * ifa_dstaddr;
|
||||
BYTE ifa_physaddr[6];
|
||||
BOOL ifa_dhcpEnabled;
|
||||
time_t ifa_dhcpLeaseExpires;
|
||||
mDNSu8 ifa_womp;
|
||||
void * ifa_data;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
} ifa_extra;
|
||||
};
|
||||
|
||||
|
||||
extern void InterfaceListDidChange( mDNS * const inMDNS );
|
||||
extern void ComputerDescriptionDidChange( mDNS * const inMDNS );
|
||||
extern void TCPIPConfigDidChange( mDNS * const inMDNS );
|
||||
extern void DynDNSConfigDidChange( mDNS * const inMDNS );
|
||||
extern void FileSharingDidChange( mDNS * const inMDNS );
|
||||
extern void FirewallDidChange( mDNS * const inMDNS );
|
||||
extern mStatus TCPAddSocket( mDNS * const inMDNS, TCPSocket *sock );
|
||||
extern mStatus SetupInterfaceList( mDNS * const inMDNS );
|
||||
extern mStatus TearDownInterfaceList( mDNS * const inMDNS );
|
||||
extern BOOL IsWOMPEnabled();
|
||||
extern void DispatchSocketEvents( mDNS * const inMDNS );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __MDNS_WIN32__
|
@@ -1,38 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Service.h"
|
||||
#include "Shellapi.h"
|
||||
|
||||
//===========================================================================================================================
|
||||
// main
|
||||
//===========================================================================================================================
|
||||
int APIENTRY wWinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPTSTR lpCmdLine,
|
||||
int nCmdShow)
|
||||
{
|
||||
LPWSTR *argv;
|
||||
int argc, res;
|
||||
|
||||
argv = CommandLineToArgvW(lpCmdLine, &argc);
|
||||
if (argv == NULL)
|
||||
argc = 0;
|
||||
res = Main( argc, argv );
|
||||
LocalFree(argv);
|
||||
return res;
|
||||
}
|
@@ -1,104 +0,0 @@
|
||||
QT -= gui
|
||||
QT -= core
|
||||
TEST = 0
|
||||
include(../../../qtcreator.pri)
|
||||
CONFIG -= console testlib TEST
|
||||
TARGET = mdnssd
|
||||
CONFIG -= app_bundle
|
||||
|
||||
TEMPLATE = app
|
||||
|
||||
DESTDIR = $$IDE_BIN_PATH
|
||||
|
||||
DEFINES += PID_FILE=\\\"/tmp/mdnsd.pid\\\" MDNS_UDS_SERVERPATH=\\\"/tmp/mdnsd\\\" MDNS_DEBUGMSGS=0
|
||||
|
||||
SOURCES += \
|
||||
uds_daemon.c \
|
||||
uDNS.c \
|
||||
mDNSDebug.c \
|
||||
mDNS.c \
|
||||
GenLinkedList.c \
|
||||
dnssd_ipc.c \
|
||||
DNSDigest.c \
|
||||
DNSCommon.c
|
||||
|
||||
HEADERS += \
|
||||
uds_daemon.h \
|
||||
uDNS.h \
|
||||
mDNSUNP.h \
|
||||
mDNSEmbeddedAPI.h \
|
||||
mDNSDebug.h \
|
||||
GenLinkedList.h \
|
||||
dnssd_ipc.h \
|
||||
DNSCommon.h \
|
||||
DebugServices.h \
|
||||
dns_sd.h
|
||||
|
||||
linux-* {
|
||||
SOURCES += mDNSPosix.c \
|
||||
PlatformCommon.c \
|
||||
PosixDaemon.c \
|
||||
mDNSUNP.c
|
||||
|
||||
HEADERS +=\
|
||||
PlatformCommon.h \
|
||||
mDNSPosix.h
|
||||
}
|
||||
|
||||
*-g++ {
|
||||
QMAKE_CFLAGS += -Wno-unused-but-set-variable -Wno-strict-aliasing
|
||||
QMAKE_CXXFLAGS += -Wno-unused-but-set-variable
|
||||
}
|
||||
|
||||
linux-* {
|
||||
DEFINES += _GNU_SOURCE HAVE_IPV6 NOT_HAVE_SA_LEN USES_NETLINK HAVE_LINUX TARGET_OS_LINUX
|
||||
}
|
||||
|
||||
macx {
|
||||
DEFINES += HAVE_IPV6 __MAC_OS_X_VERSION_MIN_REQUIRED=__MAC_OS_X_VERSION_10_4 __APPLE_USE_RFC_2292
|
||||
}
|
||||
|
||||
win32 {
|
||||
HEADERS += \
|
||||
CommonServices.h \
|
||||
DebugServices.h \
|
||||
Firewall.h \
|
||||
mDNSWin32.h \
|
||||
Poll.h \
|
||||
resource.h \
|
||||
Secret.h \
|
||||
Service.h \
|
||||
RegNames.h
|
||||
|
||||
SOURCES += \
|
||||
DebugServices.c \
|
||||
Firewall.cpp \
|
||||
LegacyNATTraversal.c \
|
||||
main.c \
|
||||
mDNSWin32.c \
|
||||
Poll.c \
|
||||
Secret.c \
|
||||
Service.c
|
||||
|
||||
RC_FILE = Service.rc
|
||||
|
||||
MC_FILES += \
|
||||
EventLog.mc
|
||||
|
||||
OTHER_FILES += \
|
||||
$$MC_FILES \
|
||||
Service.rc
|
||||
|
||||
DEFINES += NDEBUG
|
||||
DEFINES += HAVE_IPV6 _WIN32_WINNT=0x0501 MDNS_DEBUGMSGS=0 TARGET_OS_WIN32 WIN32_LEAN_AND_MEAN USE_TCP_LOOPBACK PLATFORM_NO_STRSEP PLATFORM_NO_EPIPE PLATFORM_NO_RLIMIT UNICODE _UNICODE _CRT_SECURE_NO_DEPRECATE _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1 _LEGACY_NAT_TRAVERSAL_
|
||||
LIBS += ws2_32.lib advapi32.lib ole32.lib oleaut32.lib iphlpapi.lib netapi32.lib user32.lib powrprof.lib shell32.lib
|
||||
|
||||
mc.output = ${QMAKE_FILE_BASE}.rc
|
||||
mc.commands = mc ${QMAKE_FILE_NAME}
|
||||
mc.input = MC_FILES
|
||||
mc.CONFIG += no_link target_predeps explicit_dependencies
|
||||
QMAKE_EXTRA_COMPILERS += mc
|
||||
}
|
||||
|
||||
target.path=/bin
|
||||
INSTALLS+=target
|
@@ -1,164 +0,0 @@
|
||||
import qbs.base 1.0
|
||||
import qbs.fileinfo 1.0 as FileInfo
|
||||
import "../QtcTool.qbs" as QtcTool
|
||||
|
||||
QtcTool {
|
||||
name: "mdnssd"
|
||||
|
||||
cpp.defines: [
|
||||
'PID_FILE="/tmp/mdnsd.pid"',
|
||||
'MDNS_UDS_SERVERPATH="/tmp/mdnsd"',
|
||||
"MDNS_DEBUGMSGS=0",
|
||||
"HAVE_IPV6"
|
||||
]
|
||||
cpp.includePaths: [
|
||||
".",
|
||||
buildDirectory
|
||||
]
|
||||
|
||||
Depends { name: "cpp" }
|
||||
|
||||
files: [
|
||||
"uds_daemon.c",
|
||||
"uds_daemon.h",
|
||||
"uDNS.c",
|
||||
"uDNS.h",
|
||||
"mDNSDebug.c",
|
||||
"mDNSDebug.h",
|
||||
"GenLinkedList.c",
|
||||
"GenLinkedList.h",
|
||||
"dnssd_ipc.c",
|
||||
"dnssd_ipc.h",
|
||||
"DNSDigest.c",
|
||||
"DNSCommon.c",
|
||||
"mDNSUNP.h",
|
||||
"mDNSEmbeddedAPI.h",
|
||||
"DNSCommon.h",
|
||||
"DebugServices.h",
|
||||
"dns_sd.h",
|
||||
"mDNS.c"
|
||||
]
|
||||
|
||||
Group {
|
||||
condition: qbs.targetOS == "linux"
|
||||
files: [
|
||||
"mDNSPosix.c",
|
||||
"mDNSPosix.h",
|
||||
"PlatformCommon.c",
|
||||
"PlatformCommon.h",
|
||||
"PosixDaemon.c",
|
||||
"mDNSUNP.c"
|
||||
]
|
||||
}
|
||||
|
||||
Properties {
|
||||
condition: qbs.targetOS == "linux"
|
||||
cpp.defines: outer.concat([
|
||||
"_GNU_SOURCE",
|
||||
"NOT_HAVE_SA_LEN",
|
||||
"USES_NETLINK",
|
||||
"HAVE_LINUX",
|
||||
"TARGET_OS_LINUX"
|
||||
])
|
||||
}
|
||||
|
||||
Properties {
|
||||
condition: qbs.targetOS == "macx"
|
||||
cpp.defines: outer.concat([
|
||||
"__MAC_OS_X_VERSION_MIN_REQUIRED=__MAC_OS_X_VERSION_10_4",
|
||||
"__APPLE_USE_RFC_2292"
|
||||
])
|
||||
}
|
||||
|
||||
Group {
|
||||
condition: qbs.targetOS == "windows"
|
||||
files: [
|
||||
"Firewall.h",
|
||||
"Firewall.cpp",
|
||||
"mDNSWin32.h",
|
||||
"mDNSWin32.c",
|
||||
"Poll.h",
|
||||
"Poll.c",
|
||||
"Secret.h",
|
||||
"Secret.c",
|
||||
"Service.h",
|
||||
"Service.c",
|
||||
"DebugServices.c",
|
||||
"LegacyNATTraversal.c",
|
||||
"resource.h",
|
||||
"RegNames.h",
|
||||
"CommonServices.h",
|
||||
"main.c",
|
||||
"EventLog.mc",
|
||||
"Service.rc"
|
||||
]
|
||||
}
|
||||
|
||||
Properties {
|
||||
condition: qbs.targetOS == "windows"
|
||||
cpp.includePaths: outer.concat([buildDirectory + "/" + name])
|
||||
cpp.defines: outer.concat([
|
||||
"WIN32",
|
||||
"_WIN32_WINNT=0x0501",
|
||||
"NDEBUG",
|
||||
"MDNS_DEBUGMSGS=0",
|
||||
"TARGET_OS_WIN32",
|
||||
"WIN32_LEAN_AND_MEAN",
|
||||
"USE_TCP_LOOPBACK",
|
||||
"PLATFORM_NO_STRSEP",
|
||||
"PLATFORM_NO_EPIPE",
|
||||
"PLATFORM_NO_RLIMIT",
|
||||
"UNICODE",
|
||||
"_UNICODE",
|
||||
"_CRT_SECURE_NO_DEPRECATE",
|
||||
"_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1",
|
||||
"_LEGACY_NAT_TRAVERSAL_"
|
||||
])
|
||||
cpp.dynamicLibraries: [
|
||||
"ws2_32.lib",
|
||||
"advapi32.lib",
|
||||
"ole32.lib",
|
||||
"oleaut32.lib",
|
||||
"iphlpapi.lib",
|
||||
"netapi32.lib",
|
||||
"user32.lib",
|
||||
"powrprof.lib",
|
||||
"shell32.lib"
|
||||
]
|
||||
}
|
||||
|
||||
Properties {
|
||||
condition: qbs.toolchain == 'mingw' || qbs.toolchain == 'gcc'
|
||||
cpp.cFlags: [
|
||||
"-Wno-unused-but-set-variable",
|
||||
"-Wno-strict-aliasing"
|
||||
]
|
||||
cpp.cxxFlags: [
|
||||
"-Wno-unused-but-set-variable"
|
||||
]
|
||||
}
|
||||
|
||||
FileTagger {
|
||||
pattern: "*.mc"
|
||||
fileTags: "mc"
|
||||
}
|
||||
|
||||
Rule {
|
||||
inputs: "mc"
|
||||
Artifact {
|
||||
fileName: product.name + "/" + input.baseName + ".h"
|
||||
fileTags: "hpp"
|
||||
}
|
||||
Artifact {
|
||||
fileName: product.name + "/" + input.baseName + ".rc"
|
||||
fileTags: "mc_result"
|
||||
}
|
||||
prepare: {
|
||||
var cmd = new Command("mc", input.fileName);
|
||||
cmd.workingDirectory = FileInfo.path(outputs["mc_result"][0].fileName);
|
||||
cmd.description = "mc " + FileInfo.fileName(input.fileName);
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,17 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Service.rc
|
||||
//
|
||||
|
||||
#define IDS_SERVICE_DESCRIPTION 100
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@@ -1,136 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __UDNS_H_
|
||||
#define __UDNS_H_
|
||||
|
||||
#include "mDNSEmbeddedAPI.h"
|
||||
#include "DNSCommon.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RESTART_GOODBYE_DELAY (6 * mDNSPlatformOneSecond) // delay after restarting LLQ before nuking previous known answers (avoids flutter if we restart before we have networking up)
|
||||
#define INIT_UCAST_POLL_INTERVAL (3 * mDNSPlatformOneSecond) // this interval is used after send failures on network transitions
|
||||
// which typically heal quickly, so we start agressively and exponentially back off
|
||||
#define MAX_UCAST_POLL_INTERVAL (60 * 60 * mDNSPlatformOneSecond)
|
||||
//#define MAX_UCAST_POLL_INTERVAL (1 * 60 * mDNSPlatformOneSecond)
|
||||
#define LLQ_POLL_INTERVAL (15 * 60 * mDNSPlatformOneSecond) // Polling interval for zones w/ an advertised LLQ port (ie not static zones) if LLQ fails due to NAT, etc.
|
||||
#define RESPONSE_WINDOW (60 * mDNSPlatformOneSecond) // require server responses within one minute of request
|
||||
#define MAX_UCAST_UNANSWERED_QUERIES 2 // the number of unanswered queries from any one uDNS server before trying another server
|
||||
#define DNSSERVER_PENALTY_TIME (60 * mDNSPlatformOneSecond) // number of seconds for which new questions don't pick this server
|
||||
|
||||
// On some interfaces, we want to delay the first retransmission to a minimum of 2 seconds
|
||||
// rather than the default (1 second).
|
||||
#define MIN_UCAST_RETRANS_TIMEOUT (2 * mDNSPlatformOneSecond)
|
||||
|
||||
#define DEFAULT_UPDATE_LEASE 7200
|
||||
|
||||
#define QuestionIntervalStep 3
|
||||
#define QuestionIntervalStep2 (QuestionIntervalStep*QuestionIntervalStep)
|
||||
#define QuestionIntervalStep3 (QuestionIntervalStep*QuestionIntervalStep*QuestionIntervalStep)
|
||||
#define InitialQuestionInterval ((mDNSPlatformOneSecond + QuestionIntervalStep-1) / QuestionIntervalStep)
|
||||
|
||||
// For Unicast record registrations, we initialize the interval to 1 second. When we send any query for
|
||||
// the record registration e.g., GetZoneData, we always back off by QuestionIntervalStep
|
||||
// so that the first retry does not happen until 3 seconds which should be enough for TCP/TLS to be done.
|
||||
#define INIT_RECORD_REG_INTERVAL (1 * mDNSPlatformOneSecond)
|
||||
#define MAX_RECORD_REG_INTERVAL (15 * 60 * mDNSPlatformOneSecond)
|
||||
#define MERGE_DELAY_TIME (1 * mDNSPlatformOneSecond)
|
||||
|
||||
// If we are refreshing, we do it at least 5 times with a min update frequency of
|
||||
// 5 minutes
|
||||
#define MAX_UPDATE_REFRESH_COUNT 5
|
||||
#define MIN_UPDATE_REFRESH_TIME (5 * 60 * mDNSPlatformOneSecond)
|
||||
|
||||
// For questions that use kDNSServiceFlagsTimeout and we don't have a matching resolver e.g., no dns servers,
|
||||
// then use the default value of 30 seconds
|
||||
#define DEFAULT_UDNS_TIMEOUT 30 // in seconds
|
||||
|
||||
// Entry points into unicast-specific routines
|
||||
|
||||
extern void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo);
|
||||
extern void startLLQHandshake(mDNS *m, DNSQuestion *q);
|
||||
extern void sendLLQRefresh(mDNS *m, DNSQuestion *q);
|
||||
|
||||
extern void SleepRecordRegistrations(mDNS *m);
|
||||
|
||||
// uDNS_UpdateRecord
|
||||
// following fields must be set, and the update validated, upon entry.
|
||||
// rr->NewRData
|
||||
// rr->newrdlength
|
||||
// rr->UpdateCallback
|
||||
|
||||
extern mStatus uDNS_UpdateRecord(mDNS *m, AuthRecord *rr);
|
||||
|
||||
extern void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q);
|
||||
extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name);
|
||||
extern mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr);
|
||||
extern mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt);
|
||||
extern mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question);
|
||||
extern mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question);
|
||||
extern mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalInfo *traversal);
|
||||
|
||||
extern void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData);
|
||||
extern mStatus uDNS_DeregisterRecord(mDNS *const m, AuthRecord *const rr);
|
||||
extern const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr);
|
||||
extern void uDNS_CheckCurrentQuestion(mDNS *const m);
|
||||
|
||||
// integer fields of msg header must be in HOST byte order before calling this routine
|
||||
extern void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
|
||||
const mDNSAddr *const srcaddr, const mDNSIPPort srcport);
|
||||
|
||||
extern void uDNS_Tasks(mDNS *const m);
|
||||
extern void UpdateAllSRVRecords(mDNS *m);
|
||||
extern void CheckNATMappings(mDNS *m);
|
||||
|
||||
extern mStatus uDNS_SetupDNSConfig(mDNS *const m);
|
||||
|
||||
// uDNS_SetupSearchDomains by default adds search domains. It also can be called with one or
|
||||
// more values for "action" which does the following:
|
||||
//
|
||||
// -UDNS_START_WAB_QUERY - start Wide Area Bonjour (domain enumeration) queries
|
||||
|
||||
#define UDNS_START_WAB_QUERY 0x00000001
|
||||
|
||||
extern mStatus uDNS_SetupSearchDomains(mDNS *const m, int action);
|
||||
extern domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
uDNS_LLQ_Not = 0, // Normal uDNS answer: Flush any stale records from cache, and respect record TTL
|
||||
uDNS_LLQ_Ignore, // LLQ initial challenge packet: ignore -- has no useful records for us
|
||||
uDNS_LLQ_Entire, // LLQ initial set of answers: Flush any stale records from cache, but assume TTL is 2 x LLQ refresh interval
|
||||
uDNS_LLQ_Events // LLQ event packet: don't flush cache; assume TTL is 2 x LLQ refresh interval
|
||||
} uDNS_LLQType;
|
||||
|
||||
extern uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, DNSQuestion **matchQuestion);
|
||||
extern DomainAuthInfo *GetAuthInfoForName_internal(mDNS *m, const domainname *const name);
|
||||
extern DomainAuthInfo *GetAuthInfoForQuestion(mDNS *m, const DNSQuestion *const q);
|
||||
extern void DisposeTCPConn(struct tcpInfo_t *tcp);
|
||||
|
||||
// NAT traversal
|
||||
extern void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID InterfaceID, mDNSu8 *pkt, mDNSu16 len); // Called for each received NAT-PMP packet
|
||||
extern void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv4Addr ExtAddr);
|
||||
extern void natTraversalHandlePortMapReply(mDNS *const m, NATTraversalInfo *n, const mDNSInterfaceID InterfaceID, mDNSu16 err, mDNSIPPort extport, mDNSu32 lease);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __UDNS_H_
|
File diff suppressed because it is too large
Load Diff
@@ -1,80 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
|
||||
File: uds_daemon.h
|
||||
|
||||
Contains: Interfaces necessary to talk to uds_daemon.c.
|
||||
|
||||
Version: 1.0
|
||||
|
||||
*/
|
||||
|
||||
#include "mDNSEmbeddedAPI.h"
|
||||
#include "dnssd_ipc.h"
|
||||
|
||||
/* Client interface: */
|
||||
|
||||
#define SRS_PORT(S) mDNSVal16((S)->RR_SRV.resrec.rdata->u.srv.port)
|
||||
|
||||
extern int udsserver_init(dnssd_sock_t skts[], mDNSu32 count);
|
||||
extern mDNSs32 udsserver_idle(mDNSs32 nextevent);
|
||||
extern void udsserver_info(mDNS *const m); // print out info about current state
|
||||
extern void udsserver_handle_configchange(mDNS *const m);
|
||||
extern int udsserver_exit(void); // should be called prior to app exit
|
||||
|
||||
/* Routines that uds_daemon expects to link against: */
|
||||
|
||||
typedef void (*udsEventCallback)(int fd, short filter, void *context);
|
||||
extern mStatus udsSupportAddFDToEventLoop(dnssd_sock_t fd, udsEventCallback callback, void *context, void **platform_data);
|
||||
extern int udsSupportReadFD(dnssd_sock_t fd, char* buf, int len, int flags, void *platform_data);
|
||||
extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd, void *platform_data); // Note: This also CLOSES the file descriptor as well
|
||||
|
||||
extern void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay);
|
||||
|
||||
// Globals and functions defined in uds_daemon.c and also shared with the old "daemon.c" on OS X
|
||||
|
||||
extern mDNS mDNSStorage;
|
||||
extern DNameListElem *AutoRegistrationDomains;
|
||||
extern DNameListElem *AutoBrowseDomains;
|
||||
|
||||
extern mDNSs32 ChopSubTypes(char *regtype);
|
||||
extern AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p);
|
||||
extern int CountExistingRegistrations(domainname *srv, mDNSIPPort port);
|
||||
extern void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result);
|
||||
extern int CountPeerRegistrations(mDNS *const m, ServiceRecordSet *const srs);
|
||||
|
||||
#if APPLE_OSX_mDNSResponder
|
||||
extern void machserver_automatic_browse_domain_changed(const domainname *d, mDNSBool add);
|
||||
extern void machserver_automatic_registration_domain_changed(const domainname *d, mDNSBool add);
|
||||
// External support
|
||||
extern void mDNSInitPacketFilter(void);
|
||||
extern void external_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype);
|
||||
extern void external_stop_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype);
|
||||
extern void external_start_advertising_service(const ResourceRecord *const resourceRecord);
|
||||
extern void external_stop_advertising_service(const ResourceRecord *const resourceRecord);
|
||||
extern void external_start_resolving_service(const domainname *const fqdn);
|
||||
extern void external_stop_resolving_service(const domainname *const fqdn);
|
||||
#else
|
||||
#define external_start_browsing_for_service(A,B,C) (void)(A)
|
||||
#define external_stop_browsing_for_service(A,B,C) (void)(A)
|
||||
#define external_start_advertising_service(A) (void)(A)
|
||||
#define external_stop_advertising_service(A) (void)(A)
|
||||
#define external_start_resolving_service(A) (void)(A)
|
||||
#define external_stop_resolving_service(A) (void)(A)
|
||||
#endif // APPLE_OSX_mDNSResponder
|
||||
|
||||
extern const char mDNSResponderVersionString_SCCS[];
|
||||
#define mDNSResponderVersionString (mDNSResponderVersionString_SCCS+5)
|
@@ -18,10 +18,6 @@ win32 {
|
||||
SUBDIRS += valgrindfake
|
||||
}
|
||||
|
||||
linux-* {
|
||||
SUBDIRS += mdnssd
|
||||
}
|
||||
|
||||
QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
|
||||
!isEmpty(QT_BREAKPAD_ROOT_PATH) {
|
||||
SUBDIRS += qtcrashhandler
|
||||
|
Reference in New Issue
Block a user