## gskdnsrrcache

gskdnsrrcache — A cache of Resource Record data.

## Synopsis

                        GskDnsRRCache;
    #define             GSK_TYPE_DNS_RR_CACHE
    GskDnsRRCache *     gsk_dns_rr_cache_new                (guint64 max_bytes,
                                                             guint max_records);
    GskDnsResourceRecord * gsk_dns_rr_cache_insert          (GskDnsRRCache *rr_cache,
                                                             const GskDnsResourceRecord *record,
                                                             gboolean is_authoritative,
                                                             gulong cur_time);
    GSList *            gsk_dns_rr_cache_lookup_list        (GskDnsRRCache *rr_cache,
                                                             const char *owner,
                                                             GskDnsResourceRecordType query_type,
                                                             GskDnsResourceClass query_class);
    GskDnsResourceRecord * gsk_dns_rr_cache_lookup_one      (GskDnsRRCache *rr_cache,
                                                             const char *owner,
                                                             GskDnsResourceRecordType query_type,
                                                             GskDnsResourceClass query_class,
                                                             GskDnsRRCacheLookupFlags flags);
    gboolean            gsk_dns_rr_cache_is_negative        (GskDnsRRCache *rr_cache,
                                                             const char *owner,
                                                             GskDnsResourceRecordType query_type,
                                                             GskDnsResourceClass query_class);
    void                gsk_dns_rr_cache_unlock             (GskDnsRRCache *rr_cache,
                                                             GskDnsResourceRecord *record);
    void                gsk_dns_rr_cache_lock               (GskDnsRRCache *rr_cache,
                                                             GskDnsResourceRecord *record);
    void                gsk_dns_rr_cache_mark_user          (GskDnsRRCache *rr_cache,
                                                             GskDnsResourceRecord *record);
    void                gsk_dns_rr_cache_unmark_user        (GskDnsRRCache *rr_cache,
                                                             GskDnsResourceRecord *record);
    void                gsk_dns_rr_cache_add_negative       (GskDnsRRCache *rr_cache,
                                                             const char *owner,
                                                             GskDnsResourceRecordType query_type,
                                                             GskDnsResourceClass query_class,
                                                             gulong expire_time,
                                                             gboolean is_authoritative);
    gboolean            gsk_dns_rr_cache_load_zone          (GskDnsRRCache *rr_cache,
                                                             const char *filename,
                                                             const char *default_origin,
                                                             GError **error);
    gboolean            gsk_dns_rr_cache_get_ns_addr        (GskDnsRRCache *rr_cache,
                                                             const char *host,
                                                             const char **ns_name_out,
                                                             GskSocketAddressIpv4 **address_out);
    gboolean            gsk_dns_rr_cache_get_addr           (GskDnsRRCache *rr_cache,
                                                             const char *host,
                                                             GskSocketAddressIpv4 **address);
    GskDnsRRCache *     gsk_dns_rr_cache_ref                (GskDnsRRCache *rr_cache);
    void                gsk_dns_rr_cache_unref              (GskDnsRRCache *rr_cache);
    void                gsk_dns_rr_cache_flush              (GskDnsRRCache *rr_cache,
                                                             gulong cur_time);
    gboolean            gsk_dns_rr_cache_parse_etc_hosts_line
                                                            (GskDnsRRCache *rr_cache,
                                                             const char *text);
    gboolean            gsk_dns_rr_cache_parse_etc_hosts    (GskDnsRRCache *rr_cache,
                                                             const char *filename,
                                                             gboolean may_be_missing);

## Description

This in a database of GskDnsResourceRecord's, as well as caching certain negative information. Furthermore, the GskDnsRRCache knows how to expire obsolete resource records automatically.

## Details

### GskDnsRRCache

    typedef struct _GskDnsRRCache GskDnsRRCache;

A cache of resource records and related information.

### GSK_TYPE_DNS_RR_CACHE

    #define             GSK_TYPE_DNS_RR_CACHE

Return the GType of a GskDnsRRCache. (It is a boxed type.)

### gsk_dns_rr_cache_new ()

    GskDnsRRCache *     gsk_dns_rr_cache_new                (guint64 max_bytes,
                                                             guint max_records);

Create a new, empty DNS cache.

`max_bytes` : | the maximum number of bytes to use for all the resource records and negative information in this pool. (Note that there is other overhead, like hash-tables, which is not considered in this number.)
`max_records` : | the maximum number of records in this cache.
Returns : | the new GskDnsRRCache.

### gsk_dns_rr_cache_insert ()

    GskDnsResourceRecord * gsk_dns_rr_cache_insert          (GskDnsRRCache *rr_cache,
                                                             const GskDnsResourceRecord *record,
                                                             gboolean is_authoritative,
                                                             gulong cur_time);

Insert a new finding into the resource-record cache.

