~scarneiro/ubuntu/raring/adns/fix-for-ignored-make-clean-errors

« back to all changes in this revision

Viewing changes to src/types.c

  • Committer: Bazaar Package Importer
  • Author(s): Bernd Eckenfels
  • Date: 2001-06-29 06:30:29 UTC
  • Revision ID: james.westby@ubuntu.com-20010629063029-jp10glkp51lsmamb
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * types.c
 
3
 * - RR-type-specific code, and the machinery to call it
 
4
 */
 
5
/*
 
6
 *  This file is
 
7
 *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
 
8
 *
 
9
 *  It is part of adns, which is
 
10
 *    Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
 
11
 *    Copyright (C) 1999-2000 Tony Finch <dot@dotat.at>
 
12
 *  
 
13
 *  This program is free software; you can redistribute it and/or modify
 
14
 *  it under the terms of the GNU General Public License as published by
 
15
 *  the Free Software Foundation; either version 2, or (at your option)
 
16
 *  any later version.
 
17
 *  
 
18
 *  This program is distributed in the hope that it will be useful,
 
19
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
 *  GNU General Public License for more details.
 
22
 *  
 
23
 *  You should have received a copy of the GNU General Public License
 
24
 *  along with this program; if not, write to the Free Software Foundation,
 
25
 *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 
26
 */
 
27
 
 
28
#include <stdlib.h>
 
29
 
 
30
#include <sys/types.h>
 
31
#include <sys/socket.h>
 
32
#include <netinet/in.h>
 
33
#include <arpa/inet.h>
 
34
 
 
35
#include "internal.h"
 
36
 
 
37
#define R_NOMEM           return adns_s_nomemory
 
38
#define CSP_ADDSTR(s)     do { if (!adns__vbuf_appendstr(vb,(s))) R_NOMEM; } while (0)
 
39
 
 
40
/*
 
41
 * order of sections:
 
42
 *
 
43
 * _string                    (pap)
 
44
 * _textdata, _qstring        (csp)
 
45
 * _str                       (mf,cs)
 
46
 * _intstr                    (mf,csp,cs)
 
47
 * _manyistr                  (mf,cs)
 
48
 * _txt                       (pa)
 
49
 * _inaddr                    (pa,dip,di)
 
50
 * _addr                      (pa,di,csp,cs)
 
51
 * _domain                    (pap)
 
52
 * _host_raw                  (pa)
 
53
 * _hostaddr                  (pap,pa,dip,di,mfp,mf,csp,cs +pap_findaddrs)
 
54
 * _mx_raw                    (pa,di)
 
55
 * _mx                        (pa,di)
 
56
 * _inthostaddr               (mf,cs)
 
57
 * _ptr                       (pa)
 
58
 * _strpair                   (mf,cs)
 
59
 * _intstrpair                (mf,cs)
 
60
 * _hinfo                     (pa)
 
61
 * _mailbox                   (pap +pap_mailbox822)
 
62
 * _rp                        (pa)
 
63
 * _soa                       (pa,mf,cs)
 
64
 * _flat                      (mf)
 
65
 *
 
66
 * within each section:
 
67
 *    pap_*
 
68
 *    pa_*
 
69
 *    dip_*
 
70
 *    di_*
 
71
 *    mfp_*
 
72
 *    mf_*
 
73
 *    csp_*
 
74
 *    cs_*
 
75
 */
 
76
 
 
77
/*
 
78
 * _qstring               (pap,csp)
 
79
 */
 
80
 
 
81
static adns_status pap_qstring(const parseinfo *pai, int *cbyte_io, int max,
 
82
                              int *len_r, char **str_r) {
 
83
  /* Neither len_r nor str_r may be null.
 
84
   * End of datagram (overrun) is indicated by returning adns_s_invaliddata;
 
85
   */
 
86
  const byte *dgram= pai->dgram;
 
87
  int l, cbyte;
 
88
  char *str;
 
89
 
 
90
  cbyte= *cbyte_io;
 
91
 
 
92
  if (cbyte >= max) return adns_s_invaliddata;
 
93
  GET_B(cbyte,l);
 
94
  if (cbyte+l > max) return adns_s_invaliddata;
 
95
  
 
96
  str= adns__alloc_interim(pai->qu, l+1);
 
97
  if (!str) R_NOMEM;
 
98
  
 
99
  str[l]= 0;
 
100
  memcpy(str,dgram+cbyte,l);
 
101
 
 
102
  *len_r= l;
 
103
  *str_r= str;
 
104
  *cbyte_io= cbyte+l;
 
105
  
 
106
  return adns_s_ok;
 
107
}
 
108
 
 
109
static adns_status csp_qstring(vbuf *vb, const char *dp, int len) {
 
110
  unsigned char ch;
 
111
  char buf[10];
 
112
  int cn;
 
113
 
 
114
  CSP_ADDSTR("\"");
 
115
  for (cn=0; cn<len; cn++) {
 
116
    ch= *dp++;
 
117
    if (ch == '\\') {
 
118
      CSP_ADDSTR("\\\\");
 
119
    } else if (ch == '"') {
 
120
      CSP_ADDSTR("\\\"");
 
121
    } else if (ch >= 32 && ch <= 126) {
 
122
      if (!adns__vbuf_append(vb,&ch,1)) R_NOMEM;
 
123
    } else {
 
124
      sprintf(buf,"\\x%02x",ch);
 
125
      CSP_ADDSTR(buf);
 
126
    }
 
127
  }
 
128
  CSP_ADDSTR("\"");
 
129
  
 
130
  return adns_s_ok;
 
131
}
 
132
 
 
133
/*
 
134
 * _str  (mf)
 
135
 */
 
136
 
 
137
static void mf_str(adns_query qu, void *datap) {
 
138
  char **rrp= datap;
 
139
 
 
140
  adns__makefinal_str(qu,rrp);
 
141
}
 
