]>
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
) {
23 char fakehost
[HOSTLEN
+1];
26 /* Don't waste time on invalid bans */
27 if (bp
->flags
& CHANBAN_INVALID
)
30 /* nick/ident section: return 0 (no match) if they don't match */
32 /* Determine the visible ident for sethost users. Don't test the real one. */
33 if (IsSetHost(np
) && np
->shident
&& *np
->shident
->content
)
34 visibleident
=np
->shident
->content
;
36 visibleident
=np
->ident
;
38 if (bp
->flags
& CHANBAN_USEREXACT
&& ircd_strcmp(visibleident
,bp
->user
->content
))
41 if (bp
->flags
& CHANBAN_NICKEXACT
&& ircd_strcmp(np
->nick
,bp
->nick
->content
))
44 if (bp
->flags
& CHANBAN_USERMASK
&& !match2strings(bp
->user
->content
,visibleident
))
47 if (bp
->flags
& CHANBAN_NICKMASK
&& !match2strings(bp
->nick
->content
,np
->nick
))
50 /* host section. Return 1 (match) if they do match
51 * Note that if user or ident was specified, they've already been checked
54 if (bp
->flags
& CHANBAN_HOSTANY
)
57 if ((bp
->flags
& CHANBAN_CIDR
) && (bp
->flags
& CHANBAN_HOSTEXACT
)) {
61 /* CIDR bans don't visibly match sethosted users */
62 if (IsSetHost(np
) || (IsAccount(np
) && IsHideHost(np
)))
65 /* CIDR bans don't match IPv6 hosts */
66 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
69 /* Extract the client's IP address into a usable format */
70 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
71 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
73 if ((cip
& bp
->mask
) == bp
->ipaddr
)
76 return 0; /* A CIDR ban won't match any other way */
79 if (bp
->flags
& CHANBAN_IP
) {
80 /* IP bans don't match sethosted users */
81 if (IsSetHost(np
) || (IsAccount(np
) && IsHideHost(np
)))
84 if (bp
->flags
& CHANBAN_HOSTEXACT
) {
85 /* Only exact IP bans are valid */
89 /* Well, it won't match if it's not an IPv4 host */
90 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
93 /* Extract the client's IP address into a usable format */
94 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
95 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
101 /* Hostname bans need to be checked against +x host, +h host (if set)
102 * and actual host. Note that the +x host is only generated (and checked) if it's
103 * possible for the ban to match a hidden host.. */
105 if ((bp
->flags
& CHANBAN_HIDDENHOST
) && IsAccount(np
)) {
106 sprintf(fakehost
,"%s.%s",np
->authname
, HIS_HIDDENHOST
);
108 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
109 !ircd_strcmp(fakehost
, bp
->host
->content
))
112 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
113 match2strings(bp
->host
->content
, fakehost
))
118 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
119 !ircd_strcmp(np
->sethost
->content
, bp
->host
->content
))
122 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
123 match2strings(bp
->host
->content
, np
->sethost
->content
))
127 /* If the user is +h or +rx don't check their real host */
128 if (IsSetHost(np
) || (IsHideHost(np
) && IsAccount(np
)))
131 if (bp
->flags
& CHANBAN_HOSTEXACT
&& !ircd_strcmp(np
->host
->name
->content
,bp
->host
->content
))
134 if (bp
->flags
& CHANBAN_HOSTMASK
&& match2strings(bp
->host
->content
,np
->host
->name
->content
))
143 * Returns true iff the supplied nick* matches the supplied ban*
146 int nickmatchban(nick
*np
, chanban
*bp
) {
147 char fakehost
[HOSTLEN
+1];
149 /* nick/ident section: return 0 (no match) if they don't match */
151 if (bp
->flags
& CHANBAN_INVALID
)
154 if (bp
->flags
& CHANBAN_USEREXACT
&&
155 ircd_strcmp(np
->ident
,bp
->user
->content
) &&
156 (!IsSetHost(np
) || !np
->shident
||
157 ircd_strcmp(np
->shident
->content
,bp
->user
->content
)))
160 if (bp
->flags
& CHANBAN_NICKEXACT
&& ircd_strcmp(np
->nick
,bp
->nick
->content
))
163 if (bp
->flags
& CHANBAN_USERMASK
&&
164 !match2strings(bp
->user
->content
,np
->ident
) &&
165 (!IsSetHost(np
) || !np
->shident
||
166 !match2strings(bp
->user
->content
, np
->shident
->content
)))
169 if (bp
->flags
& CHANBAN_NICKMASK
&& !match2strings(bp
->nick
->content
,np
->nick
))
172 /* host section. Return 1 (match) if they do match
173 * Note that if user or ident was specified, they've already been checked
176 if (bp
->flags
& CHANBAN_HOSTANY
)
179 if ((bp
->flags
& CHANBAN_CIDR
) && (bp
->flags
& CHANBAN_HOSTEXACT
)) {
183 /* CIDR bans don't match IPv6 hosts */
184 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
187 /* Extract the client's IP address into a usable format */
188 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
189 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
191 if ((cip
& bp
->mask
) == bp
->ipaddr
)
194 return 0; /* A CIDR ban won't match any other way */
197 if (bp
->flags
& CHANBAN_IP
) {
198 if (bp
->flags
& CHANBAN_HOSTEXACT
) {
199 /* Only exact matches for IP bans */
203 /* Well, it won't match if it's not an IPv4 host */
204 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
207 /* Extract the client's IP address into a usable format */
208 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
209 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
215 /* Hostname bans need to be checked against +x host, +h host (if set)
216 * and actual host. Note that the +x host is only generated (and checked) if it's
217 * possible for the ban to match a hidden host.. */
219 if ((bp
->flags
& CHANBAN_HIDDENHOST
) && IsAccount(np
)) {
220 sprintf(fakehost
,"%s.%s",np
->authname
, HIS_HIDDENHOST
);
222 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
223 !ircd_strcmp(fakehost
, bp
->host
->content
))
226 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
227 match2strings(bp
->host
->content
, fakehost
))
232 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
233 !ircd_strcmp(np
->sethost
->content
, bp
->host
->content
))
236 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
237 match2strings(bp
->host
->content
, np
->sethost
->content
))
241 if (bp
->flags
& CHANBAN_HOSTEXACT
&& !ircd_strcmp(np
->host
->name
->content
,bp
->host
->content
))
244 if (bp
->flags
& CHANBAN_HOSTMASK
&& match2strings(bp
->host
->content
,np
->host
->name
->content
))
253 * Returns true iff the supplied nick* is banned on the supplied chan*
255 * Also nickbanned_visible - doesn't violate privacy by checking hidden
256 * hosts and idents. Factored into one function to reduce copy&paste.
258 static int nickbanned_real(nick
*np
, channel
*cp
, int (*cmpfunc
)(nick
*, chanban
*)) {
261 for (cbp
=cp
->bans
;cbp
;cbp
=cbp
->next
) {
269 int nickbanned(nick
*np
, channel
*cp
) {
270 return nickbanned_real(np
,cp
,nickmatchban
);
273 int nickbanned_visible(nick
*np
, channel
*cp
) {
274 return nickbanned_real(np
,cp
,nickmatchban_visible
);
279 * Set the specified ban; if it completely encloses any existing bans
282 * Returns 1 if the ban was set, or 0 if the ban was not set because an
283 * existing ban overlapped it.
286 int setban(channel
*cp
, const char *ban
) {
287 chanban
**cbh
,*cbp
,*cbp2
;
291 /* Don't set our ban if something encloses it */
292 for (cbp2
=cp
->bans
;cbp2
;cbp2
=cbp2
->next
) {
293 if (banoverlap(cbp2
, cbp
)) {
294 /* This ban overlaps the one we are adding. Abort. */
300 /* Remove enclosed bans first */
301 for (cbh
=&(cp
->bans
);*cbh
;) {
302 if (banoverlap(cbp
,*cbh
)) {
306 /* Break out of the loop if we just deleted the last ban */
311 cbh
=(chanban
**)&((*cbh
)->next
);
315 /* Now set the new ban */
316 cbp
->next
=(struct chanban
*)cp
->bans
;
324 * Remove the specified ban iff an exact match is found
325 * Returns 1 if the ban was cleared, 0 if the ban didn't exist.
326 * If "optional" is 0 and the ban didn't exist, flags an error
329 int clearban(channel
*cp
, const char *ban
, int optional
) {
330 chanban
**cbh
,*cbp
,*cbp2
;
339 for (cbh
=&(cp
->bans
);*cbh
;cbh
=(chanban
**)&((*cbh
)->next
)) {
340 if (banequal(cbp
,*cbh
)) {
349 if (!found
&& !optional
) {
350 Error("channel",ERR_DEBUG
,"Couldn't remove ban %s from %s. Dumping banlist:",ban
,cp
->index
->name
->content
);
351 for (cbp2
=cp
->bans
;cbp2
;cbp2
=cbp2
->next
) {
352 Error("channel",ERR_DEBUG
,"%s %d %s",cp
->index
->name
->content
, i
++, bantostringdebug(cbp2
));
363 * Just free all the bans on the channel
366 void clearallbans(channel
*cp
) {
369 for (cbp
=cp
->bans
;cbp
;cbp
=ncbp
) {
370 ncbp
=(chanban
*)cbp
->next
;