chiark / gitweb /
Merge branches 'idx/verh' and 'idx/qmqpc'
[qmail] / tcpto.c
1 #include "tcpto.h"
2 #include "open.h"
3 #include "lock.h"
4 #include "seek.h"
5 #include "now.h"
6 #include "ip.h"
7 #include "byte.h"
8 #include "datetime.h"
9 #include "readwrite.h"
10
11 char tcpto_buf[1024];
12
13 static int flagwasthere;
14 static int fdlock;
15
16 static int getbuf()
17 {
18  int r;
19  int fd;
20
21  fdlock = open_write("queue/lock/tcpto");
22  if (fdlock == -1) return 0;
23  fd = open_read("queue/lock/tcpto");
24  if (fd == -1) { close(fdlock); return 0; }
25  if (lock_ex(fdlock) == -1) { close(fdlock); close(fd); return 0; }
26  r = read(fd,tcpto_buf,sizeof(tcpto_buf));
27  close(fd);
28  if (r < 0) { close(fdlock); return 0; }
29  r >>= 4;
30  if (!r) close(fdlock);
31  return r;
32 }
33
34 int tcpto(ip) struct ip_address *ip;
35 {
36  int n;
37  int i;
38  char *record;
39  datetime_sec when;
40
41  flagwasthere = 0;
42
43  n = getbuf();
44  if (!n) return 0;
45  close(fdlock);
46
47  record = tcpto_buf;
48  for (i = 0;i < n;++i)
49   {
50    if (byte_equal(ip->d,4,record))
51     {
52      flagwasthere = 1;
53      if (record[4] >= 2)
54       {
55        when = (unsigned long) (unsigned char) record[11];
56        when = (when << 8) + (unsigned long) (unsigned char) record[10];
57        when = (when << 8) + (unsigned long) (unsigned char) record[9];
58        when = (when << 8) + (unsigned long) (unsigned char) record[8];
59
60        if (now() - when < ((60 + (getpid() & 31)) << 6))
61          return 1;
62       }
63      return 0;
64     }
65    record += 16;
66   }
67  return 0;
68 }
69
70 void tcpto_err(ip,flagerr) struct ip_address *ip; int flagerr;
71 {
72  int n;
73  int i;
74  char *record;
75  datetime_sec when;
76  datetime_sec firstwhen;
77  int firstpos;
78  datetime_sec lastwhen;
79
80  if (!flagerr)
81    if (!flagwasthere)
82      return; /* could have been added, but not worth the effort to check */
83
84  n = getbuf();
85  if (!n) return;
86
87  record = tcpto_buf;
88  for (i = 0;i < n;++i)
89   {
90    if (byte_equal(ip->d,4,record))
91     {
92      if (!flagerr)
93        record[4] = 0;
94      else
95       {
96        lastwhen = (unsigned long) (unsigned char) record[11];
97        lastwhen = (lastwhen << 8) + (unsigned long) (unsigned char) record[10];
98        lastwhen = (lastwhen << 8) + (unsigned long) (unsigned char) record[9];
99        lastwhen = (lastwhen << 8) + (unsigned long) (unsigned char) record[8];
100        when = now();
101
102        if (record[4] && (when < 120 + lastwhen)) { close(fdlock); return; }
103
104        if (++record[4] > 10) record[4] = 10;
105        record[8] = when; when >>= 8;
106        record[9] = when; when >>= 8;
107        record[10] = when; when >>= 8;
108        record[11] = when;
109       }
110      if (seek_set(fdlock,i << 4) == 0)
111        if (write(fdlock,record,16) < 16)
112          ; /*XXX*/
113      close(fdlock);
114      return;
115     }
116    record += 16;
117   }
118
119  if (!flagerr) { close(fdlock); return; }
120
121  record = tcpto_buf;
122  for (i = 0;i < n;++i)
123   {
124    if (!record[4]) break;
125    record += 16;
126   }
127
128  if (i >= n)
129   {
130    firstpos = -1;
131    record = tcpto_buf;
132    for (i = 0;i < n;++i)
133     {
134      when = (unsigned long) (unsigned char) record[11];
135      when = (when << 8) + (unsigned long) (unsigned char) record[10];
136      when = (when << 8) + (unsigned long) (unsigned char) record[9];
137      when = (when << 8) + (unsigned long) (unsigned char) record[8];
138      when += (record[4] << 10);
139      if ((firstpos < 0) || (when < firstwhen))
140       {
141        firstpos = i;
142        firstwhen = when;
143       }
144      record += 16;
145     }
146    i = firstpos;
147   }
148
149  if (i >= 0)
150   {
151    record = tcpto_buf + (i << 4);
152    byte_copy(record,4,ip->d);
153    when = now();
154    record[8] = when; when >>= 8;
155    record[9] = when; when >>= 8;
156    record[10] = when; when >>= 8;
157    record[11] = when;
158    record[4] = 1;
159    if (seek_set(fdlock,i << 4) == 0)
160      if (write(fdlock,record,16) < 16)
161        ; /*XXX*/
162   }
163
164  close(fdlock);
165 }