~ubuntu-branches/ubuntu/karmic/gnupg2/karmic-updates

« back to all changes in this revision

Viewing changes to common/srv.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* srv.c - DNS SRV code
 
2
 * Copyright (C) 2003 Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of GNUPG.
 
5
 *
 
6
 * GNUPG is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 3 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * GNUPG is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <config.h>
 
21
#include <sys/types.h>
 
22
#ifdef _WIN32
 
23
#include <windows.h>
 
24
#else
 
25
#include <netinet/in.h>
 
26
#include <arpa/nameser.h>
 
27
#include <resolv.h>
 
28
#endif
 
29
#include <unistd.h>
 
30
#include <stdlib.h>
 
31
#include <string.h>
 
32
#include <time.h>
 
33
 
 
34
#include "util.h"
 
35
#include "srv.h"
 
36
 
 
37
/* Not every installation has gotten around to supporting SRVs
 
38
   yet... */
 
39
#ifndef T_SRV
 
40
#define T_SRV 33
 
41
#endif
 
42
 
 
43
static int
 
44
priosort(const void *a,const void *b)
 
45
{
 
46
  const struct srventry *sa=a,*sb=b;
 
47
  if(sa->priority>sb->priority)
 
48
    return 1;
 
49
  else if(sa->priority<sb->priority)
 
50
    return -1;
 
51
  else
 
52
    return 0;
 
53
}
 
54
 
 
55
int
 
56
getsrv(const char *name,struct srventry **list)
 
