Beispiel #1
0
void proxy_getservbyname(const char * service, struct servent *se_buf,
	char * buf, size_t buf_len, struct servent **se_result)
{

#ifdef __linux__
	getservbyname_r(service, NULL, se_buf, buf, buf_len, se_result);
#endif

#ifdef __APPLE__
	struct servent *se;

	MUTEX_LOCK(&internal_getsrvbyname_lock);
	if(service) {
		se = getservbyname(service, NULL);

		if ( se != NULL ) {
			memcpy(se_buf, se, buf_len);
			*se_result = se_buf;
		} else {
			*se_result = NULL;
		}
	}
	MUTEX_UNLOCK(&internal_getsrvbyname_lock);
#endif /* __APPLE__ */
}
Beispiel #2
0
static int
gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
		const struct addrinfo *req, struct gaih_servtuple *st)
{
    struct servent *s;
    size_t tmpbuflen = 1024;
    struct servent ts;
    char *tmpbuf;
    int r;

    do
    {
	tmpbuf = alloca (tmpbuflen);

	r = getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
			     &s);
	if (r != 0 || s == NULL)
	{
	    if (r == ERANGE)
		tmpbuflen *= 2;
	    else
		return GAIH_OKIFUNSPEC | -EAI_SERVICE;
	}
    }
    while (r);

    st->next = NULL;
    st->socktype = tp->socktype;
    st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
		    ? req->ai_protocol : tp->protocol);
    st->port = s->s_port;

    return 0;
}
Beispiel #3
0
struct servent *
tds_getservbyname_r(const char *name, const char *proto, struct servent *result, char *buffer, int buflen)
{
#if defined(NETDB_REENTRANT)
	return getservbyname(name, proto);

#elif defined(HAVE_FUNC_GETSERVBYNAME_R_6)
	struct servent result_buf;

	getservbyname_r(name, proto, &result_buf, buffer, buflen, &result);
	return result;

#elif defined(HAVE_FUNC_GETSERVBYNAME_R_5)
	getservbyname_r(name, proto, result, buffer, buflen);
	return result;

#elif defined(HAVE_FUNC_GETSERVBYNAME_R_4)
	struct servent_data data;

	getservbyname_r(name, proto, result, &data);
	return result;

#elif defined(HAVE_GETADDRINFO)
	struct addrinfo hints, *res;

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;
	res = NULL;
	if (getaddrinfo(NULL, name, &hints, &res))
		return NULL;
	if (res->ai_family != PF_INET || !res->ai_addr) {
		freeaddrinfo(res);
		return NULL;
	}
	memset(result, 0, sizeof(*result));
	result->s_port = ((struct sockaddr_in *) res->ai_addr)->sin_port;
	freeaddrinfo(res);
	return result;

#elif defined(TDS_NO_THREADSAFE)
	return getservbyname(name, proto);
#else
#error getservbyname_r style unknown
#endif
}
Beispiel #4
0
struct servent *getservbyname(const char *name, const char *proto)
{
    struct servent *result;

    __initbuf();
    getservbyname_r(name, proto, &serv, servbuf, SBUFSIZE, &result);
    return result;
}
Beispiel #5
0
int getservbyname_r(const char *name, const char *prots,
	struct servent *se, char *buf, size_t buflen, struct servent **res)
{
	struct addrinfo *ai, hint = { .ai_family = AF_INET };
	int i;

	if (!prots) {
		int r = getservbyname_r(name, "tcp", se, buf, buflen, res);
		if (r) r = getservbyname_r(name, "udp", se, buf, buflen, res);
		return r;
	}

	/* Align buffer */
	i = (uintptr_t)buf & sizeof(char *)-1;
	if (!i) i = sizeof(char *);
	if (buflen < 3*sizeof(char *)-i)
		return ERANGE;
	buf += sizeof(char *)-i;
	buflen -= sizeof(char *)-i;

	if (!strcmp(prots, "tcp")) hint.ai_protocol = IPPROTO_TCP;
	else if (!strcmp(prots, "udp")) hint.ai_protocol = IPPROTO_UDP;
	else return EINVAL;

	switch (getaddrinfo(0, name, &hint, &ai)) {
	case EAI_MEMORY:
	case EAI_SYSTEM:
		return ENOMEM;
	default:
		return ENOENT;
	case 0:
		break;
	}

	se->s_name = (char *)name;
	se->s_aliases = (void *)buf;
	se->s_aliases[0] = se->s_name;
	se->s_aliases[1] = 0;
	se->s_port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
	se->s_proto = (char *)prots;

