1f1b9d127SSheldon Hearn /*
2f1b9d127SSheldon Hearn * Copyright (c) 2000, 2001 Boris Popov
3f1b9d127SSheldon Hearn * All rights reserved.
4f1b9d127SSheldon Hearn *
5f1b9d127SSheldon Hearn * Redistribution and use in source and binary forms, with or without
6f1b9d127SSheldon Hearn * modification, are permitted provided that the following conditions
7f1b9d127SSheldon Hearn * are met:
8f1b9d127SSheldon Hearn * 1. Redistributions of source code must retain the above copyright
9f1b9d127SSheldon Hearn * notice, this list of conditions and the following disclaimer.
10f1b9d127SSheldon Hearn * 2. Redistributions in binary form must reproduce the above copyright
11f1b9d127SSheldon Hearn * notice, this list of conditions and the following disclaimer in the
12f1b9d127SSheldon Hearn * documentation and/or other materials provided with the distribution.
13f1b9d127SSheldon Hearn * 3. All advertising materials mentioning features or use of this software
14f1b9d127SSheldon Hearn * must display the following acknowledgement:
15f1b9d127SSheldon Hearn * This product includes software developed by Boris Popov.
16f1b9d127SSheldon Hearn * 4. Neither the name of the author nor the names of any co-contributors
17f1b9d127SSheldon Hearn * may be used to endorse or promote products derived from this software
18f1b9d127SSheldon Hearn * without specific prior written permission.
19f1b9d127SSheldon Hearn *
20f1b9d127SSheldon Hearn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21f1b9d127SSheldon Hearn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22f1b9d127SSheldon Hearn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23f1b9d127SSheldon Hearn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24f1b9d127SSheldon Hearn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25f1b9d127SSheldon Hearn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26f1b9d127SSheldon Hearn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27f1b9d127SSheldon Hearn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28f1b9d127SSheldon Hearn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29f1b9d127SSheldon Hearn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30f1b9d127SSheldon Hearn * SUCH DAMAGE.
31f1b9d127SSheldon Hearn *
32f1b9d127SSheldon Hearn * $Id: nb.c,v 1.4 2001/04/16 04:33:01 bp Exp $
33ef29b0f6SBoris Popov * $FreeBSD$
34f1b9d127SSheldon Hearn */
35f1b9d127SSheldon Hearn #include <sys/param.h>
36f1b9d127SSheldon Hearn #include <sys/socket.h>
37f1b9d127SSheldon Hearn
38f1b9d127SSheldon Hearn #include <ctype.h>
39f1b9d127SSheldon Hearn #include <netdb.h>
40f1b9d127SSheldon Hearn #include <err.h>
41f1b9d127SSheldon Hearn #include <errno.h>
42f1b9d127SSheldon Hearn #include <stdlib.h>
43f1b9d127SSheldon Hearn #include <string.h>
44f1b9d127SSheldon Hearn #include <stdio.h>
45f1b9d127SSheldon Hearn #include <unistd.h>
46f1b9d127SSheldon Hearn #include <cflib.h>
47f1b9d127SSheldon Hearn
48f1b9d127SSheldon Hearn #include <netsmb/netbios.h>
49f1b9d127SSheldon Hearn #include <netsmb/smb_lib.h>
50f1b9d127SSheldon Hearn #include <netsmb/nb_lib.h>
51f1b9d127SSheldon Hearn
52f1b9d127SSheldon Hearn int
nb_ctx_create(struct nb_ctx ** ctxpp)53f1b9d127SSheldon Hearn nb_ctx_create(struct nb_ctx **ctxpp)
54f1b9d127SSheldon Hearn {
55f1b9d127SSheldon Hearn struct nb_ctx *ctx;
56f1b9d127SSheldon Hearn
57f1b9d127SSheldon Hearn ctx = malloc(sizeof(struct nb_ctx));
58f1b9d127SSheldon Hearn if (ctx == NULL)
59f1b9d127SSheldon Hearn return ENOMEM;
60f1b9d127SSheldon Hearn bzero(ctx, sizeof(struct nb_ctx));
61ef29b0f6SBoris Popov ctx->nb_nmbtcpport = NMB_TCP_PORT;
62ef29b0f6SBoris Popov ctx->nb_smbtcpport = SMB_TCP_PORT;
63ef29b0f6SBoris Popov
64f1b9d127SSheldon Hearn *ctxpp = ctx;
65f1b9d127SSheldon Hearn return 0;
66f1b9d127SSheldon Hearn }
67f1b9d127SSheldon Hearn
68f1b9d127SSheldon Hearn void
nb_ctx_done(struct nb_ctx * ctx)69f1b9d127SSheldon Hearn nb_ctx_done(struct nb_ctx *ctx)
70f1b9d127SSheldon Hearn {
71f1b9d127SSheldon Hearn if (ctx == NULL)
72f1b9d127SSheldon Hearn return;
73f1b9d127SSheldon Hearn if (ctx->nb_scope)
74f1b9d127SSheldon Hearn free(ctx->nb_scope);
75f1b9d127SSheldon Hearn }
76f1b9d127SSheldon Hearn
77f1b9d127SSheldon Hearn int
nb_ctx_setns(struct nb_ctx * ctx,const char * addr)78f1b9d127SSheldon Hearn nb_ctx_setns(struct nb_ctx *ctx, const char *addr)
79f1b9d127SSheldon Hearn {
80f1b9d127SSheldon Hearn if (addr == NULL || addr[0] == 0)
81f1b9d127SSheldon Hearn return EINVAL;
82f1b9d127SSheldon Hearn if (ctx->nb_nsname)
83f1b9d127SSheldon Hearn free(ctx->nb_nsname);
84f1b9d127SSheldon Hearn if ((ctx->nb_nsname = strdup(addr)) == NULL)
85f1b9d127SSheldon Hearn return ENOMEM;
86f1b9d127SSheldon Hearn return 0;
87f1b9d127SSheldon Hearn }
88f1b9d127SSheldon Hearn
89f1b9d127SSheldon Hearn int
nb_ctx_setscope(struct nb_ctx * ctx,const char * scope)90f1b9d127SSheldon Hearn nb_ctx_setscope(struct nb_ctx *ctx, const char *scope)
91f1b9d127SSheldon Hearn {
92f1b9d127SSheldon Hearn size_t slen = strlen(scope);
93f1b9d127SSheldon Hearn
94f1b9d127SSheldon Hearn if (slen >= 128) {
95f1b9d127SSheldon Hearn smb_error("scope '%s' is too long", 0, scope);
96f1b9d127SSheldon Hearn return ENAMETOOLONG;
97f1b9d127SSheldon Hearn }
98f1b9d127SSheldon Hearn if (ctx->nb_scope)
99f1b9d127SSheldon Hearn free(ctx->nb_scope);
100f1b9d127SSheldon Hearn ctx->nb_scope = malloc(slen + 1);
101f1b9d127SSheldon Hearn if (ctx->nb_scope == NULL)
102f1b9d127SSheldon Hearn return ENOMEM;
103f1b9d127SSheldon Hearn nls_str_upper(ctx->nb_scope, scope);
104f1b9d127SSheldon Hearn return 0;
105f1b9d127SSheldon Hearn }
106f1b9d127SSheldon Hearn
107f1b9d127SSheldon Hearn int
nb_ctx_resolve(struct nb_ctx * ctx)108f1b9d127SSheldon Hearn nb_ctx_resolve(struct nb_ctx *ctx)
109f1b9d127SSheldon Hearn {
110f1b9d127SSheldon Hearn struct sockaddr *sap;
111f1b9d127SSheldon Hearn int error;
112f1b9d127SSheldon Hearn
113f1b9d127SSheldon Hearn ctx->nb_flags &= ~NBCF_RESOLVED;
114f1b9d127SSheldon Hearn
115f1b9d127SSheldon Hearn if (ctx->nb_nsname == NULL) {
116f1b9d127SSheldon Hearn ctx->nb_ns.sin_addr.s_addr = htonl(INADDR_BROADCAST);
117f1b9d127SSheldon Hearn } else {
118ef29b0f6SBoris Popov error = nb_resolvehost_in(ctx->nb_nsname, &sap, ctx->nb_smbtcpport);
119f1b9d127SSheldon Hearn if (error) {
120f1b9d127SSheldon Hearn smb_error("can't resolve %s", error, ctx->nb_nsname);
121f1b9d127SSheldon Hearn return error;
122f1b9d127SSheldon Hearn }
123f1b9d127SSheldon Hearn if (sap->sa_family != AF_INET) {
124f1b9d127SSheldon Hearn smb_error("unsupported address family %d", 0, sap->sa_family);
125f1b9d127SSheldon Hearn return EINVAL;
126f1b9d127SSheldon Hearn }
127f1b9d127SSheldon Hearn bcopy(sap, &ctx->nb_ns, sizeof(ctx->nb_ns));
128f1b9d127SSheldon Hearn free(sap);
129f1b9d127SSheldon Hearn }
130ef29b0f6SBoris Popov ctx->nb_ns.sin_port = htons(ctx->nb_nmbtcpport);
131f1b9d127SSheldon Hearn ctx->nb_ns.sin_family = AF_INET;
132f1b9d127SSheldon Hearn ctx->nb_ns.sin_len = sizeof(ctx->nb_ns);
133f1b9d127SSheldon Hearn ctx->nb_flags |= NBCF_RESOLVED;
134f1b9d127SSheldon Hearn return 0;
135f1b9d127SSheldon Hearn }
136f1b9d127SSheldon Hearn
137f1b9d127SSheldon Hearn /*
138f1b9d127SSheldon Hearn * used level values:
139f1b9d127SSheldon Hearn * 0 - default
140f1b9d127SSheldon Hearn * 1 - server
141f1b9d127SSheldon Hearn */
142f1b9d127SSheldon Hearn int
nb_ctx_readrcsection(struct rcfile * rcfile,struct nb_ctx * ctx,const char * sname,int level)143f1b9d127SSheldon Hearn nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx,
144f1b9d127SSheldon Hearn const char *sname, int level)
145f1b9d127SSheldon Hearn {
146f1b9d127SSheldon Hearn char *p;
147f1b9d127SSheldon Hearn int error;
148f1b9d127SSheldon Hearn
149f1b9d127SSheldon Hearn if (level > 1)
150f1b9d127SSheldon Hearn return EINVAL;
151f1b9d127SSheldon Hearn rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo);
152f1b9d127SSheldon Hearn rc_getstringptr(rcfile, sname, "nbns", &p);
153f1b9d127SSheldon Hearn if (p) {
154f1b9d127SSheldon Hearn error = nb_ctx_setns(ctx, p);
155f1b9d127SSheldon Hearn if (error) {
156f1b9d127SSheldon Hearn smb_error("invalid address specified in the section %s", 0, sname);
157f1b9d127SSheldon Hearn return error;
158f1b9d127SSheldon Hearn }
159f1b9d127SSheldon Hearn }
160f1b9d127SSheldon Hearn rc_getstringptr(rcfile, sname, "nbscope", &p);
161f1b9d127SSheldon Hearn if (p)
162f1b9d127SSheldon Hearn nb_ctx_setscope(ctx, p);
163f1b9d127SSheldon Hearn return 0;
164f1b9d127SSheldon Hearn }
165f1b9d127SSheldon Hearn
166f1b9d127SSheldon Hearn static const char *nb_err_rcode[] = {
167f1b9d127SSheldon Hearn "bad request/response format",
168f1b9d127SSheldon Hearn "NBNS server failure",
169f1b9d127SSheldon Hearn "no such name",
170f1b9d127SSheldon Hearn "unsupported request",
171f1b9d127SSheldon Hearn "request rejected",
172f1b9d127SSheldon Hearn "name already registered"
173f1b9d127SSheldon Hearn };
174f1b9d127SSheldon Hearn
175f1b9d127SSheldon Hearn static const char *nb_err[] = {
176f1b9d127SSheldon Hearn "host not found",
177f1b9d127SSheldon Hearn "too many redirects",
178f1b9d127SSheldon Hearn "invalid response",
179f1b9d127SSheldon Hearn "NETBIOS name too long",
180f1b9d127SSheldon Hearn "no interface to broadcast on and no NBNS server specified"
181f1b9d127SSheldon Hearn };
182f1b9d127SSheldon Hearn
183f1b9d127SSheldon Hearn const char *
nb_strerror(int error)184f1b9d127SSheldon Hearn nb_strerror(int error)
185f1b9d127SSheldon Hearn {
186f1b9d127SSheldon Hearn if (error == 0)
187f1b9d127SSheldon Hearn return NULL;
188f1b9d127SSheldon Hearn if (error <= NBERR_ACTIVE)
189f1b9d127SSheldon Hearn return nb_err_rcode[error - 1];
190f1b9d127SSheldon Hearn else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX)
191f1b9d127SSheldon Hearn return nb_err[error - NBERR_HOSTNOTFOUND];
192f1b9d127SSheldon Hearn else
193f1b9d127SSheldon Hearn return NULL;
194f1b9d127SSheldon Hearn }
195f1b9d127SSheldon Hearn
196