57
{
 
58
  unsigned char answer[PACKETSZ];
 
59
  int r,srvcount=0;
 
60
  unsigned char *pt,*emsg;
 
61
  u16 count,dlen;
 
62
 
 
63
  *list=NULL;
 
64
 
 
65
  r=res_query(name,C_IN,T_SRV,answer,PACKETSZ);
 
66
  if(r<sizeof(HEADER) || r>PACKETSZ)
 
67
    return -1;
 
68
 
 
69
  if((((HEADER *)answer)->rcode)==NOERROR &&
 
70
     (count=ntohs(((HEADER *)answer)->ancount)))
 
71
    {
 
72
      int i,rc;
 
73
 
 
74
      emsg=&answer[r];
 
75
      pt=&answer[sizeof(HEADER)];
 
76
 
 
77
      /* Skip over the query */
 
78
 
 
79
      rc=dn_skipname(pt,emsg);
 
80
      if(rc==-1)
 
81
        goto fail;
 
82
 
 
83
      pt+=rc+QFIXEDSZ;
 
84
 
 
85
      while(count-->0 && pt<emsg)
 
86
        {
 
87
          struct srventry *srv=NULL;
 
88
          u16 type,class;
 
89
 
 
90
          *list=xrealloc(*list,(srvcount+1)*sizeof(struct srventry));
 
91
          memset(&(*list)[srvcount],0,sizeof(struct srventry));
 
92
          srv=&(*list)[srvcount];
 
93
          srvcount++;
 
94
 
 
95
          rc=dn_skipname(pt,emsg); /* the name we just queried for */
 
96
          if(rc==-1)
 
97
            goto fail;
 
98
          pt+=rc;
 
99
 
 
100
          /* Truncated message? */
 
101
          if((emsg-pt)<16)
 
102
            goto fail;
 
103
 
 
104
          type=*pt++ << 8;
 
105
          type|=*pt++;
 
106
          /* We asked for SRV and got something else !? */
 
107
          if(type!=T_SRV)
 
108
            goto fail;
 
109
 
 
110
          class=*pt++ << 8;
 
111
          class|=*pt++;
 
112
          /* We asked for IN and got something else !? */
 
113
          if(class!=C_IN)
 
114
            goto fail;
 
115
 
 
116
          pt+=4; /* ttl */
 
117
          dlen=*pt++ << 8;
 
118
          dlen|=*pt++;
 
119
          srv->priority=*pt++ << 8;
 
120
          srv->priority|=*pt++;
 
121
          srv->weight=*pt++ << 8;
 
122
          srv->weight|=*pt++;
 
123
          srv->port=*pt++ << 8;
 
124
          srv->port|=*pt++;
 
125
 
 
126
          /* Get the name.  2782 doesn't allow name compression, but
 
127
             dn_expand still works to pull the name out of the
 
128
             packet. */
 
129
          rc=dn_expand(answer,emsg,pt,srv->target,MAXDNAME);
 
130
          if(rc==1 && srv->target[0]==0) /* "." */
 
131
            goto noanswer;
 
132
          if(rc==-1)
 
133
            goto fail;
 
134
          pt+=rc;
 
135
          /* Corrupt packet? */
 
136
          if(dlen!=rc+6)
 
137
            goto fail;
 
138
 
 
139
#if 0
 
140
          printf("count=%d\n",srvcount);
 
141
          printf("priority=%d\n",srv->priority);
 
142
          printf("weight=%d\n",srv->weight);
 
143
          printf("port=%d\n",srv->port);
 
144
          printf("target=%s\n",srv->target);
 
145
#endif
 
146
        }
 
147
 
 
148
      /* Now we have an array of all the srv records. */
 
149
 
 
150
      /* Order by priority */
 
151
      qsort(*list,srvcount,sizeof(struct srventry),priosort);
 
152
 
 
153
      /* For each priority, move the zero-weighted items first. */
 
154
      for(i=0;i<srvcount;i++)
 
155
        {
 
156
          int j;
 
157
 
 
158
          for(j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
 
159
            {
 
160
              if((*list)[j].weight==0)
 
161
                {
 
162
                  /* Swap j with i */
 
163
                  if(j!=i)
 
164
                    {
 
165
                      struct srventry temp;
 
166
 
 
167
                      memcpy(&temp,&(*list)[j],sizeof(struct srventry));
 
168
                      memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
 
169
                      memcpy(&(*list)[i],&temp,sizeof(struct srventry));
 
170
                    }
 
171
 
 
172
                  break;
 
173
                }
 
174
            }
 
175
        }
 
176
 
 
177
      /* Run the RFC-2782 weighting algorithm.  We don't need very
 
178
         high quality randomness for this, so regular libc srand/rand
 
179
         is sufficient. */
 
180
      srand(time(NULL)*getpid());
 
181
 
 
182
      for(i=0;i<srvcount;i++)
 
183
        {
 
184
          int j;
 
185
          float prio_count=0,chose;
 
186
 
 
187
          for(j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
 
188
            {
 
189
              prio_count+=(*list)[j].weight;
 
190
              (*list)[j].run_count=prio_count;
 
191
            }
 
192
 
 
193
          chose=prio_count*rand()/RAND_MAX;
 
194
 
 
195
          for(j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
 
196
            {
 
197
              if(chose<=(*list)[j].run_count)
 
198
                {
 
199
                  /* Swap j with i */
 
200
                  if(j!=i)
 
201
                    {
 
202
                      struct srventry temp;
 
203
 
 
204
                      memcpy(&temp,&(*list)[j],sizeof(struct srventry));
 
205
                      memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
 
206
                      memcpy(&(*list)[i],&temp,sizeof(struct srventry));
 
207
                    }
 
208
                  break;
 
209
                }
 
210
            }
 
211
        }
 
212
    }
 
213
  
 
214
  return srvcount;
 
215
 
 
216
 noanswer:
 
217
  xfree(*list);
 
218
  *list=NULL;
 
219
  return 0;
 
220
 
 
221
 fail:
 
222
  xfree(*list);
 
223
  *list=NULL;
 
224
  return -1;
 
225
}
 
226
 
 
227
#ifdef TEST
 
228
int
 
229
main(int argc,char *argv[])
 
230
{
 
231
  struct srventry *srv;
 
232
  int rc,i;
 
233
 
 
234
  rc=getsrv("_hkp._tcp.wwwkeys.pgp.net",&srv);
 
235
  printf("Count=%d\n\n",rc);
 
236
  for(i=0;i<rc;i++)
 
237
    {
 
238
      printf("priority=%hu\n",srv[i].priority);
 
239
      printf("weight=%hu\n",srv[i].weight);
 
240
      printf("port=%hu\n",srv[i].port);
 
241
      printf("target=%s\n",srv[i].target);
 
242
      printf("\n");
 
243
    }
 
244
 
 
245
  xfree(srv);
 
246
 
 
247
  return 0;
 
248
}
 
249
#endif /* TEST */
 
250
 
 
251
/*
 
252
Local Variables:
 
253
compile-command: "cc -DTEST -I.. -I../include -Wall -g -o srv srv.c -lresolv libutil.a"
 
254
End:
 
255
*/