<html>/*
        Written 2005 by chrak <chrak@b4b0.org> <http://www.chrakworld.com>

    shoutoutz to #b4b0 and #c1zc0 @ EFNet

 ircclient -> ciscoBNC -> router -> ircserver

/server ciscoBNCserv 7777
/quote doitup 1.1.1.1 mypass irc.LOL.com 6667


this is version 0.9, next will have more bug fixes, error checking, password protection,
ability to disconnect and resume irc sessions, lists of DOITUPs stored!

 can someone email me if they know how to turn off IOS> shell echoing?


  This code is distributed under the GNU Public Licence (GPL) version 2.
   See http://www.gnu.org/ for further details of the GPL.  If you do not
   have a web browser you can read the LICENSE file in this directory.
**/



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <time.h>


#define D_VER "0.9"
#define D_PORT "7777"
#define D_REALNAME "ciscoBNC user"


int create_server (unsigned int port);
int server_notice (int sockchar *msg);
int server_notice_from (int sockchar *msgchar *from);
int serve_client (int sock);
int relay_client_and_router (int sockint r_sock);

int rnd1toN (int max);


void
startdaemon 
(void)
{
  switch (
fork ())
    {
    case -
1:
      
perror ("fork()");
      exit (
1);
    case 
0:            /* child */
      
break;
    default:            
/* parent */
      
exit (0);
    }

  if (
setsid () == -1)
    {
      
perror ("setsid()");
      exit (
1);
    }
  
//fclose(stdin);
  //fclose(stdout);
}


// vhost = NULL for no bind()
int
connect_to_tcphost 
(const char *hostnameunsigned int port,
            const 
char *vhost)
{
  
int sock;
  
struct hostent *he, *hel;
  
struct sockaddr_in saddr;
  
struct sockaddr_in localaddr;

  if ((
sock socket (AF_INETSOCK_STREAM0)) == -1)
    {
      
perror ("socket()");
      return -
1;
    }


  if (
vhost)
    {
      if ((
hel gethostbyname (vhost)) == NULL)
    {
      
herror ("gethostbyname()");
      
close (sock);
      return -
1;
    }

      
memset (&localaddr0sizeof (struct sockaddr_in));

      
localaddr.sin_family AF_INET;
      
localaddr.sin_port 0;
      
localaddr.sin_addr = *((struct in_addr *) hel->h_addr);

/* this is to use VHOST */

      
if (bind (sock, (struct sockaddr *) &localaddrsizeof (localaddr)))
    {
      
perror ("bind()");
      
close (sock);
      return -
1;
    }
    }


  if ((
he gethostbyname (hostname)) == NULL)
    {
      
herror ("gethostbyname()");
      
close (sock);
      return -
1;
    }


  
saddr.sin_family AF_INET;
  
saddr.sin_port htons (port);
  
saddr.sin_addr = *((struct in_addr *) he->h_addr);
  if (
connect
      
(sock, (struct sockaddr *) &saddrsizeof (struct sockaddr)) == -1)
    {
      
perror ("connect()");
      
close (sock);
      return -
1;
    }
  return 
sock;
}

int
readline_from_sock 
(int sockchar *lineint max_read)
{
  
int i 0retval 0;
  
bzero (linemax_read);
  
retval recv (socklinemax_readMSG_PEEK);
  while (
line[i] != '\n' && != max_read && != retval)
    ++
i;
  
retval read (sockline, ++i);
  
line[i] = '\0';        /* terminate the string */

// sloppy but to kill it
  
if (strlen (line) == 0)
    {
      
fprintf (stderr"KILLING THIS CONNECTION\n");
      exit (
0);
    }
  return 
retval;

}




