X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fngircd%2Firc-server.c;h=3f9753b9670d93205d5d6504e34e9f87e5984cdf;hb=d697de31862bc659461498bb5169e7a9bdd525b2;hp=265a9859e04bfaa95b06d53d2cbce02b26767d16;hpb=398022631a573a2b8de7811cacb6c202e90f263e;p=ngircd.git diff --git a/src/ngircd/irc-server.c b/src/ngircd/irc-server.c index 265a9859..3f9753b9 100644 --- a/src/ngircd/irc-server.c +++ b/src/ngircd/irc-server.c @@ -31,6 +31,7 @@ #include "parse.h" #include "numeric.h" #include "ngircd.h" +#include "irc.h" #include "irc-info.h" #include "irc-write.h" #include "op.h" @@ -185,6 +186,15 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) if (!Client_CheckID(Client, Req->argv[0])) return DISCONNECTED; + if (!Req->prefix) { + /* We definitely need a prefix here! */ + Log(LOG_ALERT, "Got SERVER command without prefix! (on connection %d)", + Client_Conn(Client)); + Conn_Close(Client_Conn(Client), NULL, + "SERVER command without prefix", true); + return DISCONNECTED; + } + from = Client_Search( Req->prefix ); if (! from) { /* Uh, Server, that introduced the new server is unknown?! */ @@ -245,66 +255,96 @@ IRC_NJOIN( CLIENT *Client, REQUEST *Req ) CHANNEL *chan; CLIENT *c; - assert( Client != NULL ); - assert( Req != NULL ); + assert(Client != NULL); + assert(Req != NULL); - strlcpy( nick_in, Req->argv[1], sizeof( nick_in )); - strcpy( nick_out, "" ); + strlcpy(nick_in, Req->argv[1], sizeof(nick_in)); + strcpy(nick_out, ""); channame = Req->argv[0]; - ptr = strtok( nick_in, "," ); - while( ptr ) - { + + ptr = strtok(nick_in, ","); + while (ptr) { is_owner = is_chanadmin = is_op = is_halfop = is_voiced = false; /* cut off prefixes */ - while(( *ptr == '~') || ( *ptr == '&' ) || ( *ptr == '@' ) || - ( *ptr == '%') || ( *ptr == '+' )) - { - if( *ptr == '~' ) is_owner = true; - if( *ptr == '&' ) is_chanadmin = true; - if( *ptr == '@' ) is_op = true; - if( *ptr == '%' ) is_halfop = true; - if( *ptr == '+' ) is_voiced = true; + while ((*ptr == '~') || (*ptr == '&') || (*ptr == '@') || + (*ptr == '%') || (*ptr == '+')) { + if (*ptr == '~') + is_owner = true; + if (*ptr == '&') + is_chanadmin = true; + if (*ptr == '@') + is_op = true; + if (*ptr == '%') + is_halfop = true; + if (*ptr == '+') + is_voiced = true; ptr++; } - c = Client_Search( ptr ); - if( c ) - { - Channel_Join( c, channame ); - chan = Channel_Search( channame ); - assert( chan != NULL ); - - if( is_owner ) Channel_UserModeAdd( chan, c, 'q' ); - if( is_chanadmin ) Channel_UserModeAdd( chan, c, 'a' ); - if( is_op ) Channel_UserModeAdd( chan, c, 'o' ); - if( is_halfop ) Channel_UserModeAdd( chan, c, 'h' ); - if( is_voiced ) Channel_UserModeAdd( chan, c, 'v' ); - - /* announce to channel... */ - IRC_WriteStrChannelPrefix( Client, chan, c, false, "JOIN :%s", channame ); - - /* set Channel-User-Modes */ - strlcpy( modes, Channel_UserModes( chan, c ), sizeof( modes )); - if( modes[0] ) - { - /* send modes to channel */ - IRC_WriteStrChannelPrefix( Client, chan, Client, false, "MODE %s +%s %s", channame, modes, Client_ID( c )); - } + c = Client_Search(ptr); + if (!c) { + /* Client not found? */ + Log(LOG_ERR, + "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", + ptr, channame); + goto skip_njoin; + } - if( nick_out[0] != '\0' ) strlcat( nick_out, ",", sizeof( nick_out )); - if( is_owner ) strlcat( nick_out, "~", sizeof( nick_out )); - if( is_chanadmin ) strlcat( nick_out, "&", sizeof( nick_out )); - if( is_op ) strlcat( nick_out, "@", sizeof( nick_out )); - if( is_halfop ) strlcat( nick_out, "%", sizeof( nick_out )); - if( is_voiced ) strlcat( nick_out, "+", sizeof( nick_out )); - strlcat( nick_out, ptr, sizeof( nick_out )); + if (!Channel_Join(c, channame)) { + /* Failed to join channel. Ooops!? */ + Log(LOG_ALERT, + "Failed to join client \"%s\" to channel \"%s\" (NJOIN): killing it!", + ptr, channame); + IRC_KillClient(NULL, NULL, ptr, "Internal NJOIN error!"); + Log(LOG_DEBUG, "... done."); + goto skip_njoin; } - else Log( LOG_ERR, "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", ptr, channame ); - /* search for next Nick */ - ptr = strtok( NULL, "," ); + chan = Channel_Search(channame); + assert(chan != NULL); + + if (is_owner) + Channel_UserModeAdd(chan, c, 'q'); + if (is_chanadmin) + Channel_UserModeAdd(chan, c, 'a'); + if (is_op) + Channel_UserModeAdd(chan, c, 'o'); + if (is_halfop) + Channel_UserModeAdd(chan, c, 'h'); + if (is_voiced) + Channel_UserModeAdd(chan, c, 'v'); + + /* Announce client to the channel */ + IRC_WriteStrChannelPrefix(Client, chan, c, false, + "JOIN :%s", channame); + + /* Announce "channel user modes" to the channel, if any */ + strlcpy(modes, Channel_UserModes(chan, c), sizeof(modes)); + if (modes[0]) + IRC_WriteStrChannelPrefix(Client, chan, Client, false, + "MODE %s +%s %s", channame, + modes, Client_ID(c)); + + /* Build nick list for forwarding command */ + if (nick_out[0] != '\0') + strlcat(nick_out, ",", sizeof(nick_out)); + if (is_owner) + strlcat(nick_out, "~", sizeof(nick_out)); + if (is_chanadmin) + strlcat(nick_out, "&", sizeof(nick_out)); + if (is_op) + strlcat(nick_out, "@", sizeof(nick_out)); + if (is_halfop) + strlcat(nick_out, "%", sizeof(nick_out)); + if (is_voiced) + strlcat(nick_out, "+", sizeof(nick_out)); + strlcat(nick_out, ptr, sizeof(nick_out)); + + skip_njoin: + /* Get next nick, if any ... */ + ptr = strtok(NULL, ","); } /* forward to other servers */ @@ -327,7 +367,7 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req) { char msg[COMMAND_LEN], logmsg[COMMAND_LEN]; CLIENT *from, *target; - CONN_ID con; + CONN_ID con, client_con; int loglevel; assert(Client != NULL); @@ -367,6 +407,7 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req) return CONNECTED; } + client_con = Client_Conn(Client); con = Client_Conn(target); if (Req->argv[1][0]) @@ -388,7 +429,7 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req) Req->argv[0], Client_ID(from), Req->argv[1][0] ? Req->argv[1] : "-"); Conn_Close(con, NULL, msg, true); - if (con == Client_Conn(Client)) + if (con == client_con) return DISCONNECTED; } else { /* This server is not directly connected, so the SQUIT must