	freeaddrinfo(ai);
	*res = se;
	return 0;
}
Beispiel #6
0
int __getservbyport_r(int port, const char *proto, struct servent *result_buf,
                      char *buf, size_t buflen, struct servent **result)
{

	char port_buf[32];

	snprintf(port_buf, sizeof(port_buf), "%d", port);
	/* the plan 9 version can handle a port or a name */
	return getservbyname_r(port_buf, proto, result_buf, buf, buflen, result);
}
Beispiel #7
0
struct servent *
getservbyname(const char *name, const char *proto)
{
	extern struct servent_data _servent_data;
	static struct servent serv;

	if (getservbyname_r(name, proto, &serv, &_servent_data) != 0)
		return (NULL);
	return (&serv);
}
Beispiel #8
0
main()
{
	char		buf[8192];
	struct servent	sent, *sptr;

	sptr = getservbyname_r("tftp", "tcp", &sent, buf, sizeof(buf));
	printf("TCP, sptr = %p\n", sptr);

	sptr = getservbyname_r("tftp", "udp", &sent, buf, sizeof(buf));
	printf("UDP, sptr = %p\n", sptr);

	sptr = getservbyname_r("tftp", "tcp", &sent, buf, sizeof(buf));
	printf("TCP, sptr = %p\n", sptr);

	sptr = getservbyname_r("tftp", "udp", &sent, buf, sizeof(buf));
	printf("UDP, sptr = %p\n", sptr);

	exit(0);
}
Beispiel #9
0
void testValues() {
    f = 2;
    
    struct servent result;
    struct servent * rp;
    char buf[10];
    getservbyname_r(anystring(), anystring(), &result, buf, 10, &rp);

    //@ assert f == 2;
    //@ assert vacuous: \false;
}
Beispiel #10
0
int
compat_getservbyname_r(const char *name, const char *proto,
		       struct servent *sp, char *buf, size_t buflen,
		       struct servent **spp) {
#if GETSERVBYNAME_R_NUM_ARGS == 5
	*spp = getservbyname_r(name, proto, sp, buf, buflen);

	if (*spp == NULL)
		return -1;
	return 0;
#elif GETSERVBYNAME_R_NUM_ARGS == 4
	struct servent_data sdata;

	if (getservbyname_r(name, proto, sp, &sdata) == -1)
		return -1;
	*spp = sp;
	return 0;
#endif /* GETSERVBYNAME_R_NUM_ARGS == 5 */
	return 0;
}
Beispiel #11
0
int getservport(u_long number, const char *proto)
{
	char servdata[1024];
	struct rpcent *rpcp;
	struct servent servbuf, *servp = NULL;
	int ret = 0;
#if HAVE_GETRPCBYNUMBER_R
	char rpcdata[1024];
	struct rpcent rpcbuf;

	ret = getrpcbynumber_r(number, &rpcbuf, rpcdata, sizeof rpcdata,
				&rpcp);
#else
	rpcp = getrpcbynumber(number);
#endif

	if (ret == 0 && rpcp != NULL) {
		/* First try name.  */
		ret = getservbyname_r(rpcp->r_name, proto, &servbuf, servdata,
					sizeof servdata, &servp);
		if ((ret != 0 || servp == NULL) && rpcp->r_aliases) {
			const char **a;

			/* Then we try aliases.  */
			for (a = (const char **) rpcp->r_aliases; *a != NULL; a++) {
				ret = getservbyname_r(*a, proto, &servbuf, servdata,
							sizeof servdata, &servp);
				if (ret == 0 && servp != NULL)
					break;
			}
		}
	}

	if (ret == 0 && servp != NULL)
		return ntohs(servp->s_port);

	return 0;
}
Beispiel #12
0
/*
 * get_port_default() - set the default port number; note, that "solaris-audit"
 * used below in the code is the IANA assigned service name for the secure
 * remote solaris audit logging.
 */
static auditd_rc_t
get_port_default(int *port_default)
{

	struct servent  serventry;
	char  		serventry_buf[1024];

	if (getservbyname_r("solaris-audit", "tcp", &serventry,
	    (char *)&serventry_buf, sizeof (serventry_buf)) == NULL) {
		DPRINT((dfile, "unable to get default port number\n"));
#if DEBUG
		if (errno == ERANGE) {
			DPRINT((dfile, "low on buffer\n"));
		}
#endif
		return (AUDITD_INVALID);
	}
	*port_default = ntohs(serventry.s_port);
	DPRINT((dfile, "default port: %d\n", *port_default));

	return (AUDITD_SUCCESS);
}
Beispiel #13
0
int mksockaddr_in(const char *host,
                  char *service,
                  struct sockaddr_in *sin)
{
    memset(sin, 0, sizeof(sin));

    sin->sin_family = AF_INET;
    if (isdigit(host[0]))
        sin->sin_addr.s_addr = inet_addr(host);
    else
    {
        struct hostent hp;
        int h_errno;
        char buf[2048];


        if (gethostbyname_r(host, &hp, buf, sizeof(buf), &h_errno) == NULL)
            return -1;

        memcpy(&sin->sin_addr, hp.h_addr_list[0], hp.h_length);
    }

    if (isdigit(service[0]))
        sin->sin_port = htons(atoi(service));
    else
    {
        struct servent sp;
        char buf[2048];


        if (getservbyname_r(service, "tcp", &sp, buf, sizeof(buf)) == NULL)
            return -1;

        sin->sin_port = sp.s_port;
    }

    return 0;

}
Beispiel #14
0
static gboolean
tf_getent_services(gchar *key, gchar *member_name, GString *result)
{
  struct servent serv, *res;
  gint64 d;
  gboolean is_num;
  char buf[4096];

  if ((is_num = parse_dec_number(key, &d)) == TRUE)
    getservbyport_r((int)ntohs(d), NULL, &serv, buf, sizeof(buf), &res);
  else
    getservbyname_r(key, NULL, &serv, buf, sizeof(buf), &res);

  if (res == NULL)
    return TRUE;

  if (is_num)
    g_string_append(result, res->s_name);
  else
    g_string_append_printf(result, "%i", htons(res->s_port));

  return TRUE;
}
Beispiel #15
0
/*
 * Retreive the port number for the service name "servname" and
 * the protocol "proto".
 */