142
 
 
143
/*
 
144
 * _intstr  (mf)
 
145
 */
 
146
 
 
147
static void mf_intstr(adns_query qu, void *datap) {
 
148
  adns_rr_intstr *rrp= datap;
 
149
 
 
150
  adns__makefinal_str(qu,&rrp->str);
 
151
}
 
152
 
 
153
/*
 
154
 * _manyistr   (mf)
 
155
 */
 
156
 
 
157
static void mf_manyistr(adns_query qu, void *datap) {
 
158
  adns_rr_intstr **rrp= datap;
 
159
  adns_rr_intstr *te, *table;
 
160
  void *tablev;
 
161
  int tc;
 
162
 
 
163
  for (tc=0, te= *rrp; te->i >= 0; te++, tc++);
 
164
  tablev= *rrp;
 
165
  adns__makefinal_block(qu,&tablev,sizeof(*te)*(tc+1));
 
166
  *rrp= table= tablev;
 
167
  for (te= *rrp; te->i >= 0; te++)
 
168
    adns__makefinal_str(qu,&te->str);
 
169
}
 
170
 
 
171
/*
 
172
 * _txt   (pa,cs)
 
173
 */
 
174
 
 
175
static adns_status pa_txt(const parseinfo *pai, int cbyte, int max, void *datap) {
 
176
  adns_rr_intstr **rrp= datap, *table, *te;
 
177
  const byte *dgram= pai->dgram;
 
178
  int ti, tc, l, startbyte;
 
179
  adns_status st;
 
180
 
 
181
  startbyte= cbyte;
 
182
  if (cbyte >= max) return adns_s_invaliddata;
 
183
  tc= 0;
 
184
  while (cbyte < max) {
 
185
    GET_B(cbyte,l);
 
186
    cbyte+= l;
 
187
    tc++;
 
188
  }
 
189
  if (cbyte != max || !tc) return adns_s_invaliddata;
 
190
 
 
191
  table= adns__alloc_interim(pai->qu,sizeof(*table)*(tc+1));
 
192
  if (!table) R_NOMEM;
 
193
 
 
194
  for (cbyte=startbyte, ti=0, te=table; ti<tc; ti++, te++) {
 
195
    st= pap_qstring(pai, &cbyte, max, &te->i, &te->str);
 
196
    if (st) return st;
 
197
  }
 
198
  assert(cbyte == max);
 
199
 
 
200
  te->i= -1;
 
201
  te->str= 0;
 
202
  
 
203
  *rrp= table;
 
204
  return adns_s_ok;
 
205
}
 
206
 
 
207
static adns_status cs_txt(vbuf *vb, const void *datap) {
 
208
  const adns_rr_intstr *const *rrp= datap;
 
209
  const adns_rr_intstr *current;
 
210
  adns_status st;
 
211
  int spc;
 
212
 
 
213
  for (current= *rrp, spc=0;  current->i >= 0;  current++, spc=1) {
 
214
    if (spc) CSP_ADDSTR(" ");
 
215
    st= csp_qstring(vb,current->str,current->i); if (st) return st;
 
216
  }
 
217
  return adns_s_ok;
 
218
}
 
219
 
 
220
/*
 
221
 * _hinfo   (cs)
 
222
 */
 
223
 
 
224
static adns_status cs_hinfo(vbuf *vb, const void *datap) {
 
225
  const adns_rr_intstrpair *rrp= datap;
 
226
  adns_status st;
 
227
 
 
228
  st= csp_qstring(vb,rrp->array[0].str,rrp->array[0].i);  if (st) return st;
 
229
  CSP_ADDSTR(" ");
 
230
  st= csp_qstring(vb,rrp->array[1].str,rrp->array[1].i);  if (st) return st;
 
231
  return adns_s_ok;
 
232
}
 
233
 
 
234
/*
 
235
 * _inaddr   (pa,dip,di)
 
236
 */
 
237
 
 
238
static adns_status pa_inaddr(const parseinfo *pai, int cbyte, int max, void *datap) {
 
239
  struct in_addr *storeto= datap;
 
240
  
 
241
  if (max-cbyte != 4) return adns_s_invaliddata;
 
242
  memcpy(storeto, pai->dgram + cbyte, 4);
 
243
  return adns_s_ok;
 
244
}
 
245
 
 
246
static int search_sortlist(adns_state ads, struct in_addr ad) {
 
247
  const struct sortlist *slp;
 
248
  int i;
 
249
  
 
250
  for (i=0, slp=ads->sortlist;
 
251
       i<ads->nsortlist && !((ad.s_addr & slp->mask.s_addr) == slp->base.s_addr);
 
252
       i++, slp++);
 
253
  return i;
 
254
}
 
255
 
 
256
static int dip_inaddr(adns_state ads, struct in_addr a, struct in_addr b) {
 
257
  int ai, bi;
 
258
  
 
259
  if (!ads->nsortlist) return 0;
 
260
 
 
261
  ai= search_sortlist(ads,a);
 
262
  bi= search_sortlist(ads,b);
 
263
  return bi<ai;
 
264
}
 
265
 
 
266
static int di_inaddr(adns_state ads, const void *datap_a, const void *datap_b) {
 
267
  const struct in_addr *ap= datap_a, *bp= datap_b;
 
268
 
 
269
  return dip_inaddr(ads,*ap,*bp);
 
270
}
 
271
 
 
272
static adns_status cs_inaddr(vbuf *vb, const void *datap) {
 
273
  const struct in_addr *rrp= datap, rr= *rrp;
 
274
  const char *ia;
 
275
 
 
276
  ia= inet_ntoa(rr); assert(ia);
 
277
  CSP_ADDSTR(ia);
 
278
  return adns_s_ok;
 
279
}
 
280
 
 
281
/*
 
282
 * _addr   (pa,di,csp,cs)
 
283
 */
 
