]> jfr.im git - irc/quakenet/newserv.git/blob - proxyscan/proxyscancache.c
merge
[irc/quakenet/newserv.git] / proxyscan / proxyscancache.c
1 /*
2 * proxyscancache.c:
3 * This file deals with the cache of known hosts, clean or otherwise.
4 */
5
6 #include "proxyscan.h"
7 #include <time.h>
8 #include <stdio.h>
9 #include "../core/error.h"
10 #include <string.h>
11
12 time_t cleanscaninterval;
13 time_t dirtyscaninterval;
14
15 void cachehostinit(time_t ri) {
16 cleanscaninterval=ri;
17 dirtyscaninterval=ri*7;
18 }
19
20 cachehost *addcleanhost(time_t timestamp) {
21 cachehost *chp;
22
23 chp=getcachehost();
24 chp->lastscan=timestamp;
25 chp->proxies=NULL;
26 chp->glineid=0;
27
28 return chp;
29 }
30
31 void delcachehost(cachehost *chp) {
32 foundproxy *fpp, *nfpp;
33
34 for (fpp=chp->proxies;fpp;fpp=nfpp) {
35 nfpp=fpp->next;
36 freefoundproxy(fpp);
37 }
38 freecachehost(chp);
39 }
40
41 /*
42 * Returns a cachehost * for the named IP
43 */
44
45 cachehost *findcachehost(patricia_node_t *node) {
46 cachehost *chp;
47
48 if( (cachehost *)node->exts[ps_cache_ext] ) {
49 chp = (cachehost *)node->exts[ps_cache_ext];
50 if(chp->lastscan < (time(NULL)-(chp->proxies ? dirtyscaninterval : cleanscaninterval))) {
51 /* Needs rescan; delete and return 1 */
52 delcachehost(chp);
53 derefnode(iptree,node);
54 node->exts[ps_cache_ext] = NULL;
55 return NULL;
56 } else {
57 /* valid: return it */
58 return chp;
59 }
60 }
61
62 /* Not found: return NULL */
63 return NULL;
64 }
65
66 /*
67 * dumpcleanhosts:
68 * Dumps all cached hosts to a savefile. Expires hosts as it goes along
69 */
70
71 void dumpcachehosts(void *arg) {
72 FILE *fp;
73 cachehost *chp;
74 time_t now=time(NULL);
75 foundproxy *fpp;
76 patricia_node_t *node;
77
78 if ((fp=fopen("data/cleanhosts","w"))==NULL) {
79 Error("proxyscan",ERR_ERROR,"Unable to open cleanhosts file for writing!");
80 return;
81 }
82
83 PATRICIA_WALK_CLEAR (iptree->head, node) {
84 if (node->exts[ps_cache_ext] ) {
85 chp = (cachehost *) node->exts[ps_cache_ext];
86 if (chp) {
87 if (chp->proxies) {
88 if (chp->lastscan < (now-dirtyscaninterval)) {
89 derefnode(iptree,node);
90 delcachehost(chp);
91 node->exts[ps_cache_ext] = NULL;
92 } else
93
94 for (fpp=chp->proxies;fpp;fpp=fpp->next)
95 fprintf(fp, "%s %lu %u %i %u\n",IPtostr(node->prefix->sin),chp->lastscan,chp->glineid,fpp->type,fpp->port);
96 } else {
97 if (chp->lastscan < (now-cleanscaninterval)) {
98 /* Needs rescan anyway, so delete it */
99 derefnode(iptree,node);
100 delcachehost(chp);
101 node->exts[ps_cache_ext] = NULL;
102 } else
103 fprintf(fp,"%s %lu\n",IPtostr(node->prefix->sin),chp->lastscan);
104 }
105 }
106 }
107 } PATRICIA_WALK_CLEAR_END;
108
109 // patricia_tidy_tree(iptree);
110
111 fclose(fp);
112 }
113
114 /*
115 * loadcleanhosts:
116 * Loads clean hosts in from database.
117 */
118
119 void loadcachehosts() {
120 FILE *fp;
121 unsigned long timestamp,glineid,ptype,pport;
122 char buf[512];
123 cachehost *chp=NULL;
124 foundproxy *fpp;
125 char ip[512];
126 int res;
127 struct irc_in_addr sin;
128 unsigned char bits;
129 patricia_node_t *node;
130 int i=0;
131
132 if ((fp=fopen("data/cleanhosts","r"))==NULL) {
133 Error("proxyscan",ERR_ERROR,"Unable to open cleanhosts file for reading!");
134 return;
135 }
136
137
138 while (!feof(fp)) {
139 fgets(buf,512,fp);
140 if (feof(fp)) {
141 break;
142 }
143
144 res=sscanf(buf,"%s %lu %lu %lu %lu",ip,&timestamp,&glineid,&ptype,&pport);
145
146 if (res<2)
147 continue;
148
149 if (0 == ipmask_parse(ip,&sin, &bits)) {
150 /* invalid mask */
151 } else {
152 node = refnode(iptree, &sin, bits);
153 if( node ) {
154 i++;
155 chp=addcleanhost(timestamp);
156 node->exts[ps_cache_ext] = chp;
157
158 if (res==5) {
159 chp->glineid=glineid;
160 fpp=getfoundproxy();
161 fpp->type=ptype;
162 fpp->port=pport;
163 fpp->next=chp->proxies;
164 chp->proxies=fpp;
165 }
166 }
167 }
168 }
169
170 Error("proxyscan",ERR_INFO, "Loaded %d entries from cache", i);
171 }
172
173 /*
174 * cleancount:
175 * Returns the number of "clean" host entries present
176 */
177
178 unsigned int cleancount() {
179 unsigned int total=0;
180 cachehost *chp;
181 patricia_node_t *head, *node;
182 head = iptree->head;
183 PATRICIA_WALK (head, node) {
184 if ( node->exts[ps_cache_ext] ) {
185 chp = (cachehost *) node->exts[ps_cache_ext];
186
187 if (!chp->proxies)
188 total++;
189 }
190 } PATRICIA_WALK_END;
191
192 return total;
193 }
194
195 unsigned int dirtycount() {
196 unsigned int total=0;
197 cachehost *chp;
198 patricia_node_t *node;
199
200 PATRICIA_WALK (iptree->head, node) {
201 if ( node->exts[ps_cache_ext] ) {
202 chp = (cachehost *) node->exts[ps_cache_ext];
203 if (chp->proxies)
204 total++;
205 }
206 } PATRICIA_WALK_END;
207
208 return total;
209 }
210
211 /*
212 * scanall:
213 * Scans all hosts on the network for a given proxy, and updates the cache accordingly
214 */
215
216 void scanall(int type, int port) {
217 int i;
218 cachehost *chp;
219 nick *np;
220 unsigned int hostmarker;
221 patricia_node_t *node;
222
223 hostmarker=nexthostmarker();
224
225 PATRICIA_WALK (iptree->head, node) {
226 if ( node->exts[ps_cache_ext] ) {
227 chp = (cachehost *) node->exts[ps_cache_ext];
228 chp->marker=0;
229 }
230 } PATRICIA_WALK_END;
231
232 for (i=0;i<NICKHASHSIZE;i++) {
233 for (np=nicktable[i];np;np=np->next) {
234 if (np->host->marker==hostmarker)
235 continue;
236
237 np->host->marker=hostmarker;
238
239 if (!irc_in_addr_is_ipv4(&np->p_ipaddr))
240 continue;
241
242 if ((chp=findcachehost(np->ipnode)))
243 chp->marker=1;
244
245 queuescan(np->ipnode, type, port, SCLASS_NORMAL, 0);
246 }
247 }
248 }