#define CMD_EOB_ACK "EOB_ACK"
#define CMD_ERROR "ERROR"
#define CMD_FAKEHOST "FAKE"
+#define CMD_FAKEHOST2 "FAKE2"
#define CMD_GET "GET"
#define CMD_GLINE "GLINE"
#define CMD_HASH "HASH"
#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 "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_EOB_ACK TYPE(EOB_ACK)
#define P10_ERROR TYPE(ERROR)
#define P10_FAKEHOST TYPE(FAKEHOST)
+#define P10_FAKEHOST2 TYPE(FAKEHOST2)
#define P10_GET TYPE(GET)
#define P10_GLINE TYPE(GLINE)
#define P10_HASH TYPE(HASH)
#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
void
irc_fakehost(struct userNode *user, const char *host, const char *ident, int force)
{
- //putsock("%s " P10_FAKEHOST " %s %s %s%s", self->numeric, user->numeric, ident, host, force ? " FORCE" : "");
- putsock("%s " P10_FAKEHOST " %s %s", self->numeric, user->numeric, host);
+ /* 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)
+ */
+ putsock("%s " P10_FAKEHOST2 " %s %s %s%s", self->numeric, user->numeric, ident, host, force ? " FORCE" : "");
}
void
irc_relay(char *message)
{
putsock("%s " P10_RELAY " %s", self->numeric, message);
- fprintf(stderr,"%s " P10_RELAY " %s", self->numeric, message);
}
void
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))
{
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
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
static CMD_FUNC(cmd_topic)
{
struct chanNode *cn;
- unsigned long chan_ts, topic_ts;
+ unsigned long topic_ts;
if (argc < 3)
return 0;
}
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);
//LQ !ABADE pk910 80.153.5.212 server.zoelle1.de ~watchcat :test
//ok let's check the login datas
struct handle_info *hi;
- char tmp[MAXLEN];
- sprintf(tmp, "*!%s@%s",argv[7],argv[5]);
- if((hi = checklogin(argv[4],argv[argc-1],&argv[3][1],tmp))) {
+ char tmp[MAXLEN], tmp2[MAXLEN];
+ sprintf(tmp, "%s@%s",argv[7],argv[6]);
+ sprintf(tmp2, "%s@%s",argv[7],argv[5]);
+ if((hi = checklogin(argv[4],argv[argc-1],&argv[3][1],tmp,tmp2))) {
//login ok
struct devnull_class *th;
char devnull[512];
} else {
devnull[0] = 0;
}
- if(getfakehost(argv[4])) {
+ if(!HANDLE_FLAGGED(hi, AUTOHIDE)) {
+ sprintf(tmp,"%s LA %s 0 %s\n",argv[3],hi->handle,devnull);
+ } else if(getfakehost(argv[4])) {
sprintf(tmp,"%s LA %s %s %s\n",argv[3],hi->handle,getfakehost(argv[4]),devnull);
} else {
extern const char *hidden_host_suffix;
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)
{
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
{
char numeric[COMBO_NUMERIC_LEN+1];
int local_num = get_local_numeric();
- unsigned long timestamp = now;
struct userNode *old_user = GetUserH(nick);
if (!modes)
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);
}
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;
case 'c': do_chan_mode(MODE_NOCOLORS); break;
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;
if (in_arg >= argc)
goto error;
char *mode = modes[in_arg++];
- if(mode[0] == '!' && !(flags & MCP_OPERMODE)) { //noflood flag also for overriders
- //only allow opers
- goto error;
- }
+ if(mode[0] == '!' && !(flags & MCP_OPERMODE)) //noflood flag also for overriders
+ goto error;//only allow opers
+ else if(mode[0] == '!')
+ mode++;
+
if(mode[0] == '+' || mode[0] == '@') {
mode++;
}
break;
}
}
- if(count <= 0 || time <= 0 || count > 100 || time > 600)
+ if(count <= 0 || time <= 0 || count > 100 || time > 600)
goto error;
change->modes_set |= MODE_NOFLOOD;
safestrncpy(change->new_noflood, modes[in_arg - 1], sizeof(change->new_noflood));
} else {
change->modes_clear |= MODE_NOFLOOD;
}
+ break;
case 'F':
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;
}
DO_MODE_CHAR(NOCTCPS, 'C');
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)
DO_MODE_CHAR(NOCTCPS, 'C');
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)
DO_MODE_CHAR(NOCTCPS, 'C');
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
}
DO_MODE_CHAR(NOCTCPS, 'C');
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);
- DO_MODE_CHAR(KEY, 'a'), args_used += sprintf(args + args_used, " %d", change->new_access);
- DO_MODE_CHAR(KEY, 'F'), args_used += sprintf(args + args_used, " %s", change->new_altchan);
- DO_MODE_CHAR(KEY, 'f'), args_used += sprintf(args + args_used, " %s", change->new_noflood);
+ DO_MODE_CHAR(ACCESS, 'a'), args_used += sprintf(args + args_used, " %d", change->new_access);
+ DO_MODE_CHAR(ALTCHAN, 'F'), args_used += sprintf(args + args_used, " %s", change->new_altchan);
+ DO_MODE_CHAR(NOFLOOD, 'f'), args_used += sprintf(args + args_used, " %s", change->new_noflood);
DO_MODE_CHAR(UPASS, 'U'), args_used += sprintf(args + args_used, " %s", change->new_upass);
DO_MODE_CHAR(APASS, 'A'), args_used += sprintf(args + args_used, " %s", change->new_apass);
#undef DO_MODE_CHAR
case 'c': cleared |= MODE_NOCOLORS; break;
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;
}