]> jfr.im git - irc/quakenet/newserv.git/blob - patricianick/patricianick.c
initial commit - patricia nick index
[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
11 #include <stdio.h>
12 #include <string.h>
13
14 #define ALLOCUNIT 1000
15
16 patricianick_t *freepatricianicks;
17 int pnode_ext;
18 int pnick_ext;
19
20 int pn_cmd_dumpnodenicks(void *source, int cargc, char **cargv);
21
22 void _init() {
23 nick *np, *nnp;
24 int i;
25
26 pnode_ext = registernodeext("patricianick");
27 if ( pnode_ext == -1 ) {
28 Error("patricianick", ERR_FATAL, "Could not register a required node extension");
29 return;
30 }
31
32 pnick_ext = registernickext("patricianick");
33 if ( pnick_ext == -1) {
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
47 registercontrolcmd("dumpnodenicks", NO_DEVELOPER, 1, &pn_cmd_dumpnodenicks);
48 }
49
50 void _fini() {
51 nsfreeall(POOL_PATRICIANICK);
52
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
64 deregistercontrolcmd("dumpnodenicks", &pn_cmd_dumpnodenicks);
65 }
66
67 patricianick_t *getpatricianick() {
68 int i;
69 patricianick_t *pnp;
70
71 if (freepatricianicks==NULL) {
72 freepatricianicks=(patricianick_t *)nsmalloc(POOL_PATRICIANICK, ALLOCUNIT*sizeof(patricianick_t));
73 for(i=0;i<ALLOCUNIT-1;i++) {
74 freepatricianicks[i].np=(nick *)&(freepatricianicks[i+1]);
75 }
76 freepatricianicks[ALLOCUNIT-1].np=NULL;
77 }
78
79 pnp=freepatricianicks;
80 freepatricianicks=(patricianick_t *)pnp->np;
81
82 pnp->marker = 0;
83 pnp->np = NULL;
84 return pnp;
85 }
86
87 void addnicktonode(patricia_node_t *node, nick *np) {
88 if ( !(node->exts[pnode_ext]) ) {
89 node->exts[pnode_ext] = getpatricianick();
90 }
91
92 np->exts[pnick_ext] = ((patricianick_t *)node->exts[pnode_ext])->np;
93 ((patricianick_t *)node->exts[pnode_ext])->np = np;
94 }
95
96 void deletenickfromnode(patricia_node_t *node, nick *np) {
97 nick **tnp;
98 int found =0;
99
100 for ( tnp = &(((patricianick_t *)node->exts[pnode_ext])->np); *tnp; tnp = (nick **)(&((*tnp)->exts[pnick_ext])) ) {
101 if ( *tnp == np ) {
102 *tnp = np->exts[pnick_ext];
103 found = 1;
104 break;
105 }
106 }
107
108 if (!found) {
109 return; /* err */
110 }
111
112 if (!(((patricianick_t *)node->exts[pnode_ext])->np)) {
113 freepatricianick(node->exts[pnode_ext]);
114 node->exts[pnode_ext]= NULL;
115 }
116
117 }
118
119 void freepatricianick(patricianick_t *pnp) {
120 pnp->np=(nick *)freepatricianicks;
121 freepatricianicks=pnp;
122 }
123
124 void pn_hook_newuser(int hook, void *arg) {
125 nick *np = (nick *)arg;
126
127 addnicktonode(np->ipnode, np);
128 }
129
130 void pn_hook_lostuser(int hook, void *arg) {
131 nick *np = (nick *)arg;
132
133 deletenickfromnode(np->ipnode, np);
134 }
135
136 int pn_cmd_dumpnodenicks(void *source, int cargc, char **cargv) {
137 nick *np=(nick *)source;
138 struct irc_in_addr sin;
139 unsigned char bits;
140 patricia_node_t *head, *node;
141 patricianick_t *pnp;
142 nick *npp;
143 int limit = 0;
144
145 if (cargc < 1) {
146 controlreply(np, "Syntax: dumpnodenicks <ipv4|ipv6|cidr4|cidr6>");
147 return CMD_OK;
148 }
149
150 if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
151 controlreply(np, "Invalid mask.");
152 return CMD_OK;
153 }
154
155 head = refnode(iptree, &sin, bits);
156
157 PATRICIA_WALK(head, node)
158 {
159 pnp = node->exts[pnode_ext];
160 if (pnp ) {
161 npp = pnp->np;
162 while(npp) {
163 limit++;
164
165 if ( limit < PATRICIANICK_MAXRESULTS )
166 controlreply(np, "%s!%s@%s%s%s (%s)", npp->nick, npp->ident, npp->host->name->content, IsAccount(npp) ? "/" : "", npp->authname, IPtostr(node->prefix->sin));
167 else if ( limit == PATRICIANICK_MAXRESULTS )
168 controlreply(np, "Too many Results, truncated..");
169 npp=npp->exts[pnick_ext];
170 }
171 }
172 }
173 PATRICIA_WALK_END;
174 controlreply(np, "Nick Count: %d", limit);
175
176 return CMD_OK;
177 }
178