284
 
 
285
static adns_status pa_addr(const parseinfo *pai, int cbyte, int max, void *datap) {
 
286
  adns_rr_addr *storeto= datap;
 
287
  const byte *dgram= pai->dgram;
 
288
 
 
289
  if (max-cbyte != 4) return adns_s_invaliddata;
 
290
  storeto->len= sizeof(storeto->addr.inet);
 
291
  memset(&storeto->addr,0,sizeof(storeto->addr.inet));
 
292
  storeto->addr.inet.sin_family= AF_INET;
 
293
  memcpy(&storeto->addr.inet.sin_addr,dgram+cbyte,4);
 
294
  return adns_s_ok;
 
295
}
 
296
 
 
297
static int di_addr(adns_state ads, const void *datap_a, const void *datap_b) {
 
298
  const adns_rr_addr *ap= datap_a, *bp= datap_b;
 
299
 
 
300
  assert(ap->addr.sa.sa_family == AF_INET);
 
301
  return dip_inaddr(ads, ap->addr.inet.sin_addr, bp->addr.inet.sin_addr);
 
302
}
 
303
 
 
304
static int div_addr(void *context, const void *datap_a, const void *datap_b) {
 
305
  const adns_state ads= context;
 
306
 
 
307
  return di_addr(ads, datap_a, datap_b);
 
308
}                    
 
309
 
 
310
static adns_status csp_addr(vbuf *vb, const adns_rr_addr *rrp) {
 
311
  const char *ia;
 
312
  static char buf[30];
 
313
 
 
314
  switch (rrp->addr.inet.sin_family) {
 
315
  case AF_INET:
 
316
    CSP_ADDSTR("INET ");
 
317
    ia= inet_ntoa(rrp->addr.inet.sin_addr); assert(ia);
 
318
    CSP_ADDSTR(ia);
 
319
    break;
 
320
  default:
 
321
    sprintf(buf,"AF=%u",rrp->addr.sa.sa_family);
 
322
    CSP_ADDSTR(buf);
 
323
    break;
 
324
  }
 
325
  return adns_s_ok;
 
326
}
 
327
 
 
328
static adns_status cs_addr(vbuf *vb, const void *datap) {
 
329
  const adns_rr_addr *rrp= datap;
 
330
 
 
331
  return csp_addr(vb,rrp);
 
332
}
 
333
 
 
334
/*
 
335
 * _domain      (pap,csp,cs)
 
336
 * _dom_raw     (pa)
 
337
 */
 
338
 
 
339
static adns_status pap_domain(const parseinfo *pai, int *cbyte_io, int max,
 
340
                              char **domain_r, parsedomain_flags flags) {
 
341
  adns_status st;
 
342
  char *dm;
 
343
  
 
344
  st= adns__parse_domain(pai->qu->ads, pai->serv, pai->qu, &pai->qu->vb, flags,
 
345
                         pai->dgram,pai->dglen, cbyte_io, max);
 
346
  if (st) return st;
 
347
  if (!pai->qu->vb.used) return adns_s_invaliddata;
 
348
 
 
349
  dm= adns__alloc_interim(pai->qu, pai->qu->vb.used+1);
 
350
  if (!dm) R_NOMEM;
 
351
 
 
352
  dm[pai->qu->vb.used]= 0;
 
353
  memcpy(dm,pai->qu->vb.buf,pai->qu->vb.used);
 
354
  
 
355
  *domain_r= dm;
 
356
  return adns_s_ok;
 
357
}
 
358
 
 
359
static adns_status csp_domain(vbuf *vb, const char *domain) {
 
360
  CSP_ADDSTR(domain);
 
361
  if (!*domain) CSP_ADDSTR(".");
 
362
  return adns_s_ok;
 
363
}
 
364
 
 
365
static adns_status cs_domain(vbuf *vb, const void *datap) {
 
366
  const char *const *domainp= datap;
 
367
  return csp_domain(vb,*domainp);
 
368
}
 
369
 
 
370
static adns_status pa_dom_raw(const parseinfo *pai, int cbyte, int max, void *datap) {
 
371
  char **rrp= datap;
 
372
  adns_status st;
 
373
 
 
374
  st= pap_domain(pai, &cbyte, max, rrp, pdf_quoteok);
 
375
  if (st) return st;
 
376
  
 
377
  if (cbyte != max) return adns_s_invaliddata;
 
378
  return adns_s_ok;
 
379
}
 
380
 
 
381
/*
 
382
 * _host_raw   (pa)
 
383
 */
 
384
 
 
385
static adns_status pa_host_raw(const parseinfo *pai, int cbyte, int max, void *datap) {
 
386
  char **rrp= datap;
 
387
  adns_status st;
 
388
 
 
389
  st= pap_domain(pai, &cbyte, max, rrp,
 
390
                 pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
 
391
  if (st) return st;
 
392
  
 
393
  if (cbyte != max) return adns_s_invaliddata;
 
394
  return adns_s_ok;
 
395
}
 
396
 
 
397
/*
 
398
 * _hostaddr   (pap,pa,dip,di,mfp,mf,csp,cs +icb_hostaddr, pap_findaddrs)
 
399
 */
 
400
 
 
401
static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha,
 
402
                                 int *cbyte_io, int count, int dmstart) {
 
403
  int rri, naddrs;
 
404
  int type, class, rdlen, rdstart, ownermatched;
 
405
  unsigned long ttl;
 
406
  adns_status st;
 
407
  
 
408
  for (rri=0, naddrs=-1; rri<count; rri++) {
 
409
    st= adns__findrr_anychk(pai->qu, pai->serv, pai->dgram, pai->dglen, cbyte_io,
 
410
                            &type, &class, &ttl, &rdlen, &rdstart,
 
411
                            pai->dgram, pai->dglen, dmstart, &ownermatched);
 
412
    if (st) return st;
 
413
    if (!ownermatched || class != DNS_CLASS_IN || type != adns_r_a) {
 
414
      if (naddrs>0) break; else continue;
 
415
    }
 
416
    if (naddrs == -1) {
 
417
      naddrs= 0;
 
418
    }
 
419
    if (!adns__vbuf_ensure(&pai->qu->vb, (naddrs+1)*sizeof(adns_rr_addr))) R_NOMEM;
 
420
    adns__update_expires(pai->qu,ttl,pai->now);
 
421
    st= pa_addr(pai, rdstart,rdstart+rdlen,
 
422
                pai->qu->vb.buf + naddrs*sizeof(adns_rr_addr));
 
423
    if (st) return st;
 
424
    naddrs++;
 
425
  }
 
426
  if (naddrs >= 0) {
 
427
    ha->addrs= adns__alloc_interim(pai->qu, naddrs*sizeof(adns_rr_addr));
 
428
    if (!ha->addrs) R_NOMEM;
 
429
    memcpy(ha->addrs, pai->qu->vb.buf, naddrs*sizeof(adns_rr_addr));
 
430
    ha->naddrs= naddrs;
 
431
    ha->astatus= adns_s_ok;
 
432
 
 
433
    adns__isort(ha->addrs, naddrs, sizeof(adns_rr_addr), pai->qu->vb.buf,
 
434
                div_addr, pai->ads);
 
435
  }
 
436
  return adns_s_ok;
 
437
}
 
