/*
 * Get a UDP socket, bind it, figure out the port,
 * and advertise the port as program "prog".
 *
 * XXX - it would be nice if you could advertise ascii strings.
 */
int
udp_server(u_long prog, int rdwr)
{
	int	sock;
	struct	sockaddr_in s;

	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
		perror("socket");
		exit(1);
	}
	sock_optimize(sock, rdwr);
	bzero((void*)&s, sizeof(s));
	s.sin_family = AF_INET;
#ifdef	NO_PORTMAPPER
	s.sin_port = htons(prog);
#endif
	if (bind(sock, (struct sockaddr*)&s, sizeof(s)) < 0) {
		perror("bind");
		exit(2);
	}
#ifdef PORTMAP
	(void)pmap_unset(prog, (u_long)1);
	if (!pmap_set(prog, (u_long)1, (u_long)IPPROTO_UDP,
	    (unsigned short)sockport(sock))) {
		perror("pmap_set");
		exit(5);
	}
#endif
	return (sock);
}
Exemplo n.º 2
0
/* Add a service program to the callout list.
   The dispatch routine will be called when a rpc request for this
   program number comes in. */
bool_t
svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers,
	      void (*dispatch) (struct svc_req *, SVCXPRT *),
	      rpcproc_t protocol)
{
  struct svc_callout *prev;
  register struct svc_callout *s;

  if ((s = svc_find (prog, vers, &prev)) != NULL_SVC)
    {
      if (s->sc_dispatch == dispatch)
	goto pmap_it;		/* he is registering another xptr */
      return FALSE;
    }
  s = (struct svc_callout *) mem_alloc (sizeof (struct svc_callout));
  if (s == (struct svc_callout *) 0)
    return FALSE;

  s->sc_prog = prog;
  s->sc_vers = vers;
  s->sc_dispatch = dispatch;
  s->sc_next = svc_head;
  svc_head = s;

pmap_it:
  /* now register the information with the local binder service */
  if (protocol)
    return pmap_set (prog, vers, protocol, xprt->xp_port);

  return TRUE;
}
Exemplo n.º 3
0
/*
 * Add a service program to the callout list.
 * The dispatch routine will be called when a rpc request for this
 * program number comes in.
 */
bool_t
svc_register(SVCXPRT *xprt, u_long prog, u_long vers, void (*dispatch)(),
    int protocol)
{
	struct svc_callout *prev;
	struct svc_callout *s;

	if ((s = svc_find(prog, vers, &prev)) != NULL) {
		if (s->sc_dispatch == dispatch)
			goto pmap_it;  /* he is registering another xptr */
		return (FALSE);
	}
	s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
	if (s == NULL) {
		return (FALSE);
	}
	s->sc_prog = prog;
	s->sc_vers = vers;
	s->sc_dispatch = dispatch;
	s->sc_next = svc_head;
	svc_head = s;
pmap_it:
	/* now register the information with the local binder service */
	if (protocol) {
		return (pmap_set(prog, vers, protocol, xprt->xp_port));
	}
	return (TRUE);
}
Exemplo n.º 4
0
int main(int argn, char *argc[])
{
	//Program parameters : argc[1] : HostName or Host IP
	//					   argc[2] : Server Program Number
	//					   other arguments depend on test case

	//run_mode can switch into stand alone program or program launch by shell script
	//1 : stand alone, debug mode, more screen information
	//0 : launch by shell script as test case, only one printf -> result status
	int run_mode = 0;
	int test_status = 1; //Default test result set to FAILED
	int progNum = 5000000; //This test doesn't care with progNum, just local test of reg/unreg...
	int port = 600;
	SVCXPRT *transp = NULL;

	//Initialization
	pmap_unset(progNum, VERSNUM);

    if (run_mode)
    {
    	printf("Before creation\n");
	}

	transp = svcudp_create(RPC_ANYSOCK);
	pmap_set(progNum, VERSNUM, IPPROTO_UDP, port);

    test_status = !pmap_unset(progNum, VERSNUM);

	//This last printf gives the result status to the tests suite
	//normally should be 0: test has passed or 1: test has failed
	printf("%d\n", test_status);

	return test_status;
}
Exemplo n.º 5
0
/*
 * Add a service program to the callout list.
 * The dispatch routine will be called when a rpc request for this
 * program number comes in.
 */
