Index: Makefile =================================================================== RCS file: /home/rionda/branch/ncvs/src/usr.sbin/rpcbind/Makefile,v retrieving revision 1.8 diff -u -r1.8 Makefile --- Makefile 17 Mar 2006 18:54:43 -0000 1.8 +++ Makefile 2 Feb 2008 09:38:42 -0000 @@ -8,6 +8,8 @@ SRCS= check_bound.c rpcb_stat.c rpcb_svc_4.c rpcbind.c pmap_svc.c \ rpcb_svc.c rpcb_svc_com.c security.c warmstart.c util.c +WARNS= 3 + CFLAGS+= -DPORTMAP -DLIBWRAP .if ${MK_INET6_SUPPORT} != "no" Index: rpcb_svc_com.c =================================================================== RCS file: /home/rionda/branch/ncvs/src/usr.sbin/rpcbind/rpcb_svc_com.c,v retrieving revision 1.12 diff -u -r1.12 rpcb_svc_com.c --- rpcb_svc_com.c 7 Nov 2007 10:53:39 -0000 1.12 +++ rpcb_svc_com.c 3 Feb 2008 14:10:26 -0000 @@ -67,13 +67,6 @@ static char *nullstring = ""; static int rpcb_rmtcalls; -struct rmtcallfd_list { - int fd; - SVCXPRT *xprt; - char *netid; - struct rmtcallfd_list *next; -}; - #define NFORWARD 64 #define MAXTIME_OFF 300 /* 5 minutes */ @@ -91,6 +84,8 @@ }; static struct finfo FINFO[NFORWARD]; +extern struct rmtcallfd_list *rmthead; +extern struct rmtcallfd_list *rmttail; static bool_t xdr_encap_parms(XDR *, struct encap_parms *); static bool_t xdr_rmtcall_args(XDR *, struct r_rmtcall_args *); @@ -481,54 +476,6 @@ return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); } -static struct rmtcallfd_list *rmthead; -static struct rmtcallfd_list *rmttail; - -int -create_rmtcall_fd(struct netconfig *nconf) -{ - int fd; - struct rmtcallfd_list *rmt; - SVCXPRT *xprt; - - if ((fd = __rpc_nconf2fd(nconf)) == -1) { - if (debugging) - fprintf(stderr, - "create_rmtcall_fd: couldn't open \"%s\" (errno %d)\n", - nconf->nc_device, errno); - return (-1); - } - xprt = svc_tli_create(fd, 0, (struct t_bind *) 0, 0, 0); - if (xprt == NULL) { - if (debugging) - fprintf(stderr, - "create_rmtcall_fd: svc_tli_create failed\n"); - return (-1); - } - rmt = malloc(sizeof (struct rmtcallfd_list)); - if (rmt == NULL) { - syslog(LOG_ERR, "create_rmtcall_fd: no memory!"); - return (-1); - } - rmt->xprt = xprt; - rmt->netid = strdup(nconf->nc_netid); - xprt->xp_netid = rmt->netid; - rmt->fd = fd; - rmt->next = NULL; - if (rmthead == NULL) { - rmthead = rmt; - rmttail = rmt; - } else { - rmttail->next = rmt; - rmttail = rmt; - } - /* XXX not threadsafe */ - if (fd > svc_maxfd) - svc_maxfd = fd; - FD_SET(fd, &svc_fdset); - return (fd); -} - static int find_rmtcallfd_by_netid(char *netid) { Index: rpcbind.c =================================================================== RCS file: /home/rionda/branch/ncvs/src/usr.sbin/rpcbind/rpcbind.c,v retrieving revision 1.19 diff -u -r1.19 rpcbind.c --- rpcbind.c 7 Nov 2007 10:53:39 -0000 1.19 +++ rpcbind.c 2 Feb 2008 09:48:23 -0000 @@ -80,6 +80,8 @@ int debugging = 0; /* Tell me what's going on */ int doabort = 0; /* When debugging, do an abort on errors */ rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */ +struct rmtcallfd_list *rmthead; +struct rmtcallfd_list *rmttail; /* who to suid to if -s is given */ #define RUN_AS "daemon" @@ -92,6 +94,7 @@ int verboselog = 0; char **hosts = NULL; +char **hosts_bak = NULL; int ipv6_only = 0; int nhosts = 0; int on = 1; @@ -117,6 +120,7 @@ static int init_transport(struct netconfig *); static void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *, struct netbuf *); +int create_rmtcall_fd(struct netconfig *, struct addrinfo, char *); static void terminate(int); static void parseargs(int, char *[]); @@ -127,6 +131,7 @@ void *nc_handle; /* Net config handle */ struct rlimit rl; int maxrec = RPC_MAXDATASIZE; + int i, s, have_v6 = 1; parseargs(argc, argv); @@ -151,6 +156,60 @@ fprintf(stderr, "Sorry. You are not superuser\n"); exit(1); } + + s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (s < 0) + have_v6 = 0; + else + close(s); + + /* + * 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) { + syslog(LOG_ERR, "out of memory"); + exit(2); + } + + 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); + syslog(LOG_ERR, "out of memory"); + exit(2); + } 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); + syslog(LOG_ERR, "out of memory"); + exit(2); + } else { + nhosts += 1; + hosts = hosts_bak; + } + } + hosts[nhosts - 1] = "127.0.0.1"; + } + nc_handle = setnetconfig(); /* open netconfig file */ if (nc_handle == NULL) { syslog(LOG_ERR, "could not read /etc/netconfig"); @@ -174,12 +233,14 @@ init_transport(nconf); while ((nconf = getnetconfig(nc_handle))) { - if (nconf->nc_flag & NC_VISIBLE) - if (ipv6_only == 1 && strcmp(nconf->nc_protofmly, - "inet") == 0) { + if (nconf->nc_flag & NC_VISIBLE) { + if ((ipv6_only == 1 && strcmp(nconf->nc_protofmly, + "inet") == 0) || (have_v6 == 0 && + strcmp(nconf->nc_protofmly, "inet6") == 0)) { /* DO NOTHING */ } else init_transport(nconf); + } } endnetconfig(nc_handle); @@ -250,7 +311,6 @@ int aicode; int addrlen; int nhostsbak; - int checkbind; struct sockaddr *sa; u_int32_t host_addr[4]; /* IPv4 or IPv6 */ struct sockaddr_un sun; @@ -259,281 +319,103 @@ 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 */ + return (1); /* not my type */ #ifdef ND_DEBUG if (debugging) { - int i; - char **s; + 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); + (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 == EPROTONOSUPPORT) - non_fatal = 1; - syslog(non_fatal?LOG_DEBUG:LOG_ERR, "cannot create socket for %s", + if (!__rpc_nconf2sockinfo(nconf, &si)) { + syslog(LOG_ERR, "cannot get information 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; - 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 = 1; - while (nhostsbak > 0) { - --nhostsbak; - /* - * XXX - using RPC library internal functions. + /* + * 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 == EPROTONOSUPPORT && - 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 adress. - */ - 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 adress. - */ - 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; - } + int non_fatal = 0; + if (errno == EPROTONOSUPPORT) + non_fatal = 1; + syslog(non_fatal?LOG_DEBUG:LOG_ERR, "cannot create socket for %s", + nconf->nc_netid); + return (1); + } + 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; 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); + 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; + 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); + 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; + /* 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); } - } - if (!checkbind) - 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; - } - } + my_xprt = svc_tli_create(fd, nconf, NULL, RPC_MAXDATASIZE, + RPC_MAXDATASIZE); + if (my_xprt == 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)) { + if (!svc_reg(my_xprt, PMAPPROG, PMAPVERS, pmap_service, NULL)) { syslog(LOG_ERR, "could not register on %s", - nconf->nc_netid); + nconf->nc_netid); goto error; } + struct pmaplist *pml; + pml = malloc(sizeof (struct pmaplist)); if (pml == NULL) { syslog(LOG_ERR, "no memory!"); @@ -542,34 +424,7 @@ 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_map.pm_prot = IPPROTO_ST; pml->pml_next = list_pml; list_pml = pml; @@ -597,56 +452,323 @@ /* 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 + } 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; + /* + * Bind to specific IPs if asked to + */ + nhostsbak = nhosts; + while (nhostsbak > 0) { + nhostsbak--; - /* 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); + /* + * XXX - using RPC library internal functions. + */ + if ((fd = __rpc_nconf2fd(nconf)) < 0) { + int non_fatal = 0; + if (errno == EPROTONOSUPPORT && + 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 adress. + */ + 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 adress. + */ + 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) { + if ((aicode = getaddrinfo(NULL, servname, + &hints, &res)) != 0) { + syslog(LOG_ERR, + "cannot get local address for %s: %s", + nconf->nc_netid, + gai_strerror(aicode)); + continue; + } + } else { + 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], nconf->nc_netid); + if (res != NULL) + freeaddrinfo(res); + continue; + } else + (void)umask(oldmask); + +#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 = 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 + if (!svc_reg(my_xprt, PMAPPROG, PMAPVERS, pmap_service, NULL)) { + 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; + } + /* 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; + } + /* + * rmtcall only supported on CLTS transports for now. + */ + if (nconf->nc_semantics == NC_TPI_CLTS) { + status = create_rmtcall_fd(nconf, hints, hosts[nhostsbak]); - /* 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); + 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 + } + } /* while */ + + 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) { + syslog(LOG_ERR, "cannot get local address: %s", + gai_strerror(aicode)); + exit(1); } - } -#endif - /* - * rmtcall only supported on CLTS transports for now. - */ - if (nconf->nc_semantics == NC_TPI_CLTS) { - status = create_rmtcall_fd(nconf); + addrlen = res->ai_addrlen; + sa = (struct sockaddr *)res->ai_addr; + /* 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 PORTMAP + if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 && + (strcmp(nconf->nc_proto, NC_TCP) == 0 || + strcmp(nconf->nc_proto, NC_UDP) == 0))) { + 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; + if (strcmp(nconf->nc_proto, NC_TCP) == 0) { + if (tcptrans[0]) { + syslog(LOG_ERR, + "cannot have more than one TCP transport"); + return(1); + } + 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"); + return(1); + } + 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); + + } + 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 + /* Add version 3 stuff to rpcbind list */ + rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr); + /* Add version 4 stuff to rpcbind list */ + 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, - "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); + 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 @@ -657,6 +779,7 @@ return (1); } + static void rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf, struct netbuf *addr) @@ -678,6 +801,73 @@ list_rbl = rbl; } +int +create_rmtcall_fd(struct netconfig *nconf, struct addrinfo hints, char *host) +{ + struct addrinfo *res = NULL; + struct rmtcallfd_list *rmt; + SVCXPRT *xprt; + int aicode,fd; + + if ((fd = __rpc_nconf2fd(nconf)) == -1) { + if (debugging) + fprintf(stderr, + "create_rmtcall_fd: couldn't open \"%s\" (errno %d)\n", + nconf->nc_device, errno); + return (-1); + } + + if (strcmp("*", host) == 0) { + xprt = svc_tli_create(fd, 0, (struct t_bind *) 0, 0, 0); + } else { + if ((aicode = getaddrinfo(host, NULL, &hints, &res)) != 0) { + syslog(LOG_ERR, "cannot get local address for %s: %s", + nconf->nc_netid, gai_strerror(aicode)); + xprt = svc_tli_create(fd, 0, (struct t_bind *) 0, 0, 0); + } + if (bind(fd, (struct sockaddr *) res->ai_addr, res->ai_addrlen) != 0) { + syslog(LOG_ERR, "cannot bind rmtcall %s on %s: %m", + host, nconf->nc_netid); + if (res != NULL) { + freeaddrinfo(res); + return (-1); + } + } + + xprt = svc_tli_create(fd, nconf, NULL, + RPC_MAXDATASIZE, RPC_MAXDATASIZE); + } + + if (xprt == NULL) { + if (debugging) + fprintf(stderr, + "create_rmtcall_fd: svc_tli_create failed\n"); + return (-1); + } + rmt = malloc(sizeof (struct rmtcallfd_list)); + if (rmt == NULL) { + syslog(LOG_ERR, "create_rmtcall_fd: no memory!"); + return (-1); + } + rmt->xprt = xprt; + rmt->netid = strdup(nconf->nc_netid); + xprt->xp_netid = rmt->netid; + rmt->fd = fd; + rmt->next = NULL; + if (rmthead == NULL) { + rmthead = rmt; + rmttail = rmt; + } else { + rmttail->next = rmt; + rmttail = rmt; + } + /* XXX not threadsafe */ + if (fd > svc_maxfd) + svc_maxfd = fd; + FD_SET(fd, &svc_fdset); + return (fd); +} + /* * Catch the signal and die */ @@ -706,7 +896,7 @@ static void parseargs(int argc, char *argv[]) { - int c; + int c, i; #ifdef WARMSTART #define WSOP "w" @@ -727,12 +917,26 @@ break; case 'h': ++nhosts; - hosts = realloc(hosts, nhosts * sizeof(char *)); - if (hosts == NULL) - errx(1, "Out of memory"); + 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); + syslog(LOG_ERR, "out of memory"); + exit(2); + } + } + hosts = hosts_bak; hosts[nhosts - 1] = strdup(optarg); - if (hosts[nhosts - 1] == NULL) - errx(1, "Out of memory"); + if (hosts[nhosts - 1] == NULL) { + for (i = 0; i < (nhosts - 1); i++) + free(hosts[i]); + free(hosts); + syslog(LOG_ERR, "out of memory"); + exit(2); + } break; case 'i': insecure = 1; Index: rpcbind.h =================================================================== RCS file: /home/rionda/branch/ncvs/src/usr.sbin/rpcbind/rpcbind.h,v retrieving revision 1.3 diff -u -r1.3 rpcbind.h --- rpcbind.h 7 Nov 2007 10:53:39 -0000 1.3 +++ rpcbind.h 2 Feb 2008 09:36:15 -0000 @@ -65,6 +65,14 @@ struct encap_parms rmt_args; }; +struct rmtcallfd_list { + int fd; + SVCXPRT *xprt; + char *netid; + struct rmtcallfd_list *next; +}; + + extern int debugging; extern int doabort; extern int verboselog; @@ -111,7 +119,6 @@ SVCXPRT *, rpcvers_t); void *rpcbproc_taddr2uaddr_com(void *, struct svc_req *, SVCXPRT *, rpcvers_t); -int create_rmtcall_fd(struct netconfig *); void rpcbproc_callit_com(struct svc_req *, SVCXPRT *, rpcvers_t, rpcvers_t); void my_svc_run(void);