438
 
 
439
static void icb_hostaddr(adns_query parent, adns_query child) {
 
440
  adns_answer *cans= child->answer;
 
441
  adns_rr_hostaddr *rrp= child->ctx.info.hostaddr;
 
442
  adns_state ads= parent->ads;
 
443
  adns_status st;
 
444
 
 
445
  st= cans->status;
 
446
  rrp->astatus= st;
 
447
  rrp->naddrs= (st>0 && st<=adns_s_max_tempfail) ? -1 : cans->nrrs;
 
448
  rrp->addrs= cans->rrs.addr;
 
449
  adns__transfer_interim(child, parent, rrp->addrs, rrp->naddrs*sizeof(adns_rr_addr));
 
450
 
 
451
  if (parent->children.head) {
 
452
    LIST_LINK_TAIL(ads->childw,parent);
 
453
  } else {
 
454
    adns__query_done(parent);
 
455
  }
 
456
}
 
457
 
 
458
static adns_status pap_hostaddr(const parseinfo *pai, int *cbyte_io,
 
459
                                int max, adns_rr_hostaddr *rrp) {
 
460
  adns_status st;
 
461
  int dmstart, cbyte;
 
462
  qcontext ctx;
 
463
  int id;
 
464
  adns_query nqu;
 
465
  adns_queryflags nflags;
 
466
 
 
467
  dmstart= cbyte= *cbyte_io;
 
468
  st= pap_domain(pai, &cbyte, max, &rrp->host,
 
469
                 pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
 
470
  if (st) return st;
 
471
  *cbyte_io= cbyte;
 
472
 
 
473
  rrp->astatus= adns_s_ok;
 
474
  rrp->naddrs= -1;
 
475
  rrp->addrs= 0;
 
476
 
 
477
  cbyte= pai->nsstart;
 
478
 
 
479
  st= pap_findaddrs(pai, rrp, &cbyte, pai->nscount, dmstart);
 
480
  if (st) return st;
 
481
  if (rrp->naddrs != -1) return adns_s_ok;
 
482
 
 
483
  st= pap_findaddrs(pai, rrp, &cbyte, pai->arcount, dmstart);
 
484
  if (st) return st;
 
485
  if (rrp->naddrs != -1) return adns_s_ok;
 
486
 
 
487
  st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
 
488
                            pai->dgram, pai->dglen, dmstart,
 
489
                            adns_r_addr, adns_qf_quoteok_query);
 
490
  if (st) return st;
 
491
 
 
492
  ctx.ext= 0;
 
493
  ctx.callback= icb_hostaddr;
 
494
  ctx.info.hostaddr= rrp;
 
495
  
 
496
  nflags= adns_qf_quoteok_query;
 
497
  if (!(pai->qu->flags & adns_qf_cname_loose)) nflags |= adns_qf_cname_forbid;
 
498
  
 
499
  st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_addr),
 
500
                            &pai->qu->vb, id, nflags, pai->now, &ctx);
 
501
  if (st) return st;
 
502
 
 
503
  nqu->parent= pai->qu;
 
504
  LIST_LINK_TAIL_PART(pai->qu->children,nqu,siblings.);
 
505
 
 
506
  return adns_s_ok;
 
507
}
 
508
 
 
509
static adns_status pa_hostaddr(const parseinfo *pai, int cbyte, int max, void *datap) {
 
510
  adns_rr_hostaddr *rrp= datap;
 
511
  adns_status st;
 
512
 
 
513
  st= pap_hostaddr(pai, &cbyte, max, rrp);
 
514
  if (st) return st;
 
515
  if (cbyte != max) return adns_s_invaliddata;
 
516
 
 
517
  return adns_s_ok;
 
518
}
 
519
 
 
520
static int dip_hostaddr(adns_state ads, const adns_rr_hostaddr *ap, const adns_rr_hostaddr *bp) {
 
521
  if (ap->astatus != bp->astatus) return ap->astatus;
 
522
  if (ap->astatus) return 0;
 
523
 
 
524
  assert(ap->addrs[0].addr.sa.sa_family == AF_INET);
 
525
  assert(bp->addrs[0].addr.sa.sa_family == AF_INET);
 
526
  return dip_inaddr(ads,
 
527
                    ap->addrs[0].addr.inet.sin_addr,
 
528
                    bp->addrs[0].addr.inet.sin_addr);
 
529
}
 
530
 
 
531
static int di_hostaddr(adns_state ads, const void *datap_a, const void *datap_b) {
 
532
  const adns_rr_hostaddr *ap= datap_a, *bp= datap_b;
 
533
 
 
534
  return dip_hostaddr(ads, ap,bp);
 
535
}
 
