/* Simple bnc escrito por infamous [gH] */
/*
http://infamous.swipnet.se */
/* [infamous@dalnet] #unixos */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
extern h_errno;
int pt,mu,dp,cu,po;
char ps[20];
char vhostname[256] = "";
void
child_killer(int s)
{
wait(NULL);
cu--;
signal(SIGCHLD, child_killer);
}
int
do_connect(char *hostname, u_short port)
{
int s;
struct hostent *he;
struct sockaddr_in sin;
s = socket(AF_INET, SOCK_STREAM, 0);
if(s < 0)
return -2;
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ( *vhostname ? inet_addr(vhostname) : INADDR_ANY );
if(sin.sin_addr.s_addr == -1 && *vhostname)
{
he = gethostbyname(vhostname);
if(!he)
return -1;
memcpy(&sin.sin_addr, he->h_addr, he->h_length);
}
if(bind(s, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0)
{
perror("bind");
exit(0);
}
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = inet_addr(hostname);
if(sin.sin_addr.s_addr == -1)
{
he = gethostbyname(hostname);
if(!he)
return -1;
memcpy(&sin.sin_addr, he->h_addr, he->h_length);
}
if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
close(s);
return -2;
}
return s;
}
server(int s)
{
int sock_c=-1;
int maxfd = s+1;
char buffer[1024];
char user[1024];
char nick[100];
char tm[2];
int u,n,p,up;
fd_set rset;
u_short myport;
char *cmd, *server, *port,*nck,*pass,*spass;
char myserver[1024];
char spast[30];
strcpy(tm," ");
u=1;
n=1;
p=0;
if(po)
p=1;
while((u+n+p)&&3){
memset(buffer,0,1023);
while(tm[0]!='\n'||strlen(buffer)<=0){
memset(tm,0,2);
if(read(s,tm,1) <= 0){
close(s);
return;
}
strncat(buffer,tm,1);
}
if(!strncasecmp(buffer, "USER ", 5)){
strncpy(user, buffer,1023);
u=0;
}
else
if(!strncasecmp(buffer, "NICK ", 5)){
strncpy(nick,buffer,100);
nck=NULL;
strtok(nick," ");
nck=strtok(NULL," \n\r");
if(nck)
n=0;
if(p=1){
sprintf(buffer, ":
[email protected] NOTICE %s :You need to say /quote PASS <password>\n",nck);
write(s, buffer, strlen(buffer));
}
}
else
if(!strncasecmp(buffer, "PASS ", 5)){
strncpy(myserver,buffer,1023);
pass=NULL;
strtok(myserver," ");
pass=strtok(NULL," \n\r");
if(pass){
if(!strncmp(pass,ps,strlen(ps)))
p=0;
}
}
}
sprintf(buffer, ":
[email protected]
NOTICE %s :Level two, lets connect to something real now\n",nck);
write(s, buffer, strlen(buffer));
sprintf(buffer, ":
[email protected]
NOTICE %s :type /quote conn [server] <port> <pass> to connect\n",nck);
write(s, buffer, strlen(buffer));
while(1)
{
FD_ZERO(&rset);
FD_SET(s, &rset);
if(sock_c >= 0)
FD_SET(sock_c, &rset);
if(sock_c > s)
maxfd = sock_c + 1;
else
maxfd = s + 1;
select(maxfd, &rset, NULL, NULL, NULL);
memset(buffer, 0, 1024);
if(FD_ISSET(s, &rset))
{
if(read(s, buffer, 1023) <= 0)
{
close(s);
close(sock_c);
return;
}
if(sock_c >= 0)
{
write(sock_c, buffer, strlen(buffer));
}
else
{
cmd = NULL;
server = NULL;
port = NULL;
spass = NULL;
up = 0;
cmd = strtok(buffer, " ");
if(!cmd)
continue;
if(!strcasecmp(cmd,"vip")){
server = strtok(NULL, " \n\r");
if(!server)
continue;
strncpy(vhostname,server,256);
sprintf(buffer,":
[email protected] NOTICE %s :Your Vhost is now %s\n",nck,vhostname);
write(s,buffer,strlen(buffer));
continue;
}
if(strcasecmp(cmd, "conn"))
continue;
server = strtok(NULL, " \n\r");
if(!server)
continue;
strncpy(myserver, server,1024);
port = strtok(NULL, " \n\r");
if(!port) {
myport=dp;
}
else
myport = atoi(port);
spass = strtok(NULL, " \n\r");
if(!spass) {
up = 0;
}
else
{
up = 1;
strncpy(spast,spass,29);
}
sprintf(buffer, ":
[email protected] NOTICE %s :Making reality through %s port %i\n",nck,myserver,myport);
write(s, buffer, strlen(buffer));
sock_c = do_connect(myserver, myport);
if(sock_c < 0)
sock_c = -1;
if(up){
sprintf(buffer,"PASS %s\n",spast);
write(sock_c,buffer,strlen(buffer));
}
write(sock_c, user, strlen(user));
sprintf(buffer,"NICK %s\n",nck);
write(sock_c, buffer, strlen(buffer));
memset(buffer, 0, 1024);
read(sock_c, buffer, 1023);
if(strlen(buffer) > 0)
{
write(s, buffer, strlen(buffer));
}
continue;
}
}
if(sock_c >= 0)
{
if(FD_ISSET(sock_c, &rset))
{
memset(buffer, 0, 1024);
if(read(sock_c, buffer, 1023) <= 0)
{
close(s);
close(sock_c);
return;
}
write(s, buffer, strlen(buffer));
}
}
}
}
loadconf(){
FILE *conf;
char *confcmd,*confval;
char line[100];
int howfar;
if((conf=fopen("bnc.conf","r")) == NULL) {
return 1;
}
howfar=0;
while(!feof(conf)){
memset(line,0,100);
fgets(line,100,conf);
howfar++;
if(!strlen(line))
continue;
if(strncmp(line,"#",1)){
confcmd=NULL;
confval=NULL;
confcmd=strtok(line,":");
if(!confcmd)
continue;
confval=strtok(NULL,"\n");
if(!confval)
continue;
if(!strcasecmp(confcmd,"pt"))
pt=atoi(confval);
else
if(!strcasecmp(confcmd,"mu"))
mu=atoi(confval);
else
if(!strcasecmp(confcmd,"dp"))
dp=atoi(confval);
else
if(!strcasecmp(confcmd,"ps")){
strcpy(ps,confval);
po=1;
}
else
if(!strcasecmp(confcmd,"vh")){
strcpy(vhostname,confval);
}
else
printf("Config line %i rejected-what weirdo told you '%s' goes in my config file?\n",howfar,confcmd);
}
}
fclose(conf);
return 0;
}
int
main(int argc, char *argv[])
{
int a_sock = 0;
int s_sock = 0;
struct sockaddr_in sin;
int sinlen;
int mypid;
pt=6861;
mu=4;
dp=6667;
cu=0;
po=0;
strcpy(ps,"roots-ownz-j00");
printf("\bnc\n");
if(loadconf()) {
}
printf("* Configuration *\n");
printf(" Daemon port......:%u\n Password.........:%s\n Maxusers.........:%u\n Default port.....:%u\n",pt,ps,mu,dp);
s_sock = socket(AF_INET, SOCK_STREAM, 0);
if(s_sock < 0)
{
perror("socket");
exit(0);
}
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = htons(pt);
sin.sin_addr.s_addr = INADDR_ANY;
if(bind(s_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0)
{
perror("bind");
exit(0);
}
if(listen(s_sock, 10) < 0)
{
perror("listen");
exit(0);
}
signal(SIGHUP, SIG_IGN);
switch(fork())
{
case -1:
printf("fatal error: unable to fork()");
exit(-1);
case 0:
setsid();
break;
default:
exit(0);
}
close(0);
close(1);
close(2);
signal(SIGCHLD, child_killer);
while(1)
{
sinlen = sizeof(sin);
close(a_sock);
a_sock = accept(s_sock, (struct sockaddr *)&sin, &sinlen);
if(a_sock < 0 && errno == EINTR)
continue;
if(a_sock < 0)
{
perror("accept");
continue;
}
cu++;
if((cu>mu) && (mu>0)){
close(a_sock);
cu--;
continue;
}
switch(fork())
{
case -1:
close(a_sock);
continue;
case 0:
close(s_sock);
server(a_sock);
exit(0);
}
}
}