]>
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"
25 gline
* glinelist
= 0, *glinelistnonnode
= 0;
33 <prefix> GL <target> [!][+|-|>|<]<mask> [<expiration>] [<lastmod>]
34 [<lifetime>] [:<reason>]
39 gl_nodeext
= registernodeext("gline");
42 Error("gline", ERR_FATAL
, "Could not register a required node extension (gline)");
46 registerserverhandler("GL", &handleglinemsg
, 6);
48 /* send reburst command to get glines from before we registered handler */
49 irc_send("%s RB G", mynumeric
->content
);
55 deregisterserverhandler("GL", &handleglinemsg
);
57 for (gl
=glinelist
;gl
;gl
=ngl
) {
64 releasenodeext(gl_nodeext
);
67 int gline_setnick(nick
*np
, int duration
, char *reason
) {
71 int gline_setnode(patricia_node_t
*node
) {
75 int gline_setmask(char *mask
, int duration
, char *reason
) {
79 gline
* gline_add(long creatornum
, sstring
*creator
, char *mask
, char *reason
, time_t expires
, time_t lastmod
, time_t lifetime
) {
81 char glineiddata
[1024];
83 if ( !(gl
=gline_processmask(mask
))) { /* sets up nick,user,host,node and flags */
84 /* couldn't process gline mask */
85 Error("gline", ERR_WARNING
, "Tried to add malformed G-Line %s!", mask
);
89 gl
->creator
= creator
;
90 gl
->numeric
= creatornum
;
92 /* it's not unreasonable to assume gline is active, if we're adding a deactivated gline, we can remove this later */
93 gl
->flags
= GLINE_ACTIVE
;
97 snprintf(glineiddata
, sizeof(glineiddata
), "gline %s %s", mask
, reason
);
98 gl
->glineid
= crc32(glineiddata
);
100 gl
->reason
= getsstring(reason
, 255); /*TODO@@@ */
101 gl
->expires
= expires
;
102 gl
->lastmod
= lastmod
;
103 gl
->lifetime
= lifetime
;
105 /* Storage of glines */
106 /* ipbased glines are stored at node->ext[gl_nodeext]
107 * other glines are stored in seperate linked list (for now) */
108 if (gl
->flags
& GLINE_IPMASK
) {
109 gl
->nextbynode
= gl
->node
->exts
[gl_nodeext
];
110 gl
->node
->exts
[gl_nodeext
] = gl
;
112 gl
->nextbynonnode
= glinelistnonnode
;
113 glinelistnonnode
= gl
;
116 gl
->next
= glinelist
;
122 /* returns 1 on success, 0 on a bad mask */
123 gline
* gline_processmask(char *mask
) {
124 /* populate gl-> user,host,node,nick and set appropriate flags */
126 int foundat
=-1,foundbang
=-1;
129 struct irc_in_addr sin
;
133 if (!(gl
= newgline())) {
134 Error("gline", ERR_ERROR
, "Failed to allocate new gline");
143 gl
->flags
|= GLINE_BADCHAN
;
144 gl
->user
= getsstring(mask
, CHANNELLEN
);
149 gl
->flags
|= GLINE_REALNAME
;
152 Error("gline", ERR_WARNING
, "Tried to add malformed G-Line %s!", mask
);
155 gl
->user
= getsstring(mask
,REALLEN
);
158 /* Default case of some host/ip/cidr mask */
159 for (i
=(len
-1);i
>=0;i
--) {
162 if ((len
-i
)-1 > HOSTLEN
) {
165 } else if (i
==(len
-1)) {
166 /* no host supplied aka gline ends @ */
168 } else if (i
==(len
-2) && mask
[i
+1]=='*') {
169 /* Special case: "@*" */
170 gl
->flags
|= GLINE_HOSTANY
;
173 if (ipmask_parse(&mask
[i
+1], &sin
, &bits
) == 0) {
174 /* we have some host string */
175 gl
->host
=getsstring(&mask
[i
+1],HOSTLEN
);
177 gl
->flags
|= GLINE_HOSTMASK
;
179 gl
->flags
|= GLINE_HOSTEXACT
;
182 /* we have a / so cidr gline */
183 Error("gline", ERR_WARNING
, "CIDR: %s", &mask
[i
+1]);
184 gl
->node
= refnode(iptree
, &sin
, bits
);
185 gl
->flags
|= GLINE_IPMASK
;
190 } else if (mask
[i
]=='?' || mask
[i
]=='*') {
191 if (!foundwild
) /* Mark last wildcard in string */
196 /*TODO set hostexact/hostmask */
198 /* If there wasn't an @, this ban matches any host */
200 gl
->flags
|= GLINE_HOSTANY
;
205 for (i
=0;i
<foundat
;i
++) {
208 /* Invalid mask: nick is empty */
209 gl
->flags
|= GLINE_NICKNULL
;
211 } else if (i
==1 && mask
[0]=='*') {
212 /* matches any nick */
213 gl
->flags
|= GLINE_NICKANY
;
217 /* too long: just take the first NICKLEN chars */
218 gl
->nick
=getsstring(mask
,NICKLEN
);
220 gl
->nick
=getsstring(mask
,i
);
223 gl
->flags
|= GLINE_NICKMASK
;
225 gl
->flags
|= GLINE_NICKEXACT
;
229 } else if (mask
[i
]=='?' || mask
[i
]=='*') {
237 /* We didn't find a !, what we do now depends on what happened
240 /* A gline with no ! or @ is treated as a nick ban only */
241 /* Note that we've special-cased "*" at the top, so we can only
242 * hit the MASK or EXACT case here. */
244 gl
->nick
=getsstring(mask
,NICKLEN
);
246 gl
->nick
=getsstring(mask
,len
);
249 gl
->flags
|= GLINE_NICKMASK
;
251 gl
->flags
|= GLINE_NICKEXACT
;
253 gl
->flags
|= (GLINE_USERANY
| GLINE_HOSTANY
);
257 /* A gline with @ only is treated as user@host */
259 gl
->flags
|= GLINE_NICKANY
;
264 /* We found an @, so everything between foundbang+1 and foundat-1 is supposed to be ident */
265 /* This is true even if there was no !.. */
266 if (foundat
==(foundbang
+1)) {
267 /* empty ident matches nothing */ /*@@@TODO: * for glines? */
268 gl
->flags
|= (/*GLINE_INVALID |*/ GLINE_USERNULL
);
270 } else if (foundat
- foundbang
- 1 > USERLEN
) {
271 /* It's too long.. */
273 } else if ((foundat
- foundbang
- 1 == 1) && mask
[foundbang
+1]=='*') {
275 gl
->flags
|= GLINE_USERANY
;
277 gl
->user
=getsstring(&mask
[foundbang
+1],(foundat
-foundbang
-1));
278 if (strchr(gl
->user
->content
,'*') || strchr(gl
->user
->content
,'?'))
279 gl
->flags
|= GLINE_USERMASK
;
281 gl
->flags
|= GLINE_USEREXACT
;
283 /* Username part can't contain an @ */
284 if (gl
->user
&& strchr(gl
->user
->content
,'@')) {
285 //gl->flags |= CHANBAN_INVALID;
289 assert(gl
->flags
& (GLINE_USEREXACT
| GLINE_USERMASK
| GLINE_USERANY
| GLINE_USERNULL
));
290 assert(gl
->flags
& (GLINE_NICKEXACT
| GLINE_NICKMASK
| GLINE_NICKANY
| GLINE_NICKNULL
));
291 assert(gl
->flags
& (GLINE_HOSTEXACT
| GLINE_HOSTMASK
| GLINE_HOSTANY
| GLINE_HOSTNULL
| GLINE_IPMASK
));
296 gline
*gline_find( char *mask
) {
300 if( !(globalgline
=gline_processmask(mask
))) {
301 /* gline mask couldn't be processed */
305 if (globalgline
->flags
& GLINE_IPMASK
) {
306 gl
= globalgline
->node
->exts
[gl_nodeext
];
308 if ( gline_match( globalgline
, gl
) ) {
309 freegline(globalgline
);
317 if ( gline_match( globalgline
, gl
) ) {
318 freegline(globalgline
);
321 gl
= gl
->nextbynonnode
;
324 freegline(globalgline
);
328 /* returns non-zero on match */
329 int gline_match ( gline
*gla
, gline
*glb
) {
330 if ((!gla
->nick
&& glb
->nick
) || (gla
->nick
&& !glb
->nick
))
333 if (gla
->nick
&& ircd_strcmp(gla
->nick
->content
,glb
->nick
->content
))
336 if ((!gla
->user
&& glb
->user
) || (gla
->user
&& !glb
->user
))
339 if (gla
->user
&& ircd_strcmp(gla
->user
->content
,glb
->user
->content
))
342 if ((!gla
->host
&& glb
->host
) || (gla
->host
&& !glb
->host
))
345 if (gla
->host
&& ircd_strcmp(gla
->host
->content
,glb
->host
->content
))
348 /* TODO @@@ match bits flags */
352 void gline_send(gline
*gl
) {