536
 
 
537
static void mfp_hostaddr(adns_query qu, adns_rr_hostaddr *rrp) {
 
538
  void *tablev;
 
539
 
 
540
  adns__makefinal_str(qu,&rrp->host);
 
541
  tablev= rrp->addrs;
 
542
  adns__makefinal_block(qu, &tablev, rrp->naddrs*sizeof(*rrp->addrs));
 
543
  rrp->addrs= tablev;
 
544
}
 
545
 
 
546
static void mf_hostaddr(adns_query qu, void *datap) {
 
547
  adns_rr_hostaddr *rrp= datap;
 
548
 
 
549
  mfp_hostaddr(qu,rrp);
 
550
}
 
551
 
 
552
static adns_status csp_hostaddr(vbuf *vb, const adns_rr_hostaddr *rrp) {
 
553
  const char *errstr;
 
554
  adns_status st;
 
555
  char buf[20];
 
556
  int i;
 
557
 
 
558
  st= csp_domain(vb,rrp->host);  if (st) return st;
 
559
 
 
560
  CSP_ADDSTR(" ");
 
561
  CSP_ADDSTR(adns_errtypeabbrev(rrp->astatus));
 
562
 
 
563
  sprintf(buf," %d ",rrp->astatus);
 
564
  CSP_ADDSTR(buf);
 
565
 
 
566
  CSP_ADDSTR(adns_errabbrev(rrp->astatus));
 
567
  CSP_ADDSTR(" ");
 
568
 
 
569
  errstr= adns_strerror(rrp->astatus);
 
570
  st= csp_qstring(vb,errstr,strlen(errstr));  if (st) return st;
 
571
  
 
572
  if (rrp->naddrs >= 0) {
 
573
    CSP_ADDSTR(" (");
 
574
    for (i=0; i<rrp->naddrs; i++) {
 
575
      CSP_ADDSTR(" ");
 
576
      st= csp_addr(vb,&rrp->addrs[i]);
 
577
    }
 
578
    CSP_ADDSTR(" )");
 
579
  } else {
 
580
    CSP_ADDSTR(" ?");
 
581
  }
 
582
  return adns_s_ok;
 
583
}
 
584
 
 
585
static adns_status cs_hostaddr(vbuf *vb, const void *datap) {
 
586
  const adns_rr_hostaddr *rrp= datap;
 
587
 
 
588
  return csp_hostaddr(vb,rrp);
 
589
}
 
590
 
 
591
/*
 
592
 * _mx_raw   (pa,di)
 
593
 */
 