`rr_cache` : | a resource-record cache.
`record` : | the record to store in the cache. (The cache will maintain its own copy of the data)
`is_authoritative` : | whether the entry comes from an authoritative source, as defined by RFC 1034.
`cur_time` : | the current time, used for figuring out the absolute expiration time.
Returns : | A new copy of the record is returned; if you wish to guarantee that the record is not deleted, you should call `gsk_dns_rr_cache_lock()` on it.

### gsk_dns_rr_cache_lookup_list ()

    GSList *            gsk_dns_rr_cache_lookup_list        (GskDnsRRCache *rr_cache,
                                                             const char *owner,
                                                             GskDnsResourceRecordType query_type,
                                                             GskDnsResourceClass query_class);

Lookup some or all information about a given name in `rr_cache`'s memory.

If you receive NULL, it may be because we have gotten negative information registered with `gsk_dns_rr_cache_add_negative()` or because we don't have a relevant record on file. You may call `gsk_dns_rr_cache_is_negative()` to distinguish these cases.

`rr_cache` : | a resource-record cache to query.
`owner` : | the domain name to lookup resource-records for.
`query_type` : | the type of resource-record to look up.
`query_class` : | the address namespace in which to look for the information.
Returns : | a list of GskDnsResourceRecord which you must call `gsk_dns_rr_cache_lock()` on if you want to keep around. However, you must call `g_slist_free()` on the list itself.

### gsk_dns_rr_cache_lookup_one ()

    GskDnsResourceRecord * gsk_dns_rr_cache_lookup_one      (GskDnsRRCache *rr_cache,
                                                             const char *owner,
                                                             GskDnsResourceRecordType query_type,
                                                             GskDnsResourceClass query_class,
                                                             GskDnsRRCacheLookupFlags flags);

Find the first appropriate resource record of a given specification.

If you receive NULL, it may be because we have gotten negative information registered with `gsk_dns_rr_cache_add_negative()` or because we don't have a relevant record on file. You may call `gsk_dns_rr_cache_is_negative()` to distinguish these cases.

`rr_cache` : | a resource-record cache to query.
`owner` : | the domain name to lookup resource-records for.
`query_type` : | the type of resource-record to look up.
`query_class` : | the address namespace in which to look for the information.
`flags` : |
Returns : | a pointer to a GskDnsResourceRecord. You must call `gsk_dns_rr_cache_lock()` on it if you want to keep it around.

### gsk_dns_rr_cache_is_negative ()

    gboolean            gsk_dns_rr_cache_is_negative        (GskDnsRRCache *rr_cache,
                                                             const char *owner,
                                                             GskDnsResourceRecordType query_type,
                                                             GskDnsResourceClass query_class);

Look to see if we have an explicit negative entry for this resource-record.

Note that if `query_type` or `query_class` is WILDCARD then there must be a negative wildcard resource-record in the cache.

A negative WILDCARD resource-record in the cache will satisfy any type or class.

`rr_cache` : | a resource-record cache.
`owner` : | name to lookup.
`query_type` : | type of query to answer.
`query_class` : | class of query to answer.
Returns : | TRUE if an explicit negative entry exists in the cache. FALSE means either a positive entry or no entry exists in the cache.

### gsk_dns_rr_cache_unlock ()

    void                gsk_dns_rr_cache_unlock             (GskDnsRRCache *rr_cache,
                                                             GskDnsResourceRecord *record);

Reduce the lock-count of this record within the cache. When a record is locked, it will not be deleted, even if memory requirements are violated as a result.

Once the lock-count is zero, the resource record will be deleted whenever it grows sufficiently stale, or resources grow sufficiently scarce.

`rr_cache` : | a resource-record cache.
`record` : | a locked record belonging to that cache.

### gsk_dns_rr_cache_lock ()

    void                gsk_dns_rr_cache_lock               (GskDnsRRCache *rr_cache,
                                                             GskDnsResourceRecord *record);

Lock this record in the cache. When a record is locked, it will not be deleted, even if memory requirements are violated as a result.

`rr_cache` : | a resource-record cache.
`record` : | a record obtained from `gsk_dns_rr_cache_lookup_one()` or `gsk_dns_rr_cache_lookup_list()`.

### gsk_dns_rr_cache_mark_user ()

    void                gsk_dns_rr_cache_mark_user          (GskDnsRRCache *rr_cache,
                                                             GskDnsResourceRecord *record);

Indicate that a record should be regarded as completely authoritative. This is like locking the record, but additionally, the record will be used no matter what other supposed authorities say.

This is currently just used for handling /etc/hosts, whose entries precede any other name-server checking.

You should not call this function if the is_from_user flag is already set.

`rr_cache` : | a resource-record cache.
`record` : | a record obtained from `gsk_dns_rr_cache_lookup_one()` or `gsk_dns_rr_cache_lookup_list()`.

### gsk_dns_rr_cache_unmark_user ()

    void                gsk_dns_rr_cache_unmark_user        (GskDnsRRCache *rr_cache,
                                                             GskDnsResourceRecord *record);

