/*
 * lssocks.c
 * ~~~~~~~~~
 */

#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>

char *buf;

typedef struct ip {
 int a;
 int b;
 int c;
 int d;
} _ip;

typedef struct ips {
 int nr;
 char *src;
 char *src_port;
 char *dst;
 char *dst_port;
 char *inode;
 _ip dsrc;
 _ip ddst;
 int dsrc_port;
 int ddst_port;
 int pid;
} _list;

_list *list=NULL;
int elements=0;
int eroare=0;

_ip convert_ip ();
int convert_port ();
char *clearbuf ();
char *clearbuf3 ();
char *clearbuf3_dst ();
char *readlink_malloc ();
void read_proc ();

main (int argc, char **argv) {
 FILE *f=fopen("/proc/net/tcp","r");
 char ch;
 int n=0,n2=0,i,j;

 printf("
++ lssocks - list open ports and running processes
   ~~~~~~~
");

 printf("\n++ params:"); fflush(stdout);
 if (argc == 1) 
 {
   printf(" <none>"); fflush(stdout);
 }
 else for (i=1; i<argc; i++)
        printf(" %s",argv[i]), fflush(stdout);
 printf("\n\n");
 
 if ((argc != 2) || ( (strcmp(argv[1],"1") != 0)
 	 && (strcmp(argv[1],"2") != 0)))
 {
   printf("++ usage: %s 1 \t- to print all active connections and open ports\n",argv[0]);
   printf("          %s 2 \t- to print all running processes\n\n",argv[0]);
   exit(1);
 }
 
 buf=malloc(100);
 list=(_list*)malloc(sizeof(_list)+sizeof(_ip));

 if (f == NULL) {
  printf("couldn't open /proc/net/tcp\n");
  exit(1);
 }

 printf("file /proc/net/tcp opened ... reading connection table\n");
 sleep(1);
 bzero(buf,100);
 n=0;

 while ( ch != '\n' )
 {
   ch=getc(f);
 }
 
 while ( ch != EOF )
 {
   ch=getc(f);
   if ( ch == '\n' )
   {
     n=0;
     n2=0;
     elements++;
     list=(_list*)realloc(list,(sizeof(_list)+sizeof(_ip))*(elements+1));
   }
   else if (ch != EOF && ch !=':') { buf[n2]=ch; n2++; }

   if ( ch == ':' )
   {
     n++;
     buf[n2]='\0';

     if (n == 1)
     {
      list[elements].nr=atoi(clearbuf(n2));
     }
     if (n == 2)
     {
       list[elements].src=malloc(16);
       list[elements].src=clearbuf(n2);
       list[elements].dsrc=convert_ip(list[elements].src);
     }
     if (n == 3)
     {
       list[elements].src_port = malloc(5);
       list[elements].src_port = clearbuf3(n2);
       list[elements].dsrc_port = convert_port(list[elements].src_port);
       list[elements].dst = malloc(16);
       list[elements].dst = clearbuf3_dst(n2);
       list[elements].ddst = convert_ip(list[elements].dst);
     }
     if (n == 4)
     {
       list[elements].dst_port = malloc(5);
       list[elements].dst_port = clearbuf3(n2);
       list[elements].ddst_port = convert_port(list[elements].dst_port);
     }
     if (n == 5)
     {
       for (j=1; j<34; j++) ch=getc(f);
       list[elements].inode = malloc(10);
       j=0;
       while (1)
       {
         ch=getc(f);
         if ( (ch >='0' && ch <='9') || (ch >='A' && ch <='F')
                 || (ch >='a' && ch <='f'))
         {
         list[elements].inode[j] = ch;
         j++;
         } else break;
       }
       list[elements].inode[j]='\0';
     }
     
     n2=0;
   }
 }

 printf("reading proc "); fflush(stdout);
 if (strcmp(argv[1],"1") == 0) read_proc(1);
 else if (strcmp(argv[1],"2") == 0) read_proc(2);
 
 if (strcmp(argv[1],"1") == 0 )
 {
 printf("\n");
 printf("   no local_ip:local_port\n");
 printf("--------------------------------------------\n");
 for (i=0;i<elements;i++)
 if (list[i].ddst.a == 0)
   printf("%5d %d.%d.%d.%d:%d (LISTEN) -> %d \n",
   list[i].nr, list[i].dsrc.a, list[i].dsrc.b, list[i].dsrc.c,
   list[i].dsrc.d, list[i].dsrc_port,
   list[i].pid);
 else
   printf("%5d %d.%d.%d.%d port %d  to  %d.%d.%d.%d port %d -> %d\n",
   list[i].nr, list[i].dsrc.a, list[i].dsrc.b, list[i].dsrc.c,
   list[i].dsrc.d, list[i].dsrc_port, list[i].ddst.a, list[i].ddst.b,
   list[i].ddst.c, list[i].ddst.d, list[i].ddst_port,
   list[i].pid);
 }
 for (i=0;i<elements;i++)
 {
  free(list[i].src);
  free(list[i].src_port);
  free(list[i].dst);
  free(list[i].dst_port);
  free(list[i].inode);
 }

 printf("Everything done.\n");
 fclose(f);
}


char *clearbuf(int n)
{
  int i,j=0;
  char ch;
  char *clearedbuf=malloc(100);
  
  bzero(clearedbuf,100);

  for (i=0; i<n; i++)
  {
    ch = buf[i];
    if ( (ch >='0' && ch <='9') || (ch >='A' && ch <='F')
   	|| (ch >='a' && ch <='f'))
    {
      clearedbuf[j] = buf[i];
      j++;
    }
  }
  clearedbuf[j] = '\0';
  return clearedbuf;
}

char *clearbuf3(int n)
{
  int i,j=0;
  char ch;
  char *clearedbuf=malloc(100);
  
  bzero(clearedbuf,100);
  for (i=0; i<n; i++)
  {
    ch = buf[i];
    if ( (ch >='0' && ch <='9') || (ch >='A' && ch <='F')
   	|| (ch >='a' && ch <='f'))
    {
      clearedbuf[j] = buf[i];
      j++;
    }
    else break;
  }
  clearedbuf[j] = '\0';
  return clearedbuf;
}

char *clearbuf3_dst(int n)
{
  int i,j=0,true=0;
  char ch;
  char *clearedbuf=malloc(100);
  
  bzero(clearedbuf,100);
  for (i=0; i<n; i++)
  {
    ch = buf[i];
    if (true == 1) {
    if ( (ch >='0' && ch <='9') || (ch >='A' && ch <='F')
   	|| (ch >='a' && ch <='f'))
    {
      clearedbuf[j] = buf[i];
      j++;
    } else break;
    }
    if (ch == ' ') true = 1;
  }
  clearedbuf[j] = '\0';
  return clearedbuf;
}

_ip convert_ip (char *cp)
{
  char *converted=malloc(100);
  char *tmp=malloc(20);
  _ip pip;
  
  bzero(converted,100);
  bzero(tmp,20);
  pip.a=0; pip.b=0; pip.c=0; pip.d=0;

    converted[0]=cp[6]; converted[1]=cp[7];
    converted[2]=cp[4]; converted[3]=cp[5];
    converted[4]=cp[2]; converted[5]=cp[3];
    converted[6]=cp[0]; converted[7]=cp[1];
    converted[8]='\0';
    tmp[0]=converted[0]; tmp[1]=converted[1]; tmp[2]='\0';
    pip.a=strtol(tmp, NULL, 16);    
    tmp[0]=converted[2]; tmp[1]=converted[3]; tmp[2]='\0';
    pip.b=strtol(tmp, NULL, 16);
    tmp[0]=converted[4]; tmp[1]=converted[5]; tmp[2]='\0';
    pip.c=strtol(tmp, NULL, 16);
    tmp[0]=converted[6]; tmp[1]=converted[7]; tmp[2]='\0';
    pip.d=strtol(tmp, NULL, 16);
  return pip;
}

int convert_port (char *cp)
{
  return strtol(cp, NULL, 16);
}

char *readlink_malloc (char *filename)
{
  int size = 100;

  while (1)
    {
      char *buffer = (char *) malloc (size);
      int nchars = readlink (filename, buffer, size);
      if (nchars == -1) return NULL;
      if (nchars < size)
        return buffer;
      free (buffer);
      size *= 2;
    }
}


void read_proc(int tip)
{
#include <pwd.h>
#include <sys/types.h>

  int i,j,n,k,count,statusok;
  char *sockfile, *buffer, *buf2, *p, *exefile;
  struct stat sb;
  struct passwd *userinfo;
  FILE *fisier;
  
  sockfile=malloc(50);
  exefile=malloc(100);
  if (tip == 1)
  {  
  for (i=0; i<65535; i++)
  {
    sprintf(sockfile,"/proc/%d",i);
    if (stat(sockfile, &sb) != -1)
    {
      count=0;
      printf("."); fflush(stdout);
      for (j=0; j<65535; j++)
      {
	sprintf(sockfile,"/proc/%d/fd/%d",i,j);
	if (stat(sockfile, &sb) == -1) count++;
	else if (S_ISSOCK(sb.st_mode) != NULL)
	{
	  buffer=readlink_malloc(sockfile);
	  printf(","); fflush(stdout);
	  n=0;
  	  buf2 = malloc(sizeof(buffer)+1);
  
	  for (k=0; k<strlen(buffer); k++)
	    if (buffer[k] >= '0' && buffer[k] <= '9')
	    {
	      buf2[n]=buffer[k];
	      n++;
	    }
	  buf2[n]='\0';
	  for (k=0; k<elements; k++)
	  {
	    if (strcmp(buf2,list[k].inode) == 0)
	    {
	      (void *)list[k].pid=malloc(30);
	      list[k].pid=i;
	    }
	  }
	}
	if (count > 20) break;
      }
    }
  }
  }
  
  if (tip == 2)
  {
    count=0;
    n=0;
    buffer=malloc(41);
    printf("\nuser \t\tpid \tcommand\n");
    printf("-------------------------------------------\n");
    for (i=0; i<65535; i++)
    {
      sprintf(sockfile,"/proc/%d",i);
      if (stat(sockfile, &sb) != -1)
      {
        count++;
	bzero(buffer,41);
        sprintf(sockfile,"/proc/%d/cmdline", i);
        if ((fisier = fopen(sockfile,"r")) != NULL)
        {
          fgets(buffer, 40, fisier);

          if ( strlen(buffer) == 0)
          {
            fclose(fisier);
            sprintf(sockfile,"/proc/%d/status", i);
            if ((fisier = fopen(sockfile,"r")) != NULL)
            {
              fgets(buffer, 40, fisier);
              if (strlen(buffer) != 0)
              {
              	statusok=-1;
                buf2=malloc(21);
/*                for (j=0; j<strlen(buffer); j++)
                if (buffer[j] == ' ') break;
                while (buffer[j] == ' ') j++;
                n=0;
                for (; j<strlen(buffer); j++)
                {
                  buf2[n] = buffer[j];
                  n++;
                }
                buf2[n]='\0';
*/
		n=0;
		for (j=6; j<strlen(buffer); j++)
		buf2[n]=buffer[j], n++;
		buf2[n]='\0';
              }
              strcpy(buffer,buf2);
              free(buf2);
            }
          }

          if (p = strchr( buffer, '\n' )) { * p = 0; }
          userinfo = getpwuid(sb.st_uid);
          if ( userinfo != NULL )
/*
           if ( n == 0 )
             printf("%s \t%d \t<none>\n", userinfo->pw_name, i);
           else
*/
	if (statusok == -1) printf("%s \t\t%d \t[%s]\n", userinfo->pw_name, i, buffer);
	else printf("%s \t\t%d \t%s\n", userinfo->pw_name, i, buffer);
	statusok=0;
          fclose(fisier);
        }
      }
    }
  }
}
