//****************************************// //*** Main Function ***// //****************************************// int main(int argn, char *argc[]) { //Server parameter is : argc[1] : Server Program Number // others arguments depend on server program int progNum = atoi(argc[1]); SVCXPRT *transp = NULL; struct netconfig *nconf; //Initialization svc_unreg(progNum, VERSNUM); if ((nconf = getnetconfigent("udp")) == NULL) { fprintf(stderr, "Cannot get netconfig entry for UDP\n"); exit(1); } transp = svc_tp_create(exm_proc, progNum, VERSNUM, nconf); if (transp == NULL) { fprintf(stderr, "Cannot create service.\n"); exit(1); } if (!svc_reg(transp, progNum, VERSNUM, exm_proc, nconf)) { fprintf(stderr, "svc_reg failed!!\n"); exit(1); } svc_run(); fprintf(stderr, "svc_run() returned. ERROR has occurred.\n"); svc_unreg(progNum, VERSNUM); return 1; }
/* * Adds a socket to the list for servicing by nfscbds. */ int nfscbd_addsock(struct file *fp) { int siz; struct socket *so; int error; SVCXPRT *xprt; so = fp->f_data; siz = sb_max_adj; error = soreserve(so, siz, siz); if (error) return (error); /* * Steal the socket from userland so that it doesn't close * unexpectedly. */ if (so->so_type == SOCK_DGRAM) xprt = svc_dg_create(nfscbd_pool, so, 0, 0); else xprt = svc_vc_create(nfscbd_pool, so, 0, 0); if (xprt) { fp->f_ops = &badfileops; fp->f_data = NULL; svc_reg(xprt, NFS_CALLBCKPROG, NFSV4_CBVERS, nfscb_program, NULL); SVC_RELEASE(xprt); } return (0); }
/* * The simple case is allowing the TI-RPC library to create a * transport itself, given just the bind address and transport * semantics. * * Our local xprt cache is ignored in this path, since the * caller is not interested in sharing listeners or ports, and * the library automatically avoids ports already in use. * * Returns the count of started listeners (one or zero). */ static unsigned int svc_create_nconf_rand_port(const char *name, const rpcprog_t program, const rpcvers_t version, void (*dispatch)(struct svc_req *, SVCXPRT *), struct netconfig *nconf) { struct t_bind bindaddr; struct addrinfo *ai; SVCXPRT *xprt; ai = svc_create_bindaddr(nconf, 0); if (ai == NULL) return 0; bindaddr.addr.buf = ai->ai_addr; bindaddr.qlen = SOMAXCONN; xprt = svc_tli_create(RPC_ANYFD, nconf, &bindaddr, 0, 0); freeaddrinfo(ai); if (xprt == NULL) { xlog(D_GENERAL, "Failed to create listener xprt " "(%s, %u, %s)", name, version, nconf->nc_netid); return 0; } if (!svc_reg(xprt, program, version, dispatch, nconf)) { /* svc_reg(3) destroys @xprt in this case */ xlog(D_GENERAL, "Failed to register (%s, %u, %s)", name, version, nconf->nc_netid); return 0; } return 1; }
void *my_thread_process(void *arg) { SVCXPRT *transp = NULL; struct netconfig *nconf = NULL; struct netbuf svcaddr; int i; if (run_mode == 1) { fprintf(stderr, "Thread %d\n", atoi(arg)); } nconf = getnetconfigent("udp"); if (nconf == (struct netconfig *)NULL) { //syslog(LOG_ERR, "getnetconfigent for udp failed"); printf("err nconf\n"); pthread_exit(1); } transp = svc_tli_create(RPC_ANYFD, nconf, (struct t_bind *)NULL, 0, 0); for (i = 0; i < callNb; i++) { svc_unreg(progNum + atoi(arg), VERSNUM); svc_reg(transp, progNum + atoi(arg), VERSNUM, exm_proc, nconf); svc_unreg(progNum + atoi(arg), VERSNUM); //If we are here, test was sucessfull thread_array_result[atoi(arg)] += 1; } pthread_exit(0); }
int main(int argc, char *argv[]) { SVCXPRT *transp; socklen_t salen; int ok; struct sockaddr_storage sa; if (argc == 2 && !strcmp(argv[1], "-n")) nodaemon = 1; if (argc != 1 && !nodaemon) usage(); if (geteuid() == 0) { struct passwd *pep = getpwnam("nobody"); if (pep) setuid(pep->pw_uid); else setuid(getuid()); } /* * See if inetd started us */ salen = sizeof(sa); if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) { from_inetd = 0; } if (!from_inetd) { if (!nodaemon) possess(); (void)rpcb_unset(WALLPROG, WALLVERS, NULL); } (void)signal(SIGCHLD, killkids); openlog("rpc.rwalld", LOG_CONS|LOG_PID, LOG_DAEMON); /* create and register the service */ if (from_inetd) { transp = svc_tli_create(0, NULL, NULL, 0, 0); if (transp == NULL) { syslog(LOG_ERR, "couldn't create udp service."); exit(1); } ok = svc_reg(transp, WALLPROG, WALLVERS, wallprog_1, NULL); } else ok = svc_create(wallprog_1, WALLPROG, WALLVERS, "udp"); if (!ok) { syslog(LOG_ERR, "unable to register (WALLPROG, WALLVERS, %s)", (!from_inetd)?"udp":"(inetd)"); exit(1); } svc_run(); syslog(LOG_ERR, "svc_run returned"); exit(1); }
/* * Register an RPC server: * return 1 on success, 0 otherwise. */ int amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum, void (*dispatch)(struct svc_req *rqstp, SVCXPRT *xprt), u_long protocol, struct netconfig *ncp) { /* on TLI: svc_reg returns 1 on success, 0 otherwise */ return svc_reg(xprt, prognum, versnum, dispatch, ncp); }
/* * Adds a socket to the list for servicing by nfsds. */ int nfsrvd_addsock(struct file *fp) { int siz; struct socket *so; int error = 0; SVCXPRT *xprt; static u_int64_t sockref = 0; so = fp->f_data; siz = sb_max_adj; error = soreserve(so, siz, siz); if (error) goto out; /* * Steal the socket from userland so that it doesn't close * unexpectedly. */ if (so->so_type == SOCK_DGRAM) xprt = svc_dg_create(nfsrvd_pool, so, 0, 0); else xprt = svc_vc_create(nfsrvd_pool, so, 0, 0); if (xprt) { fp->f_ops = &badfileops; fp->f_data = NULL; xprt->xp_sockref = ++sockref; if (nfs_minvers == NFS_VER2) svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, NULL); if (nfs_minvers <= NFS_VER3 && nfs_maxvers >= NFS_VER3) svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, NULL); if (nfs_maxvers >= NFS_VER4) svc_reg(xprt, NFS_PROG, NFS_VER4, nfssvc_program, NULL); if (so->so_type == SOCK_STREAM) svc_loss_reg(xprt, nfssvc_loss); SVC_RELEASE(xprt); } out: NFSEXITCODE(error); return (error); }
int main(int argn, char *argc[]) { //Program parameters : argc[1] : HostName or Host IP // argc[2] : Server Program Number // argc[3] : Number of testes function calls // 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 = atoi(argc[2]); SVCXPRT *transp = NULL; struct netconfig *nconf = NULL; struct netbuf svcaddr; int nbCall = atoi(argc[3]); int nbOk = 0; int i; //Initialization if (run_mode) { printf("Before creation\n"); printf("nconf : %d\n", nconf); } nconf = getnetconfigent("udp"); if (nconf == (struct netconfig *) NULL) { //syslog(LOG_ERR, "getnetconfigent for udp failed"); printf("err nconf\n"); exit(1); } transp = svc_tli_create(RPC_ANYFD, nconf, (struct t_bind *)NULL, 0, 0); svc_unreg(progNum, VERSNUM); for (i = 0; i < nbCall; i++) { svc_reg(transp, progNum, VERSNUM, exm_proc, nconf); svc_unreg(progNum, VERSNUM); } //If we are here, test has passed test_status = 0; //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; }
int main(int argc, char *argv[]) { SVCXPRT *transp; int ok; struct sockaddr_storage from; socklen_t fromlen; /* * See if inetd started us */ fromlen = sizeof(from); if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) { from_inetd = 0; } if (!from_inetd) { daemon(0, 0); (void) rpcb_unset(SPRAYPROG, SPRAYVERS, NULL); (void) signal(SIGINT, cleanup); (void) signal(SIGTERM, cleanup); (void) signal(SIGHUP, cleanup); } else { (void) signal(SIGALRM, die); alarm(TIMEOUT); } openlog("rpc.sprayd", LOG_CONS|LOG_PID, LOG_DAEMON); if (from_inetd) { transp = svc_tli_create(0, NULL, NULL, 0, 0); if (transp == NULL) { syslog(LOG_ERR, "cannot create udp service."); exit(1); } ok = svc_reg(transp, SPRAYPROG, SPRAYVERS, spray_service, NULL); } else ok = svc_create(spray_service, SPRAYPROG, SPRAYVERS, "udp"); if (!ok) { syslog(LOG_ERR, "unable to register (SPRAYPROG, SPRAYVERS, %s)", (!from_inetd)?"udp":"(inetd)"); return 1; } svc_run(); syslog(LOG_ERR, "svc_run returned"); return 1; }
/* * If a port is specified on the command line, that port value will be * the same for all listeners created here. Create each listener * socket in advance and set SO_REUSEADDR, rather than allowing the * RPC library to create the listeners for us on a randomly chosen * port via svc_tli_create(RPC_ANYFD). * * Some callers want to listen for more than one RPC version using the * same port number. For example, mountd could want to listen for MNT * version 1, 2, and 3 requests. This means mountd must use the same * set of listener sockets for multiple RPC versions, since, on one * system, you can't have two listener sockets with the exact same * bind address (and port) and transport protocol. * * To accomplish this, this function caches xprts as they are created. * This cache is checked to see if a previously created xprt can be * used, before creating a new xprt for this [program, version]. If * there is a cached xprt with the same bindaddr and transport * semantics, we simply register the new version with that xprt, * rather than creating a fresh xprt for it. * * The xprt cache implemented here is local to a process. Two * separate RPC daemons can not share a set of listeners. * * Returns the count of started listeners (one or zero). */ static unsigned int svc_create_nconf_fixed_port(const char *name, const rpcprog_t program, const rpcvers_t version, void (*dispatch)(struct svc_req *, SVCXPRT *), const uint16_t port, struct netconfig *nconf) { struct addrinfo *ai; SVCXPRT *xprt; ai = svc_create_bindaddr(nconf, port); if (ai == NULL) return 0; xprt = svc_create_find_xprt(ai->ai_addr, nconf); if (xprt == NULL) { int fd; fd = svc_create_sock(ai->ai_addr, ai->ai_addrlen, nconf); if (fd == -1) goto out_free; xprt = svc_tli_create(fd, nconf, NULL, 0, 0); if (xprt == NULL) { xlog(D_GENERAL, "Failed to create listener xprt " "(%s, %u, %s)", name, version, nconf->nc_netid); (void)close(fd); goto out_free; } } if (!svc_reg(xprt, program, version, dispatch, nconf)) { /* svc_reg(3) destroys @xprt in this case */ xlog(D_GENERAL, "Failed to register (%s, %u, %s)", name, version, nconf->nc_netid); goto out_free; } svc_create_cache_xprt(xprt); freeaddrinfo(ai); return 1; out_free: freeaddrinfo(ai); return 0; }
/* * Create the nfs service for amd * return 0 (TRUE) if OK, 1 (FALSE) if failed. */ int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version) { char *nettype = "ticlts"; nfsncp = getnetconfigent(nettype); if (nfsncp == NULL) { plog(XLOG_ERROR, "cannot getnetconfigent for %s", nettype); /* failed with ticlts, try plain udp (hpux11) */ nettype = "udp"; nfsncp = getnetconfigent(nettype); if (nfsncp == NULL) { plog(XLOG_ERROR, "cannot getnetconfigent for %s", nettype); return 1; } } *nfs_xprtp = svc_tli_create(RPC_ANYFD, nfsncp, NULL, 0, 0); if (*nfs_xprtp == NULL) { plog(XLOG_ERROR, "cannot create nfs tli service for amd"); return 1; } /* * Get the service file descriptor and check its number to see if * the t_open failed. If it succeeded, then go on to binding to a * reserved nfs port. */ *soNFSp = (*nfs_xprtp)->xp_fd; if (*soNFSp < 0 || bind_nfs_port(*soNFSp, nfs_portp) < 0) { plog(XLOG_ERROR, "Can't create privileged nfs port (TLI)"); svc_destroy(*nfs_xprtp); return 1; } if (svc_reg(*nfs_xprtp, NFS_PROGRAM, nfs_version, dispatch_fxn, NULL) != 1) { plog(XLOG_ERROR, "could not register amd NFS service"); svc_destroy(*nfs_xprtp); return 1; } return 0; /* all is well */ }
int main(int argc, char *argv[]) { pid_t pid; int i; int connmaxrec = RPC_MAXDATASIZE; /* * Set non-blocking mode and maximum record size for * connection oriented RPC transports. */ if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) { msgout("unable to set maximum RPC record size"); } /* * If stdin looks like a TLI endpoint, we assume * that we were started by a port monitor. If * t_getstate fails with TBADF, this is not a * TLI endpoint. */ if (t_getstate(0) != -1 || t_errno != TBADF) { char *netid; struct netconfig *nconf = NULL; SVCXPRT *transp; int pmclose; extern char *getenv(); _rpcpmstart = 1; openlog("rusers", LOG_PID, LOG_DAEMON); if ((netid = getenv("NLSPROVIDER")) == NULL) { #ifdef DEBUG msgout("cannot get transport name"); #endif } else if ((nconf = getnetconfigent(netid)) == NULL) { #ifdef DEBUG msgout("cannot get transport info"); #endif } if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { msgout("cannot create server handle"); exit(1); } if (nconf) freenetconfigent(nconf); if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_3, rusers_service, 0)) { msgout("unable to register (RUSERSPROG, RUSERSVERS_3)."); exit(1); } if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_IDLE, rusers_service, 0)) { msgout("unable to register (RUSERSPROG, RUSERSVERS_IDLE)."); exit(1); } (void) signal(SIGALRM, closedown); (void) alarm(_RPCSVC_CLOSEDOWN); svc_run(); msgout("svc_run returned"); exit(1); /* NOTREACHED */ } #ifndef RPC_SVC_FG pid = fork(); if (pid < 0) { perror("rpc.rusersd: cannot fork"); exit(1); } if (pid) exit(0); for (i = 0; i < 20; i++) (void) close(i); setsid(); openlog("rusers", LOG_PID, LOG_DAEMON); #endif if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_3, "netpath")) { msgout("unable to create (RUSERSPROG, RUSERSVERS_3) for netpath"); exit(1); } if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_IDLE, "netpath")) { msgout( "unable to create (RUSERSPROG, RUSERSVERS_IDLE) for netpath"); exit(1); } svc_run(); msgout("svc_run returned"); return (1); }
/* * Adds the entry into the rpcbind database. * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also * Returns 0 if succeeds, else fails */ static int init_transport(struct netconfig *nconf) { int fd; struct t_bind taddr; struct addrinfo hints, *res = NULL; struct __rpc_sockinfo si; SVCXPRT *my_xprt; int status; /* bound checking ? */ int aicode; int addrlen; struct sockaddr *sa; struct sockaddr_un sun; const int one = 1; if ((nconf->nc_semantics != NC_TPI_CLTS) && (nconf->nc_semantics != NC_TPI_COTS) && (nconf->nc_semantics != NC_TPI_COTS_ORD)) return 1; /* not my type */ #ifdef RPCBIND_DEBUG if (debugging) { int i; char **s; (void)fprintf(stderr, "%s: %ld lookup routines :\n", nconf->nc_netid, nconf->nc_nlookups); for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups; i++, s++) (void)fprintf(stderr, "[%d] - %s\n", i, *s); } #endif /* * XXX - using RPC library internal functions. */ if ((fd = __rpc_nconf2fd(nconf)) < 0) { if (errno == EAFNOSUPPORT) return 1; warn("Cannot create socket for `%s'", nconf->nc_netid); return 1; } if (!__rpc_nconf2sockinfo(nconf, &si)) { warnx("Cannot get information for `%s'", nconf->nc_netid); return 1; } if (si.si_af == AF_INET6) { /* * We're doing host-based access checks here, so don't allow * v4-in-v6 to confuse things. */ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof one) < 0) { warn("Can't make socket ipv6 only"); return 1; } } if (!strcmp(nconf->nc_netid, "local")) { (void)memset(&sun, 0, sizeof sun); sun.sun_family = AF_LOCAL; #ifdef RPCBIND_RUMP (void)rump_sys_unlink(_PATH_RPCBINDSOCK); #else (void)unlink(_PATH_RPCBINDSOCK); #endif (void)strlcpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path)); sun.sun_len = SUN_LEN(&sun); addrlen = sizeof(struct sockaddr_un); sa = (struct sockaddr *)&sun; } else { /* Get rpcbind's address on this transport */ (void)memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = si.si_af; hints.ai_socktype = si.si_socktype; hints.ai_protocol = si.si_proto; if ((aicode = getaddrinfo(NULL, servname, &hints, &res)) != 0) { warnx("Cannot get local address for `%s' (%s)", nconf->nc_netid, gai_strerror(aicode)); return 1; } addrlen = res->ai_addrlen; sa = (struct sockaddr *)res->ai_addr; } if (bind(fd, sa, addrlen) < 0) { warn("Cannot bind `%s'", nconf->nc_netid); if (res != NULL) freeaddrinfo(res); return 1; } #ifndef RPCBIND_RUMP if (sa->sa_family == AF_LOCAL) if (chmod(sun.sun_path, S_IRWXU|S_IRWXG|S_IRWXO) == -1) warn("Cannot chmod `%s'", sun.sun_path); #endif /* Copy the address */ taddr.addr.len = taddr.addr.maxlen = addrlen; taddr.addr.buf = malloc(addrlen); if (taddr.addr.buf == NULL) { warn("Cannot allocate memory for `%s' address", nconf->nc_netid); if (res != NULL) freeaddrinfo(res); return 1; } (void)memcpy(taddr.addr.buf, sa, addrlen); #ifdef RPCBIND_DEBUG if (debugging) { /* for debugging print out our universal address */ char *uaddr; struct netbuf nb; nb.buf = sa; nb.len = nb.maxlen = sa->sa_len; uaddr = taddr2uaddr(nconf, &nb); (void)fprintf(stderr, "rpcbind: my address is %s fd=%d\n", uaddr, fd); (void)free(uaddr); } #endif if (res != NULL) freeaddrinfo(res); if (nconf->nc_semantics != NC_TPI_CLTS) listen(fd, SOMAXCONN); my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE); if (my_xprt == NULL) { warnx("Could not create service for `%s'", nconf->nc_netid); goto error; } #ifdef PORTMAP /* * Register both the versions for tcp/ip, udp/ip and local. */ if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 && (strcmp(nconf->nc_proto, NC_TCP) == 0 || strcmp(nconf->nc_proto, NC_UDP) == 0)) || strcmp(nconf->nc_netid, "local") == 0) { struct pmaplist *pml; if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, pmap_service, 0)) { warn("Could not register on `%s'", nconf->nc_netid); goto error; } pml = malloc(sizeof (struct pmaplist)); if (pml == NULL) { warn("Cannot allocate memory"); goto error; } pml->pml_map.pm_prog = PMAPPROG; pml->pml_map.pm_vers = PMAPVERS; pml->pml_map.pm_port = PMAPPORT; if (strcmp(nconf->nc_proto, NC_TCP) == 0) { if (tcptrans[0]) { warnx( "Cannot have more than one TCP transport"); free(pml); goto error; } tcptrans = strdup(nconf->nc_netid); if (tcptrans == NULL) { free(pml); warn("Cannot allocate memory"); goto error; } pml->pml_map.pm_prot = IPPROTO_TCP; /* Let's snarf the universal address */ /* "h1.h2.h3.h4.p1.p2" */ tcp_uaddr = taddr2uaddr(nconf, &taddr.addr); } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) { if (udptrans[0]) { free(pml); warnx( "Cannot have more than one UDP transport"); goto error; } udptrans = strdup(nconf->nc_netid); if (udptrans == NULL) { free(pml); warn("Cannot allocate memory"); goto error; } pml->pml_map.pm_prot = IPPROTO_UDP; /* Let's snarf the universal address */ /* "h1.h2.h3.h4.p1.p2" */ udp_uaddr = taddr2uaddr(nconf, &taddr.addr); } pml->pml_next = list_pml; list_pml = pml; /* Add version 3 information */ pml = malloc(sizeof (struct pmaplist)); if (pml == NULL) { warn("Cannot allocate memory"); goto error; } pml->pml_map = list_pml->pml_map; pml->pml_map.pm_vers = RPCBVERS; pml->pml_next = list_pml; list_pml = pml; /* Add version 4 information */ pml = malloc(sizeof (struct pmaplist)); if (pml == NULL) { warn("Cannot allocate memory"); goto error; } pml->pml_map = list_pml->pml_map; pml->pml_map.pm_vers = RPCBVERS4; pml->pml_next = list_pml; list_pml = pml; /* Also add version 2 stuff to rpcbind list */ rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr); } #endif /* version 3 registration */ if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) { warn("Could not register %s version 3", nconf->nc_netid); goto error; } rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr); /* version 4 registration */ if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) { warn("Could not register %s version 4", nconf->nc_netid); goto error; } rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr); /* decide if bound checking works for this transport */ status = add_bndlist(nconf, &taddr.addr); #ifdef RPCBIND_DEBUG if (debugging) { if (status < 0) { fprintf(stderr, "Error in finding bind status for %s\n", nconf->nc_netid); } else if (status == 0) { fprintf(stderr, "check binding for %s\n", nconf->nc_netid); } else if (status > 0) { fprintf(stderr, "No check binding for %s\n", nconf->nc_netid); } } #else __USE(status); #endif /* * rmtcall only supported on CLTS transports for now. */ if (nconf->nc_semantics == NC_TPI_CLTS) { status = create_rmtcall_fd(nconf); #ifdef RPCBIND_DEBUG if (debugging) { if (status < 0) { fprintf(stderr, "Could not create rmtcall fd for %s\n", nconf->nc_netid); } else { fprintf(stderr, "rmtcall fd for %s is %d\n", nconf->nc_netid, status); } } #endif } return (0); error: #ifdef RPCBIND_RUMP (void)rump_sys_close(fd); #else (void)close(fd); #endif return (1); }
/* * Adds the entry into the rpcbind database. * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also * Returns 0 if succeeds, else fails */ static int init_transport(struct netconfig *nconf) { int fd; struct t_bind taddr; struct addrinfo hints, *res = NULL; struct __rpc_sockinfo si; SVCXPRT *my_xprt; int status; /* bound checking ? */ int aicode; int addrlen; int nhostsbak; int bound; struct sockaddr *sa; u_int32_t host_addr[4]; /* IPv4 or IPv6 */ struct sockaddr_un sun; mode_t oldmask; if ((nconf->nc_semantics != NC_TPI_CLTS) && (nconf->nc_semantics != NC_TPI_COTS) && (nconf->nc_semantics != NC_TPI_COTS_ORD)) return (1); /* not my type */ #ifdef ND_DEBUG if (debugging) { int i; char **s; (void)fprintf(stderr, "%s: %ld lookup routines :\n", nconf->nc_netid, nconf->nc_nlookups); for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups; i++, s++) fprintf(stderr, "[%d] - %s\n", i, *s); } #endif /* * XXX - using RPC library internal functions. */ if ((strcmp(nconf->nc_netid, "local") == 0) || (strcmp(nconf->nc_netid, "unix") == 0)) { /* * For other transports we call this later, for each socket we * like to bind. */ if ((fd = __rpc_nconf2fd(nconf)) < 0) { int non_fatal = 0; if (errno == EAFNOSUPPORT) non_fatal = 1; syslog(non_fatal?LOG_DEBUG:LOG_ERR, "cannot create socket for %s", nconf->nc_netid); return (1); } } if (!__rpc_nconf2sockinfo(nconf, &si)) { syslog(LOG_ERR, "cannot get information for %s", nconf->nc_netid); return (1); } if ((strcmp(nconf->nc_netid, "local") == 0) || (strcmp(nconf->nc_netid, "unix") == 0)) { memset(&sun, 0, sizeof sun); sun.sun_family = AF_LOCAL; unlink(_PATH_RPCBINDSOCK); strcpy(sun.sun_path, _PATH_RPCBINDSOCK); sun.sun_len = SUN_LEN(&sun); addrlen = sizeof (struct sockaddr_un); sa = (struct sockaddr *)&sun; } else { /* Get rpcbind's address on this transport */ memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = si.si_af; hints.ai_socktype = si.si_socktype; hints.ai_protocol = si.si_proto; } if ((strcmp(nconf->nc_netid, "local") != 0) && (strcmp(nconf->nc_netid, "unix") != 0)) { /* * If no hosts were specified, just bind to INADDR_ANY. * Otherwise make sure 127.0.0.1 is added to the list. */ nhostsbak = nhosts + 1; hosts = realloc(hosts, nhostsbak * sizeof(char *)); if (nhostsbak == 1) hosts[0] = "*"; else { if (hints.ai_family == AF_INET) { hosts[nhostsbak - 1] = "127.0.0.1"; } else if (hints.ai_family == AF_INET6) { hosts[nhostsbak - 1] = "::1"; } else return 1; } /* * Bind to specific IPs if asked to */ bound = 0; while (nhostsbak > 0) { --nhostsbak; /* * XXX - using RPC library internal functions. */ if ((fd = __rpc_nconf2fd(nconf)) < 0) { int non_fatal = 0; if (errno == EAFNOSUPPORT && nconf->nc_semantics != NC_TPI_CLTS) non_fatal = 1; syslog(non_fatal ? LOG_DEBUG : LOG_ERR, "cannot create socket for %s", nconf->nc_netid); return (1); } switch (hints.ai_family) { case AF_INET: if (inet_pton(AF_INET, hosts[nhostsbak], host_addr) == 1) { hints.ai_flags &= AI_NUMERICHOST; } else { /* * Skip if we have an AF_INET6 address. */ if (inet_pton(AF_INET6, hosts[nhostsbak], host_addr) == 1) { close(fd); continue; } } break; case AF_INET6: if (inet_pton(AF_INET6, hosts[nhostsbak], host_addr) == 1) { hints.ai_flags &= AI_NUMERICHOST; } else { /* * Skip if we have an AF_INET address. */ if (inet_pton(AF_INET, hosts[nhostsbak], host_addr) == 1) { close(fd); continue; } } if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof on) < 0) { syslog(LOG_ERR, "can't set v6-only binding for " "ipv6 socket: %m"); continue; } break; default: break; } /* * If no hosts were specified, just bind to INADDR_ANY */ if (strcmp("*", hosts[nhostsbak]) == 0) hosts[nhostsbak] = NULL; if ((strcmp(nconf->nc_netid, "local") != 0) && (strcmp(nconf->nc_netid, "unix") != 0)) { if ((aicode = getaddrinfo(hosts[nhostsbak], servname, &hints, &res)) != 0) { syslog(LOG_ERR, "cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode)); continue; } addrlen = res->ai_addrlen; sa = (struct sockaddr *)res->ai_addr; } oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); if (bind(fd, sa, addrlen) != 0) { syslog(LOG_ERR, "cannot bind %s on %s: %m", (hosts[nhostsbak] == NULL) ? "*" : hosts[nhostsbak], nconf->nc_netid); if (res != NULL) freeaddrinfo(res); continue; } else bound = 1; (void)umask(oldmask); /* Copy the address */ taddr.addr.len = taddr.addr.maxlen = addrlen; taddr.addr.buf = malloc(addrlen); if (taddr.addr.buf == NULL) { syslog(LOG_ERR, "cannot allocate memory for %s address", nconf->nc_netid); if (res != NULL) freeaddrinfo(res); return 1; } memcpy(taddr.addr.buf, sa, addrlen); #ifdef ND_DEBUG if (debugging) { /* * for debugging print out our universal * address */ char *uaddr; struct netbuf nb; nb.buf = sa; nb.len = nb.maxlen = sa->sa_len; uaddr = taddr2uaddr(nconf, &nb); (void)fprintf(stderr, "rpcbind : my address is %s\n", uaddr); (void)free(uaddr); } #endif if (nconf->nc_semantics != NC_TPI_CLTS) listen(fd, SOMAXCONN); my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE); if (my_xprt == (SVCXPRT *)NULL) { syslog(LOG_ERR, "%s: could not create service", nconf->nc_netid); goto error; } } if (!bound) return 1; } else { oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); if (bind(fd, sa, addrlen) < 0) { syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid); if (res != NULL) freeaddrinfo(res); return 1; } (void) umask(oldmask); /* Copy the address */ taddr.addr.len = taddr.addr.maxlen = addrlen; taddr.addr.buf = malloc(addrlen); if (taddr.addr.buf == NULL) { syslog(LOG_ERR, "cannot allocate memory for %s address", nconf->nc_netid); if (res != NULL) freeaddrinfo(res); return 1; } memcpy(taddr.addr.buf, sa, addrlen); #ifdef ND_DEBUG if (debugging) { /* for debugging print out our universal address */ char *uaddr; struct netbuf nb; nb.buf = sa; nb.len = nb.maxlen = sa->sa_len; uaddr = taddr2uaddr(nconf, &nb); (void) fprintf(stderr, "rpcbind : my address is %s\n", uaddr); (void) free(uaddr); } #endif if (nconf->nc_semantics != NC_TPI_CLTS) listen(fd, SOMAXCONN); my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE); if (my_xprt == (SVCXPRT *)NULL) { syslog(LOG_ERR, "%s: could not create service", nconf->nc_netid); goto error; } } #ifdef PORTMAP /* * Register both the versions for tcp/ip, udp/ip and local. */ if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 && (strcmp(nconf->nc_proto, NC_TCP) == 0 || strcmp(nconf->nc_proto, NC_UDP) == 0)) || (strcmp(nconf->nc_netid, "unix") == 0) || (strcmp(nconf->nc_netid, "local") == 0)) { struct pmaplist *pml; if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, pmap_service, 0)) { syslog(LOG_ERR, "could not register on %s", nconf->nc_netid); goto error; } pml = malloc(sizeof (struct pmaplist)); if (pml == NULL) { syslog(LOG_ERR, "no memory!"); exit(1); } pml->pml_map.pm_prog = PMAPPROG; pml->pml_map.pm_vers = PMAPVERS; pml->pml_map.pm_port = PMAPPORT; if (strcmp(nconf->nc_proto, NC_TCP) == 0) { if (tcptrans[0]) { syslog(LOG_ERR, "cannot have more than one TCP transport"); goto error; } tcptrans = strdup(nconf->nc_netid); pml->pml_map.pm_prot = IPPROTO_TCP; /* Let's snarf the universal address */ /* "h1.h2.h3.h4.p1.p2" */ tcp_uaddr = taddr2uaddr(nconf, &taddr.addr); } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) { if (udptrans[0]) { syslog(LOG_ERR, "cannot have more than one UDP transport"); goto error; } udptrans = strdup(nconf->nc_netid); pml->pml_map.pm_prot = IPPROTO_UDP; /* Let's snarf the universal address */ /* "h1.h2.h3.h4.p1.p2" */ udp_uaddr = taddr2uaddr(nconf, &taddr.addr); } else if (strcmp(nconf->nc_netid, "local") == 0) pml->pml_map.pm_prot = IPPROTO_ST; else if (strcmp(nconf->nc_netid, "unix") == 0) pml->pml_map.pm_prot = IPPROTO_ST; pml->pml_next = list_pml; list_pml = pml; /* Add version 3 information */ pml = malloc(sizeof (struct pmaplist)); if (pml == NULL) { syslog(LOG_ERR, "no memory!"); exit(1); } pml->pml_map = list_pml->pml_map; pml->pml_map.pm_vers = RPCBVERS; pml->pml_next = list_pml; list_pml = pml; /* Add version 4 information */ pml = malloc (sizeof (struct pmaplist)); if (pml == NULL) { syslog(LOG_ERR, "no memory!"); exit(1); } pml->pml_map = list_pml->pml_map; pml->pml_map.pm_vers = RPCBVERS4; pml->pml_next = list_pml; list_pml = pml; /* Also add version 2 stuff to rpcbind list */ rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr); } #endif /* version 3 registration */ if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) { syslog(LOG_ERR, "could not register %s version 3", nconf->nc_netid); goto error; } rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr); /* version 4 registration */ if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) { syslog(LOG_ERR, "could not register %s version 4", nconf->nc_netid); goto error; } rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr); /* decide if bound checking works for this transport */ status = add_bndlist(nconf, &taddr.addr); #ifdef BIND_DEBUG if (debugging) { if (status < 0) { fprintf(stderr, "Error in finding bind status for %s\n", nconf->nc_netid); } else if (status == 0) { fprintf(stderr, "check binding for %s\n", nconf->nc_netid); } else if (status > 0) { fprintf(stderr, "No check binding for %s\n", nconf->nc_netid); } } #endif /* * rmtcall only supported on CLTS transports for now. */ if (nconf->nc_semantics == NC_TPI_CLTS) { status = create_rmtcall_fd(nconf); #ifdef BIND_DEBUG if (debugging) { if (status < 0) { fprintf(stderr, "Could not create rmtcall fd for %s\n", nconf->nc_netid); } else { fprintf(stderr, "rmtcall fd for %s is %d\n", nconf->nc_netid, status); } } #endif } return (0); error: close(fd); return (1); }
int main(int argc, char *argv[]) { SVCXPRT *transp; int ok; struct sockaddr_storage from; socklen_t fromlen; if (argc == 2) closedown = atoi(argv[1]); if (closedown <= 0) closedown = 20; /* * See if inetd started us */ fromlen = sizeof(from); if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) { from_inetd = 0; } if (!from_inetd) { daemon(0, 0); (void)rpcb_unset(RSTATPROG, RSTATVERS_TIME, NULL); (void)rpcb_unset(RSTATPROG, RSTATVERS_SWTCH, NULL); (void)rpcb_unset(RSTATPROG, RSTATVERS_ORIG, NULL); (void) signal(SIGINT, cleanup); (void) signal(SIGTERM, cleanup); (void) signal(SIGHUP, cleanup); } openlog("rpc.rstatd", LOG_CONS|LOG_PID, LOG_DAEMON); if (from_inetd) { transp = svc_tli_create(0, NULL, NULL, 0, 0); if (transp == NULL) { syslog(LOG_ERR, "cannot create udp service."); exit(1); } ok = svc_reg(transp, RSTATPROG, RSTATVERS_TIME, rstat_service, NULL); } else ok = svc_create(rstat_service, RSTATPROG, RSTATVERS_TIME, "udp"); if (!ok) { syslog(LOG_ERR, "unable to register (RSTATPROG, RSTATVERS_TIME, %s)", (!from_inetd)?"udp":"(inetd)"); exit(1); } if (from_inetd) ok = svc_reg(transp, RSTATPROG, RSTATVERS_SWTCH, rstat_service, NULL); else ok = svc_create(rstat_service, RSTATPROG, RSTATVERS_SWTCH, "udp"); if (!ok) { syslog(LOG_ERR, "unable to register (RSTATPROG, RSTATVERS_SWTCH, %s)", (!from_inetd)?"udp":"(inetd)"); exit(1); } if (from_inetd) ok = svc_reg(transp, RSTATPROG, RSTATVERS_ORIG, rstat_service, NULL); else ok = svc_create(rstat_service, RSTATPROG, RSTATVERS_ORIG, "udp"); if (!ok) { syslog(LOG_ERR, "unable to register (RSTATPROG, RSTATVERS_ORIG, %s)", (!from_inetd)?"udp":"(inetd)"); exit(1); } svc_run(); syslog(LOG_ERR, "svc_run returned"); exit(1); }
/* * Create the autofs service for amd */ int create_autofs_service(void) { struct t_bind *tbp = 0; int fd = -1, err = 1; /* assume failed */ plog(XLOG_INFO, "creating autofs service listener"); autofs_ncp = getnetconfigent(autofs_conftype); if (autofs_ncp == NULL) { plog(XLOG_ERROR, "create_autofs_service: cannot getnetconfigent for %s", autofs_conftype); goto out; } fd = t_open(autofs_ncp->nc_device, O_RDWR, NULL); if (fd < 0) { plog(XLOG_ERROR, "create_autofs_service: t_open failed (%s)", t_errlist[t_errno]); goto out; } tbp = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR); if (!tbp) { plog(XLOG_ERROR, "create_autofs_service: t_alloca failed"); goto out; } if (get_autofs_address(autofs_ncp, tbp) != 0) { plog(XLOG_ERROR, "create_autofs_service: get_autofs_address failed"); goto out; } autofs_xprt = svc_tli_create(fd, autofs_ncp, tbp, 0, 0); if (autofs_xprt == NULL) { plog(XLOG_ERROR, "cannot create autofs tli service for amd"); goto out; } rpcb_unset(AUTOFS_PROG, AUTOFS_VERS, autofs_ncp); if (svc_reg(autofs_xprt, AUTOFS_PROG, AUTOFS_VERS, autofs_program_1, autofs_ncp) == FALSE) { plog(XLOG_ERROR, "could not register amd AUTOFS service"); goto out; } err = 0; goto really_out; out: if (autofs_ncp) freenetconfigent(autofs_ncp); if (autofs_xprt) SVC_DESTROY(autofs_xprt); else { if (fd > 0) t_close(fd); } really_out: if (tbp) t_free((char *) tbp, T_BIND); dlog("create_autofs_service: returning %d\n", err); return err; }
int main(int argc, char *argv[]) { pid_t pid; int c; char *progname = argv[0]; int connmaxrec = RPC_MAXDATASIZE; while ((c = getopt(argc, argv, "d")) != -1) switch ((char)c) { case 'd': debug++; break; default: (void) fprintf(stderr, "usage: %s [-d]\n", progname); exit(EXIT_FAILURE); } /* * Set non-blocking mode and maximum record size for * connection oriented RPC transports. */ if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) { msgout("unable to set maximum RPC record size"); } /* * If stdin looks like a TLI endpoint, we assume * that we were started by a port monitor. If * t_getstate fails with TBADF, this is not a * TLI endpoint. */ if (t_getstate(0) != -1 || t_errno != TBADF) { char *netid; struct netconfig *nconf = NULL; SVCXPRT *transp; int pmclose; if ((netid = getenv("NLSPROVIDER")) == NULL) { if (debug) msgout("cannot get transport name"); } else if ((nconf = getnetconfigent(netid)) == NULL) { if (debug) msgout("cannot get transport info"); } pmclose = (t_getstate(0) != T_DATAXFER); if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { msgout("cannot create server handle"); exit(EXIT_FAILURE); } if (nconf) freenetconfigent(nconf); if (!svc_reg(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, 0)) { msgout("unable to register (BOOTPARAMPROG, " "BOOTPARAMVERS)."); exit(EXIT_FAILURE); } if (pmclose) { (void) signal(SIGALRM, closedown); (void) alarm(_RPCSVC_CLOSEDOWN); } svc_run(); exit(EXIT_FAILURE); /* NOTREACHED */ } /* * run this process in the background only if it was started from * a shell and the debug flag was not given. */ if (!server_child && !debug) { pid = fork(); if (pid < 0) { perror("cannot fork"); exit(EXIT_FAILURE); } if (pid) exit(EXIT_SUCCESS); closefrom(0); (void) setsid(); } /* * messges go to syslog if the program was started by * another server, or if it was run from the command line without * the debug flag. */ if (server_child || !debug) openlog("bootparam_prot", LOG_PID, LOG_DAEMON); if (debug) { if (debug == 1) msgout("in debug mode."); else msgout("in debug mode (level %d).", debug); } if (!svc_create(bootparamprog_1, BOOTPARAMPROG, BOOTPARAMVERS, "netpath")) { msgout("unable to create (BOOTPARAMPROG, BOOTPARAMVERS) " "for netpath."); exit(EXIT_FAILURE); } svc_run(); msgout("svc_run returned"); return (EXIT_FAILURE); }
/* * register an RPC server */ int amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum, void (*dispatch)(), u_long protocol, struct netconfig *ncp) { return svc_reg(xprt, prognum, versnum, dispatch, ncp); }
/* * Called after all the create_service() calls have succeeded, to complete * the setup and registration. */ static void complete_service(struct netconfig *nconf, char *port_str) { struct addrinfo hints, *res = NULL; struct __rpc_sockinfo si; struct netbuf servaddr; SVCXPRT *transp = NULL; int aicode, fd, nhostsbak; int registered = 0; if ((nconf->nc_semantics != NC_TPI_CLTS) && (nconf->nc_semantics != NC_TPI_COTS) && (nconf->nc_semantics != NC_TPI_COTS_ORD)) return; /* not my type */ /* * XXX - using RPC library internal functions. */ if (!__rpc_nconf2sockinfo(nconf, &si)) { syslog(LOG_ERR, "cannot get information for %s", nconf->nc_netid); return; } nhostsbak = nhosts; while (nhostsbak > 0) { --nhostsbak; if (sock_fdpos >= sock_fdcnt) { /* Should never happen. */ syslog(LOG_ERR, "Ran out of socket fd's"); return; } fd = sock_fd[sock_fdpos++]; if (fd < 0) continue; if (nconf->nc_semantics != NC_TPI_CLTS) listen(fd, SOMAXCONN); transp = svc_tli_create(fd, nconf, NULL, RPC_MAXDATASIZE, RPC_MAXDATASIZE); if (transp != (SVCXPRT *) NULL) { if (!svc_register(transp, SM_PROG, SM_VERS, sm_prog_1, 0)) { syslog(LOG_ERR, "can't register on %s", nconf->nc_netid); } else { if (!svc_reg(transp, SM_PROG, SM_VERS, sm_prog_1, NULL)) syslog(LOG_ERR, "can't register %s SM_PROG service", nconf->nc_netid); } } else syslog(LOG_WARNING, "can't create %s services", nconf->nc_netid); if (registered == 0) { registered = 1; memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = si.si_af; hints.ai_socktype = si.si_socktype; hints.ai_protocol = si.si_proto; if ((aicode = getaddrinfo(NULL, port_str, &hints, &res)) != 0) { syslog(LOG_ERR, "cannot get local address: %s", gai_strerror(aicode)); exit(1); } servaddr.buf = malloc(res->ai_addrlen); memcpy(servaddr.buf, res->ai_addr, res->ai_addrlen); servaddr.len = res->ai_addrlen; rpcb_set(SM_PROG, SM_VERS, nconf, &servaddr); xcreated++; freeaddrinfo(res); } } /* end while */ }
/* * Adds the entry into the rpcbind database. * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also * Returns 0 if succeeds, else fails */ static int init_transport(struct netconfig *nconf) { int fd = -1; struct t_bind taddr; struct addrinfo hints, *res; struct __rpc_sockinfo si; SVCXPRT *my_xprt = NULL; int status; /* bound checking ? */ int aicode; int addrlen = 0; int nhostsbak; int checkbind; struct sockaddr *sa = NULL; u_int32_t host_addr[4]; /* IPv4 or IPv6 */ struct sockaddr_un sun; mode_t oldmask; res = NULL; if ((nconf->nc_semantics != NC_TPI_CLTS) && (nconf->nc_semantics != NC_TPI_COTS) && (nconf->nc_semantics != NC_TPI_COTS_ORD)) return (1); /* not my type */ #ifdef RPCBIND_DEBUG if (debugging) { int i; char **s; (void) fprintf(stderr, "%s: %ld lookup routines :\n", nconf->nc_netid, nconf->nc_nlookups); for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups; i++, s++) fprintf(stderr, "[%d] - %s\n", i, *s); } #endif /* * XXX - using RPC library internal functions. For NC_TPI_CLTS * we call this later, for each socket we like to bind. */ if (nconf->nc_semantics != NC_TPI_CLTS) { if ((fd = __rpc_nconf2fd(nconf)) < 0) { syslog(LOG_ERR, "cannot create socket for %s", nconf->nc_netid); return (1); } } if (!__rpc_nconf2sockinfo(nconf, &si)) { syslog(LOG_ERR, "cannot get information for %s", nconf->nc_netid); return (1); } if ((strcmp(nconf->nc_netid, "local") == 0) || (strcmp(nconf->nc_netid, "unix") == 0)) { memset(&sun, 0, sizeof sun); sun.sun_family = AF_LOCAL; unlink(_PATH_RPCBINDSOCK); strcpy(sun.sun_path, _PATH_RPCBINDSOCK); addrlen = SUN_LEN(&sun); sa = (struct sockaddr *)&sun; } else { /* Get rpcbind's address on this transport */ memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = si.si_af; hints.ai_socktype = si.si_socktype; hints.ai_protocol = si.si_proto; } if (nconf->nc_semantics == NC_TPI_CLTS) { /* * If no hosts were specified, just bind to INADDR_ANY. Otherwise * make sure 127.0.0.1 is added to the list. */ nhostsbak = nhosts; nhostsbak++; hosts = realloc(hosts, nhostsbak * sizeof(char *)); if (nhostsbak == 1) hosts[0] = "*"; else { if (hints.ai_family == AF_INET) { hosts[nhostsbak - 1] = "127.0.0.1"; } else if (hints.ai_family == AF_INET6) { hosts[nhostsbak - 1] = "::1"; } else return 1; } /* * Bind to specific IPs if asked to */ checkbind = 0; while (nhostsbak > 0) { --nhostsbak; /* * XXX - using RPC library internal functions. */ if ((fd = __rpc_nconf2fd(nconf)) < 0) { syslog(LOG_ERR, "cannot create socket for %s", nconf->nc_netid); return (1); } switch (hints.ai_family) { case AF_INET: if (inet_pton(AF_INET, hosts[nhostsbak], host_addr) == 1) { hints.ai_flags &= AI_NUMERICHOST; } else { /* * Skip if we have an AF_INET6 adress. */ if (inet_pton(AF_INET6, hosts[nhostsbak], host_addr) == 1) continue; } break; case AF_INET6: if (inet_pton(AF_INET6, hosts[nhostsbak], host_addr) == 1) { hints.ai_flags &= AI_NUMERICHOST; } else { /* * Skip if we have an AF_INET adress. */ if (inet_pton(AF_INET, hosts[nhostsbak], host_addr) == 1) continue; } break; default: break; } /* * If no hosts were specified, just bind to INADDR_ANY */ if (strcmp("*", hosts[nhostsbak]) == 0) hosts[nhostsbak] = NULL; if ((aicode = getaddrinfo(hosts[nhostsbak], servname, &hints, &res)) != 0) { if ((aicode = getaddrinfo(hosts[nhostsbak], "portmapper", &hints, &res)) != 0) { syslog(LOG_ERR, "cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode)); continue; } } addrlen = res->ai_addrlen; sa = (struct sockaddr *)res->ai_addr; oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); if (bind(fd, sa, addrlen) != 0) { syslog(LOG_ERR, "cannot bind %s on %s: %m", (hosts[nhostsbak] == NULL) ? "*" : hosts[nhostsbak], nconf->nc_netid); if (res != NULL) freeaddrinfo(res); continue; } else checkbind++; (void) umask(oldmask); /* Copy the address */ taddr.addr.maxlen = taddr.addr.len = addrlen; taddr.addr.buf = malloc(addrlen); if (taddr.addr.buf == NULL) { syslog(LOG_ERR, "cannot allocate memory for %s address", nconf->nc_netid); if (res != NULL) freeaddrinfo(res); return 1; } memcpy(taddr.addr.buf, sa, addrlen); #ifdef RPCBIND_DEBUG if (debugging) { /* * for debugging print out our universal * address */ char *uaddr; struct netbuf nb; int sa_size = 0; nb.buf = sa; switch( sa->sa_family){ case AF_INET: sa_size = sizeof (struct sockaddr_in); break; case AF_INET6: sa_size = sizeof (struct sockaddr_in6); break; } nb.len = nb.maxlen = sa_size; uaddr = taddr2uaddr(nconf, &nb); (void) fprintf(stderr, "rpcbind : my address is %s\n", uaddr); (void) free(uaddr); } #endif my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE); if (my_xprt == (SVCXPRT *)NULL) { syslog(LOG_ERR, "%s: could not create service", nconf->nc_netid); goto error; } } if (!checkbind) return 1; } else { /* NC_TPI_COTS */ if ((strcmp(nconf->nc_netid, "local") != 0) && (strcmp(nconf->nc_netid, "unix") != 0)) { if ((aicode = getaddrinfo(NULL, servname, &hints, &res))!= 0) { if ((aicode = getaddrinfo(NULL, "portmapper", &hints, &res))!= 0) { printf("cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode)); syslog(LOG_ERR, "cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode)); return 1; } } addrlen = res->ai_addrlen; sa = (struct sockaddr *)res->ai_addr; } oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); __rpc_fd2sockinfo(fd, &si); if (bind(fd, sa, addrlen) < 0) { syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid); if (res != NULL) freeaddrinfo(res); return 1; } (void) umask(oldmask); /* Copy the address */ taddr.addr.len = taddr.addr.maxlen = addrlen; taddr.addr.buf = malloc(addrlen); if (taddr.addr.buf == NULL) { syslog(LOG_ERR, "cannot allocate memory for %s address", nconf->nc_netid); if (res != NULL) freeaddrinfo(res); return 1; } memcpy(taddr.addr.buf, sa, addrlen); #ifdef RPCBIND_DEBUG if (debugging) { /* for debugging print out our universal address */ char *uaddr; struct netbuf nb; int sa_size2 = 0; nb.buf = sa; switch( sa->sa_family){ case AF_INET: sa_size2 = sizeof (struct sockaddr_in); break; case AF_INET6: sa_size2 = sizeof (struct sockaddr_in6); break; } nb.len = nb.maxlen = sa_size2; uaddr = taddr2uaddr(nconf, &nb); (void) fprintf(stderr, "rpcbind : my address is %s\n", uaddr); (void) free(uaddr); } #endif listen(fd, SOMAXCONN); my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE); if (my_xprt == (SVCXPRT *)NULL) { syslog(LOG_ERR, "%s: could not create service", nconf->nc_netid); goto error; } } #ifdef PORTMAP /* * Register both the versions for tcp/ip, udp/ip. */ if (si.si_af == AF_INET && (si.si_proto == IPPROTO_TCP || si.si_proto == IPPROTO_UDP)) { struct pmaplist *pml; pml = malloc(sizeof (struct pmaplist)); if (pml == NULL) { syslog(LOG_ERR, "no memory!"); exit(1); } pml->pml_map.pm_prog = PMAPPROG; pml->pml_map.pm_vers = PMAPVERS; pml->pml_map.pm_port = PMAPPORT; pml->pml_map.pm_prot = si.si_proto; switch (si.si_proto) { case IPPROTO_TCP: tcptrans = strdup(nconf->nc_netid); break; case IPPROTO_UDP: udptrans = strdup(nconf->nc_netid); break; } pml->pml_next = list_pml; list_pml = pml; /* Add version 3 information */ pml = malloc(sizeof (struct pmaplist)); if (pml == NULL) { syslog(LOG_ERR, "no memory!"); exit(1); } pml->pml_map = list_pml->pml_map; pml->pml_map.pm_vers = RPCBVERS; pml->pml_next = list_pml; list_pml = pml; /* Add version 4 information */ pml = malloc (sizeof (struct pmaplist)); if (pml == NULL) { syslog(LOG_ERR, "no memory!"); exit(1); } pml->pml_map = list_pml->pml_map; pml->pml_map.pm_vers = RPCBVERS4; pml->pml_next = list_pml; list_pml = pml; /* Also add version 2 stuff to rpcbind list */ rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr); } /* We need to support portmap over IPv4. It makes sense to * support it over AF_LOCAL as well, because that allows * rpcbind to identify the owner of a socket much better * than by relying on privileged ports to tell root from * non-root users. */ if (si.si_af == AF_INET || si.si_af == AF_LOCAL) { if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, pmap_service, 0)) { syslog(LOG_ERR, "could not register on %s", nconf->nc_netid); goto error; } } #endif /* version 3 registration */ if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) { syslog(LOG_ERR, "could not register %s version 3", nconf->nc_netid); goto error; } rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr); /* version 4 registration */ if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) { syslog(LOG_ERR, "could not register %s version 4", nconf->nc_netid); goto error; } rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr); /* decide if bound checking works for this transport */ status = add_bndlist(nconf, &taddr.addr); #ifdef RPCBIND_DEBUG if (debugging) { if (status < 0) { fprintf(stderr, "Error in finding bind status for %s\n", nconf->nc_netid); } else if (status == 0) { fprintf(stderr, "check binding for %s\n", nconf->nc_netid); } else if (status > 0) { fprintf(stderr, "No check binding for %s\n", nconf->nc_netid); } } #endif /* * rmtcall only supported on CLTS transports for now. */ if (nconf->nc_semantics == NC_TPI_CLTS) { status = create_rmtcall_fd(nconf); #ifdef RPCBIND_DEBUG if (debugging) { if (status < 0) { fprintf(stderr, "Could not create rmtcall fd for %s\n", nconf->nc_netid); } else { fprintf(stderr, "rmtcall fd for %s is %d\n", nconf->nc_netid, status); } } #endif } return (0); error: close(fd); return (1); }
/*ARGSUSED*/ int main(int argc, char *argv[]) { register SVCXPRT *transp; load_libzfs(); /* * If stdin looks like a TLI endpoint, we assume * that we were started by a port monitor. If * t_getstate fails with TBADF, this is not a * TLI endpoint. */ if (t_getstate(0) != -1 || t_errno != TBADF) { char *netid; struct netconfig *nconf = NULL; openlog("rquotad", LOG_PID, LOG_DAEMON); if ((netid = getenv("NLSPROVIDER")) == NULL) { struct t_info tinfo; if (t_sync(0) == -1) { syslog(LOG_ERR, "could not do t_sync"); zexit(1); } if (t_getinfo(0, &tinfo) == -1) { syslog(LOG_ERR, "t_getinfo failed"); zexit(1); } if (tinfo.servtype == T_CLTS) { if (tinfo.addr == INET_ADDRSTRLEN) netid = "udp"; else netid = "udp6"; } else { syslog(LOG_ERR, "wrong transport"); zexit(1); } } if ((nconf = getnetconfigent(netid)) == NULL) { syslog(LOG_ERR, "cannot get transport info"); } if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { syslog(LOG_ERR, "cannot create server handle"); zexit(1); } if (nconf) freenetconfigent(nconf); if (!svc_reg(transp, RQUOTAPROG, RQUOTAVERS, dispatch, 0)) { syslog(LOG_ERR, "unable to register (RQUOTAPROG, RQUOTAVERS)."); zexit(1); } (void) sigset(SIGALRM, (void(*)(int)) closedown); (void) alarm(RPCSVC_CLOSEDOWN); svc_run(); zexit(1); /* NOTREACHED */ } /* * Started from a shell - fork the daemon. */ switch (fork()) { case 0: /* child */ break; case -1: perror("rquotad: can't fork"); zexit(1); default: /* parent */ zexit(0); } /* * Close existing file descriptors, open "/dev/null" as * standard input, output, and error, and detach from * controlling terminal. */ closefrom(0); (void) open("/dev/null", O_RDONLY); (void) open("/dev/null", O_WRONLY); (void) dup(1); (void) setsid(); openlog("rquotad", LOG_PID, LOG_DAEMON); /* * Create datagram service */ if (svc_create(dispatch, RQUOTAPROG, RQUOTAVERS, "datagram_v") == 0) { syslog(LOG_ERR, "couldn't register datagram_v service"); zexit(1); } /* * Start serving */ svc_run(); syslog(LOG_ERR, "Error: svc_run shouldn't have returned"); return (1); }
int main(int argc, char **argv) { int nflag = 0; int c; int warn = 0; char *path = NULL; void *localhandle; SVCXPRT *transp; struct netconfig *nconf = NULL; __key_encryptsession_pk_LOCAL = &key_encrypt_pk_2_svc_prog; __key_decryptsession_pk_LOCAL = &key_decrypt_pk_2_svc_prog; __key_gendes_LOCAL = &key_gen_1_svc_prog; while ((c = getopt(argc, argv, "ndDvp:")) != -1) switch (c) { case 'n': nflag++; break; case 'd': pk_nodefaultkeys(); break; case 'D': debugging = 1; break; case 'v': warn = 1; break; case 'p': path = optarg; break; default: usage(); } load_des(warn, path); __des_crypt_LOCAL = _my_crypt; if (svc_auth_reg(AUTH_DES, _svcauth_des) == -1) errx(1, "failed to register AUTH_DES authenticator"); if (optind != argc) { usage(); } /* * Initialize */ umask(S_IXUSR|S_IXGRP|S_IXOTH); if (geteuid() != 0) errx(1, "keyserv must be run as root"); setmodulus(HEXMODULUS); getrootkey(&masterkey, nflag); rpcb_unset(KEY_PROG, KEY_VERS, NULL); rpcb_unset(KEY_PROG, KEY_VERS2, NULL); if (svc_create(keyprogram, KEY_PROG, KEY_VERS, "netpath") == 0) { fprintf(stderr, "%s: unable to create service\n", argv[0]); exit(1); } if (svc_create(keyprogram, KEY_PROG, KEY_VERS2, "netpath") == 0) { fprintf(stderr, "%s: unable to create service\n", argv[0]); exit(1); } localhandle = setnetconfig(); while ((nconf = getnetconfig(localhandle)) != NULL) { if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) break; } if (nconf == NULL) errx(1, "getnetconfig: %s", nc_sperror()); unlink(KEYSERVSOCK); rpcb_unset(CRYPT_PROG, CRYPT_VERS, nconf); transp = svcunix_create(RPC_ANYSOCK, 0, 0, KEYSERVSOCK); if (transp == NULL) errx(1, "cannot create AF_LOCAL service"); if (!svc_reg(transp, KEY_PROG, KEY_VERS, keyprogram, nconf)) errx(1, "unable to register (KEY_PROG, KEY_VERS, unix)"); if (!svc_reg(transp, KEY_PROG, KEY_VERS2, keyprogram, nconf)) errx(1, "unable to register (KEY_PROG, KEY_VERS2, unix)"); if (!svc_reg(transp, CRYPT_PROG, CRYPT_VERS, crypt_prog_1, nconf)) errx(1, "unable to register (CRYPT_PROG, CRYPT_VERS, unix)"); endnetconfig(localhandle); umask(066); /* paranoia */ if (!debugging) { daemon(0,0); } signal(SIGPIPE, SIG_IGN); svc_run(); abort(); /* NOTREACHED */ }
/* * The highest level interface for server creation. * Copied from svc_generic.c and cmd/keyserv/key_generic.c, but adapted * to work only for TPI_CLTS semantics, and to be called only once * from kwarnd.c. Returns 1 (interface created) on success and 0 * (no interfaces created) on failure. */ int svc_create_local_service(void (*dispatch) (), /* Dispatch function */ u_long prognum, /* Program number */ u_long versnum, /* Version number */ char *nettype, /* Networktype token */ char *servname) /* name of the srvc */ { int num = 0; SVCXPRT *xprt; struct netconfig *nconf; struct t_bind *bind_addr; void *net; int fd; struct nd_hostserv ns; struct nd_addrlist *nas; if ((net = __rpc_setconf(nettype)) == 0) { (void) syslog(LOG_ERR, gettext("svc_create: could not read netconfig database")); return (0); } while (nconf = __rpc_getconf(net)) { if ((strcmp(nconf->nc_protofmly, NC_LOOPBACK)) || (nconf->nc_semantics != NC_TPI_COTS_ORD)) continue; if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) < 0) { (void) syslog(LOG_ERR, gettext("svc_create: %s: cannot open connection: %s"), nconf->nc_netid, t_errlist[t_errno]); break; } /* * Negotiate for returning the uid of the caller. * This should be done before enabling the endpoint for * service via t_bind() (called in svc_tli_create()) * so that requests to kwarnd contain the uid. */ if (__rpc_negotiate_uid(fd) != 0) { syslog(LOG_ERR, gettext("Could not negotiate for" " uid with loopback transport %s"), nconf->nc_netid); t_close(fd); break; } /* LINTED pointer alignment */ bind_addr = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR); if ((bind_addr == NULL)) { (void) t_close(fd); (void) syslog(LOG_ERR, gettext("svc_create: t_alloc failed\n")); break; } ns.h_host = HOST_SELF; ns.h_serv = servname; if (!netdir_getbyname(nconf, &ns, &nas)) { /* Copy the address */ bind_addr->addr.len = nas->n_addrs->len; (void) memcpy(bind_addr->addr.buf, nas->n_addrs->buf, (int) nas->n_addrs->len); bind_addr->qlen = 8; netdir_free((char *) nas, ND_ADDRLIST); } else { (void) syslog(LOG_ERR, gettext("svc_create: no well known " "address for %s on %s\n"), servname, nconf->nc_netid); (void) t_free((char *) bind_addr, T_BIND); bind_addr = NULL; } xprt = svc_tli_create(fd, nconf, bind_addr, 0, 0); if (bind_addr) (void) t_free((char *) bind_addr, T_BIND); if (xprt == NULL) { (void) t_close(fd); (void) syslog(LOG_ERR, gettext("svc_create: svc_tli_create failed\n")); break; } else { (void) rpcb_unset(prognum, versnum, nconf); if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) { (void) syslog(LOG_ERR, gettext("svc_create: cannot" " register %d vers %d on %s"), prognum, versnum, nconf->nc_netid); SVC_DESTROY(xprt); /* also t_closes fd */ break; } num = 1; break; } } __rpc_endconf(net); return (num); }
int rpc_reg(const rpcprog_t prognum, const rpcvers_t versnum, const rpcproc_t procnum, char *(*progname)(), const xdrproc_t inproc, const xdrproc_t outproc, const char *nettype) { struct netconfig *nconf; int done = FALSE; void *handle; extern mutex_t proglst_lock; if (procnum == NULLPROC) { (void) syslog(LOG_ERR, (const char *) "%s: %s %d", rpc_reg_msg, (const char *) "can't reassign procedure number %d", NULLPROC); return (-1); } if (nettype == NULL) nettype = "netpath"; /* The default behavior */ if ((handle = __rpc_setconf((char *)nettype)) == NULL) { (void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg, __reg_err1); return (-1); } /* VARIABLES PROTECTED BY proglst_lock: proglst */ (void) mutex_lock(&proglst_lock); while (nconf = __rpc_getconf(handle)) { struct proglst *pl; SVCXPRT *svcxprt; int madenow; uint_t recvsz; char *xdrbuf; char *netid; madenow = FALSE; svcxprt = NULL; for (pl = proglst; pl; pl = pl->p_nxt) if (strcmp(pl->p_netid, nconf->nc_netid) == 0) { svcxprt = pl->p_transp; xdrbuf = pl->p_xdrbuf; recvsz = pl->p_recvsz; netid = pl->p_netid; break; } if (svcxprt == NULL) { struct t_info tinfo; svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0); if (svcxprt == NULL) continue; if (t_getinfo(svcxprt->xp_fd, &tinfo) == -1) { char errorstr[100]; __tli_sys_strerror(errorstr, sizeof (errorstr), t_errno, errno); (void) syslog(LOG_ERR, "%s : %s : %s", rpc_reg_msg, "t_getinfo failed", errorstr); SVC_DESTROY(svcxprt); continue; } if ((recvsz = __rpc_get_t_size(0, tinfo.tsdu)) == 0) { (void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg, __reg_err3); SVC_DESTROY(svcxprt); continue; } if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) || ((netid = strdup(nconf->nc_netid)) == NULL)) { (void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg, __no_mem_str); SVC_DESTROY(svcxprt); break; } madenow = TRUE; } /* * Check if this (program, version, netid) had already been * registered. The check may save a few RPC calls to rpcbind */ for (pl = proglst; pl; pl = pl->p_nxt) if ((pl->p_prognum == prognum) && (pl->p_versnum == versnum) && (strcmp(pl->p_netid, netid) == 0)) break; if (pl == NULL) { /* Not yet */ /* * Note that if we're using a portmapper * instead of rpcbind then we can't do an * unregister operation here. * * The reason is that the portmapper unset * operation removes all the entries for a * given program/version regardelss of * transport protocol. * * The caller of this routine needs to ensure * that __pmap_unset() has been called for all * program/version service pairs they plan * to support before they start registering * each program/version/protocol triplet. */ if (!use_portmapper) (void) rpcb_unset(prognum, versnum, nconf); } else { /* so that svc_reg does not call rpcb_set() */ nconf = NULL; } if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) { (void) syslog(LOG_ERR, "%s couldn't register prog %d vers %d for %s", rpc_reg_msg, prognum, versnum, netid); if (madenow) { SVC_DESTROY(svcxprt); free(xdrbuf); free(netid); } continue; } pl = malloc(sizeof (struct proglst)); if (pl == NULL) { (void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg, __no_mem_str); if (madenow) { SVC_DESTROY(svcxprt); free(xdrbuf); free(netid); } break; } pl->p_progname = progname; pl->p_prognum = prognum; pl->p_versnum = versnum; pl->p_procnum = procnum; pl->p_inproc = inproc; pl->p_outproc = outproc; pl->p_transp = svcxprt; pl->p_xdrbuf = xdrbuf; pl->p_recvsz = recvsz; pl->p_netid = netid; pl->p_nxt = proglst; proglst = pl; done = TRUE; } __rpc_endconf(handle); (void) mutex_unlock(&proglst_lock); if (done == FALSE) { (void) syslog(LOG_ERR, (const char *) "%s cant find suitable transport for %s", rpc_reg_msg, nettype); return (-1); } return (0); }
/* * We use our own private version of svc_create() which registers our services * only on loopback transports and enables an option whereby Solaris ucreds * are associated with each connection, permitting us to check privilege bits. */ static int fmd_rpc_svc_create_local(void (*disp)(struct svc_req *, SVCXPRT *), rpcprog_t prog, rpcvers_t vers, uint_t ssz, uint_t rsz, int force) { struct netconfig *ncp; struct netbuf buf; SVCXPRT *xprt; void *hdl; int fd, n = 0; char door[PATH_MAX]; time_t tm; if ((hdl = setnetconfig()) == NULL) { fmd_error(EFMD_RPC_REG, "failed to iterate over " "netconfig database: %s\n", nc_sperror()); return (fmd_set_errno(EFMD_RPC_REG)); } if (force) svc_unreg(prog, vers); /* clear stale rpcbind registrations */ buf.buf = alloca(_SS_MAXSIZE); buf.maxlen = _SS_MAXSIZE; buf.len = 0; while ((ncp = getnetconfig(hdl)) != NULL) { if (strcmp(ncp->nc_protofmly, NC_LOOPBACK) != 0) continue; if (!force && rpcb_getaddr(prog, vers, ncp, &buf, HOST_SELF)) { (void) endnetconfig(hdl); return (fmd_set_errno(EFMD_RPC_BOUND)); } if ((fd = t_open(ncp->nc_device, O_RDWR, NULL)) == -1) { fmd_error(EFMD_RPC_REG, "failed to open %s: %s\n", ncp->nc_device, t_strerror(t_errno)); continue; } svc_fd_negotiate_ucred(fd); /* enable ucred option on xprt */ if ((xprt = svc_tli_create(fd, ncp, NULL, ssz, rsz)) == NULL) { (void) t_close(fd); continue; } if (svc_reg(xprt, prog, vers, disp, ncp) == FALSE) { fmd_error(EFMD_RPC_REG, "failed to register " "rpc service on %s\n", ncp->nc_netid); svc_destroy(xprt); continue; } n++; } (void) endnetconfig(hdl); /* * If we failed to register services (n == 0) because rpcbind is down, * then check to see if the RPC door file exists before attempting an * svc_door_create(), which cleverly destroys any existing door file. * The RPC APIs have no stable errnos, so we use rpcb_gettime() as a * hack to determine if rpcbind itself is down. */ if (!force && n == 0 && rpcb_gettime(HOST_SELF, &tm) == FALSE && snprintf(door, sizeof (door), RPC_DOOR_RENDEZVOUS, prog, vers) > 0 && access(door, F_OK) == 0) return (fmd_set_errno(EFMD_RPC_BOUND)); /* * Attempt to create a door server for the RPC program as well. Limit * the maximum request size for the door transport to the receive size. */ if ((xprt = svc_door_create(disp, prog, vers, ssz)) == NULL) { fmd_error(EFMD_RPC_REG, "failed to create door for " "rpc service 0x%lx/0x%lx\n", prog, vers); } else { (void) svc_control(xprt, SVCSET_CONNMAXREC, &rsz); n++; } return (n); }
/* * For simplified, easy to use kind of rpc interfaces. * nettype indicates the type of transport on which the service will be * listening. Used for conservation of the system resource. Only one * handle is created for all the services (actually one of each netid) * and same xdrbuf is used for same netid. The size of the arguments * is also limited by the recvsize for that transport, even if it is * a COTS transport. This may be wrong, but for cases like these, they * should not use the simplified interfaces like this. * * prognum - program number * versnum - version number * procnum - procedure number * progname - Server routine * inproc, outproc - in/out XDR procedures * nettype - nettype */ int rpc_reg(rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum, char *(*progname)(char *), xdrproc_t inproc, xdrproc_t outproc, char *nettype) { struct netconfig *nconf; int done = FALSE; void *handle; if (procnum == NULLPROC) { warnx("%s can't reassign procedure number %u", rpc_reg_msg, NULLPROC); return (-1); } if (nettype == NULL) nettype = "netpath"; /* The default behavior */ if ((handle = __rpc_setconf(nettype)) == NULL) { warnx(rpc_reg_err, rpc_reg_msg, __reg_err1); return (-1); } /* VARIABLES PROTECTED BY proglst_lock: proglst */ mutex_lock(&proglst_lock); while ((nconf = __rpc_getconf(handle)) != NULL) { struct proglst *pl; SVCXPRT *svcxprt; int madenow; u_int recvsz; char *xdrbuf; char *netid; madenow = FALSE; svcxprt = NULL; recvsz = 0; xdrbuf = netid = NULL; for (pl = proglst; pl; pl = pl->p_nxt) { if (strcmp(pl->p_netid, nconf->nc_netid) == 0) { svcxprt = pl->p_transp; xdrbuf = pl->p_xdrbuf; recvsz = pl->p_recvsz; netid = pl->p_netid; break; } } if (svcxprt == NULL) { struct __rpc_sockinfo si; svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0); if (svcxprt == NULL) continue; if (!__rpc_fd2sockinfo(svcxprt->xp_fd, &si)) { warnx(rpc_reg_err, rpc_reg_msg, __reg_err2); SVC_DESTROY(svcxprt); continue; } recvsz = __rpc_get_t_size(si.si_af, si.si_proto, 0); if (recvsz == 0) { warnx(rpc_reg_err, rpc_reg_msg, __reg_err3); SVC_DESTROY(svcxprt); continue; } if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) || ((netid = strdup(nconf->nc_netid)) == NULL)) { warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str); free(xdrbuf); free(netid); SVC_DESTROY(svcxprt); break; } madenow = TRUE; } /* * Check if this (program, version, netid) had already been * registered. The check may save a few RPC calls to rpcbind */ for (pl = proglst; pl; pl = pl->p_nxt) if ((pl->p_prognum == prognum) && (pl->p_versnum == versnum) && (strcmp(pl->p_netid, netid) == 0)) break; if (pl == NULL) { /* Not yet */ (void) rpcb_unset(prognum, versnum, nconf); } else { /* so that svc_reg does not call rpcb_set() */ nconf = NULL; } if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) { warnx("%s couldn't register prog %u vers %u for %s", rpc_reg_msg, (unsigned)prognum, (unsigned)versnum, netid); if (madenow) { SVC_DESTROY(svcxprt); free(xdrbuf); free(netid); } continue; } pl = malloc(sizeof (struct proglst)); if (pl == NULL) { warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str); if (madenow) { SVC_DESTROY(svcxprt); free(xdrbuf); free(netid); } break; } pl->p_progname = progname; pl->p_prognum = prognum; pl->p_versnum = versnum; pl->p_procnum = procnum; pl->p_inproc = inproc; pl->p_outproc = outproc; pl->p_transp = svcxprt; pl->p_xdrbuf = xdrbuf; pl->p_recvsz = recvsz; pl->p_netid = netid; pl->p_nxt = proglst; proglst = pl; done = TRUE; } __rpc_endconf(handle); mutex_unlock(&proglst_lock); if (done == FALSE) { warnx("%s can't find suitable transport for %s", rpc_reg_msg, nettype); return (-1); } return (0); }
int main(int argc, char **argv) { int ch, i, s; void *nc_handle; char *endptr, **hosts_bak; struct sigaction sigalarm; int grace_period = 30; struct netconfig *nconf; int have_v6 = 1; int maxrec = RPC_MAXDATASIZE; in_port_t svcport = 0; int attempt_cnt, port_len, port_pos, ret; char **port_list; while ((ch = getopt(argc, argv, "d:g:h:p:")) != (-1)) { switch (ch) { case 'd': debug_level = atoi(optarg); if (!debug_level) { usage(); /* NOTREACHED */ } break; case 'g': grace_period = atoi(optarg); if (!grace_period) { usage(); /* NOTREACHED */ } break; case 'h': ++nhosts; hosts_bak = hosts; hosts_bak = realloc(hosts, nhosts * sizeof(char *)); if (hosts_bak == NULL) { if (hosts != NULL) { for (i = 0; i < nhosts; i++) free(hosts[i]); free(hosts); out_of_mem(); } } hosts = hosts_bak; hosts[nhosts - 1] = strdup(optarg); if (hosts[nhosts - 1] == NULL) { for (i = 0; i < (nhosts - 1); i++) free(hosts[i]); free(hosts); out_of_mem(); } break; case 'p': endptr = NULL; svcport = (in_port_t)strtoul(optarg, &endptr, 10); if (endptr == NULL || *endptr != '\0' || svcport == 0 || svcport >= IPPORT_MAX) usage(); svcport_str = strdup(optarg); break; default: case '?': usage(); /* NOTREACHED */ } } if (geteuid()) { /* This command allowed only to root */ fprintf(stderr, "Sorry. You are not superuser\n"); exit(1); } kernel_lockd = FALSE; kernel_lockd_client = FALSE; if (modfind("nfslockd") < 0) { if (kldload("nfslockd") < 0) { fprintf(stderr, "Can't find or load kernel support for rpc.lockd - using non-kernel implementation\n"); } else { kernel_lockd = TRUE; } } else { kernel_lockd = TRUE; } if (kernel_lockd) { if (getosreldate() >= 800040) kernel_lockd_client = TRUE; } (void)rpcb_unset(NLM_PROG, NLM_SM, NULL); (void)rpcb_unset(NLM_PROG, NLM_VERS, NULL); (void)rpcb_unset(NLM_PROG, NLM_VERSX, NULL); (void)rpcb_unset(NLM_PROG, NLM_VERS4, NULL); /* * Check if IPv6 support is present. */ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (s < 0) have_v6 = 0; else close(s); rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); /* * If no hosts were specified, add a wildcard entry to bind to * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the * list. */ if (nhosts == 0) { hosts = malloc(sizeof(char**)); if (hosts == NULL) out_of_mem(); hosts[0] = "*"; nhosts = 1; } else { hosts_bak = hosts; if (have_v6) { hosts_bak = realloc(hosts, (nhosts + 2) * sizeof(char *)); if (hosts_bak == NULL) { for (i = 0; i < nhosts; i++) free(hosts[i]); free(hosts); out_of_mem(); } else hosts = hosts_bak; nhosts += 2; hosts[nhosts - 2] = "::1"; } else { hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *)); if (hosts_bak == NULL) { for (i = 0; i < nhosts; i++) free(hosts[i]); free(hosts); out_of_mem(); } else { nhosts += 1; hosts = hosts_bak; } } hosts[nhosts - 1] = "127.0.0.1"; } if (kernel_lockd) { if (!kernel_lockd_client) { /* * For the case where we have a kernel lockd but it * doesn't provide client locking, we run a cut-down * RPC service on a local-domain socket. The kernel's * RPC server will pass what it can't handle (mainly * client replies) down to us. */ struct sockaddr_un sun; int fd, oldmask; SVCXPRT *xprt; memset(&sun, 0, sizeof sun); sun.sun_family = AF_LOCAL; unlink(_PATH_RPCLOCKDSOCK); strcpy(sun.sun_path, _PATH_RPCLOCKDSOCK); sun.sun_len = SUN_LEN(&sun); fd = socket(AF_LOCAL, SOCK_STREAM, 0); if (!fd) { err(1, "Can't create local lockd socket"); } oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO); if (bind(fd, (struct sockaddr *) &sun, sun.sun_len) < 0) { err(1, "Can't bind local lockd socket"); } umask(oldmask); if (listen(fd, SOMAXCONN) < 0) { err(1, "Can't listen on local lockd socket"); } xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE); if (!xprt) { err(1, "Can't create transport for local lockd socket"); } if (!svc_reg(xprt, NLM_PROG, NLM_VERS4, nlm_prog_4, NULL)) { err(1, "Can't register service for local lockd socket"); } } /* * We need to look up the addresses so that we can * hand uaddrs (ascii encoded address+port strings) to * the kernel. */ nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { /* We want to listen only on udp6, tcp6, udp, tcp transports */ if (nconf->nc_flag & NC_VISIBLE) { /* Skip if there's no IPv6 support */ if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ } else { lookup_addresses(nconf); } } } endnetconfig(nc_handle); } else { attempt_cnt = 1; sock_fdcnt = 0; sock_fd = NULL; port_list = NULL; port_len = 0; nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { /* We want to listen only on udp6, tcp6, udp, tcp transports */ if (nconf->nc_flag & NC_VISIBLE) { /* Skip if there's no IPv6 support */ if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ } else { ret = create_service(nconf); if (ret == 1) /* Ignore this call */ continue; if (ret < 0) { /* * Failed to bind port, so close * off all sockets created and * try again if the port# was * dynamically assigned via * bind(2). */ clearout_service(); if (mallocd_svcport != 0 && attempt_cnt < GETPORT_MAXTRY) { free(svcport_str); svcport_str = NULL; mallocd_svcport = 0; } else { errno = EADDRINUSE; syslog(LOG_ERR, "bindresvport_sa: %m"); exit(1); } /* * Start over at the first * service. */ free(sock_fd); sock_fdcnt = 0; sock_fd = NULL; nc_handle = setnetconfig(); attempt_cnt++; } else if (mallocd_svcport != 0 && attempt_cnt == GETPORT_MAXTRY) { /* * For the last attempt, allow * different port #s for each * nconf by saving the * svcport_str and setting it * back to NULL. */ port_list = realloc(port_list, (port_len + 1) * sizeof(char *)); if (port_list == NULL) out_of_mem(); port_list[port_len++] = svcport_str; svcport_str = NULL; mallocd_svcport = 0; } } } } /* * Successfully bound the ports, so call complete_service() to * do the rest of the setup on the service(s). */ sock_fdpos = 0; port_pos = 0; nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { /* We want to listen only on udp6, tcp6, udp, tcp transports */ if (nconf->nc_flag & NC_VISIBLE) { /* Skip if there's no IPv6 support */ if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ } else if (port_list != NULL) { if (port_pos >= port_len) { syslog(LOG_ERR, "too many port#s"); exit(1); } complete_service(nconf, port_list[port_pos++]); } else complete_service(nconf, svcport_str); } } endnetconfig(nc_handle); free(sock_fd); if (port_list != NULL) { for (port_pos = 0; port_pos < port_len; port_pos++) free(port_list[port_pos]); free(port_list); } } /* * Note that it is NOT sensible to run this program from inetd - the * protocol assumes that it will run immediately at boot time. */ if (daemon(0, debug_level > 0)) { err(1, "cannot fork"); /* NOTREACHED */ } openlog("rpc.lockd", 0, LOG_DAEMON); if (debug_level) syslog(LOG_INFO, "Starting, debug level %d", debug_level); else syslog(LOG_INFO, "Starting"); sigalarm.sa_handler = (sig_t) sigalarm_handler; sigemptyset(&sigalarm.sa_mask); sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */ sigalarm.sa_flags |= SA_RESTART; if (sigaction(SIGALRM, &sigalarm, NULL) != 0) { syslog(LOG_WARNING, "sigaction(SIGALRM) failed: %s", strerror(errno)); exit(1); } if (kernel_lockd) { if (!kernel_lockd_client) { init_nsm(); client_pid = client_request(); /* * Create a child process to enter the kernel and then * wait for RPCs on our local domain socket. */ if (!fork()) nlm_syscall(debug_level, grace_period, naddrs, addrs); else svc_run(); } else { /* * The kernel lockd implementation provides * both client and server so we don't need to * do anything else. */ nlm_syscall(debug_level, grace_period, naddrs, addrs); } } else { grace_expired = 0; alarm(grace_period); init_nsm(); client_pid = client_request(); svc_run(); /* Should never return */ } exit(1); }