Blob Blame History Raw
diff -up ypserv-2.19/ypserv/ypserv.8.in.iface ypserv-2.19/ypserv/ypserv.8.in
--- ypserv-2.19/ypserv/ypserv.8.in.iface	2003-01-17 22:57:35.000000000 +0100
+++ ypserv-2.19/ypserv/ypserv.8.in	2008-09-25 13:09:39.000000000 +0200
@@ -12,6 +12,9 @@ ypserv \- NIS server
 [
 .B \-p port
 ]
+[
+.B \-i iface
+]
 .LP
 .SH DESCRIPTION
 .IX  "ypserv"  ""  "\fLypserv\fP \(em NIS server process"
@@ -59,12 +62,23 @@ Causes the server to run in debugging mo
 reports only errors (access violations, dbm failures)
 using the syslog(3) facility. In debug mode, the server does not
 background itself and prints extra status messages to stderr for
-each request that it revceives.
+each request that it receives.
 .B path
 is an optionally parameter.
 .B ypserv
 is using this directory instead of @YPMAPDIR@
 .TP
+.B "\-i" "--iface" "iface"
+Causes the server to only be available via interface 
+.B iface
+Use this if you want ypserv to only provide service on a
+particular network interface.
+.B iface
+is a required parameter
+.B ypserv
+will be using that interface instead of all the available
+network interfaces.
+.TP
 .B "\-p" "--port"  port
 .B ypserv
 will bind itself to this port.
diff -up ypserv-2.19/ypserv/ypserv.c.iface ypserv-2.19/ypserv/ypserv.c
--- ypserv-2.19/ypserv/ypserv.c.iface	2006-01-10 20:22:20.000000000 +0100
+++ ypserv-2.19/ypserv/ypserv.c	2008-09-25 13:09:39.000000000 +0200
@@ -33,11 +33,15 @@
 #include <getopt.h>
 #endif
 #include <sys/file.h>
+#include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_clnt.h>
+#include <linux/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #if defined(HAVE_RPC_SVC_SOC_H)
 #include <rpc/svc_soc.h> /* for svcudp_create() */
 #endif /* HAVE_RPC_SVC_SOC_H */
@@ -63,6 +67,8 @@
 #define YPOLDVERS 1
 #endif
 
+struct in_addr my_iface_num = {INADDR_ANY};
+
 static char *path_ypdb = YPMAPDIR;
 
 static void
