implemented set KeepConn time function for later use (relay command)
[srvx.git] / src / proto-p10.c
index c1271db0934dfca74cb5f6418ab4c72460016fe1..f544f9f019a2ddc3799bb19de4e0dc013e0a982a 100644 (file)
 #define CMD_WHO                 "WHO"
 #define CMD_WHOIS               "WHOIS"
 #define CMD_WHOWAS              "WHOWAS"
+#define CMD_XQUERY              "XQUERY"
+#define CMD_XRESPONSE           "XRESPONSE"
 
 /* Tokenized commands. */
 #define TOK_ACCOUNT             "AC"
 #define TOK_EOB_ACK             "EA"
 #define TOK_ERROR               "Y"
 #define TOK_FAKEHOST            "FA"
-#define TOK_FAKEHOST2           "FA2"
+#define TOK_FAKEHOST2           "NFH"
 #define TOK_GET                 "GET"
 #define TOK_GLINE               "GL"
 #define TOK_HASH                "HASH"
 #define TOK_WHO                 "H"
 #define TOK_WHOIS               "W"
 #define TOK_WHOWAS              "X"
+#define TOK_XQUERY              "XQ"
+#define TOK_XRESPONSE           "XR"
 
 /* Protocol messages; aliased to full commands or tokens depending
    on compile-time configuration. ircu prefers tokens WITH THE
 #define P10_WHO                 TYPE(WHO)
 #define P10_WHOIS               TYPE(WHOIS)
 #define P10_WHOWAS              TYPE(WHOWAS)
+#define P10_XQUERY              TYPE(XQUERY)
+#define P10_XRESPONSE           TYPE(XRESPONSE)
 
 /* Servers claiming to have a boot or link time before PREHISTORY
  * trigger errors to the log.  We hope no server has been running
@@ -507,11 +513,11 @@ irc_fakehost(struct userNode *user, const char *host, const char *ident, int for
 {
     /* SRVX added the possibility for FAKE IDENTS
      * but this is currently *NOT* supported by our IRCu
+     *
+     * edit 24.11.11: 
+     *  NFH (P10_FAKEHOST2) is now supported by our IRCu (git-65-21592a4)
      */
-    int useNewFakehost = 0;
-     
-    if(useNewFakehost) putsock("%s " P10_FAKEHOST2 " %s %s %s%s", self->numeric, user->numeric, ident, host, force ? " FORCE" : "");
-    else putsock("%s " P10_FAKEHOST " %s %s", self->numeric, user->numeric, host);
+    putsock("%s " P10_FAKEHOST2 " %s %s %s%s", self->numeric, user->numeric, ident, host, force ? " FORCE" : "");
 }
 
 void 
@@ -526,6 +532,12 @@ irc_simul(struct userNode *target, char *command)
     putsock("%s " P10_RELAY " %s SI %s :%s", self->numeric, target->numeric, target->numeric, command);
 }
 
+void 
+irc_keepconn(struct userNode *target, unsigned int timeout)
+{
+    putsock("%s " P10_RELAY " %s KC %s %u", self->numeric, target->numeric, target->numeric, timeout);
+}
+
 void
 irc_regnick(UNUSED_ARG(struct userNode *user))
 {
@@ -702,12 +714,16 @@ irc_introduce(const char *passwd)
 void
 irc_gline(struct server *srv, struct gline *gline)
 {
+    //<prefix> GL <target> [!][+|-|>|<]<mask> [<expiration>] [<lastmod>] [<lifetime>] [:<reason>]
+    //expiration = relative time (seconds)
+    //lastmod = timestamp
+    //livetime = timestamp
     if (gline->lastmod)
-        putsock("%s " P10_GLINE " %s +%s %lu %lu %lu :%s",
-                self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires, gline->lastmod, gline->lifetime, gline->reason);
+        putsock("%s " P10_GLINE " %s +%s %lu %lu %lu :%s", self->numeric, (srv ? srv->numeric : "*"), 
+                gline->target, gline->expires-now, gline->lastmod, gline->lifetime, gline->reason);
     else
-        putsock("%s " P10_GLINE " %s +%s %lu :%s",
-                self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires, gline->reason);
+        putsock("%s " P10_GLINE " %s +%s %lu :%s", self->numeric, (srv ? srv->numeric : "*"), 
+                gline->target, gline->expires-now, gline->reason);
 }
 
 void
@@ -957,6 +973,12 @@ irc_numeric(struct userNode *user, unsigned int num, const char *format, ...)
     putsock(":%s %03d %s %s", self->name, num, user->nick, buffer);
 }
 
