[BACK]Return to rusers.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rusers

Diff for /src/usr.bin/rusers/rusers.c between version 1.15 and 1.16

version 1.15, 2001/11/02 17:16:22 version 1.16, 2001/11/06 02:22:25
Line 62 
Line 62 
 #include <sys/ioctl.h>  #include <sys/ioctl.h>
 #include <sys/socket.h>  #include <sys/socket.h>
 #include <rpc/rpc.h>  #include <rpc/rpc.h>
 #include <rpc/pmap_clnt.h>  #include <rpc/pmap_prot.h>
 #include <arpa/inet.h>  #include <rpc/pmap_rmt.h>
 #include <rpcsvc/rusers.h>  #include <rpcsvc/rusers.h>
 #include <rpcsvc/rnusers.h>     /* Old protocol version */  #include <rpcsvc/rnusers.h>     /* Old protocol version */
   #include <arpa/inet.h>
   #include <net/if.h>
 #include <err.h>  #include <err.h>
   #include <errno.h>
   #include <ifaddrs.h>
 #include <netdb.h>  #include <netdb.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
Line 85 
Line 89 
 void print_longline(int, u_int, char *, char *, char *, char *, int);  void print_longline(int, u_int, char *, char *, char *, char *, int);
 void onehost(char *);  void onehost(char *);
 void allhosts(void);  void allhosts(void);
   void alarmclock(int);
 bool_t rusers_reply(char *, struct sockaddr_in *);  bool_t rusers_reply(char *, struct sockaddr_in *);
 bool_t rusers_reply_3(char *, struct sockaddr_in *);  bool_t rusers_reply_3(char *, struct sockaddr_in *);
   enum clnt_stat get_reply(int, in_port_t, u_long, struct rpc_msg *,
       struct rmtcallres *, bool_t (*)());
 __dead void usage(void);  __dead void usage(void);
   
 int longopt;  int longopt;