@@ -95,7 +101,25 @@ ypprog_2 (struct svc_req *rqstp, registe
   bool_t retval;
   xdrproc_t _xdr_argument, _xdr_result;
   bool_t (*local) (char *, void *, struct svc_req *);
+  struct sockaddr_in *rqhost;
+  struct in_addr rqnetwork;
 
+  if (my_iface_num.s_addr != INADDR_ANY) {
+  	/*
+	 * If we are suppost only listen on one interface
+	 * make this request comes from that inteface
+	 * otherwise ignore it.
+	 */
+	rqhost = svc_getcaller (rqstp->rq_xprt);
+	rqnetwork.s_addr = inet_netof(rqhost->sin_addr);
+  	if (rqnetwork.s_addr != inet_netof(my_iface_num)) {
+      if (debug_flag) {
+		log_msg("Ignoring request from %s: wrong network\n",
+			inet_ntoa(rqhost->sin_addr));
+	  }
+	  return;
+  	}
+  }
   switch (rqstp->rq_proc)
     {
     case YPPROC_NULL:
@@ -245,6 +269,36 @@ mysvc_run (void)
 }
 #endif
 
+static void
+get_inet_for_iface (char *iface, uint32_t *iface_num)
+{
+  struct ifreq ifr;
+  struct in_addr inaddr;
+  int fd;
+
+  *iface_num = INADDR_ANY;
+
+  fd = socket (AF_INET, SOCK_DGRAM, 0);
+  if(fd < 0)
+    return;
+
+  memset(&ifr, '\0', sizeof(ifr));
+  strncpy (ifr.ifr_name, iface,
+      IFNAMSIZ > strlen (iface) ? strlen (iface) : IFNAMSIZ);
+
+  if (ioctl (fd, SIOCGIFADDR, &ifr) < 0)
+    {
+	  log_msg("ifr_name error: %d\n", errno);
+      close (fd);
+      return;
+    }
+  memcpy(&inaddr, &ifr.ifr_netmask.sa_data[2], sizeof(struct in_addr));
+  *iface_num = inaddr.s_addr;
+
+  close (fd);
+}
+
+
 /* Create a pidfile on startup */
 static void
 create_pidfile (void)
@@ -394,7 +448,7 @@ sig_child (int sig UNUSED)
 static void
 Usage (int exitcode)
 {
-  fputs ("usage: ypserv [-d [path]] [-p port]\n", stderr);
+  fputs ("usage: ypserv [-d [path]] [-p port] [-i interface]\n", stderr);
   fputs ("       ypserv --version\n", stderr);
 
   exit (exitcode);
@@ -405,6 +459,7 @@ main (int argc, char **argv)
 {
   SVCXPRT *transp;
   int my_port = -1, my_socket, result;
+  char *my_iface = NULL;
   struct sockaddr_in s_in;
 
   openlog ("ypserv", LOG_PID, LOG_DAEMON);
@@ -417,12 +472,13 @@ main (int argc, char **argv)
 	{"version", no_argument, NULL, 'v'},
 	{"debug", no_argument, NULL, 'd'},
 	{"port", required_argument, NULL, 'p'},
+	{"iface", required_argument, NULL, 'i'},
 	{"usage", no_argument, NULL, 'u'},
 	{"help", no_argument, NULL, 'h'},
 	{NULL, 0, NULL, '\0'}
       };
 
-      c = getopt_long (argc, argv, "vdp:buh", long_options, &option_index);
+      c = getopt_long (argc, argv, "vdp:i:buh", long_options, &option_index);
       if (c == -1)
 	break;
       switch (c)
@@ -439,6 +495,11 @@ main (int argc, char **argv)
 	  if (debug_flag)
 	    log_msg ("Using port %d\n", my_port);
 	  break;
+	case 'i':
+	  my_iface = optarg;
+	  if (debug_flag)
+            log_msg ("Using interface %s\n", my_iface);
+	  break;
 	case 'u':
 	case 'h':
 	  Usage (0);
@@ -545,6 +606,11 @@ main (int argc, char **argv)
   pmap_unset (YPPROG, YPVERS);
   pmap_unset (YPPROG, YPOLDVERS);
 
+  if (my_iface)
+    {
+      get_inet_for_iface (my_iface, &my_iface_num.s_addr);
+    }
+
   if (my_port >= 0)
     {
       my_socket = socket (AF_INET, SOCK_DGRAM, 0);
@@ -556,7 +622,7 @@ main (int argc, char **argv)
 
       memset ((char *) &s_in, 0, sizeof (s_in));
       s_in.sin_family = AF_INET;
-      s_in.sin_addr.s_addr = htonl (INADDR_ANY);
+      s_in.sin_addr.s_addr = htonl (my_iface_num.s_addr);
       s_in.sin_port = htons (my_port);
 
       result = bind (my_socket, (struct sockaddr *) &s_in,
@@ -601,7 +667,7 @@ main (int argc, char **argv)
 
       memset (&s_in, 0, sizeof (s_in));
       s_in.sin_family = AF_INET;
-      s_in.sin_addr.s_addr = htonl (INADDR_ANY);
+      s_in.sin_addr.s_addr = htonl (my_iface_num.s_addr);
       s_in.sin_port = htons (my_port);
 
       result = bind (my_socket, (struct sockaddr *) &s_in,
diff -up /dev/null ypserv-2.19/ypserv/ypserv.c.iface_binding
--- /dev/null	2008-09-23 12:26:29.886003537 +0200
+++ ypserv-2.19/ypserv/ypserv.c.iface_binding	2008-09-25 13:09:39.000000000 +0200
@@ -0,0 +1,635 @@
+/* Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Thorsten Kukuk
+   Author: Thorsten Kukuk <kukuk@suse.de>
+
+   The YP Server is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   version 2 as published by the Free Software Foundation.
+
+   The YP Server is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with the YP Server; see the file COPYING. If
+   not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+   Cambridge, MA 02139, USA. */
+
+#define _GNU_SOURCE
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <signal.h>
+#include <getopt.h>
+#include <poll.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+
+#include "yp.h"
+#include "access.h"
+#include "log_msg.h"
+#include "ypserv_conf.h"
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifndef _PATH_VARRUN
+#define _PATH_VARRUN "/etc/"
+#endif
+#define _YPSERV_PIDFILE _PATH_VARRUN"ypserv.pid"
+
+#ifndef YPOLDVERS
+#define YPOLDVERS 1
+#endif
+
+volatile int children = 0;
+int forked = 0;
+
+static char *path_ypdb = YPMAPDIR;
+
+static void
+ypprog_2 (struct svc_req *rqstp, register SVCXPRT * transp)
+{
+  union {
+    domainname ypproc_domain_2_arg;
+    domainname ypproc_domain_nonack_2_arg;
+    ypreq_key ypproc_match_2_arg;
+    ypreq_nokey ypproc_first_2_arg;
+    ypreq_key ypproc_next_2_arg;
+    ypreq_xfr ypproc_xfr_2_arg;
+    ypreq_nokey ypproc_all_2_arg;
+    ypreq_nokey ypproc_master_2_arg;
+    ypreq_nokey ypproc_order_2_arg;
+    domainname ypproc_maplist_2_arg;
+  } argument;
+  union {
+    bool_t ypproc_domain_2_res;
+    bool_t ypproc_domain_nonack_2_res;
+    ypresp_val ypproc_match_2_res;
+    ypresp_key_val ypproc_first_2_res;
+    ypresp_key_val ypproc_next_2_res;
+    ypresp_xfr ypproc_xfr_2_res;
+    ypresp_all ypproc_all_2_res;
+    ypresp_master ypproc_master_2_res;
+    ypresp_order ypproc_order_2_res;
+    ypresp_maplist ypproc_maplist_2_res;
+  } result;
+  bool_t retval;
+  xdrproc_t _xdr_argument, _xdr_result;
+  bool_t (*local) (char *, void *, struct svc_req *);
+
+  switch (rqstp->rq_proc)
+    {
+    case YPPROC_NULL:
+      _xdr_argument = (xdrproc_t) xdr_void;
+      _xdr_result = (xdrproc_t) xdr_void;
+      local =
+	(bool_t (*)(char *, void *, struct svc_req *)) ypproc_null_2_svc;
+      break;
+
+    case YPPROC_DOMAIN:
+      _xdr_argument = (xdrproc_t) xdr_domainname;
+      _xdr_result = (xdrproc_t) xdr_bool;
+      local =
+	(bool_t (*)(char *, void *, struct svc_req *)) ypproc_domain_2_svc;
+      break;
+
+    case YPPROC_DOMAIN_NONACK:
+      _xdr_argument = (xdrproc_t) xdr_domainname;
+      _xdr_result = (xdrproc_t) xdr_bool;
+      local =
+	(bool_t (*)(char *, void *, struct svc_req *))
+	ypproc_domain_nonack_2_svc;
+      break;
+
+    case YPPROC_MATCH:
+      _xdr_argument = (xdrproc_t) xdr_ypreq_key;
+      _xdr_result = (xdrproc_t) xdr_ypresp_val;
+      local =
+	(bool_t (*)(char *, void *, struct svc_req *)) ypproc_match_2_svc;
+      break;
+
+    case YPPROC_FIRST:
+      _xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+      _xdr_result = (xdrproc_t) xdr_ypresp_key_val;
+      local =
+	(bool_t (*)(char *, void *, struct svc_req *)) ypproc_first_2_svc;
+      break;
+
+    case YPPROC_NEXT:
+      _xdr_argument = (xdrproc_t) xdr_ypreq_key;
+      _xdr_result = (xdrproc_t) xdr_ypresp_key_val;
+      local =
+	(bool_t (*)(char *, void *, struct svc_req *)) ypproc_next_2_svc;
+      break;
+
+    case YPPROC_XFR:
+      _xdr_argument = (xdrproc_t) xdr_ypreq_xfr;
+      _xdr_result = (xdrproc_t) xdr_ypresp_xfr;
+      local = (bool_t (*)(char *, void *, struct svc_req *)) ypproc_xfr_2_svc;
+      break;
+
+    case YPPROC_CLEAR:
+      _xdr_argument = (xdrproc_t) xdr_void;
+      _xdr_result = (xdrproc_t) xdr_void;
+      local =
+	(bool_t (*)(char *, void *, struct svc_req *)) ypproc_clear_2_svc;
+      break;
+
+    case YPPROC_ALL:
+      _xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+      _xdr_result = (xdrproc_t) xdr_ypresp_all;
+      local = (bool_t (*)(char *, void *, struct svc_req *)) ypproc_all_2_svc;
+      break;
+
+    case YPPROC_MASTER:
+      _xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+      _xdr_result = (xdrproc_t) xdr_ypresp_master;
+      local =
+	(bool_t (*)(char *, void *, struct svc_req *)) ypproc_master_2_svc;
+      break;
+
+    case YPPROC_ORDER:
+      _xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+      _xdr_result = (xdrproc_t) xdr_ypresp_order;
+      local =
+	(bool_t (*)(char *, void *, struct svc_req *)) ypproc_order_2_svc;
+      break;
+
+    case YPPROC_MAPLIST:
+      _xdr_argument = (xdrproc_t) xdr_domainname;
+      _xdr_result = (xdrproc_t) xdr_ypresp_maplist;
+      local =
+	(bool_t (*)(char *, void *, struct svc_req *)) ypproc_maplist_2_svc;
+      break;
+
+    default:
+      svcerr_noproc (transp);
+      return;
+    }
+
+  memset ((char *) &argument, 0, sizeof (argument));
+  if (!svc_getargs (transp, _xdr_argument, (caddr_t) &argument))
+    {
+      svcerr_decode (transp);
+      return;
+    }
+
+  retval = (bool_t) (*local) ((char *) &argument, (void *) &result, rqstp);
+  if (retval > 0 && !svc_sendreply (transp, _xdr_result, (char *) &result))
+      svcerr_systemerr (transp);
+
+  if (!svc_freeargs (transp, _xdr_argument, (caddr_t) &argument))
+    {
+      fprintf (stderr, "unable to free arguments");
+      exit (1);
+    }
+
+  if (!ypprog_2_freeresult (transp, _xdr_result, (caddr_t) &result))
+    fprintf (stderr, "unable to free results");
+
+  return;
+}
+
+static void
+ypserv_svc_run (void)
+{
+  int i;
+
+  for (;;)
+    {
+      struct pollfd *my_pollfd;
+
+      if (svc_max_pollfd == 0 && svc_pollfd == NULL)
+        return;
+
+      my_pollfd = malloc (sizeof (struct pollfd) * svc_max_pollfd);
+      for (i = 0; i < svc_max_pollfd; ++i)
+        {
+          my_pollfd[i].fd = svc_pollfd[i].fd;
+          my_pollfd[i].events = svc_pollfd[i].events;
+          my_pollfd[i].revents = 0;
+        }
+
+      switch (i = poll (my_pollfd, svc_max_pollfd, -1))
+        {
+        case -1:
+          free (my_pollfd);
+          if (errno == EINTR)
+            continue;
+          syslog (LOG_ERR, "svc_run: - poll failed: %m");
+          return;
+        case 0:
+          free (my_pollfd);
+          continue;
+        default:
+          svc_getreq_poll (my_pollfd, i);
+          free (my_pollfd);
+          if (forked)
+            _exit (0);
+        }
+    }
+}
+
+
+/* Create a pidfile on startup */
+static void
+create_pidfile (void)
+{
+  int fd, left, written, flags;
+  pid_t pid;
+  char pbuf[10], *ptr;
+  struct flock lock;
+
+  fd = open (_YPSERV_PIDFILE, O_CREAT | O_RDWR,
+	     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+  if (fd < 0)
+    {
+      log_msg ("cannot create pidfile %s", _YPSERV_PIDFILE);
+      if (debug_flag)
+	log_msg ("\n");
+    }
+
+  /* Make sure file gets correctly closed when process finished.  */
+  flags = fcntl (fd, F_GETFD, 0);
+  if (flags == -1)
+    {
+      /* Cannot get file flags.  */
+      close (fd);
+      return;
+    }
+  flags |= FD_CLOEXEC;		/* Close on exit.  */
+  if (fcntl (fd, F_SETFD, flags) < 0)
+    {
+      /* Cannot set new flags.  */
+      close (fd);
+      return;
+    }
+
+  lock.l_type = F_WRLCK;
+  lock.l_start = 0;
+  lock.l_whence = SEEK_SET;
+  lock.l_len = 0;
+
+  /* Is the pidfile locked by another ypserv ? */
+  if (fcntl (fd, F_GETLK, &lock) < 0)
+    {
+      log_msg ("fcntl error");
+      if (debug_flag)
+	log_msg ("\n");
+    }
+  if (lock.l_type == F_UNLCK)
+    pid = 0;			/* false, not locked by another proc */
+  else
+    pid = lock.l_pid;		/* true, return pid of lock owner */
+
+  if (0 != pid)
+    {
+      log_msg ("ypserv already running (pid %d) - exiting", pid);
+      if (debug_flag)
+	log_msg ("\n");
+      exit (1);
+    }
+
+  /* write lock */
+  lock.l_type = F_WRLCK;
+  lock.l_start = 0;
+  lock.l_whence = SEEK_SET;
+  lock.l_len = 0;
+  if (0 != fcntl (fd, F_SETLK, &lock))
+    log_msg ("cannot lock pidfile");
+  sprintf (pbuf, "%ld\n", (long) getpid ());
+  left = strlen (pbuf);
+  ptr = pbuf;
+  while (left > 0)
+    {
+      if ((written = write (fd, ptr, left)) <= 0)
+	return;			/* error */
+      left -= written;
+      ptr += written;
+    }
+
+  return;
+}
+
+/* Clean up if we quit the program. */
+static void
+sig_quit (int sig __attribute__ ((unused)))
+{
+  pmap_unset (YPPROG, YPVERS);
+  pmap_unset (YPPROG, YPOLDVERS);
+  unlink (_YPSERV_PIDFILE);
+
+  exit (0);
+}
+
+/* Reload securenets and config file */
+static void
+sig_hup (int sig __attribute__ ((unused)))
+{
+  int old_cached_filehandles = cached_filehandles;
+
+  load_securenets ();
+  load_config ();
+  /* Don't allow to decrease the number of max. cached files with
+     SIGHUP.  */
+  if (cached_filehandles < old_cached_filehandles)
+    cached_filehandles = old_cached_filehandles;
+}
+
+/* Clean up after child processes signal their termination. */
+static void
+sig_child (int sig)
+{
+  int st;
+  pid_t pid;
+
+  if (debug_flag)
+    log_msg ("sig_child: got signal %i", sig);
+
+
+  /* Clear all childs */
+  while ((pid = waitpid (-1, &st, WNOHANG)) > 0)
+    {
+      if (debug_flag)
+        log_msg ("pid=%d", pid);
+      --children;
+    }
+
+  if (children < 0)
+    log_msg ("children is lower 0 (%i)!", children);
+  else if (debug_flag)
+    log_msg ("children = %i", children);
+}
+
+
+static void
+Usage (int exitcode)
+{
+  fputs ("usage: ypserv [-d [path]] [-p port]\n", stderr);
+  fputs ("       ypserv --version\n", stderr);
+
+  exit (exitcode);
+}
+
+int
+main (int argc, char **argv)
+{
+  SVCXPRT *transp;
+  int my_port = -1, my_socket, result;
+  struct sockaddr_in s_in;
+  struct sigaction sa;
+
+  openlog ("ypserv", LOG_PID, LOG_DAEMON);
+
+  while (1)
+    {
+      int c;
+      int option_index = 0;
+      static struct option long_options[] = {
+	{"version", no_argument, NULL, 'v'},
+	{"debug", no_argument, NULL, 'd'},
+	{"port", required_argument, NULL, 'p'},
+	{"usage", no_argument, NULL, 'u'},
+	{"help", no_argument, NULL, 'h'},
+	{NULL, 0, NULL, '\0'}
+      };
+
+      c = getopt_long (argc, argv, "vdp:buh", long_options, &option_index);
+      if (c == -1)
+	break;
+      switch (c)
+	{
+	case 'v':
+	  debug_flag = 1;
+	  log_msg ("ypserv (%s) %s\n", PACKAGE, VERSION);
+	  return 0;
+	case 'd':
+	  ++debug_flag;
+	  break;
+	case 'p':
+	  my_port = atoi (optarg);
+	  if (debug_flag)
+	    log_msg ("Using port %d\n", my_port);
+	  break;
+	case 'u':
+	case 'h':
+	  Usage (0);
+	  break;
+	default:
+	  Usage (1);
+	  break;
+	}
+    }
+
+  argc -= optind;
+  argv += optind;
+
+  if (debug_flag)
+    log_msg ("[ypserv (%s) %s]\n", PACKAGE, VERSION);
+  else
+    {
+      int i;
+
+      if ((i = fork ()) > 0)
+	exit (0);
+
+      if (i < 0)
+	{
+	  log_msg ("Cannot fork: %s\n", strerror (errno));
+	  exit (-1);
+	}
+
+      if (setsid () == -1)
+	{
+	  log_msg ("Cannot setsid: %s\n", strerror (errno));
+	  exit (-1);
+	}
+
+      if ((i = fork ()) > 0)
+	exit (0);
+
+      if (i < 0)
+	{
+	  log_msg ("Cannot fork: %s\n", strerror (errno));
+	  exit (-1);
+	}
+
+      for (i = 0; i < getdtablesize (); ++i)
+	close (i);
+      errno = 0;
+
+      umask (0);
+      i = open ("/dev/null", O_RDWR);
+      dup (i);
+      dup (i);
+    }
+
+  if (argc > 0 && debug_flag)
+    {
+      path_ypdb = argv[0];
+      log_msg ("Using database directory: %s\n", path_ypdb);
+    }
+
+  /* Change current directory to database location */
+  if (chdir (path_ypdb) < 0)
+    {
+      log_msg ("ypserv: chdir: %s", strerror (errno));
+      exit (1);
+    }
+
+  create_pidfile ();
+
+  load_securenets ();
+  load_config ();
+
+  /*
+   * Ignore SIGPIPEs. They can hurt us if someone does a ypcat
+   * and then hits CTRL-C before it terminates.
+   */
+  sigaction (SIGPIPE, NULL, &sa);
+  sa.sa_handler = SIG_IGN;
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGPIPE, &sa, NULL);
+  /*
+   * If program quits, give ports free.
+   */
+  sigaction (SIGTERM, NULL, &sa);
+  sa.sa_handler = sig_quit;
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGTERM, &sa, NULL);
+
+  sigaction (SIGINT, NULL, &sa);
+  sa.sa_handler = sig_quit;
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGINT, &sa, NULL);
+
+  /*
+   * If we get a SIGHUP, reload the securenets and config file.
+   */
+  sigaction (SIGHUP, NULL, &sa);
+  sa.sa_handler = sig_hup;
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGHUP, &sa, NULL);
+
+  /*
+   * On SIGCHLD wait for the child process, so it can give free all
+   * resources.
+   */
+  sigaction (SIGCHLD, NULL, &sa);
+  sa.sa_handler = sig_child;
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGCHLD, &sa, NULL);
+
+  pmap_unset (YPPROG, YPVERS);
+  pmap_unset (YPPROG, YPOLDVERS);
+
+  if (my_port >= 0)
+    {
+      my_socket = socket (AF_INET, SOCK_DGRAM, 0);
+      if (my_socket < 0)
+	{
+	  log_msg ("can not create UDP: %s", strerror (errno));
+	  exit (1);
+	}
+
+      memset ((char *) &s_in, 0, sizeof (s_in));
+      s_in.sin_family = AF_INET;
+      s_in.sin_addr.s_addr = htonl (INADDR_ANY);
+      s_in.sin_port = htons (my_port);
+
+      result = bind (my_socket, (struct sockaddr *) &s_in,
+		     sizeof (s_in));
+      if (result < 0)
+	{
+	  log_msg ("ypserv: can not bind UDP: %s ", strerror (errno));
+	  exit (1);
+	}
+    }
+  else
+    my_socket = RPC_ANYSOCK;
+
+  transp = svcudp_create (my_socket);
+  if (transp == NULL)
+    {
+      log_msg ("cannot create udp service.");
+      exit (1);
+    }
+
+  if (!svc_register (transp, YPPROG, YPVERS, ypprog_2, IPPROTO_UDP))
+    {
+      log_msg ("unable to register (YPPROG, YPVERS, udp).");
+      exit (1);
+    }
+
+  /* XXX ypprog_2 should be ypprog_1 */
+  if (!svc_register (transp, YPPROG, YPOLDVERS, ypprog_2, IPPROTO_UDP))
+    {
+      log_msg ("unable to register (YPPROG, YPOLDVERS, udp).");
+      exit (1);
+    }
+
+  if (my_port >= 0)
+    {
+      my_socket = socket (AF_INET, SOCK_STREAM, 0);
+      if (my_socket < 0)
+	{
+	  log_msg ("ypserv: can not create TCP: %s", strerror (errno));
+	  exit (1);
+	}
+
+      memset (&s_in, 0, sizeof (s_in));
+      s_in.sin_family = AF_INET;
+      s_in.sin_addr.s_addr = htonl (INADDR_ANY);
+      s_in.sin_port = htons (my_port);
+
+      result = bind (my_socket, (struct sockaddr *) &s_in,
+		     sizeof (s_in));
+      if (result < 0)
+	{
+	  log_msg ("ypserv: can not bind TCP ", strerror (errno));
+	  exit (1);
+	}
+    }
+  else
+    my_socket = RPC_ANYSOCK;
+
+  transp = svctcp_create (my_socket, 0, 0);
+  if (transp == NULL)
+    {
+      log_msg ("ypserv: cannot create tcp service\n");
+      exit (1);
+    }
+
+  if (!svc_register (transp, YPPROG, YPVERS, ypprog_2, IPPROTO_TCP))
+    {
+      log_msg ("ypserv: unable to register (YPPROG, YPVERS, tcp)\n");
+      exit (1);
+    }
+
+  /* XXX ypprog_2 should be ypprog_1 */
+  if (!svc_register (transp, YPPROG, YPOLDVERS, ypprog_2, IPPROTO_TCP))
+    {
+      log_msg ("ypserv: unable to register (YPPROG, YPOLDVERS, tcp)\n");
+      exit (1);
+    }
+
+  ypserv_svc_run ();
+  log_msg ("svc_run returned");
+  unlink (_YPSERV_PIDFILE);
+  exit (1);
+  /* NOTREACHED */
+}