sm-notify: factor socket creation out of notify()
authorChuck Lever <chuck.lever@oracle.com>
Thu, 14 Jan 2010 17:22:26 +0000 (12:22 -0500)
committerSteve Dickson <steved@redhat.com>
Fri, 15 Jan 2010 19:55:51 +0000 (14:55 -0500)
The top half of the notify() function creates the main socket that
sm-notify uses to do its job.  To make adding IPv6 support simpler,
refactor that piece into a separate function.

The logic is modified slightly so that exit(3) is invoked only in
main().  This is not required, but it makes the code slightly easier
to understand and maintain.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
utils/statd/sm-notify.c

index e49c722..462ba79 100644 (file)
@@ -55,7 +55,7 @@ static unsigned int   opt_max_retry = 15 * 60;
 static char *          opt_srcaddr = 0;
 static uint16_t                opt_srcport = 0;
 
-static void            notify(void);
+static void            notify(const int sock);
 static int             notify_host(int, struct nsm_host *);
 static void            recv_reply(int);
 static void            insert_host(struct nsm_host *);
@@ -141,11 +141,76 @@ smn_get_host(const char *hostname,
        return 1;
 }
 
+/*
+ * Prepare a socket for sending RPC requests
+ *
+ * Returns a bound datagram socket file descriptor, or -1 if
+ * an error occurs.
+ */
+static int
+smn_create_socket(const char *srcaddr, const uint16_t srcport)
+{
+       struct sockaddr_storage address;
+       struct sockaddr *local_addr = (struct sockaddr *)&address;
+       int sock, retry_cnt = 0;
+
+retry:
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sock < 0) {
+               xlog(L_ERROR, "Failed to create RPC socket: %m");
+               return -1;
+       }
+       fcntl(sock, F_SETFL, O_NONBLOCK);
+
+       memset(&address, 0, sizeof(address));
+       local_addr->sa_family = AF_INET;        /* Default to IPv4 */
+
+       /* Bind source IP if provided on command line */
+       if (srcaddr) {
+               struct addrinfo *ai = smn_lookup(srcaddr);
+               if (!ai) {
+                       xlog(L_ERROR,
+                               "Not a valid hostname or address: \"%s\"",
+                               srcaddr);
+                       (void)close(sock);
+                       return -1;
+               }
+
+               /* We know it's IPv4 at this point */
+               memcpy(local_addr, ai->ai_addr, ai->ai_addrlen);
+
+               freeaddrinfo(ai);
+       }
+
+       /* Use source port if provided on the command line,
+        * otherwise use bindresvport */
+       if (srcport) {
+               nfs_set_port(local_addr, srcport);
+               if (bind(sock, local_addr, sizeof(struct sockaddr_in)) < 0) {
+                       xlog(L_ERROR, "Failed to bind RPC socket: %m");
+                       (void)close(sock);
+                       return -1;
+               }
+       } else {
+               struct servent *se;
+               struct sockaddr_in *sin = (struct sockaddr_in *)local_addr;
+               (void) bindresvport(sock, sin);
+               /* try to avoid known ports */
+               se = getservbyport(sin->sin_port, "udp");
+               if (se && retry_cnt < 100) {
+                       retry_cnt++;
+                       close(sock);
+                       goto retry;
+               }
+       }
+
+       return sock;
+}
+
 int
 main(int argc, char **argv)
 {
-       int     c;
-       int     force = 0;
+       int     c, sock, force = 0;
        char *  progname;
 
        progname = strrchr(argv[0], '/');
@@ -242,7 +307,14 @@ usage:             fprintf(stderr,
                close(2);
        }
 
-       notify();
+       sock = smn_create_socket(opt_srcaddr, opt_srcport);
+       if (sock == -1)
+               exit(1);
+
+       if (!nsm_drop_privileges(-1))
+               exit(1);
+
+       notify(sock);
 
        if (hosts) {
                struct nsm_host *hp;
@@ -262,68 +334,13 @@ usage:            fprintf(stderr,
  * Notify hosts
  */
 static void
-notify(void)
+notify(const int sock)
 {
-       struct sockaddr_storage address;
-       struct sockaddr *local_addr = (struct sockaddr *)&address;
        time_t  failtime = 0;
-       int     sock = -1;
-       int retry_cnt = 0;
-
- retry:
-       sock = socket(AF_INET, SOCK_DGRAM, 0);
-       if (sock < 0) {
-               xlog(L_ERROR, "Failed to create RPC socket: %m");
-               exit(1);
-       }
-       fcntl(sock, F_SETFL, O_NONBLOCK);
-
-       memset(&address, 0, sizeof(address));
-       local_addr->sa_family = AF_INET;        /* Default to IPv4 */
-
-       /* Bind source IP if provided on command line */
-       if (opt_srcaddr) {
-               struct addrinfo *ai = smn_lookup(opt_srcaddr);
-               if (!ai) {
-                       xlog(L_ERROR,
-                               "Not a valid hostname or address: \"%s\"",
-                               opt_srcaddr);
-                       exit(1);
-               }
-
-               /* We know it's IPv4 at this point */
-               memcpy(local_addr, ai->ai_addr, ai->ai_addrlen);
-
-               freeaddrinfo(ai);
-       }
-
-       /* Use source port if provided on the command line,
-        * otherwise use bindresvport */
-       if (opt_srcport) {
-               nfs_set_port(local_addr, opt_srcport);
-               if (bind(sock, local_addr, sizeof(struct sockaddr_in)) < 0) {
-                       xlog(L_ERROR, "Failed to bind RPC socket: %m");
-                       exit(1);
-               }
-       } else {
-               struct servent *se;
-               struct sockaddr_in *sin = (struct sockaddr_in *)local_addr;
-               (void) bindresvport(sock, sin);
-               /* try to avoid known ports */
-               se = getservbyport(sin->sin_port, "udp");
-               if (se && retry_cnt < 100) {
-                       retry_cnt++;
-                       close(sock);
-                       goto retry;
-               }
-       }
 
        if (opt_max_retry)
                failtime = time(NULL) + opt_max_retry;
 
-       if (!nsm_drop_privileges(-1))
-               exit(1);
-
        while (hosts) {
                struct pollfd   pfd;
                time_t          now = time(NULL);