594
 
 
595
static adns_status pa_mx_raw(const parseinfo *pai, int cbyte, int max, void *datap) {
 
596
  const byte *dgram= pai->dgram;
 
597
  adns_rr_intstr *rrp= datap;
 
598
  adns_status st;
 
599
  int pref;
 
600
 
 
601
  if (cbyte+2 > max) return adns_s_invaliddata;
 
602
  GET_W(cbyte,pref);
 
603
  rrp->i= pref;
 
604
  st= pap_domain(pai, &cbyte, max, &rrp->str,
 
605
                 pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
 
606
  if (st) return st;
 
607
  
 
608
  if (cbyte != max) return adns_s_invaliddata;
 
609
  return adns_s_ok;
 
610
}
 
611
 
 
612
static int di_mx_raw(adns_state ads, const void *datap_a, const void *datap_b) {
 
613
  const adns_rr_intstr *ap= datap_a, *bp= datap_b;
 
614
 
 
615
  if (ap->i < bp->i) return 0;
 
616
  if (ap->i > bp->i) return 1;
 
617
  return 0;
 
618
}
 
619
 
 
620
/*
 
621
 * _mx   (pa,di)
 
622
 */
 
623
 
 
624
static adns_status pa_mx(const parseinfo *pai, int cbyte, int max, void *datap) {
 
625
  const byte *dgram= pai->dgram;
 
626
  adns_rr_inthostaddr *rrp= datap;
 
627
  adns_status st;
 
628
  int pref;
 
629
 
 
630
  if (cbyte+2 > max) return adns_s_invaliddata;
 
631
  GET_W(cbyte,pref);
 
632
  rrp->i= pref;
 
633
  st= pap_hostaddr(pai, &cbyte, max, &rrp->ha);
 
634
  if (st) return st;
 
635
  
 
636
  if (cbyte != max) return adns_s_invaliddata;
 
637
  return adns_s_ok;
 
638
}
 
639
 
 
640
static int di_mx(adns_state ads, const void *datap_a, const void *datap_b) {
 
641
  const adns_rr_inthostaddr *ap= datap_a, *bp= datap_b;
 
642
 
 
643
  if (ap->i < bp->i) return 0;
 
644
  if (ap->i > bp->i) return 1;
 
645
  return dip_hostaddr(ads, &ap->ha, &bp->ha);
 
646
}
 
647
 
 
648
/*
 
649
 * _inthostaddr  (mf,cs)
 
650
 */
 
651
 
 
652
static void mf_inthostaddr(adns_query qu, void *datap) {
 
653
  adns_rr_inthostaddr *rrp= datap;
 
654
 
 
655
  mfp_hostaddr(qu,&rrp->ha);
 
656
}
 
657
 
 
658
static adns_status cs_inthostaddr(vbuf *vb, const void *datap) {
 
659
  const adns_rr_inthostaddr *rrp= datap;
 
660
  char buf[10];
 
661
 
 
662
  sprintf(buf,"%u ",rrp->i);
 
663
  CSP_ADDSTR(buf);
 
664
 
 
665
  return csp_hostaddr(vb,&rrp->ha);
 
666
}
 
667
 
 
668
/*
 
669
 * _inthost  (cs)
 
670
 */
 
671
 
 
672
static adns_status cs_inthost(vbuf *vb, const void *datap) {
 
673
  const adns_rr_intstr *rrp= datap;
 
674
  char buf[10];
 
675
 
 
676
  sprintf(buf,"%u ",rrp->i);
 
677
  CSP_ADDSTR(buf);
 
678
  return csp_domain(vb,rrp->str);
 
679
}
 
680
 
 
681
/*
 
682
 * _ptr   (pa, +icb_ptr)
 
683
 */
 
684
 
 
685
static void icb_ptr(adns_query parent, adns_query child) {
 
686
  adns_answer *cans= child->answer;
 
687
  const adns_rr_addr *queried, *found;
 
688
  adns_state ads= parent->ads;
 
689
  int i;
 
690
 
 
691
  if (cans->status == adns_s_nxdomain || cans->status == adns_s_nodata) {
 
692
    adns__query_fail(parent,adns_s_inconsistent);
 
693
    return;
 
694
  } else if (cans->status) {
 
695
    adns__query_fail(parent,cans->status);
 
696
    return;
 
697
  }
 
698
 
 
699
  queried= &parent->ctx.info.ptr_parent_addr;
 
700
  for (i=0, found=cans->rrs.addr; i<cans->nrrs; i++, found++) {
 
701
    if (queried->len == found->len &&
 
702
        !memcmp(&queried->addr,&found->addr,queried->len)) {
 
703
      if (!parent->children.head) {
 
704
        adns__query_done(parent);
 
705
        return;
 
706
      } else {
 
707
        LIST_LINK_TAIL(ads->childw,parent);
 
708
        return;
 
709
      }
 
710
    }
 
711
  }
 
712
 
 
713
  adns__query_fail(parent,adns_s_inconsistent);
 
714
}
 
715
 
 
716
static adns_status pa_ptr(const parseinfo *pai, int dmstart, int max, void *datap) {
 
717
  static const char *(expectdomain[])= { DNS_INADDR_ARPA };
 
718
  
 
719
  char **rrp= datap;
 
720
  adns_status st;
 
721
  adns_rr_addr *ap;
 
722
  findlabel_state fls;
 
723
  char *ep;
 
724
  byte ipv[4];
 
725
  char labbuf[4];
 
726
  int cbyte, i, lablen, labstart, l, id;
 
727
  adns_query nqu;
 
728
  qcontext ctx;
 
729
 
 
730
  cbyte= dmstart;
 
731
  st= pap_domain(pai, &cbyte, max, rrp,
 
732
                 pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
 
733
  if (st) return st;
 
734
  if (cbyte != max) return adns_s_invaliddata;
 
735
 
 
736
  ap= &pai->qu->ctx.info.ptr_parent_addr;
 
737
  if (!ap->len) {
 
738
    adns__findlabel_start(&fls, pai->ads, -1, pai->qu,
 
739
                          pai->qu->query_dgram, pai->qu->query_dglen,
 
740
                          pai->qu->query_dglen, DNS_HDRSIZE, 0);
 
741
    for (i=0; i<4; i++) {
 
742
      st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
 
743
      if (lablen<=0 || lablen>3) return adns_s_querydomainwrong;
 
744
      memcpy(labbuf, pai->qu->query_dgram + labstart, lablen);  labbuf[lablen]= 0;
 
745
      ipv[3-i]= strtoul(labbuf,&ep,10);  if (*ep) return adns_s_querydomainwrong;
 
746
      if (lablen>1 && pai->qu->query_dgram[labstart]=='0')
 
747
        return adns_s_querydomainwrong;
 
748
    }
 
749
    for (i=0; i<sizeof(expectdomain)/sizeof(*expectdomain); i++) {
 
750
      st= adns__findlabel_next(&fls,&lablen,&labstart); assert(!st);
 
751
      l= strlen(expectdomain[i]);
 
752
      if (lablen != l || memcmp(pai->qu->query_dgram + labstart, expectdomain[i], l))
 
753
        return adns_s_querydomainwrong;
 
754
    }
 
755
    st= adns__findlabel_next(&fls,&lablen,0); assert(!st);
 
756
    if (lablen) return adns_s_querydomainwrong;
 
757
    
 
758
    ap->len= sizeof(struct sockaddr_in);
 
759
    memset(&ap->addr,0,sizeof(ap->addr.inet));
 
760
    ap->addr.inet.sin_family= AF_INET;
 
761
    ap->addr.inet.sin_addr.s_addr=
 
762
      htonl((ipv[0]<<24) | (ipv[1]<<16) | (ipv[2]<<8) | (ipv[3]));
 
763
  }
 
764
 
 
765
  st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
 
766
                            pai->dgram, pai->dglen, dmstart,
 
767
                            adns_r_addr, adns_qf_quoteok_query);
 
768
  if (st) return st;
 
769
 
 
770
  ctx.ext= 0;
 
771
  ctx.callback= icb_ptr;
 
772
  memset(&ctx.info,0,sizeof(ctx.info));
 
773
  st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_addr),
 
774
                            &pai->qu->vb, id,
 
775
                            adns_qf_quoteok_query, pai->now, &ctx);
 
776
  if (st) return st;
 
777
 
 
778
  nqu->parent= pai->qu;
 
779
  LIST_LINK_TAIL_PART(pai->qu->children,nqu,siblings.);
 
780
  return adns_s_ok;
 
781
}
 
782
 
 
783
/*
 
784
 * _strpair   (mf)
 
785
 */
 
786
 
 
787
static void mf_strpair(adns_query qu, void *datap) {
 
788
  adns_rr_strpair *rrp= datap;
 
789
 
 
790
  adns__makefinal_str(qu,&rrp->array[0]);
 
791
  adns__makefinal_str(qu,&rrp->array[1]);
 
792
}
 
793
 
 
794
/*
 
795
 * _intstrpair   (mf)
 
796
 */
 
797
 
 
798
static void mf_intstrpair(adns_query qu, void *datap) {
 
799
  adns_rr_intstrpair *rrp= datap;
 
800
 
 
801
  adns__makefinal_str(qu,&rrp->array[0].str);
 
802
  adns__makefinal_str(qu,&rrp->array[1].str);
 
803
}
 
