1*48a54d36SAndroid Build Coastguard Worker /* -*- Mode: C; tab-width: 4 -*-
2*48a54d36SAndroid Build Coastguard Worker *
3*48a54d36SAndroid Build Coastguard Worker * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4*48a54d36SAndroid Build Coastguard Worker *
5*48a54d36SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*48a54d36SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*48a54d36SAndroid Build Coastguard Worker * You may obtain a copy of the License at
8*48a54d36SAndroid Build Coastguard Worker *
9*48a54d36SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
10*48a54d36SAndroid Build Coastguard Worker *
11*48a54d36SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*48a54d36SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*48a54d36SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*48a54d36SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*48a54d36SAndroid Build Coastguard Worker * limitations under the License.
16*48a54d36SAndroid Build Coastguard Worker *
17*48a54d36SAndroid Build Coastguard Worker * Formatting notes:
18*48a54d36SAndroid Build Coastguard Worker * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion
19*48a54d36SAndroid Build Coastguard Worker * on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>,
20*48a54d36SAndroid Build Coastguard Worker * but for the sake of brevity here I will say just this: Curly braces are not syntactially
21*48a54d36SAndroid Build Coastguard Worker * part of an "if" statement; they are the beginning and ending markers of a compound statement;
22*48a54d36SAndroid Build Coastguard Worker * therefore common sense dictates that if they are part of a compound statement then they
23*48a54d36SAndroid Build Coastguard Worker * should be indented to the same level as everything else in that compound statement.
24*48a54d36SAndroid Build Coastguard Worker * Indenting curly braces at the same level as the "if" implies that curly braces are
25*48a54d36SAndroid Build Coastguard Worker * part of the "if", which is false. (This is as misleading as people who write "char* x,y;"
26*48a54d36SAndroid Build Coastguard Worker * thinking that variables x and y are both of type "char*" -- and anyone who doesn't
27*48a54d36SAndroid Build Coastguard Worker * understand why variable y is not of type "char*" just proves the point that poor code
28*48a54d36SAndroid Build Coastguard Worker * layout leads people to unfortunate misunderstandings about how the C language really works.)
29*48a54d36SAndroid Build Coastguard Worker */
30*48a54d36SAndroid Build Coastguard Worker
31*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
32*48a54d36SAndroid Build Coastguard Worker // Incorporate mDNS.c functionality
33*48a54d36SAndroid Build Coastguard Worker
34*48a54d36SAndroid Build Coastguard Worker // We want to use much of the functionality provided by "mDNS.c",
35*48a54d36SAndroid Build Coastguard Worker // except we'll steal the packets that would be sent to normal mDNSCoreReceive() routine
36*48a54d36SAndroid Build Coastguard Worker #define mDNSCoreReceive __NOT__mDNSCoreReceive__NOT__
37*48a54d36SAndroid Build Coastguard Worker #include "mDNS.c"
38*48a54d36SAndroid Build Coastguard Worker #undef mDNSCoreReceive
39*48a54d36SAndroid Build Coastguard Worker
40*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
41*48a54d36SAndroid Build Coastguard Worker // Headers
42*48a54d36SAndroid Build Coastguard Worker
43*48a54d36SAndroid Build Coastguard Worker #include <stdio.h> // For printf()
44*48a54d36SAndroid Build Coastguard Worker #include <stdlib.h> // For malloc()
45*48a54d36SAndroid Build Coastguard Worker #include <string.h> // For strrchr(), strcmp()
46*48a54d36SAndroid Build Coastguard Worker #include <time.h> // For "struct tm" etc.
47*48a54d36SAndroid Build Coastguard Worker #include <signal.h> // For SIGINT, SIGTERM
48*48a54d36SAndroid Build Coastguard Worker #if defined(WIN32)
49*48a54d36SAndroid Build Coastguard Worker // Both mDNS.c and mDNSWin32.h declare UDPSocket_struct type resulting in a compile-time error, so
50*48a54d36SAndroid Build Coastguard Worker // trick the compiler when including mDNSWin32.h
51*48a54d36SAndroid Build Coastguard Worker # define UDPSocket_struct _UDPSocket_struct
52*48a54d36SAndroid Build Coastguard Worker # include <mDNSEmbeddedAPI.h>
53*48a54d36SAndroid Build Coastguard Worker # include <mDNSWin32.h>
54*48a54d36SAndroid Build Coastguard Worker # include <PosixCompat.h>
55*48a54d36SAndroid Build Coastguard Worker # define IFNAMSIZ 256
56*48a54d36SAndroid Build Coastguard Worker static HANDLE gStopEvent = INVALID_HANDLE_VALUE;
ConsoleControlHandler(DWORD inControlEvent)57*48a54d36SAndroid Build Coastguard Worker static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent ) { SetEvent( gStopEvent ); return TRUE; }
setlinebuf(FILE * fp)58*48a54d36SAndroid Build Coastguard Worker void setlinebuf( FILE * fp ) {}
59*48a54d36SAndroid Build Coastguard Worker #else
60*48a54d36SAndroid Build Coastguard Worker # include <netdb.h> // For gethostbyname()
61*48a54d36SAndroid Build Coastguard Worker # include <sys/socket.h> // For AF_INET, AF_INET6, etc.
62*48a54d36SAndroid Build Coastguard Worker # include <net/if.h> // For IF_NAMESIZE
63*48a54d36SAndroid Build Coastguard Worker # include <netinet/in.h> // For INADDR_NONE
64*48a54d36SAndroid Build Coastguard Worker # include <arpa/inet.h> // For inet_addr()
65*48a54d36SAndroid Build Coastguard Worker # include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform
66*48a54d36SAndroid Build Coastguard Worker #endif
67*48a54d36SAndroid Build Coastguard Worker #include "ExampleClientApp.h"
68*48a54d36SAndroid Build Coastguard Worker
69*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
70*48a54d36SAndroid Build Coastguard Worker // Types and structures
71*48a54d36SAndroid Build Coastguard Worker
72*48a54d36SAndroid Build Coastguard Worker enum
73*48a54d36SAndroid Build Coastguard Worker {
74*48a54d36SAndroid Build Coastguard Worker // Primitive operations
75*48a54d36SAndroid Build Coastguard Worker OP_probe = 0,
76*48a54d36SAndroid Build Coastguard Worker OP_goodbye = 1,
77*48a54d36SAndroid Build Coastguard Worker
78*48a54d36SAndroid Build Coastguard Worker // These are meta-categories;
79*48a54d36SAndroid Build Coastguard Worker // Query and Answer operations are actually subdivided into two classes:
80*48a54d36SAndroid Build Coastguard Worker // Browse query/answer and
81*48a54d36SAndroid Build Coastguard Worker // Resolve query/answer
82*48a54d36SAndroid Build Coastguard Worker OP_query = 2,
83*48a54d36SAndroid Build Coastguard Worker OP_answer = 3,
84*48a54d36SAndroid Build Coastguard Worker
85*48a54d36SAndroid Build Coastguard Worker // The "Browse" variants of query/answer
86*48a54d36SAndroid Build Coastguard Worker OP_browsegroup = 2,
87*48a54d36SAndroid Build Coastguard Worker OP_browseq = 2,
88*48a54d36SAndroid Build Coastguard Worker OP_browsea = 3,
89*48a54d36SAndroid Build Coastguard Worker
90*48a54d36SAndroid Build Coastguard Worker // The "Resolve" variants of query/answer
91*48a54d36SAndroid Build Coastguard Worker OP_resolvegroup = 4,
92*48a54d36SAndroid Build Coastguard Worker OP_resolveq = 4,
93*48a54d36SAndroid Build Coastguard Worker OP_resolvea = 5,
94*48a54d36SAndroid Build Coastguard Worker
95*48a54d36SAndroid Build Coastguard Worker OP_NumTypes = 6
96*48a54d36SAndroid Build Coastguard Worker };
97*48a54d36SAndroid Build Coastguard Worker
98*48a54d36SAndroid Build Coastguard Worker typedef struct ActivityStat_struct ActivityStat;
99*48a54d36SAndroid Build Coastguard Worker struct ActivityStat_struct
100*48a54d36SAndroid Build Coastguard Worker {
101*48a54d36SAndroid Build Coastguard Worker ActivityStat *next;
102*48a54d36SAndroid Build Coastguard Worker domainname srvtype;
103*48a54d36SAndroid Build Coastguard Worker int printed;
104*48a54d36SAndroid Build Coastguard Worker int totalops;
105*48a54d36SAndroid Build Coastguard Worker int stat[OP_NumTypes];
106*48a54d36SAndroid Build Coastguard Worker };
107*48a54d36SAndroid Build Coastguard Worker
108*48a54d36SAndroid Build Coastguard Worker typedef struct FilterList_struct FilterList;
109*48a54d36SAndroid Build Coastguard Worker struct FilterList_struct
110*48a54d36SAndroid Build Coastguard Worker {
111*48a54d36SAndroid Build Coastguard Worker FilterList *next;
112*48a54d36SAndroid Build Coastguard Worker mDNSAddr FilterAddr;
113*48a54d36SAndroid Build Coastguard Worker };
114*48a54d36SAndroid Build Coastguard Worker
115*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
116*48a54d36SAndroid Build Coastguard Worker // Constants
117*48a54d36SAndroid Build Coastguard Worker
118*48a54d36SAndroid Build Coastguard Worker #define kReportTopServices 15
119*48a54d36SAndroid Build Coastguard Worker #define kReportTopHosts 15
120*48a54d36SAndroid Build Coastguard Worker
121*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
122*48a54d36SAndroid Build Coastguard Worker // Globals
123*48a54d36SAndroid Build Coastguard Worker
124*48a54d36SAndroid Build Coastguard Worker mDNS mDNSStorage; // mDNS core uses this to store its globals
125*48a54d36SAndroid Build Coastguard Worker static mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals
126*48a54d36SAndroid Build Coastguard Worker mDNSexport const char ProgramName[] = "mDNSNetMonitor";
127*48a54d36SAndroid Build Coastguard Worker
128*48a54d36SAndroid Build Coastguard Worker struct timeval tv_start, tv_end, tv_interval;
129*48a54d36SAndroid Build Coastguard Worker static int FilterInterface = 0;
130*48a54d36SAndroid Build Coastguard Worker static FilterList *Filters;
131*48a54d36SAndroid Build Coastguard Worker #define ExactlyOneFilter (Filters && !Filters->next)
132*48a54d36SAndroid Build Coastguard Worker
133*48a54d36SAndroid Build Coastguard Worker static int NumPktQ, NumPktL, NumPktR, NumPktB; // Query/Legacy/Response/Bad
134*48a54d36SAndroid Build Coastguard Worker static int NumProbes, NumGoodbyes, NumQuestions, NumLegacy, NumAnswers, NumAdditionals;
135*48a54d36SAndroid Build Coastguard Worker
136*48a54d36SAndroid Build Coastguard Worker static ActivityStat *stats;
137*48a54d36SAndroid Build Coastguard Worker
138*48a54d36SAndroid Build Coastguard Worker #define OPBanner "Total Ops Probe Goodbye BrowseQ BrowseA ResolveQ ResolveA"
139*48a54d36SAndroid Build Coastguard Worker
140*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
141*48a54d36SAndroid Build Coastguard Worker // Utilities
142*48a54d36SAndroid Build Coastguard Worker
143*48a54d36SAndroid Build Coastguard Worker // Special version of printf that knows how to print IP addresses, DNS-format name strings, etc.
144*48a54d36SAndroid Build Coastguard Worker mDNSlocal mDNSu32 mprintf(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
mprintf(const char * format,...)145*48a54d36SAndroid Build Coastguard Worker mDNSlocal mDNSu32 mprintf(const char *format, ...)
146*48a54d36SAndroid Build Coastguard Worker {
147*48a54d36SAndroid Build Coastguard Worker mDNSu32 length;
148*48a54d36SAndroid Build Coastguard Worker unsigned char buffer[512];
149*48a54d36SAndroid Build Coastguard Worker va_list ptr;
150*48a54d36SAndroid Build Coastguard Worker va_start(ptr,format);
151*48a54d36SAndroid Build Coastguard Worker length = mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr);
152*48a54d36SAndroid Build Coastguard Worker va_end(ptr);
153*48a54d36SAndroid Build Coastguard Worker printf("%s", buffer);
154*48a54d36SAndroid Build Coastguard Worker return(length);
155*48a54d36SAndroid Build Coastguard Worker }
156*48a54d36SAndroid Build Coastguard Worker
157*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
158*48a54d36SAndroid Build Coastguard Worker // Host Address List
159*48a54d36SAndroid Build Coastguard Worker //
160*48a54d36SAndroid Build Coastguard Worker // Would benefit from a hash
161*48a54d36SAndroid Build Coastguard Worker
162*48a54d36SAndroid Build Coastguard Worker typedef enum
163*48a54d36SAndroid Build Coastguard Worker {
164*48a54d36SAndroid Build Coastguard Worker HostPkt_Q = 0, // Query
165*48a54d36SAndroid Build Coastguard Worker HostPkt_L = 1, // Legacy Query
166*48a54d36SAndroid Build Coastguard Worker HostPkt_R = 2, // Response
167*48a54d36SAndroid Build Coastguard Worker HostPkt_B = 3, // Bad
168*48a54d36SAndroid Build Coastguard Worker HostPkt_NumTypes = 4
169*48a54d36SAndroid Build Coastguard Worker } HostPkt_Type;
170*48a54d36SAndroid Build Coastguard Worker
171*48a54d36SAndroid Build Coastguard Worker typedef struct
172*48a54d36SAndroid Build Coastguard Worker {
173*48a54d36SAndroid Build Coastguard Worker mDNSAddr addr;
174*48a54d36SAndroid Build Coastguard Worker unsigned long pkts[HostPkt_NumTypes];
175*48a54d36SAndroid Build Coastguard Worker unsigned long totalops;
176*48a54d36SAndroid Build Coastguard Worker unsigned long stat[OP_NumTypes];
177*48a54d36SAndroid Build Coastguard Worker domainname hostname;
178*48a54d36SAndroid Build Coastguard Worker domainname revname;
179*48a54d36SAndroid Build Coastguard Worker UTF8str255 HIHardware;
180*48a54d36SAndroid Build Coastguard Worker UTF8str255 HISoftware;
181*48a54d36SAndroid Build Coastguard Worker mDNSu32 NumQueries;
182*48a54d36SAndroid Build Coastguard Worker mDNSs32 LastQuery;
183*48a54d36SAndroid Build Coastguard Worker } HostEntry;
184*48a54d36SAndroid Build Coastguard Worker
185*48a54d36SAndroid Build Coastguard Worker #define HostEntryTotalPackets(H) ((H)->pkts[HostPkt_Q] + (H)->pkts[HostPkt_L] + (H)->pkts[HostPkt_R] + (H)->pkts[HostPkt_B])
186*48a54d36SAndroid Build Coastguard Worker
187*48a54d36SAndroid Build Coastguard Worker typedef struct
188*48a54d36SAndroid Build Coastguard Worker {
189*48a54d36SAndroid Build Coastguard Worker long num;
190*48a54d36SAndroid Build Coastguard Worker long max;
191*48a54d36SAndroid Build Coastguard Worker HostEntry *hosts;
192*48a54d36SAndroid Build Coastguard Worker } HostList;
193*48a54d36SAndroid Build Coastguard Worker
194*48a54d36SAndroid Build Coastguard Worker static HostList IPv4HostList = { 0, 0, 0 };
195*48a54d36SAndroid Build Coastguard Worker static HostList IPv6HostList = { 0, 0, 0 };
196*48a54d36SAndroid Build Coastguard Worker
FindHost(const mDNSAddr * addr,HostList * list)197*48a54d36SAndroid Build Coastguard Worker mDNSlocal HostEntry *FindHost(const mDNSAddr *addr, HostList *list)
198*48a54d36SAndroid Build Coastguard Worker {
199*48a54d36SAndroid Build Coastguard Worker long i;
200*48a54d36SAndroid Build Coastguard Worker
201*48a54d36SAndroid Build Coastguard Worker for (i = 0; i < list->num; i++)
202*48a54d36SAndroid Build Coastguard Worker {
203*48a54d36SAndroid Build Coastguard Worker HostEntry *entry = list->hosts + i;
204*48a54d36SAndroid Build Coastguard Worker if (mDNSSameAddress(addr, &entry->addr))
205*48a54d36SAndroid Build Coastguard Worker return entry;
206*48a54d36SAndroid Build Coastguard Worker }
207*48a54d36SAndroid Build Coastguard Worker
208*48a54d36SAndroid Build Coastguard Worker return NULL;
209*48a54d36SAndroid Build Coastguard Worker }
210*48a54d36SAndroid Build Coastguard Worker
AddHost(const mDNSAddr * addr,HostList * list)211*48a54d36SAndroid Build Coastguard Worker mDNSlocal HostEntry *AddHost(const mDNSAddr *addr, HostList *list)
212*48a54d36SAndroid Build Coastguard Worker {
213*48a54d36SAndroid Build Coastguard Worker int i;
214*48a54d36SAndroid Build Coastguard Worker HostEntry *entry;
215*48a54d36SAndroid Build Coastguard Worker if (list->num >= list->max)
216*48a54d36SAndroid Build Coastguard Worker {
217*48a54d36SAndroid Build Coastguard Worker long newMax = list->max + 64;
218*48a54d36SAndroid Build Coastguard Worker HostEntry *newHosts = realloc(list->hosts, newMax * sizeof(HostEntry));
219*48a54d36SAndroid Build Coastguard Worker if (newHosts == NULL)
220*48a54d36SAndroid Build Coastguard Worker return NULL;
221*48a54d36SAndroid Build Coastguard Worker list->max = newMax;
222*48a54d36SAndroid Build Coastguard Worker list->hosts = newHosts;
223*48a54d36SAndroid Build Coastguard Worker }
224*48a54d36SAndroid Build Coastguard Worker
225*48a54d36SAndroid Build Coastguard Worker entry = list->hosts + list->num++;
226*48a54d36SAndroid Build Coastguard Worker
227*48a54d36SAndroid Build Coastguard Worker entry->addr = *addr;
228*48a54d36SAndroid Build Coastguard Worker for (i=0; i<HostPkt_NumTypes; i++) entry->pkts[i] = 0;
229*48a54d36SAndroid Build Coastguard Worker entry->totalops = 0;
230*48a54d36SAndroid Build Coastguard Worker for (i=0; i<OP_NumTypes; i++) entry->stat[i] = 0;
231*48a54d36SAndroid Build Coastguard Worker entry->hostname.c[0] = 0;
232*48a54d36SAndroid Build Coastguard Worker entry->revname.c[0] = 0;
233*48a54d36SAndroid Build Coastguard Worker entry->HIHardware.c[0] = 0;
234*48a54d36SAndroid Build Coastguard Worker entry->HISoftware.c[0] = 0;
235*48a54d36SAndroid Build Coastguard Worker entry->NumQueries = 0;
236*48a54d36SAndroid Build Coastguard Worker
237*48a54d36SAndroid Build Coastguard Worker if (entry->addr.type == mDNSAddrType_IPv4)
238*48a54d36SAndroid Build Coastguard Worker {
239*48a54d36SAndroid Build Coastguard Worker mDNSv4Addr ip = entry->addr.ip.v4;
240*48a54d36SAndroid Build Coastguard Worker char buffer[32];
241*48a54d36SAndroid Build Coastguard Worker // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
242*48a54d36SAndroid Build Coastguard Worker mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", ip.b[3], ip.b[2], ip.b[1], ip.b[0]);
243*48a54d36SAndroid Build Coastguard Worker MakeDomainNameFromDNSNameString(&entry->revname, buffer);
244*48a54d36SAndroid Build Coastguard Worker }
245*48a54d36SAndroid Build Coastguard Worker
246*48a54d36SAndroid Build Coastguard Worker return(entry);
247*48a54d36SAndroid Build Coastguard Worker }
248*48a54d36SAndroid Build Coastguard Worker
GotPacketFromHost(const mDNSAddr * addr,HostPkt_Type t,mDNSOpaque16 id)249*48a54d36SAndroid Build Coastguard Worker mDNSlocal HostEntry *GotPacketFromHost(const mDNSAddr *addr, HostPkt_Type t, mDNSOpaque16 id)
250*48a54d36SAndroid Build Coastguard Worker {
251*48a54d36SAndroid Build Coastguard Worker if (ExactlyOneFilter) return(NULL);
252*48a54d36SAndroid Build Coastguard Worker else
253*48a54d36SAndroid Build Coastguard Worker {
254*48a54d36SAndroid Build Coastguard Worker HostList *list = (addr->type == mDNSAddrType_IPv4) ? &IPv4HostList : &IPv6HostList;
255*48a54d36SAndroid Build Coastguard Worker HostEntry *entry = FindHost(addr, list);
256*48a54d36SAndroid Build Coastguard Worker if (!entry) entry = AddHost(addr, list);
257*48a54d36SAndroid Build Coastguard Worker if (!entry) return(NULL);
258*48a54d36SAndroid Build Coastguard Worker // Don't count our own interrogation packets
259*48a54d36SAndroid Build Coastguard Worker if (id.NotAnInteger != 0xFFFF) entry->pkts[t]++;
260*48a54d36SAndroid Build Coastguard Worker return(entry);
261*48a54d36SAndroid Build Coastguard Worker }
262*48a54d36SAndroid Build Coastguard Worker }
263*48a54d36SAndroid Build Coastguard Worker
RecordHostInfo(HostEntry * entry,const ResourceRecord * const pktrr)264*48a54d36SAndroid Build Coastguard Worker mDNSlocal void RecordHostInfo(HostEntry *entry, const ResourceRecord *const pktrr)
265*48a54d36SAndroid Build Coastguard Worker {
266*48a54d36SAndroid Build Coastguard Worker if (!entry->hostname.c[0])
267*48a54d36SAndroid Build Coastguard Worker {
268*48a54d36SAndroid Build Coastguard Worker if (pktrr->rrtype == kDNSType_A || pktrr->rrtype == kDNSType_AAAA)
269*48a54d36SAndroid Build Coastguard Worker {
270*48a54d36SAndroid Build Coastguard Worker // Should really check that the rdata in the address record matches the source address of this packet
271*48a54d36SAndroid Build Coastguard Worker entry->NumQueries = 0;
272*48a54d36SAndroid Build Coastguard Worker AssignDomainName(&entry->hostname, pktrr->name);
273*48a54d36SAndroid Build Coastguard Worker }
274*48a54d36SAndroid Build Coastguard Worker
275*48a54d36SAndroid Build Coastguard Worker if (pktrr->rrtype == kDNSType_PTR)
276*48a54d36SAndroid Build Coastguard Worker if (SameDomainName(&entry->revname, pktrr->name))
277*48a54d36SAndroid Build Coastguard Worker {
278*48a54d36SAndroid Build Coastguard Worker entry->NumQueries = 0;
279*48a54d36SAndroid Build Coastguard Worker AssignDomainName(&entry->hostname, &pktrr->rdata->u.name);
280*48a54d36SAndroid Build Coastguard Worker }
281*48a54d36SAndroid Build Coastguard Worker }
282*48a54d36SAndroid Build Coastguard Worker else if (pktrr->rrtype == kDNSType_HINFO)
283*48a54d36SAndroid Build Coastguard Worker {
284*48a54d36SAndroid Build Coastguard Worker RDataBody *rd = &pktrr->rdata->u;
285*48a54d36SAndroid Build Coastguard Worker mDNSu8 *rdend = (mDNSu8 *)rd + pktrr->rdlength;
286*48a54d36SAndroid Build Coastguard Worker mDNSu8 *hw = rd->txt.c;
287*48a54d36SAndroid Build Coastguard Worker mDNSu8 *sw = hw + 1 + (mDNSu32)hw[0];
288*48a54d36SAndroid Build Coastguard Worker if (sw + 1 + sw[0] <= rdend)
289*48a54d36SAndroid Build Coastguard Worker {
290*48a54d36SAndroid Build Coastguard Worker AssignDomainName(&entry->hostname, pktrr->name);
291*48a54d36SAndroid Build Coastguard Worker mDNSPlatformMemCopy(entry->HIHardware.c, hw, 1 + (mDNSu32)hw[0]);
292*48a54d36SAndroid Build Coastguard Worker mDNSPlatformMemCopy(entry->HISoftware.c, sw, 1 + (mDNSu32)sw[0]);
293*48a54d36SAndroid Build Coastguard Worker }
294*48a54d36SAndroid Build Coastguard Worker }
295*48a54d36SAndroid Build Coastguard Worker }
296*48a54d36SAndroid Build Coastguard Worker
SendUnicastQuery(mDNS * const m,HostEntry * entry,domainname * name,mDNSu16 rrtype,mDNSInterfaceID InterfaceID)297*48a54d36SAndroid Build Coastguard Worker mDNSlocal void SendUnicastQuery(mDNS *const m, HostEntry *entry, domainname *name, mDNSu16 rrtype, mDNSInterfaceID InterfaceID)
298*48a54d36SAndroid Build Coastguard Worker {
299*48a54d36SAndroid Build Coastguard Worker const mDNSOpaque16 id = { { 0xFF, 0xFF } };
300*48a54d36SAndroid Build Coastguard Worker DNSMessage query;
301*48a54d36SAndroid Build Coastguard Worker mDNSu8 *qptr = query.data;
302*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *const limit = query.data + sizeof(query.data);
303*48a54d36SAndroid Build Coastguard Worker const mDNSAddr *target = &entry->addr;
304*48a54d36SAndroid Build Coastguard Worker InitializeDNSMessage(&query.h, id, QueryFlags);
305*48a54d36SAndroid Build Coastguard Worker qptr = putQuestion(&query, qptr, limit, name, rrtype, kDNSClass_IN);
306*48a54d36SAndroid Build Coastguard Worker entry->LastQuery = m->timenow;
307*48a54d36SAndroid Build Coastguard Worker entry->NumQueries++;
308*48a54d36SAndroid Build Coastguard Worker
309*48a54d36SAndroid Build Coastguard Worker // Note: When there are multiple mDNSResponder agents running on a single machine
310*48a54d36SAndroid Build Coastguard Worker // (e.g. Apple mDNSResponder plus a SliMP3 server with embedded mDNSResponder)
311*48a54d36SAndroid Build Coastguard Worker // it is possible that unicast queries may not go to the primary system responder.
312*48a54d36SAndroid Build Coastguard Worker // We try the first query using unicast, but if that doesn't work we try again via multicast.
313*48a54d36SAndroid Build Coastguard Worker if (entry->NumQueries > 2)
314*48a54d36SAndroid Build Coastguard Worker {
315*48a54d36SAndroid Build Coastguard Worker target = &AllDNSLinkGroup_v4;
316*48a54d36SAndroid Build Coastguard Worker }
317*48a54d36SAndroid Build Coastguard Worker else
318*48a54d36SAndroid Build Coastguard Worker {
319*48a54d36SAndroid Build Coastguard Worker //mprintf("%#a Q\n", target);
320*48a54d36SAndroid Build Coastguard Worker InterfaceID = mDNSInterface_Any; // Send query from our unicast reply socket
321*48a54d36SAndroid Build Coastguard Worker }
322*48a54d36SAndroid Build Coastguard Worker
323*48a54d36SAndroid Build Coastguard Worker mDNSSendDNSMessage(&mDNSStorage, &query, qptr, InterfaceID, mDNSNULL, target, MulticastDNSPort, mDNSNULL, mDNSNULL);
324*48a54d36SAndroid Build Coastguard Worker }
325*48a54d36SAndroid Build Coastguard Worker
AnalyseHost(mDNS * const m,HostEntry * entry,const mDNSInterfaceID InterfaceID)326*48a54d36SAndroid Build Coastguard Worker mDNSlocal void AnalyseHost(mDNS *const m, HostEntry *entry, const mDNSInterfaceID InterfaceID)
327*48a54d36SAndroid Build Coastguard Worker {
328*48a54d36SAndroid Build Coastguard Worker // If we've done four queries without answer, give up
329*48a54d36SAndroid Build Coastguard Worker if (entry->NumQueries >= 4) return;
330*48a54d36SAndroid Build Coastguard Worker
331*48a54d36SAndroid Build Coastguard Worker // If we've done a query in the last second, give the host a chance to reply before trying again
332*48a54d36SAndroid Build Coastguard Worker if (entry->NumQueries && m->timenow - entry->LastQuery < mDNSPlatformOneSecond) return;
333*48a54d36SAndroid Build Coastguard Worker
334*48a54d36SAndroid Build Coastguard Worker // If we don't know the host name, try to find that first
335*48a54d36SAndroid Build Coastguard Worker if (!entry->hostname.c[0])
336*48a54d36SAndroid Build Coastguard Worker {
337*48a54d36SAndroid Build Coastguard Worker if (entry->revname.c[0])
338*48a54d36SAndroid Build Coastguard Worker {
339*48a54d36SAndroid Build Coastguard Worker SendUnicastQuery(m, entry, &entry->revname, kDNSType_PTR, InterfaceID);
340*48a54d36SAndroid Build Coastguard Worker //mprintf("%##s PTR %d\n", entry->revname.c, entry->NumQueries);
341*48a54d36SAndroid Build Coastguard Worker }
342*48a54d36SAndroid Build Coastguard Worker }
343*48a54d36SAndroid Build Coastguard Worker // If we have the host name but no HINFO, now ask for that
344*48a54d36SAndroid Build Coastguard Worker else if (!entry->HIHardware.c[0])
345*48a54d36SAndroid Build Coastguard Worker {
346*48a54d36SAndroid Build Coastguard Worker SendUnicastQuery(m, entry, &entry->hostname, kDNSType_HINFO, InterfaceID);
347*48a54d36SAndroid Build Coastguard Worker //mprintf("%##s HINFO %d\n", entry->hostname.c, entry->NumQueries);
348*48a54d36SAndroid Build Coastguard Worker }
349*48a54d36SAndroid Build Coastguard Worker }
350*48a54d36SAndroid Build Coastguard Worker
CompareHosts(const void * p1,const void * p2)351*48a54d36SAndroid Build Coastguard Worker mDNSlocal int CompareHosts(const void *p1, const void *p2)
352*48a54d36SAndroid Build Coastguard Worker {
353*48a54d36SAndroid Build Coastguard Worker return (int)(HostEntryTotalPackets((HostEntry *)p2) - HostEntryTotalPackets((HostEntry *)p1));
354*48a54d36SAndroid Build Coastguard Worker }
355*48a54d36SAndroid Build Coastguard Worker
ShowSortedHostList(HostList * list,int max)356*48a54d36SAndroid Build Coastguard Worker mDNSlocal void ShowSortedHostList(HostList *list, int max)
357*48a54d36SAndroid Build Coastguard Worker {
358*48a54d36SAndroid Build Coastguard Worker HostEntry *e, *end = &list->hosts[(max < list->num) ? max : list->num];
359*48a54d36SAndroid Build Coastguard Worker qsort(list->hosts, list->num, sizeof(HostEntry), CompareHosts);
360*48a54d36SAndroid Build Coastguard Worker if (list->num) mprintf("\n%-25s%s%s\n", "Source Address", OPBanner, " Pkts Query LegacyQ Response");
361*48a54d36SAndroid Build Coastguard Worker for (e = &list->hosts[0]; e < end; e++)
362*48a54d36SAndroid Build Coastguard Worker {
363*48a54d36SAndroid Build Coastguard Worker int len = mprintf("%#-25a", &e->addr);
364*48a54d36SAndroid Build Coastguard Worker if (len > 25) mprintf("\n%25s", "");
365*48a54d36SAndroid Build Coastguard Worker mprintf("%8lu %8lu %8lu %8lu %8lu %8lu %8lu", e->totalops,
366*48a54d36SAndroid Build Coastguard Worker e->stat[OP_probe], e->stat[OP_goodbye],
367*48a54d36SAndroid Build Coastguard Worker e->stat[OP_browseq], e->stat[OP_browsea],
368*48a54d36SAndroid Build Coastguard Worker e->stat[OP_resolveq], e->stat[OP_resolvea]);
369*48a54d36SAndroid Build Coastguard Worker mprintf(" %8lu %8lu %8lu %8lu",
370*48a54d36SAndroid Build Coastguard Worker HostEntryTotalPackets(e), e->pkts[HostPkt_Q], e->pkts[HostPkt_L], e->pkts[HostPkt_R]);
371*48a54d36SAndroid Build Coastguard Worker if (e->pkts[HostPkt_B]) mprintf("Bad: %8lu", e->pkts[HostPkt_B]);
372*48a54d36SAndroid Build Coastguard Worker mprintf("\n");
373*48a54d36SAndroid Build Coastguard Worker if (!e->HISoftware.c[0] && e->NumQueries > 2)
374*48a54d36SAndroid Build Coastguard Worker mDNSPlatformMemCopy(&e->HISoftware, "\x27*** Unknown (Jaguar, Windows, etc.) ***", 0x28);
375*48a54d36SAndroid Build Coastguard Worker if (e->hostname.c[0] || e->HIHardware.c[0] || e->HISoftware.c[0])
376*48a54d36SAndroid Build Coastguard Worker mprintf("%##-45s %#-14s %#s\n", e->hostname.c, e->HIHardware.c, e->HISoftware.c);
377*48a54d36SAndroid Build Coastguard Worker }
378*48a54d36SAndroid Build Coastguard Worker }
379*48a54d36SAndroid Build Coastguard Worker
380*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
381*48a54d36SAndroid Build Coastguard Worker // Receive and process packets
382*48a54d36SAndroid Build Coastguard Worker
ExtractServiceType(const domainname * const fqdn,domainname * const srvtype)383*48a54d36SAndroid Build Coastguard Worker mDNSexport mDNSBool ExtractServiceType(const domainname *const fqdn, domainname *const srvtype)
384*48a54d36SAndroid Build Coastguard Worker {
385*48a54d36SAndroid Build Coastguard Worker int i, len;
386*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *src = fqdn->c;
387*48a54d36SAndroid Build Coastguard Worker mDNSu8 *dst = srvtype->c;
388*48a54d36SAndroid Build Coastguard Worker
389*48a54d36SAndroid Build Coastguard Worker len = *src;
390*48a54d36SAndroid Build Coastguard Worker if (len == 0 || len >= 0x40) return(mDNSfalse);
391*48a54d36SAndroid Build Coastguard Worker if (src[1] != '_') src += 1 + len;
392*48a54d36SAndroid Build Coastguard Worker
393*48a54d36SAndroid Build Coastguard Worker len = *src;
394*48a54d36SAndroid Build Coastguard Worker if (len == 0 || len >= 0x40 || src[1] != '_') return(mDNSfalse);
395*48a54d36SAndroid Build Coastguard Worker for (i=0; i<=len; i++) *dst++ = *src++;
396*48a54d36SAndroid Build Coastguard Worker
397*48a54d36SAndroid Build Coastguard Worker len = *src;
398*48a54d36SAndroid Build Coastguard Worker if (len == 0 || len >= 0x40 || src[1] != '_') return(mDNSfalse);
399*48a54d36SAndroid Build Coastguard Worker for (i=0; i<=len; i++) *dst++ = *src++;
400*48a54d36SAndroid Build Coastguard Worker
401*48a54d36SAndroid Build Coastguard Worker *dst++ = 0; // Put the null root label on the end of the service type
402*48a54d36SAndroid Build Coastguard Worker
403*48a54d36SAndroid Build Coastguard Worker return(mDNStrue);
404*48a54d36SAndroid Build Coastguard Worker }
405*48a54d36SAndroid Build Coastguard Worker
recordstat(HostEntry * entry,const domainname * fqdn,int op,mDNSu16 rrtype)406*48a54d36SAndroid Build Coastguard Worker mDNSlocal void recordstat(HostEntry *entry, const domainname *fqdn, int op, mDNSu16 rrtype)
407*48a54d36SAndroid Build Coastguard Worker {
408*48a54d36SAndroid Build Coastguard Worker ActivityStat **s = &stats;
409*48a54d36SAndroid Build Coastguard Worker domainname srvtype;
410*48a54d36SAndroid Build Coastguard Worker
411*48a54d36SAndroid Build Coastguard Worker if (op != OP_probe)
412*48a54d36SAndroid Build Coastguard Worker {
413*48a54d36SAndroid Build Coastguard Worker if (rrtype == kDNSType_SRV || rrtype == kDNSType_TXT) op = op - OP_browsegroup + OP_resolvegroup;
414*48a54d36SAndroid Build Coastguard Worker else if (rrtype != kDNSType_PTR) return;
415*48a54d36SAndroid Build Coastguard Worker }
416*48a54d36SAndroid Build Coastguard Worker
417*48a54d36SAndroid Build Coastguard Worker if (!ExtractServiceType(fqdn, &srvtype)) return;
418*48a54d36SAndroid Build Coastguard Worker
419*48a54d36SAndroid Build Coastguard Worker while (*s && !SameDomainName(&(*s)->srvtype, &srvtype)) s = &(*s)->next;
420*48a54d36SAndroid Build Coastguard Worker if (!*s)
421*48a54d36SAndroid Build Coastguard Worker {
422*48a54d36SAndroid Build Coastguard Worker int i;
423*48a54d36SAndroid Build Coastguard Worker *s = malloc(sizeof(ActivityStat));
424*48a54d36SAndroid Build Coastguard Worker if (!*s) exit(-1);
425*48a54d36SAndroid Build Coastguard Worker (*s)->next = NULL;
426*48a54d36SAndroid Build Coastguard Worker (*s)->srvtype = srvtype;
427*48a54d36SAndroid Build Coastguard Worker (*s)->printed = 0;
428*48a54d36SAndroid Build Coastguard Worker (*s)->totalops = 0;
429*48a54d36SAndroid Build Coastguard Worker for (i=0; i<OP_NumTypes; i++) (*s)->stat[i] = 0;
430*48a54d36SAndroid Build Coastguard Worker }
431*48a54d36SAndroid Build Coastguard Worker
432*48a54d36SAndroid Build Coastguard Worker (*s)->totalops++;
433*48a54d36SAndroid Build Coastguard Worker (*s)->stat[op]++;
434*48a54d36SAndroid Build Coastguard Worker if (entry)
435*48a54d36SAndroid Build Coastguard Worker {
436*48a54d36SAndroid Build Coastguard Worker entry->totalops++;
437*48a54d36SAndroid Build Coastguard Worker entry->stat[op]++;
438*48a54d36SAndroid Build Coastguard Worker }
439*48a54d36SAndroid Build Coastguard Worker }
440*48a54d36SAndroid Build Coastguard Worker
printstats(int max)441*48a54d36SAndroid Build Coastguard Worker mDNSlocal void printstats(int max)
442*48a54d36SAndroid Build Coastguard Worker {
443*48a54d36SAndroid Build Coastguard Worker int i;
444*48a54d36SAndroid Build Coastguard Worker if (!stats) return;
445*48a54d36SAndroid Build Coastguard Worker for (i=0; i<max; i++)
446*48a54d36SAndroid Build Coastguard Worker {
447*48a54d36SAndroid Build Coastguard Worker int max = 0;
448*48a54d36SAndroid Build Coastguard Worker ActivityStat *s, *m = NULL;
449*48a54d36SAndroid Build Coastguard Worker for (s = stats; s; s=s->next)
450*48a54d36SAndroid Build Coastguard Worker if (!s->printed && max < s->totalops)
451*48a54d36SAndroid Build Coastguard Worker { m = s; max = s->totalops; }
452*48a54d36SAndroid Build Coastguard Worker if (!m) return;
453*48a54d36SAndroid Build Coastguard Worker m->printed = mDNStrue;
454*48a54d36SAndroid Build Coastguard Worker if (i==0) mprintf("%-25s%s\n", "Service Type", OPBanner);
455*48a54d36SAndroid Build Coastguard Worker mprintf("%##-25s%8d %8d %8d %8d %8d %8d %8d\n", m->srvtype.c, m->totalops, m->stat[OP_probe],
456*48a54d36SAndroid Build Coastguard Worker m->stat[OP_goodbye], m->stat[OP_browseq], m->stat[OP_browsea], m->stat[OP_resolveq], m->stat[OP_resolvea]);
457*48a54d36SAndroid Build Coastguard Worker }
458*48a54d36SAndroid Build Coastguard Worker }
459*48a54d36SAndroid Build Coastguard Worker
FindUpdate(mDNS * const m,const DNSMessage * const query,const mDNSu8 * ptr,const mDNSu8 * const end,DNSQuestion * q,LargeCacheRecord * pkt)460*48a54d36SAndroid Build Coastguard Worker mDNSlocal const mDNSu8 *FindUpdate(mDNS *const m, const DNSMessage *const query, const mDNSu8 *ptr, const mDNSu8 *const end,
461*48a54d36SAndroid Build Coastguard Worker DNSQuestion *q, LargeCacheRecord *pkt)
462*48a54d36SAndroid Build Coastguard Worker {
463*48a54d36SAndroid Build Coastguard Worker int i;
464*48a54d36SAndroid Build Coastguard Worker for (i = 0; i < query->h.numAuthorities; i++)
465*48a54d36SAndroid Build Coastguard Worker {
466*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *p2 = ptr;
467*48a54d36SAndroid Build Coastguard Worker ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, kDNSRecordTypePacketAuth, pkt);
468*48a54d36SAndroid Build Coastguard Worker if (!ptr) break;
469*48a54d36SAndroid Build Coastguard Worker if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && ResourceRecordAnswersQuestion(&pkt->r.resrec, q)) return(p2);
470*48a54d36SAndroid Build Coastguard Worker }
471*48a54d36SAndroid Build Coastguard Worker return(mDNSNULL);
472*48a54d36SAndroid Build Coastguard Worker }
473*48a54d36SAndroid Build Coastguard Worker
DisplayPacketHeader(mDNS * const m,const DNSMessage * const msg,const mDNSu8 * const end,const mDNSAddr * srcaddr,mDNSIPPort srcport,const mDNSAddr * dstaddr,const mDNSInterfaceID InterfaceID)474*48a54d36SAndroid Build Coastguard Worker mDNSlocal void DisplayPacketHeader(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSInterfaceID InterfaceID)
475*48a54d36SAndroid Build Coastguard Worker {
476*48a54d36SAndroid Build Coastguard Worker const char *const ptype = (msg->h.flags.b[0] & kDNSFlag0_QR_Response) ? "-R- " :
477*48a54d36SAndroid Build Coastguard Worker (srcport.NotAnInteger == MulticastDNSPort.NotAnInteger) ? "-Q- " : "-LQ-";
478*48a54d36SAndroid Build Coastguard Worker
479*48a54d36SAndroid Build Coastguard Worker struct timeval tv;
480*48a54d36SAndroid Build Coastguard Worker struct tm tm;
481*48a54d36SAndroid Build Coastguard Worker const mDNSu32 index = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNSfalse);
482*48a54d36SAndroid Build Coastguard Worker char if_name[IFNAMSIZ]; // Older Linux distributions don't define IF_NAMESIZE
483*48a54d36SAndroid Build Coastguard Worker if_indextoname(index, if_name);
484*48a54d36SAndroid Build Coastguard Worker gettimeofday(&tv, NULL);
485*48a54d36SAndroid Build Coastguard Worker localtime_r((time_t*)&tv.tv_sec, &tm);
486*48a54d36SAndroid Build Coastguard Worker mprintf("\n%d:%02d:%02d.%06d Interface %d/%s\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec, index, if_name);
487*48a54d36SAndroid Build Coastguard Worker
488*48a54d36SAndroid Build Coastguard Worker mprintf("%#-16a %s Q:%3d Ans:%3d Auth:%3d Add:%3d Size:%5d bytes",
489*48a54d36SAndroid Build Coastguard Worker srcaddr, ptype, msg->h.numQuestions, msg->h.numAnswers, msg->h.numAuthorities, msg->h.numAdditionals, end - (mDNSu8 *)msg);
490*48a54d36SAndroid Build Coastguard Worker
491*48a54d36SAndroid Build Coastguard Worker if (msg->h.id.NotAnInteger) mprintf(" ID:%u", mDNSVal16(msg->h.id));
492*48a54d36SAndroid Build Coastguard Worker
493*48a54d36SAndroid Build Coastguard Worker if (!mDNSAddrIsDNSMulticast(dstaddr)) mprintf(" To: %#a", dstaddr);
494*48a54d36SAndroid Build Coastguard Worker
495*48a54d36SAndroid Build Coastguard Worker if (msg->h.flags.b[0] & kDNSFlag0_TC)
496*48a54d36SAndroid Build Coastguard Worker {
497*48a54d36SAndroid Build Coastguard Worker if (msg->h.flags.b[0] & kDNSFlag0_QR_Response) mprintf(" Truncated");
498*48a54d36SAndroid Build Coastguard Worker else mprintf(" Truncated (KA list continues in next packet)");
499*48a54d36SAndroid Build Coastguard Worker }
500*48a54d36SAndroid Build Coastguard Worker mprintf("\n");
501*48a54d36SAndroid Build Coastguard Worker }
502*48a54d36SAndroid Build Coastguard Worker
DisplayResourceRecord(const mDNSAddr * const srcaddr,const char * const op,const ResourceRecord * const pktrr)503*48a54d36SAndroid Build Coastguard Worker mDNSlocal void DisplayResourceRecord(const mDNSAddr *const srcaddr, const char *const op, const ResourceRecord *const pktrr)
504*48a54d36SAndroid Build Coastguard Worker {
505*48a54d36SAndroid Build Coastguard Worker static const char hexchars[16] = "0123456789ABCDEF";
506*48a54d36SAndroid Build Coastguard Worker #define MaxWidth 132
507*48a54d36SAndroid Build Coastguard Worker char buffer[MaxWidth+8];
508*48a54d36SAndroid Build Coastguard Worker char *p = buffer;
509*48a54d36SAndroid Build Coastguard Worker
510*48a54d36SAndroid Build Coastguard Worker RDataBody *rd = &pktrr->rdata->u;
511*48a54d36SAndroid Build Coastguard Worker mDNSu8 *rdend = (mDNSu8 *)rd + pktrr->rdlength;
512*48a54d36SAndroid Build Coastguard Worker int n = mprintf("%#-16a %-5s %-5s%5lu %##s -> ", srcaddr, op, DNSTypeName(pktrr->rrtype), pktrr->rroriginalttl, pktrr->name->c);
513*48a54d36SAndroid Build Coastguard Worker
514*48a54d36SAndroid Build Coastguard Worker if (pktrr->RecordType == kDNSRecordTypePacketNegative) { mprintf("**** ERROR: FAILED TO READ RDATA ****\n"); return; }
515*48a54d36SAndroid Build Coastguard Worker
516*48a54d36SAndroid Build Coastguard Worker // The kDNSType_OPT case below just calls GetRRDisplayString_rdb
517*48a54d36SAndroid Build Coastguard Worker // Perhaps more (or all?) of the cases should do that?
518*48a54d36SAndroid Build Coastguard Worker switch(pktrr->rrtype)
519*48a54d36SAndroid Build Coastguard Worker {
520*48a54d36SAndroid Build Coastguard Worker case kDNSType_A: n += mprintf("%.4a", &rd->ipv4); break;
521*48a54d36SAndroid Build Coastguard Worker case kDNSType_PTR: n += mprintf("%##.*s", MaxWidth - n, rd->name.c); break;
522*48a54d36SAndroid Build Coastguard Worker case kDNSType_HINFO:// same as kDNSType_TXT below
523*48a54d36SAndroid Build Coastguard Worker case kDNSType_TXT: {
524*48a54d36SAndroid Build Coastguard Worker mDNSu8 *t = rd->txt.c;
525*48a54d36SAndroid Build Coastguard Worker while (t < rdend && t[0] && p < buffer+MaxWidth)
526*48a54d36SAndroid Build Coastguard Worker {
527*48a54d36SAndroid Build Coastguard Worker int i;
528*48a54d36SAndroid Build Coastguard Worker for (i=1; i<=t[0] && p < buffer+MaxWidth; i++)
529*48a54d36SAndroid Build Coastguard Worker {
530*48a54d36SAndroid Build Coastguard Worker if (t[i] == '\\') *p++ = '\\';
531*48a54d36SAndroid Build Coastguard Worker if (t[i] >= ' ') *p++ = t[i];
532*48a54d36SAndroid Build Coastguard Worker else
533*48a54d36SAndroid Build Coastguard Worker {
534*48a54d36SAndroid Build Coastguard Worker *p++ = '\\';
535*48a54d36SAndroid Build Coastguard Worker *p++ = '0';
536*48a54d36SAndroid Build Coastguard Worker *p++ = 'x';
537*48a54d36SAndroid Build Coastguard Worker *p++ = hexchars[t[i] >> 4];
538*48a54d36SAndroid Build Coastguard Worker *p++ = hexchars[t[i] & 0xF];
539*48a54d36SAndroid Build Coastguard Worker }
540*48a54d36SAndroid Build Coastguard Worker }
541*48a54d36SAndroid Build Coastguard Worker t += 1+t[0];
542*48a54d36SAndroid Build Coastguard Worker if (t < rdend && t[0]) { *p++ = '\\'; *p++ = ' '; }
543*48a54d36SAndroid Build Coastguard Worker }
544*48a54d36SAndroid Build Coastguard Worker *p++ = 0;
545*48a54d36SAndroid Build Coastguard Worker n += mprintf("%.*s", MaxWidth - n, buffer);
546*48a54d36SAndroid Build Coastguard Worker } break;
547*48a54d36SAndroid Build Coastguard Worker case kDNSType_AAAA: n += mprintf("%.16a", &rd->ipv6); break;
548*48a54d36SAndroid Build Coastguard Worker case kDNSType_SRV: n += mprintf("%##s:%d", rd->srv.target.c, mDNSVal16(rd->srv.port)); break;
549*48a54d36SAndroid Build Coastguard Worker case kDNSType_OPT: {
550*48a54d36SAndroid Build Coastguard Worker char b[MaxMsg];
551*48a54d36SAndroid Build Coastguard Worker // Quick hack: we don't want the prefix that GetRRDisplayString_rdb puts at the start of its
552*48a54d36SAndroid Build Coastguard Worker // string, because it duplicates the name and rrtype we already display, so we compute the
553*48a54d36SAndroid Build Coastguard Worker // length of that prefix and strip that many bytes off the beginning of the string we display.
554*48a54d36SAndroid Build Coastguard Worker mDNSu32 striplen = mDNS_snprintf(b, MaxMsg-1, "%4d %##s %s ", pktrr->rdlength, pktrr->name->c, DNSTypeName(pktrr->rrtype));
555*48a54d36SAndroid Build Coastguard Worker GetRRDisplayString_rdb(pktrr, &pktrr->rdata->u, b);
556*48a54d36SAndroid Build Coastguard Worker n += mprintf("%.*s", MaxWidth - n, b + striplen);
557*48a54d36SAndroid Build Coastguard Worker } break;
558*48a54d36SAndroid Build Coastguard Worker case kDNSType_NSEC: {
559*48a54d36SAndroid Build Coastguard Worker int i;
560*48a54d36SAndroid Build Coastguard Worker for (i=0; i<255; i++)
561*48a54d36SAndroid Build Coastguard Worker if (rd->nsec.bitmap[i>>3] & (128 >> (i&7)))
562*48a54d36SAndroid Build Coastguard Worker n += mprintf("%s ", DNSTypeName(i));
563*48a54d36SAndroid Build Coastguard Worker } break;
564*48a54d36SAndroid Build Coastguard Worker default: {
565*48a54d36SAndroid Build Coastguard Worker mDNSu8 *s = rd->data;
566*48a54d36SAndroid Build Coastguard Worker while (s < rdend && p < buffer+MaxWidth)
567*48a54d36SAndroid Build Coastguard Worker {
568*48a54d36SAndroid Build Coastguard Worker if (*s == '\\') *p++ = '\\';
569*48a54d36SAndroid Build Coastguard Worker if (*s >= ' ') *p++ = *s;
570*48a54d36SAndroid Build Coastguard Worker else
571*48a54d36SAndroid Build Coastguard Worker {
572*48a54d36SAndroid Build Coastguard Worker *p++ = '\\';
573*48a54d36SAndroid Build Coastguard Worker *p++ = '0';
574*48a54d36SAndroid Build Coastguard Worker *p++ = 'x';
575*48a54d36SAndroid Build Coastguard Worker *p++ = hexchars[*s >> 4];
576*48a54d36SAndroid Build Coastguard Worker *p++ = hexchars[*s & 0xF];
577*48a54d36SAndroid Build Coastguard Worker }
578*48a54d36SAndroid Build Coastguard Worker s++;
579*48a54d36SAndroid Build Coastguard Worker }
580*48a54d36SAndroid Build Coastguard Worker *p++ = 0;
581*48a54d36SAndroid Build Coastguard Worker n += mprintf("%.*s", MaxWidth - n, buffer);
582*48a54d36SAndroid Build Coastguard Worker } break;
583*48a54d36SAndroid Build Coastguard Worker }
584*48a54d36SAndroid Build Coastguard Worker
585*48a54d36SAndroid Build Coastguard Worker mprintf("\n");
586*48a54d36SAndroid Build Coastguard Worker }
587*48a54d36SAndroid Build Coastguard Worker
HexDump(const mDNSu8 * ptr,const mDNSu8 * const end)588*48a54d36SAndroid Build Coastguard Worker mDNSlocal void HexDump(const mDNSu8 *ptr, const mDNSu8 *const end)
589*48a54d36SAndroid Build Coastguard Worker {
590*48a54d36SAndroid Build Coastguard Worker while (ptr < end)
591*48a54d36SAndroid Build Coastguard Worker {
592*48a54d36SAndroid Build Coastguard Worker int i;
593*48a54d36SAndroid Build Coastguard Worker for (i=0; i<16; i++)
594*48a54d36SAndroid Build Coastguard Worker if (&ptr[i] < end) mprintf("%02X ", ptr[i]);
595*48a54d36SAndroid Build Coastguard Worker else mprintf(" ");
596*48a54d36SAndroid Build Coastguard Worker for (i=0; i<16; i++)
597*48a54d36SAndroid Build Coastguard Worker if (&ptr[i] < end) mprintf("%c", ptr[i] <= ' ' || ptr[i] >= 126 ? '.' : ptr[i]);
598*48a54d36SAndroid Build Coastguard Worker ptr += 16;
599*48a54d36SAndroid Build Coastguard Worker mprintf("\n");
600*48a54d36SAndroid Build Coastguard Worker }
601*48a54d36SAndroid Build Coastguard Worker }
602*48a54d36SAndroid Build Coastguard Worker
DisplayError(const mDNSAddr * srcaddr,const mDNSu8 * ptr,const mDNSu8 * const end,char * msg)603*48a54d36SAndroid Build Coastguard Worker mDNSlocal void DisplayError(const mDNSAddr *srcaddr, const mDNSu8 *ptr, const mDNSu8 *const end, char *msg)
604*48a54d36SAndroid Build Coastguard Worker {
605*48a54d36SAndroid Build Coastguard Worker mprintf("%#-16a **** ERROR: FAILED TO READ %s **** \n", srcaddr, msg);
606*48a54d36SAndroid Build Coastguard Worker HexDump(ptr, end);
607*48a54d36SAndroid Build Coastguard Worker }
608*48a54d36SAndroid Build Coastguard Worker
DisplayQuery(mDNS * const m,const DNSMessage * const msg,const mDNSu8 * const end,const mDNSAddr * srcaddr,mDNSIPPort srcport,const mDNSAddr * dstaddr,const mDNSInterfaceID InterfaceID)609*48a54d36SAndroid Build Coastguard Worker mDNSlocal void DisplayQuery(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
610*48a54d36SAndroid Build Coastguard Worker const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSInterfaceID InterfaceID)
611*48a54d36SAndroid Build Coastguard Worker {
612*48a54d36SAndroid Build Coastguard Worker int i;
613*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *ptr = msg->data;
614*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *auth = LocateAuthorities(msg, end);
615*48a54d36SAndroid Build Coastguard Worker mDNSBool MQ = (srcport.NotAnInteger == MulticastDNSPort.NotAnInteger);
616*48a54d36SAndroid Build Coastguard Worker HostEntry *entry = GotPacketFromHost(srcaddr, MQ ? HostPkt_Q : HostPkt_L, msg->h.id);
617*48a54d36SAndroid Build Coastguard Worker LargeCacheRecord pkt;
618*48a54d36SAndroid Build Coastguard Worker
619*48a54d36SAndroid Build Coastguard Worker DisplayPacketHeader(m, msg, end, srcaddr, srcport, dstaddr, InterfaceID);
620*48a54d36SAndroid Build Coastguard Worker if (msg->h.id.NotAnInteger != 0xFFFF)
621*48a54d36SAndroid Build Coastguard Worker {
622*48a54d36SAndroid Build Coastguard Worker if (MQ) NumPktQ++; else NumPktL++;
623*48a54d36SAndroid Build Coastguard Worker }
624*48a54d36SAndroid Build Coastguard Worker
625*48a54d36SAndroid Build Coastguard Worker for (i=0; i<msg->h.numQuestions; i++)
626*48a54d36SAndroid Build Coastguard Worker {
627*48a54d36SAndroid Build Coastguard Worker DNSQuestion q;
628*48a54d36SAndroid Build Coastguard Worker mDNSu8 *p2 = (mDNSu8 *)getQuestion(msg, ptr, end, InterfaceID, &q);
629*48a54d36SAndroid Build Coastguard Worker mDNSu16 ucbit = q.qclass & kDNSQClass_UnicastResponse;
630*48a54d36SAndroid Build Coastguard Worker q.qclass &= ~kDNSQClass_UnicastResponse;
631*48a54d36SAndroid Build Coastguard Worker if (!p2) { DisplayError(srcaddr, ptr, end, "QUESTION"); return; }
632*48a54d36SAndroid Build Coastguard Worker ptr = p2;
633*48a54d36SAndroid Build Coastguard Worker p2 = (mDNSu8 *)FindUpdate(m, msg, auth, end, &q, &pkt);
634*48a54d36SAndroid Build Coastguard Worker if (p2)
635*48a54d36SAndroid Build Coastguard Worker {
636*48a54d36SAndroid Build Coastguard Worker NumProbes++;
637*48a54d36SAndroid Build Coastguard Worker DisplayResourceRecord(srcaddr, ucbit ? "(PU)" : "(PM)", &pkt.r.resrec);
638*48a54d36SAndroid Build Coastguard Worker recordstat(entry, &q.qname, OP_probe, q.qtype);
639*48a54d36SAndroid Build Coastguard Worker p2 = (mDNSu8 *)skipDomainName(msg, p2, end);
640*48a54d36SAndroid Build Coastguard Worker // Having displayed this update record, clear type and class so we don't display the same one again.
641*48a54d36SAndroid Build Coastguard Worker p2[0] = p2[1] = p2[2] = p2[3] = 0;
642*48a54d36SAndroid Build Coastguard Worker }
643*48a54d36SAndroid Build Coastguard Worker else
644*48a54d36SAndroid Build Coastguard Worker {
645*48a54d36SAndroid Build Coastguard Worker const char *ptype = ucbit ? "(QU)" : "(QM)";
646*48a54d36SAndroid Build Coastguard Worker if (srcport.NotAnInteger == MulticastDNSPort.NotAnInteger) NumQuestions++;
647*48a54d36SAndroid Build Coastguard Worker else { NumLegacy++; ptype = "(LQ)"; }
648*48a54d36SAndroid Build Coastguard Worker mprintf("%#-16a %-5s %-5s %##s\n", srcaddr, ptype, DNSTypeName(q.qtype), q.qname.c);
649*48a54d36SAndroid Build Coastguard Worker if (msg->h.id.NotAnInteger != 0xFFFF) recordstat(entry, &q.qname, OP_query, q.qtype);
650*48a54d36SAndroid Build Coastguard Worker }
651*48a54d36SAndroid Build Coastguard Worker }
652*48a54d36SAndroid Build Coastguard Worker
653*48a54d36SAndroid Build Coastguard Worker for (i=0; i<msg->h.numAnswers; i++)
654*48a54d36SAndroid Build Coastguard Worker {
655*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *ep = ptr;
656*48a54d36SAndroid Build Coastguard Worker ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &pkt);
657*48a54d36SAndroid Build Coastguard Worker if (!ptr) { DisplayError(srcaddr, ep, end, "KNOWN ANSWER"); return; }
658*48a54d36SAndroid Build Coastguard Worker DisplayResourceRecord(srcaddr, "(KA)", &pkt.r.resrec);
659*48a54d36SAndroid Build Coastguard Worker
660*48a54d36SAndroid Build Coastguard Worker // In the case of queries with long multi-packet KA lists, we count each subsequent KA packet
661*48a54d36SAndroid Build Coastguard Worker // the same as a single query, to more accurately reflect the burden on the network
662*48a54d36SAndroid Build Coastguard Worker // (A query with a six-packet KA list is *at least* six times the burden on the network as a single-packet query.)
663*48a54d36SAndroid Build Coastguard Worker if (msg->h.numQuestions == 0 && i == 0)
664*48a54d36SAndroid Build Coastguard Worker recordstat(entry, pkt.r.resrec.name, OP_query, pkt.r.resrec.rrtype);
665*48a54d36SAndroid Build Coastguard Worker }
666*48a54d36SAndroid Build Coastguard Worker
667*48a54d36SAndroid Build Coastguard Worker for (i=0; i<msg->h.numAuthorities; i++)
668*48a54d36SAndroid Build Coastguard Worker {
669*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *ep = ptr;
670*48a54d36SAndroid Build Coastguard Worker ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &pkt);
671*48a54d36SAndroid Build Coastguard Worker if (!ptr) { DisplayError(srcaddr, ep, end, "AUTHORITY"); return; }
672*48a54d36SAndroid Build Coastguard Worker // After we display an Update record with its matching question (above) we zero out its type and class
673*48a54d36SAndroid Build Coastguard Worker // If any remain that haven't been zero'd out, display them here
674*48a54d36SAndroid Build Coastguard Worker if (pkt.r.resrec.rrtype || pkt.r.resrec.rrclass) DisplayResourceRecord(srcaddr, "(AU)", &pkt.r.resrec);
675*48a54d36SAndroid Build Coastguard Worker }
676*48a54d36SAndroid Build Coastguard Worker
677*48a54d36SAndroid Build Coastguard Worker for (i=0; i<msg->h.numAdditionals; i++)
678*48a54d36SAndroid Build Coastguard Worker {
679*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *ep = ptr;
680*48a54d36SAndroid Build Coastguard Worker ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &pkt);
681*48a54d36SAndroid Build Coastguard Worker if (!ptr) { DisplayError(srcaddr, ep, end, "ADDITIONAL"); return; }
682*48a54d36SAndroid Build Coastguard Worker DisplayResourceRecord(srcaddr, pkt.r.resrec.rrtype == kDNSType_OPT ? "(OP)" : "(AD)", &pkt.r.resrec);
683*48a54d36SAndroid Build Coastguard Worker }
684*48a54d36SAndroid Build Coastguard Worker
685*48a54d36SAndroid Build Coastguard Worker if (entry) AnalyseHost(m, entry, InterfaceID);
686*48a54d36SAndroid Build Coastguard Worker }
687*48a54d36SAndroid Build Coastguard Worker
DisplayResponse(mDNS * const m,const DNSMessage * const msg,const mDNSu8 * end,const mDNSAddr * srcaddr,mDNSIPPort srcport,const mDNSAddr * dstaddr,const mDNSInterfaceID InterfaceID)688*48a54d36SAndroid Build Coastguard Worker mDNSlocal void DisplayResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end,
689*48a54d36SAndroid Build Coastguard Worker const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSInterfaceID InterfaceID)
690*48a54d36SAndroid Build Coastguard Worker {
691*48a54d36SAndroid Build Coastguard Worker int i;
692*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *ptr = msg->data;
693*48a54d36SAndroid Build Coastguard Worker HostEntry *entry = GotPacketFromHost(srcaddr, HostPkt_R, msg->h.id);
694*48a54d36SAndroid Build Coastguard Worker LargeCacheRecord pkt;
695*48a54d36SAndroid Build Coastguard Worker
696*48a54d36SAndroid Build Coastguard Worker DisplayPacketHeader(m, msg, end, srcaddr, srcport, dstaddr, InterfaceID);
697*48a54d36SAndroid Build Coastguard Worker if (msg->h.id.NotAnInteger != 0xFFFF) NumPktR++;
698*48a54d36SAndroid Build Coastguard Worker
699*48a54d36SAndroid Build Coastguard Worker for (i=0; i<msg->h.numQuestions; i++)
700*48a54d36SAndroid Build Coastguard Worker {
701*48a54d36SAndroid Build Coastguard Worker DNSQuestion q;
702*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *ep = ptr;
703*48a54d36SAndroid Build Coastguard Worker ptr = getQuestion(msg, ptr, end, InterfaceID, &q);
704*48a54d36SAndroid Build Coastguard Worker if (!ptr) { DisplayError(srcaddr, ep, end, "QUESTION"); return; }
705*48a54d36SAndroid Build Coastguard Worker if (mDNSAddrIsDNSMulticast(dstaddr))
706*48a54d36SAndroid Build Coastguard Worker mprintf("%#-16a (?) **** ERROR: SHOULD NOT HAVE Q IN mDNS RESPONSE **** %-5s %##s\n", srcaddr, DNSTypeName(q.qtype), q.qname.c);
707*48a54d36SAndroid Build Coastguard Worker else
708*48a54d36SAndroid Build Coastguard Worker mprintf("%#-16a (Q) %-5s %##s\n", srcaddr, DNSTypeName(q.qtype), q.qname.c);
709*48a54d36SAndroid Build Coastguard Worker }
710*48a54d36SAndroid Build Coastguard Worker
711*48a54d36SAndroid Build Coastguard Worker for (i=0; i<msg->h.numAnswers; i++)
712*48a54d36SAndroid Build Coastguard Worker {
713*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *ep = ptr;
714*48a54d36SAndroid Build Coastguard Worker ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &pkt);
715*48a54d36SAndroid Build Coastguard Worker if (!ptr) { DisplayError(srcaddr, ep, end, "ANSWER"); return; }
716*48a54d36SAndroid Build Coastguard Worker if (pkt.r.resrec.rroriginalttl)
717*48a54d36SAndroid Build Coastguard Worker {
718*48a54d36SAndroid Build Coastguard Worker NumAnswers++;
719*48a54d36SAndroid Build Coastguard Worker DisplayResourceRecord(srcaddr, (pkt.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? "(AN)" : "(AN+)", &pkt.r.resrec);
720*48a54d36SAndroid Build Coastguard Worker if (msg->h.id.NotAnInteger != 0xFFFF) recordstat(entry, pkt.r.resrec.name, OP_answer, pkt.r.resrec.rrtype);
721*48a54d36SAndroid Build Coastguard Worker if (entry) RecordHostInfo(entry, &pkt.r.resrec);
722*48a54d36SAndroid Build Coastguard Worker }
723*48a54d36SAndroid Build Coastguard Worker else
724*48a54d36SAndroid Build Coastguard Worker {
725*48a54d36SAndroid Build Coastguard Worker NumGoodbyes++;
726*48a54d36SAndroid Build Coastguard Worker DisplayResourceRecord(srcaddr, "(DE)", &pkt.r.resrec);
727*48a54d36SAndroid Build Coastguard Worker recordstat(entry, pkt.r.resrec.name, OP_goodbye, pkt.r.resrec.rrtype);
728*48a54d36SAndroid Build Coastguard Worker }
729*48a54d36SAndroid Build Coastguard Worker }
730*48a54d36SAndroid Build Coastguard Worker
731*48a54d36SAndroid Build Coastguard Worker for (i=0; i<msg->h.numAuthorities; i++)
732*48a54d36SAndroid Build Coastguard Worker {
733*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *ep = ptr;
734*48a54d36SAndroid Build Coastguard Worker ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &pkt);
735*48a54d36SAndroid Build Coastguard Worker if (!ptr) { DisplayError(srcaddr, ep, end, "AUTHORITY"); return; }
736*48a54d36SAndroid Build Coastguard Worker mprintf("%#-16a (?) **** ERROR: SHOULD NOT HAVE AUTHORITY IN mDNS RESPONSE **** %-5s %##s\n",
737*48a54d36SAndroid Build Coastguard Worker srcaddr, DNSTypeName(pkt.r.resrec.rrtype), pkt.r.resrec.name->c);
738*48a54d36SAndroid Build Coastguard Worker }
739*48a54d36SAndroid Build Coastguard Worker
740*48a54d36SAndroid Build Coastguard Worker for (i=0; i<msg->h.numAdditionals; i++)
741*48a54d36SAndroid Build Coastguard Worker {
742*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *ep = ptr;
743*48a54d36SAndroid Build Coastguard Worker ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &pkt);
744*48a54d36SAndroid Build Coastguard Worker if (!ptr) { DisplayError(srcaddr, ep, end, "ADDITIONAL"); return; }
745*48a54d36SAndroid Build Coastguard Worker NumAdditionals++;
746*48a54d36SAndroid Build Coastguard Worker DisplayResourceRecord(srcaddr,
747*48a54d36SAndroid Build Coastguard Worker pkt.r.resrec.rrtype == kDNSType_OPT ? "(OP)" : (pkt.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? "(AD)" : "(AD+)",
748*48a54d36SAndroid Build Coastguard Worker &pkt.r.resrec);
749*48a54d36SAndroid Build Coastguard Worker if (entry) RecordHostInfo(entry, &pkt.r.resrec);
750*48a54d36SAndroid Build Coastguard Worker }
751*48a54d36SAndroid Build Coastguard Worker
752*48a54d36SAndroid Build Coastguard Worker if (entry) AnalyseHost(m, entry, InterfaceID);
753*48a54d36SAndroid Build Coastguard Worker }
754*48a54d36SAndroid Build Coastguard Worker
ProcessUnicastResponse(mDNS * const m,const DNSMessage * const msg,const mDNSu8 * end,const mDNSAddr * srcaddr,const mDNSInterfaceID InterfaceID)755*48a54d36SAndroid Build Coastguard Worker mDNSlocal void ProcessUnicastResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end, const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID)
756*48a54d36SAndroid Build Coastguard Worker {
757*48a54d36SAndroid Build Coastguard Worker int i;
758*48a54d36SAndroid Build Coastguard Worker const mDNSu8 *ptr = LocateAnswers(msg, end);
759*48a54d36SAndroid Build Coastguard Worker HostEntry *entry = GotPacketFromHost(srcaddr, HostPkt_R, msg->h.id);
760*48a54d36SAndroid Build Coastguard Worker //mprintf("%#a R\n", srcaddr);
761*48a54d36SAndroid Build Coastguard Worker
762*48a54d36SAndroid Build Coastguard Worker for (i=0; i<msg->h.numAnswers + msg->h.numAuthorities + msg->h.numAdditionals; i++)
763*48a54d36SAndroid Build Coastguard Worker {
764*48a54d36SAndroid Build Coastguard Worker LargeCacheRecord pkt;
765*48a54d36SAndroid Build Coastguard Worker ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &pkt);
766*48a54d36SAndroid Build Coastguard Worker if (ptr && pkt.r.resrec.rroriginalttl && entry) RecordHostInfo(entry, &pkt.r.resrec);
767*48a54d36SAndroid Build Coastguard Worker }
768*48a54d36SAndroid Build Coastguard Worker }
769*48a54d36SAndroid Build Coastguard Worker
AddressMatchesFilterList(const mDNSAddr * srcaddr)770*48a54d36SAndroid Build Coastguard Worker mDNSlocal mDNSBool AddressMatchesFilterList(const mDNSAddr *srcaddr)
771*48a54d36SAndroid Build Coastguard Worker {
772*48a54d36SAndroid Build Coastguard Worker FilterList *f;
773*48a54d36SAndroid Build Coastguard Worker if (!Filters) return(srcaddr->type == mDNSAddrType_IPv4);
774*48a54d36SAndroid Build Coastguard Worker for (f=Filters; f; f=f->next) if (mDNSSameAddress(srcaddr, &f->FilterAddr)) return(mDNStrue);
775*48a54d36SAndroid Build Coastguard Worker return(mDNSfalse);
776*48a54d36SAndroid Build Coastguard Worker }
777*48a54d36SAndroid Build Coastguard Worker
mDNSCoreReceive(mDNS * const m,DNSMessage * const msg,const mDNSu8 * const end,const mDNSAddr * srcaddr,mDNSIPPort srcport,const mDNSAddr * dstaddr,mDNSIPPort dstport,const mDNSInterfaceID InterfaceID)778*48a54d36SAndroid Build Coastguard Worker mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
779*48a54d36SAndroid Build Coastguard Worker const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport, const mDNSInterfaceID InterfaceID)
780*48a54d36SAndroid Build Coastguard Worker {
781*48a54d36SAndroid Build Coastguard Worker const mDNSu8 StdQ = kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery;
782*48a54d36SAndroid Build Coastguard Worker const mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery;
783*48a54d36SAndroid Build Coastguard Worker const mDNSu8 QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask);
784*48a54d36SAndroid Build Coastguard Worker mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions;
785*48a54d36SAndroid Build Coastguard Worker int goodinterface = (FilterInterface == 0);
786*48a54d36SAndroid Build Coastguard Worker
787*48a54d36SAndroid Build Coastguard Worker (void)dstaddr; // Unused
788*48a54d36SAndroid Build Coastguard Worker (void)dstport; // Unused
789*48a54d36SAndroid Build Coastguard Worker
790*48a54d36SAndroid Build Coastguard Worker // Read the integer parts which are in IETF byte-order (MSB first, LSB second)
791*48a54d36SAndroid Build Coastguard Worker msg->h.numQuestions = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]);
792*48a54d36SAndroid Build Coastguard Worker msg->h.numAnswers = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]);
793*48a54d36SAndroid Build Coastguard Worker msg->h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]);
794*48a54d36SAndroid Build Coastguard Worker msg->h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]);
795*48a54d36SAndroid Build Coastguard Worker
796*48a54d36SAndroid Build Coastguard Worker // For now we're only interested in monitoring IPv4 traffic.
797*48a54d36SAndroid Build Coastguard Worker // All IPv6 packets should just be duplicates of the v4 packets.
798*48a54d36SAndroid Build Coastguard Worker if (!goodinterface) goodinterface = (FilterInterface == (int)mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNSfalse));
799*48a54d36SAndroid Build Coastguard Worker if (goodinterface && AddressMatchesFilterList(srcaddr))
800*48a54d36SAndroid Build Coastguard Worker {
801*48a54d36SAndroid Build Coastguard Worker mDNS_Lock(m);
802*48a54d36SAndroid Build Coastguard Worker if (!mDNSAddrIsDNSMulticast(dstaddr))
803*48a54d36SAndroid Build Coastguard Worker {
804*48a54d36SAndroid Build Coastguard Worker if (QR_OP == StdQ) mprintf("Unicast query from %#a\n", srcaddr);
805*48a54d36SAndroid Build Coastguard Worker else if (QR_OP == StdR) ProcessUnicastResponse(m, msg, end, srcaddr, InterfaceID);
806*48a54d36SAndroid Build Coastguard Worker }
807*48a54d36SAndroid Build Coastguard Worker else
808*48a54d36SAndroid Build Coastguard Worker {
809*48a54d36SAndroid Build Coastguard Worker if (QR_OP == StdQ) DisplayQuery (m, msg, end, srcaddr, srcport, dstaddr, InterfaceID);
810*48a54d36SAndroid Build Coastguard Worker else if (QR_OP == StdR) DisplayResponse (m, msg, end, srcaddr, srcport, dstaddr, InterfaceID);
811*48a54d36SAndroid Build Coastguard Worker else
812*48a54d36SAndroid Build Coastguard Worker {
813*48a54d36SAndroid Build Coastguard Worker debugf("Unknown DNS packet type %02X%02X (ignored)", msg->h.flags.b[0], msg->h.flags.b[1]);
814*48a54d36SAndroid Build Coastguard Worker GotPacketFromHost(srcaddr, HostPkt_B, msg->h.id);
815*48a54d36SAndroid Build Coastguard Worker NumPktB++;
816*48a54d36SAndroid Build Coastguard Worker }
817*48a54d36SAndroid Build Coastguard Worker }
818*48a54d36SAndroid Build Coastguard Worker mDNS_Unlock(m);
819*48a54d36SAndroid Build Coastguard Worker }
820*48a54d36SAndroid Build Coastguard Worker }
821*48a54d36SAndroid Build Coastguard Worker
mDNSNetMonitor(void)822*48a54d36SAndroid Build Coastguard Worker mDNSlocal mStatus mDNSNetMonitor(void)
823*48a54d36SAndroid Build Coastguard Worker {
824*48a54d36SAndroid Build Coastguard Worker struct tm tm;
825*48a54d36SAndroid Build Coastguard Worker int h, m, s, mul, div, TotPkt;
826*48a54d36SAndroid Build Coastguard Worker #if !defined(WIN32)
827*48a54d36SAndroid Build Coastguard Worker sigset_t signals;
828*48a54d36SAndroid Build Coastguard Worker #endif
829*48a54d36SAndroid Build Coastguard Worker
830*48a54d36SAndroid Build Coastguard Worker mStatus status = mDNS_Init(&mDNSStorage, &PlatformStorage,
831*48a54d36SAndroid Build Coastguard Worker mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
832*48a54d36SAndroid Build Coastguard Worker mDNS_Init_DontAdvertiseLocalAddresses,
833*48a54d36SAndroid Build Coastguard Worker mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
834*48a54d36SAndroid Build Coastguard Worker if (status) return(status);
835*48a54d36SAndroid Build Coastguard Worker
836*48a54d36SAndroid Build Coastguard Worker gettimeofday(&tv_start, NULL);
837*48a54d36SAndroid Build Coastguard Worker
838*48a54d36SAndroid Build Coastguard Worker #if defined( WIN32 )
839*48a54d36SAndroid Build Coastguard Worker status = SetupInterfaceList(&mDNSStorage);
840*48a54d36SAndroid Build Coastguard Worker if (status) return(status);
841*48a54d36SAndroid Build Coastguard Worker gStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
842*48a54d36SAndroid Build Coastguard Worker if (gStopEvent == INVALID_HANDLE_VALUE) return mStatus_UnknownErr;
843*48a54d36SAndroid Build Coastguard Worker if (!SetConsoleCtrlHandler(ConsoleControlHandler, TRUE)) return mStatus_UnknownErr;
844*48a54d36SAndroid Build Coastguard Worker while (WaitForSingleObjectEx(gStopEvent, INFINITE, TRUE) == WAIT_IO_COMPLETION)
845*48a54d36SAndroid Build Coastguard Worker DispatchSocketEvents(&mDNSStorage);
846*48a54d36SAndroid Build Coastguard Worker if (!SetConsoleCtrlHandler(ConsoleControlHandler, FALSE)) return mStatus_UnknownErr;
847*48a54d36SAndroid Build Coastguard Worker CloseHandle(gStopEvent);
848*48a54d36SAndroid Build Coastguard Worker #else
849*48a54d36SAndroid Build Coastguard Worker mDNSPosixListenForSignalInEventLoop(SIGINT);
850*48a54d36SAndroid Build Coastguard Worker mDNSPosixListenForSignalInEventLoop(SIGTERM);
851*48a54d36SAndroid Build Coastguard Worker
852*48a54d36SAndroid Build Coastguard Worker do
853*48a54d36SAndroid Build Coastguard Worker {
854*48a54d36SAndroid Build Coastguard Worker struct timeval timeout = { 0x3FFFFFFF, 0 }; // wait until SIGINT or SIGTERM
855*48a54d36SAndroid Build Coastguard Worker mDNSBool gotSomething;
856*48a54d36SAndroid Build Coastguard Worker mDNSPosixRunEventLoopOnce(&mDNSStorage, &timeout, &signals, &gotSomething);
857*48a54d36SAndroid Build Coastguard Worker }
858*48a54d36SAndroid Build Coastguard Worker while ( !( sigismember( &signals, SIGINT) || sigismember( &signals, SIGTERM)));
859*48a54d36SAndroid Build Coastguard Worker #endif
860*48a54d36SAndroid Build Coastguard Worker
861*48a54d36SAndroid Build Coastguard Worker // Now display final summary
862*48a54d36SAndroid Build Coastguard Worker TotPkt = NumPktQ + NumPktL + NumPktR;
863*48a54d36SAndroid Build Coastguard Worker gettimeofday(&tv_end, NULL);
864*48a54d36SAndroid Build Coastguard Worker tv_interval = tv_end;
865*48a54d36SAndroid Build Coastguard Worker if (tv_start.tv_usec > tv_interval.tv_usec)
866*48a54d36SAndroid Build Coastguard Worker { tv_interval.tv_usec += 1000000; tv_interval.tv_sec--; }
867*48a54d36SAndroid Build Coastguard Worker tv_interval.tv_sec -= tv_start.tv_sec;
868*48a54d36SAndroid Build Coastguard Worker tv_interval.tv_usec -= tv_start.tv_usec;
869*48a54d36SAndroid Build Coastguard Worker h = (tv_interval.tv_sec / 3600);
870*48a54d36SAndroid Build Coastguard Worker m = (tv_interval.tv_sec % 3600) / 60;
871*48a54d36SAndroid Build Coastguard Worker s = (tv_interval.tv_sec % 60);
872*48a54d36SAndroid Build Coastguard Worker if (tv_interval.tv_sec > 10)
873*48a54d36SAndroid Build Coastguard Worker {
874*48a54d36SAndroid Build Coastguard Worker mul = 60;
875*48a54d36SAndroid Build Coastguard Worker div = tv_interval.tv_sec;
876*48a54d36SAndroid Build Coastguard Worker }
877*48a54d36SAndroid Build Coastguard Worker else
878*48a54d36SAndroid Build Coastguard Worker {
879*48a54d36SAndroid Build Coastguard Worker mul = 60000;
880*48a54d36SAndroid Build Coastguard Worker div = tv_interval.tv_sec * 1000 + tv_interval.tv_usec / 1000;
881*48a54d36SAndroid Build Coastguard Worker if (div == 0) div=1;
882*48a54d36SAndroid Build Coastguard Worker }
883*48a54d36SAndroid Build Coastguard Worker
884*48a54d36SAndroid Build Coastguard Worker mprintf("\n\n");
885*48a54d36SAndroid Build Coastguard Worker localtime_r((time_t*)&tv_start.tv_sec, &tm);
886*48a54d36SAndroid Build Coastguard Worker mprintf("Started %3d:%02d:%02d.%06d\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tv_start.tv_usec);
887*48a54d36SAndroid Build Coastguard Worker localtime_r((time_t*)&tv_end.tv_sec, &tm);
888*48a54d36SAndroid Build Coastguard Worker mprintf("End %3d:%02d:%02d.%06d\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tv_end.tv_usec);
889*48a54d36SAndroid Build Coastguard Worker mprintf("Captured for %3d:%02d:%02d.%06d\n", h, m, s, tv_interval.tv_usec);
890*48a54d36SAndroid Build Coastguard Worker if (!Filters)
891*48a54d36SAndroid Build Coastguard Worker {
892*48a54d36SAndroid Build Coastguard Worker mprintf("Unique source addresses seen on network:");
893*48a54d36SAndroid Build Coastguard Worker if (IPv4HostList.num) mprintf(" %ld (IPv4)", IPv4HostList.num);
894*48a54d36SAndroid Build Coastguard Worker if (IPv6HostList.num) mprintf(" %ld (IPv6)", IPv6HostList.num);
895*48a54d36SAndroid Build Coastguard Worker if (!IPv4HostList.num && !IPv6HostList.num) mprintf(" None");
896*48a54d36SAndroid Build Coastguard Worker mprintf("\n");
897*48a54d36SAndroid Build Coastguard Worker }
898*48a54d36SAndroid Build Coastguard Worker mprintf("\n");
899*48a54d36SAndroid Build Coastguard Worker mprintf("Modern Query Packets: %7d (avg%5d/min)\n", NumPktQ, NumPktQ * mul / div);
900*48a54d36SAndroid Build Coastguard Worker mprintf("Legacy Query Packets: %7d (avg%5d/min)\n", NumPktL, NumPktL * mul / div);
901*48a54d36SAndroid Build Coastguard Worker mprintf("Multicast Response Packets: %7d (avg%5d/min)\n", NumPktR, NumPktR * mul / div);
902*48a54d36SAndroid Build Coastguard Worker mprintf("Total Multicast Packets: %7d (avg%5d/min)\n", TotPkt, TotPkt * mul / div);
903*48a54d36SAndroid Build Coastguard Worker mprintf("\n");
904*48a54d36SAndroid Build Coastguard Worker mprintf("Total New Service Probes: %7d (avg%5d/min)\n", NumProbes, NumProbes * mul / div);
905*48a54d36SAndroid Build Coastguard Worker mprintf("Total Goodbye Announcements: %7d (avg%5d/min)\n", NumGoodbyes, NumGoodbyes * mul / div);
906*48a54d36SAndroid Build Coastguard Worker mprintf("Total Query Questions: %7d (avg%5d/min)\n", NumQuestions, NumQuestions * mul / div);
907*48a54d36SAndroid Build Coastguard Worker mprintf("Total Queries from Legacy Clients:%7d (avg%5d/min)\n", NumLegacy, NumLegacy * mul / div);
908*48a54d36SAndroid Build Coastguard Worker mprintf("Total Answers/Announcements: %7d (avg%5d/min)\n", NumAnswers, NumAnswers * mul / div);
909*48a54d36SAndroid Build Coastguard Worker mprintf("Total Additional Records: %7d (avg%5d/min)\n", NumAdditionals, NumAdditionals * mul / div);
910*48a54d36SAndroid Build Coastguard Worker mprintf("\n");
911*48a54d36SAndroid Build Coastguard Worker printstats(kReportTopServices);
912*48a54d36SAndroid Build Coastguard Worker
913*48a54d36SAndroid Build Coastguard Worker if (!ExactlyOneFilter)
914*48a54d36SAndroid Build Coastguard Worker {
915*48a54d36SAndroid Build Coastguard Worker ShowSortedHostList(&IPv4HostList, kReportTopHosts);
916*48a54d36SAndroid Build Coastguard Worker ShowSortedHostList(&IPv6HostList, kReportTopHosts);
917*48a54d36SAndroid Build Coastguard Worker }
918*48a54d36SAndroid Build Coastguard Worker
919*48a54d36SAndroid Build Coastguard Worker mDNS_Close(&mDNSStorage);
920*48a54d36SAndroid Build Coastguard Worker return(0);
921*48a54d36SAndroid Build Coastguard Worker }
922*48a54d36SAndroid Build Coastguard Worker
main(int argc,char ** argv)923*48a54d36SAndroid Build Coastguard Worker mDNSexport int main(int argc, char **argv)
924*48a54d36SAndroid Build Coastguard Worker {
925*48a54d36SAndroid Build Coastguard Worker const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
926*48a54d36SAndroid Build Coastguard Worker int i;
927*48a54d36SAndroid Build Coastguard Worker mStatus status;
928*48a54d36SAndroid Build Coastguard Worker
929*48a54d36SAndroid Build Coastguard Worker #if defined(WIN32)
930*48a54d36SAndroid Build Coastguard Worker HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
931*48a54d36SAndroid Build Coastguard Worker #endif
932*48a54d36SAndroid Build Coastguard Worker
933*48a54d36SAndroid Build Coastguard Worker setlinebuf(stdout); // Want to see lines as they appear, not block buffered
934*48a54d36SAndroid Build Coastguard Worker
935*48a54d36SAndroid Build Coastguard Worker for (i=1; i<argc; i++)
936*48a54d36SAndroid Build Coastguard Worker {
937*48a54d36SAndroid Build Coastguard Worker if (i+1 < argc && !strcmp(argv[i], "-i") && atoi(argv[i+1]))
938*48a54d36SAndroid Build Coastguard Worker {
939*48a54d36SAndroid Build Coastguard Worker FilterInterface = atoi(argv[i+1]);
940*48a54d36SAndroid Build Coastguard Worker i += 2;
941*48a54d36SAndroid Build Coastguard Worker printf("Monitoring interface %d\n", FilterInterface);
942*48a54d36SAndroid Build Coastguard Worker }
943*48a54d36SAndroid Build Coastguard Worker else
944*48a54d36SAndroid Build Coastguard Worker {
945*48a54d36SAndroid Build Coastguard Worker struct in_addr s4;
946*48a54d36SAndroid Build Coastguard Worker struct in6_addr s6;
947*48a54d36SAndroid Build Coastguard Worker FilterList *f;
948*48a54d36SAndroid Build Coastguard Worker mDNSAddr a;
949*48a54d36SAndroid Build Coastguard Worker a.type = mDNSAddrType_IPv4;
950*48a54d36SAndroid Build Coastguard Worker
951*48a54d36SAndroid Build Coastguard Worker if (inet_pton(AF_INET, argv[i], &s4) == 1)
952*48a54d36SAndroid Build Coastguard Worker a.ip.v4.NotAnInteger = s4.s_addr;
953*48a54d36SAndroid Build Coastguard Worker else if (inet_pton(AF_INET6, argv[i], &s6) == 1)
954*48a54d36SAndroid Build Coastguard Worker {
955*48a54d36SAndroid Build Coastguard Worker a.type = mDNSAddrType_IPv6;
956*48a54d36SAndroid Build Coastguard Worker mDNSPlatformMemCopy(&a.ip.v6, &s6, sizeof(a.ip.v6));
957*48a54d36SAndroid Build Coastguard Worker }
958*48a54d36SAndroid Build Coastguard Worker else
959*48a54d36SAndroid Build Coastguard Worker {
960*48a54d36SAndroid Build Coastguard Worker struct hostent *h = gethostbyname(argv[i]);
961*48a54d36SAndroid Build Coastguard Worker if (h) a.ip.v4.NotAnInteger = *(long*)h->h_addr;
962*48a54d36SAndroid Build Coastguard Worker else goto usage;
963*48a54d36SAndroid Build Coastguard Worker }
964*48a54d36SAndroid Build Coastguard Worker
965*48a54d36SAndroid Build Coastguard Worker f = malloc(sizeof(*f));
966*48a54d36SAndroid Build Coastguard Worker f->FilterAddr = a;
967*48a54d36SAndroid Build Coastguard Worker f->next = Filters;
968*48a54d36SAndroid Build Coastguard Worker Filters = f;
969*48a54d36SAndroid Build Coastguard Worker }
970*48a54d36SAndroid Build Coastguard Worker }
971*48a54d36SAndroid Build Coastguard Worker
972*48a54d36SAndroid Build Coastguard Worker status = mDNSNetMonitor();
973*48a54d36SAndroid Build Coastguard Worker if (status) { fprintf(stderr, "%s: mDNSNetMonitor failed %d\n", progname, (int)status); return(status); }
974*48a54d36SAndroid Build Coastguard Worker return(0);
975*48a54d36SAndroid Build Coastguard Worker
976*48a54d36SAndroid Build Coastguard Worker usage:
977*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "\nmDNS traffic monitor\n");
978*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Usage: %s [-i index] [host]\n", progname);
979*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Optional [-i index] parameter displays only packets from that interface index\n");
980*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Optional [host] parameter displays only packets from that host\n");
981*48a54d36SAndroid Build Coastguard Worker
982*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "\nPer-packet header output:\n");
983*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "-Q- Multicast Query from mDNS client that accepts multicast responses\n");
984*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "-R- Multicast Response packet containing answers/announcements\n");
985*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "-LQ- Multicast Query from legacy client that does *not* listen for multicast responses\n");
986*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Q/Ans/Auth/Add Number of questions, answers, authority records and additional records in packet\n");
987*48a54d36SAndroid Build Coastguard Worker
988*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "\nPer-record display:\n");
989*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(PM) Probe Question (new service starting), requesting multicast response\n");
990*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(PU) Probe Question (new service starting), requesting unicast response\n");
991*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(DE) Deletion/Goodbye (service going away)\n");
992*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(LQ) Legacy Query Question\n");
993*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(QM) Query Question, requesting multicast response\n");
994*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(QU) Query Question, requesting unicast response\n");
995*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(KA) Known Answer (information querier already knows)\n");
996*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(AN) Unique Answer to question (or periodic announcment) (entire RR Set)\n");
997*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(AN+) Answer to question (or periodic announcment) (add to existing RR Set members)\n");
998*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(AD) Unique Additional Record Set (entire RR Set)\n");
999*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "(AD+) Additional records (add to existing RR Set members)\n");
1000*48a54d36SAndroid Build Coastguard Worker
1001*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "\nFinal summary, sorted by service type:\n");
1002*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Probe Probes for this service type starting up\n");
1003*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Goodbye Goodbye (deletion) packets for this service type shutting down\n");
1004*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "BrowseQ Browse questions from clients browsing to find a list of instances of this service\n");
1005*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "BrowseA Browse answers/announcments advertising instances of this service\n");
1006*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "ResolveQ Resolve questions from clients actively connecting to an instance of this service\n");
1007*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "ResolveA Resolve answers/announcments giving connection information for an instance of this service\n");
1008*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "\n");
1009*48a54d36SAndroid Build Coastguard Worker return(-1);
1010*48a54d36SAndroid Build Coastguard Worker }
1011