[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.14 and 1.15

version 1.14, 2001/11/01 23:37:42 version 1.15, 2001/11/02 17:16:22
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_prot.h>  #include <rpc/pmap_clnt.h>
 #include <rpc/pmap_rmt.h>  #include <arpa/inet.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 89 
Line 85 
 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, u_long, u_long, struct rpc_msg *,  
     struct rmtcallres *, bool_t (*)());  
 __dead void usage(void);  __dead void usage(void);
   
 int longopt;  int longopt;
 int allopt;  int allopt;
 long termwidth;  long termwidth;
 struct itimerval timeout;  
 extern char *__progname;  extern char *__progname;
   
 struct host_list {  struct host_list {
Line 107 
Line 99 
         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 244 
Line 234 
             len, "", date, idle_time, remote);              len, "", date, idle_time, remote);
 }  }
   
 int  bool_t
 rusers_reply(char *replyp, struct sockaddr_in *raddrp)  rusers_reply(char *replyp, struct sockaddr_in *raddrp)
 {  {
         char user[RNUSERS_MAXUSERLEN + 1];          char user[RNUSERS_MAXUSERLEN + 1];
Line 260 
Line 250 
         if (!allopt && !up->uia_cnt)          if (!allopt && !up->uia_cnt)
                 return(0);                  return(0);
   
         hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,          hp = gethostbyaddr((char *)&raddrp->sin_addr,
             sizeof(struct in_addr), AF_INET);              sizeof(struct in_addr), AF_INET);
         if (hp) {          if (hp) {
                 host = hp->h_name;                  host = hp->h_name;
Line 298 
Line 288 
         return(0);          return(0);
 }  }
   
 int  bool_t
 rusers_reply_3(char *replyp, struct sockaddr_in *raddrp)  rusers_reply_3(char *replyp, struct sockaddr_in *raddrp)
 {  {
         char user[RUSERS_MAXUSERLEN + 1];          char user[RUSERS_MAXUSERLEN + 1];
Line 313 
Line 303 
   
         if (!allopt && !up3->utmp_array_len)          if (!allopt && !up3->utmp_array_len)
                 return(0);                  return(0);
   
         hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,          hp = gethostbyaddr((char *)&raddrp->sin_addr,
             sizeof(struct in_addr), AF_INET);              sizeof(struct in_addr), AF_INET);
         if (hp) {          if (hp) {
                 host = hp->h_name;                  host = hp->h_name;
Line 412 
Line 402 
         clnt_destroy(rusers_clnt);          clnt_destroy(rusers_clnt);
 }  }
   
 enum clnt_stat  
 get_reply(int sock, u_long port, u_long xid, struct rpc_msg *msgp,  
           struct rmtcallres *resp, bool_t (*callback)())  
 {  
         int inlen, 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((u_short)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 *xdrs, 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(xdrs, buf, MAX_BROADCAST_SIZE, XDR_ENCODE);  
         if (!xdr_callmsg(xdrs, msg) || !xdr_rmtcall_args(xdrs, args))  
                 return(RPC_CANTENCODEARGS);  
   
         return(RPC_SUCCESS);  
 }  
   
 void  void
 allhosts(void)  allhosts(void)
 {  {
         enum clnt_stat stat;  
         AUTH *unix_auth = authunix_create_default();  
         int outlen, outlen3;  
         int sock = -1;  
         int sock3 = -1;  
         int i, maxfd, rval;  
         u_long xid, xid3;  
         u_long port, port3;  
         fd_set *fds = NULL;  
         struct sockaddr_in *sin, baddr;  
         struct rmtcallargs args;  
         struct rmtcallres res, res3;  
         struct rpc_msg msg, msg3;  
         struct ifaddrs *ifa, *ifap = NULL;  
         char buf[MAX_BROADCAST_SIZE], buf3[MAX_BROADCAST_SIZE];  
         utmpidlearr up;          utmpidlearr up;
         utmp_array up3;          utmp_array up3;
         XDR xdr;          enum clnt_stat clnt_stat;
   
         if (getifaddrs(&ifap) != 0) {          puts("Sending broadcast for rusersd protocol version 3...");
                 perror("Cannot get list of interface addresses");          memset(&up3, 0, sizeof(up3));
                 stat = RPC_CANTSEND;          clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_3,
                 goto cleanup;              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));
   
         args.prog = RUSERSPROG;          puts("Sending broadcast for rusersd protocol version 2...");
         args.vers = RUSERSVERS_IDLE;          memset(&up, 0, sizeof(up));
         args.proc = RUSERSPROC_NAMES;          clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE,
         args.xdr_args = xdr_void;              RUSERSPROC_NAMES, xdr_void, NULL, xdr_utmpidlearr,
         args.args_ptr = NULL;              (char *)&up, rusers_reply);
           if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
         stat = rpc_setup(&sock, &xdr, &msg, &args, unix_auth, buf);                  errx(1, "%s", clnt_sperrno(clnt_stat));
         if (stat != RPC_SUCCESS)  
                 goto cleanup;  
         xid = msg.rm_xid;  
         outlen = (int)xdr_getpos(&xdr);  
         xdr_destroy(&xdr);  
   
         args.vers = RUSERSVERS_3;  
         stat = rpc_setup(&sock3, &xdr, &msg3, &args, unix_auth, buf3);  
         if (stat != RPC_SUCCESS)  
                 goto cleanup;  
         xid3 = msg3.rm_xid;  
         outlen3 = (int)xdr_getpos(&xdr);  
         xdr_destroy(&xdr);  
   
         maxfd = sock3 + 1;  
         fds = (fd_set *)calloc(howmany(maxfd, NFDBITS), sizeof(fd_mask));  
         if (fds == NULL) {  
                 stat = RPC_CANTSEND;  
                 goto cleanup;  
         }  
   
         memset(&baddr, 0, sizeof(baddr));  
         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);  
   
         memset(&res, 0, sizeof(res));  
         res.port_ptr = &port;  
         res.xdr_results = xdr_utmpidlearr;  
         res.results_ptr = (caddr_t)&up;  
   
         memset(&res3, 0, sizeof(res3));  
         res3.port_ptr = &port3;  
         res3.xdr_results = xdr_utmp_array;  
         res3.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, buf, outlen, 0,  
                                     (struct sockaddr *)&baddr,  
                                     sizeof(struct sockaddr)) != outlen) {  
                                         warn("unable to send broadcast packet");  
                                         stat = RPC_CANTSEND;  
                                         goto cleanup;  
                                 }  
                         } else {  
                                 if (sendto(sock3, buf3, outlen3, 0,  
                                     (struct sockaddr *)&baddr,  
                                     sizeof(struct sockaddr)) != outlen3) {  
                                         warn("unable to send broadcast packet");  
                                         stat = RPC_CANTSEND;  
                                         goto cleanup;  
                                 }  
                         }  
                 }  
   
                 /*  
                  * 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;  
                 while (timerisset(&timeout.it_value)) {  
                         FD_SET(sock, fds);  
                         FD_SET(sock3, fds);  
                         setitimer(ITIMER_REAL, &timeout, NULL);  
                         rval = select(maxfd, fds, NULL, NULL, NULL);  
                         setitimer(ITIMER_REAL, NULL, &timeout);  
                         if (rval == -1) {  
                                 if (!timerisset(&timeout.it_value))  
                                         break;  
                                 warn("select");         /* shouldn't happen */  
                                 stat = RPC_CANTRECV;  
                                 goto cleanup;  
                         }  
                         if (FD_ISSET(sock3, fds)) {  
                                 stat = get_reply(sock3, port3, xid3, &msg3,  
                                     &res3, rusers_reply_3);  
                                 if (stat != RPC_SUCCESS)  
                                         goto cleanup;  
                         }  
                         if (FD_ISSET(sock, fds)) {  
                                 stat = get_reply(sock, port, xid, &msg,  
                                     &res, rusers_reply);  
                                 if (stat != RPC_SUCCESS)  
                                         goto cleanup;  
                         }  
                 }  
         }  
 cleanup:  
         if (ifap != NULL)  
                 freeifaddrs(ifap);  
         if (fds != NULL)  
                 free(fds);  
         if (sock >= 0)  
                 (void)close(sock);  
         if (sock3 >= 0)  
                 (void)close(sock3);  
         AUTH_DESTROY(unix_auth);  
 }  
   
 void  
 alarmclock(int signo)  
 {  
   
         timerclear(&timeout.it_value);  
 }  }
   
 void  void

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