Projekt

Allgemein

Profil

Herunterladen (10,4 KB) Statistiken
| Zweig: | Markierung: | Revision:
/***************************************************************************
$RCSfile$
-------------------
cvs : $Id$
begin : Tue Oct 02 2002
copyright : (C) 2002 by Martin Preuss
email : martin@libchipcard.de

***************************************************************************
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
* MA 02111-1307 USA *
* *
***************************************************************************/


#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "inetaddr_p.h"
#include <gwenhywfar/misc.h>
#include <stdlib.h>
#include <assert.h>
#include <netdb.h>
#include <string.h>
#include <sys/un.h>
#include <arpa/inet.h>

#include "gwenhywfar/debug.h"

/* #define MEMTRACE */

/* needed for Solaris */
#ifndef SUN_LEN
# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
+ strlen ((ptr)->sun_path))
#endif


#ifdef MEMTRACE
static int GWEN_INETADDR__Counter=0;
#endif


uint32_t GWEN_InetAddr_GetCapabilities(void)
{
return
GWEN_INETADDR_CAPS_AF_TCP |
GWEN_INETADDR_CAPS_AF_UNIX;
}



int GWEN_InetAddr_ModuleInit(void)
{
return 0;
}



int GWEN_InetAddr_ModuleFini(void)
{
return 0;
}



GWEN_INETADDRESS *GWEN_InetAddr_new(GWEN_AddressFamily af)
{
GWEN_INETADDRESS *ia;

GWEN_NEW_OBJECT(GWEN_INETADDRESS, ia);

ia->af=af;
switch (ia->af) {
case GWEN_AddressFamilyIP: {
struct sockaddr_in *aptr;

ia->address=(struct sockaddr *)malloc(sizeof(struct sockaddr_in));
assert(ia->address);
aptr=(struct sockaddr_in *)(ia->address);
ia->size=sizeof(struct sockaddr_in);
memset(ia->address, 0, ia->size);
#ifdef PF_INET
aptr->sin_family=PF_INET;
#else
aptr->sin_family=AF_INET;
#endif
break;
}

case GWEN_AddressFamilyUnix: {
struct sockaddr_un *aptr;

ia->address=(struct sockaddr *)malloc(sizeof(struct sockaddr_un));
assert(ia->address);
aptr=(struct sockaddr_un *)(ia->address);
#if defined(PF_UNIX)
aptr->sun_family=PF_UNIX;
#elif defined (AF_UNIX)
aptr->sun_family=AF_UNIX;
#else
DBG_ERROR(GWEN_LOGDOMAIN, "No unix domain sockets available for this system");
GWEN_InetAddr_free(ia);
return 0;
#endif
aptr->sun_path[0]=0;
ia->size=sizeof(struct sockaddr_un);
memset(ia->address, 0, ia->size);
break;
}

default:
DBG_INFO(GWEN_LOGDOMAIN, "Unknown address family (%d)", af);
assert(0);
} /* switch */
#ifdef MEMTRACE
GWEN_INETADDR__Counter++;
DBG_INFO(GWEN_LOGDOMAIN, "InetAddr created, now %d", GWEN_INETADDR__Counter);
#endif
return ia;
}



GWEN_INETADDRESS *GWEN_InetAddr_dup(const GWEN_INETADDRESS *oa)
{
GWEN_INETADDRESS *ia;

GWEN_NEW_OBJECT(GWEN_INETADDRESS, ia);
ia->af=oa->af;
ia->size=oa->size;
//ia->address=(struct sockaddr *)malloc(sizeof(struct sockaddr));
if (oa->size) {
ia->address=(struct sockaddr *)malloc(oa->size);
assert(ia->address);
memmove(ia->address, oa->address, oa->size);
}
return ia;
}



void GWEN_InetAddr_free(GWEN_INETADDRESS *ia)
{
if (ia) {
#ifdef MEMTRACE
GWEN_INETADDR__Counter--;
DBG_INFO(GWEN_LOGDOMAIN, "Free InetAddr, makes %d", GWEN_INETADDR__Counter);
#endif
free(ia->address);
GWEN_FREE_OBJECT(ia);
}
}



