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