int
main 
(int argcchar *argv[])
{
  
int sockcsockl;
  
struct sockaddr_in caddr;



  
fprintf (stderr,
       
"ciscoBNC V%s\nrun with additional arg to make daemon (%s -)\n(chrak@b4b0.org) (http://www.chrakworld.com)\non port %s\n",
       
D_VERargv[0], D_PORT);

  if ((
sock create_server (atoi (D_PORT))) == -1)
    {
// change to stdout so we can see it from PHP!!@!@
      
fprintf (stderr"create_server FAIL\n");
      exit (-
1);
    }
  if (
argc 1)
    
startdaemon ();

// stop zombies
  
signal (SIGCHLDSIG_IGN);

  while (
1)
    {
      
sizeof (struct sockaddr_in);
      if ((
csock accept (sock, (struct sockaddr *) &caddr, &l)) == -1)
    {
      
perror ("accept()");
      exit (-
1);
    }
      
fprintf (stderr"connection from: %s\n"inet_ntoa (caddr.sin_addr));


      switch (
fork ())
    {
    case -
1:
      
perror ("fork()");
      
//write(csock,"fork():ERROR\r\n",strlen("fork():ERROR\r\n"));
      
exit (1);
    case 
0:        /* child */
      
server_notice (csock"connected to ciscoBNC!");
      {
        
serve_client (csock);
      }
      
close (csock);
      exit (
0);
    default:        
/* parent */
      
close (csock);
    }

    }



}




int
create_server 
(unsigned int port)
{
  
int sock1;
  
struct sockaddr_in saddr;

  if ((
sock socket (AF_INETSOCK_STREAM0)) == -1)
    {
      
perror ("socket()");
      return -
1;
    }
  
setsockopt (sockSOL_SOCKETSO_REUSEADDR, &lsizeof (int));

  
saddr.sin_family AF_INET;
  
saddr.sin_port htons (port);
  
saddr.sin_addr.s_addr INADDR_ANY;

  if (
bind (sock, (struct sockaddr *) &saddrsizeof (struct sockaddr)) == -1)
    {
      
perror ("bind()");
      return -
1;
    }
  
/* only 5 connection at a time heh!@ */
  
if (listen (sock5) == -1)
    {
      
perror ("listen()");
      return -
1;
    }
  return 
sock;
}