static int
get_port(const char *servname, const char *proto, int numonly)
{
	struct servent		se;
#ifdef HAVE_STRUCT_SERVENT_DATA
	struct servent_data	sed;
#endif
	int			port;
	const char		*e;

	if (servname == NULL)
		return (0);

	e = NULL;
	port = strtonum(servname, 0, USHRT_MAX, &e);
	if (e == NULL)
		return (port);
	if (errno == ERANGE)
		return (-2); /* invalid */
	if (numonly)
		return (-2);

	port = -1;
#ifdef HAVE_STRUCT_SERVENT_DATA
	memset(&sed, 0, sizeof(sed));
#endif
#ifdef HAVE_GETSERVBYNAME_R_4_ARGS
	if (getservbyname_r(servname, proto, &se, &sed) != -1)
		port = ntohs(se.s_port);
#endif
#ifdef HAVE_ENDSERVENT_R
	endservent_r(&sed);
#endif

	return (port);
}
Beispiel #16
0
void runSuccess() {
    struct servent result;
    struct servent * rp;
    char buf[10];
    getservbyname_r(anystring(), anystring(), &result, buf, 10, &rp);
}
Beispiel #17
0
int ResolveUtil::getServicePort(IPv4Address *result,
                                const char  *serviceName,
                                const char  *protocol,
                                int         *errorCode)
{
    BSLS_ASSERT(result);
    BSLS_ASSERT(serviceName);

    enum {
        k_BUF_LEN = 64
    };

#if defined(BSLS_PLATFORM_OS_AIX)
    servent      serverEntry;
    servent_data buffer;

    if (getservbyname_r(serviceName, protocol, &serverEntry, &buffer)) {
        // Note: according to contract, errorCode should not be loaded!
        // This sounds like an insane contract, so we keep the code.

        if (errorCode) {
            *errorCode = h_errno;  // or errno ??  Insufficient AIX doc!!!
        }
        return -1;                                                    // RETURN
    }

    result->setPortNumber(serverEntry.s_port);

#elif defined(BSLS_PLATFORM_OS_UNIX)
   // BSLS_PLATFORM_OS_SOLARIS || BSLS_PLATFORM_OS_LINUX ||
   // BSLS_PLATFORM_OS_CYGWIN || BSLS_PLATFORM_OS_HPUX

    servent serverEntry;

    // Avoid dynamic memory allocation in most common cases.

    char                               stackBuffer[k_BUF_LEN];
    int                                bufferLength = sizeof stackBuffer;
    bdlma::BufferedSequentialAllocator allocator(stackBuffer, bufferLength);

    bsl::vector<char>                  buffer(bufferLength, '\0', &allocator);

    while (1) {
        #if defined(BSLS_PLATFORM_OS_LINUX) \
         || defined(BSLS_PLATFORM_OS_FREEBSD)
        struct servent *glibcResult;

        #if defined(BSLS_PLATFORM_OS_FREEBSD)
        int getServRet;
        #endif
        if ((
        #if defined(BSLS_PLATFORM_OS_FREEBSD)
          getServRet =
        #endif
            getservbyname_r(serviceName,
                            protocol,
                            &serverEntry,
                            &buffer.front(),
                            bufferLength,
                            &glibcResult)) || !glibcResult)
        #elif defined(BSLS_PLATFORM_OS_HPUX)   \
           || defined(BSLS_PLATFORM_OS_CYGWIN) \
           || defined(BSLS_PLATFORM_OS_DARWIN)
        if (0 == getservbyname_r(serviceName,
                                 protocol,
                                 &serverEntry,
                                 &buffer))
        #else
        if (0 == getservbyname_r(serviceName,
                                 protocol,
                                 &serverEntry,
                                 &buffer.front(),
                                 bufferLength))
        #endif
        {
            #if defined(BSLS_PLATFORM_OS_FREEBSD)
              errno = getServRet;
            #endif
            if (errno == ERANGE) {
                // The buffer size is too small; not an error, retry.

                bufferLength *= 4;
                buffer.resize(bufferLength);
                errno = 0;
            }
            else {
                // Other errors: optionally set 'errorCode'.

                if (errorCode) {
                    *errorCode = h_errno;
                }
                return -1;                                            // RETURN
            }
        }
        else {
            // Note that 'getservbyname' returns the port number
            // in network byte order.

            result->setPortNumber(ntohs(static_cast<short>(
                                                         serverEntry.s_port)));
            return 0;                                                 // RETURN
        }
    }

#elif defined(BSLS_PLATFORM_OS_WINDOWS)
        servent *sp = getservbyname(serviceName, protocol);
        if (0 == sp) {
            if (errorCode) {
                *errorCode = WSAGetLastError();
            }
            return -1;                                                // RETURN
        }

        result->setPortNumber(sp->s_port);
#else

#error getServicePort does not handle current platform type!

#endif

    return 0;
}
Beispiel #18
0
int proxy_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
	struct gethostbyname_data ghdata;
	struct addrinfo_data *space;
	struct servent *se = NULL;
	struct hostent *hp = NULL;
	struct servent se_buf;
	struct addrinfo *p;
	char buf[1024];
	int port;
	PFUNC();

