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