/************************************************************************
* IRC - Internet Relay Chat protocol/native.c
*
* Copyright (C) 2000-2003 TR-IRCD Development
*
* Copyright (C) 1990 Jarkko Oikarinen and
* University of Oulu, Co Center
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "h.h"
#include "hook.h"
#include "s_conf.h"
#include "comply.h"
#include "usermode.h"
static int log_greet = -1;
static int do_introduce_client(struct hook_data *thisdata);
static int do_sendnick_TS(struct hook_data *thisdata);
static int do_inform_remote_servers(struct hook_data *thisdata);
static int do_inform_other_servers(struct hook_data *thisdata);
static int do_continue_server_estab(struct hook_data *thisdata);
static int do_start_server_estab(struct hook_data *thisdata);
static int do_connect_to_server(struct hook_data *thisdata);
void proto_modinit()
{
if (!GeneralOpts.protocol_in_use) {
hook_add_hook("continue server estab", (hookfn *) do_continue_server_estab);
hook_add_hook("start server estab", (hookfn *) do_start_server_estab);
hook_add_hook("sendnick TS", (hookfn *) do_sendnick_TS);
hook_add_hook("introduce client", (hookfn *) do_introduce_client);
hook_add_hook("inform remote servers", (hookfn *) do_inform_remote_servers);
hook_add_hook("inform other servers", (hookfn *) do_inform_other_servers);
hook_add_hook("connect to server", (hookfn *) do_connect_to_server);
log_greet = logevent_register("protocol init", LOG_ON_LOG, LOG_IRCLOG|LOG_STDOUT, LOG_INFO,
"Initialized Native TR-IRCD 5 Module");
logevent_call(log_greet);
}
return;
}
int _comply_unload_modules()
{
return 1;
}
int _comply_ignore_messages()
{
return 1;
}
int _comply_untokenize()
{
return 1;
}
int _comply_retokenize()
{
return 1;
}
int _comply_unuse_messages()
{
return 1;
}
int _comply_rehash()
{
if (!GeneralOpts.protocol_in_use)
logevent_unregister(log_greet);
return 1;
}
static int do_introduce_client(struct hook_data *thisdata)
{
struct Client *cptr = thisdata->client_p;
struct Client *sptr = thisdata->source_p;
struct User *user = thisdata->user;
char *nick = thisdata->name;
struct Client *nsptr;
char ubuf[32];
unsigned long li = 0;
char diff = '\0';
char r_sidbuf[8], r_ipbuf[8];
char *sidbuf, *ipbuf;
send_umode(NULL, sptr, 0, SEND_UMODES, ubuf);
if (!*ubuf) {
ubuf[0] = '+';
ubuf[1] = '\0';
}
hash_check_watch(sptr, RPL_LOGON);
if (!IsClientIpv6(sptr))
li = htonl(IN4_ADDR(sptr->ip));
if (HasID(sptr)) {
sidbuf = base64enc_r(sptr->user->servicestamp, r_sidbuf);
if (IsClientIpv6(sptr)) {
diff = '%';
ipbuf = sptr->hostip;
} else {
diff = ':';
ipbuf = base64enc_r(IN4_ADDR(sptr->ip), r_ipbuf);
}
sendto_flag_serv_butone(cptr, CAPAB_IDENT, CAPAB_NICKIP, NULL,
TOK1_CLIENT,
"%s %d %T %s %s %s %s %d !%s%c%s %s :%s", nick,
sptr->hopcount + 1, sptr, ubuf,
user->username, user->host, user->fakehost,
sptr->lang, sptr->id.string, diff, ipbuf, sidbuf,
sptr->info);
sendto_flag_serv_butone(cptr, CAPAB_NICKIP, CAPAB_IDENT, NULL,
TOK1_NICK,
"%s %d %T %s %s %s %s %s %lu %lu :%s", nick,
sptr->hopcount + 1, sptr, ubuf,
user->username, user->host, user->fakehost,
user->server, sptr->user->servicestamp,
li, sptr->info);
} else {
sendto_serv_butone(cptr, NULL, TOK1_NICK,
"%s %d %T %s %s %s %s %s %lu %lu :%s",
nick, sptr->hopcount + 1, sptr, ubuf,
user->username, user->host, user->fakehost,
user->server, sptr->user->servicestamp, li,
sptr->info);
}
sendto_service(SERVICE_SEE_RNICKS, 0, NULL, NULL, TOK1_NICK,
"%s %d %T %s %s %s %s %s %lu :%s", nick,
sptr->hopcount + 1, sptr, ubuf,
user->username, user->host, user->fakehost,
user->server, sptr->user->servicestamp, sptr->info);
/* FIXME: This can make a user identify to any NickServ -TimeMr14C */
if (MyClient(sptr)) {
if (sptr->nspass[0]
&& (nsptr = find_person(ServicesConf.nickserv))) {
sendto_one_server(nsptr, sptr, TOK1_PRIVMSG, "%s@%s :SIDENTIFY %s",
ServicesConf.nickserv,
ServicesConf.services_name, sptr->nspass);
}
memset(sptr->passwd, '\0', PASSWDLEN);
}
if (MyClient(cptr) && ubuf[1])
send_umode(cptr, sptr, 0, SEND_UMODES, ubuf);
return 0;
}
static int do_sendnick_TS(struct hook_data *thisdata)
{
struct Client *cptr = thisdata->client_p;
struct Client *acptr = thisdata->source_p;
char ubuf[32];
unsigned long li = 0;
char diff = '\0';
char r_sidbuf[8], r_ipbuf[8];
char *sidbuf, *ipbuf;
if (IsPerson(acptr)) {
send_umode(NULL, acptr, 0, SEND_UMODES, ubuf);
if (!*ubuf) { /* trivial optimization - Dianora */
ubuf[0] = '+';
ubuf[1] = '\0';
}
if (!IsClientIpv6(acptr))
li = htonl(IN4_ADDR(acptr->ip));
if (IsIDCapable(cptr) && HasID(acptr)) {
sidbuf = base64enc_r(acptr->user->servicestamp, r_sidbuf);
if (IsClientIpv6(acptr)) {
diff = '%';
ipbuf = acptr->hostip;
} else {
diff = ':';
ipbuf = base64enc_r(IN4_ADDR(acptr->ip), r_ipbuf);
}
sendto_one_server(cptr, NULL, TOK1_CLIENT,
"%s %d %T %s %s %s %s %d !%s%c%s %s :%s",
acptr->name, acptr->hopcount + 1,
acptr, ubuf, acptr->user->username,
acptr->user->host, acptr->user->fakehost,
acptr->lang, acptr->id.string, diff, ipbuf, sidbuf, acptr->info);
} else {
sendto_one_server(cptr, NULL, TOK1_NICK,
"%s %d %T %s %s %s %s %s %lu %lu :%s",
acptr->name, acptr->hopcount + 1, acptr, ubuf,
acptr->user->username,
acptr->user->host,
acptr->user->fakehost,
acptr->user->server,
acptr->user->servicestamp, li,
acptr->info);
}
}
return 0;
}
static int do_inform_remote_servers(struct hook_data *thisdata)
{
struct Client *bclient_p;
dlink_node *ptr;
struct Client *client_p = thisdata->client_p;
struct Client *target_p = thisdata->aclient_p;
char *name = thisdata->name;
struct ConfItem *aconf;
for (ptr = serv_list.head; ptr; ptr = ptr->next) {
bclient_p = ptr->data;
if (bclient_p == client_p)
continue;
if (!(aconf = bclient_p->serv->nline)) {
sendto_gnotice("Lost N-line for %s on %s. Closing",
get_client_name(client_p, HIDE_IP), name);
return exit_client(client_p, client_p, "Lost N line");
}
if (IsIDCapable(bclient_p)) {
if (HasID(target_p)) {
sendto_one_server(bclient_p, target_p->servptr,
TOK1_SERVER, "%C %d %c%c%c !%s :%s",
target_p, target_p->hopcount + 1,
(WillHideName(target_p) ? 'H' : 'N'),
(IsULine(target_p) ? 'U' : 'N'),
(IsHub(target_p) ? 'R' : 'N'),
target_p->id.string, target_p->info);
} else {
sendto_one_server(bclient_p, target_p->servptr,
TOK1_SERVER, "%C %d %c%c%c :%s",
target_p, target_p->hopcount + 1,
(WillHideName(target_p) ? 'H' : 'N'),
(IsULine(target_p) ? 'U' : 'N'),
(IsHub(target_p) ? 'R' : 'N'), target_p->info);
}
} else {
sendto_one_server(bclient_p, target_p->servptr,
TOK1_SERVER, "%C %d :%s",
target_p, target_p->hopcount + 1, target_p->info);
}
}
return 0;
}
static int do_inform_other_servers(struct hook_data *thisdata)
{
struct Client *cptr = thisdata->client_p;
if (HasID(cptr)) {
sendto_flag_serv_butone(cptr, CAPAB_IDENT|CAPAB_HIDENAME, 0, &me, TOK1_SERVER,
"%C 2 %c%c%c !%s :%s", cptr,
(WillHideName(cptr) ? 'H' : 'N'),
(IsULine(cptr) ? 'U' : 'N'),
(IsHub(cptr) ? 'R' : 'N'), cptr->id.string, cptr->info);
sendto_flag_serv_butone(cptr, 0, CAPAB_IDENT|CAPAB_HIDENAME, &me, TOK1_SERVER,
"%C 2 :%s", cptr, cptr->info);
} else {
sendto_flag_serv_butone(cptr, CAPAB_IDENT|CAPAB_HIDENAME, 0, &me, TOK1_SERVER,
"%C 2 %c%c%c :%s", cptr,
(WillHideName(cptr) ? 'H' : 'N'),
(IsULine(cptr) ? 'U' : 'N'), (IsHub(cptr) ? 'R' : 'N'), cptr->info);
sendto_flag_serv_butone(cptr, 0, CAPAB_IDENT|CAPAB_HIDENAME, &me, TOK1_SERVER,
"%C 2 :%s", cptr, cptr->info);
}
return 0;
}
static int do_continue_server_estab(struct hook_data *thisdata)
{
struct Client *client_p = thisdata->client_p;
struct Client *target_p;
for (target_p = &me; target_p; target_p = target_p->prev) {
/* target_p->from == target_p for target_p == client_p */
if (target_p->from == client_p)
continue;
if (IsServer(target_p)) {
if (IsIDCapable(client_p)) {
if (HasID(target_p)) {
sendto_one_server(client_p, target_p->servptr,
TOK1_SERVER, "%C %d %c%c%c !%s :%s",
target_p, target_p->hopcount + 1,
(WillHideName(target_p) ? 'H' : 'N'),
(IsULine(target_p) ? 'U' : 'N'),
(IsHub(target_p) ? 'R' : 'N'),
target_p->id.string, target_p->info);
} else {
sendto_one_server(client_p, target_p->servptr,
TOK1_SERVER, "%C %d %c%c%c :%s",
target_p, target_p->hopcount + 1,
(WillHideName(target_p) ? 'H' : 'N'),
(IsULine(target_p) ? 'U' : 'N'),
(IsHub(target_p) ? 'R' : 'N'), target_p->info);
}
} else {
sendto_one_server(client_p, target_p->servptr,
TOK1_SERVER, "%C %d :%s",
target_p, target_p->hopcount + 1, target_p->info);
}
}
}
return 0;
}
static int do_start_server_estab(struct hook_data *thisdata)
{
struct Client *client_p = thisdata->client_p;
struct ConfItem *aconf = thisdata->confitem;
int emptypass = thisdata->check;
int dontwantflags = 0;
if (!emptypass)
sendto_one(client_p, "%s %s :TS7", MSG_PASS, aconf->spasswd);
#ifdef HAVE_ENCRYPTION_ON
dontwantflags |= (IsConfEncrypted(aconf) ? 0 : CAPAB_DKEY);
#endif
send_capab_to(client_p, dontwantflags);
sendto_one_server(client_p, NULL, TOK1_MYID, "!%s", me.id.string);
sendto_one_server(client_p, NULL, TOK1_SERVER, "%C 1 :%s", &me, me.info);
sendto_one_server(client_p, NULL, TOK1_SVINFO, "%d %d 0 :%lu",
TS_CURRENT, TS_MIN, (unsigned long) timeofday);
return 0;
}
static int do_connect_to_server(struct hook_data *thisdata)
{
#ifdef HAVE_ENCRYPTION_ON
struct Client *client_p = thisdata->client_p;
#endif
do_start_server_estab(thisdata);
#ifdef HAVE_ENCRYPTION_ON
if (!CanDoDKEY(client_p) || !WantDKEY(client_p));
else {
SetNegoServer(client_p); /* VERY IMPORTANT THAT THIS IS HERE */
sendto_one(client_p, "DKEY START");
}
#endif
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1