/* Check whether a fatal signal has occurred and, if so, call the fatal signal * hooks and exit. * * This function is called automatically by poll_block(), but specialized * programs that may not always call poll_block() on a regular basis should * also call it periodically. (Therefore, any function with "block" in its * name should call fatal_signal_run() each time it is called, either directly * or through poll_block(), because such functions can only used by specialized * programs that can afford to block outside their main loop around * poll_block().) */ void fatal_signal_run(void) { sig_atomic_t sig_nr; fatal_signal_init(); sig_nr = stored_sig_nr; if (sig_nr != SIG_ATOMIC_MAX) { char namebuf[SIGNAL_NAME_BUFSIZE]; ovs_mutex_lock(&mutex); VLOG_WARN("terminating with signal %d (%s)", (int)sig_nr, signal_name(sig_nr, namebuf, sizeof namebuf)); call_hooks(sig_nr); /* Re-raise the signal with the default handling so that the program * termination status reflects that we were killed by this signal */ signal(sig_nr, SIG_DFL); raise(sig_nr); ovs_mutex_unlock(&mutex); OVS_NOT_REACHED(); } }
static void atexit_handler(void) { if (!disabled) { call_hooks(0); } }
static ad_conn_t *conn_new(ad_server_t *server, struct bufferevent *buffer) { if (server == NULL || buffer == NULL) { return NULL; } // Create a new connection container. ad_conn_t *conn = NEW_OBJECT(ad_conn_t); if (conn == NULL) return NULL; // Initialize with default values. conn->server = server; conn->buffer = buffer; conn->in = bufferevent_get_input(buffer); conn->out = bufferevent_get_output(buffer); conn_reset(conn); // Bind callback bufferevent_setcb(buffer, conn_read_cb, conn_write_cb, conn_event_cb, (void *)conn); bufferevent_setwatermark(buffer, EV_WRITE, 0, 0); bufferevent_enable(buffer, EV_WRITE); bufferevent_enable(buffer, EV_READ); // Run callbacks with AD_EVENT_INIT event. conn->status = call_hooks(AD_EVENT_INIT | AD_EVENT_WRITE, conn); return conn; }
//:FUNCTION direct_flip_obj //Handle parser checks for "flip OBJ" mixed direct_flip_obj(object ob) { if(!default_object_checks()) return 0; //:HOOK direct_flip //A yes/no/error hook called by direct_flip_obj(); if no hooks exists, the //useless message will be used. return call_hooks("direct_flip", HOOK_YES_NO_ERROR, useless( "Fiddling with " + ob->the_short())); }
/* Handles fatal signal number 'sig_nr'. * * Ordinarily this is the actual signal handler. When other code needs to * handle one of our signals, however, it can register for that signal and, if * and when necessary, call this function to do fatal signal processing for it * and terminate the process. Currently only timeval.c does this, for SIGALRM. * (It is not important whether the other code sets up its signal handler * before or after this file, because this file will only set up a signal * handler in the case where the signal has its default handling.) */ void fatal_signal_handler(int sig_nr) { call_hooks(sig_nr); /* Re-raise the signal with the default handling so that the program * termination status reflects that we were killed by this signal */ signal(sig_nr, SIG_DFL); raise(sig_nr); }
delusergo() { static char forward[200]; static char forwardto[200]; FILE *fs; int i; struct vqpasswd *pw; if ( AdminType!=DOMAIN_ADMIN ) { sprintf(StatusMessage,"%s", get_html_text("142")); vclose(); exit(0); } vdeluser( ActionUser, Domain ); /* Start create forward when delete - * Code added by Eugene Teo 6 June 2000 */ GetValue(TmpCGI,forward, "forward=", MAX_BUFF); #ifdef DEBUG fprintf(actout, "Forward: %s\n<br>", forward); #endif if (strcmp(forward, "on") == 0) { /* replace "." in name with ":" */ sprintf(TmpBuf2, ".qmail-%s", ActionUser); for(i=6;TmpBuf2[i]!=0;++i) if ( TmpBuf2[i] == '.' ) TmpBuf2[i] = ':'; if ((fs=fopen(TmpBuf2,"w")) == NULL) ack("Failed to open passwd file",21); GetValue(TmpCGI, forwardto, "forwardto=", MAX_BUFF); #ifdef DEBUG fprintf(actout, "Forward to: %s\n<br>", forwardto); #endif fprintf(fs, "&%s", forwardto); fclose(fs); /* End create forward when delete - * Code added by Eugene Teo 6 June 2000 */ } sprintf(StatusMessage, "%s %s", ActionUser, get_html_text("141")); call_hooks(HOOK_DELUSER); show_users(Username, Domain, Mytime); }
//! //! Main entry point of the application //! //! @param[in] argc the number of parameter passed on the command line //! @param[in] argv the list of arguments //! //! @return Always return 0 //! int main(int argc, char **argv) { int status = 0; char d[MAX_PATH] = "/tmp/euca-XXXXXX"; char h0[MAX_PATH] = ""; char h1[MAX_PATH] = ""; char h3[MAX_PATH] = ""; char h4[MAX_PATH] = ""; assert(call_hooks("e1", NULL) != 0); assert(call_hooks("e1", "p1") != 0); assert(init_hooks("/tmp", "/foobar") != 0); assert(init_hooks("/foobar", "/tmp") != 0); assert(mkdtemp(d) != NULL); assert(init_hooks("/tmp", d) == 0); snprintf(h1, sizeof(h1), "%s/h1", d); write2file(h1, "#!/bin/bash\necho h1 -$1- -$2- -$3-\n"); chmod(h1, S_IXUSR | S_IRUSR); snprintf(h3, sizeof(h3), "%s/h3", d); write2file(h3, "#!/bin/bash\necho h3 -$1- -$2- -$3-\n"); chmod(h3, 0); // unreadable hook snprintf(h4, sizeof(h4), "%s/h4", d); mkdir(h4, 0700); // not a file assert(call_hooks("e1", NULL) == 0); assert(call_hooks("e1", "p1") == 0); snprintf(h0, sizeof(h0), "%s/h0", d); write2file(h0, "#!/bin/bash\nexit 99;\n"); chmod(h0, S_IXUSR | S_IRUSR); assert(call_hooks("e1", "p1") == 99); assert(rmdir(h4) == 0); assert(unlink(h3) == 0); assert(unlink(h0) == 0); assert(unlink(h1) == 0); assert(rmdir(d) == 0); printf("removed directory %s\n", d); return (status); }
//:FUNCTION direct_drop_obj //Handle parser checks for "drop OBJ" mixed direct_drop_obj(object ob) { if(!default_object_checks()) return 0; if ( environment() != this_body() ) return "#You don't have it!\n"; //:HOOK prevent_drop //A yes/no/error hook called by direct_drop_obj() if the standard conditions //succeed return call_hooks("prevent_drop", HOOK_YES_NO_ERROR); }
/* Check whether a fatal signal has occurred and, if so, call the fatal signal * hooks and exit. * * This function is called automatically by poll_block(), but specialized * programs that may not always call poll_block() on a regular basis should * also call it periodically. (Therefore, any function with "block" in its * name should call fatal_signal_run() each time it is called, either directly * or through poll_block(), because such functions can only used by specialized * programs that can afford to block outside their main loop around * poll_block().) */ void fatal_signal_run(void) { int sig_nr; fatal_signal_init(); sig_nr = stored_sig_nr; if (sig_nr != SIG_ATOMIC_MAX) { call_hooks(sig_nr); /* Re-raise the signal with the default handling so that the program * termination status reflects that we were killed by this signal */ signal(sig_nr, SIG_DFL); raise(sig_nr); } }
/* Check whether a fatal signal has occurred and, if so, call the fatal signal * hooks and exit. * * This function is called automatically by poll_block(), but specialized * programs that may not always call poll_block() on a regular basis should * also call it periodically. (Therefore, any function with "block" in its * name should call fatal_signal_run() each time it is called, either directly * or through poll_block(), because such functions can only used by specialized * programs that can afford to block outside their main loop around * poll_block().) */ void fatal_signal_run(void) { sig_atomic_t sig_nr; fatal_signal_init(); sig_nr = stored_sig_nr; if (sig_nr != SIG_ATOMIC_MAX) { VLOG_WARN("terminating with signal %d (%s)", (int)sig_nr, signal_name(sig_nr)); call_hooks(sig_nr); /* Re-raise the signal with the default handling so that the program * termination status reflects that we were killed by this signal */ signal(sig_nr, SIG_DFL); raise(sig_nr); } }
//:FUNCTION direct_get_obj //Do some checks for the parser when we are the OBJ of the "get OBJ" rule mixed direct_get_obj(object ob) { object who = owner(ob); if ( environment() == this_body() ) return "#You already have it!\n"; if ( who && who != this_body() ) return "#Too bad you're not a skilled pickpocket.\n"; if ( this_object() == this_body() ) return "#You make an advance on yourself.\n"; if (environment(this_object())!=environment(this_body())) return "#You cannot get that."; if(!default_object_checks()) return 0; //:HOOK prevent_get //A yes/no/error hook called by direct_get_obj() if the standard conditions //succeed return call_hooks("prevent_get", HOOK_YES_NO_ERROR); }
static void conn_free(ad_conn_t *conn) { if (conn) { if (conn->status != AD_CLOSE) { call_hooks(AD_EVENT_CLOSE | AD_EVENT_SHUTDOWN , conn); } conn_reset(conn); if (conn->buffer) { if (conn->server->sslctx) { int sslerr = bufferevent_get_openssl_error(conn->buffer); if (sslerr) { char errmsg[256]; ERR_error_string_n(sslerr, errmsg, sizeof(errmsg)); ERROR("SSL %s (err:%d)", errmsg, sslerr); } } bufferevent_free(conn->buffer); } free(conn); } }
void fatal_signal_atexit_handler(void) { call_hooks(0); }
//:FUNCTION direct_get_obj_from_obj //Handle parser checks for "get OBJ from OBJ" //From doesn't care what relation Object 1 is in. mixed direct_get_obj_from_obj(object ob1, object ob2) { if (ob2 != 0 && environment(ob1) != ob2) return 0; return call_hooks("prevent_get", HOOK_YES_NO_ERROR); }
static void atexit_handler(void) { call_hooks(0); }
/* * 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: * * FLUSH_BUFFER if (cptr == sptr) * 0 if (cptr != sptr) */ int exit_client(aClient *cptr, aClient *sptr, aClient *from, char *comment) { #ifdef FNAME_USERLOG time_t on_for; #endif if (MyConnect(sptr)) { call_hooks(CHOOK_SIGNOFF, sptr); if (IsUnknown(sptr)) Count.unknown--; if (IsAnOper(sptr)) remove_from_list(&oper_list, sptr, NULL); if (sptr->flags & FLAGS_HAVERECVQ) { /* mark invalid, will be deleted in do_recvqs() */ DLink *lp = find_dlink(recvq_clients, sptr); if (lp) lp->flags = -1; } if (IsClient(sptr)) Count.local--; if (IsNegoServer(sptr)) sendto_realops("Lost server %s during negotiation: %s", sptr->name, comment); if (IsServer(sptr)) { Count.myserver--; if (IsULine(sptr)) Count.myulined--; remove_from_list(&server_list, sptr, NULL); if (server_list == NULL) server_was_split = YES; } sptr->flags |= FLAGS_CLOSING; if (IsPerson(sptr)) { Link *lp, *next; LOpts *lopt = sptr->user->lopt; /* poof goes their watchlist! */ hash_del_watch_list(sptr); /* if they have listopts, axe those, too */ if(lopt != NULL) { remove_from_list(&listing_clients, sptr, NULL); for (lp = lopt->yeslist; lp; lp = next) { next = lp->next; MyFree(lp->value.cp); free_link(lp); } for (lp = lopt->nolist; lp; lp = next) { next = lp->next; MyFree(lp->value.cp); free_link(lp); } MyFree(sptr->user->lopt); sptr->user->lopt = NULL; } sendto_realops_lev(CCONN_LEV, "Client exiting: %s (%s@%s) [%s] [%s]", sptr->name, sptr->user->username, sptr->user->host, (sptr->flags & FLAGS_NORMALEX) ? "Client Quit" : comment, sptr->hostip); } #ifdef FNAME_USERLOG on_for = timeofday - sptr->firsttime; #endif #if defined(USE_SYSLOG) && defined(SYSLOG_USERS) if (IsPerson(sptr)) syslog(LOG_NOTICE, "%s (%3d:%02d:%02d): %s!%s@%s %d/%d\n", myctime(sptr->firsttime), on_for / 3600, (on_for % 3600) / 60, on_for % 60, sptr->name, sptr->user->username, sptr->user->host, sptr->sendK, sptr->receiveK); #endif #if defined(FNAME_USERLOG) { char linebuf[300]; static int logfile = -1; static long lasttime; /* * This conditional makes the logfile active only after it's * been created - thus logging can be turned off by removing * the file. * * stop NFS hangs...most systems should be able to open a file in * 3 seconds. -avalon (curtesy of wumpus) * * Keep the logfile open, syncing it every 10 seconds -Taner */ if (IsPerson(sptr)) { if (logfile == -1) { alarm(3); logfile = open(FNAME_USERLOG, O_WRONLY | O_APPEND); alarm(0); } ircsprintf(linebuf, "%s (%3d:%02d:%02d): %s!%s@%s %d/%d\n", myctime(sptr->firsttime), on_for / 3600, (on_for % 3600) / 60, on_for % 60, sptr->name, sptr->user->username, sptr->user->host, sptr->sendK, sptr->receiveK); alarm(3); write(logfile, linebuf, strlen(linebuf)); alarm(0); /* Resync the file evey 10 seconds*/ if (timeofday - lasttime > 10) { alarm(3); close(logfile); alarm(0); logfile = -1; lasttime = timeofday; } } } #endif if (sptr->fd >= 0) { if (cptr != NULL && sptr != cptr) sendto_one(&me, sptr, "ERROR :Closing Link: %s %s (%s)", IsPerson(sptr) ? sptr->sockhost : "0.0.0.0", sptr->name, comment); else sendto_one(&me, sptr, "ERROR :Closing Link: %s (%s)", IsPerson(sptr) ? sptr->sockhost : "0.0.0.0", 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(sptr) == FALSE!). * It also makes sptr->from == * NULL, thus it's unnecessary * to test whether "sptr != acptr" * in the following loops. */ if (IsServer(sptr)) { sendto_ops("%s was connected for %lu seconds. %lu/%lu " "sendK/recvK.", sptr->name, (long)(timeofday - sptr->firsttime), sptr->sendK, sptr->receiveK); #ifdef USE_SYSLOG syslog(LOG_NOTICE, "%s was connected for %lu seconds. %lu/%lu " "sendK/recvK.", sptr->name, (u_long) timeofday - sptr->firsttime, sptr->sendK, sptr->receiveK); #endif close_connection(sptr); sptr->sockerr = 0; sptr->flags |= FLAGS_DEADSOCKET; } else { close_connection(sptr); sptr->sockerr = 0; sptr->flags |= FLAGS_DEADSOCKET; } } exit_one_client(cptr, sptr, from, comment); return cptr == sptr ? FLUSH_BUFFER : 0; }
/* * m_nick * parv[0] = sender prefix * parv[1] = nickname * parv[2] = hopcount when new user; TS when nick change * parv[3] = TS * ---- new user only below ---- * parv[4] = umode * parv[5] = username * parv[6] = hostname * parv[7] = server * parv[8] = serviceid * parv[9] = IP * parv[10] = ircname * -- endif */ int m_nick(aClient *cptr, aClient *sptr, int parc, char *parv[]) { struct simBan *ban; aClient *acptr, *uplink; Link *lp, *lp2; char nick[NICKLEN + 2]; ts_val newts = 0; int sameuser = 0, samenick = 0; if (parc < 2) { sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]); return 0; } if (!IsServer(sptr) && IsServer(cptr) && parc > 2) newts = atol(parv[2]); else if (IsServer(sptr) && parc > 3) newts = atol(parv[3]); else parc = 2; /* * parc == 2 on a normal client sign on (local) and a normal client * nick change * parc == 4 on a normal server-to-server client nick change * parc == 11 on a normal TS style server-to-server NICK introduction */ if ((IsServer(sptr) || (parc > 4)) && (parc < 11)) { /* * We got the wrong number of params. Someone is trying to trick * us. Kill it. -ThemBones As discussed with ThemBones, not much * point to this code now sending a whack of global kills would * also be more annoying then its worth, just note the problem, * and continue -Dianora */ sendto_realops("IGNORING BAD NICK: %s[%s@%s] on %s (from %s)", parv[1], (parc >= 6) ? parv[5] : "-", (parc >= 7) ? parv[6] : "-", (parc >= 8) ? parv[7] : "-", parv[0]); return 0; } strncpyzt(nick, parv[1], NICKLEN + 1); /* * if do_nick_name() returns a null name OR if the server sent a * nick name and do_nick_name() changed it in some way (due to rules * of nick creation) then reject it. If from a server and we reject * it, and KILL it. -avalon 4/4/92 */ if (do_nick_name(nick) == 0 || (IsServer(cptr) && strcmp(nick, parv[1]))) { sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, parv[0], parv[1], "Erroneous Nickname"); if (IsServer(cptr)) { ircstp->is_kill++; sendto_realops_lev(DEBUG_LEV, "Bad Nick: %s From: %s Via: %s", parv[1], parv[0], get_client_name(cptr, HIDEME)); sendto_one(cptr, ":%s KILL %s :%s (Bad Nick)", me.name, parv[1], me.name); if (sptr != cptr) { /* bad nick change */ sendto_serv_butone(cptr, ":%s KILL %s :%s (Bad Nick)", me.name, parv[0], me.name); sptr->flags |= FLAGS_KILLED; return exit_client(cptr, sptr, &me, "BadNick"); } } return 0; } /* * Check against nick name collisions. * * Put this 'if' here so that the nesting goes nicely on the screen * :) We check against server name list before determining if the * nickname is present in the nicklist (due to the way the below * for loop is constructed). -avalon */ do { if ((acptr = find_server(nick, NULL))) if (MyConnect(sptr)) { sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name, BadPtr(parv[0]) ? "*" : parv[0], nick); return 0; } /* * acptr already has result from find_server * Well. unless we have a capricious server on the net, a nick can * never be the same as a server name - Dianora * That's not the only case; maybe someone broke do_nick_name * or changed it so they could use "." in nicks on their network * - sedition */ if (acptr) { /* * We have a nickname trying to use the same name as a * server. Send out a nick collision KILL to remove the * nickname. As long as only a KILL is sent out, there is no * danger of the server being disconnected. Ultimate way to * jupiter a nick ? >;-). -avalon */ sendto_realops_lev(SKILL_LEV, "Nick collision on %s", sptr->name); ircstp->is_kill++; sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)", me.name, sptr->name, me.name); sptr->flags |= FLAGS_KILLED; return exit_client(cptr, sptr, &me, "Nick/Server collision"); } if (!(acptr = find_client(nick, NULL))) break; /* * If acptr == sptr, then we have a client doing a nick change * between *equivalent* nicknames as far as server is concerned * (user is changing the case of his/her nickname or somesuch) */ if (acptr == sptr) { if (strcmp(acptr->name, nick) == 0) return 0; else break; } /* If user is changing nick to itself no point in propogating */ /* * Note: From this point forward it can be assumed that acptr != * sptr (point to different client structures). * * If the older one is "non-person", the new entry is just * allowed to overwrite it. Just silently drop non-person, and * proceed with the nick. This should take care of the "dormant * nick" way of generating collisions... */ if (IsUnknown(acptr)) { if (MyConnect(acptr)) { exit_client(NULL, acptr, &me, "Overridden"); break; } else if (!(acptr->user)) { sendto_realops_lev(SKILL_LEV, "Nick Collision on %s", parv[1]); sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)", me.name, acptr->name, me.name); acptr->flags |= FLAGS_KILLED; /* Having no USER struct should be ok... */ return exit_client(cptr, acptr, &me, "Got TS NICK before Non-TS USER"); } } if (!IsServer(cptr)) { /* * NICK is coming from local client connection. Just send * error reply and ignore the command. * parv[0] is empty on connecting clients */ sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name, BadPtr(parv[0]) ? "*" : parv[0], nick); return 0; } /* * NICK was coming from a server connection. Means that the same * nick is registered for different users by different server. * This is either a race condition (two users coming online about * same time, or net reconnecting) or just two net fragments * becoming joined and having same nicks in use. We cannot have * TWO users with same nick--purge this NICK from the system with * a KILL... >;) * * Changed to something reasonable like IsServer(sptr) (true if * "NICK new", false if ":old NICK new") -orabidoo */ if (IsServer(sptr)) { /* * A new NICK being introduced by a neighbouring server (e.g. * message type "NICK new" received) */ if (!newts || !acptr->tsinfo || (newts == acptr->tsinfo)) { sendto_realops_lev(SKILL_LEV, "Nick collision on %s", parv[1]); ircstp->is_kill++; sendto_one(acptr, err_str(ERR_NICKCOLLISION), me.name, acptr->name, acptr->name); sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)", me.name, acptr->name, me.name); acptr->flags |= FLAGS_KILLED; return exit_client(cptr, acptr, &me, "Nick collision"); } else { /* XXX This looks messed up to me XXX - Raist */ sameuser = (acptr->user) && mycmp(acptr->user->username, parv[5]) == 0 && mycmp(acptr->user->host, parv[6]) == 0; if ((sameuser && newts < acptr->tsinfo) || (!sameuser && newts > acptr->tsinfo)) { return 0; } else { sendto_realops_lev(SKILL_LEV, "Nick collision on %s",parv[1]); ircstp->is_kill++; sendto_one(acptr, err_str(ERR_NICKCOLLISION), me.name, acptr->name, acptr->name); sendto_serv_butone(sptr, ":%s KILL %s :%s (Nick Collision)", me.name, acptr->name, me.name); acptr->flags |= FLAGS_KILLED; (void) exit_client(cptr, acptr, &me, "Nick collision"); break; } } } /* * * A NICK change has collided (e.g. message type * ":old NICK * new". This requires more complex cleanout. * Both clients must be * purged from this server, the "new" * must be killed from the * incoming connection, and "old" must * be purged from all outgoing * connections. */ if (!newts || !acptr->tsinfo || (newts == acptr->tsinfo) || !sptr->user) { sendto_realops_lev(SKILL_LEV, "Nick change collision: %s", parv[1]); ircstp->is_kill++; sendto_one(acptr, err_str(ERR_NICKCOLLISION), me.name, acptr->name, acptr->name); sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",me.name, sptr->name, me.name); ircstp->is_kill++; sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",me.name, acptr->name, me.name); acptr->flags |= FLAGS_KILLED; (void) exit_client(NULL, acptr, &me, "Nick collision(new)"); sptr->flags |= FLAGS_KILLED; return exit_client(cptr, sptr, &me, "Nick collision(old)"); } else { /* XXX This looks messed up XXX */ sameuser = mycmp(acptr->user->username, sptr->user->username) == 0 && mycmp(acptr->user->host, sptr->user->host) == 0; if ((sameuser && newts < acptr->tsinfo) || (!sameuser && newts > acptr->tsinfo)) { if (sameuser) sendto_realops_lev(SKILL_LEV, "Nick change collision from %s to %s", sptr->name, acptr->name); ircstp->is_kill++; sendto_serv_butone(cptr, ":%s KILL %s :%s (Nick Collision)", me.name, sptr->name, me.name); sptr->flags |= FLAGS_KILLED; if (sameuser) return exit_client(cptr, sptr, &me, "Nick collision(old)"); else return exit_client(cptr, sptr, &me, "Nick collision(new)"); } else { sendto_realops_lev(SKILL_LEV, "Nick collision on %s", acptr->name); ircstp->is_kill++; sendto_one(acptr, err_str(ERR_NICKCOLLISION), me.name, acptr->name, acptr->name); sendto_serv_butone(sptr, ":%s KILL %s :%s (Nick Collision)",me.name, acptr->name, me.name); acptr->flags |= FLAGS_KILLED; (void) exit_client(cptr, acptr, &me, "Nick collision"); } } } while (0); if (IsServer(sptr)) { uplink = find_server(parv[7], NULL); if(!uplink) { /* if we can't find the server this nick is on, * complain loudly and ignore it. - lucas */ sendto_realops("Remote nick %s on UNKNOWN server %s", nick, parv[7]); return 0; } sptr = make_client(cptr, uplink); /* If this is on a U: lined server, it's a U: lined client. */ if(IsULine(uplink)) sptr->flags|=FLAGS_ULINE; add_client_to_list(sptr); if (parc > 2) sptr->hopcount = atoi(parv[2]); if (newts) { sptr->tsinfo = newts; } else { newts = sptr->tsinfo = (ts_val) timeofday; ts_warn("Remote nick %s introduced without a TS", nick); } /* copy the nick in place */ (void) strcpy(sptr->name, nick); (void) add_to_client_hash_table(nick, sptr); if (parc >= 10) { int *s, flag; char *m; /* parse the usermodes -orabidoo */ m = &parv[4][1]; while (*m) { for (s = user_modes; (flag = *s); s += 2) if (*m == *(s + 1)) { if ((flag == UMODE_o) || (flag == UMODE_O)) Count.oper++; sptr->umode |= flag & SEND_UMODES; break; } m++; } if (parc==10) { return do_user(nick, cptr, sptr, parv[5], parv[6], parv[7], strtoul(parv[8], NULL, 0), "0.0.0.0", parv[9]); } else if (parc==11) { return do_user(nick, cptr, sptr, parv[5], parv[6], parv[7], strtoul(parv[8], NULL, 0), parv[9], parv[10]); } } } else if (sptr->name[0]) { #ifdef DONT_CHECK_QLINE_REMOTE if (MyConnect(sptr)) { #endif if ((ban = check_mask_simbanned(nick, SBAN_NICK))) { #ifndef DONT_CHECK_QLINE_REMOTE if (!MyConnect(sptr)) sendto_realops("Restricted nick %s from %s on %s", nick, (*sptr->name != 0 && !IsServer(sptr)) ? sptr->name : "<unregistered>", (sptr->user == NULL) ? ((IsServer(sptr)) ? parv[6] : me.name) : sptr->user->server); #endif if (MyConnect(sptr) && (!IsServer(cptr)) && (!IsOper(cptr)) && (!IsULine(sptr))) { sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, BadPtr(parv[0]) ? "*" : parv[0], nick, BadPtr(ban->reason) ? "Erroneous Nickname" : ban->reason); if (call_hooks(CHOOK_FORBID, cptr, nick, ban) != FLUSH_BUFFER) sendto_realops_lev(REJ_LEV, "Forbidding restricted nick %s from %s", nick, get_client_name(cptr, FALSE)); return 0; } } #ifdef DONT_CHECK_QLINE_REMOTE } #endif if (MyConnect(sptr)) { if (IsRegisteredUser(sptr)) { /* before we change their nick, make sure they're not banned * on any channels, and!! make sure they're not changing to * a banned nick -sed */ /* a little cleaner - lucas */ for (lp = sptr->user->channel; lp; lp = lp->next) { if (can_send(sptr, lp->value.chptr, NULL)) { sendto_one(sptr, err_str(ERR_BANNICKCHANGE), me.name, sptr->name, lp->value.chptr->chname); return 0; } if (nick_is_banned(lp->value.chptr, nick, sptr) != NULL) { sendto_one(sptr, err_str(ERR_BANONCHAN), me.name, sptr->name, nick, lp->value.chptr->chname); return 0; } } #ifdef ANTI_NICK_FLOOD if ((sptr->last_nick_change + MAX_NICK_TIME) < NOW) sptr->number_of_nick_changes = 0; sptr->last_nick_change = NOW; sptr->number_of_nick_changes++; if (sptr->number_of_nick_changes > MAX_NICK_CHANGES && !IsAnOper(sptr)) { sendto_one(sptr, ":%s NOTICE %s :*** Notice -- Too many nick " "changes. Wait %d seconds before trying again.", me.name, sptr->name, MAX_NICK_TIME); return 0; } #endif /* If it changed nicks, -r it */ if ((sptr->umode & UMODE_r) && (mycmp(parv[0], nick) != 0)) { unsigned int oldumode; char mbuf[BUFSIZE]; oldumode = sptr->umode; sptr->umode &= ~UMODE_r; send_umode(sptr, sptr, oldumode, ALL_UMODES, mbuf); } /* LOCAL NICKHANGE */ /* * Client just changing his/her nick. If he/she is on a * channel, send note of change to all clients on that channel. * Propagate notice to other servers. */ /* if the nickname is different, set the TS */ if (mycmp(parv[0], nick)) { sptr->tsinfo = newts ? newts : (ts_val) timeofday; } sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick); if (sptr->user) { add_history(sptr, 1); sendto_serv_butone(cptr, ":%s NICK %s :%ld", parv[0], nick, sptr->tsinfo); } } } else { /* REMOTE NICKCHANGE */ /* * Client just changing his/her nick. If he/she is on a * channel, send note of change to all clients on that channel. * Propagate notice to other servers. */ /* if the nickname is different, set the TS */ if (mycmp(parv[0], nick)) { sptr->tsinfo = newts ? newts : (ts_val) timeofday; } sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick); if (sptr->user) { add_history(sptr, 1); sendto_serv_butone(cptr, ":%s NICK %s :%ld", parv[0], nick, sptr->tsinfo); } /* If it changed nicks, -r it */ if (mycmp(parv[0], nick)) sptr->umode &= ~UMODE_r; /* * Flush the banserial for the channels the user is in, since this * could be a SVSNICK induced nick change, which overrides any ban * checking on the originating server. */ flush_user_banserial(sptr); } /* Remove dccallow entries for users who don't share common channel(s) unless they only change their nick capitalization -Kobi_S */ if(sptr->user && mycmp(parv[0], nick)) { for(lp = sptr->user->dccallow; lp; lp = lp2) { lp2 = lp->next; if(lp->flags == DCC_LINK_ME) continue; if(!find_shared_chan(sptr, lp->value.cptr)) { sendto_one(lp->value.cptr, ":%s %d %s :%s has been removed from " "your DCC allow list for signing off", me.name, RPL_DCCINFO, lp->value.cptr->name, parv[0]); del_dccallow(lp->value.cptr, sptr, 1); } } } } else { /* Client setting NICK the first time */ if (MyConnect(sptr)) { if ((ban = check_mask_simbanned(nick, SBAN_NICK))) { if (MyConnect(sptr) && (!IsServer(cptr)) && (!IsOper(cptr)) && (!IsULine(sptr))) { sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, BadPtr(parv[0]) ? "*" : parv[0], nick, BadPtr(ban->reason) ? "Erroneous Nickname" : ban->reason); if (call_hooks(CHOOK_FORBID, cptr, nick, ban) != FLUSH_BUFFER) sendto_realops_lev(REJ_LEV, "Forbidding restricted nick %s from %s", nick, get_client_name(cptr, FALSE)); return 0; } } } strcpy(sptr->name, nick); sptr->tsinfo = timeofday; if (sptr->user) { /* USER already received, now we have NICK */ if (register_user(cptr, sptr, nick, sptr->user->username, NULL) == FLUSH_BUFFER) return FLUSH_BUFFER; } } /* Finally set new nick name. */ if (sptr->name[0]) { del_from_client_hash_table(sptr->name, sptr); samenick = mycmp(sptr->name, nick) ? 0 : 1; if (IsPerson(sptr)) { if (!samenick) hash_check_watch(sptr, RPL_LOGOFF); #ifdef RWHO_PROBABILITY probability_change(sptr->name, nick); #endif } } strcpy(sptr->name, nick); add_to_client_hash_table(nick, sptr); if (IsPerson(sptr) && !samenick) hash_check_watch(sptr, RPL_LOGON); return 0; }
void send_hook_msg(int ev, Plugin *host, Plugin *caller, HookArg *hka) { log_msg("HOOK", "(<%d>) msg sent", ev); call_hooks(get_event(ev), host, caller, hka); }
modusergo() { char crypted[20]; char *tmpstr; int i; int ret_code; int password_updated = 0; struct vqpasswd *vpw=NULL; static char box[50]; static char NewBuf[156]; int count; FILE *fs; #ifdef SQWEBMAIL_PASS uid_t uid; gid_t gid; #endif vpw = vauth_getpw(ActionUser, Domain); if (!( AdminType==DOMAIN_ADMIN || (AdminType==USER_ADMIN && strcmp(ActionUser,Username)==0))){ sprintf(StatusMessage,"%s", get_html_text("142")); vclose(); exit(0); } if (strlen(Password1)>0 && strlen(Password2)>0 ) { if ( strncmp( Password1, Password2, MAX_BUFF ) != 0 ) { sprintf(StatusMessage, "%s\n", get_html_text("200")); moduser(); vclose(); exit(0); } if (strlen(Password1) > MAX_PW_CLEAR_PASSWD) { sprintf(StatusMessage,"%s %s@%s %s", get_html_text("139"), ActionUser, Domain, VA_PASSWD_TOO_LONG ); moduser(); vclose(); exit(0); } else if (vpw->pw_gid & NO_PASSWD_CHNG) { sprintf(StatusMessage, "%s", get_html_text("140")); moduser(); vclose(); exit(0); } else { sprintf(StatusMessage,"%s %s@%s", get_html_text("139"), ActionUser, Domain); } mkpasswd3(Password1,Crypted, MAX_BUFF); vpw->pw_passwd = Crypted; #ifdef CLEAR_PASS vpw->pw_clear_passwd = Password1; #endif #ifdef SQWEBMAIL_PASS vget_assign(Domain, NULL, 0, &uid, &gid ); vsqwebmail_pass( vpw->pw_dir, Crypted, uid, gid); #endif } GetValue(TmpCGI,Gecos, "gecos=", MAX_BUFF); if ( strlen( Gecos ) != 0 ) { vpw->pw_gecos = Gecos; } vauth_setpw(vpw, Domain); /* get the value of the cforward radio button */ GetValue(TmpCGI,box, "cforward=", MAX_BUFF); /* if they want to disable everything */ if ( strcmp(box,"disable") == 0 ) { /* unlink the .qmail file */ if ( vpw == NULL ) vpw = vauth_getpw(ActionUser, Domain); snprintf(NewBuf,156,"%s/.qmail", vpw->pw_dir); unlink(NewBuf); /* delete any vacation directory */ snprintf(NewBuf,156,"%s/vacation", vpw->pw_dir); vdelfiles(NewBuf); /* if they want to forward */ } else if (strcmp(box,"forward") == 0 ) { /* get the value of the foward */ GetValue(TmpCGI,box, "nforward=", MAX_BUFF); /* If nothing was entered, error */ if ( box[0] == 0 ) { sprintf(StatusMessage, "%s\n", get_html_text("215")); moduser(); vclose(); exit(0); /* check it for a valid email address } else if ( check_email_addr( box ) == 1 ) { sprintf(StatusMessage, "%s\n", get_html_text("148")); moduser(); */ } /* everything looks good, open the file */ if ( vpw == NULL ) { vpw = vauth_getpw(ActionUser, Domain); } snprintf(NewBuf,156,"%s/.qmail", vpw->pw_dir); fs = fopen(NewBuf,"w+"); tmpstr = strtok(box," ,;\n"); count=0; while( tmpstr != NULL && count < 2) { fprintf(fs,"&%s\n", tmpstr); tmpstr = strtok(NULL," ,\n"); ++count; } /* if they want to save a copy */ GetValue(TmpCGI,box, "fsaved=", MAX_BUFF); if ( strcmp(box,"on") == 0 ) { fprintf(fs,"%s/Maildir/\n", vpw->pw_dir); } fclose(fs); /* they want vacation */ } else if (strcmp(box,"vacation") == 0 ) { /* get the subject */ GetValue(TmpCGI,box, "vsubject=", MAX_BUFF); /* if no subject, error */ if ( box[0] == 0 ) { sprintf(StatusMessage, "%s\n", get_html_text("216")); moduser(); vclose(); exit(0); } /* make the vacation directory */ if ( vpw == NULL ) vpw = vauth_getpw(ActionUser, Domain); snprintf(NewBuf,156,"%s/vacation", vpw->pw_dir); mkdir(NewBuf, 448); /* open the .qmail file */ snprintf(NewBuf,156,"%s/.qmail", vpw->pw_dir); fs = fopen(NewBuf,"w+"); fprintf(fs, "| %s/autorespond 86400 3 %s/vacation/message %s/vacation\n", AUTORESPOND_BIN, vpw->pw_dir, vpw->pw_dir ); /* save a copy for the user */ fprintf(fs,"%s/Maildir/\n", vpw->pw_dir); fclose(fs); /* set up the message file */ snprintf(NewBuf,156,"%s/vacation/message", vpw->pw_dir); GetValue(TmpCGI,Message, "vmessage=",MAX_BIG_BUFF); if ( (fs = fopen(NewBuf, "w")) == NULL ) ack("123", 123); fprintf(fs, "From: %s@%s\n", ActionUser,Domain); fprintf(fs, "Subject: %s\n\n", box); fprintf(fs, "%s", Message); fclose(fs); /* save the forward for vacation too */ GetValue(TmpCGI,box,"nforward=", MAX_BUFF); snprintf(NewBuf, 156, "%s/.qmail", vpw->pw_dir); fs = fopen(NewBuf, "a+"); tmpstr = strtok(box, " ,;\n"); count = 0; while( tmpstr != NULL && count < 2 ) { fprintf(fs, "&%s\n", tmpstr); tmpstr = strtok(NULL, " ,;\n"); ++count; } fclose(fs); } else { printf("nothing\n"); } call_hooks(HOOK_MODUSER); show_users(Username, Domain, Mytime); }
addusernow() { char pw[50]; int cnt=0, num; char *c_num; char **mailingListNames; char *tmp; char *email; char **arguments; int pid; int i; int error; struct vqpasswd *mypw; c_num = malloc(MAX_BUFF); email = malloc(128); tmp = malloc(MAX_BUFF); arguments = (char **)malloc(MAX_BUFF); count_users(); load_limits(); if ( AdminType!=DOMAIN_ADMIN ) { sprintf(StatusMessage,"%s", get_html_text("142")); vclose(); exit(0); } if ( MaxPopAccounts != -1 && CurPopAccounts >= MaxPopAccounts ) { sprintf(StatusMessage, "%s %d\n", get_html_text("199"), MaxPopAccounts); show_menu(); vclose(); exit(0); } GetValue(TmpCGI,Newu, "newu=", MAX_BUFF); if ( fixup_local_name(Newu) ) { sprintf(StatusMessage, "%s %s\n", get_html_text("148"), Newu); adduser(); vclose(); exit(0); } if ( check_local_user(Newu) ) { sprintf(StatusMessage, "%s %s\n", get_html_text("175"), Newu); adduser(); vclose(); exit(0); } GetValue(TmpCGI,Password1, "password1=", MAX_BUFF); GetValue(TmpCGI,Password2, "password2=", MAX_BUFF); if ( strncmp( Password1, Password2, MAX_BUFF ) != 0 ) { sprintf(StatusMessage, "%s\n", get_html_text("200")); adduser(); vclose(); exit(0); } if ( strlen(Password1) <= 0 ) { sprintf(StatusMessage, "%s\n", get_html_text("234")); adduser(); vclose(); exit(0); } strcpy(email, ""); strcat(email,Newu); strcat(email,"@"); strcat(email,Domain); GetValue(TmpCGI,Gecos, "gecos=", MAX_BUFF); if ( strlen( Gecos ) == 0 ) { strcpy(Gecos, Newu); } GetValue(TmpCGI, c_num, "number_of_mailinglist=", MAX_BUFF); num = atoi(c_num); if(!(mailingListNames = malloc(sizeof(char *) * num))) { sprintf(StatusMessage, "%s\n", get_html_text("201")); vclose(); exit(0); } else { for(cnt = 0; cnt < num; cnt++) { if(!(mailingListNames[cnt] = malloc(MAX_BUFF))) { sprintf(StatusMessage, "%s\n", get_html_text("201")); vclose(); exit(0); } } for(cnt = 0; cnt < num; cnt++) { sprintf(tmp, "subscribe%d=", cnt); error = GetValue(TmpCGI, mailingListNames[cnt], tmp, MAX_BUFF); if( error != -1 ) { pid=fork(); if (pid==0) { sprintf(TmpBuf1, "%s/ezmlm-sub", EZMLMDIR); sprintf(TmpBuf2, "%s/%s", RealDir, mailingListNames[cnt]); execl(TmpBuf1, "ezmlm-sub", TmpBuf2, email, NULL); exit(127); } else { wait(&pid); } } } } /* add the user then get the vpopmail password structure */ if ( vadduser( Newu, Domain, Password1, Gecos, USE_POP ) == 0 && #ifdef MYSQL_REPLICATION !sleep(2) && #endif (mypw = vauth_getpw( Newu, Domain )) != NULL ) { /* from the load_limits() function, set user flags */ if( DisablePOP > 0 ) mypw->pw_gid |= NO_POP; if( DisableIMAP > 0 ) mypw->pw_gid |= NO_IMAP; if( DisableDialup > 0 ) mypw->pw_gid |= NO_DIALUP; if( DisablePasswordChanging > 0 ) mypw->pw_gid |= NO_PASSWD_CHNG; if( DisableWebmail > 0 ) mypw->pw_gid |= NO_WEBMAIL; if( DisableRelay > 0 ) mypw->pw_gid |= NO_RELAY; if( DefaultQuota[0]!= 0 ) mypw->pw_shell = DefaultQuota; /* update the user information */ if ( vauth_setpw( mypw, Domain ) != VA_SUCCESS ) { /* report error */ sprintf(StatusMessage, "%s %s@%s (%s) %s", get_html_text("002"), Newu, Domain, Gecos, get_html_text("120")); } else { /* report success */ sprintf(StatusMessage, "%s %s@%s (%s) %s", get_html_text("002"), Newu, Domain, Gecos, get_html_text("119")); } /* otherwise, report error */ } else { sprintf(StatusMessage, "<font color=\"red\">%s %s@%s (%s) %s</font>", get_html_text("002"), Newu, Domain, Gecos, get_html_text("120")); } call_hooks( HOOK_ADDUSER ); /* After we add the user, show the user page * people like to visually verify the results */ show_users(Username, Domain, Mytime); }
//! //! Handles the instance migration request. //! //! @param[in] nc a pointer to the node controller (NC) state //! @param[in] pMeta a pointer to the node controller (NC) metadata structure //! @param[in] instances metadata for the instance to migrate to destination //! @param[in] instancesLen number of instances in the instance list //! @param[in] action IP of the destination Node Controller //! @param[in] credentials credentials that enable the migration //! //! @return EUCA_OK on success or EUCA_*ERROR on failure //! //! @pre //! //! @post static int doMigrateInstances(struct nc_state_t *nc, ncMetadata * pMeta, ncInstance ** instances, int instancesLen, char *action, char *credentials) { int ret = EUCA_OK; int credentials_prepared = 0; if (instancesLen <= 0) { LOGERROR("called with invalid instancesLen (%d)\n", instancesLen); pMeta->replyString = strdup("internal error (invalid instancesLen)"); return (EUCA_INVALID_ERROR); } LOGDEBUG("verifying %d instance[s] for migration...\n", instancesLen); for (int inst_idx = 0; inst_idx < instancesLen; inst_idx++) { LOGDEBUG("verifying instance # %d...\n", inst_idx); if (instances[inst_idx]) { ncInstance *instance_idx = instances[inst_idx]; LOGDEBUG("[%s] proposed migration action '%s' (%s > %s) [creds=%s]\n", SP(instance_idx->instanceId), SP(action), SP(instance_idx->migration_src), SP(instance_idx->migration_dst), (instance_idx->migration_credentials == NULL) ? "UNSET" : "present"); } else { pMeta->replyString = strdup("internal error (instance count mismatch)"); LOGERROR("Mismatch between migration instance count (%d) and length of instance list\n", instancesLen); return (EUCA_ERROR); } } // TO-DO: Optimize the location of this loop, placing it inside various conditionals below? for (int inst_idx = 0; inst_idx < instancesLen; inst_idx++) { ncInstance *instance_req = instances[inst_idx]; char *sourceNodeName = instance_req->migration_src; char *destNodeName = instance_req->migration_dst; LOGDEBUG("[%s] processing instance # %d (%s > %s)\n", instance_req->instanceId, inst_idx, instance_req->migration_src, instance_req->migration_dst); // this is a call to the source of migration if (!strcmp(pMeta->nodeName, sourceNodeName)) { // locate the instance structure ncInstance *instance; sem_p(inst_sem); { instance = find_instance(&global_instances, instance_req->instanceId); } sem_v(inst_sem); if (instance == NULL) { LOGERROR("[%s] cannot find instance\n", instance_req->instanceId); pMeta->replyString = strdup("failed to locate instance to migrate"); return (EUCA_NOT_FOUND_ERROR); } if (strcmp(action, "prepare") == 0) { sem_p(inst_sem); instance->migration_state = MIGRATION_PREPARING; euca_strncpy(instance->migration_src, sourceNodeName, HOSTNAME_SIZE); euca_strncpy(instance->migration_dst, destNodeName, HOSTNAME_SIZE); euca_strncpy(instance->migration_credentials, credentials, CREDENTIAL_SIZE); instance->migrationTime = time(NULL); save_instance_struct(instance); copy_instances(); sem_v(inst_sem); // Establish migration-credential keys if this is the first instance preparation for this host. LOGINFO("[%s] migration source preparing %s > %s [creds=%s]\n", SP(instance->instanceId), SP(instance->migration_src), SP(instance->migration_dst), (instance->migration_credentials == NULL) ? "UNSET" : "present"); if (!credentials_prepared) { if (generate_migration_keys(sourceNodeName, credentials, TRUE, instance) != EUCA_OK) { pMeta->replyString = strdup("internal error (migration credentials generation failed)"); return (EUCA_SYSTEM_ERROR); } else { credentials_prepared++; } } sem_p(inst_sem); instance->migration_state = MIGRATION_READY; save_instance_struct(instance); copy_instances(); sem_v(inst_sem); } else if (strcmp(action, "commit") == 0) { sem_p(inst_sem); if (instance->migration_state == MIGRATION_IN_PROGRESS) { LOGWARN("[%s] duplicate request to migration source to initiate %s > %s (already migrating)\n", instance->instanceId, instance->migration_src, instance->migration_dst); sem_v(inst_sem); return (EUCA_DUPLICATE_ERROR); } else if (instance->migration_state != MIGRATION_READY) { LOGERROR("[%s] request to commit migration %s > %s when source migration_state='%s' (not 'ready')\n", instance->instanceId, SP(sourceNodeName), SP(destNodeName), migration_state_names[instance->migration_state]); sem_v(inst_sem); return (EUCA_UNSUPPORTED_ERROR); } instance->migration_state = MIGRATION_IN_PROGRESS; outgoing_migrations_in_progress++; LOGINFO("[%s] migration source initiating %s > %s [creds=%s] (1 of %d active outgoing migrations)\n", instance->instanceId, instance->migration_src, instance->migration_dst, (instance->migration_credentials == NULL) ? "UNSET" : "present", outgoing_migrations_in_progress); save_instance_struct(instance); copy_instances(); sem_v(inst_sem); // since migration may take a while, we do them in a thread pthread_t tcb = { 0 }; if (pthread_create(&tcb, NULL, migrating_thread, (void *)instance)) { LOGERROR("[%s] failed to spawn a migration thread\n", instance->instanceId); return (EUCA_THREAD_ERROR); } set_corrid_pthread( get_corrid()!=NULL ? get_corrid()->correlation_id : NULL , tcb); if (pthread_detach(tcb)) { LOGERROR("[%s] failed to detach the migration thread\n", instance->instanceId); return (EUCA_THREAD_ERROR); } } else if (strcmp(action, "rollback") == 0) { if ((instance->migration_state == MIGRATION_READY) || (instance->migration_state == MIGRATION_PREPARING)) { LOGINFO("[%s] rolling back migration (%s > %s) on source\n", instance->instanceId, instance->migration_src, instance->migration_dst); sem_p(inst_sem); migration_rollback(instance); sem_v(inst_sem); } else { LOGINFO("[%s] ignoring request to roll back migration on source with instance in state %s(%s) -- duplicate rollback request?\n", instance->instanceId, instance->stateName, migration_state_names[instance->migration_state]); } } else { LOGERROR("[%s] action '%s' is not valid\n", instance->instanceId, action); return (EUCA_INVALID_ERROR); } } else if (!strcmp(pMeta->nodeName, destNodeName)) { // this is a migrate request to destination if (!strcmp(action, "commit")) { LOGERROR("[%s] action '%s' for migration (%s > %s) is not valid on destination node\n", instance_req->instanceId, action, SP(sourceNodeName), SP(destNodeName)); return (EUCA_UNSUPPORTED_ERROR); } else if (!strcmp(action, "rollback")) { LOGINFO("[%s] rolling back migration (%s > %s) on destination\n", instance_req->instanceId, SP(sourceNodeName), SP(destNodeName)); sem_p(inst_sem); { ncInstance *instance = find_instance(&global_instances, instance_req->instanceId); if (instance != NULL) { LOGDEBUG("[%s] marked for cleanup\n", instance->instanceId); change_state(instance, SHUTOFF); instance->migration_state = MIGRATION_CLEANING; save_instance_struct(instance); } } sem_v(inst_sem); return EUCA_OK; } else if (strcmp(action, "prepare") != 0) { LOGERROR("[%s] action '%s' is not valid or not implemented\n", instance_req->instanceId, action); return (EUCA_INVALID_ERROR); } // Everything from here on is specific to "prepare" on a destination. // allocate a new instance struct ncInstance *instance = clone_instance(instance_req); if (instance == NULL) { LOGERROR("[%s] could not allocate instance struct\n", instance_req->instanceId); goto failed_dest; } sem_p(inst_sem); instance->migration_state = MIGRATION_PREPARING; euca_strncpy(instance->migration_src, sourceNodeName, HOSTNAME_SIZE); euca_strncpy(instance->migration_dst, destNodeName, HOSTNAME_SIZE); euca_strncpy(instance->migration_credentials, credentials, CREDENTIAL_SIZE); save_instance_struct(instance); sem_v(inst_sem); // Establish migration-credential keys. LOGINFO("[%s] migration destination preparing %s > %s [creds=%s]\n", instance->instanceId, SP(instance->migration_src), SP(instance->migration_dst), (instance->migration_credentials == NULL) ? "UNSET" : "present"); // First, call config-file modification script to authorize source node. LOGDEBUG("[%s] authorizing migration source node %s\n", instance->instanceId, instance->migration_src); if (authorize_migration_keys("-a", instance->migration_src, instance->migration_credentials, instance, TRUE) != EUCA_OK) { goto failed_dest; } // Then, generate keys and restart libvirtd. if (generate_migration_keys(instance->migration_dst, instance->migration_credentials, TRUE, instance) != EUCA_OK) { goto failed_dest; } int error; if (vbr_parse(&(instance->params), pMeta) != EUCA_OK) { goto failed_dest; } // set up networking char *brname = NULL; if ((error = vnetStartNetwork(nc->vnetconfig, instance->ncnet.vlan, NULL, NULL, NULL, &brname)) != EUCA_OK) { LOGERROR("[%s] start network failed for instance, terminating it\n", instance->instanceId); EUCA_FREE(brname); goto failed_dest; } euca_strncpy(instance->params.guestNicDeviceName, brname, sizeof(instance->params.guestNicDeviceName)); EUCA_FREE(brname); // TODO: move stuff in startup_thread() into a function? set_instance_params(instance); if ((error = create_instance_backing(instance, TRUE)) // create files that back the disks || (error = gen_instance_xml(instance)) // create euca-specific instance XML file || (error = gen_libvirt_instance_xml(instance))) { // transform euca-specific XML into libvirt XML LOGERROR("[%s] failed to prepare images for migrating instance (error=%d)\n", instance->instanceId, error); goto failed_dest; } // attach any volumes for (int v = 0; v < EUCA_MAX_VOLUMES; v++) { ncVolume *volume = &instance->volumes[v]; if (strcmp(volume->stateName, VOL_STATE_ATTACHED) && strcmp(volume->stateName, VOL_STATE_ATTACHING)) continue; // skip the entry unless attached or attaching LOGDEBUG("[%s] volumes [%d] = '%s'\n", instance->instanceId, v, volume->stateName); // TODO: factor what the following out of here and doAttachVolume() in handlers_default.c int have_remote_device = 0; char *xml = NULL; char *remoteDevStr = NULL; char scUrl[512]; char localDevReal[32], localDevTag[256], remoteDevReal[132]; char *tagBuf = localDevTag; ebs_volume_data *vol_data = NULL; ret = convert_dev_names(volume->localDev, localDevReal, tagBuf); if (ret) goto unroll; //Do the ebs connect. LOGTRACE("[%s][%s] Connecting EBS volume to local host\n", instance->instanceId, volume->volumeId); get_service_url("storage", nc, scUrl); if (strlen(scUrl) == 0) { LOGERROR("[%s][%s] Failed to lookup enabled Storage Controller. Cannot attach volume %s\n", instance->instanceId, volume->volumeId, scUrl); have_remote_device = 0; goto unroll; } else { LOGTRACE("[%s][%s] Using SC URL: %s\n", instance->instanceId, volume->volumeId, scUrl); } //Do the ebs connect. LOGTRACE("[%s][%s] Connecting EBS volume to local host\n", instance->instanceId, volume->volumeId); int rc = connect_ebs_volume(scUrl, volume->attachmentToken, nc->config_use_ws_sec, nc->config_sc_policy_file, nc->ip, nc->iqn, &remoteDevStr, &vol_data); if (rc) { LOGERROR("Error connecting ebs volume %s\n", volume->attachmentToken); have_remote_device = 0; ret = EUCA_ERROR; goto unroll; } // update the volume struct with connection string obtained from SC euca_strncpy(volume->connectionString, vol_data->connect_string, sizeof(volume->connectionString)); if (!remoteDevStr || !strstr(remoteDevStr, "/dev")) { LOGERROR("[%s][%s] failed to connect to iscsi target\n", instance->instanceId, volume->volumeId); remoteDevReal[0] = '\0'; } else { LOGDEBUG("[%s][%s] attached iSCSI target of host device '%s'\n", instance->instanceId, volume->volumeId, remoteDevStr); snprintf(remoteDevReal, sizeof(remoteDevReal), "%s", remoteDevStr); have_remote_device = 1; } EUCA_FREE(remoteDevStr); // something went wrong above, abort if (!have_remote_device) { goto unroll; } // make sure there is a block device if (check_block(remoteDevReal)) { LOGERROR("[%s][%s] cannot verify that host device '%s' is available for hypervisor attach\n", instance->instanceId, volume->volumeId, remoteDevReal); goto unroll; } // generate XML for libvirt attachment request if (gen_volume_xml(volume->volumeId, instance, localDevReal, remoteDevReal) // creates vol-XXX.xml || gen_libvirt_volume_xml(volume->volumeId, instance)) { // creates vol-XXX-libvirt.xml via XSLT transform LOGERROR("[%s][%s] could not produce attach device xml\n", instance->instanceId, volume->volumeId); goto unroll; } // invoke hooks char path[EUCA_MAX_PATH]; char lpath[EUCA_MAX_PATH]; snprintf(path, sizeof(path), EUCALYPTUS_VOLUME_XML_PATH_FORMAT, instance->instancePath, volume->volumeId); // vol-XXX.xml snprintf(lpath, sizeof(lpath), EUCALYPTUS_VOLUME_LIBVIRT_XML_PATH_FORMAT, instance->instancePath, volume->volumeId); // vol-XXX-libvirt.xml if (call_hooks(NC_EVENT_PRE_ATTACH, lpath)) { LOGERROR("[%s][%s] cancelled volume attachment via hooks\n", instance->instanceId, volume->volumeId); goto unroll; } // read in libvirt XML, which may have been modified by the hook above if ((xml = file2str(lpath)) == NULL) { LOGERROR("[%s][%s] failed to read volume XML from %s\n", instance->instanceId, volume->volumeId, lpath); goto unroll; } continue; unroll: ret = EUCA_ERROR; // TODO: unroll all volume attachments goto failed_dest; } sem_p(inst_sem); instance->migration_state = MIGRATION_READY; instance->bootTime = time(NULL); // otherwise nc_state.booting_cleanup_threshold will kick in change_state(instance, BOOTING); // not STAGING, since in that mode we don't poll hypervisor for info LOGINFO("[%s] migration destination ready %s > %s\n", instance->instanceId, instance->migration_src, instance->migration_dst); save_instance_struct(instance); error = add_instance(&global_instances, instance); copy_instances(); sem_v(inst_sem); if (error) { if (error == EUCA_DUPLICATE_ERROR) { LOGINFO("[%s] instance struct already exists (from previous migration?), deleting and re-adding...\n", instance->instanceId); error = remove_instance(&global_instances, instance); if (error) { LOGERROR("[%s] could not replace (remove) instance struct, failing...\n", instance->instanceId); goto failed_dest; } error = add_instance(&global_instances, instance); if (error) { LOGERROR("[%s] could not replace (add) instance struct, failing...\n", instance->instanceId); goto failed_dest; } } else { LOGERROR("[%s] could not add instance struct, failing...\n", instance->instanceId); goto failed_dest; } } continue; failed_dest: sem_p(inst_sem); // Just making sure... if (instance != NULL) { LOGERROR("[%s] setting instance to Teardown(cleaning) after destination failure to prepare for migration\n", instance->instanceId); // Set state to Teardown(cleaning) so source won't wait until timeout to roll back. instance->migration_state = MIGRATION_CLEANING; instance->terminationTime = time(NULL); change_state(instance, TEARDOWN); save_instance_struct(instance); add_instance(&global_instances, instance); // OK if this fails--that should mean it's already been added. copy_instances(); } // If no remaining incoming or pending migrations, deauthorize all clients. // TO-DO: Consolidate with similar sequence in handlers.c into a utility function? if (!incoming_migrations_in_progress) { int incoming_migrations_pending = 0; LOGINFO("[%s] no remaining active incoming migrations -- checking to see if there are any pending migrations\n", instance->instanceId); bunchOfInstances *head = NULL; for (head = global_instances; head; head = head->next) { if ((head->instance->migration_state == MIGRATION_PREPARING) || (head->instance->migration_state == MIGRATION_READY)) { LOGINFO("[%s] is pending migration, state='%s', deferring deauthorization of migration keys\n", head->instance->instanceId, migration_state_names[head->instance->migration_state]); incoming_migrations_pending++; } } // TO-DO: Add belt and suspenders? if (!incoming_migrations_pending) { LOGINFO("[%s] no remaining incoming or pending migrations -- deauthorizing all migration client keys\n", instance->instanceId); authorize_migration_keys("-D -r", NULL, NULL, NULL, FALSE); } } sem_v(inst_sem); // Set to generic EUCA_ERROR unless already set to a more-specific error. if (ret == EUCA_OK) { ret = EUCA_ERROR; } } else { LOGERROR("unexpected migration request (node %s is neither source nor destination)\n", pMeta->nodeName); ret = EUCA_ERROR; } } return ret; }
} static void conn_event_cb(struct bufferevent *buffer, short what, void *userdata) { DEBUG("event_cb 0x%x", what); ad_conn_t *conn = userdata; if (what & BEV_EVENT_EOF || what & BEV_EVENT_ERROR || what & BEV_EVENT_TIMEOUT) { conn->status = AD_CLOSE; conn_cb(conn, AD_EVENT_CLOSE | ((what & BEV_EVENT_TIMEOUT) ? AD_EVENT_TIMEOUT : 0)); } } static void conn_cb(ad_conn_t *conn, int event) { DEBUG("conn_cb: status:0x%x, event:0x%x", conn->status, event) if(conn->status == AD_OK || conn->status == AD_TAKEOVER) { int status = call_hooks(event, conn); // Update status only when it's higher then before. if (! (conn->status == AD_CLOSE || (conn->status == AD_DONE && conn->status >= status))) { conn->status = status; } } if(conn->status == AD_DONE) { if (ad_server_get_option_int(conn->server, "server.request_pipelining")) { call_hooks(AD_EVENT_CLOSE , conn); conn_reset(conn); call_hooks(AD_EVENT_INIT , conn); } else { // Do nothing but drain input buffer. if (event == AD_EVENT_READ) { DEBUG("Draining in-buffer. %d", conn->status);