Undo the affect of `gsk_dns_rr_cache_mark_user()`.

`rr_cache` : | a resource-record cache.
`record` : | a record which had previously been passed to `gsk_dns_rr_cache_mark_user()`.

### gsk_dns_rr_cache_add_negative ()

    void                gsk_dns_rr_cache_add_negative       (GskDnsRRCache *rr_cache,
                                                             const char *owner,
                                                             GskDnsResourceRecordType query_type,
                                                             GskDnsResourceClass query_class,
                                                             gulong expire_time,
                                                             gboolean is_authoritative);

Add an entry into the cache indicating that there is no entry of the given type.

The DNS specification refers to this as 'negative caching'.

`rr_cache` : | a resource-record cache.
`owner` : | the name which the negative response belongs to.
`query_type` : | type of negative response.
`query_class` : | address namespace of negative response.
`expire_time` : | when this negative record should be deleted.
`is_authoritative` : | whether this negative record came from an authority.

### gsk_dns_rr_cache_load_zone ()

    gboolean            gsk_dns_rr_cache_load_zone          (GskDnsRRCache *rr_cache,
                                                             const char *filename,
                                                             const char *default_origin,
                                                             GError **error);

Parse a zone file. This file format is defined in RFC 1035, Section 5.

`rr_cache` : | a resource-record cache.
`filename` : | a zone file to parse.
`default_origin` : | the initial origin.
`error` : |
Returns : | whether the zone file was parsed successfully.

### gsk_dns_rr_cache_get_ns_addr ()

    gboolean            gsk_dns_rr_cache_get_ns_addr        (GskDnsRRCache *rr_cache,
                                                             const char *host,
                                                             const char **ns_name_out,
                                                             GskSocketAddressIpv4 **address_out);

Look up an address for a nameserver.

`rr_cache` : | a resource-record cache.
`host` : | the name to find a nameserver for.
`ns_name_out` : | a string, maintained by the RRCache, for the nameserver record, if there is any present. The string should not be freed by the caller.
`address_out` : | pointer to where the returned address should be put. The address should be g_object_unref'd by the caller.
Returns : | whether an address could be found.

### gsk_dns_rr_cache_get_addr ()

    gboolean            gsk_dns_rr_cache_get_addr           (GskDnsRRCache *rr_cache,
                                                             const char *host,
                                                             GskSocketAddressIpv4 **address);

Look up the IP address of a name. This will follow CNAME records.

BUGS: - OBSOLETE BUG: This will allow a loop of CNAMEs to cause a hang! (i think i fixed this bug...)

`rr_cache` : | a resource-record cache.
`host` : | a name to obtain an IP address for.
`address` : | pointer to where the returned address should be put.
Returns : | whether the cache has sufficient information to resolve the name.

### gsk_dns_rr_cache_ref ()

    GskDnsRRCache *     gsk_dns_rr_cache_ref                (GskDnsRRCache *rr_cache);

Increase the reference count on the resource record cache. The cache will not be destroyed until the reference count gets to 0.

`rr_cache` : | a resource-record cache.
Returns : | `rr_cache`, for convenience.

### gsk_dns_rr_cache_unref ()

    void                gsk_dns_rr_cache_unref              (GskDnsRRCache *rr_cache);

Decrease the reference count on the resource record cache. The cache will be destroyed when the reference count gets to 0.

`rr_cache` : | a resource-record cache.

### gsk_dns_rr_cache_flush ()

    void                gsk_dns_rr_cache_flush              (GskDnsRRCache *rr_cache,
                                                             gulong cur_time);

Flush out the expired records from the cache, and try to ensure that we are using an acceptable amount of memory.

`rr_cache` : | a resource-record cache.
`cur_time` : | the current unix time.

### gsk_dns_rr_cache_parse_etc_hosts_line ()

    gboolean            gsk_dns_rr_cache_parse_etc_hosts_line
                                                            (GskDnsRRCache *rr_cache,
                                                             const char *text);

Process a single line of text from an /etc/hosts file.

This file format is defined in RFC 952.

TODO: this does not handle IPv6 correctly!!!

`rr_cache` : | a resource-record cache.
`text` : | a line from an /etc/hosts file.
Returns : | whether the line was parsed successfully.

### gsk_dns_rr_cache_parse_etc_hosts ()

    gboolean            gsk_dns_rr_cache_parse_etc_hosts    (GskDnsRRCache *rr_cache,
                                                             const char *filename,
                                                             gboolean may_be_missing);

Process an /etc/hosts file.

This file format is defined in RFC 952.

TODO: this does not handle IPv6 correctly!!!

`rr_cache` : | a resource-record cache.
`filename` : | an /etc/hosts file.
`may_be_missing` : | whether to return an error if the file does not exist.
Returns : | whether the file was parsed successfully.