GOOGLE
/************************************************************************
* psybnc2.3, src/p_link.c
* Copyright (C) 2001 the most psychoid and
* the cool lam3rz IRC Group, IRCnet
* http://www.psychoid.lam3rz.de
*
* 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 1, 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.
*/
#ifndef lint
static char rcsid[] = "@(#)$Id: p_link.c, v 2.3 2001/07/13 02:03:00 psychoid Exp $";
#endif
#define P_LINK
#include <p_global.h>
#ifdef LINKAGE
/* look for a link by hostname and port */
int getlink(int peern)
{
int i=1;
pcontext;
while (i<=MAXCONN)
{
if (strlen(datalink(i)->host)==strlen(newpeer(peern)->host)) {
if (strstr(datalink(i)->host,newpeer(peern)->host)!=NULL) {
if (datalink(i)->port==newpeer(peern)->lnkport)
return i;
}
}
i++;
}
return 0x0;
}
/* look for a link by name */
int getlinkbyname(char *namelink)
{
struct linknodes *th;
int i;
pcontext;
th=linknode;
while (th!=NULL)
{
i=th->uid;
if (strlen(datalink(i)->name)==strlen(namelink)) {
if (strstr(datalink(i)->name,namelink)!=NULL) {
return i;
}
}
th=th->next;
}
return 0x0;
}
/* return a new link */
int getnewlink()
{
int i=1;
pcontext;
D_CREATE=1;
while (i<=MAXCONN)
{
if (datalink(i)->type==0) return i;
i++;
}
return 0x0;
}
/* linking a relay */
int linkrelayconnected(int nlink)
{
int tmpsock;
pcontext;
tmpsock=datalink(nlink)->outsock;
ssnprintf(tmpsock,gettxt(507),datalink(nlink)->iam,datalink(nlink)->iam,datalink(nlink)->iam);
ssnprintf(tmpsock,gettxt(508),datalink(nlink)->iam);
log(LOG_INFO,-1,gettxt(509),datalink(nlink)->iam);
return 0x0;
}
int errorrelaylink(int nlink, int errn)
{
struct socketnodes *lkm;
pcontext;
log(LOG_ERROR,-1,gettxt(510),datalink(nlink)->iam);
lkm=getpsocketbysock(datalink(nlink)->outsock);
if(lkm!=NULL)
{
lkm->sock->errorhandler=NULL;
killsocket(datalink(nlink)->outsock);
}
lkm=getpsocketbysock(datalink(nlink)->insock);
if(lkm!=NULL)
{
lkm->sock->errorhandler=NULL;
killsocket(datalink(nlink)->insock);
}
datalink(nlink)->instate=STD_NOCON;
datalink(nlink)->outstate=STD_NOCON;
datalink(nlink)->insock=0;
datalink(nlink)->outsock=0;
return -1;
}
int killrelaylink(int nlink)
{
struct socketnodes *lkm;
pcontext;
log(LOG_WARNING,-1,gettxt(511),datalink(nlink)->iam);
lkm=getpsocketbysock(datalink(nlink)->outsock);
if(lkm!=NULL)
{
lkm->sock->destructor=NULL;
killsocket(datalink(nlink)->outsock);
}
lkm=getpsocketbysock(datalink(nlink)->insock);
if(lkm!=NULL)
{
lkm->sock->destructor=NULL;
killsocket(datalink(nlink)->insock);
}
datalink(nlink)->instate=STD_NOCON;
datalink(nlink)->outstate=STD_NOCON;
datalink(nlink)->insock=0;
datalink(nlink)->outsock=0;
return -1;
}
/* link connected */
int connectedlink(int nlink)
{
char buf[400];
struct socketnodes *lkm;
int tmpsock;
pcontext;
tmpsock=datalink(nlink)->outsock;
ap_snprintf(ircbuf,sizeof(ircbuf),gettxt(512),datalink(nlink)->name,socketnode->sock->sport);
writesock_URGENT(tmpsock,ircbuf);
if (*datalink(nlink)->pass==0)
{
strmncpy(datalink(nlink)->pass,randstring(15),sizeof(datalink(nlink)->pass));
writelink(nlink);
}
ssnprintf(tmpsock,gettxt(513),datalink(nlink)->pass);
ssnprintf(tmpsock,gettxt(514),me,me);
#ifdef PARTYCHANNEL
ssnprintf(tmpsock,gettxt(515));
#endif
#ifdef INTNET
joinintnettolink(nlink);
#endif
ssnprintf(tmpsock,gettxt(516));
log(LOG_INFO,-1,gettxt(517),
nlink,datalink(nlink)->host,datalink(nlink)->port);
return 0x0;
}
int errorlink(int nlink,int errn)
{
pcontext;
log(LOG_ERROR,-1,gettxt(518),
nlink,datalink(nlink)->host,datalink(nlink)->port);
currentsocket->sock->destructor=NULL;
killsocket(datalink(nlink)->outsock);
datalink(nlink)->outstate=STD_NOCON;
return -1;
}
int killedlink(int nlink)
{
char buf[400];
pcontext;
log(LOG_WARNING,-1,gettxt(519),
nlink,datalink(nlink)->host,datalink(nlink)->port);
sysparty(gettxt(520),datalink(nlink)->iam);
killsocket(datalink(nlink)->outsock);
datalink(nlink)->outstate=STD_NOCON;
removetopology(me,datalink(nlink)->iam,lostlink);
return -1;
}
/* the simplest way of the proxy - the relay handling */
int relay(int nlink)
{
pcontext;
if(currentsocket->sock->syssock==datalink(nlink)->outsock)
writesock(datalink(nlink)->insock,ircbuf);
if(currentsocket->sock->syssock==datalink(nlink)->insock)
writesock(datalink(nlink)->outsock,ircbuf);
}
/* process a single link */
int processlink(int nlink, int sock, int state)
{
struct usernodes *th,*th2;
struct linknodes *lh;
struct stringarray *lkm,*pre;
int rc,rr=0;
char *pt,*pt2;
char buf[600];
char l,k;
char o[]="->";
char i[]="<-";
char r[]="R ";
char sic[500];
int last;
pcontext;
if (state!=STD_CONN) return 0x0;
parse();
pcontext;
if (!ifcommand("IAM") && !ifcommand(gettxt(521))) broadcast(nlink); /* if its the IAM message, it does NOT
get broadcasted */
pcontext;
pt=strchr(ircto,'@');
#ifdef PARTYCHANNEL
if(pt==NULL) pt=strchr(ircto,'*');
#endif
pcontext;
if (pt!=NULL)
{
*pt=0;
pt++;
if (strmcmp(pt,me)!=0 || (*ircto=='*' && strlen(pt)==1))
{
pcontext;
if (ifcommand(gettxt(522)))
{
rc=checkuser(ircto);
if (rc==0)
{
ap_snprintf(ircbuf,sizeof(ircbuf),gettxt(523),me,ircnick,irchost,ircto);
broadcast(0);
return 0x0;
}
#ifdef PARTYCHANNEL
ssnprintf(user(rc)->insock,gettxt(524),ircnick,irchost,user(rc)->nick,irccontent);
#else
ssnprintf(user(rc)->insock,gettxt(525),ircnick,irchost,user(rc)->nick,irccontent);
#endif
return 0x0;
}
pcontext;
if (ifcommand(gettxt(526)))
{
if(strstr(irccontent,o)!=NULL || strstr(irccontent,i)!=NULL) /* this is a listlink for the topology */
{
pt=strchr(irccontent,'[');
if(pt!=NULL)
{
pt++;
pt2=strstr(pt,"]*");
if(pt2!=NULL)
{
*pt2=0;
strmncpy(sic,pt,sizeof(sic)); /* in sic we got the first linker */
pt2++;
pt=strstr(pt2,o);
if(pt==NULL) pt=strstr(pt2,i);
if(pt==NULL) return 0x0;
pt2=strchr(pt+3,' ');
if(pt2!=NULL)
{
*pt2=0;
if(strstr(pt,o)==pt)
{
pt+=3;
addtopology(sic,pt);
} else {
pt+=3;
addtopology(pt,sic);
}
return 0x0;
}
}
}
}
pcontext;
#ifdef PARTYCHANNEL
if(strstr(ircbuf,gettxt(527))==ircbuf)
{
if(*ircto=='*') /* systemrequest */
{
pt=strchr(irccontent,']');
if(pt!=NULL)
{
pt+=2;
if(*pt=='*')
{
pt2=strchr(pt,'(');
if (pt2!=NULL)
{
pt+=2;
*pt2=0;
ap_snprintf(buf,sizeof(buf),gettxt(528),pt,irchost);
if(partyadd(buf)==1)
{
ap_snprintf(buf,sizeof(buf),gettxt(529) PARTYCHAN "\r\n",pt,irchost,pt,irchost);
th=usernode;
while(th!=NULL)
{
rc=th->uid;
if(user(rc)->instate==STD_CONN && user(rc)->sysmsg==1 && user(rc)->parent==0)
{
writesock(user(rc)->insock,buf);
}
th=th->next;
}
return 0x0;
}
}
}
}
}
}
#endif
rc=checkuser(ircto);
if (rc!=0)
{
ssnprintf(user(rc)->insock,gettxt(530),ircnick,user(rc)->nick,irccontent);
return 0x0;
}
}
}
}
pcontext;
if (ifcommand("IAM"))
{
if(*ircnick==0 || strchr(ircnick,' ')!=NULL || strchr(ircnick,'@')!=NULL || strchr(ircnick,'*')!=NULL)
{
sysparty(gettxt(531));
killsocket(sock);
datalink(nlink)->instate=STD_NOCON;
datalink(nlink)->outstate=STD_NOCON;
datalink(nlink)->insock=0;
datalink(nlink)->outsock=0;
clearlink(nlink);
eraselinkini(nlink);
return 0x0;
}
strmncpy(datalink(nlink)->iam,ircnick,sizeof(datalink(nlink)->iam));
addtopology(me,datalink(nlink)->iam);
writelink(nlink);
}
pcontext;
if (ifcommand(gettxt(532)))
{
if (strmcmp(me,ircto)!=0)
{
log(LOG_ERROR,-1,gettxt(533),
nlink,datalink(nlink)->host,datalink(nlink)->port);
killsocket(sock);
removetopology(me,datalink(nlink)->iam,lostlink);
datalink(nlink)->instate=STD_NOCON;
datalink(nlink)->outstate=STD_NOCON;
datalink(nlink)->insock=0;
datalink(nlink)->outsock=0;
clearlink(nlink);
eraselinkini(nlink);
return 0x0;
}
}
pcontext;
if (ifcommand(gettxt(534)))
{
th=usernode;
while (th!=NULL) {
rc=th->uid;
if ((user(rc)->instate==STD_CONN && user(rc)->parent==0 && user(rc)->sysmsg==1) || rc==1)
{
strmncpy(sic,irccontent,sizeof(sic));
#ifdef PARTYCHANNEL
strcpy(irccommand,gettxt(535));
strcpy(ircto,PARTYCHAN);
strcat(ircto," ");
#endif
/* keeping being compatible with earlier versions requires this */
if(strlen(ircnick)==6 && strstr(ircnick,gettxt(536))==ircnick)
{
#ifdef PARTYCHANNEL
if(strstr(irccontent,gettxt(537))!=NULL)
{
pt=strstr(irccontent,gettxt(538));
if(pt!=NULL)
{
pt+=5;
pt2=strchr(pt,' ');
if (pt2!=NULL) *pt2=0;
strmncpy(ircnick,pt,sizeof(ircnick));
ap_snprintf(buf,sizeof(buf),gettxt(539),pt,irchost);
strcpy(irccommand,"JOIN");
strcpy(irccontent,PARTYCHAN);
*ircto=0;
if(rr==0) { partyadd(buf); rr=1; }
}
}
if(strstr(irccontent,gettxt(540))!=NULL)
{
pt=strstr(irccontent,gettxt(541));
if(pt!=NULL)
{
pt+=5;
pt2=strchr(pt,' ');
if (pt2!=NULL) *pt2=0;
strmncpy(ircnick,pt,sizeof(ircnick));
ap_snprintf(buf,sizeof(buf),gettxt(542),pt,irchost);
strcpy(irccommand,"PART");
strcpy(irccontent,gettxt(543));
if(rr==0) { partyremove(buf); rr=1; }
}
}
#endif
if(strstr(irccontent,gettxt(544))==irccontent)
{
ap_snprintf(ircbuf,sizeof(ircbuf),gettxt(545),me);
broadcast(0);
return 0x0;
}
if(strstr(irccontent,gettxt(546))==irccontent)
{
pt=irccontent+11;
pt2=strchr(pt,')');
if(pt2!=NULL) *pt2=0;
removetopology(irchost,pt,lostlink);
if(pt2!=NULL) *pt2=')';
}
}
#ifdef PARTYCHANNEL
ap_snprintf(buf,sizeof(buf),gettxt(547),
ircnick,irchost,ircnick,irchost,
irccommand,ircto,irccontent);
if(user(rc)->instate==STD_CONN && user(rc)->parent==0 && user(rc)->sysmsg==1)
writesock(user(rc)->insock,buf);
#endif
ap_snprintf(irccontent,sizeof(irccontent),"%s",sic);
}
th=th->next;
}
return 0x0;
}
pcontext;
if (ifcommand("BWHO"))
{
th=usernode;
while (th!=NULL) {
rc=th->uid;last=0;
if (user(rc)->instate!=STD_NOUSE)
{
if (user(rc)->parent != 0) l='^'; else { l='*';last=1; }
if (user(rc)->sysmsg == 0) l='+';
if (*user(rc)->host==0) l=' '; else last=0;
if(last==1)
ap_snprintf(ircbuf,sizeof(ircbuf),gettxt(548),me,ircnick,irchost,me,l,user(rc)->login,user(rc)->nick,user(rc)->network,user(rc)->server,user(rc)->user,user(rc)->last);
else
ap_snprintf(ircbuf,sizeof(ircbuf),gettxt(549),me,ircnick,irchost,me,l,user(rc)->login,user(rc)->nick,user(rc)->network,user(rc)->server,user(rc)->user);
broadcast(0);
}
th=th->next;
}
return 0x0;
}
pcontext;
if (ifcommand(gettxt(550)))
{
lh=linknode;
while (lh!=NULL)
{
rc=lh->uid;
l=' ';
if (datalink(rc)->type!=0)
{
if (datalink(rc)->type==LI_LINK)
{
pt=o;
if (datalink(rc)->outstate==STD_CONN) l='*';
}
if (datalink(rc)->type==LI_ALLOW)
{
if (datalink(rc)->instate==STD_CONN) l='*';
pt=i;
}
if (datalink(rc)->type==LI_RELAY) { pt=r; l='*';}
ap_snprintf(ircbuf,sizeof(ircbuf),gettxt(551),me,ircnick,irchost,me,l,rc,pt,datalink(rc)->iam,datalink(rc)->host,datalink(rc)->port);
broadcast(0);
}
lh=lh->next;
}
return 0x0;
}
pcontext;
#ifdef PARTYCHANNEL
if (ifcommand(gettxt(552)))
{
strmncpy(partytopic,irccontent,sizeof(partytopic));
th=usernode;
while (th!=NULL) {
rc=th->uid;
if (user(rc)->instate==STD_CONN && user(rc)->parent==0)
{
ssnprintf(user(rc)->insock,gettxt(553) PARTYCHAN gettxt(554),
ircnick,irchost,ircnick,irchost,irccontent);
}
th=th->next;
}
}
#endif
#ifdef INTNET
if (ifcommand(gettxt(555)))
{
pt=strchr(ircbuf,'\r');
if(pt==NULL) pt=strchr(ircbuf,'\n');
if(pt!=NULL) *pt=0;
strmncpy(ircbuf,rtrim(irccontent),sizeof(ircbuf));
internalinbound(0,nlink);
}
#endif
pcontext;
br:
}
/* error handler for the link checking */
int checklinkerror(int nlink,int errn)
{
checklinkkill(nlink);
currentsocket->sock->destructor=NULL;
return 0x0;
}
/* Destructor for the link checking */
int checklinkkill(int nlink,int errn)
{
int sock;
pcontext;
if(datalink(nlink)->type==LI_ALLOW)
sock=datalink(nlink)->insock;
else
sock=datalink(nlink)->outsock;
sysparty(gettxt(556),datalink(nlink)->iam);
log(LOG_WARNING,-1,gettxt(557),nlink);
killsocket(sock);
datalink(nlink)->instate=STD_NOCON;
datalink(nlink)->outstate=STD_NOCON;
datalink(nlink)->insock=0;
datalink(nlink)->outsock=0;
removetopology(me,datalink(nlink)->iam,lostlink);
return 0x0;
}
/* checking a single linktraffic */
int checklinkdata (int nlink)
{
pcontext;
if (datalink(nlink)->type==0) return 0x0;
if (datalink(nlink)->instate!=STD_CONN && datalink(nlink)->outstate!=STD_CONN) return 0x0;
if (datalink(nlink)->type==LI_RELAY)
relay(nlink);
if (datalink(nlink)->type==LI_LINK)
processlink(nlink,datalink(nlink)->outsock,datalink(nlink)->outstate);
if (datalink(nlink)->type==LI_ALLOW)
processlink(nlink,datalink(nlink)->insock,datalink(nlink)->instate);
}
/* linking a relay */
int linkrelay(int npeer, int rootlink)
{
int tmpsock;
struct socketnodes *lkm;
char *ho;
char vsl[10];
int issl=SSL_OFF;
int nlink;
int proto;
pcontext;
vsl[0]=0;
#ifdef HAVE_SSL
if(strstr(newpeer(npeer)->server,"S=")==newpeer(npeer)->server)
{
issl=SSL_ON;
ho=newpeer(npeer)->server+2;
strcpy(vsl,"SSL-");
} else
#endif
ho=newpeer(npeer)->host;
log(LOG_INFO,-1,gettxt(558),
vsl,
newpeer(npeer)->login,
datalink(rootlink)->name,
newpeer(npeer)->host,
newpeer(npeer)->lnkport,
ho,
newpeer(npeer)->port,
newpeer(npeer)->vhost);
lkm=getpsocketbysock(newpeer(npeer)->insock);
if(lkm!=NULL)
{
lkm->sock->flag=SOC_CONN;
lkm->sock->param=npeer;
lkm->sock->constructor=NULL;
lkm->sock->constructed=NULL;
lkm->sock->handler=checklinkdata;
lkm->sock->errorhandler=errorrelaylink;
lkm->sock->destructor=killrelaylink;
}
proto=getprotocol(ho);
tmpsock=createsocket(0,ST_CONNECT,0,NULL,linkrelayconnected,errorrelaylink,checklinkdata,killrelaylink,proto,issl);
tmpsock=connectto(tmpsock,ho,newpeer(npeer)->port,newpeer(npeer)->vhost);
if (tmpsock!=0)
{
nlink=getnewlink();
if (nlink==0) {
killsocket(tmpsock);
log(LOG_ERROR,-1,gettxt(559));
return -1;
}
datalink(nlink)->type=LI_RELAY;
datalink(nlink)->instate=STD_CONN;
datalink(nlink)->insock=newpeer(npeer)->insock;
strmncpy(datalink(nlink)->iam,newpeer(npeer)->nick,sizeof(datalink(nlink)->iam));
strmncpy(datalink(nlink)->host,newpeer(npeer)->host,sizeof(datalink(nlink)->host));
strmncpy(datalink(nlink)->pass,newpeer(npeer)->pass,sizeof(datalink(nlink)->pass));
strmncpy(datalink(nlink)->name,newpeer(npeer)->name,sizeof(datalink(nlink)->name));
datalink(nlink)->port=datalink(nlink)->port;
datalink(nlink)->outstate=STD_CONN;
datalink(nlink)->outsock=tmpsock;
clearpeer(npeer);
lkm=getpsocketbysock(tmpsock);
if(lkm!=NULL)
{
lkm->sock->flag=SOC_SYN;
lkm->sock->param=nlink;
}
return 0x0;
}
log(LOG_ERROR,-1,gettxt(560),newpeer(npeer)->server,newpeer(npeer)->port);
return -1;
}
/* connect a single link */
int connectlink(int nlink)
{
int tmpsock;
int proto;
int issl=SSL_OFF;
char vsl[10];
char *ho;
pcontext;
vsl[0]=0;
if (datalink(nlink)->type!=LI_LINK)
return 0x0;
if (datalink(nlink)->outstate==STD_CONN)
return 0x0;
if (datalink(nlink)->delayed>0)
{
datalink(nlink)->delayed-=1;
return 0x0;
}
#ifdef HAVE_SSL
if(strstr(datalink(nlink)->host,"S=")==datalink(nlink)->host)
{
ho=datalink(nlink)->host+2;
issl=SSL_ON;
strcpy(vsl,"SSL-");
} else
#endif
ho=datalink(nlink)->host;
datalink(nlink)->delayed=0;
log(LOG_INFO,-1,gettxt(561),vsl,nlink,ho,datalink(nlink)->port);
/* we got a server and a port */
proto=getprotocol(ho);
tmpsock=createsocket(0,ST_CONNECT,nlink,NULL,connectedlink,errorlink,checklinkdata,killedlink,proto,issl);
tmpsock=connectto(tmpsock,ho,datalink(nlink)->port,NULL);
if (tmpsock!=0)
{
datalink(nlink)->outstate=STD_CONN;
datalink(nlink)->outsock=tmpsock;
return 0x1;
}
log(LOG_ERROR,-1,gettxt(562),nlink,datalink(nlink)->host,datalink(nlink)->port);
datalink(nlink)->outstate=STD_NOCON;
return -1;
}
#endif
/* checking unconnected links */
int checklinks()
{
#ifdef LINKAGE
struct linknodes *th;
int i;
pcontext;
th=linknode;
while (th!=NULL)
{
i=th->uid;
if (connectlink(i)==1) return 0x0;
th=th->next;
}
#endif
return 0x0;
}
Copyright © 1945 -