ReactOS 0.4.16-dev-329-g9223134
nbt.c
Go to the documentation of this file.
1/* Copyright (c) 2003 Juan Lang
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16 *
17 * I am heavily indebted to Chris Hertel's excellent Implementing CIFS,
18 * http://ubiqx.org/cifs/ , for whatever understanding I have of NBT.
19 * I also stole from Mike McCormack's smb.c and netapi32.c, although little of
20 * that code remains.
21 * Lack of understanding and bugs are my fault.
22 *
23 * FIXME:
24 * - Of the NetBIOS session functions, only client functions are supported, and
25 * it's likely they'll be the only functions supported. NBT requires session
26 * servers to listen on TCP/139. This requires root privilege, and Samba is
27 * likely to be listening here already. This further restricts NetBIOS
28 * applications, both explicit users and implicit ones: CreateNamedPipe
29 * won't actually create a listening pipe, for example, so applications can't
30 * act as RPC servers using a named pipe protocol binding, DCOM won't be able
31 * to support callbacks or servers over the named pipe protocol, etc.
32 *
33 * - Datagram support is omitted for the same reason. To send a NetBIOS
34 * datagram, you must include the NetBIOS name by which your application is
35 * known. This requires you to have registered the name previously, and be
36 * able to act as a NetBIOS datagram server (listening on UDP/138).
37 *
38 * - Name registration functions are omitted for the same reason--registering a
39 * name requires you to be able to defend it, and this means listening on
40 * UDP/137.
41 * Win98 requires you either use your computer's NetBIOS name (with the NULL
42 * suffix byte) as the calling name when creating a session, or to register
43 * a new name before creating one: it disallows '*' as the calling name.
44 * Win2K initially starts with an empty name table, and doesn't allow you to
45 * use the machine's NetBIOS name (with the NULL suffix byte) as the calling
46 * name. Although it allows sessions to be created with '*' as the calling
47 * name, doing so results in timeouts for all receives, because the
48 * application never gets them.
49 * So, a well-behaved NetBIOS application will typically want to register a
50 * name. I should probably support a do-nothing name list that allows
51 * NCBADDNAME to add to it, but doesn't actually register the name, or does
52 * attempt to register it without being able to defend it.
53 *
54 * - Name lookups may not behave quite as you'd expect/like if you have
55 * multiple LANAs. If a name is resolvable through DNS, or if you're using
56 * WINS, it'll resolve on _any_ LANA. So, a Call will succeed on any LANA as
57 * well.
58 * I'm not sure how Windows behaves in this case. I could try to force
59 * lookups to the correct adapter by using one of the GetPreferred*
60 * functions, but with the possibility of multiple adapters in the same
61 * same subnet, there's no guarantee that what IpHlpApi thinks is the
62 * preferred adapter will actually be a LANA. (It's highly probable because
63 * this is an unusual configuration, but not guaranteed.)
64 *
65 * See also other FIXMEs in the code.
66 */
67
68#include "netapi32.h"
69
70#include <winsock2.h>
71#include <winreg.h>
72
74
75#define PORT_NBNS 137
76#define PORT_NBDG 138
77#define PORT_NBSS 139
78
79#ifndef INADDR_NONE
80#define INADDR_NONE ~0UL
81#endif
82
83#define NBR_ADDWORD(p,word) (*(WORD *)(p)) = htons(word)
84#define NBR_GETWORD(p) ntohs(*(WORD *)(p))
85
86#define MIN_QUERIES 1
87#define MAX_QUERIES 0xffff
88#define MIN_QUERY_TIMEOUT 100
89#define MAX_QUERY_TIMEOUT 0xffffffff
90#define BCAST_QUERIES 3
91#define BCAST_QUERY_TIMEOUT 750
92#define WINS_QUERIES 3
93#define WINS_QUERY_TIMEOUT 750
94#define MAX_WINS_SERVERS 2
95#define MIN_CACHE_TIMEOUT 60000
96#define CACHE_TIMEOUT 360000
97
98#define MAX_NBT_NAME_SZ 255
99#define SIMPLE_NAME_QUERY_PKT_SIZE 16 + MAX_NBT_NAME_SZ
100
101#define NBNS_TYPE_NB 0x0020
102#define NBNS_TYPE_NBSTAT 0x0021
103#define NBNS_CLASS_INTERNET 0x00001
104#define NBNS_HEADER_SIZE (sizeof(WORD) * 6)
105#define NBNS_RESPONSE_AND_OPCODE 0xf800
106#define NBNS_RESPONSE_AND_QUERY 0x8000
107#define NBNS_REPLYCODE 0x0f
108
109#define NBSS_HDRSIZE 4
110
111#define NBSS_MSG 0x00
112#define NBSS_REQ 0x81
113#define NBSS_ACK 0x82
114#define NBSS_NACK 0x83
115#define NBSS_RETARGET 0x84
116#define NBSS_KEEPALIVE 0x85
117
118#define NBSS_ERR_NOT_LISTENING_ON_NAME 0x80
119#define NBSS_ERR_NOT_LISTENING_FOR_CALLER 0x81
120#define NBSS_ERR_BAD_NAME 0x82
121#define NBSS_ERR_INSUFFICIENT_RESOURCES 0x83
122
123#define NBSS_EXTENSION 0x01
124
125typedef struct _NetBTSession
126{
131
132typedef struct _NetBTAdapter
133{
140
151static struct NBNameCache *gNameCache;
152
153/* Converts from a NetBIOS name into a Second Level Encoding-formatted name.
154 * Assumes p is not NULL and is either NULL terminated or has at most NCBNAMSZ
155 * bytes, and buffer has at least MAX_NBT_NAME_SZ bytes. Pads with space bytes
156 * if p is NULL-terminated. Returns the number of bytes stored in buffer.
157 */
158static int NetBTNameEncode(const UCHAR *p, UCHAR *buffer)
159{
160 int i,len=0;
161
162 if (!p) return 0;
163 if (!buffer) return 0;
164
165 buffer[len++] = NCBNAMSZ * 2;
166 for (i = 0; i < NCBNAMSZ && p[i]; i++)
167 {
168 buffer[len++] = ((p[i] & 0xf0) >> 4) + 'A';
169 buffer[len++] = (p[i] & 0x0f) + 'A';
170 }
171 while (len < NCBNAMSZ * 2)
172 {
173 buffer[len++] = 'C';
174 buffer[len++] = 'A';
175 }
176 if (*gScopeID)
177 {
178 int scopeIDLen = strlen(gScopeID);
179
180 memcpy(buffer + len, gScopeID, scopeIDLen);
181 len += scopeIDLen;
182 }
183 buffer[len++] = 0; /* add second terminator */
184 return len;
185}
186
187/* Creates a NBT name request packet for name in buffer. If broadcast is true,
188 * creates a broadcast request, otherwise creates a unicast request.
189 * Returns the number of bytes stored in buffer.
190 */
193{
194 int i = 0;
195
196 if (len < SIMPLE_NAME_QUERY_PKT_SIZE) return 0;
197
198 NBR_ADDWORD(&buffer[i],xid); i+=2; /* transaction */
199 if (broadcast)
200 {
201 NBR_ADDWORD(&buffer[i],0x0110); /* flags: r=req,op=query,rd=1,b=1 */
202 i+=2;
203 }
204 else
205 {
206 NBR_ADDWORD(&buffer[i],0x0100); /* flags: r=req,op=query,rd=1,b=0 */
207 i+=2;
208 }
209 NBR_ADDWORD(&buffer[i],0x0001); i+=2; /* one name query */
210 NBR_ADDWORD(&buffer[i],0x0000); i+=2; /* zero answers */
211 NBR_ADDWORD(&buffer[i],0x0000); i+=2; /* zero authorities */
212 NBR_ADDWORD(&buffer[i],0x0000); i+=2; /* zero additional */
213
215
216 NBR_ADDWORD(&buffer[i],qtype); i+=2;
218
219 return i;
220}
221
222/* Sends a name query request for name on fd to destAddr. Sets SO_BROADCAST on
223 * fd if broadcast is TRUE. Assumes fd is not INVALID_SOCKET, and name is not
224 * NULL.
225 * Returns 0 on success, -1 on failure.
226 */
228 WORD qtype, DWORD destAddr, BOOL broadcast)
229{
230 int ret = 0, on = 1;
231 struct in_addr addr;
232
233 addr.s_addr = destAddr;
234 TRACE("name %s, dest addr %s\n", name, inet_ntoa(addr));
235
236 if (broadcast)
237 ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (const char*)&on, sizeof(on));
238 if(ret == 0)
239 {
240 WSABUF wsaBuf;
242 struct sockaddr_in sin;
243
244 memset(&sin, 0, sizeof(sin));
245 sin.sin_addr.s_addr = destAddr;
246 sin.sin_family = AF_INET;
247 sin.sin_port = htons(PORT_NBNS);
248
249 wsaBuf.buf = (CHAR*)buf;
250 wsaBuf.len = NetBTNameReq(name, xid, qtype, broadcast, buf,
251 sizeof(buf));
252 if (wsaBuf.len > 0)
253 {
254 DWORD bytesSent;
255
256 ret = WSASendTo(fd, &wsaBuf, 1, &bytesSent, 0,
257 (struct sockaddr*)&sin, sizeof(sin), NULL, NULL);
258 if (ret < 0 || bytesSent < wsaBuf.len)
259 ret = -1;
260 else
261 ret = 0;
262 }
263 else
264 ret = -1;
265 }
266 return ret;
267}
268
269typedef BOOL (*NetBTAnswerCallback)(void *data, WORD answerCount,
270 WORD answerIndex, PUCHAR rData, WORD rdLength);
271
272/* Waits on fd until GetTickCount() returns a value greater than or equal to
273 * waitUntil for a name service response. If a name response matching xid
274 * is received, calls answerCallback once for each answer resource record in
275 * the response. (The callback's answerCount will be the total number of
276 * answers to expect, and answerIndex will be the 0-based index that's being
277 * sent this time.) Quits parsing if answerCallback returns FALSE.
278 * Returns NRC_GOODRET on timeout or a valid response received, something else
279 * on error.
280 */
282 DWORD waitUntil, NetBTAnswerCallback answerCallback, void *data)
283{
284 BOOL found = FALSE;
285 DWORD now;
287
288 if (!adapter) return NRC_BADDR;
289 if (fd == INVALID_SOCKET) return NRC_BADDR;
290 if (!answerCallback) return NRC_BADDR;
291
292 while (!found && ret == NRC_GOODRET && (int)((now = GetTickCount()) - waitUntil) < 0)
293 {
294 DWORD msToWait = waitUntil - now;
295 struct fd_set fds;
296 struct timeval timeout = { msToWait / 1000, msToWait % 1000 };
297 int r;
298
299 FD_ZERO(&fds);
300 FD_SET(fd, &fds);
301 r = select(fd + 1, &fds, NULL, NULL, &timeout);
302 if (r < 0)
303 ret = NRC_SYSTEM;
304 else if (r == 1)
305 {
306 /* FIXME: magic #, is this always enough? */
307 UCHAR buffer[256];
308 int fromsize;
309 struct sockaddr_in fromaddr;
310 WORD respXID, flags, queryCount, answerCount;
311 WSABUF wsaBuf = { sizeof(buffer), (CHAR*)buffer };
312 DWORD bytesReceived, recvFlags = 0;
313
314 fromsize = sizeof(fromaddr);
315 r = WSARecvFrom(fd, &wsaBuf, 1, &bytesReceived, &recvFlags,
316 (struct sockaddr*)&fromaddr, &fromsize, NULL, NULL);
317 if(r < 0)
318 {
319 ret = NRC_SYSTEM;
320 break;
321 }
322
323 if (bytesReceived < NBNS_HEADER_SIZE)
324 continue;
325
326 respXID = NBR_GETWORD(buffer);
327 if (adapter->nameQueryXID != respXID)
328 continue;
329
330 flags = NBR_GETWORD(buffer + 2);
331 queryCount = NBR_GETWORD(buffer + 4);
332 answerCount = NBR_GETWORD(buffer + 6);
333
334 /* a reply shouldn't contain a query, ignore bad packet */
335 if (queryCount > 0)
336 continue;
337
339 {
340 if ((flags & NBNS_REPLYCODE) != 0)
341 ret = NRC_NAMERR;
342 else if ((flags & NBNS_REPLYCODE) == 0 && answerCount > 0)
343 {
345 BOOL shouldContinue = TRUE;
346 WORD answerIndex = 0;
347
348 found = TRUE;
349 /* decode one answer at a time */
350 while (ret == NRC_GOODRET && answerIndex < answerCount &&
351 ptr - buffer < bytesReceived && shouldContinue)
352 {
353 WORD rLen;
354
355 /* scan past name */
356 for (; ptr[0] && ptr - buffer < bytesReceived; )
357 ptr += ptr[0] + 1;
358 ptr++;
359 ptr += 2; /* scan past type */
360 if (ptr - buffer < bytesReceived && ret == NRC_GOODRET
362 ptr += sizeof(WORD);
363 else
364 ret = NRC_SYSTEM; /* parse error */
365 ptr += sizeof(DWORD); /* TTL */
366 rLen = NBR_GETWORD(ptr);
367 rLen = min(rLen, bytesReceived - (ptr - buffer));
368 ptr += sizeof(WORD);
369 shouldContinue = answerCallback(data, answerCount,
370 answerIndex, ptr, rLen);
371 ptr += rLen;
372 answerIndex++;
373 }
374 }
375 }
376 }
377 }
378 TRACE("returning 0x%02x\n", ret);
379 return ret;
380}
381
382typedef struct _NetBTNameQueryData {
386
387/* Name query callback function for NetBTWaitForNameResponse, creates a cache
388 * entry on the first answer, adds each address as it's called again (as long
389 * as there's space). If there's an error that should be propagated as the
390 * NetBIOS error, modifies queryData's ret member to the proper return code.
391 */
392static BOOL NetBTFindNameAnswerCallback(void *pVoid, WORD answerCount,
393 WORD answerIndex, PUCHAR rData, WORD rLen)
394{
395 NetBTNameQueryData *queryData = pVoid;
396 BOOL ret;
397
398 if (queryData)
399 {
400 if (queryData->cacheEntry == NULL)
401 {
402 queryData->cacheEntry = HeapAlloc(GetProcessHeap(), 0,
403 FIELD_OFFSET(NBNameCacheEntry, addresses[answerCount]));
404 if (queryData->cacheEntry)
405 queryData->cacheEntry->numAddresses = 0;
406 else
407 queryData->ret = NRC_OSRESNOTAV;
408 }
409 if (rLen == 6 && queryData->cacheEntry &&
410 queryData->cacheEntry->numAddresses < answerCount)
411 {
412 queryData->cacheEntry->addresses[queryData->cacheEntry->
413 numAddresses++] = *(const DWORD *)(rData + 2);
414 ret = queryData->cacheEntry->numAddresses < answerCount;
415 }
416 else
417 ret = FALSE;
418 }
419 else
420 ret = FALSE;
421 return ret;
422}
423
424/* Workhorse NetBT name lookup function. Sends a name lookup query for
425 * ncb->ncb_callname to sendTo, as a broadcast if broadcast is TRUE, using
426 * adapter->nameQueryXID as the transaction ID. Waits up to timeout
427 * milliseconds, and retries up to maxQueries times, waiting for a reply.
428 * If a valid response is received, stores the looked up addresses as a
429 * NBNameCacheEntry in *cacheEntry.
430 * Returns NRC_GOODRET on success, though this may not mean the name was
431 * resolved--check whether *cacheEntry is NULL.
432 */
434 DWORD sendTo, BOOL broadcast, DWORD timeout, DWORD maxQueries,
435 NBNameCacheEntry **cacheEntry)
436{
437 unsigned int queries;
438 NetBTNameQueryData queryData;
439
440 if (!adapter) return NRC_BADDR;
441 if (fd == INVALID_SOCKET) return NRC_BADDR;
442 if (!ncb) return NRC_BADDR;
443 if (!cacheEntry) return NRC_BADDR;
444
445 queryData.cacheEntry = NULL;
446 queryData.ret = NRC_GOODRET;
447 for (queries = 0; queryData.cacheEntry == NULL && queries < maxQueries;
448 queries++)
449 {
450 if (!NCB_CANCELLED(ncb))
451 {
453 adapter->nameQueryXID, NBNS_TYPE_NB, sendTo, broadcast);
454
455 if (r == 0)
458 &queryData);
459 else
460 queryData.ret = NRC_SYSTEM;
461 }
462 else
463 queryData.ret = NRC_CMDCAN;
464 }
465 if (queryData.cacheEntry)
466 {
467 memcpy(queryData.cacheEntry->name, ncb->ncb_callname, NCBNAMSZ);
468 memcpy(queryData.cacheEntry->nbname, ncb->ncb_callname, NCBNAMSZ);
469 }
470 *cacheEntry = queryData.cacheEntry;
471 return queryData.ret;
472}
473
474/* Attempts to add cacheEntry to the name cache in *nameCache; if *nameCache
475 * has not yet been created, creates it, using gCacheTimeout as the cache
476 * entry timeout. If memory allocation fails, or if NBNameCacheAddEntry fails,
477 * frees cacheEntry.
478 * Returns NRC_GOODRET on success, and something else on failure.
479 */
480static UCHAR NetBTStoreCacheEntry(struct NBNameCache **nameCache,
481 NBNameCacheEntry *cacheEntry)
482{
483 UCHAR ret;
484
485 if (!nameCache) return NRC_BADDR;
486 if (!cacheEntry) return NRC_BADDR;
487
488 if (!*nameCache)
490 if (*nameCache)
491 ret = NBNameCacheAddEntry(*nameCache, cacheEntry)
493 else
494 {
495 HeapFree(GetProcessHeap(), 0, cacheEntry);
497 }
498 return ret;
499}
500
501/* Attempts to resolve name using inet_addr(), then gethostbyname() if
502 * gEnableDNS is TRUE, if the suffix byte is either <00> or <20>. If the name
503 * can be looked up, returns 0 and stores the looked up addresses as a
504 * NBNameCacheEntry in *cacheEntry.
505 * Returns NRC_GOODRET on success, though this may not mean the name was
506 * resolved--check whether *cacheEntry is NULL. Returns something else on
507 * error.
508 */
510 NBNameCacheEntry **cacheEntry)
511{
513
514 TRACE("name %s, cacheEntry %p\n", name, cacheEntry);
515
516 if (!name) return NRC_BADDR;
517 if (!cacheEntry) return NRC_BADDR;
518
519 if (isalnum(name[0]) && (name[NCBNAMSZ - 1] == 0 ||
520 name[NCBNAMSZ - 1] == 0x20))
521 {
522 CHAR toLookup[NCBNAMSZ];
523 unsigned int i;
524
525 for (i = 0; i < NCBNAMSZ - 1 && name[i] && name[i] != ' '; i++)
526 toLookup[i] = name[i];
527 toLookup[i] = '\0';
528
529 if (isdigit(toLookup[0]))
530 {
531 unsigned long addr = inet_addr(toLookup);
532
533 if (addr != INADDR_NONE)
534 {
535 *cacheEntry = HeapAlloc(GetProcessHeap(), 0,
536 FIELD_OFFSET(NBNameCacheEntry, addresses[1]));
537 if (*cacheEntry)
538 {
539 memcpy((*cacheEntry)->name, name, NCBNAMSZ);
540 memset((*cacheEntry)->nbname, 0, NCBNAMSZ);
541 (*cacheEntry)->nbname[0] = '*';
542 (*cacheEntry)->numAddresses = 1;
543 (*cacheEntry)->addresses[0] = addr;
544 }
545 else
547 }
548 }
549 if (gEnableDNS && ret == NRC_GOODRET && !*cacheEntry)
550 {
551 struct hostent *host;
552
553 if ((host = gethostbyname(toLookup)) != NULL)
554 {
555 for (i = 0; ret == NRC_GOODRET && host->h_addr_list &&
556 host->h_addr_list[i]; i++)
557 ;
558 if (host->h_addr_list && host->h_addr_list[0])
559 {
560 *cacheEntry = HeapAlloc(GetProcessHeap(), 0,
561 FIELD_OFFSET(NBNameCacheEntry, addresses[i]));
562 if (*cacheEntry)
563 {
564 memcpy((*cacheEntry)->name, name, NCBNAMSZ);
565 memset((*cacheEntry)->nbname, 0, NCBNAMSZ);
566 (*cacheEntry)->nbname[0] = '*';
567 (*cacheEntry)->numAddresses = i;
568 for (i = 0; i < (*cacheEntry)->numAddresses; i++)
569 (*cacheEntry)->addresses[i] =
570 *(DWORD*)host->h_addr_list[i];
571 }
572 else
574 }
575 }
576 }
577 }
578
579 TRACE("returning 0x%02x\n", ret);
580 return ret;
581}
582
583/* Looks up the name in ncb->ncb_callname, first in the name caches (global
584 * and this adapter's), then using gethostbyname(), next by WINS if configured,
585 * and finally using broadcast NetBT name resolution. In NBT parlance, this
586 * makes this an "H-node". Stores an entry in the appropriate name cache for a
587 * found node, and returns it as *cacheEntry.
588 * Assumes data, ncb, and cacheEntry are not NULL.
589 * Returns NRC_GOODRET on success--which doesn't mean the name was resolved,
590 * just that all name lookup operations completed successfully--and something
591 * else on failure. *cacheEntry will be NULL if the name was not found.
592 */
594 const NBNameCacheEntry **cacheEntry)
595{
597
598 TRACE("adapter %p, ncb %p, cacheEntry %p\n", adapter, ncb, cacheEntry);
599
600 if (!cacheEntry) return NRC_BADDR;
601 *cacheEntry = NULL;
602
603 if (!adapter) return NRC_BADDR;
604 if (!ncb) return NRC_BADDR;
605
606 if (ncb->ncb_callname[0] == '*')
607 ret = NRC_NOWILD;
608 else
609 {
610 *cacheEntry = NBNameCacheFindEntry(gNameCache, ncb->ncb_callname);
611 if (!*cacheEntry)
612 *cacheEntry = NBNameCacheFindEntry(adapter->nameCache,
613 ncb->ncb_callname);
614 if (!*cacheEntry)
615 {
616 NBNameCacheEntry *newEntry = NULL;
617
618 ret = NetBTinetResolve(ncb->ncb_callname, &newEntry);
619 if (ret == NRC_GOODRET && newEntry)
620 {
621 ret = NetBTStoreCacheEntry(&gNameCache, newEntry);
622 if (ret != NRC_GOODRET)
623 newEntry = NULL;
624 }
625 else
626 {
629
630 if(fd == INVALID_SOCKET)
632 else
633 {
634 int winsNdx;
635
636 adapter->nameQueryXID++;
637 for (winsNdx = 0; ret == NRC_GOODRET && *cacheEntry == NULL
638 && winsNdx < gNumWINSServers; winsNdx++)
641 gWINSQueries, &newEntry);
642 if (ret == NRC_GOODRET && newEntry)
643 {
644 ret = NetBTStoreCacheEntry(&gNameCache, newEntry);
645 if (ret != NRC_GOODRET)
646 newEntry = NULL;
647 }
648 if (ret == NRC_GOODRET && *cacheEntry == NULL)
649 {
650 DWORD bcastAddr =
651 adapter->ipr.dwAddr & adapter->ipr.dwMask;
652
653 if (adapter->ipr.dwBCastAddr)
654 bcastAddr |= ~adapter->ipr.dwMask;
655 ret = NetBTNameWaitLoop(adapter, fd, ncb, bcastAddr,
657 if (ret == NRC_GOODRET && newEntry)
658 {
659 ret = NetBTStoreCacheEntry(&adapter->nameCache,
660 newEntry);
661 if (ret != NRC_GOODRET)
662 newEntry = NULL;
663 }
664 }
666 }
667 }
668 *cacheEntry = newEntry;
669 }
670 }
671 TRACE("returning 0x%02x\n", ret);
672 return ret;
673}
674
676{
681
682/* Callback function for NetBTAstatRemote, parses the rData for the node
683 * status and name list of the remote node. Always returns FALSE, since
684 * there's never more than one answer we care about in a node status response.
685 */
686static BOOL NetBTNodeStatusAnswerCallback(void *pVoid, WORD answerCount,
687 WORD answerIndex, PUCHAR rData, WORD rLen)
688{
689 NetBTNodeQueryData *data = pVoid;
690
691 if (data && !data->gotResponse && rData && rLen >= 1)
692 {
693 /* num names is first byte; each name is NCBNAMSZ + 2 bytes */
694 if (rLen >= rData[0] * (NCBNAMSZ + 2))
695 {
696 WORD i;
697 PUCHAR src;
699
700 data->gotResponse = TRUE;
701 data->astat->name_count = rData[0];
702 for (i = 0, src = rData + 1,
703 dst = (PNAME_BUFFER)((PUCHAR)data->astat +
704 sizeof(ADAPTER_STATUS));
705 i < data->astat->name_count && src - rData < rLen &&
706 (PUCHAR)dst - (PUCHAR)data->astat < data->astatLen;
707 i++, dst++, src += NCBNAMSZ + 2)
708 {
709 UCHAR flags = *(src + NCBNAMSZ);
710
711 memcpy(dst->name, src, NCBNAMSZ);
712 /* we won't actually see a registering name in the returned
713 * response. It's useful to see if no other flags are set; if
714 * none are, then the name is registered. */
715 dst->name_flags = REGISTERING;
716 if (flags & 0x80)
717 dst->name_flags |= GROUP_NAME;
718 if (flags & 0x10)
719 dst->name_flags |= DEREGISTERED;
720 if (flags & 0x08)
721 dst->name_flags |= DUPLICATE;
722 if (dst->name_flags == REGISTERING)
723 dst->name_flags = REGISTERED;
724 }
725 /* arbitrarily set HW type to Ethernet */
726 data->astat->adapter_type = 0xfe;
727 if (src - rData < rLen)
728 memcpy(data->astat->adapter_address, src,
729 min(rLen - (src - rData), 6));
730 }
731 }
732 return FALSE;
733}
734
735/* This uses the WINS timeout and query values, as they're the
736 * UCAST_REQ_RETRY_TIMEOUT and UCAST_REQ_RETRY_COUNT according to the RFCs.
737 */
739{
741 const NBNameCacheEntry *cacheEntry = NULL;
742
743 TRACE("adapter %p, NCB %p\n", adapter, ncb);
744
745 if (!adapter) return NRC_BADDR;
746 if (!ncb) return NRC_INVADDRESS;
747
748 ret = NetBTInternalFindName(adapter, ncb, &cacheEntry);
749 if (ret == NRC_GOODRET && cacheEntry)
750 {
751 if (cacheEntry->numAddresses > 0)
752 {
755
756 if(fd == INVALID_SOCKET)
758 else
759 {
760 NetBTNodeQueryData queryData;
761 DWORD queries;
763
764 adapter->nameQueryXID++;
765 astat->name_count = 0;
766 queryData.gotResponse = FALSE;
767 queryData.astat = astat;
768 queryData.astatLen = ncb->ncb_length;
769 for (queries = 0; !queryData.gotResponse &&
770 queries < gWINSQueries; queries++)
771 {
772 if (!NCB_CANCELLED(ncb))
773 {
775 adapter->nameQueryXID, NBNS_TYPE_NBSTAT,
776 cacheEntry->addresses[0], FALSE);
777
778 if (r == 0)
782 else
783 ret = NRC_SYSTEM;
784 }
785 else
786 ret = NRC_CMDCAN;
787 }
789 }
790 }
791 else
792 ret = NRC_CMDTMO;
793 }
794 else if (ret == NRC_CMDCAN)
795 ; /* do nothing, we were cancelled */
796 else
797 ret = NRC_CMDTMO;
798 TRACE("returning 0x%02x\n", ret);
799 return ret;
800}
801
802static UCHAR NetBTAstat(void *adapt, PNCB ncb)
803{
805 UCHAR ret;
806
807 TRACE("adapt %p, NCB %p\n", adapt, ncb);
808
809 if (!adapter) return NRC_ENVNOTDEF;
810 if (!ncb) return NRC_INVADDRESS;
811 if (!ncb->ncb_buffer) return NRC_BADDR;
812 if (ncb->ncb_length < sizeof(ADAPTER_STATUS)) return NRC_BUFLEN;
813
814 if (ncb->ncb_callname[0] == '*')
815 {
816 DWORD physAddrLen;
817 MIB_IFROW ifRow;
819
820 memset(astat, 0, sizeof(ADAPTER_STATUS));
821 astat->rev_major = 3;
822 ifRow.dwIndex = adapter->ipr.dwIndex;
823 if (GetIfEntry(&ifRow) != NO_ERROR)
824 ret = NRC_BRIDGE;
825 else
826 {
827 physAddrLen = min(ifRow.dwPhysAddrLen, 6);
828 if (physAddrLen > 0)
829 memcpy(astat->adapter_address, ifRow.bPhysAddr, physAddrLen);
830 /* doubt anyone cares, but why not.. */
831 if (ifRow.dwType == MIB_IF_TYPE_TOKENRING)
832 astat->adapter_type = 0xff;
833 else
834 astat->adapter_type = 0xfe; /* for Ethernet */
835 astat->max_sess_pkt_size = 0xffff;
836 astat->xmit_success = adapter->xmit_success;
837 astat->recv_success = adapter->recv_success;
839 }
840 }
841 else
843 TRACE("returning 0x%02x\n", ret);
844 return ret;
845}
846
847static UCHAR NetBTFindName(void *adapt, PNCB ncb)
848{
850 UCHAR ret;
851 const NBNameCacheEntry *cacheEntry = NULL;
852 PFIND_NAME_HEADER foundName;
853
854 TRACE("adapt %p, NCB %p\n", adapt, ncb);
855
856 if (!adapter) return NRC_ENVNOTDEF;
857 if (!ncb) return NRC_INVADDRESS;
858 if (!ncb->ncb_buffer) return NRC_BADDR;
859 if (ncb->ncb_length < sizeof(FIND_NAME_HEADER)) return NRC_BUFLEN;
860
861 foundName = (PFIND_NAME_HEADER)ncb->ncb_buffer;
862 memset(foundName, 0, sizeof(FIND_NAME_HEADER));
863
864 ret = NetBTInternalFindName(adapter, ncb, &cacheEntry);
865 if (ret == NRC_GOODRET)
866 {
867 if (cacheEntry)
868 {
869 DWORD spaceFor = min((ncb->ncb_length - sizeof(FIND_NAME_HEADER)) /
870 sizeof(FIND_NAME_BUFFER), cacheEntry->numAddresses);
871 DWORD ndx;
872
873 for (ndx = 0; ndx < spaceFor; ndx++)
874 {
875 PFIND_NAME_BUFFER findNameBuffer;
876
877 findNameBuffer =
878 (PFIND_NAME_BUFFER)((PUCHAR)foundName +
879 sizeof(FIND_NAME_HEADER) + foundName->node_count *
880 sizeof(FIND_NAME_BUFFER));
881 memset(findNameBuffer->destination_addr, 0, 2);
882 memcpy(findNameBuffer->destination_addr + 2,
883 &adapter->ipr.dwAddr, sizeof(DWORD));
884 memset(findNameBuffer->source_addr, 0, 2);
885 memcpy(findNameBuffer->source_addr + 2,
886 &cacheEntry->addresses[ndx], sizeof(DWORD));
887 foundName->node_count++;
888 }
889 if (spaceFor < cacheEntry->numAddresses)
890 ret = NRC_BUFLEN;
891 }
892 else
893 ret = NRC_CMDTMO;
894 }
895 TRACE("returning 0x%02x\n", ret);
896 return ret;
897}
898
899static UCHAR NetBTSessionReq(SOCKET fd, const UCHAR *calledName,
900 const UCHAR *callingName)
901{
903 int r;
904 unsigned int len = 0;
905 DWORD bytesSent, bytesReceived, recvFlags = 0;
906 WSABUF wsaBuf;
907
908 buffer[0] = NBSS_REQ;
909 buffer[1] = 0;
910
911 len += NetBTNameEncode(calledName, &buffer[NBSS_HDRSIZE]);
912 len += NetBTNameEncode(callingName, &buffer[NBSS_HDRSIZE + len]);
913
914 NBR_ADDWORD(&buffer[2], len);
915
916 wsaBuf.len = len + NBSS_HDRSIZE;
917 wsaBuf.buf = (char*)buffer;
918
919 r = WSASend(fd, &wsaBuf, 1, &bytesSent, 0, NULL, NULL);
920 if(r < 0 || bytesSent < len + NBSS_HDRSIZE)
921 {
922 ERR("send failed\n");
923 return NRC_SABORT;
924 }
925
926 /* I've already set the recv timeout on this socket (if it supports it), so
927 * just block. Hopefully we'll always receive the session acknowledgement
928 * within one timeout.
929 */
930 wsaBuf.len = NBSS_HDRSIZE + 1;
931 r = WSARecv(fd, &wsaBuf, 1, &bytesReceived, &recvFlags, NULL, NULL);
932 if (r < 0 || bytesReceived < NBSS_HDRSIZE)
933 ret = NRC_SABORT;
934 else if (buffer[0] == NBSS_NACK)
935 {
936 if (r == NBSS_HDRSIZE + 1)
937 {
938 switch (buffer[NBSS_HDRSIZE])
939 {
942 break;
943 default:
944 ret = NRC_NOCALL;
945 }
946 }
947 else
948 ret = NRC_NOCALL;
949 }
950 else if (buffer[0] == NBSS_RETARGET)
951 {
952 FIXME("Got a session retarget, can't deal\n");
953 ret = NRC_NOCALL;
954 }
955 else if (buffer[0] == NBSS_ACK)
957 else
958 ret = NRC_SYSTEM;
959
960 TRACE("returning 0x%02x\n", ret);
961 return ret;
962}
963
964static UCHAR NetBTCall(void *adapt, PNCB ncb, void **sess)
965{
967 UCHAR ret;
968 const NBNameCacheEntry *cacheEntry = NULL;
969
970 TRACE("adapt %p, ncb %p\n", adapt, ncb);
971
972 if (!adapter) return NRC_ENVNOTDEF;
973 if (!ncb) return NRC_INVADDRESS;
974 if (!sess) return NRC_BADDR;
975
976 ret = NetBTInternalFindName(adapter, ncb, &cacheEntry);
977 if (ret == NRC_GOODRET)
978 {
979 if (cacheEntry && cacheEntry->numAddresses > 0)
980 {
981 SOCKET fd;
982
985 if (fd != INVALID_SOCKET)
986 {
988 struct sockaddr_in sin;
989
990 if (ncb->ncb_rto > 0)
991 {
992 timeout = ncb->ncb_rto * 500;
994 sizeof(timeout));
995 }
996 if (ncb->ncb_sto > 0)
997 {
998 timeout = ncb->ncb_sto * 500;
1000 sizeof(timeout));
1001 }
1002
1003 memset(&sin, 0, sizeof(sin));
1004 memcpy(&sin.sin_addr, &cacheEntry->addresses[0],
1005 sizeof(sin.sin_addr));
1006 sin.sin_family = AF_INET;
1007 sin.sin_port = htons(PORT_NBSS);
1008 /* FIXME: use nonblocking mode for the socket, check the
1009 * cancel flag periodically
1010 */
1011 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin))
1012 == SOCKET_ERROR)
1013 ret = NRC_CMDTMO;
1014 else
1015 {
1016 static const UCHAR fakedCalledName[] = "*SMBSERVER";
1017 const UCHAR *calledParty = cacheEntry->nbname[0] == '*'
1018 ? fakedCalledName : cacheEntry->nbname;
1019
1020 ret = NetBTSessionReq(fd, calledParty, ncb->ncb_name);
1021 if (ret != NRC_GOODRET && calledParty[0] == '*')
1022 {
1023 FIXME("NBT session to \"*SMBSERVER\" refused,\n");
1024 FIXME("should try finding name using ASTAT\n");
1025 }
1026 }
1027 if (ret != NRC_GOODRET)
1028 closesocket(fd);
1029 else
1030 {
1033
1034 if (session)
1035 {
1036 session->fd = fd;
1038 session->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NetBTSession.cs");
1039 *sess = session;
1040 }
1041 else
1042 {
1044 closesocket(fd);
1045 }
1046 }
1047 }
1048 else
1050 }
1051 else
1052 ret = NRC_NAMERR;
1053 }
1054 TRACE("returning 0x%02x\n", ret);
1055 return ret;
1056}
1057
1058/* Notice that I don't protect against multiple thread access to NetBTSend.
1059 * This is because I don't update any data in the adapter, and I only make a
1060 * single call to WSASend, which I assume to act atomically (not interleaving
1061 * data from other threads).
1062 * I don't lock, because I only depend on the fd being valid, and this won't be
1063 * true until a session setup is completed.
1064 */
1065static UCHAR NetBTSend(void *adapt, void *sess, PNCB ncb)
1066{
1068 NetBTSession *session = sess;
1070 int r;
1071 WSABUF wsaBufs[2];
1072 DWORD bytesSent;
1073
1074 TRACE("adapt %p, session %p, NCB %p\n", adapt, session, ncb);
1075
1076 if (!adapter) return NRC_ENVNOTDEF;
1077 if (!ncb) return NRC_INVADDRESS;
1078 if (!ncb->ncb_buffer) return NRC_BADDR;
1079 if (!session) return NRC_SNUMOUT;
1080 if (session->fd == INVALID_SOCKET) return NRC_SNUMOUT;
1081
1082 buffer[0] = NBSS_MSG;
1083 buffer[1] = 0;
1084 NBR_ADDWORD(&buffer[2], ncb->ncb_length);
1085
1086 wsaBufs[0].len = NBSS_HDRSIZE;
1087 wsaBufs[0].buf = (char*)buffer;
1088 wsaBufs[1].len = ncb->ncb_length;
1089 wsaBufs[1].buf = (char*)ncb->ncb_buffer;
1090
1091 r = WSASend(session->fd, wsaBufs, sizeof(wsaBufs) / sizeof(wsaBufs[0]),
1092 &bytesSent, 0, NULL, NULL);
1093 if (r == SOCKET_ERROR)
1094 {
1096 ret = NRC_SABORT;
1097 }
1098 else if (bytesSent < NBSS_HDRSIZE + ncb->ncb_length)
1099 {
1100 FIXME("Only sent %d bytes (of %d), hanging up session\n", bytesSent,
1101 NBSS_HDRSIZE + ncb->ncb_length);
1103 ret = NRC_SABORT;
1104 }
1105 else
1106 {
1107 ret = NRC_GOODRET;
1108 adapter->xmit_success++;
1109 }
1110 TRACE("returning 0x%02x\n", ret);
1111 return ret;
1112}
1113
1114static UCHAR NetBTRecv(void *adapt, void *sess, PNCB ncb)
1115{
1117 NetBTSession *session = sess;
1119 int r;
1120 WSABUF wsaBufs[2];
1121 DWORD bufferCount, bytesReceived, flags;
1122
1123 TRACE("adapt %p, session %p, NCB %p\n", adapt, session, ncb);
1124
1125 if (!adapter) return NRC_ENVNOTDEF;
1126 if (!ncb) return NRC_BADDR;
1127 if (!ncb->ncb_buffer) return NRC_BADDR;
1128 if (!session) return NRC_SNUMOUT;
1129 if (session->fd == INVALID_SOCKET) return NRC_SNUMOUT;
1130
1132 bufferCount = 0;
1133 if (session->bytesPending == 0)
1134 {
1135 bufferCount++;
1136 wsaBufs[0].len = NBSS_HDRSIZE;
1137 wsaBufs[0].buf = (char*)buffer;
1138 }
1139 wsaBufs[bufferCount].len = ncb->ncb_length;
1140 wsaBufs[bufferCount].buf = (char*)ncb->ncb_buffer;
1141 bufferCount++;
1142
1143 flags = 0;
1144 /* FIXME: should poll a bit so I can check the cancel flag */
1145 r = WSARecv(session->fd, wsaBufs, bufferCount, &bytesReceived, &flags,
1146 NULL, NULL);
1148 {
1150 ERR("Receive error, WSAGetLastError() returns %d\n", WSAGetLastError());
1152 ret = NRC_SABORT;
1153 }
1154 else if (NCB_CANCELLED(ncb))
1155 {
1157 ret = NRC_CMDCAN;
1158 }
1159 else
1160 {
1161 if (bufferCount == 2)
1162 {
1163 if (buffer[0] == NBSS_KEEPALIVE)
1164 {
1166 FIXME("Oops, received a session keepalive and lost my place\n");
1167 /* need to read another session header until we get a session
1168 * message header. */
1170 ret = NRC_SABORT;
1171 goto error;
1172 }
1173 else if (buffer[0] != NBSS_MSG)
1174 {
1176 FIXME("Received unexpected session msg type %d\n", buffer[0]);
1178 ret = NRC_SABORT;
1179 goto error;
1180 }
1181 else
1182 {
1183 if (buffer[1] & NBSS_EXTENSION)
1184 {
1186 FIXME("Received a message that's too long for my taste\n");
1188 ret = NRC_SABORT;
1189 goto error;
1190 }
1191 else
1192 {
1193 session->bytesPending = NBSS_HDRSIZE
1194 + NBR_GETWORD(&buffer[2]) - bytesReceived;
1195 ncb->ncb_length = bytesReceived - NBSS_HDRSIZE;
1197 }
1198 }
1199 }
1200 else
1201 {
1202 if (bytesReceived < session->bytesPending)
1203 session->bytesPending -= bytesReceived;
1204 else
1205 session->bytesPending = 0;
1207 ncb->ncb_length = bytesReceived;
1208 }
1209 if (session->bytesPending > 0)
1210 ret = NRC_INCOMP;
1211 else
1212 {
1213 ret = NRC_GOODRET;
1214 adapter->recv_success++;
1215 }
1216 }
1217error:
1218 TRACE("returning 0x%02x\n", ret);
1219 return ret;
1220}
1221
1222static UCHAR NetBTHangup(void *adapt, void *sess)
1223{
1224 NetBTSession *session = sess;
1225
1226 TRACE("adapt %p, session %p\n", adapt, session);
1227
1228 if (!session) return NRC_SNUMOUT;
1229
1230 /* I don't lock the session, because NetBTRecv knows not to decrement
1231 * past 0, so if a receive completes after this it should still deal.
1232 */
1233 closesocket(session->fd);
1234 session->fd = INVALID_SOCKET;
1235 session->bytesPending = 0;
1236 session->cs.DebugInfo->Spare[0] = 0;
1239
1240 return NRC_GOODRET;
1241}
1242
1243static void NetBTCleanupAdapter(void *adapt)
1244{
1245 TRACE("adapt %p\n", adapt);
1246 if (adapt)
1247 {
1249
1250 if (adapter->nameCache)
1251 NBNameCacheDestroy(adapter->nameCache);
1253 }
1254}
1255
1256static void NetBTCleanup(void)
1257{
1258 TRACE("\n");
1259 if (gNameCache)
1260 {
1262 gNameCache = NULL;
1263 }
1264}
1265
1267{
1268 UCHAR ret;
1270
1271 if (!ipRow) return NRC_BADDR;
1272
1274 if (adapter)
1275 {
1276 adapter->ipr = *ipRow;
1278 {
1280 ret = NRC_SYSTEM;
1281 }
1282 else
1283 ret = NRC_GOODRET;
1284 }
1285 else
1287 return ret;
1288}
1289
1290/* Callback for NetBIOS adapter enumeration. Assumes closure is a pointer to
1291 * a MIB_IPADDRTABLE containing all the IP adapters needed to be added to the
1292 * NetBIOS adapter table. For each callback, checks if the passed-in adapt
1293 * has an entry in the table; if so, this adapter was enumerated previously,
1294 * and it's enabled. As a flag, the table's dwAddr entry is changed to
1295 * INADDR_LOOPBACK, since this is an invalid address for a NetBT adapter.
1296 * The NetBTEnum function will add any remaining adapters from the
1297 * MIB_IPADDRTABLE to the NetBIOS adapter table.
1298 */
1299static BOOL NetBTEnumCallback(UCHAR totalLANAs, UCHAR lanaIndex,
1300 ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
1301{
1302 BOOL ret;
1303 PMIB_IPADDRTABLE table = closure;
1304
1305 if (table && data)
1306 {
1307 DWORD ndx;
1308
1309 ret = FALSE;
1310 for (ndx = 0; !ret && ndx < table->dwNumEntries; ndx++)
1311 {
1312 const NetBTAdapter *adapter = data->data;
1313
1314 if (table->table[ndx].dwIndex == adapter->ipr.dwIndex)
1315 {
1317 table->table[ndx].dwAddr = INADDR_LOOPBACK;
1318 ret = TRUE;
1319 }
1320 }
1321 }
1322 else
1323 ret = FALSE;
1324 return ret;
1325}
1326
1327/* Enumerates adapters by:
1328 * - retrieving the IP address table for the local machine
1329 * - eliminating loopback addresses from the table
1330 * - eliminating redundant addresses, that is, multiple addresses on the same
1331 * subnet
1332 * Calls NetBIOSEnumAdapters, passing the resulting table as the callback
1333 * data. The callback reenables each adapter that's already in the NetBIOS
1334 * table. After NetBIOSEnumAdapters returns, this function adds any remaining
1335 * adapters to the NetBIOS table.
1336 */
1337static UCHAR NetBTEnum(void)
1338{
1339 UCHAR ret;
1340 DWORD size = 0;
1341
1342 TRACE("\n");
1343
1345 {
1346 PMIB_IPADDRTABLE ipAddrs, coalesceTable = NULL;
1347 DWORD numIPAddrs = (size - sizeof(MIB_IPADDRTABLE)) /
1348 sizeof(MIB_IPADDRROW) + 1;
1349
1351 if (ipAddrs)
1352 coalesceTable = HeapAlloc(GetProcessHeap(),
1354 (min(numIPAddrs, MAX_LANA + 1) - 1) * sizeof(MIB_IPADDRROW));
1355 if (ipAddrs && coalesceTable)
1356 {
1357 if (GetIpAddrTable(ipAddrs, &size, FALSE) == ERROR_SUCCESS)
1358 {
1359 DWORD ndx;
1360
1361 for (ndx = 0; ndx < ipAddrs->dwNumEntries; ndx++)
1362 {
1363 if ((ipAddrs->table[ndx].dwAddr &
1364 ipAddrs->table[ndx].dwMask) !=
1366 {
1368 DWORD innerIndex;
1369
1370 /* make sure we don't have more than one entry
1371 * for a subnet */
1372 for (innerIndex = 0; newNetwork &&
1373 innerIndex < coalesceTable->dwNumEntries; innerIndex++)
1374 if ((ipAddrs->table[ndx].dwAddr &
1375 ipAddrs->table[ndx].dwMask) ==
1376 (coalesceTable->table[innerIndex].dwAddr
1377 & coalesceTable->table[innerIndex].dwMask))
1378 newNetwork = FALSE;
1379
1380 if (newNetwork)
1381 memcpy(&coalesceTable->table[
1382 coalesceTable->dwNumEntries++],
1383 &ipAddrs->table[ndx], sizeof(MIB_IPADDRROW));
1384 }
1385 }
1386
1388 coalesceTable);
1389 ret = NRC_GOODRET;
1390 for (ndx = 0; ret == NRC_GOODRET &&
1391 ndx < coalesceTable->dwNumEntries; ndx++)
1392 if (coalesceTable->table[ndx].dwAddr != INADDR_LOOPBACK)
1393 ret = NetBTRegisterAdapter(&coalesceTable->table[ndx]);
1394 }
1395 else
1396 ret = NRC_SYSTEM;
1397 HeapFree(GetProcessHeap(), 0, ipAddrs);
1398 HeapFree(GetProcessHeap(), 0, coalesceTable);
1399 }
1400 else
1402 }
1403 else
1404 ret = NRC_SYSTEM;
1405 TRACE("returning 0x%02x\n", ret);
1406 return ret;
1407}
1408
1409static const WCHAR VxD_MSTCPW[] = { 'S','Y','S','T','E','M','\\','C','u','r',
1410 'r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','S','e','r','v',
1411 'i','c','e','s','\\','V','x','D','\\','M','S','T','C','P','\0' };
1412static const WCHAR NetBT_ParametersW[] = { 'S','Y','S','T','E','M','\\','C','u',
1413 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','S','e','r',
1414 'v','i','c','e','s','\\','N','e','t','B','T','\\','P','a','r','a','m','e','t',
1415 'e','r','s','\0' };
1416static const WCHAR EnableDNSW[] = { 'E','n','a','b','l','e','D','N','S','\0' };
1417static const WCHAR BcastNameQueryCountW[] = { 'B','c','a','s','t','N','a','m',
1418 'e','Q','u','e','r','y','C','o','u','n','t','\0' };
1419static const WCHAR BcastNameQueryTimeoutW[] = { 'B','c','a','s','t','N','a','m',
1420 'e','Q','u','e','r','y','T','i','m','e','o','u','t','\0' };
1421static const WCHAR NameSrvQueryCountW[] = { 'N','a','m','e','S','r','v',
1422 'Q','u','e','r','y','C','o','u','n','t','\0' };
1423static const WCHAR NameSrvQueryTimeoutW[] = { 'N','a','m','e','S','r','v',
1424 'Q','u','e','r','y','T','i','m','e','o','u','t','\0' };
1425static const WCHAR ScopeIDW[] = { 'S','c','o','p','e','I','D','\0' };
1426static const WCHAR CacheTimeoutW[] = { 'C','a','c','h','e','T','i','m','e','o',
1427 'u','t','\0' };
1428static const WCHAR Config_NetworkW[] = { 'S','o','f','t','w','a','r','e','\\',
1429 'W','i','n','e','\\','N','e','t','w','o','r','k','\0' };
1430
1431/* Initializes global variables and registers the NetBT transport */
1432void NetBTInit(void)
1433{
1434 HKEY hKey;
1435 NetBIOSTransport transport;
1436 LONG ret;
1437
1438 TRACE("\n");
1439
1440 gEnableDNS = TRUE;
1445 gNumWINSServers = 0;
1446 memset(gWINSServers, 0, sizeof(gWINSServers));
1447 gScopeID[0] = '\0';
1449
1450 /* Try to open the Win9x NetBT configuration key */
1452 /* If that fails, try the WinNT NetBT configuration key */
1453 if (ret != ERROR_SUCCESS)
1455 &hKey);
1456 if (ret == ERROR_SUCCESS)
1457 {
1458 DWORD dword, size;
1459
1460 size = sizeof(dword);
1462 (LPBYTE)&dword, &size) == ERROR_SUCCESS)
1463 gEnableDNS = dword;
1464 size = sizeof(dword);
1466 (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERIES
1467 && dword <= MAX_QUERIES)
1468 gBCastQueries = dword;
1469 size = sizeof(dword);
1471 (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERY_TIMEOUT)
1472 gBCastQueryTimeout = dword;
1473 size = sizeof(dword);
1475 (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERIES
1476 && dword <= MAX_QUERIES)
1477 gWINSQueries = dword;
1478 size = sizeof(dword);
1480 (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERY_TIMEOUT)
1481 gWINSQueryTimeout = dword;
1482 size = sizeof(gScopeID) - 1;
1484 == ERROR_SUCCESS)
1485 {
1486 /* convert into L2-encoded version, suitable for use by
1487 NetBTNameEncode */
1488 char *ptr, *lenPtr;
1489
1490 for (ptr = gScopeID + 1, lenPtr = gScopeID; ptr - gScopeID < sizeof(gScopeID) && *ptr; ++ptr)
1491 {
1492 if (*ptr == '.')
1493 {
1494 lenPtr = ptr;
1495 *lenPtr = 0;
1496 }
1497 else
1498 {
1499 ++*lenPtr;
1500 }
1501 }
1502 }
1504 (LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_CACHE_TIMEOUT)
1505 gCacheTimeout = dword;
1507 }
1508 /* WINE-specific NetBT registry settings. Because our adapter naming is
1509 * different than MS', we can't do per-adapter WINS configuration in the
1510 * same place. Just do a global WINS configuration instead.
1511 */
1512 /* @@ Wine registry key: HKCU\Software\Wine\Network */
1514 {
1515 static const char *nsValueNames[] = { "WinsServer", "BackupWinsServer" };
1516 char nsString[16];
1517 DWORD size, ndx;
1518
1519 for (ndx = 0; ndx < sizeof(nsValueNames) / sizeof(nsValueNames[0]);
1520 ndx++)
1521 {
1522 size = sizeof(nsString) / sizeof(char);
1523 if (RegQueryValueExA(hKey, nsValueNames[ndx], NULL, NULL,
1524 (LPBYTE)nsString, &size) == ERROR_SUCCESS)
1525 {
1526 unsigned long addr = inet_addr(nsString);
1527
1530 }
1531 }
1533 }
1534
1535 transport.enumerate = NetBTEnum;
1536 transport.astat = NetBTAstat;
1537 transport.findName = NetBTFindName;
1538 transport.call = NetBTCall;
1539 transport.send = NetBTSend;
1540 transport.recv = NetBTRecv;
1541 transport.hangup = NetBTHangup;
1543 transport.cleanup = NetBTCleanup;
1546}
static INT adapt(INT delta, INT numpoints, BOOL firsttime)
Definition: IdnToAscii.c:20
_STLP_DECLSPEC complex< float > _STLP_CALL sin(const complex< float > &)
#define isdigit(c)
Definition: acclib.h:68
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
CHAR FAR *WSAAPI inet_ntoa(IN IN_ADDR in)
Definition: addrconv.c:160
ULONG WSAAPI inet_addr(IN CONST CHAR FAR *cp)
Definition: addrconv.c:71
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
#define RegCloseKey(hKey)
Definition: registry.h:49
#define NO_ERROR
Definition: dderror.h:5
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3268
LONG WINAPI RegQueryValueExA(_In_ HKEY hkeyorg, _In_ LPCSTR name, _In_ LPDWORD reserved, _Out_opt_ LPDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ LPDWORD count)
Definition: reg.c:4009
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
void NetBIOSEnableAdapter(UCHAR lana)
Definition: netbios.c:231
BOOL NetBIOSRegisterAdapter(ULONG transport, DWORD ifIndex, void *data)
Definition: netbios.c:175
BOOL NetBIOSRegisterTransport(ULONG id, NetBIOSTransport *transport)
Definition: netbios.c:131
void NetBIOSHangupSession(const NCB *ncb)
Definition: netbios.c:664
void NetBIOSEnumAdapters(ULONG transport, NetBIOSEnumAdaptersCallback cb, void *closure)
Definition: netbios.c:296
INT WSAAPI WSARecvFrom(IN SOCKET s, IN OUT LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesRecvd, IN OUT LPDWORD lpFlags, OUT LPSOCKADDR lpFrom, IN OUT LPINT lpFromlen, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
Definition: recv.c:254
INT WSAAPI WSARecv(IN SOCKET s, IN OUT LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesRecvd, IN OUT LPDWORD lpFlags, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
Definition: recv.c:155
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
INT WSAAPI WSASend(IN SOCKET s, IN LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesSent, IN DWORD dwFlags, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
Definition: send.c:145
INT WSAAPI WSASendTo(IN SOCKET s, IN LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesSent, IN DWORD dwFlags, IN CONST struct sockaddr *lpTo, IN INT iToLen, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
Definition: send.c:247
#define IPPROTO_TCP
Definition: ip.h:196
#define IPPROTO_UDP
Definition: ip.h:197
#define SOCK_STREAM
Definition: tcpip.h:118
#define AF_INET
Definition: tcpip.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
time_t now
Definition: finger.c:65
return adapter
FxAutoRegKey hKey
PHOSTENT WSAAPI gethostbyname(IN const char FAR *name)
Definition: getxbyxx.c:221
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizeiptr size
Definition: glext.h:5919
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLenum const GLvoid * addr
Definition: glext.h:9621
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow)
DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder)
#define MIB_IF_TYPE_TOKENRING
Definition: ipifcons.h:224
struct _MIB_IPADDRROW MIB_IPADDRROW
struct _MIB_IPADDRTABLE MIB_IPADDRTABLE
#define MAX_DOMAIN_NAME_LEN
Definition: iptypes.h:31
#define MAX_SCOPE_ID_LEN
Definition: iptypes.h:32
#define IN_CLASSA_NET
Definition: inet.h:98
#define INADDR_LOOPBACK
Definition: inet.h:78
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define htons(x)
Definition: module.h:215
#define htonl(x)
Definition: module.h:214
#define for
Definition: utility.h:88
static PVOID ptr
Definition: dispmode.c:27
#define min(a, b)
Definition: monoChain.cc:55
#define NRC_REMTFUL
Definition: nb30.h:66
struct _ADAPTER_STATUS * PADAPTER_STATUS
struct _FIND_NAME_BUFFER * PFIND_NAME_BUFFER
#define NRC_BADDR
Definition: nb30.h:57
#define NRC_NOWILD
Definition: nb30.h:69
struct _FIND_NAME_HEADER * PFIND_NAME_HEADER
#define NRC_OSRESNOTAV
Definition: nb30.h:81
#define NRC_SYSTEM
Definition: nb30.h:89
#define NRC_SABORT
Definition: nb30.h:72
struct _FIND_NAME_HEADER FIND_NAME_HEADER
#define DEREGISTERED
Definition: nb30.h:14
#define REGISTERING
Definition: nb30.h:12
#define GROUP_NAME
Definition: nb30.h:10
#define NRC_SNUMOUT
Definition: nb30.h:58
#define DUPLICATE
Definition: nb30.h:15
#define NRC_BUFLEN
Definition: nb30.h:53
#define NRC_GOODRET
Definition: nb30.h:52
#define REGISTERED
Definition: nb30.h:13
#define NRC_NAMERR
Definition: nb30.h:71
#define NRC_CMDCAN
Definition: nb30.h:61
#define NRC_ENVNOTDEF
Definition: nb30.h:80
#define NRC_INVADDRESS
Definition: nb30.h:85
#define NRC_BRIDGE
Definition: nb30.h:76
#define NCBNAMSZ
Definition: nb30.h:7
#define NRC_NOCALL
Definition: nb30.h:68
#define MAX_LANA
Definition: nb30.h:8
#define NRC_CMDTMO
Definition: nb30.h:55
#define NRC_INCOMP
Definition: nb30.h:56
BOOL NBNameCacheAddEntry(struct NBNameCache *cache, NBNameCacheEntry *entry)
Definition: nbnamecache.c:111
void NBNameCacheDestroy(struct NBNameCache *cache)
Definition: nbnamecache.c:176
struct NBNameCache * NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS)
Definition: nbnamecache.c:92
const NBNameCacheEntry * NBNameCacheFindEntry(struct NBNameCache *cache, const UCHAR name[NCBNAMSZ])
Definition: nbnamecache.c:151
#define WINS_QUERY_TIMEOUT
Definition: nbt.c:93
struct _NetBTNameQueryData NetBTNameQueryData
static int NetBTSendNameQuery(SOCKET fd, const UCHAR name[NCBNAMSZ], WORD xid, WORD qtype, DWORD destAddr, BOOL broadcast)
Definition: nbt.c:227
#define NBSS_MSG
Definition: nbt.c:111
static BOOL NetBTEnumCallback(UCHAR totalLANAs, UCHAR lanaIndex, ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
Definition: nbt.c:1299
static const WCHAR BcastNameQueryTimeoutW[]
Definition: nbt.c:1419
static char gScopeID[MAX_SCOPE_ID_LEN]
Definition: nbt.c:149
#define NBR_GETWORD(p)
Definition: nbt.c:84
static UCHAR NetBTRegisterAdapter(const MIB_IPADDRROW *ipRow)
Definition: nbt.c:1266
static const WCHAR ScopeIDW[]
Definition: nbt.c:1425
#define MIN_QUERIES
Definition: nbt.c:86
static UCHAR NetBTAstatRemote(NetBTAdapter *adapter, PNCB ncb)
Definition: nbt.c:738
struct _NetBTAdapter NetBTAdapter
static UCHAR NetBTRecv(void *adapt, void *sess, PNCB ncb)
Definition: nbt.c:1114
void NetBTInit(void)
Definition: nbt.c:1432
#define NBSS_HDRSIZE
Definition: nbt.c:109
#define NBSS_ACK
Definition: nbt.c:113
#define PORT_NBNS
Definition: nbt.c:75
#define INADDR_NONE
Definition: nbt.c:80
static const WCHAR BcastNameQueryCountW[]
Definition: nbt.c:1417
static const WCHAR Config_NetworkW[]
Definition: nbt.c:1428
static DWORD gBCastQueries
Definition: nbt.c:143
static DWORD NetBTNameReq(const UCHAR name[NCBNAMSZ], WORD xid, WORD qtype, BOOL broadcast, UCHAR *buffer, int len)
Definition: nbt.c:191
static UCHAR NetBTEnum(void)
Definition: nbt.c:1337
static BOOL gEnableDNS
Definition: nbt.c:142
static UCHAR NetBTNameWaitLoop(const NetBTAdapter *adapter, SOCKET fd, const NCB *ncb, DWORD sendTo, BOOL broadcast, DWORD timeout, DWORD maxQueries, NBNameCacheEntry **cacheEntry)
Definition: nbt.c:433
static DWORD gWINSQueryTimeout
Definition: nbt.c:146
static DWORD gCacheTimeout
Definition: nbt.c:150
static struct NBNameCache * gNameCache
Definition: nbt.c:151
static UCHAR NetBTInternalFindName(NetBTAdapter *adapter, PNCB ncb, const NBNameCacheEntry **cacheEntry)
Definition: nbt.c:593
static const WCHAR NameSrvQueryCountW[]
Definition: nbt.c:1421
static UCHAR NetBTFindName(void *adapt, PNCB ncb)
Definition: nbt.c:847
static BOOL NetBTFindNameAnswerCallback(void *pVoid, WORD answerCount, WORD answerIndex, PUCHAR rData, WORD rLen)
Definition: nbt.c:392
static UCHAR NetBTHangup(void *adapt, void *sess)
Definition: nbt.c:1222
static const WCHAR VxD_MSTCPW[]
Definition: nbt.c:1409
#define NBNS_HEADER_SIZE
Definition: nbt.c:104
#define NBSS_KEEPALIVE
Definition: nbt.c:116
static DWORD gBCastQueryTimeout
Definition: nbt.c:144
static const WCHAR EnableDNSW[]
Definition: nbt.c:1416
static DWORD gWINSQueries
Definition: nbt.c:145
static UCHAR NetBTinetResolve(const UCHAR name[NCBNAMSZ], NBNameCacheEntry **cacheEntry)
Definition: nbt.c:509
#define MIN_CACHE_TIMEOUT
Definition: nbt.c:95
#define BCAST_QUERY_TIMEOUT
Definition: nbt.c:91
static UCHAR NetBTStoreCacheEntry(struct NBNameCache **nameCache, NBNameCacheEntry *cacheEntry)
Definition: nbt.c:480
static UCHAR NetBTCall(void *adapt, PNCB ncb, void **sess)
Definition: nbt.c:964
static const WCHAR NetBT_ParametersW[]
Definition: nbt.c:1412
static ULONG gTransportID
Definition: nbt.c:141
static UCHAR NetBTSessionReq(SOCKET fd, const UCHAR *calledName, const UCHAR *callingName)
Definition: nbt.c:899
#define NBSS_ERR_INSUFFICIENT_RESOURCES
Definition: nbt.c:121
#define MIN_QUERY_TIMEOUT
Definition: nbt.c:88
static void NetBTCleanup(void)
Definition: nbt.c:1256
#define NBNS_REPLYCODE
Definition: nbt.c:107
static int NetBTNameEncode(const UCHAR *p, UCHAR *buffer)
Definition: nbt.c:158
static DWORD gWINSServers[MAX_WINS_SERVERS]
Definition: nbt.c:147
static void NetBTCleanupAdapter(void *adapt)
Definition: nbt.c:1243
#define PORT_NBSS
Definition: nbt.c:77
#define SIMPLE_NAME_QUERY_PKT_SIZE
Definition: nbt.c:99
static UCHAR NetBTSend(void *adapt, void *sess, PNCB ncb)
Definition: nbt.c:1065
static int gNumWINSServers
Definition: nbt.c:148
struct _NetBTNodeQueryData NetBTNodeQueryData
#define NBNS_RESPONSE_AND_OPCODE
Definition: nbt.c:105
#define BCAST_QUERIES
Definition: nbt.c:90
#define NBSS_RETARGET
Definition: nbt.c:115
#define WINS_QUERIES
Definition: nbt.c:92
static UCHAR NetBTWaitForNameResponse(const NetBTAdapter *adapter, SOCKET fd, DWORD waitUntil, NetBTAnswerCallback answerCallback, void *data)
Definition: nbt.c:281
#define CACHE_TIMEOUT
Definition: nbt.c:96
#define NBNS_CLASS_INTERNET
Definition: nbt.c:103
#define NBNS_TYPE_NBSTAT
Definition: nbt.c:102
struct _NetBTSession NetBTSession
#define NBSS_NACK
Definition: nbt.c:114
#define MAX_WINS_SERVERS
Definition: nbt.c:94
BOOL(* NetBTAnswerCallback)(void *data, WORD answerCount, WORD answerIndex, PUCHAR rData, WORD rdLength)
Definition: nbt.c:269
#define NBNS_TYPE_NB
Definition: nbt.c:101
#define MAX_QUERIES
Definition: nbt.c:87
#define NBR_ADDWORD(p, word)
Definition: nbt.c:83
#define NBNS_RESPONSE_AND_QUERY
Definition: nbt.c:106
static const WCHAR NameSrvQueryTimeoutW[]
Definition: nbt.c:1423
static const WCHAR CacheTimeoutW[]
Definition: nbt.c:1426
static BOOL NetBTNodeStatusAnswerCallback(void *pVoid, WORD answerCount, WORD answerIndex, PUCHAR rData, WORD rLen)
Definition: nbt.c:686
#define NBSS_REQ
Definition: nbt.c:112
#define NBSS_EXTENSION
Definition: nbt.c:123
static UCHAR NetBTAstat(void *adapt, PNCB ncb)
Definition: nbt.c:802
#define closesocket
Definition: ncftp.h:477
#define TRANSPORT_NBT
Definition: netbios.h:173
#define NCB_CANCELLED(pncb)
Definition: netbios.h:129
LONGLONG xid
Definition: nfs41_driver.c:106
#define BOOL
Definition: nt_native.h:43
#define KEY_READ
Definition: nt_native.h:1023
#define DWORD
Definition: nt_native.h:44
long LONG
Definition: pedump.c:60
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
INT WSAAPI setsockopt(IN SOCKET s, IN INT level, IN INT optname, IN CONST CHAR FAR *optval, IN INT optlen)
Definition: sockctrl.c:421
SOCKET WSAAPI WSASocketA(IN INT af, IN INT type, IN INT protocol, IN LPWSAPROTOCOL_INFOA lpProtocolInfo, IN GROUP g, IN DWORD dwFlags)
Definition: socklife.c:444
#define TRACE(s)
Definition: solgame.cpp:4
DWORD xmit_success
Definition: nb30.h:108
WORD name_count
Definition: nb30.h:124
UCHAR rev_major
Definition: nb30.h:99
DWORD recv_success
Definition: nb30.h:109
UCHAR adapter_type
Definition: nb30.h:101
WORD max_sess_pkt_size
Definition: nb30.h:123
UCHAR adapter_address[6]
Definition: nb30.h:98
DWORD_PTR Spare[8/sizeof(DWORD_PTR)]
Definition: winbase.h:912
PCRITICAL_SECTION_DEBUG DebugInfo
Definition: winbase.h:919
UCHAR source_addr[6]
Definition: nb30.h:131
UCHAR destination_addr[6]
Definition: nb30.h:130
WORD node_count
Definition: nb30.h:135
UCHAR bPhysAddr[MAXLEN_PHYSADDR]
Definition: ifmib.h:43
DWORD dwPhysAddrLen
Definition: ifmib.h:42
DWORD dwType
Definition: ifmib.h:39
DWORD dwIndex
Definition: ifmib.h:38
DWORD dwMask
Definition: ipmib.h:38
DWORD dwAddr
Definition: ipmib.h:36
IF_INDEX dwIndex
Definition: ipmib.h:37
MIB_IPADDRROW table[1]
Definition: ipmib.h:48
DWORD dwNumEntries
Definition: ipmib.h:47
UCHAR nbname[NCBNAMSZ]
Definition: nbnamecache.h:35
UCHAR name[NCBNAMSZ]
Definition: nbnamecache.h:34
DWORD addresses[1]
Definition: nbnamecache.h:37
Definition: nb30.h:148
PUCHAR ncb_buffer
Definition: nb30.h:153
UCHAR ncb_sto
Definition: nb30.h:158
WORD ncb_length
Definition: nb30.h:154
UCHAR ncb_callname[NCBNAMSZ]
Definition: nb30.h:155
UCHAR ncb_name[NCBNAMSZ]
Definition: nb30.h:156
UCHAR ncb_rto
Definition: nb30.h:157
NetBIOSFindName findName
Definition: netbios.h:155
NetBIOSCall call
Definition: netbios.h:156
NetBIOSSend send
Definition: netbios.h:157
NetBIOSRecv recv
Definition: netbios.h:158
NetBIOSHangup hangup
Definition: netbios.h:159
NetBIOSAstat astat
Definition: netbios.h:154
NetBIOSEnum enumerate
Definition: netbios.h:153
NetBIOSCleanupAdapter cleanupAdapter
Definition: netbios.h:160
NetBIOSCleanup cleanup
Definition: netbios.h:161
DWORD xmit_success
Definition: nbt.c:137
WORD nameQueryXID
Definition: nbt.c:135
MIB_IPADDRROW ipr
Definition: nbt.c:134
struct NBNameCache * nameCache
Definition: nbt.c:136
DWORD recv_success
Definition: nbt.c:138
NBNameCacheEntry * cacheEntry
Definition: nbt.c:383
PADAPTER_STATUS astat
Definition: nbt.c:678
BOOL gotResponse
Definition: nbt.c:677
SOCKET fd
Definition: nbt.c:128
CRITICAL_SECTION cs
Definition: nbt.c:127
DWORD bytesPending
Definition: nbt.c:129
ULONG len
Definition: ws2def.h:519
CHAR FAR * buf
Definition: ws2def.h:520
Definition: winsock.h:66
Definition: tcpip.h:126
in_addr_t s_addr
Definition: inet.h:64
Definition: name.c:39
CRITICAL_SECTION cs
Definition: dhcpd.h:245
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
static const u8_t broadcast[6]
Definition: test_dhcp.c:23
data1 newNetwork
Definition: tftpd.cpp:50
#define DWORD_PTR
Definition: treelist.c:76
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * LPBYTE
Definition: typedefs.h:53
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
int ret
char * host
Definition: whois.c:55
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define WSA_FLAG_OVERLAPPED
Definition: winsock2.h:466
int PASCAL FAR WSAGetLastError(void)
Definition: dllmain.c:112
#define FD_ZERO(set)
Definition: winsock.h:96
#define INVALID_SOCKET
Definition: winsock.h:332
#define PF_INET
Definition: winsock.h:373
#define SOCK_DGRAM
Definition: winsock.h:336
UINT_PTR SOCKET
Definition: winsock.h:47
#define SOCKET_ERROR
Definition: winsock.h:333
#define SOL_SOCKET
Definition: winsock.h:398
#define SO_SNDTIMEO
Definition: winsock.h:192
#define FD_SET(fd, set)
Definition: winsock.h:89
#define SO_BROADCAST
Definition: winsock.h:183
#define SO_RCVTIMEO
Definition: winsock.h:193
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175