// rpc scanner by console
// easily add a new service by adding a id and a name to the rpc_targets struct
// should work on most OS's
// tested on redhat, solaris7, and openbsd


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define pquit(x)        { perror(x); exit(1); }
#define cbuff(x)  { strcpy(x,"");       }

void usage(char *name) {
  fprintf(stderr,"Usage: %s <ipfile> <output>\n",name);
  exit(1); }



struct rpc_targets {
  int id;
  char *name;
 };

 struct rpc_targets targets[] =
{
  {100083, "cmsd"        },
  {100068, "ttdbserverd" },
  {100232, "sadmind"     },
  {100024, "statd"       },
  {300019, "amd"         },
  {0, 0                  }
};

int checkrpc(char *host,FILE *log) {
  struct sockaddr_in rpcaddr;
  struct pmaplist *head;
  struct hostent *he;
  int i;

if ((he=gethostbyname(host)) == NULL) return -1;


 memset(&rpcaddr, 0, sizeof(struct sockaddr_in));
 rpcaddr.sin_family = AF_INET;
 rpcaddr.sin_port   = htons(PMAPPORT);
 memcpy(&rpcaddr.sin_addr.s_addr, he->h_addr_list[0], he->h_length);


  if ((head = pmap_getmaps(&rpcaddr)) == NULL) return -1;


for ( ;head != NULL; head=head->pml_next) {
    for (i=0; targets[i].id; i++) {
         if (head->pml_map.pm_prog==targets[i].id) {
             fprintf(log,"%s is running %s\n",host,targets[i].name);
             fflush(log);
            }
        }
    }
}


int main(int argc, char **argv) {
 char hbuf[1024];
 FILE *input;
 FILE *output;
 pid_t pid;
 int i;

  if (argc < 2) usage(argv[0]);


  if ((input=fopen(argv[1],"r")) == NULL) pquit("error opening input file");
  if ((output=fopen(argv[2],"a")) == NULL) pquit("error opening output file");

  pid = fork();
  if (pid < 0) pquit("fork");
  if (pid > 0) {
         printf("launched in bg with pid %d\n",pid);
         exit(0); }

  while (fgets(hbuf,sizeof(hbuf)-1,input) != NULL) {
     hbuf[strlen(hbuf)-1]=0;
     checkrpc(hbuf,output);
     cbuff(hbuf);
     }
}



