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 *);
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], '/');
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;
* 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);