bool
svc_register(SVCXPRT *xprt, u_long prog, u_long vers,
	     void (*dispatch) (struct svc_req *req, SVCXPRT *xprt),
	     int protocol)
{
	struct svc_callout *prev;
	struct svc_callout *s;

	assert(xprt != NULL);
	assert(dispatch != NULL);

	s = svc_find((rpcprog_t) prog, (rpcvers_t) vers, &prev, NULL);
	if (s) {
		if (s->rec.sc_dispatch == dispatch)
			goto pmap_it;	/* he is registering another xprt */
		return (false);
	}
	s = mem_alloc(sizeof(struct svc_callout));
	s->rec.sc_prog = (rpcprog_t) prog;
	s->rec.sc_vers = (rpcvers_t) vers;
	s->rec.sc_dispatch = dispatch;
	s->sc_next = svc_head;
	svc_head = s;

 pmap_it:
	/* now register the information with the local binder service */
	if (protocol)
		return (pmap_set(prog, vers, protocol, xprt->xp_port));

	return (true);
}
Exemplo n.º 6
0
static PyObject * portmap_set(PyObject *self, PyObject *args)
{
	unsigned long program, version;
	int protocol;
	unsigned short port;
	
	if (!PyArg_ParseTuple(args, "kkiH:set", 
			      &program, &version, &protocol, &port))
		return NULL;
	// Tai: removed the unset here so we can bind both TCP and UDP
	pmap_set(program, version, protocol, port);
	
	Py_INCREF(Py_None);
	return Py_None;
}
Exemplo n.º 7
0
static void
register_port (int portnum, int abort_if_fail)
{
#ifdef HAVE_PMAP_SET
    /* Register our service with the portmapper */
    /* protocol: pmap_set (prognum, versnum, protocol, portp) */

    if (pmap_set (RPC_PROGNUM, RPC_PROGVER, IPPROTO_TCP, portnum))
	signal (SIGINT, signal_int_handler);
    else {
	fprintf (stderr, "Cannot register service with portmapper\n");
	if (abort_if_fail)
	    exit (1);
    }
#else
    if (abort_if_fail) {
	fprintf (stderr,
		 "This system lacks port registration, try using the -p\n"
		 "flag to force installation at a given port");
    }
#endif
}
Exemplo n.º 8
0
/************************************************************************
*									*
*  This routine is used to register a specific function which will be	*
*  called when there is a message.					*
*  User function to be called can be NULL, indicating unregistering     *
*  message, or user-func address, which takes a form of                 *
*  func(u_long proc_id,  where proc_id is ID number.                    *
*       Ipgmsg *msg)       where msg is a message.                        *
*									*
*  Return program number for success and 0 for failure.			*
*  									*
*  In RPC term, SERVER registers/unregisters program and version number	*
*									*/
u_long
ipgwin_register_msg_receive(
      u_long prognum,		/* program ID */
      u_long versnum,		/* program version */
      void (*userfunc)(u_long, Ipgmsg*))
{
   Svcmsg *current, *prev;	/* ptrs used for message item */
   Svcmsg *newitem;		/* new created item */
   SVCXPRT *transp;		/* transport info */
   int protocol;		/* protocol */

   /* Check if the msgid has been registered or not.  If the message  */
   /* has been registered, only change the user function.  If the user */
   /* function is NULL, delete the message item from the list.  If the */
   /* message has not been registered, add the new message item at the */
   /* first of the list.					       */
   for (current=prev=svchead; current; prev=current, current=current->next)
   {
      if ((current->prognum == prognum) &&
          (current->versnum == versnum))   /* Found */
      {
         svc_unregister(current->prognum, current->versnum);
	 svc_destroy(current->xprt);

         if (current == prev)  /* Only one item on the list */
	    svchead = NULL;
         else
            prev->next = current->next;
         (void)free((char *)current);

	 if (userfunc == NULL) 
	    return(prognum) ;
	 else
	    break;
      }
   }

   /* Create an RPC with TCP socket */
   if ((transp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL)
   {
      STDERR("Can't create RPC");
      return(0);
   }

   /* Get the "transient" program number if prognum is zero */
   if (prognum == 0)
   {
      /* The "transient" program number starts at 0x40000000 */
      /* Get the unused number.				     */
      prognum = 0x40000000;
      while (!pmap_set(prognum, versnum, IPPROTO_TCP, transp->xp_port))
	 prognum++;

      /* We don't need to register it at svc_register since pmap_set */
      /* has done it.						     */
      protocol = 0;
   }
   else
   {
      /* Erase the pormapper's table */
      pmap_unset(prognum, versnum);

      protocol = IPPROTO_TCP;
   }

   /* Register the portmapper. */
   /* Note that Sun suggests that the program number ranges from */
   /* 0x20000000 to 0x5fffffff.  However, our routine doesn't    */
   /* check for this limit.		        */
#ifdef SOLARIS
   if (!svc_register(transp, prognum, versnum,
		     ipgwin_priv_msg_receive, protocol))
#elif LINUX 
   if (!svc_register(transp, prognum, versnum,
		     ipgwin_priv_msg_receive, protocol))
#else
   if (!svc_register(transp, prognum, versnum, 
       (void (*)(DOTDOTDOT))ipgwin_priv_msg_receive, protocol))
#endif
   {
      STDERR("ipgwin_register_msg_receive:Can't register RPC");
      svc_destroy(transp);
      return(0);
   }

   /* Create new item */
   if ((newitem = (Svcmsg *)malloc(sizeof(Svcmsg))) == NULL)
   {
      PERROR("ipgwin_register_message_receive:malloc:Message is not registered");
      return(0);
   }
   newitem->xprt = transp;
   newitem->prognum = prognum;
   newitem->versnum = versnum;
   newitem->msgfunc = userfunc;

   /* Add a new item at the front of the list */
   newitem->next = svchead;
   svchead = newitem; 
   return(prognum);
}
Exemplo n.º 9
0
Arquivo: ldmd.c Projeto: dgaer/LDM
/*
 * Create a TCP socket, bind it to a port, call 'listen' (we are a
 * server), and inform the portmap (rpcbind) service.  Does _not_ create
 * an RPC SVCXPRT or do the xprt_register() or svc_fds() stuff.
 *
 * Arguments:
 *      sockp           Pointer to socket (file) descriptor.  Set on and only on
 *                      success.
 *      localIpAddr     The IP address, in network byte order, of the 
 *                      local interface to use.  May be htonl(INADDR_ANY).
 *      localPort       The number of the local port on which the LDM server
 *                      should listen.
 * Returns:
 *      0               Success.
 *      EACCES          The process doesn't have appropriate privileges.
 *      EADDRINUSE      The local address is already in use.
 *      EADDRNOTAVAIL   The specified address is not available from the local
 *                      machine.
 *      EAFNOSUPPORT    The system doesn't support IP.
 *      EMFILE          No more file descriptors are available for this process.
 *      ENFILE          No more file descriptors are available for the system.
 *      ENOBUFS         Insufficient resources were available in the system.
 *      ENOMEM          Insufficient memory was available.
 *      ENOSR           There were insufficient STREAMS resources available.
 *      EOPNOTSUPP      The socket protocol does not support listen().
 *      EPROTONOSUPPORT The system doesn't support TCP.
 */
static int create_ldm_tcp_svc(
        int* sockp,
        in_addr_t localIpAddr,
        unsigned localPort)
{
    int error = 0; /* success */
    int sock;

    /*
     * Get a TCP socket.
     */
    udebug("create_ldm_tcp_svc(): Getting TCP socket");
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock < 0) {
        error = errno;

        serror("Couldn't get socket for server");
    }
    else {
        unsigned short port = (unsigned short) localPort;
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);

        /*
         * Eliminate problem with EADDRINUSE for reserved socket.
         * We get this if an upstream data source hasn't tried to
         * write on the other end and we are in FIN_WAIT_2
         */
        udebug("create_ldm_tcp_svc(): Eliminating EADDRINUSE problem.");
        {
            int on = 1;

            (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
                    sizeof(on));
        }

        (void) memset(&addr, 0, len);
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = localIpAddr;
        addr.sin_port = (short) htons((short) port);

        /*
         * If privilege available, set it so we can bind to the port for LDM
         * services.  Also needed for the pmap_set() call.
         */
        udebug("create_ldm_tcp_svc(): Getting root privs");
        rootpriv();

        udebug("create_ldm_tcp_svc(): Binding socket");
        if (bind(sock, (struct sockaddr *) &addr, len) < 0) {
            error = errno;

            serror("Couldn't obtain local address %s:%u for server",
                    inet_ntoa(addr.sin_addr), (unsigned) port);

            if (error == EACCES) {
                error = 0;
                addr.sin_port = 0; /* let system assign port */

                if (bind(sock, (struct sockaddr *) &addr, len) < 0) {
                    error = errno;

                    serror("Couldn't obtain local address %s:* for server",
                            inet_ntoa(addr.sin_addr));
                }
            } /* requested port is reserved */
        } /* couldn't bind to requested port */

        if (!error) {
            /*
             * Get the local address associated with the bound socket.
             */
            udebug("create_ldm_tcp_svc(): Calling getsockname()");
            if (getsockname(sock, (struct sockaddr *) &addr, &len) < 0) {
                error = errno;

                serror("Couldn't get local address of server's socket");
            }
            else {
                port = (short) ntohs((short) addr.sin_port);

                unotice("Using local address %s:%u", inet_ntoa(addr.sin_addr),
                        (unsigned) port);

                udebug("create_ldm_tcp_svc(): Calling listen()");
                if (listen(sock, 32) != 0) {
                    error = errno;

                    serror("Couldn't listen() on server's socket");
                }
                else {
                    /*
                     * Register with the portmapper if it's running.  The
                     * check to see if it's running is made because on a
                     * FreeBSD 4.7-STABLE system, a pmap_set() call takes
                     * one minute even if the portmapper isn't running.
                     */
                    udebug("create_ldm_tcp_svc(): Checking portmapper");
                    if (local_portmapper_running()) {
                        udebug("create_ldm_tcp_svc(): Registering");

                        if (pmap_set(LDMPROG, 6, IPPROTO_TCP, port) == 0) {
                            uwarn("Can't register TCP service %lu on "
                                    "port %u", LDMPROG, (unsigned) port);
                            uwarn("Downstream LDMs won't be able to "
                                    "connect via the RPC portmapper daemon "
                                    "(rpcbind(8), portmap(8), etc.)");
                        }
                        else {
                            portIsMapped = 1;

                            (void) pmap_set(LDMPROG, 5, IPPROTO_TCP, port);
                        }
                    } /* a local portmapper is running */

                    /*
                     * Done with the need for privilege.
                     */
                    udebug("create_ldm_tcp_svc(): Releasing root privs");
                    unpriv();

                    *sockp = sock;
                } /* listen() success */
            } /* getsockname() success */
        } /* "sock" is bound to local address */

        if (error)
            (void) close(sock);
    } /* "sock" is open */

    return error;
}
Exemplo n.º 10
0
/* This one _can_ be used to begin grabbing messages
   (if they want to build their own main function)
   */
