sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Support for hostname & hostaddr related functions sl@0: // sl@0: // sl@0: sl@0: #include "SYSIF.H" sl@0: #include "FDESC.H" sl@0: #include <unistd.h> sl@0: #include <stdlib.h> sl@0: #include <sys/errno.h> sl@0: #include "LPOSIX.H" sl@0: #include <sys/socket.h> sl@0: #include <libc/netinet/in.h> sl@0: #include <netdb_r.h> sl@0: #include <string.h> sl@0: #include <in_sock.h> sl@0: #include <networking/dnd_err.h> sl@0: sl@0: extern "C" { sl@0: sl@0: /** sl@0: Get the internet name of this host. Actually this will always return a null sl@0: string with TCPIP 030 and onwards because the "name" of a mobile host sl@0: isn't really very meaningful - in practice the IP address is chosen dynamically sl@0: once you start doing real networking, at which time the ISP can resolve the sl@0: IP address into a name of some sort if you really want. sl@0: @return sl@0: @param name sl@0: @param size sl@0: */ sl@0: EXPORT_C int gethostname (char *name, size_t size) sl@0: { sl@0: int* perrno=__errno(); sl@0: RSocketServ ss; sl@0: TInt err=ss.Connect(1); sl@0: if (err==KErrNone) sl@0: { sl@0: RHostResolver r; sl@0: err=r.Open(ss, AF_INET, KProtocolInetUdp); sl@0: if (err==KErrNone) sl@0: { sl@0: TBuf<128> hostname; sl@0: err=r.GetHostName(hostname); sl@0: if (err==KErrNone) sl@0: { sl@0: if (size>(size_t)hostname.Length()) sl@0: { sl@0: TPtr8 retval((TText8*)name,size); sl@0: retval.Copy(hostname); sl@0: retval.PtrZ(); sl@0: } sl@0: else sl@0: err=ENAMETOOLONG; sl@0: } sl@0: r.Close(); sl@0: } sl@0: ss.Close(); sl@0: } sl@0: return MapError(err,*perrno); sl@0: } sl@0: sl@0: /** sl@0: Get the internet name of the host by address. sl@0: @return sl@0: @param addr Address of the host sl@0: @param length sl@0: @param format sl@0: */ sl@0: EXPORT_C struct hostent* gethostbyaddr (const char* addr, int length, int format) sl@0: { sl@0: return _gethostbyaddr_r(_REENT,addr,length,format); sl@0: } sl@0: sl@0: /** sl@0: Get the internet name of the host by name. sl@0: @return sl@0: @param name Name of the host sl@0: */ sl@0: EXPORT_C struct hostent* gethostbyname (const char* name) sl@0: { sl@0: return _gethostbyname_r(_REENT,name); sl@0: } sl@0: sl@0: enum GetHostType {ByName = 1, ByAddr}; sl@0: sl@0: #define MAX_ADDR_OR_ALIAS_LIST 5 sl@0: sl@0: struct hostent_buf sl@0: { sl@0: struct hostent iHostent; sl@0: char *iAliasesPtr[MAX_ADDR_OR_ALIAS_LIST+1]; sl@0: char *iAddrListPtr[MAX_ADDR_OR_ALIAS_LIST+1]; sl@0: THostName iHostAliases[MAX_ADDR_OR_ALIAS_LIST]; sl@0: struct sockaddr iHostAddress[MAX_ADDR_OR_ALIAS_LIST]; sl@0: }; sl@0: sl@0: struct hostent* mapNameRecord(struct _reent* rp, TFixedArray<TNameRecord, MAX_ADDR_OR_ALIAS_LIST>& aRecord, const TInt aCount, const GetHostType aHostType, const int aLength, const int aFormat) sl@0: { sl@0: free(rp->_netdb); sl@0: struct hostent_buf* hbp = (struct hostent_buf*)calloc(1,sizeof(struct hostent_buf)); sl@0: rp->_netdb = hbp; sl@0: if (hbp==0) sl@0: { sl@0: rp->_errno=ENOMEM; sl@0: return 0; sl@0: } sl@0: sl@0: // Set-up Aliases & Address list pointer sl@0: hbp->iHostent.h_aliases = &hbp->iAliasesPtr[0]; sl@0: hbp->iHostent.h_addr_list = &hbp->iAddrListPtr[0]; sl@0: sl@0: // Fill-up Host Name sl@0: hbp->iHostent.h_name = (char*) &hbp->iHostAliases[0]; sl@0: TPtr8 name((TText8*)&hbp->iHostAliases[0], aRecord[0].iName.Length()+1); sl@0: name.Copy(aRecord[0].iName); sl@0: name.ZeroTerminate(); sl@0: sl@0: hbp->iHostent.h_addrtype = aFormat; sl@0: hbp->iHostent.h_length = aLength; sl@0: sl@0: // Fill-up Address sl@0: hbp->iAddrListPtr[0] = (char*)&hbp->iHostAddress[0].sa_data[0]; // ... which is iAddr sl@0: unsigned long len=sizeof(struct sockaddr); sl@0: aRecord[0].iAddr.SetFamily(aFormat); // not set by GetByName(_L("")); sl@0: STATIC_CAST(TUSockAddr*,&aRecord[0].iAddr)->Get(&hbp->iHostAddress[0],&len); sl@0: sl@0: if (aCount > 1) sl@0: { sl@0: // If there are multiple host name or address sl@0: TInt i; sl@0: if (aHostType == ByName) sl@0: { sl@0: // there are multiple addresses for a given host sl@0: hbp->iAliasesPtr[0] = NULL; sl@0: for (i=1; i<aCount; i++) sl@0: { sl@0: hbp->iAddrListPtr[i] = (char*)&hbp->iHostAddress[i].sa_data[0]; sl@0: len=sizeof(struct sockaddr); sl@0: aRecord[i].iAddr.SetFamily(aFormat); // not set by GetByName(_L("")); sl@0: STATIC_CAST(TUSockAddr*,&aRecord[i].iAddr)->Get(&hbp->iHostAddress[i],&len); sl@0: } sl@0: hbp->iAddrListPtr[i] = NULL; sl@0: } sl@0: else sl@0: { sl@0: // there are multiple host/aliases name for a given address sl@0: hbp->iAddrListPtr[1] = NULL; sl@0: for (i=1; i<aCount; i++) sl@0: { sl@0: hbp->iAliasesPtr[i-1] = (char*) &hbp->iHostAliases[i]; sl@0: name.Set((TText8*)&hbp->iHostAliases[i], 0, aRecord[i].iName.Length()+1); sl@0: name.Copy(aRecord[i].iName); sl@0: name.ZeroTerminate(); sl@0: } sl@0: hbp->iAliasesPtr[i-1] = NULL; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: hbp->iAliasesPtr[0] = NULL; sl@0: hbp->iAddrListPtr[1] = NULL; sl@0: } sl@0: return &hbp->iHostent; sl@0: } sl@0: sl@0: /** sl@0: Get the internet name of the host by address. sl@0: @return sl@0: @param rp pointer sl@0: @param addr sl@0: @param length sl@0: @param format sl@0: */ sl@0: EXPORT_C struct hostent* _gethostbyaddr_r (struct _reent* rp, const char* addr, int length, int format) sl@0: // sl@0: // For AF_INET, sl@0: { sl@0: RSocketServ ss; sl@0: TInt err=ss.Connect(); sl@0: struct hostent* retval=0; sl@0: if (err==KErrNone) sl@0: { sl@0: RHostResolver r; sl@0: err=r.Open(ss, AF_INET, KProtocolInetUdp); sl@0: if (err==KErrNone) sl@0: { sl@0: struct sockaddr buf; sl@0: buf.sa_family=(unsigned short)format; sl@0: memcpy(buf.sa_data,addr,length); sl@0: TUSockAddr addr(&buf,length+4); sl@0: sl@0: TFixedArray<TNameRecord, MAX_ADDR_OR_ALIAS_LIST> record; sl@0: TNameEntry entry; sl@0: TInt count = 0; sl@0: err=r.GetByAddress(addr,entry); sl@0: if (err==KErrNone) sl@0: { sl@0: record[count++]=entry(); sl@0: while ((r.Next(entry) == KErrNone) && (count < MAX_ADDR_OR_ALIAS_LIST)) sl@0: { sl@0: record[count++] = entry(); sl@0: } sl@0: retval = mapNameRecord(rp, record, count, ByAddr, length, format); sl@0: } sl@0: r.Close(); sl@0: } sl@0: ss.Close(); sl@0: } sl@0: if (err==-3004) // NETDIAL busy sl@0: err=TRY_AGAIN; sl@0: sl@0: // KErrDndAddrNotFound=-5121 should be excluded (Returned when no data found for GetByAddr) sl@0: if ((err<-3000) && (err!=KErrDndAddrNotFound)) // i.e. a NETDIAL error sl@0: err=NO_RECOVERY; sl@0: MapError(err,rp->_errno); sl@0: return retval; sl@0: } sl@0: sl@0: /** sl@0: Get the internet name of the host by name. sl@0: @return sl@0: @param rp sl@0: @param name name of the host sl@0: */ sl@0: EXPORT_C struct hostent* _gethostbyname_r (struct _reent* rp, const char* name) sl@0: { sl@0: RSocketServ ss; sl@0: TInt err=ss.Connect(); sl@0: struct hostent* retval=0; sl@0: if (err==KErrNone) sl@0: { sl@0: RHostResolver r; sl@0: err=r.Open(ss, AF_INET, KProtocolInetUdp); sl@0: if (err==KErrNone) sl@0: { sl@0: TFixedArray<TNameRecord, MAX_ADDR_OR_ALIAS_LIST> record; sl@0: TNameEntry entry; sl@0: #ifdef _UNICODE sl@0: TPtrC8 ptr(REINTERPRET_CAST(const TUint8*,name)); sl@0: TBuf<0x40> hostname; sl@0: hostname.Copy(ptr); sl@0: #else sl@0: TPtrC8 hostname(REINTERPRET_CAST(const TUint8*,name)); sl@0: #endif /* _UNICODE */ sl@0: sl@0: TInt count = 0; sl@0: err=r.GetByName(hostname,entry); sl@0: if (err==KErrNone) sl@0: { sl@0: record[count++]=entry(); sl@0: while ((r.Next(entry) == KErrNone) && (count < MAX_ADDR_OR_ALIAS_LIST)) sl@0: { sl@0: record[count++] = entry(); sl@0: } sl@0: retval = mapNameRecord(rp, record, count, ByName, sizeof(struct in_addr), AF_INET); sl@0: } sl@0: r.Close(); sl@0: } sl@0: ss.Close(); sl@0: } sl@0: if (err==-3004) // NETDIAL busy sl@0: err=TRY_AGAIN; sl@0: sl@0: // KErrDndNameNotFound=-5120 should be excluded (Returned when no data found for GetByName) sl@0: if ((err<-3000) && (err!=KErrDndNameNotFound)) // i.e. a NETDIAL error sl@0: err=NO_RECOVERY; sl@0: MapError(err,rp->_errno); sl@0: return retval; sl@0: } sl@0: sl@0: } // extern "C"