home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / nmap254b.zip / nmap_rpc.c < prev    next >
C/C++ Source or Header  |  2001-07-30  |  22KB  |  592 lines

  1.  
  2. /***********************************************************************/
  3. /* rpc.c -- Functions related to the RPCGrind (-sR) facility of Nmap.  */
  4. /* This includes reading the nmap-rpc services file and sending rpc    */
  5. /* queries and interpreting responses.  The actual scan engine used    */
  6. /* for rpc grinding is pos_scan (which is not in this file)            */
  7. /*                                                                     */
  8. /***********************************************************************/
  9. /*  The Nmap Security Scanner is (C) 1995-2001 Insecure.Com LLC. This  */
  10. /*  program is free software; you can redistribute it and/or modify    */
  11. /*  it under the terms of the GNU General Public License as published  */
  12. /*  by the Free Software Foundation; Version 2.  This guarantees your  */
  13. /*  right to use, modify, and redistribute this software under certain */
  14. /*  conditions.  If this license is unacceptable to you, we may be     */
  15. /*  willing to sell alternative licenses (contact sales@insecure.com). */
  16. /*                                                                     */
  17. /*  If you received these files with a written license agreement       */
  18. /*  stating terms other than the (GPL) terms above, then that          */
  19. /*  alternative license agreement takes precendence over this comment. */
  20. /*                                                                     */
  21. /*  Source is provided to this software because we believe users have  */
  22. /*  a right to know exactly what a program is going to do before they  */
  23. /*  run it.  This also allows you to audit the software for security   */
  24. /*  holes (none have been found so far).                               */
  25. /*                                                                     */
  26. /*  Source code also allows you to port Nmap to new platforms, fix     */
  27. /*  bugs, and add new features.  You are highly encouraged to send     */
  28. /*  your changes to fyodor@insecure.org for possible incorporation     */
  29. /*  into the main distribution.  By sending these changes to Fyodor or */
  30. /*  one the insecure.org development mailing lists, it is assumed that */
  31. /*  you are offering Fyodor the unlimited, non-exclusive right to      */
  32. /*  reuse, modify, and relicense the code.  This is important because  */
  33. /*  the inability to relicense code has caused devastating problems    */
  34. /*  for other Free Software projects (such as KDE and NASM).  Nmap     */
  35. /*  will always be available Open Source.  If you wish to specify      */
  36. /*  special license conditions of your contributions, just say so      */
  37. /*  when you send them.                                                */
  38. /*                                                                     */
  39. /*  This program is distributed in the hope that it will be useful,    */
  40. /*  but WITHOUT ANY WARRANTY; without even the implied warranty of     */
  41. /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  */
  42. /*  General Public License for more details (                          */
  43. /*  http://www.gnu.org/copyleft/gpl.html ).                            */
  44. /*                                                                     */
  45. /***********************************************************************/
  46.  
  47. /* $Id: nmap_rpc.c,v 1.3 2001/07/30 06:08:00 fyodor Exp $ */
  48.  
  49.  
  50. #include "nmap_rpc.h"
  51.  
  52. extern struct ops o;
  53. static int services_initialized = 0;
  54. static struct rpc_info ri;
  55. static int udp_rpc_socket = -1;
  56. static int tcp_rpc_socket = -1;
  57. static unsigned long rpc_xid_base = (unsigned long) -1;
  58.                        /* The XID we send in queries is 
  59.                        this random base number + the 
  60.                        RPC prog number we are scanning
  61.                        for */
  62. static size_t tcp_readlen=0; /* used in get_rpc_results but can be reset in 
  63.                 send_rpc_query */
  64.  
  65. static void rpc_services_init() {
  66.   char filename[512];
  67.   FILE *fp;
  68.   char *tmpptr, *p;
  69.   char line[1024];
  70.   int lineno = 0;
  71.  
  72.   services_initialized = 1;
  73.   ri.num_alloc = 256;
  74.   ri.num_used = 0;
  75.   ri.names = (char **) cp_alloc(ri.num_alloc * sizeof(char *));
  76.   ri.numbers = (unsigned long *) cp_alloc(ri.num_alloc * sizeof(unsigned long));
  77.  
  78.   if (nmap_fetchfile(filename, sizeof(filename), "nmap-rpc") == -1) {
  79.     error("Unable to find nmap-rpc!  Resorting to /etc/rpc");
  80.     strcpy(filename, "/etc/rpc");
  81.   }
  82.  
  83.   fp = fopen(filename, "r");
  84.   if (!fp) {
  85.     fatal("Unable to open %s for reading rpc information", filename);
  86.   }
  87.  
  88.   while(fgets(line, sizeof(line), fp)) {
  89.     lineno++;
  90.     p = line;
  91.  
  92.     if (ri.num_used == ri.num_alloc) {
  93.       tmpptr = (char *) cp_alloc(ri.num_alloc * 3 * sizeof(char *));
  94.       memcpy(tmpptr, ri.names, ri.num_alloc * sizeof(char *));
  95.       ri.names = (char **) tmpptr;
  96.       tmpptr = (char *) cp_alloc(ri.num_alloc * 3 * sizeof(unsigned long));
  97.       memcpy(tmpptr, ri.numbers, ri.num_alloc * sizeof(char *));
  98.       ri.numbers = (unsigned long *) tmpptr;
  99.       ri.num_alloc *= 3;
  100.     }
  101.  
  102.     while(*p && *p != '#' && !isalnum((int) *p)) p++;
  103.  
  104.     if (!*p || *p == '#') continue;
  105.  
  106.     tmpptr = strpbrk(p, " \t");
  107.     if (!tmpptr) 
  108.       continue;
  109.     *tmpptr = '\0';
  110.     
  111.     ri.names[ri.num_used] = cp_strdup(p);
  112.     p = tmpptr + 1;
  113.  
  114.     while(*p && !isdigit((int) *p)) p++;
  115.  
  116.     if (!*p)
  117.       continue;
  118.  
  119.     ri.numbers[ri.num_used] = strtoul(p, NULL, 10);
  120.     ri.num_used++;
  121.   }
  122.   fclose(fp);
  123.   return;
  124. }
  125.  
  126. char *nmap_getrpcnamebynum(unsigned long num) {
  127.   int i;
  128.  
  129.   if (!services_initialized) {
  130.     rpc_services_init();
  131.   }
  132.  
  133.   for(i=0; i < ri.num_used; i++) {
  134.     if (ri.numbers[i] == num)
  135.       return ri.names[i];
  136.   }
  137.   return NULL;
  138. }
  139.  
  140. int get_rpc_procs(unsigned long **programs, unsigned long *num_programs) {
  141.   if (!services_initialized) {
  142.     rpc_services_init();
  143.   }
  144.   
  145.   *programs = ri.numbers;
  146.   *num_programs = ri.num_used;
  147.   if (ri.num_used == 0) fatal("Unable to find any valid rpc procedures in your rpc file!  RPC scanning won't work for you");
  148.   return 0;
  149. }
  150.  
  151. /* Send an RPC query to the specified host/port on the specified protocol
  152.    looking for the specified RPC program.  We cache our sending sockets
  153.    to avoid recreating and (with TCP) reconnect() ing them each time */
  154. int send_rpc_query(struct in_addr *target_host, unsigned short portno,
  155.            int ipproto, unsigned long program, int scan_offset, 
  156.            int trynum) {
  157.   static struct in_addr last_target_host;
  158.   static int last_ipproto = -1;
  159.   static unsigned short last_portno = 0; 
  160.   struct sockaddr_in sock;
  161.   char rpch_buf[256]; 
  162.   struct rpc_hdr *rpch;
  163.   int res;
  164.  
  165.   /* static int numruns = 0;
  166.      if (numruns++ > 2)
  167.      fatal("Done");  */
  168.  
  169.   rpch = (struct rpc_hdr *) ((char *)rpch_buf + sizeof(unsigned long));
  170.   bzero(rpch, sizeof(struct rpc_hdr));
  171.  
  172.  
  173.   while(rpc_xid_base == (unsigned long) -1)
  174.     rpc_xid_base = (unsigned long) get_random_uint();
  175.   
  176.   if (o.debugging > 1) {
  177.     printf("Sending RPC probe for program %li to %hu/%s -- scan_offset=%d trynum=%d xid=%lX\n", program, portno, (ipproto == IPPROTO_TCP)? "tcp" : "udp", scan_offset, trynum, rpc_xid_base + ((portno & 0x3FFF) << 16) + (trynum << 30) +  scan_offset);
  178.   }
  179.  
  180.   /* First we check whether we have to create a new connection -- we 
  181.      need to if we have a new target_host, or a new portno, or the socket
  182.      we want to use is -1 */
  183.   if (ipproto == IPPROTO_TCP && 
  184.       (last_target_host.s_addr != target_host->s_addr ||
  185.        last_portno != portno || last_ipproto != IPPROTO_TCP)) {
  186.     /* New host or port -- kill our old tcp socket */
  187.     if (tcp_rpc_socket != -1) {
  188.       close(tcp_rpc_socket);
  189.       tcp_rpc_socket = -1;
  190.       tcp_readlen = 0;
  191.     }
  192.   }
  193.   last_ipproto = ipproto;
  194.   last_target_host.s_addr = target_host->s_addr;
  195.   last_portno = portno;
  196.   
  197.   bzero(&sock, sizeof(&sock));
  198.   sock.sin_family = AF_INET;
  199.   sock.sin_addr.s_addr = target_host->s_addr;
  200.   sock.sin_port = htons(portno);
  201.     
  202.   if (ipproto == IPPROTO_TCP && tcp_rpc_socket == -1) {
  203.     if ((tcp_rpc_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
  204.       pfatal("Socket troubles in send_rpc_query");
  205.     /* I should unblock the socket here and timeout the connect() */
  206.     res = connect(tcp_rpc_socket, (struct sockaddr *) &sock, 
  207.           sizeof(struct sockaddr_in));
  208.     if (res == -1) {
  209.       if (o.debugging) {
  210.     gh_perror("Failed to connect to port %d of %s in send_rpc_query",
  211.           portno, inet_ntoa(*target_host));
  212.       }
  213.       close(tcp_rpc_socket);
  214.       tcp_rpc_socket = -1;
  215.       return -1;
  216.     }
  217.     unblock_socket(tcp_rpc_socket);
  218.   } else if (ipproto == IPPROTO_UDP && udp_rpc_socket == -1) {
  219.     if ((udp_rpc_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
  220.       pfatal("UDP socket troubles in send_rpc_query");
  221.     unblock_socket(udp_rpc_socket);
  222.   }
  223.   
  224.   /* OK, now that we have our sockets together, we form and send a
  225.      query ... */
  226.   rpch->type_msg = htonl(RPC_MSG_CALL); /* rpc request                 */
  227.   rpch->version_rpc=htonl(2);           /* portmapper v.2 (hmm, and v3&&4?) */
  228.   /*rpch->prog_proc=0;*/                    /* proc_null() rpc function     */
  229.   /*rpch->authcred_flavor=0;*/              /* AUTH_NULL for credentials    */
  230.   /*rpch->authcred_length=0;*/              /* length of credentials is zero*/
  231.   /*rpch->authveri_flavor=0;*/              /* no verifiers field          */
  232.   /*rpch->authveri_length=0;*/              /* zero length verifier field  */
  233.   
  234.   /* Bits are TTPPPPPPPPPPPPPP BBBBBBBBBBBBBBBB */
  235.   /* Where T are trynum bits, P is the lowest 14 bits of the port number,
  236.      and B is the scan[] offset */
  237.   rpch->xid = htonl(rpc_xid_base + ((portno & 0x3FFF) << 16) + 
  238.             (trynum << 30) +  scan_offset); 
  239.   rpch->prog_id = htonl(program);
  240.   rpch->prog_ver = htonl(31337 + (rpc_xid_base & 0xFFFFF));
  241.   
  242.   if (ipproto == IPPROTO_UDP) {
  243.     /* Simply send this sucker we have created ... */
  244.     do {  
  245.       if (o.debugging > 1)
  246.     hdump((unsigned char *) rpch, sizeof(struct rpc_hdr));
  247.       res = sendto(udp_rpc_socket, (char *)rpch, sizeof(struct rpc_hdr), 0,
  248.            (struct sockaddr *) &sock, sizeof(struct sockaddr_in));
  249.     } while(res == -1 && (errno == EINTR || errno == ENOBUFS));
  250.     if (res == -1) {
  251.       if (o.debugging) {
  252.     gh_perror("Sendto in send_rpc_query");
  253.     close(udp_rpc_socket);
  254.     udp_rpc_socket = -1;
  255.       }
  256.       return -1;
  257.     }
  258.   } else {
  259.     /* TCP socket */
  260.     /* 0x80000000 means only 1 record marking */
  261.     *(unsigned long *)rpch_buf = htonl(sizeof(struct rpc_hdr) | 0x80000000);
  262.     res = Write(tcp_rpc_socket, rpch_buf, sizeof(struct rpc_hdr) + sizeof(unsigned long));
  263.     if (res == -1) {
  264.       if (o.debugging) {
  265.     gh_perror("Write in send_rpc_query");
  266.       }
  267.       close(tcp_rpc_socket);
  268.       tcp_rpc_socket = -1;
  269.       return -1;
  270.     }
  271.   }
  272.   return 0;
  273. }
  274.  
  275. int rpc_are_we_done(char *msg, int msg_len, struct hoststruct *target, 
  276.             struct portinfo *scan, struct scanstats *ss, 
  277.             struct portinfolist *pil, struct rpcscaninfo *rsi) {
  278.  
  279.   struct rpc_hdr_rcv *rpc_pack;
  280.   unsigned long scan_offset;
  281.   int trynum;
  282.   struct portinfo *current;
  283.  
  284.   rpc_pack = (struct rpc_hdr_rcv *) msg;     
  285.   if (msg_len < 24 || msg_len > 32 || (msg_len < 32 && rpc_pack->accept_stat == PROG_MISMATCH)) {
  286.     /* This is not a valid reply -- we kill the port 
  287.        (from an RPC perspective) */ 
  288.     if (o.debugging > 1) {
  289.       printf("Port %hu/%s labelled NON_RPC because of invalid sized message (%d)\n", rsi->rpc_current_port->portno, (rsi->rpc_current_port->proto == IPPROTO_TCP)? "TPC" : "UDP", msg_len);
  290.     }
  291.     rsi->rpc_status = RPC_STATUS_NOT_RPC;
  292.     ss->numqueries_outstanding = 0;
  293.     return 1;
  294.   }
  295.  
  296.   /* Now it is time to decode the scan offset */
  297.   scan_offset = ntohl(rpc_pack->xid);
  298.   scan_offset -= rpc_xid_base;
  299.   if (((scan_offset >> 16) & 0x3FFF) != (unsigned long) (rsi->rpc_current_port->portno & 0x3FFF)) {
  300.     /* Doh -- this doesn't seem right */
  301.     if (o.debugging > 1) {
  302.       printf("Port %hu/%s labelled NON_RPC because ((scan_offset >> 16) & 0x3FFF) is %li\n", rsi->rpc_current_port->portno, (rsi->rpc_current_port->proto == IPPROTO_TCP)? "TPC" : "UDP", ((scan_offset >> 16) & 0x3FFF));
  303.     }
  304.     rsi->rpc_status = RPC_STATUS_NOT_RPC;
  305.     ss->numqueries_outstanding = 0;
  306.     return 1;
  307.   }
  308.   trynum = scan_offset >> 30;
  309.   scan_offset &= 0xFFFF;
  310.   if (scan_offset >= rsi->rpc_number) {
  311.     error("Invalid scan_offset returned in RPC packet");
  312.     rsi->rpc_status = RPC_STATUS_NOT_RPC;
  313.     ss->numqueries_outstanding = 0;
  314.     return 1;
  315.   }
  316.   if (ntohl(rpc_pack->type_msg) != RPC_MSG_REPLY) {
  317.     error("Strange -- RPC type is %d shoulb be RPC_MSG_REPLY (1)", ntohl(rpc_pack->type_msg));
  318.     return 0;
  319.   }
  320.   if (ntohl(rpc_pack->auth_flavor) != 0 /* AUTH_NULL */ ||
  321.       ntohl(rpc_pack->opaque_length != 0)) {
  322.     error("Strange -- auth flavor/opaque_length are %d/%d should generally be 0/0", rpc_pack->auth_flavor, rpc_pack->opaque_length);
  323.     rsi->rpc_status = RPC_STATUS_NOT_RPC;
  324.     ss->numqueries_outstanding = 0;
  325.     return 1;
  326.   }
  327.  
  328.   /* OK, now that we know what this is a response to, we delete the
  329.       appropriate entry from our scanlist */
  330.   current = &scan[scan_offset];
  331.     
  332.    
  333.   if (current->state != PORT_TESTING && current->state != PORT_CLOSED &&
  334.       current->state != PORT_FIREWALLED) {
  335.     error("Supposed scan_offset refers to port in state %s (should be testing,closed, or firewalld)", statenum2str(current->state));
  336.     rsi->rpc_status = RPC_STATUS_NOT_RPC;
  337.     ss->numqueries_outstanding = 0;
  338.     return 1;
  339.   }
  340.      
  341.   if (trynum > current->trynum) {
  342.     error("Bogus trynum %d when we are only up to %d in get_rpc_results", trynum, current->trynum);
  343.     rsi->rpc_status = RPC_STATUS_NOT_RPC;
  344.     ss->numqueries_outstanding = 0;
  345.     return 1;
  346.   }
  347.  
  348.   if (current->next > -1) scan[current->next].prev = current->prev;
  349.   if (current->prev > -1) scan[current->prev].next = current->next;
  350.   if (current == pil->testinglist)
  351.     pil->testinglist = (current->next >= 0)?  &scan[current->next] : NULL;
  352.   current->next = -1;
  353.   current->prev = -1;
  354.      
  355.      /* Adjust timeouts ... */
  356.   adjust_timeouts(current->sent[trynum], &(target->to));
  357.      
  358.   /* If a non-zero trynum finds a port that hasn't been discovered, the
  359.     earlier packets(s) were probably dropped.  So we decrease our 
  360.     numqueries_ideal, otherwise we increase it slightly */
  361.   if (trynum == 0) {
  362.     ss->numqueries_ideal = MIN(ss->numqueries_ideal + (ss->packet_incr/ss->numqueries_ideal), ss->max_width);
  363.   } else  {
  364.     if (!ss->alreadydecreasedqueries) {
  365.       ss->alreadydecreasedqueries = 1;
  366.       ss->numqueries_ideal *= ss->fallback_percent;
  367.       if (ss->numqueries_ideal < 1.0) ss->numqueries_ideal = 1.0;
  368.       if (o.debugging) 
  369.     { 
  370.       log_write(LOG_STDOUT, "Lost a packet, decreasing window to %d\n", (int) ss->numqueries_ideal);
  371.     }
  372.     }
  373.   }
  374.  
  375.   if (current->state == PORT_TESTING)
  376.     ss->numqueries_outstanding--;
  377.      
  378.   if (ntohl(rpc_pack->accept_stat) == PROG_UNAVAIL) {
  379.     current->state = PORT_CLOSED;
  380.     if (o.debugging > 1) {
  381.       error("Port %hu/%s claims that it is not RPC service %li", rsi->rpc_current_port->portno, (rsi->rpc_current_port->proto == IPPROTO_TCP)? "TCP" : "UDP",  current->portno);
  382.     }
  383.     rsi->valid_responses_this_port++;
  384.     return 0;
  385.   } else if (ntohl(rpc_pack->accept_stat) == PROG_MISMATCH) {
  386.     if (o.debugging > 1) {
  387.       error("Port %hu/%s claims IT IS RPC service %li", rsi->rpc_current_port->portno, (rsi->rpc_current_port->proto == IPPROTO_TCP)? "TCP" : "UDP",  current->portno);
  388.     }
  389.     current->state = PORT_OPEN;
  390.     rsi->rpc_status = RPC_STATUS_GOOD_PROG;
  391.     rsi->rpc_program = current->portno;
  392.     rsi->rpc_lowver = ntohl(rpc_pack->low_version);
  393.     rsi->rpc_highver = ntohl(rpc_pack->high_version);
  394.     rsi->valid_responses_this_port++;
  395.     ss->numqueries_outstanding = 0;
  396.     return 1;
  397.   } else if (ntohl(rpc_pack->accept_stat) == SUCCESS) {
  398.     error("Umm -- RPC returned success for bogus version -- thats OK I guess");
  399.     rsi->rpc_status = RPC_STATUS_GOOD_PROG;
  400.     rsi->rpc_program = current->portno;
  401.     rsi->rpc_lowver = rsi->rpc_highver = 0;
  402.     rsi->valid_responses_this_port++;
  403.     ss->numqueries_outstanding = 0;
  404.     return 1;
  405.   } else {
  406.     fatal("Illegal rpc accept_stat");
  407.   }
  408.   return 0;
  409. }
  410.  
  411. void get_rpc_results(struct hoststruct *target, struct portinfo *scan,
  412.              struct scanstats *ss, struct portinfolist *pil, 
  413.              struct rpcscaninfo *rsi) {
  414.  
  415. int max_sd = -1;
  416. fd_set fds_r; 
  417. int sres;
  418. struct timeval tv;
  419. int res;
  420. static char readbuf[512];
  421. struct sockaddr_in from;
  422. NET_SIZE_T fromlen = sizeof(struct sockaddr_in);
  423. char *current_msg;
  424. unsigned long current_msg_len;
  425.  
  426.  if ((udp_rpc_socket == -1 && tcp_rpc_socket == -1) || ss->numqueries_outstanding <= 0)
  427.    return;
  428.  
  429.  FD_ZERO(&fds_r);
  430.  
  431.  if (udp_rpc_socket >= 0 && rsi->rpc_current_port->proto == IPPROTO_UDP) {
  432.    FD_SET(udp_rpc_socket, &fds_r);
  433.    max_sd = udp_rpc_socket;
  434.  }
  435.  else if (tcp_rpc_socket >= 0 && rsi->rpc_current_port->proto == IPPROTO_TCP) {
  436.    FD_SET(tcp_rpc_socket, &fds_r);
  437.    if (tcp_rpc_socket > max_sd)
  438.      max_sd = tcp_rpc_socket;
  439.  } else {
  440.    error("Unable to find listening socket in get_rpc_results");
  441.    return;
  442.  }
  443.  
  444.  
  445.  while (ss->numqueries_outstanding > 0) {
  446.  
  447.    
  448.    /* Insure there is no timeout ... */
  449.    if (o.host_timeout) {    
  450.      gettimeofday(&tv, NULL);
  451.      if (TIMEVAL_MSEC_SUBTRACT(tv, target->host_timeout) >= 0) {
  452.        target->timedout = 1;
  453.        return;
  454.      }
  455.    }
  456.  
  457.    tv.tv_sec = target->to.timeout / 1000000;
  458.    tv.tv_usec = target->to.timeout % 1000000;
  459.    sres = select(max_sd + 1, &fds_r, NULL, NULL, &tv);
  460.    if (!sres)
  461.      break;
  462.    if (sres == -1 && errno == EINTR)
  463.      continue;
  464.    if (udp_rpc_socket >= 0 && FD_ISSET(udp_rpc_socket, &fds_r)) {
  465.      res = recvfrom(udp_rpc_socket, readbuf, sizeof(readbuf), 0, (struct sockaddr *) &from, &fromlen);
  466.    
  467.      if (res < 0) {
  468.        /* Doh! */
  469.        if (o.debugging || o.verbose)
  470.      gh_perror("recvfrom in get_rpc_results");
  471.        ss->numqueries_outstanding = 0;
  472.        rsi->rpc_status = RPC_STATUS_NOT_RPC;
  473.        return;
  474.      }
  475.      if (o.debugging > 1)
  476.        printf("Received %d byte UDP packet\n", res);
  477.      /* Now we check that the response is from the expected host/port */
  478.      if (from.sin_addr.s_addr != target->host.s_addr ||
  479.      from.sin_port != htons(rsi->rpc_current_port->portno)) {
  480.        if (o.debugging > 1) {
  481.      printf("Received UDP packet from %d.%d.%d.%d/%hu when expecting packet from %d.%d.%d.%d/%hu\n", NIPQUAD(from.sin_addr.s_addr), ntohs(from.sin_port), NIPQUAD(target->host.s_addr), rsi->rpc_current_port->portno);
  482.        }
  483.        continue;
  484.      }
  485.  
  486.      if (rpc_are_we_done(readbuf, res, target, scan, ss, pil, rsi) != 0) {
  487.        return;
  488.      }
  489.    } else if (tcp_rpc_socket >= 0 && FD_ISSET(tcp_rpc_socket, &fds_r)) {
  490.      do {     
  491.        res = read(tcp_rpc_socket, readbuf + tcp_readlen, sizeof(readbuf) - tcp_readlen);
  492.      } while(res == -1 && errno == EINTR);
  493.      if (res <= 0) {
  494.        if (o.debugging) {
  495.      if (res == -1)
  496.        gh_perror("Failed to read() from tcp rpc socket in get_rpc_results");
  497.      else {
  498.        error("Lamer on port %li closed RPC socket on me in get_rpc_results", rsi->rpc_current_port->portno);
  499.      }
  500.        }
  501.        ss->numqueries_outstanding = 0;
  502.        rsi->rpc_status = RPC_STATUS_NOT_RPC;
  503.        return;
  504.      }
  505.  
  506.      tcp_readlen += res;
  507.  
  508.      if (tcp_readlen < 28) {
  509.        /* This is suspiciously small -- I'm assuming this is not the first
  510.       part of a valid RPC packet */
  511.        if (o.debugging > 1) {
  512.      printf("Port %hu/%s labelled NON_RPC because tcp_readlen is %d (should be at least 28)\n", rsi->rpc_current_port->portno, (rsi->rpc_current_port->proto == IPPROTO_TCP)? "TCP" : "UDP", tcp_readlen);
  513.        }
  514.        ss->numqueries_outstanding = 0;
  515.        rsi->rpc_status = RPC_STATUS_NOT_RPC;
  516.        return;
  517.      }
  518.      /* I'm ignoring the multiple msg fragment possibility for now */
  519.      current_msg_len = ntohl((*(unsigned long *)readbuf)) & 0x7FFFFFFF;
  520.                              
  521.      if (current_msg_len > tcp_readlen - 4) {
  522.        if (o.debugging > 1) {
  523.      printf("Port %hu/%s labelled NON_RPC because current_msg_len is %li while tcp_readlen is %d\n", rsi->rpc_current_port->portno, (rsi->rpc_current_port->proto == IPPROTO_TCP)? "TCP" : "UDP", current_msg_len, tcp_readlen);
  524.        }
  525.        ss->numqueries_outstanding = 0;
  526.        rsi->rpc_status = RPC_STATUS_NOT_RPC;
  527.        return;
  528.      }
  529.      current_msg = readbuf + 4;
  530.  
  531.      do {
  532.        if (rpc_are_we_done(current_msg, current_msg_len, target, scan, ss, 
  533.                pil, rsi) != 0) 
  534.      return;
  535.  
  536.        current_msg += current_msg_len;
  537.        if ((current_msg - readbuf) + 4UL < tcp_readlen) {       
  538.      current_msg_len = ntohl(*(unsigned long *) current_msg) & 0x7FFFFFFF;
  539.      current_msg += 4;
  540.        } else {
  541.      if ((unsigned long) (current_msg - readbuf) < tcp_readlen) {
  542.        tcp_readlen -= current_msg - readbuf;
  543.        memmove(readbuf, current_msg, tcp_readlen);
  544.      } else tcp_readlen = 0;
  545.      break;       
  546.        }
  547.  
  548.        if (current_msg_len < 24 || current_msg_len > 32) {
  549.      ss->numqueries_outstanding = 0;
  550.      if (o.debugging > 1) {
  551.        printf("Port %hu/%s labelled NON_RPC because current_msg_len is %li\n", rsi->rpc_current_port->portno, (rsi->rpc_current_port->proto == IPPROTO_TCP)? "TCP" : "UDP", current_msg_len);
  552.      }
  553.      rsi->rpc_status = RPC_STATUS_NOT_RPC;
  554.      return;
  555.        }
  556.  
  557.        if ((current_msg - readbuf) + current_msg_len > tcp_readlen) {
  558.      tcp_readlen -= current_msg - readbuf;
  559.      memmove(readbuf +4 , current_msg, tcp_readlen);
  560.      *(unsigned long *)&readbuf = htonl(current_msg_len);
  561.      tcp_readlen += 4;
  562.      break;
  563.        }
  564.      } while(1);
  565.    }
  566.  }
  567.  return;
  568. }
  569.  
  570.  
  571. void close_rpc_query_sockets() {
  572.   if (udp_rpc_socket != -1) {
  573.     close(udp_rpc_socket);
  574.     udp_rpc_socket = -1;
  575.   }
  576.  
  577.   if (tcp_rpc_socket != -1) {
  578.     close(tcp_rpc_socket);
  579.     tcp_rpc_socket = -1;
  580.   }
  581. }
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.