From 81844d2b65e5b5fab28caec29d1ff6c7d680c34a Mon Sep 17 00:00:00 2001 From: David Shaw Date: Tue, 11 Mar 2003 22:04:53 +0000 Subject: * http.c (connect_server): Use DNS SRV to get a server list. Fail over to A records if necessary. * Makefile.am, srv.h, srv.c: New DNS SRV handling code. --- util/srv.c | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 util/srv.c (limited to 'util/srv.c') diff --git a/util/srv.c b/util/srv.c new file mode 100644 index 000000000..8fc0ca0de --- /dev/null +++ b/util/srv.c @@ -0,0 +1,246 @@ +/* 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#ifdef USE_DNS_SRV +#include +#include +#include +#include +#include +#include +#include +#include +#include "memory.h" +#include "types.h" +#include "srv.h" + +#ifndef T_SRV +#define T_SRV 33 +#endif + +static int priosort(const void *a,const void *b) +{ + const struct srventry *sa=a,*sb=b; + if(sa->priority>sb->priority) + return 1; + else if(sa->prioritypriority) + return -1; + else + return 0; +} + +int +getsrv(const char *name,struct srventry **list) +{ + char answer[PACKETSZ]; + int r,srvcount=0; + char *pt,*emsg; + u16 count,dlen; + + *list=NULL; + + r=res_query(name,C_IN,T_SRV,answer,PACKETSZ); + if(rrcode)==NOERROR && + (count=ntohs(((HEADER *)answer)->ancount))) + { + int i,rc; + + emsg=&answer[r]; + pt=&answer[sizeof(HEADER)]; + + /* Skip over the query */ + + rc=dn_skipname(pt,emsg); + if(rc==-1) + goto fail; + + pt+=rc+QFIXEDSZ; + + while(count-->0 && ptpriority=*pt++ << 8; + srv->priority|=*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->target,MAXDNAME); + if(rc==1 && srv->target[0]==0) /* "." */ + goto noanswer; + if(rc==-1) + goto fail; + pt+=rc; + /* Corrupt packet? */ + if(dlen!=rc+6) + goto fail; + +#if 0 + printf("count=%d\n",srvcount); + printf("priority=%d\n",srv->priority); + printf("weight=%d\n",srv->weight); + printf("port=%d\n",srv->port); + printf("target=%s\n",srv->target); +#endif + } + + /* Now we have an array of all the srv records. */ + + /* Order by priority */ + qsort(*list,srvcount,sizeof(struct srventry),priosort); + + /* For each priority, move the zero-weighted items first. */ + for(i=0;i