int GWEN_InetAddr_SetAddress(GWEN_INETADDRESS *ia,
const char *addr)
{
assert(ia);

switch (ia->af) {
case GWEN_AddressFamilyIP: {
struct sockaddr_in *aptr;

aptr=(struct sockaddr_in *)(ia->address);
/* reset */
#ifdef PF_INET
aptr->sin_family=PF_INET;
#elif defined (AF_INET)
aptr->sun_family=AF_INET;
#else
DBG_ERROR(GWEN_LOGDOMAIN, "No TCP sockets available for this system");
return GWEN_ERROR_BAD_ADDRESS_FAMILY;
#endif
aptr->sin_addr.s_addr=0;

if (addr) {
/* ok, address to be set */
if (!inet_aton(addr, &aptr->sin_addr))
/* bad address, so maybe it rather is a name */
return GWEN_ERROR_BAD_ADDRESS;
}
break;
}

case GWEN_AddressFamilyUnix: {
struct sockaddr_un *aptr;

aptr=(struct sockaddr_un *)(ia->address);
#ifdef PF_UNIX
aptr->sun_family=PF_UNIX;
#elif defined (AF_UNIX)
aptr->sun_family=AF_UNIX;
#else
DBG_ERROR(GWEN_LOGDOMAIN, "No unix domain sockets available for this system");
return GWEN_ERROR_BAD_ADDRESS_FAMILY;
#endif
memset(aptr->sun_path, 0, sizeof(aptr->sun_path));
if (addr) {
/* ok, address to be set */
if ((strlen(addr)+1)>sizeof(aptr->sun_path)) {
/* bad address */
DBG_INFO(GWEN_LOGDOMAIN, "Path too long (%d>%d)",
(int)(strlen(addr)+1), (int)(sizeof(aptr->sun_path)));
return GWEN_ERROR_BAD_ADDRESS;
}
strcpy(aptr->sun_path, addr);
ia->size=SUN_LEN(aptr);
}
break;
}
default:
return GWEN_ERROR_BAD_ADDRESS_FAMILY;
} /* switch */

return 0;
}



/* internal function */
int GWEN_InetAddr_TranslateHError(int herr)
{
int rv;

switch (herr) {
case HOST_NOT_FOUND:
rv=GWEN_ERROR_HOST_NOT_FOUND;
break;
#ifdef NO_ADDRESS
case NO_ADDRESS:
rv=GWEN_ERROR_NO_ADDRESS;
break;
#endif
case NO_RECOVERY:
rv=GWEN_ERROR_NO_RECOVERY;
break;
case TRY_AGAIN:
rv=GWEN_ERROR_TRY_AGAIN;
break;
default:
rv=GWEN_ERROR_UNKNOWN_DNS_ERROR;
break;
} /* switch */
return rv;
}



int GWEN_InetAddr_SetName(GWEN_INETADDRESS *ia, const char *name)
{
struct hostent *he;

assert(ia);

switch (ia->af) {
case GWEN_AddressFamilyIP: {
struct sockaddr_in *aptr;

aptr=(struct sockaddr_in *)(ia->address);
/* try to resolve name */
he=gethostbyname(name);
if (!he)
return GWEN_InetAddr_TranslateHError(h_errno);
/* name resolved, store address */
memcpy(&(aptr->sin_addr),
he->h_addr_list[0],
sizeof(struct in_addr));
break;
}

case GWEN_AddressFamilyUnix: {
struct sockaddr_un *aptr;

aptr=(struct sockaddr_un *)(ia->address);
#ifdef PF_UNIX
aptr->sun_family=PF_UNIX;
#elif defined (AF_UNIX)
aptr->sun_family=AF_UNIX;
#else
DBG_ERROR(GWEN_LOGDOMAIN, "No unix domain sockets available for this system");
return GWEN_ERROR_BAD_ADDRESS_FAMILY;
#endif
aptr->sun_path[0]=0;

if (name) {
/* ok, address to be set */
if ((strlen(name)+1)>sizeof(aptr->sun_path)) {
/* bad address */
DBG_INFO(GWEN_LOGDOMAIN, "Path too long (%d>%d)",
(int)(strlen(name)+1), (int)(sizeof(aptr->sun_path)));
return GWEN_ERROR_BAD_ADDRESS;
}
strcpy(aptr->sun_path, name);
ia->size=SUN_LEN(aptr);
}
break;
}

default:
return GWEN_INETADDR_ERROR_BAD_ADDRESS_FAMILY;
} /* switch */
return 0;
}