void
flick_server_run()
{
	int maxconn = -1;
	fd_set fds;
	flick_server_list *tmp = lst;
	struct sockaddr_in server;
	short port = -1;
	int sock;
	int len = sizeof(struct sockaddr_in);
	FLICK_BUFFER the_buf, return_buf;
	
	the_buf.real_buf_start = the_buf.buf_read = the_buf.buf_start =
	         the_buf.buf_current = (void *)calloc(8192, 1);
	
	the_buf.real_buf_end = the_buf.buf_end = (((char *) the_buf.buf_start)
						  + 8188);
	
	return_buf.real_buf_start = return_buf.real_buf_end =
	      return_buf.buf_read = 0;
	return_buf.buf_start  = return_buf.buf_current = (void *)calloc(8192, 1);
	return_buf.buf_end = ((char *) return_buf.buf_start) + 8188;
	
	if(!the_buf.buf_start || !return_buf.buf_start) {
		perror("Insufficient memory for server buffers");
		exit(1);
	}
	
	FD_ZERO(&fds);
	
	/* Get the listening socket & port for this machine */
	while(tmp) {
		
		/* Get a socket for this skeleton function */
		sock = get_a_socket();
		memset((char *)&server, 0, sizeof(server));
		server.sin_family = AF_INET;
		
		/* Get a port for this skeleton function */
		server.sin_port = 0;
		if (bind(sock, (struct sockaddr *) &server, len) != 0) {
			perror("cannot `bind' to socket");
			exit(1);
		}
		if ((getsockname(sock, (struct sockaddr *) &server, &len) != 0)
		    || (listen(sock, 8) != 0)) {
			perror("cannot `getsockname' or `listen'");
			exit(1);
		}
		
		tmp->sock = sock;
		port = ntohs(server.sin_port);
		
		/* Register the port with the RPC port mapper & initialize the fd_set */
		pmap_unset(tmp->server.prog_num, tmp->server.vers_num);
		pmap_set(tmp->server.prog_num, tmp->server.vers_num, IPPROTO_TCP, port);
		FD_SET(sock, &fds);
		
		if (sock > maxconn)
			maxconn = sock;
		
		tmp = tmp->next;
	}
	
	/* Accept new clients, read client requests & send replies forever... */
	while (1) {
		int qty = select(maxconn + 1, &fds, 0, 0, 0);
		flick_server_list *last = 0;
		
		tmp = lst;
		while (qty > 0) {
			if (FD_ISSET(tmp->sock, &fds)) {
				if (tmp->listen) {
					flick_server_list *new_list = (flick_server_list *)malloc(sizeof(flick_server_list));
					if (!new_list)
						exit(1);
					new_list->next = lst;
					lst = new_list;
					lst->sock = accept(tmp->sock, 0, 0);
					lst->func = tmp->func;
					lst->server = tmp->server;
					lst->listen = 0;
					if (lst->sock > maxconn)
						maxconn = lst->sock;
				} else do {
					FLICK_TARGET_STRUCT ts;
					ts.socket_fd = tmp->sock;
					ts.port = port;
					
					if (flick_server_get_request(&ts, &the_buf)) {
						switch ((*tmp->func)(&the_buf, &return_buf)) {
						case FLICK_OPERATION_SUCCESS:{
							flick_server_send_reply(&ts, &return_buf);
							break;
						}
						case FLICK_OPERATION_SUCCESS_NOREPLY:{
							break;
						}
						default /* FLICK_OPERATION_FAILURE */ :{
							/* the socket has been closed */
							if (last) {
								last->next = tmp->next;
								free(tmp);
								tmp = last;
							} else {
								lst = tmp->next;
								free(tmp);
								tmp = 0;
							}
							break;
						}}
					} else {
						/* the socket has been closed */
						if (last) {
							last->next = tmp->next;
							free(tmp);
							tmp = last;
						} else {
							lst = tmp->next;
							free(tmp);
							tmp = 0;
						}
					}
				} while (flick_buffer_contains_more(&the_buf));
				qty--;
			}
			last = tmp;
			if (tmp)
				tmp = tmp->next;
			else
				tmp = lst;
		}
		if (qty < 0)
			fprintf(stderr,"Error %d in server\n", errno);
		
		/* reset the file descriptor list */
		FD_ZERO(&fds);
		tmp = lst;
		while (tmp) {
			FD_SET(tmp->sock, &fds);
			tmp = tmp->next;
		}
	}
	exit(1);
}
Exemplo n.º 11
0
static status_e activate_rpc( struct service *sp )
{
   union xsockaddr        tsin;
   socklen_t              sin_len = sizeof(tsin);
   unsigned long          vers ;
   struct service_config *scp = SVC_CONF( sp ) ;
   struct rpc_data       *rdp = SC_RPCDATA( scp ) ;
   char                  *sid = SC_ID( scp ) ;
   unsigned               registered_versions = 0 ;
   int                    sd = SVC_FD( sp ) ;
   const char            *func = "activate_rpc" ;

   if( SC_BIND_ADDR(scp) != 0 )
      memcpy( &tsin, SC_BIND_ADDR(scp), sizeof(tsin) );
   else
      memset( &tsin, 0, sizeof(tsin));

   if ( SC_PROTOVAL ( scp ) == IPPROTO_TCP ) {
      M_SET ( scp->sc_xflags, SF_NOLIBWRAP );
   }
   if( SC_IPV4( scp ) ) {
      tsin.sa_in.sin_family = AF_INET ;
      sin_len = sizeof(struct sockaddr_in);
   } else if( SC_IPV6( scp ) ) {
      tsin.sa_in6.sin6_family = AF_INET6 ;
      sin_len = sizeof(struct sockaddr_in6);
   }

   if ( bind( sd, &tsin.sa, sin_len ) == -1 )
   {
      msg( LOG_ERR, func, "bind failed (%m). service = %s", sid ) ;
      return( FAILED ) ;
   }

   /*
    * Find the port number that was assigned to the socket
    */
   if ( getsockname( sd, &tsin.sa, &sin_len ) == -1 )
   {
      msg( LOG_ERR, func,
            "getsockname failed (%m). service = %s", sid ) ;
      return( FAILED ) ;
   }
   
   if( tsin.sa.sa_family == AF_INET )
      SC_SET_PORT( scp, ntohs( tsin.sa_in.sin_port ) ) ;
   else if( tsin.sa.sa_family == AF_INET6 )
      SC_SET_PORT( scp, ntohs( tsin.sa_in6.sin6_port ) ) ;

   /*
    * Try to register as many versions as possible
    */
   for ( vers = RD_MINVERS( rdp ) ; vers <= RD_MAXVERS( rdp ) ; vers++ ) {
/*      Is this right?  For instance, if we have both tcp and udp services,
 *      this will unregister the previously registered protocol.
 *      pmap_unset(RD_PROGNUM(rdp), vers);
 */
      if ( pmap_set( RD_PROGNUM( rdp ), vers, SC_PROTOVAL( scp ), 
			      SC_PORT( scp ) ) )
         registered_versions++ ;
      else
         msg( LOG_ERR, func,
            "pmap_set failed. service=%s program=%ld version=%ld",
               sid, RD_PROGNUM( rdp ), vers ) ;
      sleep(1);
   }

   if ( debug.on )
      msg( LOG_DEBUG, func,
            "Registered %d versions of %s", registered_versions, sid ) ;

   return( ( registered_versions == 0 ) ? FAILED : OK ) ;
}
Exemplo n.º 12
0
/*
 * Nfs server daemon mostly just a user context for nfssvc()
 *
 * 1 - do file descriptor and signal cleanup
 * 2 - fork the nfsd(s)
 * 3 - create server socket(s)
 * 4 - register socket with portmap
 *
 * For connectionless protocols, just pass the socket into the kernel via.
 * nfssvc().
 * For connection based sockets, loop doing accepts. When you get a new
 * socket from accept, pass the msgsock into the kernel via. nfssvc().
 * The arguments are:
 *	-r - reregister with portmapper
 *	-t - support tcp nfs clients
 *	-u - support udp nfs clients
 * followed by "n" which is the number of nfsds' to fork off
 */
