7 /* resource record memory and list management
11 /* DNS_RR *dns_rr_create(qname, rname, type, class, ttl, preference,
15 /* unsigned short type;
16 /* unsigned short class;
18 /* unsigned preference;
22 /* void dns_rr_free(list)
25 /* DNS_RR *dns_rr_copy(record)
28 /* DNS_RR *dns_rr_append(list, record)
32 /* DNS_RR *dns_rr_sort(list, compar)
34 /* int (*compar)(DNS_RR *, DNS_RR *);
36 /* int dns_rr_compare_pref(DNS_RR *a, DNS_RR *b)
40 /* DNS_RR *dns_rr_shuffle(list)
43 /* DNS_RR *dns_rr_remove(list, record)
47 /* The routines in this module maintain memory for DNS resource record
48 /* information, and maintain lists of DNS resource records.
50 /* dns_rr_create() creates and initializes one resource record.
51 /* The \fIqname\fR field specifies the query name.
52 /* The \fIrname\fR field specifies the reply name.
53 /* \fIpreference\fR is used for MX records; \fIdata\fR is a null
54 /* pointer or specifies optional resource-specific data;
55 /* \fIdata_len\fR is the amount of resource-specific data.
57 /* dns_rr_free() releases the resource used by of zero or more
60 /* dns_rr_copy() makes a copy of a resource record.
62 /* dns_rr_append() appends a resource record to a (list of) resource
64 /* A null input list is explicitly allowed.
66 /* dns_rr_sort() sorts a list of resource records into ascending
67 /* order according to a user-specified criterion. The result is the
70 /* dns_rr_compare_pref() is a dns_rr_sort() helper to sort records
71 /* by their MX preference.
73 /* dns_rr_shuffle() randomly permutes a list of resource records.
75 /* dns_rr_remove() removes the specified record from the specified list.
76 /* The updated list is the result value.
77 /* The record MUST be a list member.
81 /* The Secure Mailer license must be distributed with this software.
84 /* IBM T.J. Watson Research
86 /* Yorktown Heights, NY 10598, USA
95 /* Utility library. */
105 /* dns_rr_create - fill in resource record structure */
107 DNS_RR
*dns_rr_create(const char *qname
, const char *rname
,
108 ushort type
, ushort
class,
109 unsigned int ttl
, unsigned pref
,
110 const char *data
, size_t data_len
)
114 rr
= (DNS_RR
*) mymalloc(sizeof(*rr
) + data_len
- 1);
115 rr
->qname
= mystrdup(qname
);
116 rr
->rname
= mystrdup(rname
);
121 if (data
&& data_len
> 0)
122 memcpy(rr
->data
, data
, data_len
);
123 rr
->data_len
= data_len
;
128 /* dns_rr_free - destroy resource record structure */
130 void dns_rr_free(DNS_RR
*rr
)
134 dns_rr_free(rr
->next
);
141 /* dns_rr_copy - copy resource record */
143 DNS_RR
*dns_rr_copy(DNS_RR
*src
)
145 ssize_t len
= sizeof(*src
) + src
->data_len
- 1;
149 * Combine struct assignment and data copy in one block copy operation.
151 dst
= (DNS_RR
*) mymalloc(len
);
152 memcpy((char *) dst
, (char *) src
, len
);
153 dst
->qname
= mystrdup(src
->qname
);
154 dst
->rname
= mystrdup(src
->rname
);
159 /* dns_rr_append - append resource record to list */
161 DNS_RR
*dns_rr_append(DNS_RR
*list
, DNS_RR
*rr
)
166 list
->next
= dns_rr_append(list
->next
, rr
);
171 /* dns_rr_compare_pref - compare resource records by preference */
173 int dns_rr_compare_pref(DNS_RR
*a
, DNS_RR
*b
)
175 if (a
->pref
!= b
->pref
)
176 return (a
->pref
- b
->pref
);
178 if (a
->type
== b
->type
) /* 200412 */
180 if (a
->type
== T_AAAA
)
182 if (b
->type
== T_AAAA
)
188 /* dns_rr_sort_callback - glue function */
190 static int (*dns_rr_sort_user
) (DNS_RR
*, DNS_RR
*);
192 static int dns_rr_sort_callback(const void *a
, const void *b
)
194 DNS_RR
*aa
= *(DNS_RR
**) a
;
195 DNS_RR
*bb
= *(DNS_RR
**) b
;
197 return (dns_rr_sort_user(aa
, bb
));
200 /* dns_rr_sort - sort resource record list */
202 DNS_RR
*dns_rr_sort(DNS_RR
*list
, int (*compar
) (DNS_RR
*, DNS_RR
*))
204 int (*saved_user
) (DNS_RR
*, DNS_RR
*);
211 * Save state and initialize.
213 saved_user
= dns_rr_sort_user
;
214 dns_rr_sort_user
= compar
;
217 * Build linear array with pointers to each list element.
219 for (len
= 0, rr
= list
; rr
!= 0; len
++, rr
= rr
->next
)
221 rr_array
= (DNS_RR
**) mymalloc(len
* sizeof(*rr_array
));
222 for (len
= 0, rr
= list
; rr
!= 0; len
++, rr
= rr
->next
)
226 * Sort by user-specified criterion.
228 qsort((char *) rr_array
, len
, sizeof(*rr_array
), dns_rr_sort_callback
);
233 for (i
= 0; i
< len
- 1; i
++)
234 rr_array
[i
]->next
= rr_array
[i
+ 1];
235 rr_array
[i
]->next
= 0;
241 myfree((char *) rr_array
);
242 dns_rr_sort_user
= saved_user
;
246 /* dns_rr_shuffle - shuffle resource record list */
248 DNS_RR
*dns_rr_shuffle(DNS_RR
*list
)
257 * Build linear array with pointers to each list element.
259 for (len
= 0, rr
= list
; rr
!= 0; len
++, rr
= rr
->next
)
261 rr_array
= (DNS_RR
**) mymalloc(len
* sizeof(*rr_array
));
262 for (len
= 0, rr
= list
; rr
!= 0; len
++, rr
= rr
->next
)
266 * Shuffle resource records.
268 for (i
= 0; i
< len
; i
++) {
271 rr_array
[i
] = rr_array
[r
];
278 for (i
= 0; i
< len
- 1; i
++)
279 rr_array
[i
]->next
= rr_array
[i
+ 1];
280 rr_array
[i
]->next
= 0;
286 myfree((char *) rr_array
);
290 /* dns_rr_remove - remove record from list, return new list */
292 DNS_RR
*dns_rr_remove(DNS_RR
*list
, DNS_RR
*record
)
295 msg_panic("dns_rr_remove: record not found");
297 if (list
== record
) {
302 list
->next
= dns_rr_remove(list
->next
, record
);