]>
jfr.im git - irc/quakenet/newserv.git/blob - channel/channelbans.c
8 #include "../nick/nick.h"
9 #include "../lib/irc_string.h"
10 #include "../irc/irc_config.h"
11 #include "../irc/irc.h"
14 * nickmatchban_visible:
15 * Returns true iff the supplied nick* matches the supplied ban*
16 * Doesn't check "invisible" things like true hosts and IPs for
19 * copy & pasted this, touch and go whether this was a good idea.
22 int nickmatchban_visible(nick
*np
, chanban
*bp
) {
24 char fakehost
[HOSTLEN
+1];
27 /* Don't waste time on invalid bans */
28 if (bp
->flags
& CHANBAN_INVALID
)
31 /* nick/ident section: return 0 (no match) if they don't match */
33 /* Determine the visible ident for sethost users. Don't test the real one. */
34 if (IsSetHost(np
) && np
->shident
&& *np
->shident
->content
)
35 visibleident
=np
->shident
->content
;
37 visibleident
=np
->ident
;
39 if (bp
->flags
& CHANBAN_USEREXACT
&& ircd_strcmp(visibleident
,bp
->user
->content
))
42 if (bp
->flags
& CHANBAN_NICKEXACT
&& ircd_strcmp(np
->nick
,bp
->nick
->content
))
45 if (bp
->flags
& CHANBAN_USERMASK
&& !match2strings(bp
->user
->content
,visibleident
))
48 if (bp
->flags
& CHANBAN_NICKMASK
&& !match2strings(bp
->nick
->content
,np
->nick
))
51 /* host section. Return 1 (match) if they do match
52 * Note that if user or ident was specified, they've already been checked
55 if (bp
->flags
& CHANBAN_HOSTANY
)
58 if ((bp
->flags
& CHANBAN_CIDR
) && (bp
->flags
& CHANBAN_HOSTEXACT
)) {
62 /* CIDR bans don't visibly match sethosted users */
63 if (IsSetHost(np
) || (IsAccount(np
) && IsHideHost(np
)))
66 /* CIDR bans don't match IPv6 hosts */
67 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
70 /* Extract the client's IP address into a usable format */
71 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
72 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
74 if ((cip
& bp
->mask
) == bp
->ipaddr
)
77 return 0; /* A CIDR ban won't match any other way */
80 if (bp
->flags
& CHANBAN_IP
) {
81 /* IP bans don't match sethosted users */
82 if (IsSetHost(np
) || (IsAccount(np
) && IsHideHost(np
)))
85 if (bp
->flags
& CHANBAN_HOSTEXACT
) {
86 /* If it's an exact IP ban we can compare it numerically */
90 /* Well, it won't match if it's not an IPv4 host */
91 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
94 /* Extract the client's IP address into a usable format */
95 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
96 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
101 /* It's not an exact IP ban so let's generate the string */
102 ipstring
=IPtostr(np
->p_ipaddr
);
104 if (bp
->flags
& CHANBAN_HOSTMASK
&& match2strings(bp
->host
->content
,ipstring
))
108 /* Hostname bans need to be checked against +x host, +h host (if set)
109 * and actual host. Note that the +x host is only generated (and checked) if it's
110 * possible for the ban to match a hidden host.. */
112 if ((bp
->flags
& CHANBAN_HIDDENHOST
) && IsAccount(np
)) {
113 sprintf(fakehost
,"%s.%s",np
->authname
, HIS_HIDDENHOST
);
115 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
116 !ircd_strcmp(fakehost
, bp
->host
->content
))
119 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
120 match2strings(bp
->host
->content
, fakehost
))
125 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
126 !ircd_strcmp(np
->sethost
->content
, bp
->host
->content
))
129 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
130 match2strings(bp
->host
->content
, np
->sethost
->content
))
134 /* If the user is +h or +rx don't check their real host */
135 if (IsSetHost(np
) || (IsHideHost(np
) && IsAccount(np
)))
138 if (bp
->flags
& CHANBAN_HOSTEXACT
&& !ircd_strcmp(np
->host
->name
->content
,bp
->host
->content
))
141 if (bp
->flags
& CHANBAN_HOSTMASK
&& match2strings(bp
->host
->content
,np
->host
->name
->content
))
150 * Returns true iff the supplied nick* matches the supplied ban*
153 int nickmatchban(nick
*np
, chanban
*bp
) {
154 const char *ipstring
;
155 char fakehost
[HOSTLEN
+1];
157 /* nick/ident section: return 0 (no match) if they don't match */
159 if (bp
->flags
& CHANBAN_INVALID
)
162 if (bp
->flags
& CHANBAN_USEREXACT
&&
163 ircd_strcmp(np
->ident
,bp
->user
->content
) &&
164 (!IsSetHost(np
) || !np
->shident
||
165 ircd_strcmp(np
->shident
->content
,bp
->user
->content
)))
168 if (bp
->flags
& CHANBAN_NICKEXACT
&& ircd_strcmp(np
->nick
,bp
->nick
->content
))
171 if (bp
->flags
& CHANBAN_USERMASK
&&
172 !match2strings(bp
->user
->content
,np
->ident
) &&
173 (!IsSetHost(np
) || !np
->shident
||
174 !match2strings(bp
->user
->content
, np
->shident
->content
)))
177 if (bp
->flags
& CHANBAN_NICKMASK
&& !match2strings(bp
->nick
->content
,np
->nick
))
180 /* host section. Return 1 (match) if they do match
181 * Note that if user or ident was specified, they've already been checked
184 if (bp
->flags
& CHANBAN_HOSTANY
)
187 if ((bp
->flags
& CHANBAN_CIDR
) && (bp
->flags
& CHANBAN_HOSTEXACT
)) {
191 /* CIDR bans don't match IPv6 hosts */
192 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
195 /* Extract the client's IP address into a usable format */
196 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
197 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
199 if ((cip
& bp
->mask
) == bp
->ipaddr
)
202 return 0; /* A CIDR ban won't match any other way */
205 if (bp
->flags
& CHANBAN_IP
) {
206 if (bp
->flags
& CHANBAN_HOSTEXACT
) {
207 /* If it's an exact IP ban we can compare it numerically */
211 /* Well, it won't match if it's not an IPv4 host */
212 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
215 /* Extract the client's IP address into a usable format */
216 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
217 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
222 /* It's not an exact IP ban so let's generate the string */
223 ipstring
=IPtostr(np
->p_ipaddr
);
225 if (bp
->flags
& CHANBAN_HOSTMASK
&& match2strings(bp
->host
->content
,ipstring
))
229 /* Hostname bans need to be checked against +x host, +h host (if set)
230 * and actual host. Note that the +x host is only generated (and checked) if it's
231 * possible for the ban to match a hidden host.. */
233 if ((bp
->flags
& CHANBAN_HIDDENHOST
) && IsAccount(np
)) {
234 sprintf(fakehost
,"%s.%s",np
->authname
, HIS_HIDDENHOST
);
236 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
237 !ircd_strcmp(fakehost
, bp
->host
->content
))
240 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
241 match2strings(bp
->host
->content
, fakehost
))
246 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
247 !ircd_strcmp(np
->sethost
->content
, bp
->host
->content
))
250 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
251 match2strings(bp
->host
->content
, np
->sethost
->content
))
255 if (bp
->flags
& CHANBAN_HOSTEXACT
&& !ircd_strcmp(np
->host
->name
->content
,bp
->host
->content
))
258 if (bp
->flags
& CHANBAN_HOSTMASK
&& match2strings(bp
->host
->content
,np
->host
->name
->content
))
267 * Returns true iff the supplied nick* is banned on the supplied chan*
269 * Also nickbanned_visible - doesn't violate privacy by checking hidden
270 * hosts and idents. Factored into one function to reduce copy&paste.
272 static int nickbanned_real(nick
*np
, channel
*cp
, int (*cmpfunc
)(nick
*, chanban
*)) {
275 for (cbp
=cp
->bans
;cbp
;cbp
=cbp
->next
) {
283 int nickbanned(nick
*np
, channel
*cp
) {
284 return nickbanned_real(np
,cp
,nickmatchban
);
287 int nickbanned_visible(nick
*np
, channel
*cp
) {
288 return nickbanned_real(np
,cp
,nickmatchban_visible
);
293 * Set the specified ban; if it completely encloses any existing bans
296 * Returns 1 if the ban was set, or 0 if the ban was not set because an
297 * existing ban overlapped it.
300 int setban(channel
*cp
, const char *ban
) {
301 chanban
**cbh
,*cbp
,*cbp2
;
305 /* Don't set our ban if something encloses it */
306 for (cbp2
=cp
->bans
;cbp2
;cbp2
=cbp2
->next
) {
307 if (banoverlap(cbp2
, cbp
)) {
308 /* This ban overlaps the one we are adding. Abort. */
314 /* Remove enclosed bans first */
315 for (cbh
=&(cp
->bans
);*cbh
;) {
316 if (banoverlap(cbp
,*cbh
)) {
320 /* Break out of the loop if we just deleted the last ban */
325 cbh
=(chanban
**)&((*cbh
)->next
);
329 /* Now set the new ban */
330 cbp
->next
=(struct chanban
*)cp
->bans
;
338 * Remove the specified ban iff an exact match is found
339 * Returns 1 if the ban was cleared, 0 if the ban didn't exist.
340 * If "optional" is 0 and the ban didn't exist, flags an error
343 int clearban(channel
*cp
, const char *ban
, int optional
) {
344 chanban
**cbh
,*cbp
,*cbp2
;
353 for (cbh
=&(cp
->bans
);*cbh
;cbh
=(chanban
**)&((*cbh
)->next
)) {
354 if (banequal(cbp
,*cbh
)) {
363 if (!found
&& !optional
) {
364 Error("channel",ERR_DEBUG
,"Couldn't remove ban %s from %s. Dumping banlist:",ban
,cp
->index
->name
->content
);
365 for (cbp2
=cp
->bans
;cbp2
;cbp2
=cbp2
->next
) {
366 Error("channel",ERR_DEBUG
,"%s %d %s",cp
->index
->name
->content
, i
++, bantostringdebug(cbp2
));
377 * Just free all the bans on the channel
380 void clearallbans(channel
*cp
) {
383 for (cbp
=cp
->bans
;cbp
;cbp
=ncbp
) {
384 ncbp
=(chanban
*)cbp
->next
;