NetBSD/gnu/dist/postfix/dns/dns_rr.c

196 lines
4.5 KiB
C

/*++
/* NAME
/* dns_rr 3
/* SUMMARY
/* resource record memory and list management
/* SYNOPSIS
/* #include <dns.h>
/*
/* DNS_RR *dns_rr_create(name, fixed, preference, data, data_len)
/* const char *name;
/* DNS_FIXED *fixed;
/* unsigned preference;
/* const char *data;
/* unsigned len;
/*
/* void dns_rr_free(list)
/* DNS_RR *list;
/*
/* DNS_RR *dns_rr_copy(record)
/* DNS_RR *record;
/*
/* DNS_RR *dns_rr_append(list, record)
/* DNS_RR *list;
/* DNS_RR *record;
/*
/* DNS_RR *dns_rr_sort(list, compar)
/* DNS_RR *list
/* int (*compar)(DNS_RR *, DNS_RR *);
/* DESCRIPTION
/* The routines in this module maintain memory for DNS resource record
/* information, and maintain lists of DNS resource records.
/*
/* dns_rr_create() creates and initializes one resource record.
/* The \fIname\fR record specifies the record name.
/* The \fIfixed\fR argument specifies generic resource record
/* information such as resource type and time to live;
/* \fIpreference\fR is used for MX records; \fIdata\fR is a null
/* pointer or specifies optional resource-specific data;
/* \fIdata_len\fR is the amount of resource-specific data.
/*
/* dns_rr_free() releases the resource used by of zero or more
/* resource records.
/*
/* dns_rr_copy() makes a copy of a resource record.
/*
/* dns_rr_append() appends a resource record to a (list of) resource
/* record(s).
/*
/* dns_rr_sort() sorts a list of resource records into ascending
/* order according to a user-specified criterion. The result is the
/* sorted list.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <string.h>
#include <stdlib.h>
/* Utility library. */
#include <msg.h>
#include <mymalloc.h>
/* DNS library. */
#include "dns.h"
/* dns_rr_create - fill in resource record structure */
DNS_RR *dns_rr_create(const char *name, DNS_FIXED *fixed, unsigned pref,
const char *data, unsigned data_len)
{
DNS_RR *rr;
rr = (DNS_RR *) mymalloc(sizeof(*rr) + data_len - 1);
rr->name = mystrdup(name);
rr->type = fixed->type;
rr->class = fixed->class;
rr->ttl = fixed->ttl;
rr->pref = pref;
if (data && data_len > 0)
memcpy(rr->data, data, data_len);
rr->data_len = data_len;
rr->next = 0;
return (rr);
}
/* dns_rr_free - destroy resource record structure */
void dns_rr_free(DNS_RR *rr)
{
if (rr) {
if (rr->next)
dns_rr_free(rr->next);
myfree(rr->name);
myfree((char *) rr);
}
}
/* dns_rr_copy - copy resource record */
DNS_RR *dns_rr_copy(DNS_RR *src)
{
int len = sizeof(*src) + src->data_len - 1;
DNS_RR *dst;
/*
* Combine struct assignment and data copy in one block copy operation.
*/
dst = (DNS_RR *) mymalloc(len);
memcpy((char *) dst, (char *) src, len);
dst->name = mystrdup(src->name);
dst->next = 0;
return (dst);
}
/* dns_rr_append - append resource record to list */
DNS_RR *dns_rr_append(DNS_RR *list, DNS_RR *rr)
{
if (list == 0) {
list = rr;
} else {
list->next = dns_rr_append(list->next, rr);
}
return (list);
}
/* dns_rr_sort_callback - glue function */
static int (*dns_rr_sort_user) (DNS_RR *, DNS_RR *);
static int dns_rr_sort_callback(const void *a, const void *b)
{
DNS_RR *aa = *(DNS_RR **) a;
DNS_RR *bb = *(DNS_RR **) b;
return (dns_rr_sort_user(aa, bb));
}
/* dns_rr_sort - sort resource record list */
DNS_RR *dns_rr_sort(DNS_RR *list, int (*compar) (DNS_RR *, DNS_RR *))
{
int (*saved_user) (DNS_RR *, DNS_RR *);
DNS_RR **rr_array;
DNS_RR *rr;
int len;
int i;
/*
* Save state and initialize.
*/
saved_user = dns_rr_sort_user;
dns_rr_sort_user = compar;
/*
* Build linear array with pointers to each list element.
*/
for (len = 0, rr = list; rr != 0; len++, rr = rr->next)
/* void */ ;
rr_array = (DNS_RR **) mymalloc(len * sizeof(*rr_array));
for (len = 0, rr = list; rr != 0; len++, rr = rr->next)
rr_array[len] = rr;
/*
* Sort by user-specified criterion.
*/
qsort((char *) rr_array, len, sizeof(*rr_array), dns_rr_sort_callback);
/*
* Fix the links.
*/
for (i = 0; i < len - 1; i++)
rr_array[i]->next = rr_array[i + 1];
rr_array[i]->next = 0;
list = rr_array[0];
/*
* Cleanup.
*/
myfree((char *) rr_array);
dns_rr_sort_user = saved_user;
return (list);
}