Anope IRC Services  Version 1.8
hostserv.c
Go to the documentation of this file.
1 /* HostServ functions
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  *
12  */
13 
14 /*************************************************************************/
15 #include "services.h"
16 #include "pseudo.h"
17 
18 #define HASH(nick) ((tolower((nick)[0])&31)<<5 | (tolower((nick)[1])&31))
19 
20 void load_hs_dbase_v1(dbFILE * f);
21 void load_hs_dbase_v2(dbFILE * f);
22 void load_hs_dbase_v3(dbFILE * f);
23 
24 HostCore *head = NULL; /* head of the HostCore list */
25 
26 E int do_hs_sync(NickCore * nc, char *vIdent, char *hostmask,
27  char *creator, time_t time);
28 
29 E void moduleAddHostServCmds(void);
30 
31 /*************************************************************************/
32 
34 {
36 }
37 
38 /*************************************************************************/
39 
45 void get_hostserv_stats(long *nrec, long *memuse)
46 {
47  long count = 0, mem = 0;
48  HostCore *hc;
49 
50  for (hc = head; hc; hc = hc->next) {
51  count++;
52  mem += sizeof(*hc);
53  if (hc->nick)
54  mem += strlen(hc->nick) + 1;
55  if (hc->vIdent)
56  mem += strlen(hc->vIdent) + 1;
57  if (hc->vHost)
58  mem += strlen(hc->vHost) + 1;
59  if (hc->creator)
60  mem += strlen(hc->creator) + 1;
61  }
62 
63  *nrec = count;
64  *memuse = mem;
65 }
66 
67 /*************************************************************************/
68 
73 void hostserv_init(void)
74 {
75  if (s_HostServ) {
77  }
78 }
79 
80 /*************************************************************************/
81 
88 void hostserv(User * u, char *buf)
89 {
90  char *cmd, *s;
91 
92  cmd = strtok(buf, " ");
93 
94  if (!cmd) {
95  return;
96  } else if (stricmp(cmd, "\1PING") == 0) {
97  if (!(s = strtok(NULL, ""))) {
98  s = "";
99  }
100  anope_cmd_ctcp(s_HostServ, u->nick, "PING %s", s);
101  } else if (skeleton) {
102  notice_lang(s_HostServ, u, SERVICE_OFFLINE, s_HostServ);
103  } else {
104  if (ircd->vhost) {
105  mod_run_cmd(s_HostServ, u, HOSTSERV, cmd);
106  } else {
107  notice_lang(s_HostServ, u, SERVICE_OFFLINE, s_HostServ);
108  }
109  }
110 }
111 
112 /*************************************************************************/
113 /* Start of Linked List routines */
114 /*************************************************************************/
115 
117 {
118  return head;
119 }
120 
131 HostCore *createHostCorelist(HostCore * next, char *nick, char *vIdent,
132  char *vHost, char *creator, int32 tmp_time)
133 {
134 
135  next = malloc(sizeof(HostCore));
136  if (next == NULL) {
138  "Unable to allocate memory to create the vHost LL, problems i sense..");
139  } else {
140  next->nick = malloc(sizeof(char) * strlen(nick) + 1);
141  next->vHost = malloc(sizeof(char) * strlen(vHost) + 1);
142  next->creator = malloc(sizeof(char) * strlen(creator) + 1);
143  if (vIdent)
144  next->vIdent = malloc(sizeof(char) * strlen(vIdent) + 1);
145  if ((next->nick == NULL) || (next->vHost == NULL)
146  || (next->creator == NULL)) {
148  "Unable to allocate memory to create the vHost LL, problems i sense..");
149  return NULL;
150  }
151  strcpy(next->nick, nick);
152  strcpy(next->vHost, vHost);
153  strcpy(next->creator, creator);
154  if (vIdent) {
155  if ((next->vIdent == NULL)) {
157  "Unable to allocate memory to create the vHost LL, problems i sense..");
158  return NULL;
159  }
160  strcpy(next->vIdent, vIdent);
161  } else {
162  next->vIdent = NULL;
163  }
164  next->time = tmp_time;
165  next->next = NULL;
166  return next;
167  }
168  return NULL;
169 }
170 
171 /*************************************************************************/
180 HostCore *findHostCore(HostCore * head, char *nick, boolean * found)
181 {
182  HostCore *previous, *current;
183 
184  *found = false;
185  current = head;
186  previous = current;
187 
188  if (!nick) {
189  return NULL;
190  }
191 
192  while (current != NULL) {
193  if (stricmp(nick, current->nick) == 0) {
194  *found = true;
195  break;
196  } else if (stricmp(nick, current->nick) < 0) {
197  /* we know were not gonna find it now.... */
198  break;
199  } else {
200  previous = current;
201  current = current->next;
202  }
203  }
204  if (current == head) {
205  return NULL;
206  } else {
207  return previous;
208  }
209 }
210 
211 /*************************************************************************/
212 HostCore *insertHostCore(HostCore * head, HostCore * prev, char *nick,
213  char *vIdent, char *vHost, char *creator,
214  int32 tmp_time)
215 {
216 
217  HostCore *newCore, *tmp;
218 
219  if (!nick || !vHost || !creator) {
220  return NULL;
221  }
222 
223  newCore = malloc(sizeof(HostCore));
224  if (newCore == NULL) {
226  "Unable to allocate memory to insert into the vHost LL, problems i sense..");
227  return NULL;
228  } else {
229  newCore->nick = malloc(sizeof(char) * strlen(nick) + 1);
230  newCore->vHost = malloc(sizeof(char) * strlen(vHost) + 1);
231  newCore->creator = malloc(sizeof(char) * strlen(creator) + 1);
232  if (vIdent)
233  newCore->vIdent = malloc(sizeof(char) * strlen(vIdent) + 1);
234  if ((newCore->nick == NULL) || (newCore->vHost == NULL)
235  || (newCore->creator == NULL)) {
237  "Unable to allocate memory to create the vHost LL, problems i sense..");
238  return NULL;
239  }
240  strcpy(newCore->nick, nick);
241  strcpy(newCore->vHost, vHost);
242  strcpy(newCore->creator, creator);
243  if (vIdent) {
244  if ((newCore->vIdent == NULL)) {
246  "Unable to allocate memory to create the vHost LL, problems i sense..");
247  return NULL;
248  }
249  strcpy(newCore->vIdent, vIdent);
250  } else {
251  newCore->vIdent = NULL;
252  }
253  newCore->time = tmp_time;
254  if (prev == NULL) {
255  tmp = head;
256  head = newCore;
257  newCore->next = tmp;
258  } else {
259  tmp = prev->next;
260  prev->next = newCore;
261  newCore->next = tmp;
262  }
263  }
264  return head;
265 }
266 
267 /*************************************************************************/
269 {
270 
271  HostCore *tmp;
272 
273  if (prev == NULL) {
274  tmp = head;
275  head = head->next;
276  } else {
277  tmp = prev->next;
278  prev->next = tmp->next;
279  }
280  free(tmp->vHost);
281  free(tmp->nick);
282  free(tmp->creator);
283  if (tmp->vIdent) {
284  free(tmp->vIdent);
285  }
286  free(tmp);
287  return head;
288 }
289 
290 /*************************************************************************/
291 void addHostCore(char *nick, char *vIdent, char *vhost, char *creator,
292  int32 tmp_time)
293 {
294  HostCore *tmp;
295  boolean found = false;
296 
297  if (head == NULL) {
298  head =
299  createHostCorelist(head, nick, vIdent, vhost, creator,
300  tmp_time);
301  } else {
302  tmp = findHostCore(head, nick, &found);
303  if (!found) {
304  head =
305  insertHostCore(head, tmp, nick, vIdent, vhost, creator,
306  tmp_time);
307  } else {
308  head = deleteHostCore(head, tmp); /* delete the old entry */
309  addHostCore(nick, vIdent, vhost, creator, tmp_time); /* recursive call to add new entry */
310  }
311  }
312 }
313 
314 /*************************************************************************/
315 char *getvHost(char *nick)
316 {
317  HostCore *tmp;
318  boolean found = false;
319  tmp = findHostCore(head, nick, &found);
320  if (found) {
321  if (tmp == NULL)
322  return head->vHost;
323  else
324  return tmp->next->vHost;
325  }
326  return NULL;
327 }
328 
329 /*************************************************************************/
330 char *getvIdent(char *nick)
331 {
332  HostCore *tmp;
333  boolean found = false;
334  tmp = findHostCore(head, nick, &found);
335  if (found) {
336  if (tmp == NULL)
337  return head->vIdent;
338  else
339  return tmp->next->vIdent;
340  }
341  return NULL;
342 }
343 
344 /*************************************************************************/
345 void delHostCore(char *nick)
346 {
347 #ifdef USE_RDB
348  static char clause[128];
349  char *q_nick;
350 #endif
351  HostCore *tmp;
352  boolean found = false;
353  tmp = findHostCore(head, nick, &found);
354  if (found) {
355  head = deleteHostCore(head, tmp);
356 
357 #ifdef USE_RDB
358  /* Reflect this change in the database right away. */
359  if (rdb_open()) {
360  q_nick = rdb_quote(nick);
361  snprintf(clause, sizeof(clause), "nick='%s'", q_nick);
362  if (rdb_scrub_table("anope_hs_core", clause) == 0)
363  alog("Unable to scrub table 'anope_hs_core' - HostServ RDB update failed.");
364  rdb_close();
365  free(q_nick);
366  }
367 #endif
368 
369  }
370 
371 }
372 
373 /*************************************************************************/
374 /* End of Linked List routines */
375 /*************************************************************************/
376 /*************************************************************************/
377 /* Start of Load/Save routines */
378 /*************************************************************************/
379 #define SAFE(x) do { \
380  if ((x) < 0) { \
381  if (!forceload) \
382  fatal("Read error on %s", HostDBName); \
383  failed = 1; \
384  break; \
385  } \
386 } while (0)
387 
388 void load_hs_dbase(void)
389 {
390  dbFILE *f;
391  int ver;
392 
393  if (!(f = open_db(s_HostServ, HostDBName, "r", HOST_VERSION))) {
394  return;
395  }
396  ver = get_file_version(f);
397 
398  if (ver == 1) {
399  load_hs_dbase_v1(f);
400  } else if (ver == 2) {
401  load_hs_dbase_v2(f);
402  } else if (ver == 3) {
403  load_hs_dbase_v3(f);
404  }
405  close_db(f);
406 }
407 
409 {
410  int c;
411  int failed = 0;
412  int32 tmp;
413 
414  char *nick;
415  char *vHost;
416 
417  tmp = time(NULL);
418 
419  while (!failed && (c = getc_db(f)) == 1) {
420 
421  if (c == 1) {
422  SAFE(read_string(&nick, f));
423  SAFE(read_string(&vHost, f));
424  addHostCore(nick, NULL, vHost, "Unknown", tmp); /* could get a speed increase by not searching the list */
425  free(nick); /* as we know the db is in alphabetical order... */
426  free(vHost);
427  } else {
428  fatal("Invalid format in %s %d", HostDBName, c);
429  }
430  }
431 }
432 
434 {
435  int c;
436  int failed = 0;
437 
438  char *nick;
439  char *vHost;
440  char *creator;
441  uint32 time;
442 
443  while (!failed && (c = getc_db(f)) == 1) {
444 
445  if (c == 1) {
446  SAFE(read_string(&nick, f));
447  SAFE(read_string(&vHost, f));
448  SAFE(read_string(&creator, f));
449  SAFE(read_int32(&time, f));
450  addHostCore(nick, NULL, vHost, creator, time); /* could get a speed increase by not searching the list */
451  free(nick); /* as we know the db is in alphabetical order... */
452  free(vHost);
453  free(creator);
454  } else {
455  fatal("Invalid format in %s %d", HostDBName, c);
456  }
457  }
458 }
459 
461 {
462  int c;
463  int failed = 0;
464 
465  char *nick;
466  char *vHost;
467  char *creator;
468  char *vIdent;
469  uint32 time;
470 
471  while (!failed && (c = getc_db(f)) == 1) {
472  if (c == 1) {
473  SAFE(read_string(&nick, f));
474  SAFE(read_string(&vIdent, f));
475  SAFE(read_string(&vHost, f));
476  SAFE(read_string(&creator, f));
477  SAFE(read_int32(&time, f));
478  addHostCore(nick, vIdent, vHost, creator, time); /* could get a speed increase by not searching the list */
479  free(nick); /* as we know the db is in alphabetical order... */
480  free(vHost);
481  free(creator);
482  free(vIdent);
483  } else {
484  fatal("Invalid format in %s %d", HostDBName, c);
485  }
486  }
487 }
488 
489 #undef SAFE
490 /*************************************************************************/
491 #define SAFE(x) do { \
492  if ((x) < 0) { \
493  restore_db(f); \
494  log_perror("Write error on %s", HostDBName); \
495  if (time(NULL) - lastwarn > WarningTimeout) { \
496  anope_cmd_global(NULL, "Write error on %s: %s", HostDBName, \
497  strerror(errno)); \
498  lastwarn = time(NULL); \
499  } \
500  return; \
501  } \
502 } while (0)
503 
504 void save_hs_dbase(void)
505 {
506  dbFILE *f;
507  static time_t lastwarn = 0;
508  HostCore *current;
509 
510  if (!(f = open_db(s_HostServ, HostDBName, "w", HOST_VERSION)))
511  return;
512 
513  current = head;
514  while (current != NULL) {
515  SAFE(write_int8(1, f));
516  SAFE(write_string(current->nick, f));
517  SAFE(write_string(current->vIdent, f));
518  SAFE(write_string(current->vHost, f));
519  SAFE(write_string(current->creator, f));
520  SAFE(write_int32(current->time, f));
521  current = current->next;
522  }
523  SAFE(write_int8(0, f));
524  close_db(f);
525 
526 }
527 
528 #undef SAFE
529 
531 {
532 #ifdef USE_RDB
533  HostCore *current;
534 
535  if (!rdb_open())
536  return;
537 
538  if (rdb_tag_table("anope_hs_core") == 0) {
539  alog("Unable to tag table 'anope_hs_core' - HostServ RDB save failed.");
540  rdb_close();
541  return;
542  }
543 
544  current = head;
545  while (current != NULL) {
546  if (rdb_save_hs_core(current) == 0) {
547  alog("Unable to save HostCore for %s - HostServ RDB save failed.", current->nick);
548  rdb_close();
549  return;
550  }
551  current = current->next;
552  }
553 
554  if (rdb_clean_table("anope_hs_core") == 0)
555  alog("Unable to clean table 'anope_hs_core' - HostServ RDB save failed.");
556 
557  rdb_close();
558 #endif
559 }
560 
561 /*************************************************************************/
562 /* End of Load/Save Functions */
563 /*************************************************************************/
564 /*************************************************************************/
565 /* Start of Generic Functions */
566 /*************************************************************************/
567 
568 int do_hs_sync(NickCore * nc, char *vIdent, char *hostmask, char *creator,
569  time_t time)
570 {
571  int i;
572  NickAlias *na;
573 
574  for (i = 0; i < nc->aliases.count; i++) {
575  na = nc->aliases.list[i];
576  addHostCore(na->nick, vIdent, hostmask, creator, time);
577  }
578  return MOD_CONT;
579 }
580 
581 /*************************************************************************/
582 int do_on_id(User * u)
583 { /* we've assumed that the user exists etc.. */
584  char *vHost; /* as were only gonna call this from nsid routine */
585  char *vIdent;
586  vHost = getvHost(u->nick);
587  vIdent = getvIdent(u->nick);
588  if (vHost != NULL) {
589  if (vIdent) {
590  notice_lang(s_HostServ, u, HOST_IDENT_ACTIVATED, vIdent,
591  vHost);
592  } else {
593  notice_lang(s_HostServ, u, HOST_ACTIVATED, vHost);
594  }
595  anope_cmd_vhost_on(u->nick, vIdent, vHost);
596  if (ircd->vhost) {
597  if (u->vhost)
598  free(u->vhost);
599  u->vhost = sstrdup(vHost);
600  }
601  if (ircd->vident) {
602  if (vIdent) {
603  if (u->vident)
604  free(u->vident);
605  u->vident = sstrdup(vIdent);
606  }
607  }
608  set_lastmask(u);
609  }
610  return MOD_CONT;
611 }
612 
613 /*************************************************************************/
615 {
616  int i, j;
617  NickAlias *na;
618 
619  if (is_services_oper(u)) {
620  return 1;
621  }
622  if (!nick_identified(u)) {
623  return 0;
624  }
625 
626  /* Look through all user's aliases (0000412) */
627  for (i = 0; i < u->na->nc->aliases.count; i++) {
628  na = u->na->nc->aliases.list[i];
629  for (j = 0; j < HostNumber; j++) {
630  if (stricmp(HostSetters[j], na->nick) == 0) {
631  return 1;
632  }
633  }
634  }
635 
636  return 0;
637 }
638 
640 {
641  return is_host_setter(u); /* only here incase we want to split them up later */
642 }
643 
644 /*
645  * Sets the last_usermak properly. Using virtual ident and/or host
646  */
648 {
649  if (u->na->last_usermask)
650  free(u->na->last_usermask);
651 
652  u->na->last_usermask =
653  smalloc(strlen(common_get_vident(u)) +
654  strlen(common_get_vhost(u)) + 2);
655  sprintf(u->na->last_usermask, "%s@%s", common_get_vident(u),
656  common_get_vhost(u));
657 
658 }
time_t time
Definition: services.h:1113
E int do_hs_sync(NickCore *nc, char *vIdent, char *hostmask, char *creator, time_t time)
Definition: hostserv.c:568
char nick[NICKMAX]
Definition: services.h:875
E int snprintf(char *buf, size_t size, const char *fmt,...)
Definition: compat.c:37
static Channel * current
Definition: channels.c:427
E void moduleAddHostServCmds(void)
Definition: hostserv.c:33
E IRCDVar * ircd
Definition: extern.h:39
E int nick_identified(User *u)
Definition: nickserv.c:1111
char * vhost
Definition: services.h:880
int vhost
Definition: services.h:301
void load_hs_dbase_v2(dbFILE *f)
Definition: hostserv.c:433
E int stricmp(const char *s1, const char *s2)
Definition: compat.c:58
E void anope_cmd_vhost_on(char *nick, char *vIdent, char *vhost)
Definition: ircd.c:549
HostCore * head
Definition: hostserv.c:24
E void modules_core_init(int number, char **list)
Definition: modules.c:127
E char * HostDBName
Definition: extern.h:301
void hostserv_init(void)
Definition: hostserv.c:73
void save_hs_rdb_dbase(void)
Definition: hostserv.c:530
char * rdb_quote(char *str)
Definition: rdb.c:60
void save_hs_dbase(void)
Definition: hostserv.c:504
int vident
Definition: services.h:337
#define write_int8(val, f)
Definition: datafiles.h:60
#define HOSTSERV
Definition: modules.h:56
E void notice_lang(char *source, User *dest, int message,...)
Definition: send.c:169
E char ** HostServCoreModules
Definition: extern.h:482
E char * sstrdup(const char *s)
Definition: memory.c:105
NickCore * nc
Definition: services.h:533
int rdb_close()
Definition: rdb.c:47
void load_hs_dbase_v1(dbFILE *f)
Definition: hostserv.c:408
E void E void E void fatal(const char *fmt,...) FORMAT(printf
void ** list
Definition: slist.h:21
#define getc_db(f)
Definition: datafiles.h:48
E int read_string(char **ret, dbFILE *f)
Definition: db-merger.c:1806
int16 count
Definition: slist.h:23
char * getvHost(char *nick)
Definition: hostserv.c:315
void addHostCore(char *nick, char *vIdent, char *vhost, char *creator, int32 tmp_time)
Definition: hostserv.c:291
HostCore * findHostCore(HostCore *head, char *nick, boolean *found)
Definition: hostserv.c:180
E int get_file_version(dbFILE *f)
Definition: datafiles.c:30
void delHostCore(char *nick)
Definition: hostserv.c:345
int rdb_save_hs_core(HostCore *hc)
Definition: rdb.c:313
void hostserv(User *u, char *buf)
Definition: hostserv.c:88
int32_t int32
Definition: db-merger.c:122
E void close_db(dbFILE *f)
Definition: db-merger.c:1706
HostCore * next
Definition: services.h:1108
void get_hostserv_stats(long *nrec, long *memuse)
Definition: hostserv.c:45
int rdb_scrub_table(char *table, char *clause)
Definition: rdb.c:138
void load_hs_dbase_v3(dbFILE *f)
Definition: hostserv.c:460
Command * c
Definition: ns_recover.c:17
E int HostServCoreNumber
Definition: extern.h:483
#define SAFE(x)
Definition: hostserv.c:491
u_int32_t uint32
Definition: db-merger.c:123
E dbFILE * open_db(const char *service, const char *filename, const char *mode, uint32 version)
Definition: datafiles.c:295
E void alog(const char *fmt,...) FORMAT(printf
int is_host_remover(User *u)
Definition: hostserv.c:639
#define MOD_CONT
Definition: modules.h:54
int is_host_setter(User *u)
Definition: hostserv.c:614
E int HostNumber
Definition: extern.h:367
char * vHost
Definition: services.h:1111
#define E
Definition: extern.h:18
static time_t lastwarn
Definition: datafiles.c:19
E char * s_HostServ
Definition: extern.h:303
char * nick
Definition: services.h:526
E int skeleton
Definition: extern.h:778
char * vident
Definition: services.h:882
void set_lastmask(User *u)
Definition: hostserv.c:647
HostCore * insertHostCore(HostCore *head, HostCore *prev, char *nick, char *vIdent, char *vHost, char *creator, int32 tmp_time)
Definition: hostserv.c:212
char * vIdent
Definition: services.h:1110
int rdb_clean_table(char *table)
Definition: rdb.c:113
int rdb_open()
Definition: rdb.c:31
SList aliases
Definition: services.h:559
HostCore * hostCoreListHead()
Definition: hostserv.c:116
E int is_services_oper(User *u)
Definition: operserv.c:606
int do_on_id(User *u)
Definition: hostserv.c:582
int rdb_tag_table(char *table)
Definition: rdb.c:75
E void * smalloc(long size)
Definition: memory.c:30
void load_hs_dbase(void)
Definition: hostserv.c:388
char * creator
Definition: services.h:1112
E int read_int32(uint32 *ret, dbFILE *f)
Definition: datafiles.c:444
char * getvIdent(char *nick)
Definition: hostserv.c:330
MDE void mod_run_cmd(char *service, User *u, CommandHash *cmdTable[], const char *cmd)
Definition: commands.c:67
E int write_string(const char *s, dbFILE *f)
Definition: db-merger.c:1826
HostCore * createHostCorelist(HostCore *next, char *nick, char *vIdent, char *vHost, char *creator, int32 tmp_time)
Definition: hostserv.c:131
#define HOST_VERSION
Definition: services.h:469
E void anope_cmd_ctcp(char *source, char *dest, const char *fmt,...)
Definition: ircd.c:672
char * last_usermask
Definition: services.h:529
E int write_int32(uint32 val, dbFILE *f)
Definition: db-merger.c:1773
E char ** HostSetters
Definition: extern.h:366
E char * common_get_vhost(User *u)
Definition: actions.c:251
char * nick
Definition: services.h:1109
E char * common_get_vident(User *u)
Definition: actions.c:272
NickAlias * na
Definition: services.h:892
E void anope_cmd_global(char *source, const char *fmt,...)
Definition: ircd.c:506
HostCore * deleteHostCore(HostCore *head, HostCore *prev)
Definition: hostserv.c:268