/* * Copyright (c) 2002-2004 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: dnsres.c,v 1.24 2006/12/28 03:31:40 ca Exp $") #include "sm/ctype.h" #include "sm/dns.h" #include "sm/dns-int.h" /* ** DNS_RESE_NEW -- create a new DNS result entry and fill in data ** ** Parameters: ** rrname -- name of query ** type -- DNS type ** ttl -- TTL ** pref -- preference ** weight -- weight (result of mxrand()) ** reshost -- hostname ** n -- len of reshost ** ipv4 -- IPv4 address ** pdns_rese -- new DNS result entry (output) ** ** Returns: ** usual sm_error code */ sm_ret_T dns_rese_new(const uchar *rrname, size_t l, dns_type_T type, uint ttl, ushort pref, ushort weight, const uchar *reshost, size_t n, ipv4_T ipv4, dns_rese_P *pdns_rese) { dns_rese_P dns_rese; sm_ret_T ret; SM_REQUIRE(pdns_rese != NULL); ret = sm_error_temp(SM_EM_DNS, ENOMEM); dns_rese = (dns_rese_P) sm_zalloc(sizeof(*dns_rese)); if (NULL == dns_rese) return ret; if (rrname != NULL) { dns_rese->dnsrese_name = sm_cstr_scpyn0(rrname, l); if (NULL == dns_rese->dnsrese_name) goto error; } dns_rese->dnsrese_ttl = ttl; dns_rese->dnsrese_type = type; switch (type) { case T_MX: dns_rese->dnsrese_val.dnsresu_name = sm_cstr_scpyn0(reshost, n); if (dns_rese->dnsrese_val.dnsresu_name == NULL) goto error; dns_rese->dnsrese_pref = pref; dns_rese->dnsrese_weight = weight; break; case T_A: dns_rese->dnsrese_val.dnsresu_a = ipv4; break; case T_PTR: dns_rese->dnsrese_val.dnsresu_name = sm_cstr_scpyn0(reshost, n); if (dns_rese->dnsrese_val.dnsresu_name == NULL) goto error; break; case T_CNAME: dns_rese->dnsrese_val.dnsresu_name = sm_cstr_scpyn0(reshost, n); if (dns_rese->dnsrese_val.dnsresu_name == NULL) goto error; break; default: ret = sm_error_perm(SM_EM_DNS, EINVAL); break; } *pdns_rese = dns_rese; return SM_SUCCESS; error: if (dns_rese != NULL) { SM_CSTR_FREE(dns_rese->dnsrese_name); sm_free_size(dns_rese, sizeof(*dns_rese)); } return ret; } /* ** DNS_RESE_FREE -- free a DNS result entry ** ** Parameters: ** dns_rese -- DNS result entry ** ** Returns: ** usual sm_error code */ sm_ret_T dns_rese_free(dns_rese_P dns_rese) { if (NULL == dns_rese) return SM_SUCCESS; SM_CSTR_FREE(dns_rese->dnsrese_name); if (T_MX == dns_rese->dnsrese_type || T_CNAME == dns_rese->dnsrese_type || T_PTR == dns_rese->dnsrese_type) SM_CSTR_FREE(dns_rese->dnsrese_val.dnsresu_name); sm_free_size(dns_rese, sizeof(*dns_rese)); return SM_SUCCESS; } /* ** DNS_RES_NEW -- create a new DNS result structure ** ** Parameters: ** maxentries -- maximum number of DNS result records to add ** pdns_res -- new DNS result struct (output) ** ** Returns: ** usual sm_error code */ sm_ret_T dns_res_new(uint maxentries, dns_res_P *pdns_res) { dns_res_P dns_res; SM_REQUIRE(pdns_res != NULL); /* pdns_res = NULL; */ dns_res = (dns_res_P) sm_zalloc(sizeof(*dns_res)); if (NULL == dns_res) return sm_error_temp(SM_EM_DNS, ENOMEM); DRESL_INIT(dns_res); dns_res->dnsres_maxentries = (maxentries == 0) ? MAXRESHOSTS : maxentries; *pdns_res = dns_res; return SM_SUCCESS; } /* ** DNS_RESL_FREE -- free DNS result list ** ** Parameters: ** dns_res -- DNS result header ** ** Returns: ** usual sm_error code (currently: always SM_SUCCESS) */ sm_ret_T dns_resl_free(dns_res_P dns_res) { dns_rese_P dns_rese, dns_rese_next; if (NULL == dns_res) return SM_SUCCESS; /* free list... */ for (dns_rese = DRESL_FIRST(dns_res); dns_rese != DRESL_END(dns_res); dns_rese = dns_rese_next) { dns_rese_next = DRESL_NEXT(dns_rese); dns_rese_free(dns_rese); } DRESL_INIT(dns_res); return SM_SUCCESS; } /* ** DNS_RES_FREE -- free an entire DNS result struct ** ** Parameters: ** dns_res -- DNS result entry ** ** Returns: ** usual sm_error code (currently: always SM_SUCCESS) */ sm_ret_T dns_res_free(dns_res_P dns_res) { sm_ret_T ret; if (NULL == dns_res) return SM_SUCCESS; ret = dns_resl_free(dns_res); if (sm_is_err(ret)) return ret; sm_free_size(dns_res, sizeof(*dns_res)); return SM_SUCCESS; }