/*
* Copyright (c) 2000, Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Boris Popov.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: nbns_rq.c,v 1.9 2005/02/24 02:04:38 lindak Exp $
*/
/*
*/
#include <ctype.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <unistd.h>
#include <libintl.h>
#define NB_NEEDRESOLVER
#include "charsets.h"
#include "private.h"
/*
* nbns request
*/
struct nbns_rq {
int nr_opcode;
int nr_nmflags;
int nr_rcode;
int nr_qdcount;
int nr_ancount;
int nr_nscount;
int nr_arcount;
int nr_rpnmflags;
int nr_rprcode;
int nr_flags;
int nr_fd;
int nr_maxretry;
};
/*
* Call NetBIOS name lookup and return a result in the
* same form as getaddrinfo(3) returns. Return code is
* zero or one of the EAI_xxx codes like getaddrinfo.
*/
int
{
int err;
/*
* Try NetBIOS name lookup.
*/
err = EAI_OVERFLOW;
goto out;
}
goto nomem;
/* Note: this returns an NBERROR value. */
if (err) {
if (smb_verbose)
"nbns_resolvename: %s"),
err = EAI_NODATA;
goto out;
}
/* Note: sap allocated */
/*
* Build the addrinfo struct to return.
*/
goto nomem;
/*
* The type of this is really sockaddr_in,
* but is returned in the generic form.
* See nbns_resolvename.
*/
return (0);
err = EAI_MEMORY;
out:
if (sap)
if (ucname)
return (err);
}
int
{
return (NBERROR(NBERR_NAMETOOLONG));
if (error)
return (error);
/*
* Pad the name with blanks, but
* leave the "type" byte NULL.
* nb_name_encode adds the type.
*/
if (error) {
return (error);
}
for (;;) {
if (error)
break;
/*
* Not an authoritative answer. Query again
* using the NS address in the 2nd record.
*/
if (rdrcount-- == 0) {
break;
}
if (error)
break;
if (error)
break;
continue;
}
if (rqp->nr_rpancount == 0) {
break;
}
if (error)
break;
len = sizeof (struct sockaddr_in);
return (ENOMEM);
/*
* Solaris sockaddr_in doesn't a sin_len field.
* dest->sin_len = len;
*/
break;
}
return (error);
}
/*
* NB: system, workgroup are both NB_NAMELEN
*/
int
{
char nrtype;
unsigned char nrcount;
if (error)
return (error);
rqp->nr_nmflags = 0;
if (error) {
return (error);
}
/*
* Darwin had a loop here, allowing redirect, etc.
* but we only handle point-to-point for node status.
*/
if (error)
goto out;
if (rqp->nr_rpancount == 0) {
goto out;
}
if (error)
goto out;
/* Compiler didn't like cast on lvalue++ */
/* LINTED */
/* Terminate the string: */
/* Strip off trailing spaces */
if (*cp != (char)0x20)
break;
*cp = (char)0;
}
DPRINT(" %s[%02x] Flags 0x%x",
if (!foundgroup ||
}
} else {
/*
* Track at least ONE name, in case
* no server name is found
*/
}
/*
* Keep the first NBT_SERVER name.
*/
foundserver = 1;
}
}
out:
return (error);
}
int
{
int error;
if (trnid == 0)
return (ENOMEM);
if (error) {
return (error);
}
return (0);
}
void
{
return;
}
/*
* Extract resource record from the packet. Assume that there is only
* one mbuf.
*/
int
{
if (len < 1)
return (NBERROR(NBERR_INVALIDRESPONSE));
if (error)
return (error);
return (error);
}
int
{
int error;
if (error)
return (error);
/*
* When looked into the ethereal trace, 'nmblookup' command sets this
* flag. We will also set.
*/
if (rqp->nr_qdcount) {
return (EINVAL);
}
if (error)
return (error);
if (error)
return (error);
return (0);
}
static int
{
int n, len;
if (n == -1)
return (-1);
if (n == 0)
return (ETIMEDOUT);
return (ETIMEDOUT);
if (n < 0)
return (errno);
return (0);
}
static int
{
if (s < 0)
return (errno);
sizeof (opt)) < 0)
return (errno);
}
if (is_system_labeled())
sizeof (opt));
/* locaddr.sin_len = sizeof (locaddr); */
return (errno);
return (0);
}
static int
{
int rc;
if (ina == INADDR_BROADCAST) {
/* Turn on the broadcast bit. */
/*LINTED*/
}
if (ina == INADDR_BROADCAST) {
/* Turn the broadcast bit back off. */
}
if (rc < 0)
return (errno);
return (0);
}
int
{
if (error)
return (error);
/*
* Minor hack: If nr_dest is set, send there only.
* Used by _getnodestatus, _resolvname redirects.
*/
if (error) {
"nbns error %d sending to %s"),
}
goto do_recv;
}
if (error) {
"nbns error %d sending to wins1"),
0, error);
}
}
if (error) {
"nbns error %d sending to wins2"),
0, error);
}
}
/*
* If broadcast is enabled, start broadcasting
* only after wins servers fail to respond, or
* immediately if no WINS servers configured.
*/
if (error) {
"nbns error %d sending broadcast"),
0, error);
}
}
/*
* Wait for responses from ANY of the above.
*/
continue;
if (error) {
"nbns recv error %d"),
0, error);
return (error);
}
return (NBERROR(NBERR_INVALIDRESPONSE));
return (NBERROR(NBERR_INVALIDRESPONSE));
break;
}
return (NBERROR(NBERR_HOSTNOTFOUND));
if (rqp->nr_rprcode)
return (0);
}