int
main(int argc, char *argv[])
{
	struct nfsd_args nfsdargs;
	struct sockaddr_in inetaddr, inetpeer;
	fd_set *ready, *sockbits;
	size_t fd_size;
	int ch, connect_type_cnt, i, maxsock = 0, msgsock;
	int nfsdcnt = DEFNFSDCNT, on, reregister = 0, sock;
	int udpflag = 0, tcpflag = 0, tcpsock;
	const char *errstr = NULL;
	socklen_t len;

	/* Start by writing to both console and log. */
	openlog("nfsd", LOG_PID | LOG_PERROR, LOG_DAEMON);

	if (argc == 1)
		udpflag = 1;
	while ((ch = getopt(argc, argv, "n:rtu")) != -1)
		switch (ch) {
		case 'n':
			nfsdcnt = strtonum(optarg, 1, MAXNFSDCNT, &errstr);
			if (errstr) {
				syslog(LOG_ERR, "nfsd count is %s: %s", errstr, optarg);
				return(1);
			}
			break;
		case 'r':
			reregister = 1;
			break;
		case 't':
			tcpflag = 1;
			break;
		case 'u':
			udpflag = 1;
			break;
		default:
			usage();
		};
	argv += optind;
	argc -= optind;

	/*
	 * XXX
	 * Backward compatibility, trailing number is the count of daemons.
	 */
	if (argc > 1)
		usage();
	if (argc == 1) {
		nfsdcnt = strtonum(argv[0], 1, MAXNFSDCNT, &errstr);
		if (errstr) {
			syslog(LOG_ERR, "nfsd count is %s: %s", errstr, optarg);
			return(1);
		}
	}

	if (debug == 0) {
		daemon(0, 0);
		(void)signal(SIGHUP, SIG_IGN);
		(void)signal(SIGINT, SIG_IGN);
		(void)signal(SIGQUIT, SIG_IGN);
		(void)signal(SIGSYS, nonfs);
	}
	(void)signal(SIGCHLD, reapchild);

	if (reregister) {
		if (udpflag &&
		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT))) {
			syslog(LOG_ERR, "can't register with portmap for UDP (%m).");
			return (1);
		}
		if (tcpflag &&
		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT))) {
			syslog(LOG_ERR, "can't register with portmap for TCP (%m).");
			return (1);
		}
		return (0);
	}

	/* Cut back to writing to log only. */
	closelog();
	openlog("nfsd", LOG_PID, LOG_DAEMON);

	for (i = 0; i < nfsdcnt; i++) {
		switch (fork()) {
		case -1:
			syslog(LOG_ERR, "fork: %m");
			return (1);
		case 0:
			break;
		default:
			continue;
		}

		setproctitle("server");
		nsd.nsd_nfsd = NULL;
		if (nfssvc(NFSSVC_NFSD, &nsd) < 0) {
			syslog(LOG_ERR, "nfssvc: %m");
			return (1);
		}
		return (0);
	}

	/* If we are serving udp, set up the socket. */
	if (udpflag) {
		if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
			syslog(LOG_ERR, "can't create udp socket");
			return (1);
		}
		memset(&inetaddr, 0, sizeof inetaddr);
		inetaddr.sin_family = AF_INET;
		inetaddr.sin_addr.s_addr = INADDR_ANY;
		inetaddr.sin_port = htons(NFS_PORT);
		inetaddr.sin_len = sizeof(inetaddr);
		if (bind(sock, (struct sockaddr *)&inetaddr,
		    sizeof(inetaddr)) < 0) {
			syslog(LOG_ERR, "can't bind udp addr");
			return (1);
		}
		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
			syslog(LOG_ERR, "can't register with udp portmap");
			return (1);
		}
		nfsdargs.sock = sock;
		nfsdargs.name = NULL;
		nfsdargs.namelen = 0;
		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
			syslog(LOG_ERR, "can't Add UDP socket");
			return (1);
		}
		(void)close(sock);
	}

	/* Now set up the master server socket waiting for tcp connections. */
	on = 1;
	connect_type_cnt = 0;
	if (tcpflag) {
		if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
			syslog(LOG_ERR, "can't create tcp socket");
			return (1);
		}
		if (setsockopt(tcpsock,
		    SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
		memset(&inetaddr, 0, sizeof inetaddr);
		inetaddr.sin_family = AF_INET;
		inetaddr.sin_addr.s_addr = INADDR_ANY;
		inetaddr.sin_port = htons(NFS_PORT);
		inetaddr.sin_len = sizeof(inetaddr);
		if (bind(tcpsock, (struct sockaddr *)&inetaddr,
		    sizeof (inetaddr)) < 0) {
			syslog(LOG_ERR, "can't bind tcp addr");
			return (1);
		}
		if (listen(tcpsock, 5) < 0) {
			syslog(LOG_ERR, "listen failed");
			return (1);
		}
		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
			syslog(LOG_ERR, "can't register tcp with portmap");
			return (1);
		}
		maxsock = tcpsock;
		connect_type_cnt++;
	}

	if (connect_type_cnt == 0)
		return (0);

	setproctitle("master");

	/*
	 * Allocate space for the fd_set pointers and fill in sockbits
	 */
	fd_size = howmany(maxsock + 1, NFDBITS) * sizeof(fd_mask);
	sockbits = malloc(fd_size);
	ready = malloc(fd_size);
	if (sockbits == NULL || ready == NULL) {
		syslog(LOG_ERR, "cannot allocate memory");
		return (1);
	}
	memset(sockbits, 0, fd_size);
	if (tcpflag)
		FD_SET(tcpsock, sockbits);

	/*
	 * Loop forever accepting connections and passing the sockets
	 * into the kernel for the mounts.
	 */
	for (;;) {
		memcpy(ready, sockbits, fd_size);
		if (connect_type_cnt > 1) {
			if (select(maxsock + 1,
			    ready, NULL, NULL, NULL) < 1) {
				syslog(LOG_ERR, "select failed: %m");
				return (1);
			}
		}
		if (tcpflag && FD_ISSET(tcpsock, ready)) {
			len = sizeof(inetpeer);
			if ((msgsock = accept(tcpsock,
			    (struct sockaddr *)&inetpeer, &len)) < 0) {
				if (errno == EWOULDBLOCK || errno == EINTR ||
				    errno == ECONNABORTED)
					continue;
				syslog(LOG_ERR, "accept failed: %m");
				return (1);
			}
			memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
			if (setsockopt(msgsock, SOL_SOCKET,
			    SO_KEEPALIVE, &on, sizeof(on)) < 0)
				syslog(LOG_ERR,
				    "setsockopt SO_KEEPALIVE: %m");
			nfsdargs.sock = msgsock;
			nfsdargs.name = (caddr_t)&inetpeer;
			nfsdargs.namelen = sizeof(inetpeer);
			if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
				syslog(LOG_ERR, "can't Add TCP socket");
				return (1);
			}
			(void)close(msgsock);
		}
	}
}
Exemplo n.º 13
0
static int getprognum(long *prognum, SVCXPRT **xprt, char *fd_str,
			char *prog_str, long vers, char *tp_type)
{
	static ulong_t start = 0x40000000;
	int fd;
#ifdef TDRPC
	ushort_t port;
	int proto;
#else
	struct netconfig *nc;
	struct netbuf *nb;
#endif

	/* If prognum specified, use it instead of transient hassel. */
	if (*prognum) {
		*xprt = NULL;
		sprintf(fd_str, "-1"); /* have child close all fds */
		sprintf(prog_str, "%u", *prognum);
		return (TRUE);
	}

	/*
	 * Transient hassel:
	 *	- parent must create mapping since someone else could
	 *	  steal the transient prognum before child created it
	 * 	- pass the child the fd to use for service
	 * 	- close the fd (after exec), free xprt, leave mapping intact
	 */
#ifdef TDRPC
	if (strcmp(tp_type, "udp") != 0) {
		proto = IPPROTO_UDP;
		*xprt = svcudp_bufcreate(RPC_ANYSOCK, 0, 0);
	} else {
		proto = IPPROTO_TCP;
		*xprt = svctcp_create(RPC_ANYSOCK, 0, 0);
	}
	if (*xprt == NULL)
		return (FALSE);
	port = (*xprt)->xp_port;
	fd = (*xprt)->xp_sock;
	while (!pmap_set(start, vers, proto, port))
		start++;
#else
	/* tp_type is legit: users choice or a loopback netid */
	if ((nc = getnetconfigent(tp_type)) == NULL)
		return (FALSE);
	if ((*xprt = svc_tli_create(RPC_ANYFD, nc, NULL, 0, 0)) == NULL) {
		freenetconfigent(nc);
		return (FALSE);
	}
	nb = &(*xprt)->xp_ltaddr;
	fd = (*xprt)->xp_fd;
	while (!rpcb_set(start, vers, nc, nb))
		start++;
	freenetconfigent(nc);
#endif

	*prognum = start;
	sprintf(fd_str, "%u", fd);
	sprintf(prog_str, "%u", *prognum);

	return (TRUE);
}