]>
jfr.im git - irc/quakenet/newserv.git/blob - trusts/data.c
5 #include "../lib/sstring.h"
6 #include "../core/hooks.h"
7 #include "../core/nsmalloc.h"
8 #include "../lib/irc_string.h"
13 void th_dbupdatecounts ( trusthost
*);
14 void tg_dbupdatecounts ( trustgroup
*);
16 static trusthost
* th_getnextchildbyhost ( trusthost
*, trusthost
*);
18 void trusts_freeall ( void ) {
22 for ( tg
= tglist
; tg
; tg
= ntg
) {
24 for ( th
= tg
-> hosts
; th
; th
= nth
) {
36 trustgroup
* tg_getbyid ( unsigned int id
) {
39 for ( tg
= tglist
; tg
; tg
= tg
-> next
)
46 void th_free ( trusthost
* th
) {
47 nsfree ( POOL_TRUSTS
, th
);
50 static void th_updatechildren ( trusthost
* th
) {
51 trusthost
* nth
= NULL
;
56 nth
= th_getnextchildbyhost ( th
, nth
);
60 nth
-> nextbychild
= th
-> children
;
65 void th_linktree ( void ) {
70 for ( tg
= tglist
; tg
; tg
= tg
-> next
)
71 for ( th
= tg
-> hosts
; th
; th
= th
-> next
)
72 th
-> parent
= th_getsmallestsupersetbyhost ( th
-> ip
, th
-> mask
);
74 for ( tg
= tglist
; tg
; tg
= tg
-> next
)
75 for ( th
= tg
-> hosts
; th
; th
= th
-> next
)
77 th_updatechildren ( th
-> parent
);
80 trusthost
* th_add ( trustgroup
* tg
, unsigned int id
, char * host
, unsigned int maxusage
, time_t lastseen
) {
84 if (! trusts_str2cidr ( host
, & ip
, & mask
))
87 th
= nsmalloc ( POOL_TRUSTS
, sizeof ( trusthost
));
92 th
-> maxusage
= maxusage
;
93 th
-> lastseen
= lastseen
;
106 th
-> next
= tg
-> hosts
;
112 void tg_free ( trustgroup
* tg
) {
113 triggerhook ( HOOK_TRUSTS_LOSTGROUP
, tg
);
115 freesstring ( tg
-> name
);
116 freesstring ( tg
-> createdby
);
117 freesstring ( tg
-> contact
);
118 freesstring ( tg
-> comment
);
119 nsfree ( POOL_TRUSTS
, tg
);
122 trustgroup
* tg_add ( unsigned int id
, char * name
, unsigned int trustedfor
, int mode
, unsigned int maxperident
, unsigned int maxusage
, time_t expires
, time_t lastseen
, time_t lastmaxuserreset
, char * createdby
, char * contact
, char * comment
) {
123 trustgroup
* tg
= nsmalloc ( POOL_TRUSTS
, sizeof ( trustgroup
));
127 tg
-> name
= getsstring ( name
, TRUSTNAMELEN
);
128 tg
-> createdby
= getsstring ( createdby
, NICKLEN
);
129 tg
-> contact
= getsstring ( contact
, CONTACTLEN
);
130 tg
-> comment
= getsstring ( comment
, COMMENTLEN
);
131 if (! tg
-> name
|| ! tg
-> createdby
|| ! tg
-> contact
|| ! tg
-> comment
) {
137 tg
-> trustedfor
= trustedfor
;
139 tg
-> maxperident
= maxperident
;
140 tg
-> maxusage
= maxusage
;
141 tg
-> expires
= expires
;
142 tg
-> lastseen
= lastseen
;
143 tg
-> lastmaxuserreset
= lastmaxuserreset
;
150 memset ( tg
-> exts
, 0 , sizeof ( tg
-> exts
));
155 triggerhook ( HOOK_TRUSTS_NEWGROUP
, tg
);
160 trusthost
* th_getbyhost ( uint32_t ip
) {
162 trusthost
* th
, * result
= NULL
;
165 for ( tg
= tglist
; tg
; tg
= tg
-> next
) {
166 for ( th
= tg
-> hosts
; th
; th
= th
-> next
) {
167 if (( ip
& th
-> mask
) == th
-> ip
) {
168 if (! result
|| ( th
-> mask
> mask
)) {
179 trusthost
* th_getbyhostandmask ( uint32_t ip
, uint32_t mask
) {
183 for ( tg
= tglist
; tg
; tg
= tg
-> next
)
184 for ( th
= tg
-> hosts
; th
; th
= th
-> next
)
185 if (( th
-> ip
== ip
) && ( th
-> mask
== mask
))
191 /* returns the ip with the smallest prefix that is still a superset of the given host */
192 trusthost
* th_getsmallestsupersetbyhost ( uint32_t ip
, uint32_t mask
) {
194 trusthost
* th
, * result
= NULL
;
197 for ( tg
= tglist
; tg
; tg
= tg
-> next
) {
198 for ( th
= tg
-> hosts
; th
; th
= th
-> next
) {
199 if ( th
-> ip
== ( ip
& th
-> mask
)) {
200 if (( th
-> mask
< mask
) && (! result
|| ( th
-> mask
> smask
))) {
211 /* returns the first ip that is a subset it comes across */
212 trusthost
* th_getsubsetbyhost ( uint32_t ip
, uint32_t mask
) {
216 for ( tg
= tglist
; tg
; tg
= tg
-> next
)
217 for ( th
= tg
-> hosts
; th
; th
= th
-> next
)
218 if (( th
-> ip
& mask
) == ip
)
225 /* NOT reentrant obviously */
226 static trusthost
* th_getnextchildbyhost ( trusthost
* orig
, trusthost
* th
) {
231 for ( tg
= tglist
; tg
; tg
= tg
-> next
) {
237 /* INVARIANT: tg => th */
241 if ( th
-> parent
== orig
)
251 th
= th
-> group
-> next
-> hosts
;
254 if ( th
-> parent
== orig
)
259 void th_getsuperandsubsets ( uint32_t ip
, uint32_t mask
, trusthost
** superset
, trusthost
** subset
) {
260 * superset
= th_getsmallestsupersetbyhost ( ip
, mask
);
261 * subset
= th_getsubsetbyhost ( ip
, mask
);
264 void trusts_flush ( void ) {
267 time_t t
= time ( NULL
);
269 for ( tg
= tglist
; tg
; tg
= tg
-> next
) {
273 tg_dbupdatecounts ( tg
);
275 for ( th
= tg
-> hosts
; th
; th
= th
-> next
) {
279 th_dbupdatecounts ( th
);
284 trustgroup
* tg_strtotg ( char * name
) {
290 id
= strtoul (& name
[ 1 ], NULL
, 10 );
294 for ( tg
= tglist
; tg
; tg
= tg
-> next
)
299 for ( tg
= tglist
; tg
; tg
= tg
-> next
)
300 if (! match ( name
, tg
-> name
-> content
))
303 id
= strtoul ( name
, NULL
, 10 );
308 for ( tg
= tglist
; tg
; tg
= tg
-> next
)
315 void th_adjusthosts ( trusthost
* th
, trusthost
* superset
, trusthost
* subset
) {
317 * First and foremost, CIDR doesn't allow hosts to cross boundaries, i.e. everything with a smaller prefix
318 * is entirely contained with the prefix that is one smaller.
319 * e.g. 0.0.0.0/23, 0.0.0.128/23, you can't have a single prefix for 0.0.0.64-0.0.0.192, instead
320 * you have two, 0.0.0.64/26 and 0.0.0.128/26.
322 * This makes the code MUCH easier as the entire thing is one huge set/tree.
325 * 1: host isn't covered by any existing hosts.
326 * 2: host is covered by a less specific one only, e.g. adding 0.0.0.1/32, while 0.0.0.0/24 already exists.
327 * 3: host is covered by a more specific one only, e.g. adding 0.0.0.0/24 while 0.0.0.1/32 already exists
328 * (note there might be more than one more specific host, e.g. 0.0.0.1/32 and 0.0.0.2/32).
329 * 4: covered by more and less specific cases, e.g. adding 0.0.0.0/24 to: { 0.0.0.1/32, 0.0.0.2/32, 0.0.0.0/16 }.
334 * !superset && !subset
336 * Scan through the host hash and add any clients which match our host, this is exactly the same as case 3
337 * but without needing to check (though checking doesn't hurt), so we'll just use the code for that.
342 * superset && !subset
344 * We have the less specific host in 'superset', we know it is the only one so pull out clients in it's
345 * ->users list matching our new host.
346 * No need to look for extra hosts in the main nick hash as they're all covered already.
351 * !superset && subset
353 * We have one host in 'subset', but there might be more than one, we don't care though!
354 * We can scan the entire host hash and pull out any hosts that match us and don't have
355 * a trust group already, this ignores any with a more specific prefix.
362 * Here we first fix up the ones less specific then us, so we just perform what we did for case 2,
363 * then we perform what we did for case 3.
372 * if(1 || 3 || 4): DO 3
375 /* we let the compiler do the boolean minimisation for clarity reasons */
377 if (( superset
&& ! subset
) || ( superset
&& subset
)) { /* cases 2 and 4 */
379 for ( np
= superset
-> users
; np
; np
= nnp
) {
380 nnp
= nextbytrust ( np
);
381 if (( irc_in_addr_v4_to_int (& np
-> p_ipaddr
) & th
-> mask
) == th
-> ip
) {
382 trusts_lostnick ( np
, 1 );
383 trusts_newnick ( np
, 1 );
388 if ((! superset
&& ! subset
) || (! superset
&& subset
) || ( superset
&& subset
)) { /* cases 1, 3 and 4 */
392 for ( i
= 0 ; i
< NICKHASHSIZE
; i
++)
393 for ( np
= nicktable
[ i
]; np
; np
= np
-> next
)
394 if (! gettrusthost ( np
) && (( irc_in_addr_v4_to_int (& np
-> p_ipaddr
) & th
-> mask
) == th
-> ip
))
395 trusts_newnick ( np
, 1 );
399 unsigned int nexttgmarker ( void ) {
400 static unsigned int tgmarker
= 0 ;
405 /* If we wrapped to zero, zap the marker on all groups */
406 for ( tg
= tglist
; tg
; tg
= tg
-> next
)
415 unsigned int nextthmarker ( void ) {
416 static unsigned int thmarker
= 0 ;
422 /* If we wrapped to zero, zap the marker on all hosts */
423 for ( tg
= tglist
; tg
; tg
= tg
-> next
)
424 for ( th
= tg
-> hosts
; th
; th
= th
-> next
)