Use iphlpapi to enumerate LAN adapters.
Add names to NetBIOS transports, and eliminates loopback adapters from enumerated LAN adapters.
This commit is contained in:
parent
9d5295f5bd
commit
c5e856a300
|
@ -4,7 +4,7 @@ TOPOBJDIR = ../..
|
|||
SRCDIR = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
MODULE = netapi32.dll
|
||||
IMPORTS = advapi32 kernel32
|
||||
IMPORTS = iphlpapi advapi32 kernel32
|
||||
|
||||
LDDLLFLAGS = @LDDLLFLAGS@
|
||||
SYMBOLFILE = $(MODULE).tmp.o
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
|
@ -33,183 +34,73 @@
|
|||
#include "winerror.h"
|
||||
#include "nb30.h"
|
||||
#include "lmcons.h"
|
||||
|
||||
#ifdef HAVE_SYS_FILE_H
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKIO_H
|
||||
# include <sys/sockio.h>
|
||||
#endif
|
||||
#ifdef HAVE_NET_IF_H
|
||||
# include <net/if.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
# ifndef max
|
||||
# define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
# endif
|
||||
# define ifreq_size(i) max(sizeof(struct ifreq),\
|
||||
sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
|
||||
# else
|
||||
# define ifreq_size(i) sizeof(struct ifreq)
|
||||
# endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
|
||||
#include "iphlpapi.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(netbios);
|
||||
|
||||
HMODULE NETAPI32_hModule = 0;
|
||||
|
||||
struct NetBiosAdapter
|
||||
{
|
||||
int valid;
|
||||
unsigned char address[6];
|
||||
};
|
||||
|
||||
static struct NetBiosAdapter NETBIOS_Adapter[MAX_LANA];
|
||||
|
||||
# ifdef SIOCGIFHWADDR
|
||||
int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
|
||||
{
|
||||
if (ioctl(sd, SIOCGIFHWADDR, ifr) < 0)
|
||||
return -1;
|
||||
memcpy(address, (unsigned char *)&ifr->ifr_hwaddr.sa_data, 6);
|
||||
return 0;
|
||||
}
|
||||
# else
|
||||
# ifdef SIOCGENADDR
|
||||
int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
|
||||
{
|
||||
if (ioctl(sd, SIOCGENADDR, ifr) < 0)
|
||||
return -1;
|
||||
memcpy(address, (unsigned char *) ifr->ifr_enaddr, 6);
|
||||
return 0;
|
||||
}
|
||||
# else
|
||||
int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
# endif /* SIOCGENADDR */
|
||||
# endif /* SIOCGIFHWADDR */
|
||||
|
||||
int enum_hw(void)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef HAVE_NET_IF_H
|
||||
int sd;
|
||||
struct ifreq ifr, *ifrp;
|
||||
struct ifconf ifc;
|
||||
unsigned char buf[1024];
|
||||
int i, ofs;
|
||||
/* BSD 4.4 defines the size of an ifreq to be
|
||||
* max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
|
||||
* However, under earlier systems, sa_len isn't present, so
|
||||
* the size is just sizeof(struct ifreq)
|
||||
*/
|
||||
|
||||
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (sd < 0)
|
||||
return NRC_OPENERROR;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ifc.ifc_len = sizeof(buf);
|
||||
ifc.ifc_buf = buf;
|
||||
/* get the ifconf interface */
|
||||
if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0)
|
||||
{
|
||||
close(sd);
|
||||
return NRC_OPENERROR;
|
||||
}
|
||||
|
||||
/* loop through the interfaces, looking for a valid one */
|
||||
/* n = ifc.ifc_len; */
|
||||
ofs = 0;
|
||||
for (i = 0; i < ifc.ifc_len; i++)
|
||||
{
|
||||
unsigned char *a = NETBIOS_Adapter[i].address;
|
||||
|
||||
ifrp = (struct ifreq *)((char *)ifc.ifc_buf+ofs);
|
||||
strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
|
||||
|
||||
/* try to get the address for this interface */
|
||||
if(get_hw_address(sd, &ifr, a)==0)
|
||||
{
|
||||
/* make sure it's not blank */
|
||||
/* if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
|
||||
continue; */
|
||||
|
||||
TRACE("Found valid adapter %d at %02x:%02x:%02x:%02x:%02x:%02x\n", i,
|
||||
a[0],a[1],a[2],a[3],a[4],a[5]);
|
||||
|
||||
NETBIOS_Adapter[i].valid = TRUE;
|
||||
|
||||
ret++;
|
||||
}
|
||||
ofs += ifreq_size(ifr);
|
||||
}
|
||||
close(sd);
|
||||
TRACE("found %d adapters\n",ret);
|
||||
#endif /* HAVE_NET_IF_H */
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wprint_mac(WCHAR* buffer, int index)
|
||||
{
|
||||
int i;
|
||||
unsigned char val;
|
||||
for (i = 0; i<6; i++)
|
||||
{
|
||||
val = NETBIOS_Adapter[index].address[i];
|
||||
if ((val >>4) >9)
|
||||
buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
|
||||
else
|
||||
buffer[2*i] = (WCHAR)((val >>4) + '0');
|
||||
if ((val & 0xf ) >9)
|
||||
buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
|
||||
else
|
||||
buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
|
||||
}
|
||||
buffer[12]=(WCHAR)0;
|
||||
|
||||
}
|
||||
static UCHAR NETBIOS_Enum(PNCB ncb)
|
||||
{
|
||||
int i;
|
||||
LANA_ENUM *lanas = (PLANA_ENUM) ncb->ncb_buffer;
|
||||
|
||||
DWORD apiReturn, size = 0;
|
||||
PMIB_IFTABLE table;
|
||||
UCHAR ret;
|
||||
|
||||
TRACE("NCBENUM\n");
|
||||
|
||||
lanas->length = 0;
|
||||
for (i = 0; i < enum_hw(); i++)
|
||||
{
|
||||
lanas->lana[lanas->length] = i;
|
||||
lanas->length++;
|
||||
}
|
||||
return NRC_GOODRET;
|
||||
|
||||
apiReturn = GetIfTable(NULL, &size, FALSE);
|
||||
if (apiReturn != NO_ERROR)
|
||||
{
|
||||
table = (PMIB_IFTABLE)malloc(size);
|
||||
if (table)
|
||||
{
|
||||
apiReturn = GetIfTable(table, &size, FALSE);
|
||||
if (apiReturn == NO_ERROR)
|
||||
{
|
||||
lanas->length = 0;
|
||||
for (i = 0; i < table->dwNumEntries && lanas->length < MAX_LANA;
|
||||
i++)
|
||||
{
|
||||
if (table->table[i].dwType != MIB_IF_TYPE_LOOPBACK)
|
||||
{
|
||||
lanas->lana[lanas->length] = table->table[i].dwIndex;
|
||||
lanas->length++;
|
||||
}
|
||||
}
|
||||
ret = NRC_GOODRET;
|
||||
}
|
||||
else
|
||||
ret = NRC_SYSTEM;
|
||||
free(table);
|
||||
}
|
||||
else
|
||||
ret = NRC_NORESOURCES;
|
||||
}
|
||||
else
|
||||
ret = NRC_SYSTEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static UCHAR NETBIOS_Astat(PNCB ncb)
|
||||
{
|
||||
struct NetBiosAdapter *nad = &NETBIOS_Adapter[ncb->ncb_lana_num];
|
||||
PADAPTER_STATUS astat = (PADAPTER_STATUS) ncb->ncb_buffer;
|
||||
|
||||
MIB_IFROW row;
|
||||
|
||||
TRACE("NCBASTAT (Adapter %d)\n", ncb->ncb_lana_num);
|
||||
|
||||
if(!nad->valid)
|
||||
return NRC_INVADDRESS;
|
||||
|
||||
|
||||
memset(astat, 0, sizeof astat);
|
||||
memcpy(astat->adapter_address, nad->address, sizeof astat->adapter_address);
|
||||
|
||||
|
||||
row.dwIndex = ncb->ncb_lana_num;
|
||||
if (GetIfEntry(&row) != NO_ERROR)
|
||||
return NRC_INVADDRESS;
|
||||
/* doubt anyone cares, but why not.. */
|
||||
if (row.dwType == MIB_IF_TYPE_TOKENRING)
|
||||
astat->adapter_type = 0xff;
|
||||
else
|
||||
astat->adapter_type = 0xfe; /* for Ethernet */
|
||||
return NRC_GOODRET;
|
||||
}
|
||||
|
||||
|
@ -241,9 +132,16 @@ BOOL WINAPI Netbios(PNCB pncb)
|
|||
{
|
||||
case NCBRESET:
|
||||
FIXME("NCBRESET adapter %d\n",pncb->ncb_lana_num);
|
||||
if( (pncb->ncb_lana_num < MAX_LANA ) &&
|
||||
NETBIOS_Adapter[pncb->ncb_lana_num].valid)
|
||||
ret = NRC_GOODRET;
|
||||
if(pncb->ncb_lana_num < MAX_LANA )
|
||||
{
|
||||
MIB_IFROW row;
|
||||
|
||||
row.dwIndex = pncb->ncb_lana_num;
|
||||
if (GetIfEntry(&row) != NO_ERROR)
|
||||
ret = NRC_GOODRET;
|
||||
else
|
||||
ret = NRC_ILLCMD; /* NetBIOS emulator not found */
|
||||
}
|
||||
else
|
||||
ret = NRC_ILLCMD; /* NetBIOS emulator not found */
|
||||
break;
|
||||
|
|
|
@ -18,12 +18,14 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "winbase.h"
|
||||
#include "nb30.h"
|
||||
#include "lmcons.h"
|
||||
#include "lmapibuf.h"
|
||||
#include "lmerr.h"
|
||||
#include "lmwksta.h"
|
||||
#include "iphlpapi.h"
|
||||
#include "winerror.h"
|
||||
#include "winternl.h"
|
||||
#include "ntsecapi.h"
|
||||
|
@ -59,8 +61,53 @@ BOOL NETAPI_IsLocalComputer(LPCWSTR ServerName)
|
|||
}
|
||||
}
|
||||
|
||||
int enum_hw(void);
|
||||
void wprint_mac(WCHAR* buffer, int index);
|
||||
static void wprint_mac(WCHAR* buffer, PIP_ADAPTER_INFO adapter)
|
||||
{
|
||||
if (adapter != NULL)
|
||||
{
|
||||
int i;
|
||||
unsigned char val;
|
||||
|
||||
for (i = 0; i<max(adapter->AddressLength, 6); i++)
|
||||
{
|
||||
val = adapter->Address[i];
|
||||
if ((val >>4) >9)
|
||||
buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
|
||||
else
|
||||
buffer[2*i] = (WCHAR)((val >>4) + '0');
|
||||
if ((val & 0xf ) >9)
|
||||
buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
|
||||
else
|
||||
buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
|
||||
}
|
||||
buffer[12]=(WCHAR)0;
|
||||
}
|
||||
else
|
||||
buffer[0] = 0;
|
||||
}
|
||||
|
||||
#define TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
|
||||
#define TRANSPORT_NAME_LEN \
|
||||
(sizeof(TRANSPORT_NAME_HEADER) + MAX_ADAPTER_NAME_LENGTH)
|
||||
|
||||
static void wprint_name(WCHAR *buffer, int len, PIP_ADAPTER_INFO adapter)
|
||||
{
|
||||
WCHAR *ptr;
|
||||
const char *name;
|
||||
|
||||
if (!buffer)
|
||||
return;
|
||||
if (!adapter)
|
||||
return;
|
||||
|
||||
for (ptr = buffer, name = TRANSPORT_NAME_HEADER; *name && ptr < buffer + len;
|
||||
ptr++, name++)
|
||||
*ptr = *name;
|
||||
for (name = adapter->AdapterName; name && *name && ptr < buffer + len;
|
||||
ptr++, name++)
|
||||
*ptr = *name;
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
NET_API_STATUS WINAPI
|
||||
NetWkstaTransportEnum(LPCWSTR ServerName, DWORD level, LPBYTE* pbuf,
|
||||
|
@ -84,49 +131,73 @@ NetWkstaTransportEnum(LPCWSTR ServerName, DWORD level, LPBYTE* pbuf,
|
|||
|
||||
switch (level)
|
||||
{
|
||||
case 0: /* transport info */
|
||||
{
|
||||
PWKSTA_TRANSPORT_INFO_0 ti;
|
||||
int i,size_needed,n_adapt = enum_hw();
|
||||
|
||||
if (n_adapt == 0)
|
||||
case 0: /* transport info */
|
||||
{
|
||||
PWKSTA_TRANSPORT_INFO_0 ti;
|
||||
int i,size_needed,n_adapt;
|
||||
DWORD apiReturn, adaptInfoSize = 0;
|
||||
PIP_ADAPTER_INFO info, ptr;
|
||||
|
||||
apiReturn = GetAdaptersInfo(NULL, &adaptInfoSize);
|
||||
if (apiReturn == ERROR_NO_DATA)
|
||||
return ERROR_NETWORK_UNREACHABLE;
|
||||
if (!read_entries)
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
if (!total_entries || !pbuf)
|
||||
return RPC_X_NULL_REF_POINTER;
|
||||
|
||||
size_needed = n_adapt * (sizeof(WKSTA_TRANSPORT_INFO_0)
|
||||
* 13 * sizeof (WCHAR));
|
||||
if (prefmaxlen == MAX_PREFERRED_LENGTH)
|
||||
NetApiBufferAllocate( size_needed, (LPVOID *) pbuf);
|
||||
else
|
||||
{
|
||||
if (size_needed > prefmaxlen)
|
||||
return ERROR_MORE_DATA;
|
||||
NetApiBufferAllocate(prefmaxlen,
|
||||
(LPVOID *) pbuf);
|
||||
}
|
||||
for (i = 0; i <n_adapt; i++)
|
||||
{
|
||||
ti = (PWKSTA_TRANSPORT_INFO_0)
|
||||
((PBYTE) *pbuf + i * sizeof(WKSTA_TRANSPORT_INFO_0));
|
||||
ti->wkti0_quality_of_service=0;
|
||||
ti->wkti0_number_of_vcs=0;
|
||||
ti->wkti0_transport_name=NULL;
|
||||
ti->wkti0_transport_address= (LPWSTR)
|
||||
((PBYTE )*pbuf + n_adapt* sizeof(WKSTA_TRANSPORT_INFO_0)
|
||||
+ i * 13 * sizeof (WCHAR));
|
||||
ti->wkti0_wan_ish=TRUE; /*TCPIP/NETBIOS Protocoll*/
|
||||
wprint_mac(ti->wkti0_transport_address,i);
|
||||
TRACE("%d of %d:ti at %p transport_address at %p %s\n",i,n_adapt,
|
||||
ti, ti->wkti0_transport_address, debugstr_w(ti->wkti0_transport_address));
|
||||
}
|
||||
|
||||
info = (PIP_ADAPTER_INFO)malloc(adaptInfoSize);
|
||||
apiReturn = GetAdaptersInfo(info, &adaptInfoSize);
|
||||
if (apiReturn != NO_ERROR)
|
||||
{
|
||||
free(info);
|
||||
return apiReturn;
|
||||
}
|
||||
|
||||
for (n_adapt = 0, ptr = info; ptr; ptr = ptr->Next)
|
||||
n_adapt++;
|
||||
size_needed = n_adapt * (sizeof(WKSTA_TRANSPORT_INFO_0)
|
||||
+ n_adapt * TRANSPORT_NAME_LEN * sizeof (WCHAR)
|
||||
+ n_adapt * 13 * sizeof (WCHAR));
|
||||
if (prefmaxlen == MAX_PREFERRED_LENGTH)
|
||||
NetApiBufferAllocate( size_needed, (LPVOID *) pbuf);
|
||||
else
|
||||
{
|
||||
if (size_needed > prefmaxlen)
|
||||
{
|
||||
free(info);
|
||||
return ERROR_MORE_DATA;
|
||||
}
|
||||
NetApiBufferAllocate(prefmaxlen,
|
||||
(LPVOID *) pbuf);
|
||||
}
|
||||
for (i = 0, ptr = info; ptr; ptr = ptr->Next, i++)
|
||||
{
|
||||
ti = (PWKSTA_TRANSPORT_INFO_0)
|
||||
((PBYTE) *pbuf + i * sizeof(WKSTA_TRANSPORT_INFO_0));
|
||||
ti->wkti0_quality_of_service=0;
|
||||
ti->wkti0_number_of_vcs=0;
|
||||
ti->wkti0_transport_name= (LPWSTR)
|
||||
((PBYTE )*pbuf +
|
||||
n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0)
|
||||
+ i * TRANSPORT_NAME_LEN * sizeof (WCHAR));
|
||||
wprint_name(ti->wkti0_transport_name,TRANSPORT_NAME_LEN, ptr);
|
||||
ti->wkti0_transport_address= (LPWSTR)
|
||||
((PBYTE )*pbuf +
|
||||
n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0) +
|
||||
n_adapt * TRANSPORT_NAME_LEN * sizeof (WCHAR)
|
||||
+ i * 13 * sizeof (WCHAR));
|
||||
ti->wkti0_wan_ish=TRUE; /*TCPIP/NETBIOS Protocoll*/
|
||||
wprint_mac(ti->wkti0_transport_address, ptr);
|
||||
TRACE("%d of %d:ti at %p transport_address at %p %s\n",i,n_adapt,
|
||||
ti, ti->wkti0_transport_address, debugstr_w(ti->wkti0_transport_address));
|
||||
}
|
||||
*read_entries = n_adapt;
|
||||
*total_entries = n_adapt;
|
||||
if(hresume) *hresume= 0;
|
||||
break;
|
||||
}
|
||||
free(info);
|
||||
if(hresume) *hresume= 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ERR("Invalid level %ld is specified\n", level);
|
||||
return ERROR_INVALID_LEVEL;
|
||||
|
|
|
@ -100,9 +100,11 @@ typedef struct _LANA_ENUM
|
|||
#define NRC_ILLCMD 0x03
|
||||
#define NRC_CMDTMO 0x05
|
||||
#define NRC_INCOMP 0x06
|
||||
#define NRC_NORESOURCES 0x38
|
||||
#define NRC_INVADDRESS 0x39
|
||||
#define NRC_PENDING 0xff
|
||||
#define NRC_OPENERROR 0x3f
|
||||
#define NRC_SYSTEM 0x40
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue