diff --git a/usr.sbin/ypserv/yp_main.c b/usr.sbin/ypserv/yp_main.c index cfa45e4a3e3f..7ae15d9485b7 100644 --- a/usr.sbin/ypserv/yp_main.c +++ b/usr.sbin/ypserv/yp_main.c @@ -84,6 +84,16 @@ char *yp_dir = _PATH_YP; int do_dns = 0; int resfd; +struct socktype { + const char *st_name; + int st_type; +}; +static struct socktype stlist[] = { + { "tcp", SOCK_STREAM }, + { "udp", SOCK_DGRAM }, + { NULL, 0 } +}; + static void _msgout(char* msg) { @@ -187,7 +197,7 @@ reaper(int sig) static void usage(void) { - fprintf(stderr, "usage: ypserv [-h] [-d] [-n] [-p path]\n"); + fprintf(stderr, "usage: ypserv [-h] [-d] [-n] [-p path] [-P port]\n"); exit(1); } @@ -230,8 +240,11 @@ main(int argc, char *argv[]) struct sockaddr_in saddr; socklen_t asize = sizeof (saddr); int ch; + in_port_t yp_port = 0; + char *errstr; + struct socktype *st; - while ((ch = getopt(argc, argv, "hdnp:")) != -1) { + while ((ch = getopt(argc, argv, "hdnp:P:")) != -1) { switch (ch) { case 'd': debug = ypdb_debug = 1; @@ -242,6 +255,14 @@ main(int argc, char *argv[]) case 'p': yp_dir = optarg; break; + case 'P': + yp_port = (in_port_t)strtonum(optarg, 1, 65535, + (const char **)&errstr); + if (yp_port == 0 && errstr != NULL) { + _msgout("invalid port number provided"); + exit(1); + } + break; case 'h': default: usage(); @@ -277,6 +298,39 @@ main(int argc, char *argv[]) (void) pmap_unset(YPPROG, 1); } + /* + * Initialize TCP/UDP sockets. + */ + memset((char *)&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_ANY); + saddr.sin_port = htons(yp_port); + for (st = stlist; st->st_name != NULL; st++) { + /* Do not bind the socket if the user didn't specify a port */ + if (yp_port == 0) + break; + + sock = socket(AF_INET, st->st_type, 0); + if (sock == -1) { + if ((asprintf(&errstr, "cannot create a %s socket", + st->st_name)) == -1) + err(1, "unexpected failure in asprintf()"); + _msgout(errstr); + free((void *)errstr); + exit(1); + } + if (bind(sock, (struct sockaddr *) &saddr, sizeof(saddr)) + == -1) { + if ((asprintf(&errstr, "cannot bind %s socket", + st->st_name)) == -1) + err(1, "unexpected failure in asprintf()"); + _msgout(errstr); + free((void *)errstr); + exit(1); + } + errstr = NULL; + } + if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { transp = svcudp_create(sock); if (transp == NULL) { diff --git a/usr.sbin/ypserv/ypserv.8 b/usr.sbin/ypserv/ypserv.8 index 608b2028c57d..d4da3b79e862 100644 --- a/usr.sbin/ypserv/ypserv.8 +++ b/usr.sbin/ypserv/ypserv.8 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 4, 1995 +.Dd February 3, 2008 .Dt YPSERV 8 .Os .Sh NAME @@ -40,6 +40,7 @@ .Nm .Op Fl n .Op Fl d +.Op Fl P Ar port .Op Fl p Ar path .Sh DESCRIPTION .Tn NIS @@ -403,6 +404,9 @@ in subprocesses, allowing the parent server process to go on handling other requests.) This makes it easier to trace the server with a debugging tool. +.It Fl P Ar port +Force ypserv to bind to a specific TCP/UDP port, rather than selecting +its own. .It Fl p Ar path Normally, .Nm