Added netapi32.dll and the Netbios() call.
[wine] / dlls / netapi32 / netapi32.c
1 /*              
2  * Copyright 2001 Mike McCormack
3  */
4
5 #include <string.h>
6 #include <stdio.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9
10 #include "winbase.h"
11 #include "winreg.h"
12 #include "wingdi.h"
13 #include "winuser.h"
14 #include "debugtools.h"
15 #include "winerror.h"
16 #include "nb30.h"
17
18 #ifdef HAVE_SYS_FILE_H
19 # include <sys/file.h>
20 #endif
21 #include <sys/ioctl.h>
22 #ifdef HAVE_SYS_SOCKET_H
23 # include <sys/socket.h>
24 #endif
25 #ifdef HAVE_SYS_SOCKIO_H
26 # include <sys/sockio.h>
27 #endif
28 #ifdef HAVE_NET_IF_H
29 # include <net/if.h>
30 #endif
31 #ifdef HAVE_NETINET_IN_H
32 # include <netinet/in.h>
33 #endif
34
35 #ifdef HAVE_SOCKADDR_SA_LEN
36 #  ifndef max
37 #   define max(a,b) ((a) > (b) ? (a) : (b))
38 #  endif
39 #  define ifreq_size(i) max(sizeof(struct ifreq),\
40 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
41 # else
42 #  define ifreq_size(i) sizeof(struct ifreq)
43 # endif /* defined(HAVE_SOCKADDR_SA_LEN) */
44
45 DEFAULT_DEBUG_CHANNEL(netbios);
46
47 HMODULE NETAPI32_hModule = 0;
48
49 struct NetBiosAdapter
50 {
51     int valid;
52     unsigned char address[6];
53 };
54
55 static struct NetBiosAdapter NETBIOS_Adapter[MAX_LANA];
56
57 # ifdef SIOCGIFHWADDR
58 int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
59 {
60     if (ioctl(sd, SIOCGIFHWADDR, ifr) < 0)
61         return -1;
62     memcpy(address, (unsigned char *)&ifr->ifr_hwaddr.sa_data, 6);
63     return 0;
64 }
65 # else
66 #  ifdef SIOCGENADDR
67 int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
68 {
69     if (ioctl(sd, SIOCGENADDR, ifr) < 0)
70         return -1;
71     memcpy(address, (unsigned char *) ifr->ifr_enaddr, 6);
72     return 0;
73 }
74 #   else
75 int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
76 {
77     return -1;
78 }
79 #  endif /* SIOCGENADDR */
80 # endif /* SIOCGIFHWADDR */
81
82 static UCHAR NETBIOS_Enum(PNCB ncb)
83 {
84 #ifdef HAVE_NET_IF_H
85     int             sd;
86     struct ifreq    ifr, *ifrp;
87     struct ifconf   ifc;
88     unsigned char   buf[1024];
89     int             i, ofs;
90 #endif
91     LANA_ENUM *lanas = (PLANA_ENUM) ncb->ncb_buffer;
92
93     TRACE("NCBENUM\n");
94
95     lanas->length = 0;
96
97 #ifdef HAVE_NET_IF_H
98     /* BSD 4.4 defines the size of an ifreq to be
99      * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
100      * However, under earlier systems, sa_len isn't present, so
101      *  the size is just sizeof(struct ifreq)
102      */
103
104     sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
105     if (sd < 0)
106         return NRC_OPENERROR;
107
108     memset(buf, 0, sizeof(buf));
109     ifc.ifc_len = sizeof(buf);
110     ifc.ifc_buf = buf;
111     /* get the ifconf interface */
112     if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0)
113     {
114         close(sd);
115         return NRC_OPENERROR;
116     }
117
118     /* loop through the interfaces, looking for a valid one */
119     /* n = ifc.ifc_len; */
120     ofs = 0;
121     for (i = 0; i < ifc.ifc_len; i++)
122     {
123         unsigned char *a = NETBIOS_Adapter[i].address;
124
125         ifrp = (struct ifreq *)((char *)ifc.ifc_buf+ofs);
126         strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
127
128         /* try to get the address for this interface */
129         if(get_hw_address(sd, &ifr, a)==0)
130         {
131             /* make sure it's not blank */
132             /* if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
133                 continue; */
134
135             TRACE("Found valid adapter %d at %02x:%02x:%02x:%02x:%02x:%02x\n", i,
136                         a[0],a[1],a[2],a[3],a[4],a[5]);
137
138             NETBIOS_Adapter[i].valid = TRUE;
139             lanas->lana[lanas->length] = i;
140             lanas->length++;
141         }
142         ofs += ifreq_size(ifr);
143     }
144     close(sd);
145 #endif /* HAVE_NET_IF_H */
146     return NRC_GOODRET;
147 }
148
149
150 static UCHAR NETBIOS_Astat(PNCB ncb)
151 {
152     struct NetBiosAdapter *nad = &NETBIOS_Adapter[ncb->ncb_lana_num];
153     PADAPTER_STATUS astat = (PADAPTER_STATUS) ncb->ncb_buffer;
154
155     TRACE("NCBASTAT (Adapter %d)\n", ncb->ncb_lana_num);
156
157     if(!nad->valid)
158         return NRC_INVADDRESS;
159
160     memset(astat, 0, sizeof astat);
161     memcpy(astat->adapter_address, nad->address, sizeof astat->adapter_address);
162
163     return NRC_GOODRET;
164 }
165
166 BOOL WINAPI
167 NETAPI32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
168 {
169     TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
170
171     switch (fdwReason) {
172         case DLL_PROCESS_ATTACH:
173             NETAPI32_hModule = hinstDLL;
174             break;
175         case DLL_PROCESS_DETACH:
176             break;
177     }
178
179     return TRUE;
180 }
181
182 BOOL WINAPI Netbios(PNCB pncb)
183 {
184     UCHAR ret = NRC_ILLCMD; 
185
186     TRACE("ncb = %p\n",pncb);
187
188     if(!pncb)
189         return NRC_INVADDRESS;
190
191     switch(pncb->ncb_command&0x7f)
192     {
193     case NCBRESET:
194         FIXME("NCBRESET adapter %d\n",pncb->ncb_lana_num);
195         if( (pncb->ncb_lana_num < MAX_LANA ) && 
196              NETBIOS_Adapter[pncb->ncb_lana_num].valid)
197             ret = NRC_GOODRET;
198         else
199             ret = NRC_ILLCMD; /* NetBIOS emulator not found */
200         break;
201
202     case NCBADDNAME:
203         FIXME("NCBADDNAME\n");
204         break;
205
206     case NCBADDGRNAME:
207         FIXME("NCBADDGRNAME\n");
208         break;
209
210     case NCBDELNAME:
211         FIXME("NCBDELNAME\n");
212         break;
213
214     case NCBSEND:
215         FIXME("NCBSEND\n");
216         break;
217
218     case NCBRECV:
219         FIXME("NCBRECV\n");
220         break;
221
222     case NCBHANGUP:
223         FIXME("NCBHANGUP\n");
224         break;
225
226     case NCBCANCEL:
227         FIXME("NCBCANCEL\n");
228         break;
229
230     case NCBLISTEN:
231         FIXME("NCBLISTEN\n");
232         break;
233
234     case NCBASTAT:
235         ret = NETBIOS_Astat(pncb);
236         break;
237
238     case NCBENUM:
239         ret = NETBIOS_Enum(pncb);
240         break;
241
242     default:
243         FIXME("(%p): command code %02x\n", pncb, pncb->ncb_command);
244
245         ret = NRC_ILLCMD; /* NetBIOS emulator not found */
246     }
247     pncb->ncb_retcode = ret;
248     return ret;
249 }
250