/* srv.c - DNS SRV code
* Copyright (C) 2003 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
*
* GNUPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GNUPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
#undef TEST
#ifdef TEST
#define HAVE_RESOLV_A
#endif
#include
#include
#include
#include
#include
#include
#include "srv.h"
#include
#include
#include
/* Not every installation has gotten around to supporting SRVs
yet...*/
#ifndef T_SRV
#define T_SRV 33
#endif
static int priosort(const void *a, const void *b) {
const struct ns_srv_reply *sa=a, *sb=b;
if (sa->prio>sb->prio)
return 1;
else if (sa->prioprio)
return -1;
else
return 0;
}
struct ns_srv_reply *srv_lookup(char *service, char *protocol, char *domain) {
struct ns_srv_reply *reply = NULL;
struct ns_srv_reply *list;
char name[1024];
#ifdef HAVE_RESOLV_A
unsigned char answer[PACKETSZ];
int r, srvcount=0;
unsigned char *pt, *emsg;
int count, dlen;
list = NULL;
g_snprintf(name, sizeof(name ), "_%s._%s.%s", service, protocol, domain);
_res.options |= RES_DEBUG;
if ( res_init() != 0 )
return NULL;
r=res_query(name, C_IN, T_SRV, answer, PACKETSZ);
if (rPACKETSZ)
return NULL;
if ((((HEADER *)answer)->rcode)==NOERROR && (count=ntohs(((HEADER *)answer)->ancount))) {
int i, rc;
emsg=&answer[r]; /* end of message ??? */
pt=&answer[sizeof(HEADER)];
/* Skip over the query */
rc=dn_skipname(pt, emsg);
if (rc==-1)
goto fail;
pt+=rc+QFIXEDSZ;
while (count-->0 && ptprio=*pt++ << 8;
srv->prio|=*pt++;
srv->weight=*pt++ << 8;
srv->weight|=*pt++;
srv->port=*pt++ << 8;
srv->port|=*pt++;
/* Get the name. 2782 doesn't allow name compression, but
dn_expand still works to pull the name out of the
packet. */
rc=dn_expand(answer, emsg, pt, srv->name, MAXDNAME);
if (rc==1 && srv->name[0]==0) /* "." */
goto noanswer;
if (rc==-1)
goto fail;
pt+=rc;
/* Corrupt packet? */
if (dlen!=rc+6)
goto fail;
}
/* Now we have an array of all the srv records. */
/* Order by priority */
qsort(list, srvcount, sizeof(struct ns_srv_reply), priosort);
/* For each priority, move the zero-weighted items first. */
for (i=0; iprio);
printf("weight=%hu\n", srv->weight);
printf("port=%hu\n", srv->port);
printf("target=%s\n", srv->name);
printf("\n");
g_free(srv);
return 0;
}
#endif /* TEST */