/* 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 */