FreeBSD/usr.sbin/rpc.lockd/lockd.c
/*
 * This routine creates and binds sockets on the appropriate
 * addresses. It gets called one time for each transport.
 * It returns 0 upon success, 1 for ingore the call and -1 to indicate
 * bind failed with EADDRINUSE.
 * Any file descriptors that have been created are stored in sock_fd and
 * the total count of them is maintained in sock_fdcnt.
 */
This routine creates and binds sockets on the appropriate
addresses. It gets called one time for each transport.
It returns 0 upon success, 1 for ingore the call and -1 to indicate
bind failed with EADDRINUSE.
Any file descriptors that have been created are stored in sock_fd and
the total count of them is maintained in sock_fdcnt.
This routine creates and binds sockets on the appropriate addresses . It gets called one time for each transport . It returns 0 upon success 1 for ingore the call and - 1 to indicate bind failed with EADDRINUSE . Any file descriptors that have been created are stored in sock_fd and the total count of them is maintained in sock_fdcnt .
static int
create_service(struct netconfig *nconf)
{
	struct addrinfo hints, *res = NULL;
	struct sockaddr_in *sin;
	struct sockaddr_in6 *sin6;
	struct __rpc_sockinfo si;
	int aicode;
	int fd;
	int nhostsbak;
	int r;
	u_int32_t host_addr[4];  
	int mallocd_res;
	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
	    (nconf->nc_semantics != NC_TPI_COTS) &&
	    (nconf->nc_semantics != NC_TPI_COTS_ORD))
		return (1);	
	if (!__rpc_nconf2sockinfo(nconf, &si)) {
		syslog(LOG_ERR, "cannot get information for %s",
		    nconf->nc_netid);
		return (1);
	}
	memset(&hints, 0, sizeof hints);
	hints.ai_family = si.si_af;
	hints.ai_socktype = si.si_socktype;
	hints.ai_protocol = si.si_proto;
	nhostsbak = nhosts;
	while (nhostsbak > 0) {
		--nhostsbak;
		sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int));
		if (sock_fd == NULL)
			out_of_mem();
		sock_fd[sock_fdcnt++] = -1;	
		mallocd_res = 0;
		hints.ai_flags = AI_PASSIVE;
		if ((fd = __rpc_nconf2fd(nconf)) < 0) {
			syslog(LOG_ERR, "cannot create socket for %s",
			    nconf->nc_netid);
			continue;
		}
		switch (hints.ai_family) {
			case AF_INET:
				if (inet_pton(AF_INET, hosts[nhostsbak],
				    host_addr) == 1) {
					hints.ai_flags |= AI_NUMERICHOST;
				} else {
					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 {
					if (inet_pton(AF_INET, hosts[nhostsbak],
					    host_addr) == 1) {
						close(fd);
						continue;
					}
				}
				break;
			default:
				break;
		}
		if (strcmp("*", hosts[nhostsbak]) == 0) {
			if (svcport_str == NULL) {
				res = malloc(sizeof(struct addrinfo));
				if (res == NULL) 
					out_of_mem();
				mallocd_res = 1;
				res->ai_flags = hints.ai_flags;
				res->ai_family = hints.ai_family;
				res->ai_protocol = hints.ai_protocol;
				switch (res->ai_family) {
					case AF_INET:
						sin = malloc(sizeof(struct sockaddr_in));
						if (sin == NULL) 
							out_of_mem();
						sin->sin_family = AF_INET;
						sin->sin_port = htons(0);
						sin->sin_addr.s_addr = htonl(INADDR_ANY);
						res->ai_addr = (struct sockaddr*) sin;
						res->ai_addrlen = (socklen_t)
						    sizeof(struct sockaddr_in);
						break;
					case AF_INET6:
						sin6 = malloc(sizeof(struct sockaddr_in6));
						if (sin6 == NULL)
							out_of_mem();
						sin6->sin6_family = AF_INET6;
						sin6->sin6_port = htons(0);
						sin6->sin6_addr = in6addr_any;
						res->ai_addr = (struct sockaddr*) sin6;
						res->ai_addrlen = (socklen_t)
						    sizeof(struct sockaddr_in6);
						break;
					default:
						syslog(LOG_ERR,
						    "bad addr fam %d",
						    res->ai_family);
						exit(1);
				}
			} else { 
				if ((aicode = getaddrinfo(NULL, svcport_str,
				    &hints, &res)) != 0) {
					syslog(LOG_ERR,
					    "cannot get local address for %s: %s",
					    nconf->nc_netid,
					    gai_strerror(aicode));
					close(fd);
					continue;
				}
			}
		} else {
			if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str,
			    &hints, &res)) != 0) {
				syslog(LOG_ERR,
				    "cannot get local address for %s: %s",
				    nconf->nc_netid, gai_strerror(aicode));
				close(fd);
				continue;
			}
		}
		sock_fd[sock_fdcnt - 1] = fd;
		r = bindresvport_sa(fd, res->ai_addr);
		if (r != 0) {
			if (errno == EADDRINUSE && mallocd_svcport != 0) {
				if (mallocd_res != 0) {
					free(res->ai_addr);
					free(res);
				} else
					freeaddrinfo(res);
				return (-1);
			}
			syslog(LOG_ERR, "bindresvport_sa: %m");
			exit(1);
		}
		if (svcport_str == NULL) {
			svcport_str = malloc(NI_MAXSERV * sizeof(char));
			if (svcport_str == NULL)
				out_of_mem();
			mallocd_svcport = 1;
			if (getnameinfo(res->ai_addr,
			    res->ai_addr->sa_len, NULL, NI_MAXHOST,
			    svcport_str, NI_MAXSERV * sizeof(char),
			    NI_NUMERICHOST | NI_NUMERICSERV))
				errx(1, "Cannot get port number");
		}
		if (mallocd_res != 0) {
			free(res->ai_addr);
			free(res);
		} else
			freeaddrinfo(res);
		res = NULL;
	}
	return (0);
}
static int create_service ( struct netconfig * nconf ) { struct addrinfo hints , * res = NULL ; struct sockaddr_in * sin ; struct sockaddr_in6 * sin6 ; struct __rpc_sockinfo si ; int aicode ; int fd ; int nhostsbak ; int r ; u_int32_t host_addr [ 4 ] ; int mallocd_res ; if ( ( nconf -> nc_semantics != NC_TPI_CLTS ) && ( nconf -> nc_semantics != NC_TPI_COTS ) && ( nconf -> nc_semantics != NC_TPI_COTS_ORD ) ) return ( 1 ) ; if ( ! __rpc_nconf2sockinfo ( nconf , & si ) ) { syslog ( LOG_ERR , " " , nconf -> nc_netid ) ; return ( 1 ) ; } memset ( & hints , 0 , sizeof hints ) ; hints . ai_family = si . si_af ; hints . ai_socktype = si . si_socktype ; hints . ai_protocol = si . si_proto ; nhostsbak = nhosts ; while ( nhostsbak > 0 ) { -- nhostsbak ; sock_fd = realloc ( sock_fd , ( sock_fdcnt + 1 ) * sizeof ( int ) ) ; if ( sock_fd == NULL ) out_of_mem ( ) ; sock_fd [ sock_fdcnt ++ ] = -1 ; mallocd_res = 0 ; hints . ai_flags = AI_PASSIVE ; if ( ( fd = __rpc_nconf2fd ( nconf ) ) < 0 ) { syslog ( LOG_ERR , " " , nconf -> nc_netid ) ; continue ; } switch ( hints . ai_family ) { case AF_INET : if ( inet_pton ( AF_INET , hosts [ nhostsbak ] , host_addr ) == 1 ) { hints . ai_flags |= AI_NUMERICHOST ; } else { 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 { if ( inet_pton ( AF_INET , hosts [ nhostsbak ] , host_addr ) == 1 ) { close ( fd ) ; continue ; } } break ; default : break ; } if ( strcmp ( " " , hosts [ nhostsbak ] ) == 0 ) { if ( svcport_str == NULL ) { res = malloc ( sizeof ( struct addrinfo ) ) ; if ( res == NULL ) out_of_mem ( ) ; mallocd_res = 1 ; res -> ai_flags = hints . ai_flags ; res -> ai_family = hints . ai_family ; res -> ai_protocol = hints . ai_protocol ; switch ( res -> ai_family ) { case AF_INET : sin = malloc ( sizeof ( struct sockaddr_in ) ) ; if ( sin == NULL ) out_of_mem ( ) ; sin -> sin_family = AF_INET ; sin -> sin_port = htons ( 0 ) ; sin -> sin_addr . s_addr = htonl ( INADDR_ANY ) ; res -> ai_addr = ( struct sockaddr * ) sin ; res -> ai_addrlen = ( socklen_t ) sizeof ( struct sockaddr_in ) ; break ; case AF_INET6 : sin6 = malloc ( sizeof ( struct sockaddr_in6 ) ) ; if ( sin6 == NULL ) out_of_mem ( ) ; sin6 -> sin6_family = AF_INET6 ; sin6 -> sin6_port = htons ( 0 ) ; sin6 -> sin6_addr = in6addr_any ; res -> ai_addr = ( struct sockaddr * ) sin6 ; res -> ai_addrlen = ( socklen_t ) sizeof ( struct sockaddr_in6 ) ; break ; default : syslog ( LOG_ERR , " " , res -> ai_family ) ; exit ( 1 ) ; } } else { if ( ( aicode = getaddrinfo ( NULL , svcport_str , & hints , & res ) ) != 0 ) { syslog ( LOG_ERR , " " , nconf -> nc_netid , gai_strerror ( aicode ) ) ; close ( fd ) ; continue ; } } } else { if ( ( aicode = getaddrinfo ( hosts [ nhostsbak ] , svcport_str , & hints , & res ) ) != 0 ) { syslog ( LOG_ERR , " " , nconf -> nc_netid , gai_strerror ( aicode ) ) ; close ( fd ) ; continue ; } } sock_fd [ sock_fdcnt - 1 ] = fd ; r = bindresvport_sa ( fd , res -> ai_addr ) ; if ( r != 0 ) { if ( errno == EADDRINUSE && mallocd_svcport != 0 ) { if ( mallocd_res != 0 ) { free ( res -> ai_addr ) ; free ( res ) ; } else freeaddrinfo ( res ) ; return ( -1 ) ; } syslog ( LOG_ERR , " " ) ; exit ( 1 ) ; } if ( svcport_str == NULL ) { svcport_str = malloc ( NI_MAXSERV * sizeof ( char ) ) ; if ( svcport_str == NULL ) out_of_mem ( ) ; mallocd_svcport = 1 ; if ( getnameinfo ( res -> ai_addr , res -> ai_addr -> sa_len , NULL , NI_MAXHOST , svcport_str , NI_MAXSERV * sizeof ( char ) , NI_NUMERICHOST | NI_NUMERICSERV ) ) errx ( 1 , " " ) ; } if ( mallocd_res != 0 ) { free ( res -> ai_addr ) ; free ( res ) ; } else freeaddrinfo ( res ) ; res = NULL ; } return ( 0 ) ; }
This routine creates and binds sockets on the appropriate
 addresses.
This routine creates and binds sockets on the appropriate addresses .
/* IPv4 or IPv6 */ /* not my type */ /*
	 * XXX - using RPC library internal functions.
	 */ /* Get rpc.statd's address on this transport */ /*
	 * Bind to specific IPs if asked to
	 */ /* Set invalid for now. */ /*	
		 * XXX - using RPC library internal functions.
		 */ /*
					 * Skip if we have an AF_INET6 address.
					 */ /*
					 * Skip if we have an AF_INET address.
					 */ /*
		 * If no hosts were specified, just bind to INADDR_ANY
		 */ /* Store the fd. */ /* Now, attempt the bind. */