]> jfr.im git - irc/quakenet/newserv.git/blame - patricianick/patricianick.c
merge
[irc/quakenet/newserv.git] / patricianick / patricianick.c
CommitLineData
84ca44e7
P
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"
7f32dbdf 10#include "../lib/version.h"
84ca44e7
P
11
12#include <stdio.h>
13#include <string.h>
14
32a0a978 15#define ALLOCUNIT 100
84ca44e7 16
7f32dbdf
P
17MODULE_VERSION("")
18
84ca44e7
P
19patricianick_t *freepatricianicks;
20int pnode_ext;
21int pnick_ext;
22
35a8a596 23int pn_cmd_nodeuserlist(void *source, int cargc, char **cargv);
84ca44e7
P
24
25void _init() {
26 nick *np, *nnp;
27 int i;
28
29 pnode_ext = registernodeext("patricianick");
32a0a978 30 if (pnode_ext == -1) {
84ca44e7
P
31 Error("patricianick", ERR_FATAL, "Could not register a required node extension");
32 return;
33 }
34
35 pnick_ext = registernickext("patricianick");
32a0a978 36 if (pnick_ext == -1) {
84ca44e7
P
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
2394d0d8 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.");
84ca44e7
P
51}
52
53void _fini() {
54 nsfreeall(POOL_PATRICIANICK);
32a0a978 55
84ca44e7
P
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
35a8a596 67 deregistercontrolcmd("nodeuserlist", &pn_cmd_nodeuserlist);
84ca44e7
P
68}
69
70patricianick_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++) {
32a0a978 77 freepatricianicks[i].identhash[0]=(nick *)&(freepatricianicks[i+1]);
84ca44e7 78 }
32a0a978 79 freepatricianicks[ALLOCUNIT-1].identhash[0]=NULL;
84ca44e7
P
80 }
81
82 pnp=freepatricianicks;
32a0a978 83 freepatricianicks=(patricianick_t *)pnp->identhash[0];
84ca44e7 84
32a0a978 85 memset(pnp, 0, sizeof(patricianick_t));
84ca44e7
P
86 return pnp;
87}
88
89void addnicktonode(patricia_node_t *node, nick *np) {
32a0a978
C
90 unsigned long hash;
91
94a4dc1c
P
92 patricia_ref_prefix(node->prefix);
93
32a0a978 94 if (!(node->exts[pnode_ext])) {
84ca44e7
P
95 node->exts[pnode_ext] = getpatricianick();
96 }
32a0a978
C
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;
84ca44e7
P
101}
102
103void deletenickfromnode(patricia_node_t *node, nick *np) {
104 nick **tnp;
32a0a978
C
105 int found, i;
106
107 found = 0;
84ca44e7 108
32a0a978
C
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) {
84ca44e7
P
111 *tnp = np->exts[pnick_ext];
112 found = 1;
113 break;
114 }
115 }
116
117 if (!found) {
32a0a978
C
118 Error("patricianick", ERR_ERROR, "Could not remove %s!%s from %s", np->nick, np->ident, IPtostr(node->prefix->sin));
119 return;
84ca44e7
P
120 }
121
32a0a978
C
122 for (i = 0; i < PATRICIANICK_HASHSIZE; i++) {
123 if (((patricianick_t *)node->exts[pnode_ext])->identhash[i]) {
124 return;
125 }
84ca44e7
P
126 }
127
32a0a978
C
128 freepatricianick(node->exts[pnode_ext]);
129 node->exts[pnode_ext]= NULL;
84ca44e7
P
130}
131
132void freepatricianick(patricianick_t *pnp) {
32a0a978 133 pnp->identhash[0]=(nick *)freepatricianicks;
84ca44e7
P
134 freepatricianicks=pnp;
135}
136
137void pn_hook_newuser(int hook, void *arg) {
138 nick *np = (nick *)arg;
139
140 addnicktonode(np->ipnode, np);
141}
142
143void pn_hook_lostuser(int hook, void *arg) {
144 nick *np = (nick *)arg;
145
146 deletenickfromnode(np->ipnode, np);
147}
148
35a8a596 149int pn_cmd_nodeuserlist(void *source, int cargc, char **cargv) {
84ca44e7
P
150 nick *np=(nick *)source;
151 struct irc_in_addr sin;
152 unsigned char bits;
32a0a978 153 unsigned int count, i;
84ca44e7
P
154 patricia_node_t *head, *node;
155 patricianick_t *pnp;
156 nick *npp;
84ca44e7
P
157
158 if (cargc < 1) {
2394d0d8 159 return CMD_USAGE;
84ca44e7
P
160 }
161
162 if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
163 controlreply(np, "Invalid mask.");
2394d0d8 164 return CMD_ERROR;
84ca44e7
P
165 }
166
167 head = refnode(iptree, &sin, bits);
32a0a978 168 count = 0;
84ca44e7
P
169
170 PATRICIA_WALK(head, node)
171 {
172 pnp = node->exts[pnode_ext];
32a0a978
C
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 }
84ca44e7
P
189 }
190 }
191 PATRICIA_WALK_END;
8ac1acd3 192 derefnode(iptree, head);
84ca44e7 193
32a0a978 194 controlreply(np, "Total users on %s: %d", cargv[0], count);
84ca44e7
P
195 return CMD_OK;
196}