]>
jfr.im git - irc/quakenet/newserv.git/blob - gline/gline.c
7 #include <sys/socket.h>
8 #include <netinet/in.h>
11 #include "../control/control.h"
12 #include "../nick/nick.h"
13 #include "../localuser/localuserchannel.h"
14 #include "../core/hooks.h"
15 #include "../server/server.h"
16 #include "../parser/parser.h"
17 #include "../core/schedule.h"
18 #include "../lib/array.h"
19 #include "../lib/base64.h"
20 #include "../lib/irc_string.h"
21 #include "../lib/splitline.h"
22 #include "../core/nsmalloc.h"
26 gline
* glinelist
= 0, *glinelistnonnode
= 0;
34 <prefix> GL <target> [!][+|-|>|<]<mask> [<expiration>] [<lastmod>]
35 [<lifetime>] [:<reason>]
40 gl_nodeext
= registernodeext("gline");
42 if ( gl_nodeext
== -1 ) {
43 Error("gline", ERR_FATAL
, "Could not register a required node extension (gline)");
47 registerserverhandler("GL", &handleglinemsg
, 6);
49 /* send reburst command to get glines from before we registered handler */
50 irc_send("%s RB G", mynumeric
->content
);
56 deregisterserverhandler("GL", &handleglinemsg
);
58 for (gl
=glinelist
;gl
;gl
=ngl
) {
65 releasenodeext(gl_nodeext
);
67 nsfreeall(POOL_GLINE
);
70 int gline_setnick(nick
*np
, int duration
, char *reason
) {
74 int gline_setnode(patricia_node_t
*node
) {
78 int gline_setmask(char *mask
, int duration
, char *reason
) {
82 gline
* gline_add(long creatornum
, sstring
*creator
, char *mask
, char *reason
, time_t expires
, time_t lastmod
, time_t lifetime
) {
84 char glineiddata
[1024];
86 if ( !(gl
=gline_processmask(mask
))) { /* sets up nick,user,host,node and flags */
87 /* couldn't process gline mask */
88 Error("gline", ERR_WARNING
, "Tried to add malformed G-Line %s!", mask
);
92 gl
->creator
= creator
;
93 gl
->numeric
= creatornum
;
95 /* it's not unreasonable to assume gline is active, if we're adding a deactivated gline, we can remove this later */
96 gl
->flags
= GLINE_ACTIVE
;
100 snprintf(glineiddata
, sizeof(glineiddata
), "gline %s %s", mask
, reason
);
101 gl
->glineid
= crc32(glineiddata
);
103 gl
->reason
= getsstring(reason
, 255); /*TODO@@@ */
104 gl
->expires
= expires
;
105 gl
->lastmod
= lastmod
;
106 gl
->lifetime
= lifetime
;
108 /* Storage of glines */
109 /* ipbased glines are stored at node->ext[gl_nodeext]
110 * other glines are stored in seperate linked list (for now) */
111 if (gl
->flags
& GLINE_IPMASK
) {
112 gl
->nextbynode
= gl
->node
->exts
[gl_nodeext
];
113 gl
->node
->exts
[gl_nodeext
] = gl
;
115 gl
->nextbynonnode
= glinelistnonnode
;
116 glinelistnonnode
= gl
;
119 gl
->next
= glinelist
;
125 /* returns 1 on success, 0 on a bad mask */
126 gline
* gline_processmask(char *mask
) {
127 /* populate gl-> user,host,node,nick and set appropriate flags */
129 int foundat
=-1,foundbang
=-1;
132 struct irc_in_addr sin
;
136 if (!(gl
= newgline())) {
137 Error("gline", ERR_ERROR
, "Failed to allocate new gline");
146 gl
->flags
|= GLINE_BADCHAN
;
147 gl
->user
= getsstring(mask
, CHANNELLEN
);
152 gl
->flags
|= GLINE_REALNAME
;
155 Error("gline", ERR_WARNING
, "Tried to add malformed G-Line %s!", mask
);
158 gl
->user
= getsstring(mask
,REALLEN
);
161 /* Default case of some host/ip/cidr mask */
162 for (i
=(len
-1);i
>=0;i
--) {
165 if ((len
-i
)-1 > HOSTLEN
) {
168 } else if (i
==(len
-1)) {
169 /* no host supplied aka gline ends @ */
171 } else if (i
==(len
-2) && mask
[i
+1]=='*') {
172 /* Special case: "@*" */
173 gl
->flags
|= GLINE_HOSTANY
;
176 if (ipmask_parse(&mask
[i
+1], &sin
, &bits
) == 0) {
177 /* we have some host string */
178 gl
->host
=getsstring(&mask
[i
+1],HOSTLEN
);
180 gl
->flags
|= GLINE_HOSTMASK
;
182 gl
->flags
|= GLINE_HOSTEXACT
;
185 /* we have a / so cidr gline */
186 Error("gline", ERR_WARNING
, "CIDR: %s", &mask
[i
+1]);
187 gl
->node
= refnode(iptree
, &sin
, bits
);
188 gl
->flags
|= GLINE_IPMASK
;
193 } else if (mask
[i
]=='?' || mask
[i
]=='*') {
194 if (!foundwild
) /* Mark last wildcard in string */
199 /*TODO set hostexact/hostmask */
201 /* If there wasn't an @, this ban matches any host */
203 gl
->flags
|= GLINE_HOSTANY
;
208 for (i
=0;i
<foundat
;i
++) {
211 /* Invalid mask: nick is empty */
212 gl
->flags
|= GLINE_NICKNULL
;
214 } else if (i
==1 && mask
[0]=='*') {
215 /* matches any nick */
216 gl
->flags
|= GLINE_NICKANY
;
220 /* too long: just take the first NICKLEN chars */
221 gl
->nick
=getsstring(mask
,NICKLEN
);
223 gl
->nick
=getsstring(mask
,i
);
226 gl
->flags
|= GLINE_NICKMASK
;
228 gl
->flags
|= GLINE_NICKEXACT
;
232 } else if (mask
[i
]=='?' || mask
[i
]=='*') {
240 /* We didn't find a !, what we do now depends on what happened
243 /* A gline with no ! or @ is treated as a nick ban only */
244 /* Note that we've special-cased "*" at the top, so we can only
245 * hit the MASK or EXACT case here. */
247 gl
->nick
=getsstring(mask
,NICKLEN
);
249 gl
->nick
=getsstring(mask
,len
);
252 gl
->flags
|= GLINE_NICKMASK
;
254 gl
->flags
|= GLINE_NICKEXACT
;
256 gl
->flags
|= (GLINE_USERANY
| GLINE_HOSTANY
);
260 /* A gline with @ only is treated as user@host */
262 gl
->flags
|= GLINE_NICKANY
;
267 /* We found an @, so everything between foundbang+1 and foundat-1 is supposed to be ident */
268 /* This is true even if there was no !.. */
269 if (foundat
==(foundbang
+1)) {
270 /* empty ident matches nothing */ /*@@@TODO: * for glines? */
271 gl
->flags
|= (/*GLINE_INVALID |*/ GLINE_USERNULL
);
273 } else if (foundat
- foundbang
- 1 > USERLEN
) {
274 /* It's too long.. */
276 } else if ((foundat
- foundbang
- 1 == 1) && mask
[foundbang
+1]=='*') {
278 gl
->flags
|= GLINE_USERANY
;
280 gl
->user
=getsstring(&mask
[foundbang
+1],(foundat
-foundbang
-1));
281 if (strchr(gl
->user
->content
,'*') || strchr(gl
->user
->content
,'?'))
282 gl
->flags
|= GLINE_USERMASK
;
284 gl
->flags
|= GLINE_USEREXACT
;
286 /* Username part can't contain an @ */
287 if (gl
->user
&& strchr(gl
->user
->content
,'@')) {
288 //gl->flags |= CHANBAN_INVALID;
292 assert(gl
->flags
& (GLINE_USEREXACT
| GLINE_USERMASK
| GLINE_USERANY
| GLINE_USERNULL
));
293 assert(gl
->flags
& (GLINE_NICKEXACT
| GLINE_NICKMASK
| GLINE_NICKANY
| GLINE_NICKNULL
));
294 assert(gl
->flags
& (GLINE_HOSTEXACT
| GLINE_HOSTMASK
| GLINE_HOSTANY
| GLINE_HOSTNULL
| GLINE_IPMASK
));
299 gline
*gline_find( char *mask
) {
303 if( !(globalgline
=gline_processmask(mask
))) {
304 /* gline mask couldn't be processed */
308 if (globalgline
->flags
& GLINE_IPMASK
) {
309 gl
= globalgline
->node
->exts
[gl_nodeext
];
311 if ( gline_match( globalgline
, gl
) ) {
312 freegline(globalgline
);
320 if ( gline_match( globalgline
, gl
) ) {
321 freegline(globalgline
);
324 gl
= gl
->nextbynonnode
;
327 freegline(globalgline
);
331 /* returns non-zero on match */
332 int gline_match ( gline
*gla
, gline
*glb
) {
333 if ((!gla
->nick
&& glb
->nick
) || (gla
->nick
&& !glb
->nick
))
336 if (gla
->nick
&& ircd_strcmp(gla
->nick
->content
,glb
->nick
->content
))
339 if ((!gla
->user
&& glb
->user
) || (gla
->user
&& !glb
->user
))
342 if (gla
->user
&& ircd_strcmp(gla
->user
->content
,glb
->user
->content
))
345 if ((!gla
->host
&& glb
->host
) || (gla
->host
&& !glb
->host
))
348 if (gla
->host
&& ircd_strcmp(gla
->host
->content
,glb
->host
->content
))
351 /* TODO @@@ match bits flags */
355 void gline_send(gline
*gl
) {