804
 
 
805
/*
 
806
 * _hinfo   (pa)
 
807
 */
 
808
 
 
809
static adns_status pa_hinfo(const parseinfo *pai, int cbyte, int max, void *datap) {
 
810
  adns_rr_intstrpair *rrp= datap;
 
811
  adns_status st;
 
812
  int i;
 
813
 
 
814
  for (i=0; i<2; i++) {
 
815
    st= pap_qstring(pai, &cbyte, max, &rrp->array[i].i, &rrp->array[i].str);
 
816
    if (st) return st;
 
817
  }
 
818
 
 
819
  if (cbyte != max) return adns_s_invaliddata;
 
820
  
 
821
  return adns_s_ok;
 
822
}
 
823
 
 
824
/*
 
825
 * _mailbox   (pap,cs)
 
826
 */
 
827
 
 
828
static adns_status pap_mailbox822(const parseinfo *pai, int *cbyte_io, int max,
 
829
                                  char **mb_r) {
 
830
  int lablen, labstart, i, needquote, c, r, neednorm;
 
831
  const unsigned char *p;
 
832
  char *str;
 
833
  findlabel_state fls;
 
834
  adns_status st;
 
835
  vbuf *vb;
 
836
 
 
837
  vb= &pai->qu->vb;
 
838
  vb->used= 0;
 
839
  adns__findlabel_start(&fls, pai->ads,
 
840
                        -1, pai->qu,
 
841
                        pai->dgram, pai->dglen, max,
 
842
                        *cbyte_io, cbyte_io);
 
843
  st= adns__findlabel_next(&fls,&lablen,&labstart);
 
844
  if (!lablen) {
 
845
    adns__vbuf_appendstr(vb,".");
 
846
    goto x_ok;
 
847
  }
 
848
 
 
849
  neednorm= 1;
 
850
  for (i=0, needquote=0, p= pai->dgram+labstart; i<lablen; i++) {
 
851
    c= *p++;
 
852
    if ((c&~128) < 32 || (c&~128) == 127) return adns_s_invaliddata;
 
853
    if (c == '.' && !neednorm) neednorm= 1;
 
854
    else if (c==' ' || c>=127 || ctype_822special(c)) needquote++;
 
855
    else neednorm= 0;
 
856
  }
 
857
 
 
858
  if (needquote || neednorm) {
 
859
    r= adns__vbuf_ensure(vb, lablen+needquote+4); if (!r) R_NOMEM;
 
860
    adns__vbuf_appendq(vb,"\"",1);
 
861
    for (i=0, needquote=0, p= pai->dgram+labstart; i<lablen; i++, p++) {
 
862
      c= *p;
 
863
      if (c == '"' || c=='\\') adns__vbuf_appendq(vb,"\\",1);
 
864
      adns__vbuf_appendq(vb,p,1);
 
865
    }
 
866
    adns__vbuf_appendq(vb,"\"",1);
 
867
  } else {
 
868
    r= adns__vbuf_append(vb, pai->dgram+labstart, lablen); if (!r) R_NOMEM;
 
869
  }
 
870
 
 
871
  r= adns__vbuf_appendstr(vb,"@"); if (!r) R_NOMEM;
 
872
 
 
873
  st= adns__parse_domain_more(&fls,pai->ads, pai->qu,vb,0, pai->dgram);
 
874
  if (st) return st;
 
875
 
 
876
 x_ok:
 
877
  str= adns__alloc_interim(pai->qu, vb->used+1); if (!str) R_NOMEM;
 
878
  memcpy(str,vb->buf,vb->used);
 
879
  str[vb->used]= 0;
 
880
  *mb_r= str;
 
881
  return adns_s_ok;
 
882
}
 
883
 
 
884
static adns_status pap_mailbox(const parseinfo *pai, int *cbyte_io, int max,
 
885
                               char **mb_r) {
 
886
  if (pai->qu->typei->type & adns__qtf_mail822) {
 
887
    return pap_mailbox822(pai, cbyte_io, max, mb_r);
 
888
  } else {
 
889
    return pap_domain(pai, cbyte_io, max, mb_r, pdf_quoteok);
 
890
  }
 
891
}
 
892
 
 
893
static adns_status csp_mailbox(vbuf *vb, const char *mailbox) {
 
894
  return csp_domain(vb,mailbox);
 
895
}
 
896
 
 
897
/*
 
898
 * _rp   (pa,cs)
 
899
 */
 
900
 
 
901
static adns_status pa_rp(const parseinfo *pai, int cbyte, int max, void *datap) {
 
902
  adns_rr_strpair *rrp= datap;
 
903
  adns_status st;
 
904
 
 
905
  st= pap_mailbox(pai, &cbyte, max, &rrp->array[0]);
 
906
  if (st) return st;
 
907
 
 
908
  st= pap_domain(pai, &cbyte, max, &rrp->array[1], pdf_quoteok);
 
909
  if (st) return st;
 
910
 
 
911
  if (cbyte != max) return adns_s_invaliddata;
 
912
  return adns_s_ok;
 
913
}
 
914
 
 
915
static adns_status cs_rp(vbuf *vb, const void *datap) {
 
916
  const adns_rr_strpair *rrp= datap;
 
917
  adns_status st;
 
918
 
 
919
  st= csp_mailbox(vb,rrp->array[0]);  if (st) return st;
 
920
  CSP_ADDSTR(" ");
 
921
  st= csp_domain(vb,rrp->array[1]);  if (st) return st;
 
922
 
 
923
  return adns_s_ok;
 
924
}  
 
925
 
 
926
/*
 
927
 * _soa   (pa,mf,cs)
 
928
 */
 
