]> jfr.im git - irc/quakenet/newserv.git/blob - patricianick/patricianick.c
FAKEUSERS: remove unused variable
[irc/quakenet/newserv.git] / patricianick / patricianick.c
1 /* patricianick.c */
2
3 #include "patricianick.h"
4 #include "../irc/irc_config.h"
5 #include "../lib/irc_string.h"
6 #include "../core/error.h"
7 #include "../core/nsmalloc.h"
8 #include "../control/control.h"
9 #include "../core/schedule.h"
10 #include "../lib/version.h"
11
12 #include <stdio.h>
13 #include <string.h>
14
15 #define ALLOCUNIT 100
16
17 MODULE_VERSION("")
18
19 patricianick_t *freepatricianicks;
20 int pnode_ext;
21 int pnick_ext;
22
23 int pn_cmd_nodeuserlist(void *source, int cargc, char **cargv);
24
25 void _init() {
26 nick *np, *nnp;
27 int i;
28
29 pnode_ext = registernodeext("patricianick");
30 if (pnode_ext == -1) {
31 Error("patricianick", ERR_FATAL, "Could not register a required node extension");
32 return;
33 }
34
35 pnick_ext = registernickext("patricianick");
36 if (pnick_ext == -1) {
37 Error("patricianick", ERR_FATAL, "Could not register a required nick extension");
38 return;
39 }
40
41 for (i=0;i<NICKHASHSIZE;i++)
42 for (np=nicktable[i];np;np=nnp) {
43 nnp=np->next;
44 addnicktonode(np->ipnode, np);
45 }
46
47 registerhook(HOOK_NICK_NEWNICK, &pn_hook_newuser);
48 registerhook(HOOK_NICK_LOSTNICK, &pn_hook_lostuser);
49
50 registercontrolhelpcmd("nodeuserlist", NO_OPER, 1, &pn_cmd_nodeuserlist, "Usage: nodeuserlist <ipv4|ipv6|cidr4|cidr6>\nLists all users on a given IP address or CIDR range.");
51 }
52
53 void _fini() {
54 nsfreeall(POOL_PATRICIANICK);
55
56 if (pnode_ext != -1) {
57 releasenodeext(pnode_ext);
58 }
59
60 if (pnick_ext != -1) {
61 releasenickext(pnick_ext);
62 }
63
64 deregisterhook(HOOK_NICK_NEWNICK, &pn_hook_newuser);
65 deregisterhook(HOOK_NICK_LOSTNICK, &pn_hook_lostuser);
66
67 deregistercontrolcmd("nodeuserlist", &pn_cmd_nodeuserlist);
68 }
69
70 patricianick_t *getpatricianick() {
71 int i;
72 patricianick_t *pnp;
73
74 if (freepatricianicks==NULL) {
75 freepatricianicks=(patricianick_t *)nsmalloc(POOL_PATRICIANICK, ALLOCUNIT*sizeof(patricianick_t));
76 for(i=0;i<ALLOCUNIT-1;i++) {
77 freepatricianicks[i].identhash[0]=(nick *)&(freepatricianicks[i+1]);
78 }
79 freepatricianicks[ALLOCUNIT-1].identhash[0]=NULL;
80 }
81
82 pnp=freepatricianicks;
83 freepatricianicks=(patricianick_t *)pnp->identhash[0];
84
85 memset(pnp, 0, sizeof(patricianick_t));
86 return pnp;
87 }
88
89 void addnicktonode(patricia_node_t *node, nick *np) {
90 unsigned long hash;
91
92 patricia_ref_prefix(node->prefix);
93
94 if (!(node->exts[pnode_ext])) {
95 node->exts[pnode_ext] = getpatricianick();
96 }
97
98 hash = pn_getidenthash(np->ident);
99 np->exts[pnick_ext] = ((patricianick_t *)node->exts[pnode_ext])->identhash[hash];
100 ((patricianick_t *)node->exts[pnode_ext])->identhash[hash] = np;
101 }
102
103 void deletenickfromnode(patricia_node_t *node, nick *np) {
104 nick **tnp;
105 int found, i;
106
107 found = 0;
108
109 for (tnp = &(((patricianick_t *)node->exts[pnode_ext])->identhash[pn_getidenthash(np->ident)]); *tnp; tnp = (nick **)(&((*tnp)->exts[pnick_ext]))) {
110 if (*tnp == np) {
111 *tnp = np->exts[pnick_ext];
112 found = 1;
113 break;
114 }
115 }
116
117 if (!found) {
118 Error("patricianick", ERR_ERROR, "Could not remove %s!%s from %s", np->nick, np->ident, IPtostr(node->prefix->sin));
119 return;
120 }
121
122 for (i = 0; i < PATRICIANICK_HASHSIZE; i++) {
123 if (((patricianick_t *)node->exts[pnode_ext])->identhash[i]) {
124 return;
125 }
126 }
127
128 freepatricianick(node->exts[pnode_ext]);
129 node->exts[pnode_ext]= NULL;
130 }
131
132 void freepatricianick(patricianick_t *pnp) {
133 pnp->identhash[0]=(nick *)freepatricianicks;
134 freepatricianicks=pnp;
135 }
136
137 void pn_hook_newuser(int hook, void *arg) {
138 nick *np = (nick *)arg;
139
140 addnicktonode(np->ipnode, np);
141 }
142
143 void pn_hook_lostuser(int hook, void *arg) {
144 nick *np = (nick *)arg;
145
146 deletenickfromnode(np->ipnode, np);
147 }
148
149 int pn_cmd_nodeuserlist(void *source, int cargc, char **cargv) {
150 nick *np=(nick *)source;
151 struct irc_in_addr sin;
152 unsigned char bits;
153 unsigned int count, i;
154 patricia_node_t *head, *node;
155 patricianick_t *pnp;
156 nick *npp;
157
158 if (cargc < 1) {
159 return CMD_USAGE;
160 }
161
162 if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
163 controlreply(np, "Invalid mask.");
164 return CMD_ERROR;
165 }
166
167 head = refnode(iptree, &sin, bits);
168 count = 0;
169
170 PATRICIA_WALK(head, node)
171 {
172 pnp = node->exts[pnode_ext];
173 if (pnp) {
174 if (count < PATRICIANICK_MAXRESULTS) {
175 for (i = 0; i < PATRICIANICK_HASHSIZE; i++) {
176 for (npp = pnp->identhash[i]; npp; npp=npp->exts[pnick_ext]) {
177 controlreply(np, "%s!%s@%s%s%s (%s)", npp->nick, npp->ident, npp->host->name->content, IsAccount(npp) ? "/" : "", npp->authname, IPtostr(node->prefix->sin));
178 }
179 }
180
181 count += node->usercount;
182
183 if (count >= PATRICIANICK_MAXRESULTS) {
184 controlreply(np, "Too many results, output truncated");
185 }
186 } else {
187 count += node->usercount;
188 }
189 }
190 }
191 PATRICIA_WALK_END;
192 derefnode(iptree, head);
193
194 controlreply(np, "Total users on %s: %d", cargv[0], count);
195 return CMD_OK;
196 }