//      printf("proxy_getaddrinfo node %s service %s\n",node,service);
	space = calloc(1, sizeof(struct addrinfo_data));
	if(!space) goto err1;

	if(node && !inet_aton(node, &((struct sockaddr_in *) &space->sockaddr_space)->sin_addr)) {
		/* some folks (nmap) use getaddrinfo() with AI_NUMERICHOST to check whether a string
		   containing a numeric ip was passed. we must return failure in that case. */
		if(hints && (hints->ai_flags & AI_NUMERICHOST)) return EAI_NONAME;
		hp = proxy_gethostbyname(node, &ghdata);
		if(hp)
			memcpy(&((struct sockaddr_in *) &space->sockaddr_space)->sin_addr,
			       *(hp->h_addr_list), sizeof(in_addr_t));
		else
			goto err2;
	}
	if(service) getservbyname_r(service, NULL, &se_buf, buf, sizeof(buf), &se);

	port = se ? se->s_port : htons(atoi(service ? service : "0"));
	((struct sockaddr_in *) &space->sockaddr_space)->sin_port = port;

	*res = p = &space->addrinfo_space;
	assert((size_t)p == (size_t) space);

	p->ai_addr = &space->sockaddr_space;
	if(node)
		snprintf(space->addr_name, sizeof(space->addr_name), "%s", node);
	p->ai_canonname = space->addr_name;
	p->ai_next = NULL;
	p->ai_family = space->sockaddr_space.sa_family = AF_INET;
	p->ai_addrlen = sizeof(space->sockaddr_space);

	if(hints) {
		p->ai_socktype = hints->ai_socktype;
		p->ai_flags = hints->ai_flags;
		p->ai_protocol = hints->ai_protocol;
	} else {
#ifndef AI_V4MAPPED
#define AI_V4MAPPED 0
#endif
		p->ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);
	}

	goto out;
	err2:
	free(space);
	err1:
	return 1;
	out:
	return 0;
}
Beispiel #19
0
void runFailure4() {
    struct servent result;
    struct servent * rp;
    char buf[10];
    getservbyname_r(anystring(), NULL, &result, buf, 10, &rp);
}
void TcpSocket::getServicePort( struct servent    * pServicePort, const std::string & pService ) const
{
	//
	// Initialise the service port details.
	//
	memset( pServicePort, 0, sizeof( struct servent ) );

	//
	// Port has been specified as a number so get all the relevant details
	// using the port number.
	//
	if ( 0 != atoi( pService.c_str() ) )
	{

		struct servent *lvServicePtr;

#if defined( SOLARIS )

		char lvServiceBuffer[1024];
		memset( lvServiceBuffer, 0, sizeof( lvServiceBuffer ) );
		lvServicePtr = getservbyport_r( atoi( pService.c_str() ), "tcp",
			pServicePort,
			lvServiceBuffer,
			sizeof( lvServiceBuffer ) );

#else // !defined( SOLARIS )

		lvServicePtr = getservbyport( atoi( pService.c_str() ), "tcp" );

#endif // !defined( SOLARIS )

		if ( 0 != lvServicePtr )
		{
			memcpy( pServicePort, lvServicePtr, sizeof( struct servent ) );
		}
		else
		{
			pServicePort->s_port = htons( atoi( pService.c_str() ) );
			pServicePort->s_proto = "tcp";
		}

	}

	//
	// Port name specified.
	//
	else
	{

		if ( 0 == atoi( pService.c_str() ) )
		{

			struct servent *lvServicePtr;

#if defined( SOLARIS )
			char lvServiceBuffer[1024];
			memset( lvServiceBuffer, 0, sizeof( lvServiceBuffer ) );
			lvServicePtr = getservbyname_r( pService.c_str(), "tcp",
				pServicePort,
				lvServiceBuffer,
				sizeof( lvServiceBuffer ) );
#else // !defined( SOLARIS )

			lvServicePtr = getservbyname( pService.c_str(), "tcp" );

#endif // !defined( SOLARIS )

			if ( 0 == lvServicePtr )
			{

				//throw exception
				std::ostringstream streamErrInfo;
				std::string strErrorInfo;

				streamErrInfo << "Unknown service";
				strErrorInfo = streamErrInfo.str();

				throw std::exception(strErrorInfo.c_str());
			}
			memcpy( pServicePort, lvServicePtr, sizeof( struct servent ) );

		}
	}
}
Beispiel #21
0
unsigned int
ServiceNameToPortNumber(const char *const s, const int proto)
{
    char str[64];
    char *cp;
#if defined(HAVE_GETSERVBYNAME_R) && (defined(AIX) || defined(TRU64UNIX) || defined(DIGITAL_UNIX))
    struct servent *sp;
#elif defined(HAVE_GETSERVBYNAME_R) && (defined(LINUX) || defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
    struct servent se, *sp;
    char spbuf[256];
#else
    struct servent *sp;
#endif
    strncpy(str, s, sizeof(str) - 1);
    str[sizeof(str) - 1] = '\0';
    cp = str;
    if (isdigit((int) *cp))
    {
        while (isdigit((int) *cp))
            cp++;
        *cp = '\0';
        return (atoi(str));
    }
    for (;; cp++)
    {
        if ((*cp == '\0')
                || ((!ISALNUM(*cp)) && (*cp != '-') && (*cp != '_')))
            break;
    }
    *cp = '\0';

    sp = NULL;
#if defined(HAVE_GETSERVBYNAME_R) && (defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
    if ((sp == NULL) && ((proto == 0) || (proto == 't')))
    {
        memset(spbuf, 0, sizeof(spbuf));
        sp = getservbyname_r(str, "tcp", &se, spbuf, sizeof(spbuf));
    }
    if ((sp == NULL) && ((proto == 0) || (proto == 'u')))
    {
        memset(spbuf, 0, sizeof(spbuf));
        sp = getservbyname_r(str, "udp", &se, spbuf, sizeof(spbuf));
    }
#elif defined(HAVE_GETSERVBYNAME_R) && defined(LINUX)
    if ((sp == NULL) && ((proto == 0) || (proto == 't')))
    {
        memset(spbuf, 0, sizeof(spbuf));
        if (getservbyname_r(str, "tcp", &se, spbuf, sizeof(spbuf), &sp) != 0)
            sp = NULL;
    }
    if ((sp == NULL) && ((proto == 0) || (proto == 'u')))
    {
        memset(spbuf, 0, sizeof(spbuf));
        if (getservbyname_r(str, "udp", &se, spbuf, sizeof(spbuf), &sp) != 0)
            sp = NULL;
    }
#elif defined(HAVE_GETSERVBYNAME_R) && defined(AIX)
    {
        struct servent_data sed;
        if ((sp == NULL) && ((proto == 0) || (proto == 't')))
        {
            memset(&sed, 0, sizeof(sed));
            if (getservbyname_r(str, "tcp", sp, &sed) != 0)
                sp = NULL;
        }
        if ((sp == NULL) && ((proto == 0) || (proto == 'u')))
        {
            memset(&sed, 0, sizeof(sed));
            if (getservbyname_r(str, "udp", sp, &sed) != 0)
                sp = NULL;
        }
    }
#else
    /* Note: getservbyname is already threadsafe on: HP-UX, Tru64 */
    if ((sp == NULL) && ((proto == 0) || (proto == 't')))
    {
        sp = getservbyname(str, "tcp");
    }
    if ((sp == NULL) && ((proto == 0) || (proto == 'u')))
    {
        sp = getservbyname(str, "udp");
    }
#endif

    if (sp != NULL)
    {
        return ((unsigned int) ntohs((unsigned short) sp->s_port));
    }
    return (0);	/* error */
}	/* ServiceNameToPortNumber */
Beispiel #22
0
/*
 * valid_props validates all the properties in an array of inetd_prop_t's,
 * marking each property as valid or invalid.  If any properties are invalid,
 * it returns B_FALSE, otherwise it returns B_TRUE.  Note that some properties
 * are interdependent, so if one is invalid, it leaves others in an
 * indeterminate state (such as ISRPC and SVC_NAME).  In this case, the
 * indeterminate property will be marked valid.  IE, the only properties
 * marked invalid are those that are KNOWN to be invalid.
 *
 * Piggy-backed onto this validation if 'fmri' is non-NULL is the construction
 * of a structured configuration, a basic_cfg_t,  which is used by inetd.
 * If 'fmri' is set then the latter three parameters need to be set to
 * non-NULL values, and if the configuration is valid, the storage referenced
 * by cfgpp is set to point at an initialized basic_cfg_t.
 */
