This file is indexed.

/usr/include/pjlib-util/resolver.h is in libpjproject-dev 2.7.2~dfsg-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
/* $Id: resolver.h 5349 2016-06-20 10:10:42Z nanang $ */
/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#ifndef __PJLIB_UTIL_RESOLVER_H__
#define __PJLIB_UTIL_RESOLVER_H__

/**
 * @file resolver.h
 * @brief Asynchronous DNS resolver
 */
#include <pjlib-util/dns.h>


PJ_BEGIN_DECL


/**
 * @defgroup PJ_DNS_RESOLVER DNS Asynchronous/Caching Resolution Engine
 * @ingroup PJ_DNS
 * @{
 *
 * This module manages the host/server resolution by performing asynchronous
 * DNS queries and caching the results in the cache. It uses PJLIB-UTIL 
 * low-level DNS parsing functions (see @ref PJ_DNS) and currently supports
 * several types of DNS resource records such as A record (typical query with
 * gethostbyname()) and SRV record.
 *
 * \section PJ_DNS_RESOLVER_FEATURES Features
 *
 * \subsection PJ_DNS_RESOLVER_FEATURES_ASYNC Asynchronous Query and Query Aggregation
 * 
 * The DNS queries are performed asychronously, with timeout setting 
 * configured on per resolver instance basis. Application can issue multiple
 * asynchronous queries simultaneously. Subsequent queries to the same resource
 * (name and DNS resource type) while existing query is still pending will be
 * merged into one query, so that only one DNS request packet is issued.
 * 
 * \subsection PJ_DNS_RESOLVER_FEATURES_RETRANSMISSION Query Retransmission
 *
 * Asynchronous query will be retransmitted if no response is received
 * within the preconfigured time. Once maximum retransmission count is
 * exceeded and no response is received, the query will time out and the
 * callback will be called when error status.
 *
 * \subsection PJ_DNS_RESOLVER_FEATURES_CACHING Response Caching with TTL
 *
 * The resolver instance caches the results returned by nameservers, to
 * enhance the performance by minimizing the message round-trip to the server.
 * The TTL of the cached resposne is calculated from minimum TTL value found 
 * across all resource record (RR) TTL in the response and further more it can
 * be limited to some preconfigured maximum TTL in the resolver. 
 *
 * Response caching can be  disabled by setting the maximum TTL value of the 
 * resolver to zero.
 *
 * \subsection PJ_DNS_RESOLVER_FEATURES_PARALLEL Parallel and Backup Name Servers
 *
 * When the resolver is configured with multiple nameservers, initially the
 * queries will be issued to multiple name servers simultaneously to probe
 * which servers are not active. Once the probing stage is done, subsequent 
 * queries will be directed to only one ACTIVE server which provides the best
 * response time.
 *
 * Name servers are probed periodically to see which nameservers are active
 * and which are down. This probing is done when a query is sent, thus no
 * timer is needed to maintain this. Also probing will be done in parallel
 * so that there would be no additional delay for the query.
 *
 *
 * \subsection PJ_DNS_RESOLVER_FEATURES_REC Supported Resource Records
 *
 * The low-level DNS parsing utility (see @ref PJ_DNS) supports parsing of
 * the following DNS resource records (RR):
 *  - DNS A record
 *  - DNS SRV record
 *  - DNS PTR record
 *  - DNS NS record
 *  - DNS CNAME record
 *
 * For other types of record, application can parse the raw resource 
 * record data (rdata) from the parsed DNS packet (#pj_dns_parsed_packet).
 *
 *
 * \section PJ_DNS_RESOLVER_USING Using the Resolver
 *
 * To use the resolver, application first creates the resolver instance by
 * calling #pj_dns_resolver_create(). If application already has its own
 * timer and ioqueue instances, it can instruct the resolver to use these
 * instances so that application does not need to poll the resolver 
 * periodically to process events. If application does not specify the
 * timer and ioqueue instance for the resolver, an internal timer and
 * ioqueue will be created by the resolver. And since the resolver does not
 * create it's own thread, application MUST poll the resolver periodically
 * by calling #pj_dns_resolver_handle_events() to allow events (network and 
 * timer) to be processed.
 *
 * Next, application MUST configure the nameservers to be used by the
 * resolver, by calling #pj_dns_resolver_set_ns().
 *
 * Application performs asynchronous query by submitting the query with
 * #pj_dns_resolver_start_query(). Once the query completes (either 
 * successfully or times out), the callback will be called.
 *
 * Application can cancel a pending query by calling #pj_dns_resolver_cancel_query().
 *
 * Resolver must be destroyed by calling #pj_dns_resolver_destroy() to
 * release all resources back to the system.
 *
 *
 * \section PJ_DNS_RESOLVER_LIMITATIONS Resolver Limitations
 *
 * Current implementation mainly suffers from a growing memory problem,
 * which mainly is caused by the response caching. Although there is only
 * one cache entry per {query, name} combination, these cache entry will
 * never get deleted since there is no timer is created to invalidate these
 * entries. So the more unique names being queried by application, there more
 * enties will be created in the response cache.
 *
 * Note that a single response entry will occupy about 600-700 bytes of 
 * pool memory (the PJ_DNS_RESOLVER_RES_BUF_SIZE value plus internal
 * structure). 
 *
 * Application can work around this problem by doing one of these:
 *  - disable caching by setting PJ_DNS_RESOLVER_MAX_TTL and 
 *    PJ_DNS_RESOLVER_INVALID_TTL to zero.
 *  - periodically query #pj_dns_resolver_get_cached_count() and destroy-
 *    recreate the resolver to recycle the memory used by the resolver.
 *
 * Note that future improvement may solve this problem by introducing 
 * expiration timer to the cached entries.
 *
 *
 * \section PJ_DNS_RESOLVER_REFERENCE Reference
 *
 * The PJLIB-UTIL resolver was built from the information in the following
 * standards:
 *  - <A HREF="http://www.faqs.org/rfcs/rfc1035.html">
 *    RFC 1035: "Domain names - implementation and specification"</A>
 *  - <A HREF="http://www.faqs.org/rfcs/rfc2782.html">
 *    RFC 2782: "A DNS RR for specifying the location of services (DNS SRV)"
 *    </A>
 */



