debian/rules: Use `git' potty wrapper.
[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 }