00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "services.h"
00016
00017 Server *servlist = NULL;
00018 Server *me_server = NULL;
00019 Server *serv_uplink = NULL;
00020 uint32 uplink_capab;
00021 char *uplink;
00022 char *TS6UPLINK;
00023 char *TS6SID;
00024
00025
00026 static Server *server_cur;
00027
00028 CapabInfo capab_info[] = {
00029 {"NOQUIT", CAPAB_NOQUIT},
00030 {"TSMODE", CAPAB_TSMODE},
00031 {"UNCONNECT", CAPAB_UNCONNECT},
00032 {"NICKIP", CAPAB_NICKIP},
00033 {"SSJOIN", CAPAB_NSJOIN},
00034 {"ZIP", CAPAB_ZIP},
00035 {"BURST", CAPAB_BURST},
00036 {"TS5", CAPAB_TS5},
00037 {"TS3", CAPAB_TS3},
00038 {"DKEY", CAPAB_DKEY},
00039 {"PT4", CAPAB_PT4},
00040 {"SCS", CAPAB_SCS},
00041 {"QS", CAPAB_QS},
00042 {"UID", CAPAB_UID},
00043 {"KNOCK", CAPAB_KNOCK},
00044 {"CLIENT", CAPAB_CLIENT},
00045 {"IPV6", CAPAB_IPV6},
00046 {"SSJ5", CAPAB_SSJ5},
00047 {"SN2", CAPAB_SN2},
00048 {"TOK1", CAPAB_TOKEN},
00049 {"TOKEN", CAPAB_TOKEN},
00050 {"VHOST", CAPAB_VHOST},
00051 {"SSJ3", CAPAB_SSJ3},
00052 {"SJB64", CAPAB_SJB64},
00053 {"CHANMODES", CAPAB_CHANMODE},
00054 {"NICKCHARS", CAPAB_NICKCHARS},
00055 {NULL, 0}
00056 };
00057
00058
00059
00065 Server *first_server(int flags)
00066 {
00067 server_cur = servlist;
00068 if (flags > -1) {
00069 while (server_cur && (server_cur->flags != flags))
00070 server_cur = next_server(flags);
00071 }
00072 return server_cur;
00073 }
00074
00075
00076
00082 Server *next_server(int flags)
00083 {
00084 if (!server_cur)
00085 return NULL;
00086
00087 do {
00088 if (server_cur->links) {
00089 server_cur = server_cur->links;
00090 } else if (server_cur->next) {
00091 server_cur = server_cur->next;
00092 } else {
00093 do {
00094 server_cur = server_cur->uplink;
00095 if (server_cur && server_cur->next) {
00096 server_cur = server_cur->next;
00097 break;
00098 }
00099 } while (server_cur);
00100 }
00101 } while (server_cur && ((flags > -1) || (server_cur->flags != flags)));
00102
00103 return server_cur;
00104 }
00105
00106
00107
00120 Server *new_server(Server * uplink, const char *name, const char *desc,
00121 uint16 flags, char *suid)
00122 {
00123 Server *serv;
00124
00125 serv = scalloc(sizeof(Server), 1);
00126 if (!name)
00127 name = "";
00128 serv->name = sstrdup(name);
00129 serv->desc = sstrdup(desc);
00130 serv->flags = flags;
00131 serv->uplink = uplink;
00132 if (suid) {
00133 serv->suid = sstrdup(suid);
00134 } else {
00135 serv->suid = NULL;
00136 }
00137 if (ircd->sync)
00138 serv->sync = SSYNC_IN_PROGRESS;
00139 else
00140 serv->sync = SSYNC_UNKNOWN;
00141 serv->links = NULL;
00142 serv->prev = NULL;
00143
00144 if (!uplink) {
00145 serv->hops = 0;
00146 serv->next = servlist;
00147 if (servlist)
00148 servlist->prev = serv;
00149 servlist = serv;
00150 } else {
00151 serv->hops = uplink->hops + 1;
00152 serv->next = uplink->links;
00153 if (uplink->links)
00154 uplink->links->prev = serv;
00155 uplink->links = serv;
00156 }
00157
00158 if ((uplink == me_server) && !(flags & SERVER_JUPED))
00159 serv_uplink = serv;
00160
00161
00162 if (GlobalOnCycle && GlobalOnCycleUP && !(flags & SERVER_JUPED))
00163 notice_server(s_GlobalNoticer, serv, "%s", GlobalOnCycleUP);
00164
00165 return serv;
00166 }
00167
00168
00169
00180 static void delete_server(Server * serv, const char *quitreason)
00181 {
00182 Server *s, *snext;
00183 User *u, *unext;
00184 NickAlias *na;
00185
00186 if (!serv) {
00187 if (debug) {
00188 alog("debug: delete_server() called with NULL arg!");
00189 }
00190 return;
00191 }
00192
00193 if (debug)
00194 alog("debug: delete_server() called for %s", serv->name);
00195
00196 if (ircdcap->noquit || ircdcap->qs) {
00197 if ((uplink_capab & ircdcap->noquit)
00198 || (uplink_capab & ircdcap->qs)) {
00199 u = firstuser();
00200 while (u) {
00201 unext = nextuser();
00202 if (u->server == serv) {
00203 if ((na = u->na) && !(na->status & NS_VERBOTEN)
00204 && (!(na->nc->flags & NI_SUSPENDED))
00205 && (na->status & (NS_IDENTIFIED | NS_RECOGNIZED))) {
00206 na->last_seen = time(NULL);
00207 if (na->last_quit)
00208 free(na->last_quit);
00209 na->last_quit =
00210 (quitreason ? sstrdup(quitreason) : NULL);
00211 }
00212 if (LimitSessions) {
00213 del_session(u->host);
00214 }
00215 delete_user(u);
00216 }
00217 u = unext;
00218 }
00219 if (debug)
00220 alog("debug: delete_server() cleared all users");
00221 }
00222 }
00223
00224 s = serv->links;
00225 while (s) {
00226 snext = s->next;
00227 delete_server(s, quitreason);
00228 s = snext;
00229 }
00230
00231 if (debug)
00232 alog("debug: delete_server() cleared all servers");
00233
00234 free(serv->name);
00235 free(serv->desc);
00236 if (serv->prev)
00237 serv->prev->next = serv->next;
00238 if (serv->next)
00239 serv->next->prev = serv->prev;
00240 if (serv->uplink->links == serv)
00241 serv->uplink->links = serv->next;
00242
00243 if (debug)
00244 alog("debug: delete_server() completed");
00245 }
00246
00247
00248
00255 Server *findserver(Server * s, const char *name)
00256 {
00257 Server *sl;
00258
00259 if (!name || !*name) {
00260 return NULL;
00261 }
00262
00263 if (debug >= 3) {
00264 alog("debug: findserver(%p)", name);
00265 }
00266 while (s && (stricmp(s->name, name) != 0)) {
00267 if (s->links) {
00268 sl = findserver(s->links, name);
00269 if (sl) {
00270 s = sl;
00271 } else {
00272 s = s->next;
00273 }
00274 } else {
00275 s = s->next;
00276 }
00277 }
00278 if (debug >= 3) {
00279 alog("debug: findserver(%s) -> %p", name, (void *) s);
00280 }
00281 return s;
00282 }
00283
00284
00285
00292 Server *findserver_uid(Server * s, const char *name)
00293 {
00294 Server *sl;
00295
00296 if (!name || !*name) {
00297 return NULL;
00298 }
00299
00300 if (debug >= 3) {
00301 alog("debug: findserver_uid(%p)", name);
00302 }
00303 while (s && s->suid && (stricmp(s->suid, name) != 0)) {
00304 if (s->links) {
00305 sl = findserver_uid(s->links, name);
00306 if (sl) {
00307 s = sl;
00308 } else {
00309 s = s->next;
00310 }
00311 } else {
00312 s = s->next;
00313 }
00314 }
00315 if (debug >= 3) {
00316 alog("debug: findserver_uid(%s) -> %p", name, (void *) s);
00317 }
00318 return s;
00319 }
00320
00321
00322
00329 int anope_check_sync(const char *name)
00330 {
00331 Server *s;
00332 s = findserver(servlist, name);
00333
00334 if (!s)
00335 return 0;
00336
00337 if (is_sync(s))
00338 return 1;
00339 else
00340 return -1;
00341 }
00342
00343
00344
00354 void do_server(const char *source, char *servername, char *hops,
00355 char *descript, char *numeric)
00356 {
00357 Server *s;
00358
00359 if (debug) {
00360 if (!*source) {
00361 alog("debug: Server introduced (%s)", servername);
00362 } else {
00363 alog("debug: Server introduced (%s) from %s", servername,
00364 source);
00365 }
00366 }
00367
00368 if (source[0] == '\0')
00369 s = me_server;
00370 else
00371 s = findserver(servlist, source);
00372
00373 new_server(s, servername, descript, 0, numeric);
00374 send_event(EVENT_SERVER_CONNECT, 1, servername);
00375 }
00376
00377
00378
00386 void do_squit(const char *source, int ac, char **av)
00387 {
00388 char buf[BUFSIZE];
00389 Server *s;
00390
00391 if (UseTS6 && ircd->ts6) {
00392 s = findserver_uid(servlist, av[0]);
00393 if (!s) {
00394 s = findserver(servlist, av[0]);
00395 }
00396 } else {
00397 s = findserver(servlist, av[0]);
00398 }
00399 if (!s) {
00400 alog("SQUIT for nonexistent server (%s)!!", av[0]);
00401 return;
00402 }
00403 send_event(EVENT_SERVER_SQUIT, 1, s->name);
00404
00405
00406
00407
00408 if (s->flags & SERVER_JUPED) {
00409 snprintf(buf, BUFSIZE, "Received SQUIT for juped server %s",
00410 s->name);
00411 anope_cmd_global(s_OperServ, buf);
00412 }
00413
00414 snprintf(buf, sizeof(buf), "%s %s", s->name,
00415 (s->uplink ? s->uplink->name : ""));
00416
00417 if (ircdcap->unconnect) {
00418 if ((s->uplink == me_server)
00419 && (uplink_capab & ircdcap->unconnect)) {
00420 if (debug) {
00421 alog("debug: Sending UNCONNECT SQUIT for %s", s->name);
00422 }
00423
00424 anope_cmd_squit(s->name, buf);
00425 }
00426 }
00427
00428 delete_server(s, buf);
00429 }
00430
00431
00432
00439 void capab_parse(int ac, char **av)
00440 {
00441 int i;
00442 int j;
00443 char *s, *tmp;
00444
00445 char *temp;
00446
00447 for (i = 0; i < ac; i++) {
00448 temp = av[i];
00449
00450 s = myStrGetToken(temp, '=', 0);
00451 tmp = myStrGetTokenRemainder(temp, '=', 1);
00452
00453 if (!s)
00454 continue;
00455
00456 for (j = 0; capab_info[j].token; j++) {
00457 if (stricmp(s, capab_info[j].token) == 0)
00458 uplink_capab |= capab_info[j].flag;
00459
00460 if ((stricmp(s, "NICKIP") == 0) && !ircd->nickip)
00461 ircd->nickip = 1;
00462 if ((stricmp(s, "CHANMODES") == 0) && tmp)
00463 ircd->chanmodes = sstrdup(tmp);
00464 if ((stricmp(s, "NICKCHARS") == 0) && tmp)
00465 ircd->nickchars = sstrdup(tmp);
00466 }
00467
00468 if (s)
00469 free(s);
00470 if (tmp)
00471 free(tmp);
00472 }
00473 }
00474
00475
00476
00483 int is_ulined(char *server)
00484 {
00485 int j;
00486
00487 for (j = 0; j < NumUlines; j++) {
00488 if (stricmp(Ulines[j], server) == 0) {
00489 return 1;
00490 }
00491 }
00492
00493 return 0;
00494 }
00495
00496
00497
00504 int is_sync(Server * server)
00505 {
00506 if ((server->sync == SSYNC_DONE) || (server->sync == SSYNC_UNKNOWN))
00507 return 1;
00508 return 0;
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 void finish_sync(Server * serv, int sync_links)
00520 {
00521 Server *s;
00522
00523 if (!serv || is_sync(serv))
00524 return;
00525
00526
00527 s = serv;
00528 do {
00529 if (!is_sync(s)) {
00530 if (debug)
00531 alog("debug: Finishing sync for server %s", s->name);
00532
00533 s->sync = SSYNC_DONE;
00534 }
00535
00536 if (!sync_links)
00537 break;
00538
00539 if (s->links) {
00540 s = s->links;
00541 } else if (s->next) {
00542 s = s->next;
00543 } else {
00544 do {
00545 s = s->uplink;
00546 if (s == serv)
00547 s = NULL;
00548 if (s == me_server)
00549 s = NULL;
00550 } while (s && !(s->next));
00551 if (s)
00552 s = s->next;
00553 }
00554 } while (s);
00555
00556
00557 restore_unsynced_topics();
00558 alog("Server %s is done syncing", serv->name);
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568 static int ts6_uid_initted = 0;
00569 static char ts6_new_uid[10];
00570 static unsigned int ts6_uid_index = 9;
00571
00572 void ts6_uid_init(void)
00573 {
00574 unsigned int i;
00575 char buf[BUFSIZE];
00576
00577
00578 if (TS6SID != NULL) {
00579 snprintf(ts6_new_uid, 10, "%sAAAAAA", TS6SID);
00580 ts6_uid_initted = 1;
00581 } else {
00582 alog("warning: no TS6SID specified, disabling TS6 support.");
00583 UseTS6 = 0;
00584
00585 return;
00586 }
00587 }
00588
00589 void ts6_uid_increment(unsigned int slot)
00590 {
00591 if (slot != strlen(TS6SID)) {
00592 if (ts6_new_uid[slot] == 'Z')
00593 ts6_new_uid[slot] = '0';
00594 else if (ts6_new_uid[slot] == '9') {
00595 ts6_new_uid[slot] = 'A';
00596 ts6_uid_increment(slot - 1);
00597 } else
00598 ts6_new_uid[slot]++;
00599 } else {
00600 if (ts6_new_uid[slot] == 'Z')
00601 for (slot = 3; slot < 9; slot++)
00602 ts6_new_uid[slot] = 'A';
00603 else
00604 ts6_new_uid[slot]++;
00605 }
00606 }
00607
00608 char *ts6_uid_retrieve(void)
00609 {
00610 if (ts6_uid_initted != 1)
00611 ts6_uid_init();
00612
00613 ts6_uid_increment(ts6_uid_index - 1);
00614
00615 return ts6_new_uid;
00616 }
00617
00618