/**
 * Opaque data type for DNS resolver object.
 */
typedef struct pj_dns_resolver pj_dns_resolver;

/**
 * Opaque data type for asynchronous DNS query object.
 */
typedef struct pj_dns_async_query pj_dns_async_query;

/**
 * Type of asynchronous callback which will be called when the asynchronous
 * query completes.
 *
 * @param user_data	The user data set by application when creating the
 *			asynchronous query.
 * @param status	Status of the DNS resolution.
 * @param response	The response packet received from the server. This
 *			argument may be NULL when status is not PJ_SUCCESS.
 */
typedef void pj_dns_callback(void *user_data,
			     pj_status_t status,
			     pj_dns_parsed_packet *response);


/**
 * This structure describes resolver settings.
 */
typedef struct pj_dns_settings
{
    unsigned	options;	/**< Options flags.			    */
    unsigned	qretr_delay;	/**< Query retransmit delay in msec.	    */
    unsigned	qretr_count;	/**< Query maximum retransmission count.    */
    unsigned	cache_max_ttl;	/**< Maximum TTL for cached responses. If the
				     value is zero, caching is disabled.    */
    unsigned	good_ns_ttl;	/**< See #PJ_DNS_RESOLVER_GOOD_NS_TTL	    */
    unsigned	bad_ns_ttl;	/**< See #PJ_DNS_RESOLVER_BAD_NS_TTL	    */
} pj_dns_settings;


/**
 * This structure represents DNS A record, as the result of parsing
 * DNS response packet using #pj_dns_parse_a_response().
 */
typedef struct pj_dns_a_record
{
    /** The target name being queried.   */
    pj_str_t		name;

    /** If target name corresponds to a CNAME entry, the alias contains
     *  the value of the CNAME entry, otherwise it will be empty.
     */
    pj_str_t		alias;

    /** Number of IP addresses. */
    unsigned		addr_count;

    /** IP addresses of the host found in the response */
    pj_in_addr		addr[PJ_DNS_MAX_IP_IN_A_REC];

    /** Internal buffer for hostname and alias. */
    char		buf_[128];

} pj_dns_a_record;


/**
 * This structure represents DNS address record, i.e: DNS A and DNS AAAA
 * records, as the result of parsing DNS response packet using
 * #pj_dns_parse_addr_response().
 */
typedef struct pj_dns_addr_record
{
    /** The target name being queried.   */
    pj_str_t		name;

    /** If target name corresponds to a CNAME entry, the alias contains
     *  the value of the CNAME entry, otherwise it will be empty.
     */
    pj_str_t		alias;

    /** Number of IP addresses. */
    unsigned		addr_count;

    /** IP addresses of the host found in the response */
    struct {

	/** IP address family */
	int		af;
	
	/** IP address */
	union {
	    /** IPv4 address */
	    pj_in_addr	v4;

	    /** IPv6 address */
	    pj_in6_addr	v6;
	} ip;

    } addr[PJ_DNS_MAX_IP_IN_A_REC];

    /** Internal buffer for hostname and alias. */
    char		buf_[128];

} pj_dns_addr_record;


