~ubuntu-branches/ubuntu/intrepid/djbdns/intrepid-security

« back to all changes in this revision

Viewing changes to pickdns-data.c

  • Committer: Bazaar Package Importer
  • Author(s): Gerrit Pape
  • Date: 2008-03-02 23:22:04 UTC
  • Revision ID: james.westby@ubuntu.com-20080302232204-wa3owprcpeiyu8kj
Tags: upstream-1.05
ImportĀ upstreamĀ versionĀ 1.05

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <sys/types.h>
 
3
#include <sys/stat.h>
 
4
#include <unistd.h>
 
5
#include "buffer.h"
 
6
#include "exit.h"
 
7
#include "cdb_make.h"
 
8
#include "open.h"
 
9
#include "alloc.h"
 
10
#include "gen_allocdefs.h"
 
11
#include "stralloc.h"
 
12
#include "getln.h"
 
13
#include "case.h"
 
14
#include "strerr.h"
 
15
#include "str.h"
 
16
#include "byte.h"
 
17
#include "scan.h"
 
18
#include "fmt.h"
 
19
#include "ip4.h"
 
20
#include "dns.h"
 
21
 
 
22
#define FATAL "pickdns-data: fatal: "
 
23
 
 
24
void nomem(void)
 
25
{
 
26
  strerr_die2x(111,FATAL,"out of memory");
 
27
}
 
28
 
 
29
void ipprefix_cat(stralloc *out,char *s)
 
30
{
 
31
  unsigned long u;
 
32
  char ch;
 
33
  unsigned int j;
 
34
 
 
35
  for (;;)
 
36
    if (*s == '.')
 
37
      ++s;
 
38
    else {
 
39
      j = scan_ulong(s,&u);
 
40
      if (!j) return;
 
41
      s += j;
 
42
      ch = u;
 
43
      if (!stralloc_catb(out,&ch,1)) nomem();
 
44
    }
 
45
}
 
46
 
 
47
struct address {
 
48
  char *name;
 
49
  unsigned int namelen;
 
50
  char ip[4];
 
51
  char location[2];
 
52
} ;
 
53
 
 
54
int address_diff(struct address *p,struct address *q)
 
55
{
 
56
  int r;
 
57
 
 
58
  r = byte_diff(p->location,2,q->location);
 
59
  if (r < 0) return -1;
 
60
  if (r > 0) return 1;
 
61
  if (p->namelen < q->namelen) return -1;
 
62
  if (p->namelen > q->namelen) return 1;
 
63
  return case_diffb(p->name,p->namelen,q->name);
 
64
}
 
65
 
 
66
void address_sort(struct address *z,unsigned int n)
 
67
{
 
68
  unsigned int i;
 
69
  unsigned int j;
 
70
  unsigned int p;
 
71
  unsigned int q;
 
72
  struct address t;
 
73
 
 
74
  i = j = n;
 
75
  --z;
 
76
 
 
77
  while (j > 1) {
 
78
    if (i > 1) { --i; t = z[i]; }
 
79
    else { t = z[j]; z[j] = z[i]; --j; }
 
80
    q = i;
 
81
    while ((p = q * 2) < j) {
 
82
      if (address_diff(&z[p + 1],&z[p]) >= 0) ++p;
 
83
      z[q] = z[p]; q = p;
 
84
    }
 
85
    if (p == j) {
 
86
      z[q] = z[p]; q = p;
 
87
    }
 
88
    while ((q > i) && (address_diff(&t,&z[p = q/2]) > 0)) {
 
89
      z[q] = z[p]; q = p;
 
90
    }
 
91
    z[q] = t;
 
92
  }
 
93
}
 
94
 
 
95
GEN_ALLOC_typedef(address_alloc,struct address,s,len,a)
 
96
GEN_ALLOC_readyplus(address_alloc,struct address,s,len,a,i,n,x,30,address_alloc_readyplus)
 
97
GEN_ALLOC_append(address_alloc,struct address,s,len,a,i,n,x,30,address_alloc_readyplus,address_alloc_append)
 
98
 
 
99
static address_alloc x;
 
100
 
 
101
int fd;
 
102
buffer b;
 
103
char bspace[1024];
 
104
 
 
105
int fdcdb;
 
106
struct cdb_make cdb;
 
107
static stralloc key;
 
108
static stralloc result;
 
109
 
 
110
static stralloc line;
 
111
int match = 1;
 
112
unsigned long linenum = 0;
 
113
 
 
114
#define NUMFIELDS 3
 
115
static stralloc f[NUMFIELDS];
 
116
 
 
117
char strnum[FMT_ULONG];
 
118
 
 
119
void syntaxerror(const char *why)
 
120
{
 
121
  strnum[fmt_ulong(strnum,linenum)] = 0;
 
122
  strerr_die4x(111,FATAL,"unable to parse data line ",strnum,why);
 
123
}
 