+void
+irc_xresponse(struct server *target, const char *routing, const char *response)
+{
+    putsock("%s " P10_XRESPONSE " %s %s :%s", self->numeric, target->numeric, routing, response);
+}
+
 static void send_burst(void);
 
 static void
@@ -1485,7 +1507,7 @@ static CMD_FUNC(cmd_clearmode)
 static CMD_FUNC(cmd_topic)
 {
     struct chanNode *cn;
-    unsigned long chan_ts, topic_ts;
+    unsigned long topic_ts;
 
     if (argc < 3)
         return 0;
@@ -1495,10 +1517,8 @@ static CMD_FUNC(cmd_topic)
     }
     if (argc >= 5) {
         /* Looks like an Asuka style topic burst. */
-        chan_ts = atoi(argv[2]);
         topic_ts = atoi(argv[3]);
     } else {
-        chan_ts = cn->timestamp;
         topic_ts = now;
     }
     SetChannelTopic(cn, GetUserH(origin), argv[argc-1], 0);
@@ -1820,6 +1840,16 @@ static CMD_FUNC(cmd_relay)
     return 1;
 }
 
+static CMD_FUNC(cmd_xquery)
+{
+    struct server *source;
+    if ((argc < 4)
+        || !(source = GetServerH(origin)))
+        return 0;
+    call_xquery_funcs(source, argv[2], argv[3]);
+    return 1;
+}
+
 void
 free_user(struct userNode *user)
 {
@@ -1963,6 +1993,8 @@ init_parse(void)
     dict_insert(irc_func_dict, TOK_ADMIN, cmd_admin);
     dict_insert(irc_func_dict, CMD_TIME, cmd_time);
     dict_insert(irc_func_dict, TOK_TIME, cmd_time);
+    /* We don't handle XR or the (not really defined) XQUERY. */
+    dict_insert(irc_func_dict, TOK_XQUERY, cmd_xquery);
 
     /* In P10, DESTRUCT doesn't do anything except be broadcast to servers.
      * Apparently to obliterate channels from any servers that think they
@@ -2236,7 +2268,6 @@ AddLocalUser(const char *nick, const char *ident, const char *hostname, const ch
 {
     char numeric[COMBO_NUMERIC_LEN+1];
     int local_num = get_local_numeric();
-    unsigned long timestamp = now;
     struct userNode *old_user = GetUserH(nick);
 
     if (!modes)
@@ -2244,7 +2275,6 @@ AddLocalUser(const char *nick, const char *ident, const char *hostname, const ch
     if (old_user) {
         if (IsLocal(old_user))
             return old_user;
-        timestamp = old_user->timestamp - 1;
     }
     if (local_num == -1) {
         log_module(MAIN_LOG, LOG_ERROR, "Unable to allocate numnick for service %s", nick);
@@ -2557,7 +2587,7 @@ keyncpy(char output[], char input[], size_t output_size)
 }
 
 struct mod_chanmode *
-mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel)
+mod_chanmode_parse(struct chanNode *channel, struct userNode *user, char **modes, unsigned int argc, unsigned int flags, short base_oplevel)
 {
     struct mod_chanmode *change;
     unsigned int ii, in_arg, ch_arg, add;
@@ -2584,6 +2614,7 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un
         case 'M': do_chan_mode(MODE_NOAMSGS); break;
         case 'N': do_chan_mode(MODE_NONOTICES); break;
         case 'u': do_chan_mode(MODE_AUDITORIUM); break;
+        case 'S': do_chan_mode(MODE_SSLCHAN); break;
         case 'i': do_chan_mode(MODE_INVITEONLY); break;
         case 'm': do_chan_mode(MODE_MODERATED); break;
         case 'n': do_chan_mode(MODE_NOPRIVMSGS); break;
@@ -2677,8 +2708,28 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un
             if (add) {
                 if (in_arg >= argc)
                     goto error;
+                char *altchan = modes[in_arg++];
+                struct chanNode *target;
+                if(!IsChannelName(altchan) || !(target = GetChannel(altchan)))
+                    goto error;
+                if(!(flags & MCP_OPERMODE)) {
+                    //check if the user has the permissions to use this channel as target
+                    struct modeNode *mn;
+                    struct userData *uData;
+                    struct chanData *cData;
+                    if(user && (mn = GetUserMode(target, user)) && (mn->modes & MODE_CHANOP)) {
+                        //allow - user is opped on target channel
+                    } else if(user && user->handle_info && 
+                              (uData = GetChannelUser(channel->channel_info, user->handle_info)) && 
+                              (cData = uData->channel) && 
+                              uData->access >= cData->lvlOpts[lvlGiveOps]
+                             ) {
+                        //allow - user has access to get op on the channel
+                    } else 
+                        goto error;
+                }
                 change->modes_set |= MODE_ALTCHAN;
-                safestrncpy(change->new_altchan, modes[in_arg++], sizeof(change->new_altchan));
+                safestrncpy(change->new_altchan, altchan, sizeof(change->new_altchan));
             } else {
                 change->modes_clear |= MODE_ALTCHAN;
             }
@@ -2873,6 +2924,7 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod
         DO_MODE_CHAR(NONOTICES, 'N');
         DO_MODE_CHAR(NOAMSGS, 'M');
         DO_MODE_CHAR(AUDITORIUM, 'u');
+        DO_MODE_CHAR(SSLCHAN, 'S');
         DO_MODE_CHAR(REGISTERED, 'z');
 #undef DO_MODE_CHAR
         if (change->modes_clear & channel->modes & MODE_KEY)
@@ -2919,6 +2971,7 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod
         DO_MODE_CHAR(NONOTICES, 'N');
         DO_MODE_CHAR(NOAMSGS, 'M');
         DO_MODE_CHAR(AUDITORIUM, 'u');
+        DO_MODE_CHAR(SSLCHAN, 'S');
         DO_MODE_CHAR(REGISTERED, 'z');
 #undef DO_MODE_CHAR
         if(change->modes_set & MODE_KEY)
@@ -2998,6 +3051,7 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
         DO_MODE_CHAR(NONOTICES, 'N');
         DO_MODE_CHAR(NOAMSGS, 'M');
         DO_MODE_CHAR(AUDITORIUM, 'u');
+        DO_MODE_CHAR(SSLCHAN, 'S');
         DO_MODE_CHAR(REGISTERED, 'z');
 #undef DO_MODE_CHAR
     }
@@ -3017,6 +3071,7 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
         DO_MODE_CHAR(NONOTICES, 'N');
                DO_MODE_CHAR(NOAMSGS, 'M');
         DO_MODE_CHAR(AUDITORIUM, 'u');
+        DO_MODE_CHAR(SSLCHAN, 'S');
         DO_MODE_CHAR(REGISTERED, 'z');
         DO_MODE_CHAR(LIMIT, 'l'), args_used += sprintf(args + args_used, " %d", change->new_limit);
         DO_MODE_CHAR(KEY, 'k'), args_used += sprintf(args + args_used, " %s", change->new_key);
@@ -3082,6 +3137,7 @@ clear_chanmode(struct chanNode *channel, const char *modes)
         case 'C': cleared |= MODE_NOCTCPS; break;
         case 'M': cleared |= MODE_NOAMSGS; break;
         case 'u': cleared |= MODE_AUDITORIUM; break;
+        case 'S': cleared |= MODE_SSLCHAN; break;
         case 'N': cleared |= MODE_NONOTICES; break;
         case 'z': cleared |= MODE_REGISTERED; break;
         }