view dcclib/su2str.c @ 0:c7f6b056b673

First import of vendor version
author Peter Gervai <grin@grin.hu>
date Tue, 10 Mar 2009 13:49:58 +0100
parents
children
line wrap: on
line source

/* Distributed Checksum Clearinghouse
 *
 * Copyright (c) 2008 by Rhyolite Software, LLC
 *
 * This agreement is not applicable to any entity which sells anti-spam
 * solutions to others or provides an anti-spam solution as part of a
 * security solution sold to other entities, or to a private network
 * which employs the DCC or uses data provided by operation of the DCC
 * but does not provide corresponding data to other users.
 *
 * Permission to use, copy, modify, and distribute this software without
 * changes for any purpose with or without fee is hereby granted, provided
 * that the above copyright notice and this permission notice appear in all
 * copies and any distributed versions or copies are either unchanged
 * or not called anything similar to "DCC" or "Distributed Checksum
 * Clearinghouse".
 *
 * Parties not eligible to receive a license under this agreement can
 * obtain a commercial license to use DCC by contacting Rhyolite Software
 * at sales@rhyolite.com.
 *
 * A commercial license would be for Distributed Checksum and Reputation
 * Clearinghouse software.  That software includes additional features.  This
 * free license for Distributed ChecksumClearinghouse Software does not in any
 * way grant permision to use Distributed Checksum and Reputation Clearinghouse
 * software
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 *
 * Rhyolite Software DCC 1.3.103-1.42 $Revision$
 */

#include "dcc_defs.h"
#ifndef DCC_WIN32
#include <arpa/inet.h>
#endif

#if !defined(HAVE_INET_NTOP) || defined(NO_IPV6)
#define DCC_INET_NTOP dcc_inet_ntop
extern const char *DCC_INET_NTOP(int, const void *, char *, size_t);
#else
#define DCC_INET_NTOP inet_ntop
#endif



/* strip IPv6 prefix from ::ffff:10.2.3.4 */
const char *
dcc_trim_ffff(const char *str)
{
	return strncmp("::ffff:", str, 7) ? str : (str+7);
}



const char *
dcc_ipv4tostr(char *buf, int buf_len, const struct in_addr *addr4)
{
	if (!DCC_INET_NTOP(AF_INET, addr4, buf, buf_len))
		STRLCPY(buf, "???", buf_len);
	return buf;
}



const char *
dcc_ipv6tostr(char *buf, int buf_len, const struct in6_addr *addr6)
{
	if (!DCC_INET_NTOP(AF_INET6, addr6, buf, buf_len))
		STRLCPY(buf, "???", buf_len);
	return buf;
}



const char *
dcc_ipv6tostr2(char *buf, int buf_len, const struct in6_addr *addr6)
{
	struct in_addr addr4;

	if (dcc_ipv6toipv4(&addr4, addr6))
		return dcc_ipv4tostr(buf, buf_len, &addr4);

	if (!DCC_INET_NTOP(AF_INET6, addr6, buf, buf_len))
		STRLCPY(buf, "???", buf_len);
	return buf;
}



const char *
dcc_ip2str(char *buf, int buf_len, const DCC_IP *ip)
{
	if (ip->family == AF_INET)
		return dcc_ipv4tostr(buf, buf_len, &ip->u.v4);
	else
		return dcc_ipv6tostr(buf, buf_len, &ip->u.v6);
}



/* convert to a string including the port number.
 *	try to make a short IPv4 string */
const char *
dcc_su2str(char *buf, int buf_len, const DCC_SOCKU *su)
{
	int i;

	if (su->sa.sa_family == AF_INET) {
		dcc_ipv4tostr(buf, buf_len, &su->ipv4.sin_addr);
	} else {
		dcc_ipv6tostr2(buf, buf_len, &su->ipv6.sin6_addr);
	}
	i = strlen(buf);
	snprintf(buf+i, buf_len-i, ",%d", ntohs(*DCC_SU_PORTP(su)));
	return buf;
}



/* convert to a string without the port number.
 *	try to make a short IPv4 string */
const char *
dcc_su2str2(char *buf, int buf_len, const DCC_SOCKU *su)
{
	if (su->sa.sa_family == AF_INET)
		return dcc_ipv4tostr(buf, buf_len, &su->ipv4.sin_addr);

	return dcc_ipv6tostr2(buf, buf_len, &su->ipv6.sin6_addr);
}



/* convert to a string without a boring port number
 *	try to make a short IPv4 string */
const char *
dcc_su2str3(char *buf, int buf_len, const DCC_SOCKU *su, u_short port)
{
	if (*DCC_SU_PORTP(su) != port) {
		return dcc_su2str(buf, buf_len, su);
	} else {
		return dcc_su2str2(buf, buf_len, su);
	}
}



/* Convert IP address to a string, but not into a single buffer
 *	This is not thread safe but good enough for error messages */
const char *
dcc_su2str_err(const DCC_SOCKU *su)
{
	static int bufno;
	static struct {
	    char    str[DCC_SU2STR_SIZE];
	} bufs[4];
	char *s;

	s = bufs[bufno].str;
	bufno = (bufno+1) % DIM(bufs);
	return dcc_su2str(s, sizeof(bufs[0].str), su);
}



const char *
dcc_host_portname(char *buf, int buf_len,
		  const char *hostname, const char *portname)
{
	if (!portname || *portname == '\0' || !strcmp(portname, "-")) {
		STRLCPY(buf, hostname, buf_len);
	} else {
		snprintf(buf, buf_len, "%s,%s", hostname, portname);
	}
	return buf;
}



/* Convert IP address to a name */
const char *
dcc_su2name(char *name, int name_len, const DCC_SOCKU *su)
{
#undef EXPANDED
#if defined(USE_GETIPNODEBYNAME) && !defined(EXPANDED) && !defined(NO_IPV6)
#define EXPANDED
	struct hostent *hp;
	int error;

	dcc_host_lock();
	if (su->sa.sa_family == AF_INET)
		hp = getipnodebyaddr(&su->ipv4.sin_addr,
				     sizeof(su->ipv4.sin_addr),
				     su->sa.sa_family, &error);
	else
		hp = getipnodebyaddr(&su->ipv6.sin6_addr,
				     sizeof(su->ipv6.sin6_addr),
				     su->sa.sa_family, &error);
	if (!hp) {
		if (name_len > 0)
			*name = '\0';
	} else {
		if (name_len > 0)
			STRLCPY(name, hp->h_name, name_len);
		freehostent(hp);
	}
	dcc_host_unlock();
#endif
#if defined(USE_GETADDRINFO) && !defined(EXPANDED) && !defined(NO_IPV6)
#define EXPANDED
	int error;

	dcc_host_lock();
	error = getnameinfo(&su->sa, DCC_SU_LEN(su),
			    name, name_len, 0, 0, NI_NAMEREQD);
	dcc_host_unlock();
	if (error && name_len > 0)
		*name = '\0';
#endif
#ifndef EXPANDED
	struct hostent *hp;
	DCC_SOCKU su4;

	dcc_host_lock();
	if (dcc_ipv6sutoipv4(&su4, su)) {
		hp = gethostbyaddr((char *)&su4.ipv4.sin_addr,
				   sizeof(su4.ipv4.sin_addr),
				   AF_INET);
	} else {
		hp = 0;
	}
	if (name_len > 0)
		STRLCPY(name, hp ? hp->h_name : "", name_len);
	dcc_host_unlock();
#endif
	return name;
#undef EXPANDED
}