/**
 * Set default values to the DNS settings.
 *
 * @param s	    The DNS settings to be initialized.
 */
PJ_DECL(void) pj_dns_settings_default(pj_dns_settings *s);


/**
 * Create DNS resolver instance. After the resolver is created, application
 * MUST configure the nameservers with #pj_dns_resolver_set_ns().
 *
 * When creating the resolver, application may specify both timer heap
 * and ioqueue instance, so that it doesn't need to poll the resolver
 * periodically.
 *
 * @param pf	     Pool factory where the memory pool will be created from.
 * @param name	     Optional resolver name to identify the instance in 
 *		     the log.
 * @param options    Optional options, must be zero for now.
 * @param timer	     Optional timer heap instance to be used by the resolver.
 *		     If timer heap is not specified, an internal timer will be
 *		     created, and application would need to poll the resolver
 *		     periodically.
 * @param ioqueue    Optional I/O Queue instance to be used by the resolver.
 *		     If ioqueue is not specified, an internal one will be
 *		     created, and application would need to poll the resolver
 *		     periodically.
 * @param p_resolver Pointer to receive the resolver instance.
 *
 * @return	     PJ_SUCCESS on success, or the appropriate error code,
 */
PJ_DECL(pj_status_t) pj_dns_resolver_create(pj_pool_factory *pf,
					    const char *name,
					    unsigned options,
					    pj_timer_heap_t *timer,
					    pj_ioqueue_t *ioqueue,
					    pj_dns_resolver **p_resolver);


/**
 * Update the name servers for the DNS resolver. The name servers MUST be
 * configured before any resolution can be done. The order of nameservers
 * specifies their priority; the first name server will be tried first
 * before the next in the list.
 *
 * @param resolver  The resolver instance.
 * @param count     Number of name servers in the array.
 * @param servers   Array of name server IP addresses or hostnames. If
 *		    hostname is specified, the hostname must be resolvable
 *		    with pj_gethostbyname().
 * @param ports	    Optional array of ports. If this argument is NULL,
 *		    the nameserver will use default port.
 *
 * @return	    PJ_SUCCESS on success, or the appropriate error code,
 */
PJ_DECL(pj_status_t) pj_dns_resolver_set_ns(pj_dns_resolver *resolver,
					    unsigned count,
					    const pj_str_t servers[],
					    const pj_uint16_t ports[]);


/**
 * Get the resolver current settings.
 *
 * @param resolver  The resolver instance.
 * @param st	    Buffer to be filled up with resolver settings.
 *
 * @return	    The query timeout setting, in seconds.
 */
PJ_DECL(pj_status_t) pj_dns_resolver_get_settings(pj_dns_resolver *resolver,
						  pj_dns_settings *st);


/**
 * Modify the resolver settings. Application should initialize the settings
 * by retrieving current settings first before applying new settings, to
 * ensure that all fields are initialized properly.
 *
 * @param resolver  The resolver instance.
 * @param st	    The resolver settings.
 *
 * @return	    PJ_SUCCESS on success, or the appropriate error code,
 */
PJ_DECL(pj_status_t) pj_dns_resolver_set_settings(pj_dns_resolver *resolver,
						  const pj_dns_settings *st);


/**
 * Poll for events from the resolver. This function MUST be called 
 * periodically when the resolver is using it's own timer or ioqueue
 * (in other words, when NULL is specified as either \a timer or
 * \a ioqueue argument in #pj_dns_resolver_create()).
 *
 * @param resolver  The resolver instance.
 * @param timeout   Maximum time to wait for event occurence. If this
 *		    argument is NULL, this function will wait forever
 *		    until events occur.
 */
PJ_DECL(void) pj_dns_resolver_handle_events(pj_dns_resolver *resolver,
					    const pj_time_val *timeout);


/**
 * Destroy DNS resolver instance.
 *
 * @param resolver  The resolver object to be destryed
 * @param notify    If non-zero, all pending asynchronous queries will be
 *		    cancelled and its callback will be called. If FALSE,
 *		    then no callback will be called.
 *
 * @return	    PJ_SUCCESS on success, or the appropriate error code,
 */
PJ_DECL(pj_status_t) pj_dns_resolver_destroy(pj_dns_resolver *resolver,
					     pj_bool_t notify);


