]> jfr.im git - irc/quakenet/newserv.git/blame - channel/channelbans.c
CHANNEL: Slightly rearranged logic.
[irc/quakenet/newserv.git] / channel / channelbans.c
CommitLineData
c86edd1d
Q
1/* channelbans.c */
2
3#include <assert.h>
4#include <string.h>
5#include <stdio.h>
6
7#include "channel.h"
8#include "../nick/nick.h"
9#include "../lib/irc_string.h"
10#include "../irc/irc_config.h"
11#include "../irc/irc.h"
873f4217 12#include "../lib/irc_ipv6.h"
c86edd1d 13
795410dd 14/*
873f4217 15 * nickmatchban:
795410dd 16 * Returns true iff the supplied nick* matches the supplied ban*
795410dd 17 *
873f4217 18 * "visibleonly" flag indicates that we shouldn't check against the real
19 * host if it's masked.
795410dd 20 */
21
873f4217 22int nickmatchban(nick *np, chanban *bp, int visibleonly) {
795410dd 23 char fakehost[HOSTLEN+1];
873f4217 24 char *ident;
795410dd 25
e831c619 26 /* If it's not valid, don't bother */
795410dd 27 if (bp->flags & CHANBAN_INVALID)
28 return 0;
29
e831c619 30 /* nick/ident section: return 0 (no match) if they don't match */
31
873f4217 32 /* Pick up the visible username. If a sethost username is set, the real
33 * username is not checked. */
34 ident=np->ident;
35 if (IsSetHost(np) && np->shident)
36 ident=np->shident->content;
795410dd 37
873f4217 38 if (bp->flags & CHANBAN_USEREXACT &&
39 ircd_strcmp(ident,bp->user->content))
795410dd 40 return 0;
41
42 if (bp->flags & CHANBAN_NICKEXACT && ircd_strcmp(np->nick,bp->nick->content))
43 return 0;
44
873f4217 45 if (bp->flags & CHANBAN_USERMASK &&
46 !match2strings(bp->user->content,ident))
795410dd 47 return 0;
48
49 if (bp->flags & CHANBAN_NICKMASK && !match2strings(bp->nick->content,np->nick))
873f4217 50 return 0;
795410dd 51
52 /* host section. Return 1 (match) if they do match
53 * Note that if user or ident was specified, they've already been checked
54 */
55
56 if (bp->flags & CHANBAN_HOSTANY)
57 return 1;
e831c619 58
59 /* "visibleonly" means don't check IP/realhost if they are sethosted/+x.
60 * We change this to mean "Don't check IP/realhost unconditionally" - by
61 * clearing it to 0 if the user isn't sethosted or +x. Simplifies logic
62 * later. */
63
64 if (!(IsSetHost(np) || (IsAccount(np) && IsHideHost(np)))
65 visibleonly=0;
795410dd 66
e831c619 67 if ((bp->flags & CHANBAN_IP) && !visibleonly) {
873f4217 68 if (ipmask_check(&(np->ipnode->prefix->sin), &(bp->ipaddr), bp->prefixlen))
795410dd 69 return 1;
795410dd 70 }
71
873f4217 72 /* Hostname bans need to be checked against +x host, +h host (if set)
73 * and actual host. Note that the +x host is only generated (and checked) if it's
e831c619 74 * possible for the ban to match a hidden host. And it's checked regardless
75 * of whether the user is actually +x. */
795410dd 76
873f4217 77 if ((bp->flags & CHANBAN_HIDDENHOST) && IsAccount(np)) {
78 sprintf(fakehost,"%s.%s",np->authname, HIS_HIDDENHOST);
79
80 if ((bp->flags & CHANBAN_HOSTEXACT) &&
81 !ircd_strcmp(fakehost, bp->host->content))
82 return 1;
795410dd 83
873f4217 84 if ((bp->flags & CHANBAN_HOSTMASK) &&
85 match2strings(bp->host->content, fakehost))
86 return 1;
87 }
795410dd 88
873f4217 89 if (IsSetHost(np)) {
90 if ((bp->flags & CHANBAN_HOSTEXACT) &&
795410dd 91 !ircd_strcmp(np->sethost->content, bp->host->content))
873f4217 92 return 1;
795410dd 93
873f4217 94 if ((bp->flags & CHANBAN_HOSTMASK) &&
795410dd 95 match2strings(bp->host->content, np->sethost->content))
795410dd 96 return 1;
97 }
98
873f4217 99 /* If we are only checking visible host and the host is somehow masked, don't check
100 * against the real one. */
e831c619 101 if (visibleonly)
c86edd1d
Q
102 return 0;
103
873f4217 104 if (bp->flags & CHANBAN_HOSTEXACT && !ircd_strcmp(np->host->name->content,bp->host->content))
c86edd1d 105 return 1;
e340eee8 106
873f4217 107 if (bp->flags & CHANBAN_HOSTMASK && match2strings(bp->host->content,np->host->name->content))
108 return 1;
c86edd1d
Q
109
110 return 0;
111}
112
113/*
114 * nickbanned:
115 * Returns true iff the supplied nick* is banned on the supplied chan*
795410dd 116 *
873f4217 117 * Pass the visibleonly flag on to nickbanned().
c86edd1d 118 */
873f4217 119int nickbanned(nick *np, channel *cp, int visibleonly) {
c86edd1d
Q
120 chanban *cbp;
121
122 for (cbp=cp->bans;cbp;cbp=cbp->next) {
873f4217 123 if (nickmatchban(np,cbp,visibleonly))
c86edd1d
Q
124 return 1;
125 }
126
127 return 0;
128}
129
130/*
131 * setban:
132 * Set the specified ban; if it completely encloses any existing bans
133 * then remove them.
11032584 134 *
135 * Returns 1 if the ban was set, or 0 if the ban was not set because an
136 * existing ban overlapped it.
c86edd1d
Q
137 */
138
11032584 139int setban(channel *cp, const char *ban) {
c86edd1d
Q
140 chanban **cbh,*cbp,*cbp2;
141
142 cbp=makeban(ban);
143
11032584 144 /* Don't set our ban if something encloses it */
145 for (cbp2=cp->bans;cbp2;cbp2=cbp2->next) {
146 if (banoverlap(cbp2, cbp)) {
147 /* This ban overlaps the one we are adding. Abort. */
148 freechanban(cbp);
149 return 0;
150 }
151 }
152
c86edd1d
Q
153 /* Remove enclosed bans first */
154 for (cbh=&(cp->bans);*cbh;) {
155 if (banoverlap(cbp,*cbh)) {
156 cbp2=(*cbh);
157 (*cbh)=cbp2->next;
158 freechanban(cbp2);
159 /* Break out of the loop if we just deleted the last ban */
160 if ((*cbh)==NULL) {
161 break;
162 }
163 } else {
164 cbh=(chanban **)&((*cbh)->next);
165 }
166 }
167
168 /* Now set the new ban */
169 cbp->next=(struct chanban *)cp->bans;
170 cp->bans=cbp;
11032584 171
172 return 1;
c86edd1d
Q
173}
174
175/*
176 * clearban:
177 * Remove the specified ban iff an exact match is found
178 * Returns 1 if the ban was cleared, 0 if the ban didn't exist.
179 * If "optional" is 0 and the ban didn't exist, flags an error
180 */
181
182int clearban(channel *cp, const char *ban, int optional) {
183 chanban **cbh,*cbp,*cbp2;
184 int found=0;
185 int i=0;
186
187 if (!cp)
188 return 0;
189
190 cbp=makeban(ban);
191
192 for (cbh=&(cp->bans);*cbh;cbh=(chanban **)&((*cbh)->next)) {
193 if (banequal(cbp,*cbh)) {
194 cbp2=(*cbh);
195 (*cbh)=cbp2->next;
196 freechanban(cbp2);
197 found=1;
198 break;
199 }
200 }
201
202 if (!found && !optional) {
203 Error("channel",ERR_DEBUG,"Couldn't remove ban %s from %s. Dumping banlist:",ban,cp->index->name->content);
204 for (cbp2=cp->bans;cbp2;cbp2=cbp2->next) {
205 Error("channel",ERR_DEBUG,"%s %d %s",cp->index->name->content, i++, bantostringdebug(cbp2));
206 }
207 }
208
209 freechanban(cbp);
210
211 return found;
212}
213
214/*
215 * clearallbans:
216 * Just free all the bans on the channel
217 */
218
219void clearallbans(channel *cp) {
220 chanban *cbp,*ncbp;
221
222 for (cbp=cp->bans;cbp;cbp=ncbp) {
223 ncbp=(chanban *)cbp->next;
224 freechanban(cbp);
225 }
226
227 cp->bans=NULL;
228}