267 lines
6.2 KiB
C
267 lines
6.2 KiB
C
/*
|
|
* Copyright 2001 Mike McCormack
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include "winbase.h"
|
|
#include "winreg.h"
|
|
#include "wingdi.h"
|
|
#include "winuser.h"
|
|
#include "wine/debug.h"
|
|
#include "winerror.h"
|
|
#include "nb30.h"
|
|
|
|
#ifdef HAVE_SYS_FILE_H
|
|
# include <sys/file.h>
|
|
#endif
|
|
#include <sys/ioctl.h>
|
|
#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_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 /* defined(HAVE_SOCKADDR_SA_LEN) */
|
|
|
|
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 */
|
|
|
|
static UCHAR NETBIOS_Enum(PNCB ncb)
|
|
{
|
|
#ifdef HAVE_NET_IF_H
|
|
int sd;
|
|
struct ifreq ifr, *ifrp;
|
|
struct ifconf ifc;
|
|
unsigned char buf[1024];
|
|
int i, ofs;
|
|
#endif
|
|
LANA_ENUM *lanas = (PLANA_ENUM) ncb->ncb_buffer;
|
|
|
|
TRACE("NCBENUM\n");
|
|
|
|
lanas->length = 0;
|
|
|
|
#ifdef HAVE_NET_IF_H
|
|
/* 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;
|
|
lanas->lana[lanas->length] = i;
|
|
lanas->length++;
|
|
}
|
|
ofs += ifreq_size(ifr);
|
|
}
|
|
close(sd);
|
|
#endif /* HAVE_NET_IF_H */
|
|
return NRC_GOODRET;
|
|
}
|
|
|
|
|
|
static UCHAR NETBIOS_Astat(PNCB ncb)
|
|
{
|
|
struct NetBiosAdapter *nad = &NETBIOS_Adapter[ncb->ncb_lana_num];
|
|
PADAPTER_STATUS astat = (PADAPTER_STATUS) ncb->ncb_buffer;
|
|
|
|
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);
|
|
|
|
return NRC_GOODRET;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
NETAPI32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|
{
|
|
TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
|
|
|
|
switch (fdwReason) {
|
|
case DLL_PROCESS_ATTACH:
|
|
NETAPI32_hModule = hinstDLL;
|
|
break;
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL WINAPI Netbios(PNCB pncb)
|
|
{
|
|
UCHAR ret = NRC_ILLCMD;
|
|
|
|
TRACE("ncb = %p\n",pncb);
|
|
|
|
if(!pncb)
|
|
return NRC_INVADDRESS;
|
|
|
|
switch(pncb->ncb_command&0x7f)
|
|
{
|
|
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;
|
|
else
|
|
ret = NRC_ILLCMD; /* NetBIOS emulator not found */
|
|
break;
|
|
|
|
case NCBADDNAME:
|
|
FIXME("NCBADDNAME\n");
|
|
break;
|
|
|
|
case NCBADDGRNAME:
|
|
FIXME("NCBADDGRNAME\n");
|
|
break;
|
|
|
|
case NCBDELNAME:
|
|
FIXME("NCBDELNAME\n");
|
|
break;
|
|
|
|
case NCBSEND:
|
|
FIXME("NCBSEND\n");
|
|
break;
|
|
|
|
case NCBRECV:
|
|
FIXME("NCBRECV\n");
|
|
break;
|
|
|
|
case NCBHANGUP:
|
|
FIXME("NCBHANGUP\n");
|
|
break;
|
|
|
|
case NCBCANCEL:
|
|
FIXME("NCBCANCEL\n");
|
|
break;
|
|
|
|
case NCBLISTEN:
|
|
FIXME("NCBLISTEN\n");
|
|
break;
|
|
|
|
case NCBASTAT:
|
|
ret = NETBIOS_Astat(pncb);
|
|
break;
|
|
|
|
case NCBENUM:
|
|
ret = NETBIOS_Enum(pncb);
|
|
break;
|
|
|
|
default:
|
|
FIXME("(%p): command code %02x\n", pncb, pncb->ncb_command);
|
|
|
|
ret = NRC_ILLCMD; /* NetBIOS emulator not found */
|
|
}
|
|
pncb->ncb_retcode = ret;
|
|
return ret;
|
|
}
|
|
|