/* * del_from_accept * * inputs - pointer to source client * - pointer to target client * output - NONE * side effects - Delete's source pointer to targets allow list * * Walk through the target's accept list, remove if source is found, * Then walk through the source's on_accept_list remove target if found. */ void del_from_accept(struct Client *source, struct Client *target) { dlink_node *ptr; dlink_node *ptr2; dlink_node *next_ptr; dlink_node *next_ptr2; struct Client *target_p; for (ptr = target->allow_list.head; ptr; ptr = next_ptr) { next_ptr = ptr->next; target_p = ptr->data; if(source == target_p) { dlinkDelete(ptr, &target->allow_list); free_dlink_node(ptr); for (ptr2 = source->on_allow_list.head; ptr2; ptr2 = next_ptr2) { next_ptr2 = ptr2->next; target_p = ptr2->data; if (target == target_p) { dlinkDelete(ptr2, &source->on_allow_list); free_dlink_node(ptr2); } } } } }
void dbuf_delete(struct dbuf_queue *qptr, size_t count) { dlink_node *ptr; struct dbuf_block *first; assert(qptr->total_size >= count); if (count == 0) return; /* free whole blocks first.. */ while (1) { if (!count) return; ptr = qptr->blocks.head; first = ptr->data; if (count < first->size) break; qptr->total_size -= first->size; count -= first->size; dlinkDelete(ptr, &qptr->blocks); free_dlink_node(ptr); BlockHeapFree(dbuf_heap, first); } /* ..then remove data from the beginning of the queue */ first->size -= count; qptr->total_size -= count; memmove((void *) &first->data, (void *) &first->data[count], first->size); }
void exit_aborted_clients(void) { dlink_node *ptr, *next; struct Client *target_p; for(ptr = abort_list.head; ptr; ptr = next) { target_p = ptr->data; next = ptr->next; if (ptr->data == NULL) { sendto_realops_flags(FLAGS_ALL, L_ALL, "Warning: null client on abort_list!"); dlinkDelete(ptr, &abort_list); free_dlink_node(ptr); continue; } dlinkDelete(ptr, &abort_list); exit_client(target_p, target_p, &me, "Dead link"); free_dlink_node(ptr); } }
static void free_exited_clients(void *unused) { dlink_node *ptr, *next; struct Client *target_p; for(ptr = dead_list.head; ptr; ptr = next) { target_p = ptr->data; next = ptr->next; if (ptr->data == NULL) { sendto_realops_flags(FLAGS_ALL, L_ALL, "Warning: null client on dead_list!"); dlinkDelete(ptr, &dead_list); free_dlink_node(ptr); continue; } release_client_state(target_p); free_client(target_p); dlinkDelete(ptr, &dead_list); free_dlink_node(ptr); } }
/* * free_channel_list * * inputs - pointer to dlink_list * output - NONE * side effects - */ static void free_channel_list(dlink_list *list) { dlink_node *ptr; dlink_node *next_ptr; struct Ban *actualBan; for (ptr = list->head; ptr; ptr = next_ptr) { next_ptr = ptr->next; actualBan = ptr->data; MyFree(actualBan->banstr); MyFree(actualBan->who); BlockHeapFree(ban_heap, actualBan); free_dlink_node(ptr); } }
/* ** mo_jupe ** parv[0] = sender prefix ** parv[1] = server we're juping ** parv[2] = reason for jupe */ static void mo_jupe(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p; struct Client *ajupe; dlink_node *m; char reason[REALLEN+2]; if(!ServerInfo.hub) return; if(!IsOperAdmin(source_p)) { sendto_one(source_p, ":%s NOTICE %s :You must be an admin to use this command", me.name, parv[0]); return; } if (bogus_host(parv[1])) { sendto_one(source_p, ":%s NOTICE %s :Invalid servername: %s", me.name, parv[0], parv[1]); return; } if(match(parv[1], me.name)) { sendto_one(source_p, ":%s NOTICE %s :I cant jupe myself!", me.name, source_p->name); return; } sendto_wallops_flags(UMODE_WALLOP, &me, "JUPE for %s requested by %s: %s", parv[1], get_oper_name(source_p), parv[2]); sendto_server(NULL, NOCAPS, NOCAPS, ":%s WALLOPS :JUPE for %s requested by %s!%s@%s: %s", parv[0], parv[1], source_p->name, source_p->username, source_p->host, parv[2]); ilog(L_NOTICE, "JUPE for %s requested by %s: %s", parv[1], get_oper_name(source_p), parv[2]); target_p= find_server(parv[1]); if(target_p) exit_client(client_p, target_p, &me, parv[2]); sendto_server(NULL, NOCAPS, NOCAPS, ":%s SERVER %s 1 :JUPED: %s", me.name, parv[1], parv[2]); sendto_realops_flags(UMODE_ALL, L_ALL, "Link with %s established: (JUPED) link", parv[1]); ajupe = make_client(NULL); /* make_client() adds client to unknown_list */ m = dlinkFind(&unknown_list, ajupe); if(m != NULL) dlinkDelete(m, &unknown_list); free_dlink_node(m); make_server(ajupe); ajupe->hopcount = 1; strlcpy(ajupe->name,parv[1],HOSTLEN); /* we need to give 7 chars to prepend "JUPED: " */ if(strlen(parv[2]) > (REALLEN-7)) parv[2][REALLEN-7] = '\0'; ircsprintf(reason, "%s %s", "JUPED:", parv[2]); strlcpy(ajupe->info,reason,REALLEN); ajupe->serv->up = me.name; ajupe->servptr = &me; SetServer(ajupe); SetDead(ajupe); Count.server++; Count.myserver++; /* Some day, all these lists will be consolidated *sigh* */ add_client_to_list(ajupe); add_to_client_hash_table(ajupe->name, ajupe); dlinkAdd(ajupe, &ajupe->lnode, &ajupe->servptr->serv->servers); add_server_to_list(ajupe); }
/*! \brief SVSMODE command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = nickname * - parv[2] = TS * - parv[3] = mode * - parv[4] = optional argument (services account, vhost) */ static int ms_svsmode(struct Client *source_p, int parc, char *parv[]) { const struct user_modes *tab = NULL; struct Client *target_p = NULL; int what = MODE_ADD; unsigned int setmodes = 0; const char *modes = NULL, *extarg = NULL; time_t ts = 0; if (!HasFlag(source_p, FLAGS_SERVICE)) return 0; ts = atol(parv[2]); modes = parv[3]; extarg = (parc > 4) ? parv[4] : NULL; if ((target_p = find_person(source_p, parv[1])) == NULL) return 0; if (ts && (ts != target_p->tsinfo)) return 0; setmodes = target_p->umodes; for (const char *m = modes; *m; ++m) { switch (*m) { case '+': what = MODE_ADD; break; case '-': what = MODE_DEL; break; case 'd': if (!EmptyString(extarg)) strlcpy(target_p->account, extarg, sizeof(target_p->account)); break; case 'x': if (!EmptyString(extarg) && valid_hostname(extarg)) user_set_hostmask(target_p, extarg, what); break; case 'o': if (what == MODE_DEL && HasUMode(target_p, UMODE_OPER)) { ClearOper(target_p); --Count.oper; if (MyConnect(target_p)) { dlink_node *node = NULL; detach_conf(target_p, CONF_OPER); ClrOFlag(target_p); DelUMode(target_p, ConfigGeneral.oper_only_umodes); if ((node = dlinkFindDelete(&oper_list, target_p))) free_dlink_node(node); } } break; case 'i': if (what == MODE_ADD && !HasUMode(target_p, UMODE_INVISIBLE)) { AddUMode(target_p, UMODE_INVISIBLE); ++Count.invisi; } if (what == MODE_DEL && HasUMode(target_p, UMODE_INVISIBLE)) { DelUMode(target_p, UMODE_INVISIBLE); --Count.invisi; } break; case 'S': /* Only servers may set +S in a burst */ case 'W': /* Only servers may set +W in a burst */ break; default: if ((tab = umode_map[(unsigned char)*m])) { if (what == MODE_ADD) AddUMode(target_p, tab->flag); else DelUMode(target_p, tab->flag); } break; } } if (extarg) sendto_server(source_p, 0, 0, ":%s SVSMODE %s %lu %s %s", source_p->id, target_p->id, (unsigned long)target_p->tsinfo, modes, extarg); else sendto_server(source_p, 0, 0, ":%s SVSMODE %s %lu %s", source_p->id, target_p->id, (unsigned long)target_p->tsinfo, modes); if (MyConnect(target_p) && (setmodes != target_p->umodes)) { char modebuf[IRCD_BUFSIZE] = ""; send_umode(target_p, target_p, setmodes, modebuf); } return 0; }
/*! \brief SVSMODE command handler (called by services) * * \param client_p Pointer to allocated Client struct with physical connection * to this server, i.e. with an open socket connected. * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = sender prefix * - parv[1] = nickname * - parv[2] = TS (or mode, depending on svs version) * - parv[3] = mode (or services id if old svs version) * - parv[4] = optional argument (services id) */ static void ms_svsmode(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p = NULL; int what = MODE_ADD; unsigned int flag = 0, setflags = 0; char *m = NULL, *modes = NULL, *extarg = NULL; time_t ts = 0; if (!HasFlag(source_p, FLAGS_SERVICE)) return; if ((parc >= 4) && ((*parv[3] == '+') || (*parv[3] == '-'))) { ts = atol(parv[2]); modes = parv[3]; extarg = (parc > 4) ? parv[4] : NULL; } else { modes = parv[2]; extarg = (parc > 3) ? parv[3] : NULL; } if ((target_p = find_person(client_p, parv[1])) == NULL) return; if (ts && (ts != target_p->tsinfo)) return; setflags = target_p->umodes; for (m = modes; *m; ++m) { switch (*m) { case '+': what = MODE_ADD; break; case '-': what = MODE_DEL; break; case 'x': if (what == MODE_ADD && extarg) user_set_hostmask(target_p, extarg); break; case 'd': if (!EmptyString(extarg)) strlcpy(target_p->svid, extarg, sizeof(target_p->svid)); break; case 'o': if (what == MODE_DEL && HasUMode(target_p, UMODE_OPER)) { ClearOper(target_p); Count.oper--; if (MyConnect(target_p)) { dlink_node *dm = NULL; detach_conf(target_p, OPER_TYPE); ClrOFlag(target_p); DelUMode(target_p, ConfigFileEntry.oper_only_umodes); if ((dm = dlinkFindDelete(&oper_list, target_p)) != NULL) free_dlink_node(dm); } } break; case 'i': if (what == MODE_ADD && !HasUMode(target_p, UMODE_INVISIBLE)) { AddUMode(target_p, UMODE_INVISIBLE); ++Count.invisi; } if (what == MODE_DEL && HasUMode(target_p, UMODE_INVISIBLE)) { DelUMode(target_p, UMODE_INVISIBLE); --Count.invisi; } break; case ' ': case '\n': case '\r': case '\t': break; default: if ((flag = user_modes[(unsigned char) * m])) execute_callback(umode_cb, client_p, target_p, what, flag); break; } } if (extarg) { sendto_server(client_p, CAP_TS6, NOCAPS, ":%s SVSMODE %s %lu %s %s", ID(source_p), ID(target_p), (unsigned long)target_p->tsinfo, modes, extarg); sendto_server(client_p, NOCAPS, CAP_TS6, ":%s SVSMODE %s %lu %s %s", source_p->name, target_p->name, (unsigned long)target_p->tsinfo, modes, extarg); } else { sendto_server(client_p, CAP_TS6, NOCAPS, ":%s SVSMODE %s %lu %s", ID(source_p), ID(target_p), (unsigned long)target_p->tsinfo, modes); sendto_server(client_p, NOCAPS, CAP_TS6, ":%s SVSMODE %s %lu %s", source_p->name, target_p->name, (unsigned long)target_p->tsinfo, modes); } if (MyConnect(target_p) && (setflags != target_p->umodes)) { char modebuf[IRCD_BUFSIZE]; send_umode(target_p, target_p, setflags, 0xffffffff, modebuf); } }
/* ** exit_client - This is old "m_bye". Name changed, because this is not a ** protocol function, but a general server utility function. ** ** This function exits a client of *any* type (user, server, etc) ** from this server. Also, this generates all necessary prototol ** messages that this exit may cause. ** ** 1) If the client is a local client, then this implicitly ** exits all other clients depending on this connection (e.g. ** remote clients having 'from'-field that points to this. ** ** 2) If the client is a remote client, then only this is exited. ** ** For convenience, this function returns a suitable value for ** m_function return value: ** ** CLIENT_EXITED if (client_p == source_p) ** 0 if (client_p != source_p) */ int exit_client( struct Client* client_p, /* The local client originating the * exit or NULL, if this exit is * generated by this server for * internal reasons. * This will not get any of the * generated messages. */ struct Client* source_p, /* Client exiting */ struct Client* from, /* Client firing off this Exit, * never NULL! */ const char* comment /* Reason for the exit */ ) { char comment1[HOSTLEN + HOSTLEN + 2]; dlink_node *m; fprintf(stderr, "Exiting client: %s\n", comment); if (MyConnect(source_p)) { /* DO NOT REMOVE. exit_client can be called twice after a failed * read/write. */ if(IsClosing(source_p)) return 0; SetClosing(source_p); if (source_p->flags & FLAGS_IPHASH) remove_one_ip(&source_p->localClient->ip); delete_adns_queries(source_p->localClient->dns_query); delete_identd_queries(source_p); client_flush_input(source_p); /* This source_p could have status of one of STAT_UNKNOWN, STAT_CONNECTING * STAT_HANDSHAKE or STAT_UNKNOWN * all of which are lumped together into unknown_list * * In all above cases IsRegistered() will not be true. */ if (!IsRegistered(source_p)) { m = dlinkFind(&unknown_list,source_p); if(m != NULL) { dlinkDelete(m, &unknown_list); free_dlink_node(m); } } if (IsOper(source_p)) { m = dlinkFind(&oper_list,source_p); if(m != NULL) { dlinkDelete(m, &oper_list); free_dlink_node(m); } } if (IsClient(source_p)) { Count.local--; if(IsPerson(source_p)) /* a little extra paranoia */ { m = dlinkFind(&lclient_list,source_p); if(m != NULL) { dlinkDelete(m,&lclient_list); free_dlink_node(m); } } } /* As soon as a client is known to be a server of some sort * it has to be put on the serv_list, or SJOIN's to this new server * from the connect burst will not be seen. */ if (IsServer(source_p) || IsConnecting(source_p) || IsHandshake(source_p)) { m = dlinkFind(&serv_list,source_p); if(m != NULL) { dlinkDelete(m,&serv_list); free_dlink_node(m); unset_chcap_usage_counts(source_p); } } if (IsServer(source_p)) { Count.myserver--; if(ServerInfo.hub) remove_lazylink_flags(source_p->localClient->serverMask); else uplink = NULL; } if (IsPerson(source_p)) sendto_realops_flags(FLAGS_CCONN, L_ALL, "Client exiting: %s (%s@%s) [%s] [%s]", source_p->name, source_p->username, source_p->host, comment, source_p->localClient->sockhost); log_user_exit(source_p); if (source_p->localClient->fd >= 0) { if (client_p != NULL && source_p != client_p) sendto_one(source_p, "ERROR :Closing Link: %s %s (%s)", source_p->host, source_p->name, comment); else sendto_one(source_p, "ERROR :Closing Link: %s (%s)", source_p->host, comment); } /* ** Currently only server connections can have ** depending remote clients here, but it does no ** harm to check for all local clients. In ** future some other clients than servers might ** have remotes too... ** ** Close the Client connection first and mark it ** so that no messages are attempted to send to it. ** (The following *must* make MyConnect(source_p) == FALSE!). ** It also makes source_p->from == NULL, thus it's unnecessary ** to test whether "source_p != target_p" in the following loops. */ close_connection(source_p); } if(IsServer(source_p)) { if(ConfigServerHide.hide_servers) { /* set netsplit message to "me.name *.split" to still show * that its a split, but hide the servers splitting */ ircsprintf(comment1,"%s *.split", me.name); } else { if((source_p->serv) && (source_p->serv->up)) strcpy(comment1, source_p->serv->up); else strcpy(comment1, "<Unknown>"); strcat(comment1," "); strcat(comment1, source_p->name); } remove_dependents(client_p, source_p, from, comment, comment1); if (source_p->servptr == &me) { sendto_realops_flags(FLAGS_ALL, L_ALL, "%s was connected for %d seconds. %d/%d sendK/recvK.", source_p->name, (int)(CurrentTime - source_p->firsttime), source_p->localClient->sendK, source_p->localClient->receiveK); ilog(L_NOTICE, "%s was connected for %d seconds. %d/%d sendK/recvK.", source_p->name, CurrentTime - source_p->firsttime, source_p->localClient->sendK, source_p->localClient->receiveK); } } exit_one_client(client_p, source_p, from, comment); return client_p == source_p ? CLIENT_EXITED : 0; }
/* set_user_mode() * * added 15/10/91 By Darren Reed. * parv[0] - command * parv[1] - username to change mode for * parv[2] - modes to change */ static void set_user_mode(struct Client *source_p, const int parc, char *parv[]) { const struct user_modes *tab = NULL; const unsigned int setmodes = source_p->umodes; const struct Client *target_p = NULL; int what = MODE_ADD, badmode = 0; if ((target_p = find_person(source_p, parv[1])) == NULL) { if (MyConnect(source_p)) sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]); return; } if (source_p != target_p) { sendto_one_numeric(source_p, &me, ERR_USERSDONTMATCH); return; } if (parc < 3) { char buf[IRCD_BUFSIZE] = ""; char *m = buf; *m++ = '+'; for (tab = umode_tab; tab->c; ++tab) if (HasUMode(source_p, tab->flag)) *m++ = tab->c; *m = '\0'; sendto_one_numeric(source_p, &me, RPL_UMODEIS, buf); return; } /* Parse user mode change string */ for (const char *m = parv[2]; *m; ++m) { switch (*m) { case '+': what = MODE_ADD; break; case '-': what = MODE_DEL; break; case 'o': if (what == MODE_ADD) { if (!MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER)) { ++Count.oper; SetOper(source_p); } } else { if (!HasUMode(source_p, UMODE_OPER)) break; ClearOper(source_p); --Count.oper; if (MyConnect(source_p)) { dlink_node *node = NULL; detach_conf(source_p, CONF_OPER); ClrOFlag(source_p); DelUMode(source_p, ConfigGeneral.oper_only_umodes); if ((node = dlinkFindDelete(&oper_list, source_p))) free_dlink_node(node); } } break; case 'S': /* Only servers may set +S in a burst */ case 'W': /* Only servers may set +W in a burst */ case 'r': /* Only services may set +r */ case 'x': /* Only services may set +x */ break; default: if ((tab = umode_map[(unsigned char)*m])) { if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER) && (ConfigGeneral.oper_only_umodes & tab->flag)) badmode = 1; else { if (what == MODE_ADD) AddUMode(source_p, tab->flag); else DelUMode(source_p, tab->flag); } } else if (MyConnect(source_p)) badmode = 1; break; } } if (badmode) sendto_one_numeric(source_p, &me, ERR_UMODEUNKNOWNFLAG); if (MyConnect(source_p) && HasUMode(source_p, UMODE_ADMIN) && !HasOFlag(source_p, OPER_FLAG_ADMIN)) { sendto_one_notice(source_p, &me, ":*** You have no admin flag;"); DelUMode(source_p, UMODE_ADMIN); } if (!(setmodes & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE)) ++Count.invisi; if ((setmodes & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE)) --Count.invisi; /* * Compare new modes with old modes and send string which will cause * servers to update correctly. */ send_umode_out(source_p, setmodes); }