/* * 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 #include #include #ifdef HAVE_UNISTD_H # include #endif #include "winbase.h" #include "winreg.h" #include "wingdi.h" #include "winuser.h" #include "wine/debug.h" #include "winerror.h" #include "nb30.h" #include "lmcons.h" #ifdef HAVE_SYS_FILE_H # include #endif #ifdef HAVE_SYS_IOCTL_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #ifdef HAVE_SYS_SOCKIO_H # include #endif #ifdef HAVE_NET_IF_H # include #endif #ifdef HAVE_NETINET_IN_H # include #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 */ 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; TRACE("NCBENUM\n"); lanas->length = 0; for (i = 0; i < enum_hw(); i++) { lanas->lana[lanas->length] = i; lanas->length++; } 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 DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { TRACE("%p,%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; } NET_API_STATUS WINAPI NetServerEnum( LPCWSTR servername, DWORD level, LPBYTE* bufptr, DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, DWORD servertype, LPCWSTR domain, LPDWORD resume_handle ) { FIXME("Stub (%p, %ld %p %ld %p %p %ld %s %p)\n",servername, level, bufptr, prefmaxlen, entriesread, totalentries, servertype, debugstr_w(domain), resume_handle); return ERROR_NO_BROWSER_SERVERS_FOUND; }