929
 
 
930
static adns_status pa_soa(const parseinfo *pai, int cbyte, int max, void *datap) {
 
931
  adns_rr_soa *rrp= datap;
 
932
  const byte *dgram= pai->dgram;
 
933
  adns_status st;
 
934
  int msw, lsw, i;
 
935
 
 
936
  st= pap_domain(pai, &cbyte, max, &rrp->mname,
 
937
                 pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0);
 
938
  if (st) return st;
 
939
 
 
940
  st= pap_mailbox(pai, &cbyte, max, &rrp->rname);
 
941
  if (st) return st;
 
942
 
 
943
  if (cbyte+20 != max) return adns_s_invaliddata;
 
944
  
 
945
  for (i=0; i<5; i++) {
 
946
    GET_W(cbyte,msw);
 
947
    GET_W(cbyte,lsw);
 
948
    (&rrp->serial)[i]= (msw<<16) | lsw;
 
949
  }
 
950
 
 
951
  return adns_s_ok;
 
952
}
 
953
 
 
954
static void mf_soa(adns_query qu, void *datap) {
 
955
  adns_rr_soa *rrp= datap;
 
956
 
 
957
  adns__makefinal_str(qu,&rrp->mname);
 
958
  adns__makefinal_str(qu,&rrp->rname);
 
959
}
 
960
 
 
961
static adns_status cs_soa(vbuf *vb, const void *datap) {
 
962
  const adns_rr_soa *rrp= datap;
 
963
  char buf[20];
 
964
  int i;
 
965
  adns_status st;
 
966
  
 
967
  st= csp_domain(vb,rrp->mname);  if (st) return st;
 
968
  CSP_ADDSTR(" ");
 
969
  st= csp_mailbox(vb,rrp->rname);  if (st) return st;
 
970
 
 
971
  for (i=0; i<5; i++) {
 
972
    sprintf(buf," %lu",(&rrp->serial)[i]);
 
973
    CSP_ADDSTR(buf);
 
974
  }
 
975
 
 
976
  return adns_s_ok;
 
977
}
 
978
 
 
979
/*
 
980
 * _flat   (mf)
 
981
 */
 
982
 
 
983
static void mf_flat(adns_query qu, void *data) { }
 
984
 
 
985
/*
 
986
 * Now the table.
 
987
 */
 
988
 
 
989
#define TYPESZ_M(member)           (sizeof(*((adns_answer*)0)->rrs.member))
 
990
 
 
991
#define DEEP_MEMB(memb) TYPESZ_M(memb), mf_##memb, cs_##memb
 
992
#define FLAT_MEMB(memb) TYPESZ_M(memb), mf_flat, cs_##memb
 
993
 
 
994
#define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \
 
995
 { adns_r_##code, rrt, fmt, TYPESZ_M(memb), mf_##memb, printer, parser, comparer }
 
996
#define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \
 
997
 { adns_r_##code, rrt, fmt, TYPESZ_M(memb), mf_flat, printer, parser, comparer }
 
998
 
 
999
static const typeinfo typeinfos[] = {
 
1000
/* Must be in ascending order of rrtype ! */
 
1001
/* mem-mgmt code  rrt     fmt     member      parser      comparer    printer       */
 
1002
                                                                                       
 
1003
FLAT_TYPE(a,      "A",     0,     inaddr,     pa_inaddr,  di_inaddr,  cs_inaddr     ),
 
1004
DEEP_TYPE(ns_raw, "NS",   "raw",  str,        pa_host_raw,0,          cs_domain     ),
 
1005
DEEP_TYPE(cname,  "CNAME", 0,     str,        pa_dom_raw, 0,          cs_domain     ),
 
1006
DEEP_TYPE(soa_raw,"SOA",  "raw",  soa,        pa_soa,     0,          cs_soa        ),
 
1007
DEEP_TYPE(ptr_raw,"PTR",  "raw",  str,        pa_host_raw,0,          cs_domain     ),
 
1008
DEEP_TYPE(hinfo,  "HINFO", 0,     intstrpair, pa_hinfo,   0,          cs_hinfo      ),
 
1009
DEEP_TYPE(mx_raw, "MX",   "raw",  intstr,     pa_mx_raw,  di_mx_raw,  cs_inthost    ),
 
1010
DEEP_TYPE(txt,    "TXT",   0,     manyistr,   pa_txt,     0,          cs_txt        ),
 
1011
DEEP_TYPE(rp_raw, "RP",   "raw",  strpair,    pa_rp,      0,          cs_rp         ),
 
1012
                                                                                       
 
1013
FLAT_TYPE(addr,   "A",  "addr",   addr,       pa_addr,    di_addr,    cs_addr       ),
 
1014
DEEP_TYPE(ns,     "NS", "+addr",  hostaddr,   pa_hostaddr,di_hostaddr,cs_hostaddr   ),
 
1015
DEEP_TYPE(ptr,    "PTR","checked",str,        pa_ptr,     0,          cs_domain     ),
 
1016
DEEP_TYPE(mx,     "MX", "+addr",  inthostaddr,pa_mx,      di_mx,      cs_inthostaddr),
 
1017
                                                                              
 
1018
DEEP_TYPE(soa,    "SOA","822",    soa,        pa_soa,     0,          cs_soa        ),
 
1019
DEEP_TYPE(rp,     "RP", "822",    strpair,    pa_rp,      0,          cs_rp         ),
 
1020
};
 
1021
 
 
1022
const typeinfo *adns__findtype(adns_rrtype type) {
 
1023
  const typeinfo *begin, *end, *mid;
 
1024
 
 
1025
  begin= typeinfos;  end= typeinfos+(sizeof(typeinfos)/sizeof(typeinfo));
 
1026
 
 
1027
  while (begin < end) {
 
1028
    mid= begin + ((end-begin)>>1);
 
1029
    if (mid->type == type) return mid;
 
1030
    if (type > mid->type) begin= mid+1;
 
1031
    else end= mid;
 
1032
  }
 
1033
  return 0;
 
1034
}