1/*
2 * Copyright (c) 2000, 2001 Boris Popov
3 * All rights reserved.
4 *
5 * Portions Copyright (C) 2001 - 2010 Apple Inc. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *    This product includes software developed by Boris Popov.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $Id: nb.c,v 1.2 2005/10/07 03:51:09 lindak Exp $
35 */
36
37#include <netsmb/netbios.h>
38#include <netsmb/smb_lib.h>
39#include <netsmb/nb_lib.h>
40
41
42#define NBNS_FMT_ERR	0x01	/* Request was invalidly formatted */
43#define NBNS_SRV_ERR	0x02	/* Problem with NBNS, connot process name */
44#define NBNS_NME_ERR	0x03	/* No such name */
45#define NBNS_IMP_ERR	0x04	/* Unsupport request */
46#define NBNS_RFS_ERR	0x05	/* For policy reasons server will not register this name fron this host */
47#define NBNS_ACT_ERR	0x06	/* Name is owned by another host */
48#define NBNS_CFT_ERR	0x07	/* Name conflict error  */
49
50static int nb_resolve_wins(CFArrayRef WINSAddresses, CFMutableArrayRef *addressArray)
51{
52	CFIndex ii, count = CFArrayGetCount(WINSAddresses);
53	int  error = ENOMEM;
54
55	for (ii = 0; ii < count; ii++) {
56		CFStringRef winsString = CFArrayGetValueAtIndex(WINSAddresses, ii);
57		char winsName[SMB_MAX_DNS_SRVNAMELEN+1];
58
59		if (winsString == NULL) {
60			continue;
61		}
62
63		CFStringGetCString(winsString, winsName,  sizeof(winsName), kCFStringEncodingUTF8);
64		error = resolvehost(winsName, addressArray, NULL, NBNS_UDP_PORT_137, TRUE, FALSE);
65		if (error == 0) {
66			break;
67		}
68		smb_log_info("can't resolve WINS[%d] %s, syserr = %s", ASL_LEVEL_DEBUG,
69					 (int)ii, winsName, strerror(error));
70	}
71	return error;
72}
73
74/*
75 * Used for resolving NetBIOS names
76 */
77int nb_ctx_resolve(struct nb_ctx *ctx, CFArrayRef WINSAddresses)
78{
79	int error = 0;
80
81	if (WINSAddresses == NULL) {
82		ctx->nb_ns.sin_addr.s_addr = htonl(INADDR_BROADCAST);
83		ctx->nb_ns.sin_port = htons(NBNS_UDP_PORT_137);
84		ctx->nb_ns.sin_family = AF_INET;
85		ctx->nb_ns.sin_len = sizeof(ctx->nb_ns);
86	} else {
87		CFMutableArrayRef addressArray = NULL;
88		CFMutableDataRef addressData = NULL;
89		struct connectAddress *conn = NULL;
90
91		error = nb_resolve_wins(WINSAddresses, &addressArray);
92		if (error) {
93			return error;
94		}
95		/*
96		 * At this point we have at least one IPv4 sockaddr in outAddressArray
97		 * that we can use. May want to change this in the future to try all
98		 * address.
99		 */
100		addressData = (CFMutableDataRef)CFArrayGetValueAtIndex(addressArray, 0);
101		if (addressData)
102			conn = (struct connectAddress *)((void *)CFDataGetMutableBytePtr(addressData));
103
104		if (conn)
105			memcpy(&ctx->nb_ns, &conn->addr, conn->addr.sa_len);
106		else
107			error = ENOMEM;
108		CFRelease(addressArray);
109	}
110	return error;
111}
112
113/*
114 * Convert NetBIOS name lookup errors to UNIX errors
115 */
116int nb_error_to_errno(int error)
117{
118	switch (error) {
119	case NBNS_FMT_ERR:
120		error = EINVAL;
121		break;
122	case NBNS_SRV_ERR:
123		error = EBUSY;
124		break;
125	case NBNS_NME_ERR:
126		error = ENOENT;
127		break;
128	case NBNS_IMP_ERR:
129		error = ENOTSUP;
130		break;
131	case NBNS_RFS_ERR:
132		error = EACCES;
133		break;
134	case NBNS_ACT_ERR:
135		error = EADDRINUSE;
136		break;
137	case NBNS_CFT_ERR:
138		error = EADDRINUSE;
139		break;
140	default:
141		error = ETIMEDOUT;
142		break;
143	};
144	return error;
145}
146