/**
 * Create and start asynchronous DNS query for a single resource. Depending
 * on whether response cache is available, this function will either start
 * an asynchronous DNS query or call the callback immediately.
 *
 * If response is not available in the cache, an asynchronous query will be
 * started, and callback will be called at some time later when the query
 * completes. If \a p_query argument is not NULL, it will be filled with
 * the asynchronous query object.
 *
 * If response is available in the cache, the callback will be called 
 * immediately before this function returns. In this case, if \a p_query
 * argument is not NULL, the value will be set to NULL since no new query
 * is started.
 *
 * @param resolver  The resolver object.
 * @param name	    The name to be resolved.
 * @param type	    The type of resource (see #pj_dns_type constants).
 * @param options   Optional options, must be zero for now.
 * @param cb	    Callback to be called when the query completes,
 *		    either successfully or with failure.
 * @param user_data Arbitrary user data to be associated with the query,
 *		    and which will be given back in the callback.
 * @param p_query   Optional pointer to receive the query object, if one
 *		    was started. If this pointer is specified, a NULL may
 *		    be returned if response cache is available immediately.
 *
 * @return	    PJ_SUCCESS if either an asynchronous query has been 
 *		    started successfully or response cache is available and
 *		    the user callback has been called.
 */
PJ_DECL(pj_status_t) pj_dns_resolver_start_query(pj_dns_resolver *resolver,
						 const pj_str_t *name,
						 int type,
						 unsigned options,
						 pj_dns_callback *cb,
						 void *user_data,
						 pj_dns_async_query **p_query);

/**
 * Cancel a pending query.
 *
 * @param query	    The pending asynchronous query to be cancelled.
 * @param notify    If non-zero, the callback will be called with failure
 *		    status to notify that the query has been cancelled.
 *
 * @return	    PJ_SUCCESS on success, or the appropriate error code,
 */
PJ_DECL(pj_status_t) pj_dns_resolver_cancel_query(pj_dns_async_query *query,
						  pj_bool_t notify);

/**
 * A utility function to parse a DNS response containing A records into 
 * DNS A record.
 *
 * @param pkt	    The DNS response packet.
 * @param rec	    The structure to be initialized with the parsed
 *		    DNS A record from the packet.
 *
 * @return	    PJ_SUCCESS if response can be parsed successfully.
 */
PJ_DECL(pj_status_t) pj_dns_parse_a_response(const pj_dns_parsed_packet *pkt,
					     pj_dns_a_record *rec);


/**
 * A utility function to parse a DNS response containing AAAA records into 
 * DNS AAAA record.
 *
 * @param pkt	    The DNS response packet.
 * @param rec	    The structure to be initialized with the parsed
 *		    DNS AAAA record from the packet.
 *
 * @return	    PJ_SUCCESS if response can be parsed successfully.
 */
PJ_DECL(pj_status_t) pj_dns_parse_addr_response(
					    const pj_dns_parsed_packet *pkt,
					    pj_dns_addr_record *rec);


/**
 * Put the specified DNS packet into DNS cache. This function is mainly used
 * for testing the resolver, however it can also be used to inject entries
 * into the resolver.
 *
 * The packet MUST contain either answer section or query section so that
 * it can be indexed.
 *
 * @param resolver  The resolver instance.
 * @param pkt	    DNS packet to be added to the DNS cache. If the packet
 *		    matches existing entry, it will update the entry.
 * @param set_ttl   If the value is PJ_FALSE, the entry will not expire 
 *		    (so use with care). Otherwise cache expiration will be
 *		    calculated based on the TTL of the answeres.
 *
 * @return	    PJ_SUCCESS on success, or the appropriate error code.
 */
PJ_DECL(pj_status_t) pj_dns_resolver_add_entry(pj_dns_resolver *resolver,
					       const pj_dns_parsed_packet *pkt,
					       pj_bool_t set_ttl);

/**
 * Get the total number of response in the response cache.
 *
 * @param resolver  The resolver instance.
 *
 * @return	    Current number of entries being stored in the response
 *		    cache.
 */
PJ_DECL(unsigned) pj_dns_resolver_get_cached_count(pj_dns_resolver *resolver);


/**
 * Dump resolver state to the log.
 *
 * @param resolver  The resolver instance.
 * @param detail    Will print detailed entries.
 */
PJ_DECL(void) pj_dns_resolver_dump(pj_dns_resolver *resolver,
				   pj_bool_t detail);


/**
 * @}
 */

PJ_END_DECL


#endif	/* __PJLIB_UTIL_RESOLVER_H__ */