mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 01:26:58 +00:00
FS-3110 --comment-only phase 1 to replace udns with ldns in mod_enum may need to rerun bootstrap
This commit is contained in:
310
libs/ldns/examples/ldns-update.c
Normal file
310
libs/ldns/examples/ldns-update.c
Normal file
@@ -0,0 +1,310 @@
|
||||
/* $Id: ldns-update.c,v 1.1 2005/09/13 09:37:05 ho Exp $ */
|
||||
/*
|
||||
* Example of the update functionality
|
||||
*
|
||||
* See the file LICENSE for the license
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <strings.h>
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
/* dynamic update stuff */
|
||||
static ldns_resolver *
|
||||
ldns_update_resolver_new(const char *fqdn, const char *zone,
|
||||
ldns_rr_class class, uint16_t port, ldns_tsig_credentials *tsig_cred, ldns_rdf **zone_rdf)
|
||||
{
|
||||
ldns_resolver *r1, *r2;
|
||||
ldns_pkt *query = NULL, *resp;
|
||||
ldns_rr_list *nslist, *iplist;
|
||||
ldns_rdf *soa_zone, *soa_mname, *ns_name;
|
||||
size_t i;
|
||||
ldns_status s;
|
||||
|
||||
if (class == 0) {
|
||||
class = LDNS_RR_CLASS_IN;
|
||||
}
|
||||
|
||||
if (port == 0) {
|
||||
port = LDNS_PORT;
|
||||
}
|
||||
|
||||
/* First, get data from /etc/resolv.conf */
|
||||
s = ldns_resolver_new_frm_file(&r1, NULL);
|
||||
if (s != LDNS_STATUS_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r2 = ldns_resolver_new();
|
||||
if (!r2) {
|
||||
goto bad;
|
||||
}
|
||||
ldns_resolver_set_port(r2, port);
|
||||
|
||||
/* TSIG key data available? Copy into the resolver. */
|
||||
if (tsig_cred) {
|
||||
ldns_resolver_set_tsig_algorithm(r2, ldns_tsig_algorithm(tsig_cred));
|
||||
ldns_resolver_set_tsig_keyname(r2, ldns_tsig_keyname(tsig_cred));
|
||||
ldns_resolver_set_tsig_keydata(r2, ldns_tsig_keydata(tsig_cred));
|
||||
}
|
||||
|
||||
/* Now get SOA zone, mname, NS, and construct r2. [RFC2136 4.3] */
|
||||
|
||||
/* Explicit 'zone' or no? */
|
||||
if (zone) {
|
||||
soa_zone = ldns_dname_new_frm_str(zone);
|
||||
if (ldns_update_soa_mname(soa_zone, r1, class, &soa_mname)
|
||||
!= LDNS_STATUS_OK) {
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
if (ldns_update_soa_zone_mname(fqdn, r1, class, &soa_zone,
|
||||
&soa_mname) != LDNS_STATUS_OK) {
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass zone_rdf on upwards. */
|
||||
*zone_rdf = ldns_rdf_clone(soa_zone);
|
||||
|
||||
/* NS */
|
||||
query = ldns_pkt_query_new(soa_zone, LDNS_RR_TYPE_NS, class, LDNS_RD);
|
||||
if (!query) {
|
||||
goto bad;
|
||||
}
|
||||
soa_zone = NULL;
|
||||
|
||||
ldns_pkt_set_random_id(query);
|
||||
|
||||
if (ldns_resolver_send_pkt(&resp, r1, query) != LDNS_STATUS_OK) {
|
||||
dprintf("%s", "NS query failed!\n");
|
||||
goto bad;
|
||||
}
|
||||
ldns_pkt_free(query);
|
||||
if (!resp) {
|
||||
goto bad;
|
||||
}
|
||||
/* Match SOA MNAME to NS list, adding it first */
|
||||
nslist = ldns_pkt_answer(resp);
|
||||
for (i = 0; i < ldns_rr_list_rr_count(nslist); i++) {
|
||||
ns_name = ldns_rr_rdf(ldns_rr_list_rr(nslist, i), 0);
|
||||
if (!ns_name)
|
||||
continue;
|
||||
if (ldns_rdf_compare(soa_mname, ns_name) == 0) {
|
||||
/* Match */
|
||||
iplist = ldns_get_rr_list_addr_by_name(r1, ns_name, class, 0);
|
||||
(void) ldns_resolver_push_nameserver_rr_list(r2, iplist);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then all the other NSs. XXX Randomize? */
|
||||
for (i = 0; i < ldns_rr_list_rr_count(nslist); i++) {
|
||||
ns_name = ldns_rr_rdf(ldns_rr_list_rr(nslist, i), 0);
|
||||
if (!ns_name)
|
||||
continue;
|
||||
if (ldns_rdf_compare(soa_mname, ns_name) != 0) {
|
||||
/* No match, add it now. */
|
||||
iplist = ldns_get_rr_list_addr_by_name(r1, ns_name, class, 0);
|
||||
(void) ldns_resolver_push_nameserver_rr_list(r2, iplist);
|
||||
}
|
||||
}
|
||||
|
||||
ldns_resolver_set_random(r2, false);
|
||||
ldns_pkt_free(resp);
|
||||
ldns_resolver_deep_free(r1);
|
||||
return r2;
|
||||
|
||||
bad:
|
||||
if (r1)
|
||||
ldns_resolver_deep_free(r1);
|
||||
if (r2)
|
||||
ldns_resolver_deep_free(r2);
|
||||
if (query)
|
||||
ldns_pkt_free(query);
|
||||
if (resp)
|
||||
ldns_pkt_free(resp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static ldns_status
|
||||
ldns_update_send_simple_addr(const char *fqdn, const char *zone,
|
||||
const char *ipaddr, uint16_t p, uint32_t ttl, ldns_tsig_credentials *tsig_cred)
|
||||
{
|
||||
ldns_resolver *res;
|
||||
ldns_pkt *u_pkt = NULL, *r_pkt;
|
||||
ldns_rr_list *up_rrlist;
|
||||
ldns_rr *up_rr;
|
||||
ldns_rdf *zone_rdf;
|
||||
char *rrstr;
|
||||
uint32_t rrstrlen, status = LDNS_STATUS_OK;
|
||||
|
||||
if (!fqdn || strlen(fqdn) == 0)
|
||||
return LDNS_STATUS_ERR;
|
||||
|
||||
/* Create resolver */
|
||||
res = ldns_update_resolver_new(fqdn, zone, 0, p, tsig_cred, &zone_rdf);
|
||||
if (!res || !zone_rdf) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Set up the update section. */
|
||||
up_rrlist = ldns_rr_list_new();
|
||||
if (!up_rrlist) {
|
||||
goto cleanup;
|
||||
}
|
||||
/* Create input for ldns_rr_new_frm_str() */
|
||||
if (ipaddr) {
|
||||
/* We're adding A or AAAA */
|
||||
rrstrlen = strlen(fqdn) + sizeof (" IN AAAA ") + strlen(ipaddr) + 1;
|
||||
rrstr = (char *)malloc(rrstrlen);
|
||||
if (!rrstr) {
|
||||
ldns_rr_list_deep_free(up_rrlist);
|
||||
goto cleanup;
|
||||
}
|
||||
snprintf(rrstr, rrstrlen, "%s IN %s %s", fqdn,
|
||||
strchr(ipaddr, ':') ? "AAAA" : "A", ipaddr);
|
||||
|
||||
if (ldns_rr_new_frm_str(&up_rr, rrstr, ttl, NULL, NULL) !=
|
||||
LDNS_STATUS_OK) {
|
||||
ldns_rr_list_deep_free(up_rrlist);
|
||||
free(rrstr);
|
||||
goto cleanup;
|
||||
}
|
||||
free(rrstr);
|
||||
ldns_rr_list_push_rr(up_rrlist, up_rr);
|
||||
} else {
|
||||
/* We're removing A and/or AAAA from 'fqdn'. [RFC2136 2.5.2] */
|
||||
up_rr = ldns_rr_new();
|
||||
ldns_rr_set_owner(up_rr, ldns_dname_new_frm_str(fqdn));
|
||||
ldns_rr_set_ttl(up_rr, 0);
|
||||
ldns_rr_set_class(up_rr, LDNS_RR_CLASS_ANY);
|
||||
|
||||
ldns_rr_set_type(up_rr, LDNS_RR_TYPE_A);
|
||||
ldns_rr_list_push_rr(up_rrlist, ldns_rr_clone(up_rr));
|
||||
|
||||
ldns_rr_set_type(up_rr, LDNS_RR_TYPE_AAAA);
|
||||
ldns_rr_list_push_rr(up_rrlist, up_rr);
|
||||
}
|
||||
|
||||
/* Create update packet. */
|
||||
u_pkt = ldns_update_pkt_new(zone_rdf, LDNS_RR_CLASS_IN, NULL, up_rrlist, NULL);
|
||||
zone_rdf = NULL;
|
||||
if (!u_pkt) {
|
||||
ldns_rr_list_deep_free(up_rrlist);
|
||||
goto cleanup;
|
||||
}
|
||||
ldns_pkt_set_random_id(u_pkt);
|
||||
|
||||
/* Add TSIG */
|
||||
if (tsig_cred)
|
||||
if (ldns_update_pkt_tsig_add(u_pkt, res) != LDNS_STATUS_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ldns_resolver_send_pkt(&r_pkt, res, u_pkt) != LDNS_STATUS_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
ldns_pkt_free(u_pkt);
|
||||
if (!r_pkt) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (ldns_pkt_get_rcode(r_pkt) != LDNS_RCODE_NOERROR) {
|
||||
ldns_lookup_table *t = ldns_lookup_by_id(ldns_rcodes,
|
||||
(int)ldns_pkt_get_rcode(r_pkt));
|
||||
if (t) {
|
||||
dprintf(";; UPDATE response was %s\n", t->name);
|
||||
} else {
|
||||
dprintf(";; UPDATE response was (%d)\n", ldns_pkt_get_rcode(r_pkt));
|
||||
}
|
||||
status = LDNS_STATUS_ERR;
|
||||
}
|
||||
ldns_pkt_free(r_pkt);
|
||||
ldns_resolver_deep_free(res);
|
||||
return status;
|
||||
|
||||
cleanup:
|
||||
if (res)
|
||||
ldns_resolver_deep_free(res);
|
||||
if (u_pkt)
|
||||
ldns_pkt_free(u_pkt);
|
||||
return LDNS_STATUS_ERR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(FILE *fp, char *prog)
|
||||
{
|
||||
fprintf(fp, "%s domain [zone] ip tsig_name tsig_alg tsig_hmac\n", prog);
|
||||
fprintf(fp, " send a dynamic update packet to <ip>\n\n");
|
||||
fprintf(fp, " Use 'none' instead of ip to remove any previous address\n");
|
||||
fprintf(fp, " If 'zone' is not specified, try to figure it out from the zone's SOA\n");
|
||||
fprintf(fp, " Example: %s my.example.org 1.2.3.4\n", prog);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *fqdn, *ipaddr, *zone, *prog;
|
||||
ldns_status ret;
|
||||
ldns_tsig_credentials tsig_cr, *tsig_cred;
|
||||
int c = 2;
|
||||
uint32_t defttl = 300;
|
||||
uint32_t port = 5353;
|
||||
|
||||
prog = strdup(argv[0]);
|
||||
|
||||
switch (argc) {
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
break;
|
||||
default:
|
||||
usage(stderr, prog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fqdn = argv[1];
|
||||
c = 2;
|
||||
if (argc == 4 || argc == 7) {
|
||||
zone = argv[c++];
|
||||
} else {
|
||||
zone = NULL;
|
||||
}
|
||||
|
||||
if (strcmp(argv[c], "none") == 0) {
|
||||
ipaddr = NULL;
|
||||
} else {
|
||||
ipaddr = argv[c];
|
||||
}
|
||||
c++;
|
||||
if (argc == 6 || argc == 7) {
|
||||
tsig_cr.keyname = argv[c++];
|
||||
if (strncasecmp(argv[c], "hmac-sha1", 9) == 0) {
|
||||
tsig_cr.algorithm = (char*)"hmac-sha1.";
|
||||
} else if (strncasecmp(argv[c], "hmac-md5", 8) == 0) {
|
||||
tsig_cr.algorithm = (char*)"hmac-md5.sig-alg.reg.int.";
|
||||
} else {
|
||||
fprintf(stderr, "Unknown algorithm, try \"hmac-md5\" "
|
||||
"or \"hmac-sha1\".\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
tsig_cr.keydata = argv[++c];
|
||||
tsig_cred = &tsig_cr;
|
||||
} else {
|
||||
tsig_cred = NULL;
|
||||
}
|
||||
|
||||
printf(";; trying UPDATE with FQDN \"%s\" and IP \"%s\"\n",
|
||||
fqdn, ipaddr ? ipaddr : "<none>");
|
||||
printf(";; tsig: \"%s\" \"%s\" \"%s\"\n", tsig_cr.keyname,
|
||||
tsig_cr.algorithm, tsig_cr.keydata);
|
||||
|
||||
ret = ldns_update_send_simple_addr(fqdn, zone, ipaddr, port, defttl, tsig_cred);
|
||||
exit(ret);
|
||||
}
|
Reference in New Issue
Block a user