boolean_t
valid_props(inetd_prop_t *prop, const char *fmri, basic_cfg_t **cfgpp,
    uu_list_pool_t *proto_info_pool, uu_list_pool_t *tlx_ci_pool)
{
	char			*bufp, *cp;
	boolean_t		ret = B_TRUE;
	int			i;
	long			uidl;
	boolean_t		isrpc;
	int			sock_type_id;
	int			rpc_pnum;
	int			rpc_lv, rpc_hv;
	basic_cfg_t		*cfg;
	char			*proto = NULL;
	int			pi;
	char			**netids = NULL;
	int			ni = 0;

	if (fmri != NULL)
		assert((cfgpp != NULL) && (proto_info_pool != NULL) &&
		    (tlx_ci_pool != NULL));

	/*
	 * Set all checkable properties to valid as a baseline.  We'll be
	 * marking all invalid properties.
	 */
	for (i = 0; prop[i].ip_name != NULL; i++) {
		if (prop[i].ip_error != IVE_UNSET)
			prop[i].ip_error = IVE_VALID;
	}

	if (((cfg = calloc(1, sizeof (basic_cfg_t))) == NULL) ||
	    ((fmri != NULL) &&
	    ((cfg->proto_list = uu_list_create(proto_info_pool, NULL, 0)) ==
	    NULL))) {
		free(cfg);
		return (B_FALSE);
	}

	/* Check a service name was supplied */
	if ((prop[PT_SVC_NAME_INDEX].ip_error == IVE_UNSET) ||
	    ((cfg->svc_name =
	    strdup(prop[PT_SVC_NAME_INDEX].ip_value.iv_string)) == NULL))
		prop[PT_SVC_NAME_INDEX].ip_error = IVE_INVALID;

	/* Check that iswait and isrpc have valid boolean values */

	if ((prop[PT_ISWAIT_INDEX].ip_error == IVE_UNSET) ||
	    (((cfg->iswait = prop[PT_ISWAIT_INDEX].ip_value.iv_boolean) !=
	    B_TRUE) && (cfg->iswait != B_FALSE)))
		prop[PT_ISWAIT_INDEX].ip_error = IVE_INVALID;

	if ((prop[PT_ISRPC_INDEX].ip_error == IVE_UNSET) ||
	    (((isrpc = prop[PT_ISRPC_INDEX].ip_value.iv_boolean) != B_TRUE) &&
	    (isrpc != B_FALSE))) {
		prop[PT_ISRPC_INDEX].ip_error = IVE_INVALID;
	} else if (isrpc) {
		/*
		 * This is an RPC service, so ensure that the RPC version
		 * numbers are zero or greater, that the low version isn't
		 * greater than the high version and a valid program name
		 * is supplied.
		 */

		if ((prop[PT_RPC_LW_VER_INDEX].ip_error == IVE_UNSET) ||
		    ((rpc_lv = prop[PT_RPC_LW_VER_INDEX].ip_value.iv_int) <
		    0))
			prop[PT_RPC_LW_VER_INDEX].ip_error = IVE_INVALID;

		if ((prop[PT_RPC_HI_VER_INDEX].ip_error == IVE_UNSET) ||
		    ((rpc_hv = prop[PT_RPC_HI_VER_INDEX].ip_value.iv_int) <
		    0))
			prop[PT_RPC_HI_VER_INDEX].ip_error = IVE_INVALID;

		if ((prop[PT_RPC_LW_VER_INDEX].ip_error != IVE_INVALID) &&
		    (prop[PT_RPC_HI_VER_INDEX].ip_error != IVE_INVALID) &&
		    (rpc_lv > rpc_hv)) {
			prop[PT_RPC_LW_VER_INDEX].ip_error = IVE_INVALID;
			prop[PT_RPC_HI_VER_INDEX].ip_error = IVE_INVALID;
		}

		if ((cfg->svc_name != NULL) &&
		    ((rpc_pnum = get_rpc_prognum(cfg->svc_name)) == -1))
			prop[PT_SVC_NAME_INDEX].ip_error = IVE_INVALID;
	}

	/* Check that the socket type is one of the acceptable values. */
	cfg->istlx = B_FALSE;
	if ((prop[PT_SOCK_TYPE_INDEX].ip_error == IVE_UNSET) ||
	    ((sock_type_id = get_sock_type_id(
	    prop[PT_SOCK_TYPE_INDEX].ip_value.iv_string)) == -1) &&
	    !(cfg->istlx = is_tlx_service(prop)))
		prop[PT_SOCK_TYPE_INDEX].ip_error = IVE_INVALID;

	/* Get the bind address */
	if (!cfg->istlx && prop[PT_BIND_ADDR_INDEX].ip_error != IVE_UNSET &&
	    (cfg->bind_addr =
	    strdup(prop[PT_BIND_ADDR_INDEX].ip_value.iv_string)) == NULL)
		prop[PT_BIND_ADDR_INDEX].ip_error = IVE_INVALID;

	/*
	 * Iterate through all the different protos/netids resulting from the
	 * proto property and check that they're valid and perform checks on
	 * other fields that are tied-in with the proto.
	 */

	pi = 0;
	do {
		socket_info_t		*si = NULL;
		tlx_info_t		*ti = NULL;
		proto_info_t		*p_inf = NULL;
		boolean_t		v6only = B_FALSE;
		char			*only;
		boolean_t		invalid_proto = B_FALSE;
		char			**protos;
		struct protoent		pe;
		char			gpbuf[1024];
		struct netconfig	*nconf = NULL;

		/*
		 * If we don't know whether it's an rpc service or its
		 * endpoint type, we can't do any of the proto checks as we
		 * have no context; break out.
		 */
		if ((prop[PT_ISRPC_INDEX].ip_error != IVE_VALID) ||
		    (prop[PT_SOCK_TYPE_INDEX].ip_error != IVE_VALID))
			break;

		/* skip proto specific processing if the proto isn't set. */
		if (prop[PT_PROTO_INDEX].ip_error == IVE_UNSET) {
			invalid_proto = B_TRUE;
			goto past_proto_processing;
		}
		protos = prop[PT_PROTO_INDEX].ip_value.iv_string_list;

		/*
		 * Get the next netid/proto.
		 */

		if (!cfg->istlx || !isrpc) {
			proto = protos[pi++];
		/*
		 * This is a TLI/RPC service, so get the next netid, expanding
		 * any supplied nettype.
		 */
		} else if ((netids == NULL) ||
		    ((proto = netids[ni++]) == NULL)) {
			/*
			 * Either this is the first time around or
			 * we've exhausted the last set of netids, so
			 * try and get the next set using the currently
			 * indexed proto entry.
			 */

			if (netids != NULL) {
				destroy_strings(netids);
				netids = NULL;
			}

			if (protos[pi] != NULL) {
				if ((netids = get_netids(protos[pi++])) ==
				    NULL) {
					invalid_proto = B_TRUE;
					proto = protos[pi - 1];
				} else {
					ni = 0;
					proto = netids[ni++];
				}
			} else {
				proto = NULL;
			}
		}

		if (proto == NULL)
			break;

		if (invalid_proto)
			goto past_proto_processing;

		/* strip a trailing only to simplify further processing */
		only = proto + strlen(proto) - (sizeof ("6only") - 1);
		if ((only > proto) && (strcmp(only, "6only") == 0)) {
			*++only = '\0';
			v6only = B_TRUE;
		}

		/* validate the proto/netid */

		if (!cfg->istlx) {
			if (!valid_socket_proto(proto))
				invalid_proto = B_TRUE;
		} else {
			/*
			 * Check if we've got a valid netid. If
			 * getnetconfigent() fails, we check to see whether
			 * we've got a v6 netid that may have been rejected
			 * because no IPv6 interface was configured before
			 * flagging 'proto' as invalid. If the latter condition
			 * holds, we don't flag the proto as invalid, and
			 * leave inetd to handle the value appropriately
			 * when it tries to listen on behalf of the service.
			 */
			if (((nconf = getnetconfigent(proto)) == NULL) &&
			    !v6_proto(proto))
				invalid_proto = B_TRUE;
		}
		if (invalid_proto)
			goto past_proto_processing;

		/*
		 * dissallow datagram type nowait services
		 */
		if ((prop[PT_ISWAIT_INDEX].ip_error == IVE_VALID) &&
		    !cfg->iswait) {
			if (strncmp(proto, SOCKET_PROTO_UDP,
			    sizeof (SOCKET_PROTO_UDP) - 1) == 0) {
				invalid_proto = B_TRUE;
			} else if (cfg->istlx && (nconf != NULL) &&
			    (nconf->nc_semantics == NC_TPI_CLTS)) {
					invalid_proto = B_TRUE;
			}
			if (invalid_proto) {
				prop[PT_ISWAIT_INDEX].ip_error = IVE_INVALID;
				goto past_proto_processing;
			}
		}

		/*
		 * We're running in validate only mode. Don't bother creating
		 * any proto structures (they don't do any further validation).
		 */
		if (fmri == NULL)
			goto past_proto_processing;

		/*
		 * Create the apropriate transport info structure.
		 */
		if (cfg->istlx) {
			if ((ti = create_tlx_info(proto, tlx_ci_pool)) != NULL)
				p_inf = (proto_info_t *)ti;
		} else {
			struct sockaddr_storage *ss;

			if ((si = calloc(1, sizeof (socket_info_t))) != NULL) {
				p_inf = (proto_info_t *)si;
				si->type = sock_type_id;
				ss = &si->local_addr;

				if (v6_socket_proto(proto)) {
					ss->ss_family = AF_INET6;
					/* already in network order */
					((struct sockaddr_in6 *)ss)->sin6_addr =
					    in6addr_any;
				} else {
					ss->ss_family = AF_INET;
					((struct sockaddr_in *)ss)->sin_addr.
					    s_addr = htonl(INADDR_ANY);
				}
				if (set_bind_addr(ss, cfg->bind_addr) != 0) {
					prop[PT_BIND_ADDR_INDEX].ip_error =
					    IVE_INVALID;
				}
			}
		}
		if (p_inf == NULL) {
			invalid_proto = B_TRUE;
			goto past_proto_processing;
		}

		p_inf->v6only = v6only;

		/*
		 * Store the supplied proto string for error reporting,
		 * re-attaching the 'only' suffix if one was taken off.
		 */
		if ((p_inf->proto = malloc(strlen(proto) + 5)) == NULL) {
			invalid_proto = B_TRUE;
			goto past_proto_processing;
		} else {
			(void) strlcpy(p_inf->proto, proto, strlen(proto) + 5);
			if (v6only)
				(void) strlcat(p_inf->proto, "only",
				    strlen(proto) + 5);
		}

		/*
		 * Validate and setup RPC/non-RPC specifics.
		 */

		if (isrpc) {
			rpc_info_t *ri;

			if ((rpc_pnum != -1) && (rpc_lv != -1) &&
			    (rpc_hv != -1)) {
				if ((ri = create_rpc_info(proto, rpc_pnum,
				    rpc_lv, rpc_hv)) == NULL) {
					invalid_proto = B_TRUE;
				} else {
					p_inf->ri = ri;
				}
			}
		}

past_proto_processing:
		/* validate non-RPC service name */
		if (!isrpc && (cfg->svc_name != NULL)) {
			struct servent	se;
			char		gsbuf[NSS_BUFLEN_SERVICES];
			char		*gsproto = proto;

			if (invalid_proto) {
				/*
				 * Make getservbyname_r do its lookup without a
				 * proto.
				 */
				gsproto = NULL;
			} else if (gsproto != NULL) {
				/*
				 * Since getservbyname & getprotobyname don't
				 * support tcp6, udp6 or sctp6 take off the 6
				 * digit from protocol.
				 */
				if (v6_socket_proto(gsproto))
					gsproto[strlen(gsproto) - 1] = '\0';
			}

			if (getservbyname_r(cfg->svc_name, gsproto, &se, gsbuf,
			    sizeof (gsbuf)) == NULL) {
				if (gsproto != NULL)
					invalid_proto = B_TRUE;
				prop[PT_SVC_NAME_INDEX].ip_error = IVE_INVALID;
			} else if (cfg->istlx && (ti != NULL)) {
				/* LINTED E_BAD_PTR_CAST_ALIGN */
				SS_SETPORT(*(struct sockaddr_storage *)
				    ti->local_addr.buf, se.s_port);
			} else if (!cfg->istlx && (si != NULL)) {
				if ((gsproto != NULL) &&
				    getprotobyname_r(gsproto, &pe, gpbuf,
				    sizeof (gpbuf)) == NULL) {
					invalid_proto = B_TRUE;
				} else {
					si->protocol = pe.p_proto;
				}
				SS_SETPORT(si->local_addr, se.s_port);
			}

		}

		if (p_inf != NULL) {
			p_inf->listen_fd = -1;

			/* add new proto entry to proto_list */
			uu_list_node_init(p_inf, &p_inf->link, proto_info_pool);
			(void) uu_list_insert_after(cfg->proto_list, NULL,
			    p_inf);
		}

		if (nconf != NULL)
			freenetconfigent(nconf);
		if (invalid_proto)
			prop[PT_PROTO_INDEX].ip_error = IVE_INVALID;
	} while (proto != NULL);	/* while just processed a proto */

	/*
	 * Check that the exec string for the start method actually exists and
	 * that the user is either a valid username or uid. Note we don't
	 * mandate the setting of these fields, and don't do any checks
	 * for arg0, hence its absence.
	 */

	if (prop[PT_EXEC_INDEX].ip_error != IVE_UNSET) {
		/* Don't pass any arguments to access() */
		if ((bufp = strdup(
		    prop[PT_EXEC_INDEX].ip_value.iv_string)) == NULL) {
			prop[PT_EXEC_INDEX].ip_error = IVE_INVALID;
		} else {
			if ((cp = strpbrk(bufp, " \t")) != NULL)
				*cp = '\0';

			if ((access(bufp, F_OK) == -1) && (errno == ENOENT))
				prop[PT_EXEC_INDEX].ip_error = IVE_INVALID;
			free(bufp);
		}
	}

	if (prop[PT_USER_INDEX].ip_error != IVE_UNSET) {
		char		pw_buf[NSS_BUFLEN_PASSWD];
		struct passwd	pw;

		if (getpwnam_r(prop[PT_USER_INDEX].ip_value.iv_string, &pw,
		    pw_buf, NSS_BUFLEN_PASSWD) == NULL) {
			errno = 0;
			uidl = strtol(prop[PT_USER_INDEX].ip_value.iv_string,
			    &bufp, 10);
			if ((errno != 0) || (*bufp != '\0') ||
			    (getpwuid_r(uidl, &pw, pw_buf,
			    NSS_BUFLEN_PASSWD) == NULL))
				prop[PT_USER_INDEX].ip_error = IVE_INVALID;
		}
	}

	/*
	 * Iterate through the properties in the array verifying that any
	 * default properties are valid, and setting the return boolean
	 * according to whether any properties were marked invalid.
	 */

	for (i = 0; prop[i].ip_name != NULL; i++) {
		if (prop[i].ip_error == IVE_UNSET)
			continue;

		if (prop[i].ip_default &&
		    !valid_default_prop(prop[i].ip_name, &prop[i].ip_value))
			prop[i].ip_error = IVE_INVALID;

		if (prop[i].ip_error == IVE_INVALID)
			ret = B_FALSE;
	}

	/* pass back the basic_cfg_t if requested and it's a valid config */
	if ((cfgpp != NULL) && ret) {
		*cfgpp = cfg;
	} else {
		destroy_basic_cfg(cfg);
	}

	return (ret);
}
Beispiel #23
0
/* *********************************************************************** */
int NPSL_GetServByNameBasic(const char *serv_name, const char *serv_proto,
	NPSL_SERVENT *serv_ent_ptr, void *serv_ent_buffer_ptr,
	unsigned int serv_ent_buffer_length, unsigned int *required_length,
	char *error_text)
{
	int           return_code = NPSL_SUCCESS;
	NPSL_SERVENT *tmp_ent_ptr;

	if (required_length != NULL)
		*required_length = 0;

	if (serv_name == NULL) {
		if (error_text != NULL)
			strcpy(error_text, "The 'serv_name' parameter is 'NULL'.");
		return_code = NPSL_FAILURE;
	}
	else if (!(*serv_name)) {
		if (error_text != NULL)
			strcpy(error_text, "The 'serv_name' parameter is an empty string.");
		return_code = NPSL_FAILURE;
	}
	else if ((serv_proto != NULL) && (!(*serv_proto))) {
		if (error_text != NULL)
			strcpy(error_text,
		"The 'serv_proto' parameter is not 'NULL', but is an empty string.");
		return_code = NPSL_FAILURE;
	}
	else if ((return_code = NPSL_CheckServEntParams(serv_ent_ptr,
		serv_ent_buffer_ptr, serv_ent_buffer_length, error_text)) !=
		NPSL_SUCCESS)
		;
	else {
#if NPSL_HAS_GETSERVBYNAME_R
		if ((tmp_ent_ptr = getservbyname_r(serv_name, serv_proto,
			serv_ent_ptr, serv_ent_buffer_ptr,
			((int) serv_ent_buffer_length))) == NULL) {
			if (error_text != NULL) {
				sprintf(error_text,
					"%s '%s()' for service name '%-.127s', protocol '%-.127s': ",
					"Unable to get service entry with", "getservbyname_r",
					serv_name, (serv_proto != NULL) ? serv_proto : "*NULL*");
				NPSL_AppendLastErrorString(0, NPSL_MAX_ERROR_TEXT, error_text);
			}
			return_code = NPSL_SUPP_MapLastError();
		}
#else
		if ((tmp_ent_ptr = getservbyname(serv_name, serv_proto)) == NULL) {
			if (error_text != NULL) {
				sprintf(error_text,
					"%s '%s()' for service name '%-.127s', protocol '%-.127s': ",
					"Unable to get service entry with", "getservbyname",
					serv_name, (serv_proto != NULL) ? serv_proto : "*NULL*");
				NPSL_AppendLastErrorString(0, NPSL_MAX_ERROR_TEXT, error_text);
			}
			return_code = NPSL_SUPP_MapLastError();
		}
		else
			return_code = NPSL_CopyServEntFlatBasic(tmp_ent_ptr, serv_ent_ptr,
				serv_ent_buffer_ptr, serv_ent_buffer_length, required_length,
				error_text);
#endif // #if NPSL_HAS_GETSERVBYNAME_R
	}

	return(return_code);
}