Line 99 
Line 106 
         struct in_addr addr;          struct in_addr addr;
 } *hosts;  } *hosts;
   
   #define MAX_BROADCAST_SIZE 1400
   
 int  int
 main(int argc, char **argv)  main(int argc, char **argv)
 {  {
Line 303 
Line 312 
   
         if (!allopt && !up3->utmp_array_len)          if (!allopt && !up3->utmp_array_len)
                 return(0);                  return(0);
   
         hp = gethostbyaddr((char *)&raddrp->sin_addr,          hp = gethostbyaddr((char *)&raddrp->sin_addr,
             sizeof(struct in_addr), AF_INET);              sizeof(struct in_addr), AF_INET);
         if (hp) {          if (hp) {
Line 348 
Line 357 
         utmpidlearr up;          utmpidlearr up;
         utmp_array up3;          utmp_array up3;
         CLIENT *rusers_clnt;          CLIENT *rusers_clnt;
         struct sockaddr_in addr;          struct sockaddr_in sin;
         struct hostent *hp;          struct hostent *hp;
         struct timeval tv = { 25, 0 };          struct timeval tv = { 25, 0 };
         int error;          int error;
Line 369 
Line 378 
             xdr_utmp_array, &up3, tv);              xdr_utmp_array, &up3, tv);
         switch (error) {          switch (error) {
         case RPC_SUCCESS:          case RPC_SUCCESS:
                 addr.sin_addr.s_addr = *(int *)hp->h_addr;                  sin.sin_addr.s_addr = *(int *)hp->h_addr;
                 rusers_reply_3((char *)&up3, &addr);                  rusers_reply_3((char *)&up3, &sin);
                 clnt_destroy(rusers_clnt);                  clnt_destroy(rusers_clnt);
                 return;                  return;
         case RPC_PROGVERSMISMATCH:          case RPC_PROGVERSMISMATCH:
Line 397 
Line 406 
                 clnt_destroy(rusers_clnt);                  clnt_destroy(rusers_clnt);
                 exit(1);                  exit(1);
         }          }
         addr.sin_addr.s_addr = *(int *)hp->h_addr;          sin.sin_addr.s_addr = *(int *)hp->h_addr;
         rusers_reply((char *)&up, &addr);          rusers_reply((char *)&up, &sin);
         clnt_destroy(rusers_clnt);          clnt_destroy(rusers_clnt);
 }  }
   
   enum clnt_stat
   get_reply(int sock, in_port_t port, u_long xid, struct rpc_msg *msgp,
             struct rmtcallres *resp, bool_t (*callback)())
   {
           ssize_t inlen;
           socklen_t fromlen;
           struct sockaddr_in raddr;
           char inbuf[UDPMSGSIZE];
           XDR xdr;
   
   retry:
           msgp->acpted_rply.ar_verf = _null_auth;
           msgp->acpted_rply.ar_results.where = (caddr_t)resp;
           msgp->acpted_rply.ar_results.proc = xdr_rmtcallres;
   
           fromlen = sizeof(struct sockaddr);
           inlen = recvfrom(sock, inbuf, sizeof(inbuf), 0,
               (struct sockaddr *)&raddr, &fromlen);
           if (inlen < 0) {
                   if (errno == EINTR)
                           goto retry;
                   return (RPC_CANTRECV);
           }
           if (inlen < sizeof(u_int32_t))
                   goto retry;
   
           /*
            * If the reply we got matches our request, decode the
            * replay and pass it to the callback function.
            */
           xdrmem_create(&xdr, inbuf, (u_int)inlen, XDR_DECODE);
           if (xdr_replymsg(&xdr, msgp)) {
                   if ((msgp->rm_xid == xid) &&
                       (msgp->rm_reply.rp_stat == MSG_ACCEPTED) &&
                       (msgp->acpted_rply.ar_stat == SUCCESS)) {
                           raddr.sin_port = htons(port);
                           (void)(*callback)(resp->results_ptr, &raddr);
                   }
           }
           xdr.x_op = XDR_FREE;
           msgp->acpted_rply.ar_results.proc = xdr_void;
           (void)xdr_replymsg(&xdr, msgp);
           (void)(*resp->xdr_results)(&xdr, resp->results_ptr);
           xdr_destroy(&xdr);
   
           return(RPC_SUCCESS);
   }
   
   enum clnt_stat
   rpc_setup(int *fdp, XDR *xdr, struct rpc_msg *msg, struct rmtcallargs *args,
             AUTH *unix_auth, char *buf)
   {
           int on = 1;
   
           if ((*fdp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
                   return(RPC_CANTSEND);
   
           if (setsockopt(*fdp, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
                   return(RPC_CANTSEND);
   
           msg->rm_xid = arc4random();
           msg->rm_direction = CALL;
           msg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
           msg->rm_call.cb_prog = PMAPPROG;
           msg->rm_call.cb_vers = PMAPVERS;
           msg->rm_call.cb_proc = PMAPPROC_CALLIT;
           msg->rm_call.cb_cred = unix_auth->ah_cred;
           msg->rm_call.cb_verf = unix_auth->ah_verf;
   
           xdrmem_create(xdr, buf, MAX_BROADCAST_SIZE, XDR_ENCODE);
           if (!xdr_callmsg(xdr, msg) || !xdr_rmtcall_args(xdr, args))
                   return(RPC_CANTENCODEARGS);
   
           return(RPC_SUCCESS);
   }
   
 void  void
 allhosts(void)  allhosts(void)
 {  {
           enum clnt_stat stat;
           struct itimerval timeout;
           AUTH *unix_auth = authunix_create_default();
           size_t outlen[2];
           int sock[2] = { -1, -1 };
           int i, maxfd, rval;
           u_long xid[2], port[2];
           fd_set *fds = NULL;
           struct sockaddr_in *sin, baddr;
           struct rmtcallargs args;
           struct rmtcallres res[2];
           struct rpc_msg msg[2];
           struct ifaddrs *ifa, *ifap = NULL;
           char buf[2][MAX_BROADCAST_SIZE];
         utmpidlearr up;          utmpidlearr up;
         utmp_array up3;          utmp_array up3;
         enum clnt_stat clnt_stat;          XDR xdr;
   
         puts("Sending broadcast for rusersd protocol version 3...");          if (getifaddrs(&ifap) != 0)
         memset(&up3, 0, sizeof(up3));                  err(1, "can't get list of interface addresses");
         clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_3,  
             RUSERSPROC_NAMES, xdr_void, NULL, xdr_utmp_array,  
             (char *)&up3, rusers_reply_3);  
         if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)  
                 errx(1, "%s", clnt_sperrno(clnt_stat));  
   
         puts("Sending broadcast for rusersd protocol version 2...");  
         memset(&up, 0, sizeof(up));          memset(&up, 0, sizeof(up));
         clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE,          memset(&up3, 0, sizeof(up3));
             RUSERSPROC_NAMES, xdr_void, NULL, xdr_utmpidlearr,          memset(&baddr, 0, sizeof(baddr));
             (char *)&up, rusers_reply);          memset(&res, 0, sizeof(res));
         if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)          memset(&msg, 0, sizeof(msg));
                 errx(1, "%s", clnt_sperrno(clnt_stat));  
           args.prog = RUSERSPROG;
           args.vers = RUSERSVERS_IDLE;
           args.proc = RUSERSPROC_NAMES;
           args.xdr_args = xdr_void;
           args.args_ptr = NULL;
   
           stat = rpc_setup(&sock[0], &xdr, &msg[0], &args, unix_auth, buf[0]);
           if (stat != RPC_SUCCESS)
                   goto cleanup;
           xid[0] = msg[0].rm_xid;
           outlen[0] = xdr_getpos(&xdr);
           xdr_destroy(&xdr);
   
           args.vers = RUSERSVERS_3;
           stat = rpc_setup(&sock[1], &xdr, &msg[1], &args, unix_auth, buf[1]);
           if (stat != RPC_SUCCESS)
                   goto cleanup;
           xid[1] = msg[1].rm_xid;
           outlen[1] = xdr_getpos(&xdr);
           xdr_destroy(&xdr);
   
           maxfd = MAX(sock[0], sock[1]) + 1;
           fds = (fd_set *)calloc(howmany(maxfd, NFDBITS), sizeof(fd_mask));
           if (fds == NULL)
                   err(1, NULL);
   
           baddr.sin_len = sizeof(struct sockaddr_in);
           baddr.sin_family = AF_INET;
           baddr.sin_port = htons(PMAPPORT);
           baddr.sin_addr.s_addr = htonl(INADDR_ANY);
   
           res[0].port_ptr = &port[0];
           res[0].xdr_results = xdr_utmpidlearr;
           res[0].results_ptr = (caddr_t)&up;
   
           res[1].port_ptr = &port[1];
           res[1].xdr_results = xdr_utmp_array;
           res[1].results_ptr = (caddr_t)&up3;
   
           (void)signal(SIGALRM, alarmclock);
   
           /*
            * We do 6 runs through the loop.  On even runs we send
            * a version 3 broadcast.  On odd ones we send a version 2
            * broadcast.  This should give version 3 replies enough
            * of an 'edge' over the old version 2 ones in most cases.
            * We select() waiting for replies for 5 seconds in between
            * each broadcast.
            */
           for (i = 0; i < 6; i++) {
                   for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
                           if (ifa->ifa_addr->sa_family != AF_INET ||
                               !(ifa->ifa_flags & IFF_BROADCAST) ||
                               !(ifa->ifa_flags & IFF_UP) ||
                               ifa->ifa_broadaddr == NULL ||
                               ifa->ifa_broadaddr->sa_family != AF_INET)
                                   continue;
                           sin = (struct sockaddr_in *)ifa->ifa_broadaddr;
                           baddr.sin_addr = sin->sin_addr;
   
                           /* use protocol 2 or 3 depending on i (odd or even) */
                           if (i & 1) {
                                   if (sendto(sock[0], buf[0], outlen[0], 0,
                                       (struct sockaddr *)&baddr,
                                       sizeof(struct sockaddr)) != outlen[0])
                                           err(1, "can't send broadcast packet");
                           } else {
                                   if (sendto(sock[1], buf[1], outlen[1], 0,
                                       (struct sockaddr *)&baddr,
                                       sizeof(struct sockaddr)) != outlen[1])
                                           err(1, "can't send broadcast packet");
                           }
                   }
   
                   /*
                    * We stay in the select loop for ~5 seconds
                    */
                   timerclear(&timeout.it_value);
                   timeout.it_value.tv_sec = 5;
                   timeout.it_value.tv_usec = 0;
                   for (;;) {
                           FD_SET(sock[0], fds);
                           FD_SET(sock[1], fds);
                           setitimer(ITIMER_REAL, &timeout, NULL);
                           rval = select(maxfd, fds, NULL, NULL, NULL);
                           setitimer(ITIMER_REAL, NULL, &timeout);
                           if (rval == -1) {
                                   if (errno == EINTR)
                                           break;
                                   err(1, "select");       /* shouldn't happen */
                           }
                           if (FD_ISSET(sock[1], fds)) {
                                   stat = get_reply(sock[1], (in_port_t)port[1],
                                       xid[1], &msg[1], &res[1], rusers_reply_3);
                                   if (stat != RPC_SUCCESS)
                                           goto cleanup;
                           }
                           if (FD_ISSET(sock[0], fds)) {
                                   stat = get_reply(sock[0], (in_port_t)port[0],
                                       xid[0], &msg[0], &res[0], rusers_reply);
                                   if (stat != RPC_SUCCESS)
                                           goto cleanup;
                           }
                   }
           }
   cleanup:
           if (ifap != NULL)
                   freeifaddrs(ifap);
           if (fds != NULL)
                   free(fds);
           if (sock[0] >= 0)
                   (void)close(sock[0]);
           if (sock[1] >= 0)
                   (void)close(sock[1]);
           AUTH_DESTROY(unix_auth);
           if (stat != RPC_SUCCESS) {
                   clnt_perrno(stat);
                   exit(1);
           }
   }
   
   void
   alarmclock(int signo)
   {
   
           ;               /* just interupt */
 }  }
   
 void  void

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.16