124
void die_datatmp(void)
 
125
{
 
126
  strerr_die2sys(111,FATAL,"unable to create data.tmp: ");
 
127
}
 
128
 
 
129
int main()
 
130
{
 
131
  struct address t;
 
132
  int i;
 
133
  int j;
 
134
  int k;
 
135
  char ch;
 
136
 
 
137
  umask(022);
 
138
 
 
139
  if (!address_alloc_readyplus(&x,0)) nomem();
 
140
 
 
141
  fd = open_read("data");
 
142
  if (fd == -1) strerr_die2sys(111,FATAL,"unable to open data: ");
 
143
  buffer_init(&b,buffer_unixread,fd,bspace,sizeof bspace);
 
144
 
 
145
  fdcdb = open_trunc("data.tmp");
 
146
  if (fdcdb == -1) die_datatmp();
 
147
  if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp();
 
148
 
 
149
  while (match) {
 
150
    ++linenum;
 
151
    if (getln(&b,&line,&match,'\n') == -1)
 
152
      strerr_die2sys(111,FATAL,"unable to read line: ");
 
153
 
 
154
    while (line.len) {
 
155
      ch = line.s[line.len - 1];
 
156
      if ((ch != ' ') && (ch != '\t') && (ch != '\n')) break;
 
157
      --line.len;
 
158
    }
 
159
    if (!line.len) continue;
 
160
 
 
161
    j = 1;
 
162
    for (i = 0;i < NUMFIELDS;++i) {
 
163
      if (j >= line.len) {
 
164
        if (!stralloc_copys(&f[i],"")) nomem();
 
165
      }
 
166
      else {
 
167
        k = byte_chr(line.s + j,line.len - j,':');
 
168
        if (!stralloc_copyb(&f[i],line.s + j,k)) nomem();
 
169
        j += k + 1;
 
170
      }
 
171
    }
 
172
 
 
173
    switch(line.s[0]) {
 
174
      default:
 
175
        syntaxerror(": unrecognized leading character");
 
176
      case '#':
 
177
        break;
 
178
      case '-':
 
179
        break;
 
180
      case '+':
 
181
        byte_zero(&t,sizeof t);
 
182
        if (!dns_domain_fromdot(&t.name,f[0].s,f[0].len)) nomem();
 
183
        t.namelen = dns_domain_length(t.name);
 
184
        case_lowerb(t.name,t.namelen);
 
185
        if (!stralloc_0(&f[1])) nomem();
 
186
        if (!ip4_scan(f[1].s,t.ip)) syntaxerror(": malformed IP address");
 
187
        if (!stralloc_0(&f[2])) nomem();
 
188
        if (!stralloc_0(&f[2])) nomem();
 
189
        byte_copy(t.location,2,f[2].s);
 
190
        if (!address_alloc_append(&x,&t)) nomem();
 
191
        break;
 
192
      case '%':
 
193
        if (!stralloc_0(&f[0])) nomem();
 
194
        if (!stralloc_0(&f[0])) nomem();
 
195
        if (!stralloc_copyb(&result,f[0].s,2)) nomem();
 
196
        if (!stralloc_0(&f[1])) nomem();
 
197
        if (!stralloc_copys(&key,"%")) nomem();
 
198
        ipprefix_cat(&key,f[1].s);
 
199
        if (cdb_make_add(&cdb,key.s,key.len,result.s,result.len) == -1)
 
200
          die_datatmp();
 
201
        break;
 
202
    }
 
203
  }
 
204
 
 
205
  close(fd);
 
206
  address_sort(x.s,x.len);
 
207
 
 
208
  i = 0;
 
209
  while (i < x.len) {
 
210
    for (j = i + 1;j < x.len;++j)
 
211
      if (address_diff(x.s + i,x.s + j))
 
212
        break;
 
213
    if (!stralloc_copys(&key,"+")) nomem();
 
214
    if (!stralloc_catb(&key,x.s[i].location,2)) nomem();
 
215
    if (!stralloc_catb(&key,x.s[i].name,x.s[i].namelen)) nomem();
 
216
    if (!stralloc_copys(&result,"")) nomem();
 
217
    while (i < j)
 
218
      if (!stralloc_catb(&result,x.s[i++].ip,4)) nomem();
 
219
    if (cdb_make_add(&cdb,key.s,key.len,result.s,result.len) == -1)
 
220
      die_datatmp();
 
221
  }
 
222
 
 
223
  if (cdb_make_finish(&cdb) == -1) die_datatmp();
 
224
  if (fsync(fdcdb) == -1) die_datatmp();
 
225
  if (close(fdcdb) == -1) die_datatmp(); /* NFS stupidity */
 
226
  if (rename("data.tmp","data.cdb") == -1)
 
227
    strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
 
228
 
 
229
  _exit(0);
 
230
}