transp_sockets.c revision 310490
1151497Sru/* 2151497Sru * Copyright (c) 1997-2014 Erez Zadok 3151497Sru * Copyright (c) 1990 Jan-Simon Pendry 4151497Sru * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 5151497Sru * Copyright (c) 1990 The Regents of the University of California. 6151497Sru * All rights reserved. 7151497Sru * 8151497Sru * This code is derived from software contributed to Berkeley by 9151497Sru * Jan-Simon Pendry at Imperial College, London. 10151497Sru * 11151497Sru * Redistribution and use in source and binary forms, with or without 12151497Sru * modification, are permitted provided that the following conditions 13151497Sru * are met: 14151497Sru * 1. Redistributions of source code must retain the above copyright 15151497Sru * notice, this list of conditions and the following disclaimer. 16151497Sru * 2. Redistributions in binary form must reproduce the above copyright 17151497Sru * notice, this list of conditions and the following disclaimer in the 18151497Sru * documentation and/or other materials provided with the distribution. 19151497Sru * 3. Neither the name of the University nor the names of its contributors 20151497Sru * may be used to endorse or promote products derived from this software 21151497Sru * without specific prior written permission. 22151497Sru * 23151497Sru * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24151497Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25151497Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26151497Sru * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27151497Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28151497Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29151497Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30151497Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31151497Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32151497Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33151497Sru * SUCH DAMAGE. 34151497Sru * 35151497Sru * 36151497Sru * File: am-utils/conf/transp/transp_sockets.c 37151497Sru * 38151497Sru * Socket specific utilities. 39151497Sru * -Erez Zadok <ezk@cs.columbia.edu> 40151497Sru */ 41151497Sru 42151497Sru#ifdef HAVE_CONFIG_H 43151497Sru# include <config.h> 44151497Sru#endif /* HAVE_CONFIG_H */ 45151497Sru#include <am_defs.h> 46151497Sru#include <amu.h> 47151497Sru 48151497Sru 49151497Sru/* 50151497Sru * find the IP address that can be used to connect to the local host 51151497Sru */ 52151497Sruvoid 53151497Sruamu_get_myaddress(struct in_addr *iap, const char *preferred_localhost) 54151497Sru{ 55151497Sru struct hostent *hp; 56151497Sru char dq[20]; 57151497Sru 58151497Sru#ifdef DEBUG_off 59151497Sru#error this code is old and probably not useful any longer. 60151497Sru#error Erez, Jan 21, 2004. 61151497Sru struct sockaddr_in sin; 62151497Sru 63151497Sru /* 64151497Sru * Most modern systems should use 127.0.0.1 as the localhost address over 65151497Sru * which you can do NFS mounts. In the past we found that some NFS 66151497Sru * clients may not allow mounts from localhost. So we used 67151497Sru * get_myaddress() and that seemed to work. Alas, on some other systems, 68151497Sru * get_myaddress() may return one of the interface addresses at random, 69151497Sru * and thus use a less efficient IP address than 127.0.0.1. The solution 70151497Sru * is to hard-code 127.0.0.1, but still check if get_myaddress() returns a 71151497Sru * different value and warn about it. 72151497Sru */ 73151497Sru memset((char *) &sin, 0, sizeof(sin)); 74151497Sru get_myaddress(&sin); 75151497Sru if (sin.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) 76151497Sru dlog("amu_get_myaddress: myaddress conflict (0x%x vs. 0x%lx)", 77151497Sru sin.sin_addr.s_addr, (u_long) htonl(INADDR_LOOPBACK)); 78151497Sru#endif /* DEBUG_off */ 79151497Sru 80151497Sru if (preferred_localhost == NULL) 81151497Sru goto out; 82151497Sru 83151497Sru /* if specified preferred locahost, then try to use it */ 84151497Sru hp = gethostbyname(preferred_localhost); 85151497Sru if (hp == NULL) { 86151497Sru /* XXX: if hstrerror()/h_errno aren't portable, then need to port the next statement */ 87151497Sru plog(XLOG_ERROR, "Unable to resolve localhost_address \"%s\" (%s): using default", 88151497Sru preferred_localhost, hstrerror(h_errno)); 89151497Sru goto out; 90151497Sru } 91151497Sru if (hp->h_addr_list == NULL) { 92151497Sru plog(XLOG_ERROR, "localhost_address \"%s\" has no IP addresses: using default", 93151497Sru preferred_localhost); 94151497Sru goto out; 95151497Sru } 96151497Sru if (hp->h_addr_list[1] != NULL) { 97151497Sru plog(XLOG_ERROR, "localhost_address \"%s\" has more than one IP addresses: using first", 98151497Sru preferred_localhost); 99151497Sru goto out; 100151497Sru } 101151497Sru memmove((voidp) &iap->s_addr, (voidp) hp->h_addr_list[0], sizeof(iap->s_addr)); 102151497Sru plog(XLOG_INFO, "localhost_address \"%s\" requested, using %s", 103151497Sru preferred_localhost, inet_dquad(dq, sizeof(dq), iap->s_addr)); 104151497Sru return; 105151497Sru 106151497Sru out: 107151497Sru iap->s_addr = htonl(INADDR_LOOPBACK); 108151497Sru} 109151497Sru 110151497Sru 111151497Sru/* 112151497Sru * How to bind to reserved ports. 113151497Sru * Note: if *pp is non-null and is greater than 0, then *pp will not be modified. 114151497Sru */ 115151497Sruint 116151497Srubind_resv_port(int so, u_short *pp) 117151497Sru{ 118151497Sru struct sockaddr_in sin; 119151497Sru int rc; 120151497Sru u_short port; 121151497Sru 122151497Sru memset((voidp) &sin, 0, sizeof(sin)); 123151497Sru sin.sin_family = AF_INET; 124151497Sru 125151497Sru if (pp && *pp > 0) { 126151497Sru sin.sin_port = htons(*pp); 127151497Sru rc = bind(so, (struct sockaddr *) &sin, sizeof(sin)); 128151497Sru } else { 129151497Sru port = IPPORT_RESERVED; 130151497Sru 131151497Sru do { 132151497Sru --port; 133151497Sru sin.sin_port = htons(port); 134151497Sru rc = bind(so, (struct sockaddr *) &sin, sizeof(sin)); 135151497Sru } while (rc < 0 && (int) port > IPPORT_RESERVED / 2); 136151497Sru 137151497Sru if (pp && rc == 0) 138151497Sru *pp = port; 139151497Sru } 140151497Sru 141151497Sru return rc; 142151497Sru} 143151497Sru 144151497Sru 145151497Sru/* 146151497Sru * close a descriptor, Sockets style 147151497Sru */ 148151497Sruint 149151497Sruamu_close(int fd) 150151497Sru{ 151151497Sru return close(fd); 152151497Sru} 153151497Sru 154151497Sru 155151497Sru/* 156151497Sru * Create an rpc client attached to the mount daemon. 157151497Sru */ 158151497SruCLIENT * 159151497Sruget_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, int *sock, u_long mnt_version) 160151497Sru{ 161151497Sru CLIENT *client; 162151497Sru 163151497Sru /* 164151497Sru * First try a TCP socket 165151497Sru */ 166151497Sru if ((*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0) { 167151497Sru /* 168151497Sru * Bind to a privileged port 169151497Sru */ 170151497Sru if (bind_resv_port(*sock, (u_short *) NULL) < 0) 171151497Sru plog(XLOG_ERROR, "can't bind privileged port (socket)"); 172151497Sru 173151497Sru /* 174151497Sru * Find mountd port to connect to. 175151497Sru * Connect to mountd. 176151497Sru * Create a tcp client. 177151497Sru */ 178151497Sru if ((sin->sin_port = htons(pmap_getport(sin, MOUNTPROG, mnt_version, IPPROTO_TCP))) != 0) { 179151497Sru if (connect(*sock, (struct sockaddr *) sin, sizeof(*sin)) >= 0 180151497Sru && ((client = clnttcp_create(sin, MOUNTPROG, mnt_version, sock, 0, 0)) != NULL)) 181151497Sru return client; 182151497Sru } 183151497Sru /* 184151497Sru * Failed so close socket 185151497Sru */ 186151497Sru (void) close(*sock); 187151497Sru } /* tcp socket opened */ 188151497Sru /* TCP failed so try UDP */ 189151497Sru if ((*sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 190151497Sru plog(XLOG_ERROR, "Can't create socket to connect to mountd: %m"); 191151497Sru *sock = RPC_ANYSOCK; 192151497Sru return NULL; 193151497Sru } 194151497Sru /* 195151497Sru * Bind to a privileged port 196151497Sru */ 197151497Sru if (bind_resv_port(*sock, (u_short *) NULL) < 0) 198151497Sru plog(XLOG_ERROR, "can't bind privileged port"); 199151497Sru 200151497Sru /* 201151497Sru * Zero out the port - make sure we recompute 202151497Sru */ 203151497Sru sin->sin_port = 0; 204151497Sru 205151497Sru /* 206151497Sru * Make a UDP client 207151497Sru */ 208151497Sru if ((client = clntudp_create(sin, MOUNTPROG, mnt_version, *tv, sock)) == NULL) { 209151497Sru (void) close(*sock); 210151497Sru *sock = RPC_ANYSOCK; 211151497Sru return NULL; 212151497Sru } 213151497Sru dlog("get_mount_client: Using udp, port %d", sin->sin_port); 214151497Sru return client; 215151497Sru} 216151497Sru 217151497Sru 218151497Sru/* 219151497Sru * find the address of the caller of an RPC procedure. 220151497Sru */ 221151497Srustruct sockaddr_in * 222151497Sruamu_svc_getcaller(SVCXPRT *xprt) 223151497Sru{ 224151497Sru /* glibc 2.2 returns a sockaddr_storage ??? */ 225151497Sru return (struct sockaddr_in *) svc_getcaller(xprt); 226151497Sru} 227151497Sru 228151497Sru 229151497Sru/* 230151497Sru * Register an RPC server: 231151497Sru * return 1 on success, 0 otherwise. 232151497Sru */ 233151497Sruint 234151497Sruamu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum, 235151497Sru void (*dispatch)(struct svc_req *rqstp, SVCXPRT *transp), 236151497Sru u_long protocol, struct netconfig *dummy) 237151497Sru{ 238151497Sru /* on Sockets: svc_register returns 1 on success, 0 otherwise */ 239151497Sru return svc_register(xprt, prognum, versnum, dispatch, protocol); 240151497Sru} 241151497Sru 242151497Sru 243151497Sru/* 244151497Sru * Create the nfs service for amd 245151497Sru */ 246151497Sruint 247151497Srucreate_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version) 248151497Sru{ 249151497Sru *soNFSp = socket(AF_INET, SOCK_DGRAM, 0); 250151497Sru 251151497Sru if (*soNFSp < 0 || bind_resv_port(*soNFSp, nfs_portp) < 0) { 252151497Sru plog(XLOG_FATAL, "Can't create privileged nfs port (socket)"); 253151497Sru if (*soNFSp >= 0) 254151497Sru close(*soNFSp); 255151497Sru return 1; 256151497Sru } 257151497Sru if ((*nfs_xprtp = svcudp_create(*soNFSp)) == NULL) { 258151497Sru plog(XLOG_FATAL, "cannot create rpc/udp service"); 259151497Sru close(*soNFSp); 260151497Sru return 2; 261151497Sru } 262151497Sru if ((*nfs_portp = (*nfs_xprtp)->xp_port) >= IPPORT_RESERVED) { 263151497Sru plog(XLOG_FATAL, "Can't create privileged nfs port"); 264151497Sru svc_destroy(*nfs_xprtp); 265151497Sru close(*soNFSp); 266151497Sru return 1; 267151497Sru } 268151497Sru if (!svc_register(*nfs_xprtp, NFS_PROGRAM, nfs_version, dispatch_fxn, 0)) { 269151497Sru plog(XLOG_FATAL, "unable to register (%lu, %lu, 0)", 270151497Sru (u_long) NFS_PROGRAM, nfs_version); 271151497Sru svc_destroy(*nfs_xprtp); 272151497Sru close(*soNFSp); 273151497Sru return 3; 274151497Sru } 275151497Sru 276151497Sru return 0; /* all is well */ 277151497Sru} 278151497Sru 279151497Sru 280151497Sru/* 281151497Sru * Create the amq service for amd (both TCP and UDP) 282151497Sru */ 283151497Sruint 284151497Srucreate_amq_service(int *udp_soAMQp, 285151497Sru SVCXPRT **udp_amqpp, 286151497Sru struct netconfig **dummy1, 287151497Sru int *tcp_soAMQp, 288151497Sru SVCXPRT **tcp_amqpp, 289151497Sru struct netconfig **dummy2, 290151497Sru u_short preferred_amq_port) 291151497Sru{ 292151497Sru /* first create TCP service */ 293151497Sru if (tcp_soAMQp) { 294151497Sru *tcp_soAMQp = socket(AF_INET, SOCK_STREAM, 0); 295151497Sru if (*tcp_soAMQp < 0) { 296151497Sru plog(XLOG_FATAL, "cannot create tcp socket for amq service: %m"); 297151497Sru return 1; 298151497Sru } 299151497Sru 300151497Sru /* next, bind to a specific (TCP) port if asked for */ 301151497Sru if (preferred_amq_port > 0) { 302151497Sru /* 303151497Sru * Note: if &preferred_amq_port is non-null and is greater than 0, 304151497Sru * then the pointer will not be modified. We don't want it to be 305151497Sru * modified because it was passed down to create_amq_service as a 306151497Sru * non-pointer (a variable on the stack, not to be modified!) 307151497Sru */ 308151497Sru if (bind_resv_port(*tcp_soAMQp, &preferred_amq_port) < 0) { 309151497Sru plog(XLOG_FATAL, "can't bind amq service to requested TCP port %d: %m)", preferred_amq_port); 310151497Sru return 1; 311151497Sru } 312151497Sru } 313151497Sru 314151497Sru /* now create RPC service handle for amq */ 315151497Sru if (tcp_amqpp && 316151497Sru (*tcp_amqpp = svctcp_create(*tcp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) { 317151497Sru plog(XLOG_FATAL, "cannot create tcp service for amq: soAMQp=%d", *tcp_soAMQp); 318151497Sru return 1; 319151497Sru } 320151497Sru 321151497Sru#ifdef SVCSET_CONNMAXREC 322151497Sru /* 323151497Sru * This is *BSD at its best. 324151497Sru * They just had to do things differently than everyone else 325151497Sru * so they fixed a library DoS issue by forcing client-side changes... 326151497Sru */ 327151497Sru# ifndef RPC_MAXDATASIZE 328151497Sru# define RPC_MAXDATASIZE 9000 329151497Sru# endif /* not RPC_MAXDATASIZE */ 330151497Sru if (tcp_amqpp) { 331151497Sru int maxrec = RPC_MAXDATASIZE; 332151497Sru SVC_CONTROL(*tcp_amqpp, SVCSET_CONNMAXREC, &maxrec); 333151497Sru } 334151497Sru#endif /* not SVCSET_CONNMAXREC */ 335151497Sru } 336151497Sru 337151497Sru /* next create UDP service */ 338151497Sru if (udp_soAMQp) { 339151497Sru *udp_soAMQp = socket(AF_INET, SOCK_DGRAM, 0); 340151497Sru if (*udp_soAMQp < 0) { 341151497Sru plog(XLOG_FATAL, "cannot create udp socket for amq service: %m"); 342151497Sru return 1; 343151497Sru } 344151497Sru 345151497Sru /* next, bind to a specific (UDP) port if asked for */ 346151497Sru if (preferred_amq_port > 0) { 347151497Sru /* 348151497Sru * Note: see comment about using &preferred_amq_port above in this 349151497Sru * function. 350151497Sru */ 351151497Sru if (bind_resv_port(*udp_soAMQp, &preferred_amq_port) < 0) { 352151497Sru plog(XLOG_FATAL, "can't bind amq service to requested UDP port %d: %m)", preferred_amq_port); 353151497Sru return 1; 354151497Sru } 355151497Sru } 356151497Sru 357151497Sru /* now create RPC service handle for amq */ 358151497Sru if (udp_amqpp && 359151497Sru (*udp_amqpp = svcudp_bufcreate(*udp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) { 360151497Sru plog(XLOG_FATAL, "cannot create udp service for amq: soAMQp=%d", *udp_soAMQp); 361151497Sru return 1; 362151497Sru } 363151497Sru } 364151497Sru 365151497Sru return 0; /* all is well */ 366151497Sru} 367151497Sru 368151497Sru 369151497Sru/* 370151497Sru * Check if the portmapper is running and reachable: 0==down, 1==up 371151497Sru */ 372151497Sruint check_pmap_up(char *host, struct sockaddr_in* sin) 373151497Sru{ 374151497Sru CLIENT *client; 375151497Sru enum clnt_stat clnt_stat = RPC_TIMEDOUT; /* assume failure */ 376151497Sru int socket = RPC_ANYSOCK; 377151497Sru struct timeval timeout; 378151497Sru 379151497Sru timeout.tv_sec = 2; 380151497Sru timeout.tv_usec = 0; 381151497Sru sin->sin_port = htons(PMAPPORT); 382151497Sru client = clntudp_create(sin, PMAPPROG, PMAPVERS, timeout, &socket); 383151497Sru 384151497Sru if (client == (CLIENT *) NULL) { 385151497Sru plog(XLOG_ERROR, 386151497Sru "%s: cannot create connection to contact portmapper on host \"%s\"%s", 387151497Sru __func__, host, clnt_spcreateerror("")); 388151497Sru return 0; 389151497Sru } 390151497Sru 391151497Sru timeout.tv_sec = 6; 392151497Sru /* Ping the portmapper on a remote system by calling the nullproc */ 393151497Sru clnt_stat = clnt_call(client, 394151497Sru PMAPPROC_NULL, 395151497Sru (XDRPROC_T_TYPE) xdr_void, 396151497Sru NULL, 397151497Sru (XDRPROC_T_TYPE) xdr_void, 398151497Sru NULL, 399151497Sru timeout); 400151497Sru clnt_destroy(client); 401151497Sru close(socket); 402151497Sru sin->sin_port = 0; 403151497Sru 404151497Sru if (clnt_stat == RPC_TIMEDOUT) { 405151497Sru plog(XLOG_ERROR, 406151497Sru "%s: failed to contact portmapper on host \"%s\": %s", 407151497Sru __func__, host, clnt_sperrno(clnt_stat)); 408151497Sru return 0; 409151497Sru } 410151497Sru return 1; 411151497Sru} 412151497Sru 413151497Sru 414151497Sru/* 415151497Sru * Find the best NFS version for a host and protocol. 416151497Sru */ 417151497Sruu_long 418151497Sruget_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto, u_long def) 419151497Sru{ 420151497Sru CLIENT *clnt; 421151497Sru int again = 0; 422151497Sru enum clnt_stat clnt_stat; 423151497Sru struct timeval tv; 424151497Sru int sock; 425151497Sru char *errstr; 426151497Sru 427151497Sru /* 428151497Sru * If not set or set wrong, then try from NFS_VERS_MAX on down. If 429151497Sru * set, then try from nfs_version on down. 430151497Sru */ 431151497Sru if (!nfs_valid_version(nfs_version)) { 432151497Sru if (nfs_valid_version(def)) 433151497Sru nfs_version = def; 434151497Sru else 435151497Sru nfs_version = NFS_VERS_MAX; 436151497Sru again = 1; 437151497Sru } 438151497Sru tv.tv_sec = 2; /* retry every 2 seconds, but also timeout */ 439151497Sru tv.tv_usec = 0; 440151497Sru 441151497Sru for (; nfs_version >= NFS_VERS_MIN; nfs_version--) { 442151497Sru 443151497Sru sock = RPC_ANYSOCK; 444151497Sru errstr = NULL; 445151497Sru if (STREQ(proto, "tcp")) 446151497Sru clnt = clnttcp_create(sin, NFS_PROGRAM, nfs_version, &sock, 0, 0); 447151497Sru else if (STREQ(proto, "udp")) 448151497Sru clnt = clntudp_create(sin, NFS_PROGRAM, nfs_version, tv, &sock); 449151497Sru else 450151497Sru clnt = NULL; 451151497Sru 452151497Sru if (clnt != NULL) { 453151497Sru /* Try three times (6/2=3) to verify the CLIENT handle. */ 454151497Sru tv.tv_sec = 6; 455151497Sru clnt_stat = clnt_call(clnt, 456151497Sru NFSPROC_NULL, 457151497Sru (XDRPROC_T_TYPE) xdr_void, 458151497Sru 0, 459151497Sru (XDRPROC_T_TYPE) xdr_void, 460151497Sru 0, 461151497Sru tv); 462151497Sru 463151497Sru if (clnt_stat != RPC_SUCCESS) 464151497Sru errstr = clnt_sperrno(clnt_stat); 465151497Sru 466151497Sru close(sock); 467151497Sru clnt_destroy(clnt); 468151497Sru if (clnt_stat == RPC_SUCCESS) 469151497Sru break; 470151497Sru } else { 471151497Sru #ifdef HAVE_CLNT_SPCREATEERROR 472151497Sru errstr = clnt_spcreateerror(""); 473151497Sru #else /* not HAVE_CLNT_SPCREATEERROR */ 474151497Sru errstr = ""; 475151497Sru #endif /* not HAVE_CLNT_SPCREATEERROR */ 476151497Sru } 477151497Sru 478151497Sru if (errstr) { 479151497Sru plog(XLOG_INFO, "%s: NFS(%lu,%s) failed for %s: %s", __func__, 480151497Sru nfs_version, proto, host, errstr); 481151497Sru } 482151497Sru } 483151497Sru 484151497Sru if (nfs_version < NFS_VERS_MIN) 485151497Sru nfs_version = 0; 486151497Sru 487151497Sru plog(XLOG_INFO, "%s: returning NFS(%lu,%s) on host %s", __func__, 488151497Sru nfs_version, proto, host); 489151497Sru return nfs_version; 490151497Sru} 491151497Sru 492151497Sru 493151497Sru#if defined(HAVE_FS_AUTOFS) && defined(AUTOFS_PROG) 494151497Sru/* 495151497Sru * Register the autofs service for amd 496151497Sru */ 497151497Sruint 498151497Sruregister_autofs_service(char *autofs_conftype, void (*autofs_dispatch)(struct svc_req *rqstp, SVCXPRT *transp)) 499151497Sru{ 500151497Sru int autofs_socket; 501151497Sru SVCXPRT *autofs_xprt = NULL; 502151497Sru 503151497Sru autofs_socket = socket(AF_INET, SOCK_DGRAM, 0); 504151497Sru 505151497Sru if (autofs_socket < 0 || bind_resv_port(autofs_socket, NULL) < 0) { 506151497Sru plog(XLOG_FATAL, "Can't create privileged autofs port (socket)"); 507151497Sru return 1; 508151497Sru } 509151497Sru if ((autofs_xprt = svcudp_create(autofs_socket)) == NULL) { 510151497Sru plog(XLOG_FATAL, "Can't create autofs rpc/udp service"); 511151497Sru return 2; 512151497Sru } 513151497Sru if (autofs_xprt->xp_port >= IPPORT_RESERVED) { 514151497Sru plog(XLOG_FATAL, "Can't create privileged autofs port"); 515151497Sru return 1; 516151497Sru } 517151497Sru if (!svc_register(autofs_xprt, AUTOFS_PROG, AUTOFS_VERS, autofs_dispatch, 0)) { 518151497Sru plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)", 519151497Sru (u_long) AUTOFS_PROG, (u_long) AUTOFS_VERS); 520151497Sru return 3; 521151497Sru } 522151497Sru 523151497Sru return 0; /* all is well */ 524151497Sru} 525151497Sru 526151497Sru 527151497Sruint 528151497Sruunregister_autofs_service(char *autofs_conftype) 529151497Sru{ 530151497Sru svc_unregister(AUTOFS_PROG, AUTOFS_VERS); 531151497Sru return 0; 532151497Sru} 533151497Sru#endif /* HAVE_FS_AUTOFS && AUTOFS_PROG */ 534151497Sru