int GWEN_InetAddr_GetAddress(const GWEN_INETADDRESS *ia,
char *buffer, unsigned int bsize)
{
const char *s;

assert(ia);
assert(buffer);

switch (ia->af) {
case GWEN_AddressFamilyIP: {
struct sockaddr_in *aptr;

aptr=(struct sockaddr_in *)(ia->address);
s=inet_ntoa(aptr->sin_addr);
assert(s);
if (strlen(s)+1>bsize)
return GWEN_ERROR_BUFFER_OVERFLOW;
strcpy(buffer, s);
break;
}

case GWEN_AddressFamilyUnix: {
struct sockaddr_un *aptr;
int i;

aptr=(struct sockaddr_un *)(ia->address);
s=aptr->sun_path;
i=ia->size;
i-=sizeof(aptr->sun_family);
if (i+1>(int)bsize)
return GWEN_ERROR_BUFFER_OVERFLOW;
memmove(buffer, s, i);
buffer[i]=0;
break;
}

default:
return GWEN_ERROR_BAD_ADDRESS_FAMILY;
} /* switch */
return 0;
}



int GWEN_InetAddr_GetName(const GWEN_INETADDRESS *ia,
char *buffer, unsigned int bsize)
{
struct hostent *he;
struct in_addr lia;

assert(ia);
assert(buffer);

switch (ia->af) {
case GWEN_AddressFamilyIP: {
struct sockaddr_in *aptr;

aptr=(struct sockaddr_in *)(ia->address);
/* resolve name from address */
lia=aptr->sin_addr;
#ifdef PF_INET
he=gethostbyaddr((char *)&lia, sizeof(lia), PF_INET);
#else
he=gethostbyaddr((char *)&lia, sizeof(lia), AF_INET);
#endif
if (!he)
return GWEN_InetAddr_TranslateHError(h_errno);

/* copy name into given buffer */
assert(he->h_name);
if (strlen(he->h_name)+1>bsize)
return GWEN_ERROR_BUFFER_OVERFLOW;
/* copy the name into the buffer */
strcpy(buffer, he->h_name);
break;
}

case GWEN_AddressFamilyUnix: {
struct sockaddr_un *aptr;

aptr=(struct sockaddr_un *)(ia->address);
/* simply copy path */
if (strlen(aptr->sun_path)+1>bsize)
return GWEN_ERROR_BUFFER_OVERFLOW;
strcpy(buffer, aptr->sun_path);
break;
}

default:
return GWEN_INETADDR_ERROR_BAD_ADDRESS_FAMILY;

} /* switch */

/* finished */
return 0;
}



int GWEN_InetAddr_GetPort(const GWEN_INETADDRESS *ia)
{
int i;

assert(ia);

switch (ia->af) {
case GWEN_AddressFamilyIP: {
struct sockaddr_in *aptr;

aptr=(struct sockaddr_in *)(ia->address);
i=ntohs(aptr->sin_port);
break;
}

default:
DBG_INFO(GWEN_LOGDOMAIN, "not an IP address");
i=0;
} /* switch */

return i;
}



int GWEN_InetAddr_SetPort(GWEN_INETADDRESS *ia, int port)
{
assert(ia);

switch (ia->af) {
case GWEN_AddressFamilyIP: {
struct sockaddr_in *aptr;

aptr=(struct sockaddr_in *)(ia->address);
aptr->sin_port=htons(port);
break;
}

default:
return GWEN_ERROR_BAD_ADDRESS_FAMILY;
} /* switch */
return 0;
}






(10-10/26)