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