int
serve_client 
(int sock)
{
  
char buf[1024];
  
char doitup[250];
  
char mbuf[1024];
  
int connected_to_router 0;
  
int connecting_to_irc 0;
  
int sent_pass_once 0;
  
int r_sock;
  
char *routername;
  
char *routerpass;
  
char *ircservname;
  
char *ircport;
  
char myuser[20], mynick[20];


  
srand (time (NULL));        // seed random # generator

  
snprintf (myusersizeof (myuser), "user%d"rnd1toN (99));
  
snprintf (mynicksizeof (mynick), "d0ud%d"rnd1toN (99));


repeatdoitup:
  
routername NULL;
  
routerpass NULL;
  
ircservname NULL;
  
ircport NULL;

  
server_notice (sock"**************TO CONTINUE*******************");
  
server_notice (sock,
         
"HELP ME OUT CLICK ADS AT http://www.chrakworld.com !!");
  
server_notice (sock,
         
"/QUOTE DOITUP router routerpass ircserver ircserverport");
  
server_notice (sock,
         
"EXAMPLE /quote doitup 1.1.1.1 mypass irc.LOL.com 6667");


  while (
1)
    {
      if (
readline_from_sock (sockbufsizeof (buf)) == -1)
    {
      
perror ("readline_from_sock()");    //change.
      
return -1;
    }
      if (!
strncasecmp (buf"DOITUP"strlen ("DOITUP")))
    {
      
char *p;

      
strncpy (doitupbufsizeof (doitup));
      if ((
strtok (doitup" \r\n")))
        {
          while ((
strtok (NULL" \r\n"))
             && (!
routername || !routerpass || !ircservname
             
|| !ircport))
        {
          if (!
routername)
            
routername p;
          else if (!
routerpass)
            
routerpass p;
          else if (!
ircservname)
            
ircservname p;
          else if (!
ircport)
            
ircport p;
        }
          if (!
routername || !routerpass || !ircservname || !ircport)
        
goto repeatdoitup;    // fuck you
          
snprintf (bufsizeof (buf),
            
"OK.. connecting to router %s with pass %s,ircserver %s:%s\n\nQUOTE something else if nothing happens\n",
            
routernamerouterpassircservnameircport);
          
server_notice (sockbuf);
          
goto doitup_done;    // goto
        
}
      else
        {
          
goto repeatdoitup;    //LOL
        
}
    }
    }
doitup_done:

  while (
1)
    {
      if (
readline_from_sock (sockbufsizeof (buf)) == -1)
    {
      
perror ("readline_from_sock()");    //change.
      
return -1;
    }

      if ((
r_sock connect_to_tcphost (routername23NULL)) != -1)
    {
      
connected_to_router 1;
      
snprintf (mbufsizeof (mbuf), "connected to %s"routername);
      
server_notice (sockmbuf);
      while (
1)
        {
          if (
readline_from_sock (r_sockbufsizeof (buf)) == -1)
        {
          
perror ("readline_from_sock()");    //change.
          // do something
        
}
          else
        {
          
//        buf[strlen (buf) - 1] = '\0';
          
if (strstr (buf"assword:"))    // send router passwd
            
{
              if (
sent_pass_once)    // failed already. reprompted
            
{
              
// test this
              
server_notice (sock"ROUTER PASSWORD FAILED!!!");
              return -
1;
            }
              
sent_pass_once 1;
              
server_notice_from (sock"Logging into router...",
                      
"ciscoBNC");
              
write (r_sock"cisco\r\n"strlen ("cisco\r\n"));
            }
          else if (
buf[strlen (buf) - 1] == '>')    // got cmd prompt
            
{
              if (
connecting_to_irc)    // failed. back at prompt.
            
{
              
server_notice (sock"connect irc port FAILED!!");
              return -
1;
            }
              
server_notice_from (sock"trying connect irc server",
                      
routername);

//                    write (r_sock,
//                           "telnet Sterling.VA.US.UnderNet.org 6667\r\n",
//                           strlen
//                           ("telnet Sterling.VA.US.UnderNet.org 6667\r\n"));
              
snprintf (bufsizeof (buf), "connect %s %s\r\n",
                
ircservnameircport);
              
write (r_sockbufstrlen (buf));
              
connecting_to_irc 1;

            }
          else if (
strstr (buf"Open"))    // connection opened!
            
{

              
snprintf (bufsizeof (buf), "USER %s %s %s %s\r\n",
                
myuserrouternameircservnameD_REALNAME);
              
write (r_sockbufstrlen (buf));
              
snprintf (bufsizeof (buf), "NICK %s\r\n"mynick);
              
write (r_sockbufstrlen (buf));

              
relay_client_and_router (sockr_sock);
              return 
0;
            }

        }
        }
    }
      else
    {
      
// fail!
      
return -1;
    }

    }

}


int
server_notice 
(int sockchar *msg)
{
  
char buf[1024];
  
snprintf (bufsizeof (buf), "NOTICE * :%s\r\n"msg);
  return 
write (sockbufstrlen (buf));
}


int
server_notice_from 
(int sockchar *msgchar *from)
{
  
char buf[1024];

  
snprintf (bufsizeof (buf), "%s: %s"frommsg);
  return 
server_notice (sockbuf);
}


// assumes we are connected to irc server from router already.
int
relay_client_and_router 
(int sockint r_sock)
{
  
char buf[1024];
  
char buf1[1024];
  
fd_set rfds;
  
int retval;



  while (
1)
    {
      
FD_ZERO (&rfds);
      
FD_SET (sock, &rfds);
      
FD_SET (r_sock, &rfds);

      
retval select (1023, &rfdsNULLNULL0);
      if (
retval)
    {

      if (
FD_ISSET (sock, &rfds))
        {
          if (
readline_from_sock (sockbufsizeof (buf)) > 0)
        {
          
write (r_sockbufstrlen (buf));
          
strncpy (buf1bufsizeof (buf1));    // save last thing sent. we will need this to stop shell echo from IOS.
        
}        // else..
        
}
      if (
FD_ISSET (r_sock, &rfds))
        {
          if (
readline_from_sock (r_sockbufsizeof (buf)) > 0)
        {
          if (
strcmp (bufbuf1))
            
write (sockbufstrlen (buf));
          else
            {
//                  printf ("IGNORING IOS ECHO\n");
            
}        // else
        
}

        }
    }

    }
}

int
rnd1toN 
(int max)
{
  return (
rand () % max) + 1;
}