187866Ssheldonh/*
287866Ssheldonh * Copyright (c) 2000, Boris Popov
387866Ssheldonh * All rights reserved.
487866Ssheldonh *
587866Ssheldonh * Redistribution and use in source and binary forms, with or without
687866Ssheldonh * modification, are permitted provided that the following conditions
787866Ssheldonh * are met:
887866Ssheldonh * 1. Redistributions of source code must retain the above copyright
987866Ssheldonh *    notice, this list of conditions and the following disclaimer.
1087866Ssheldonh * 2. Redistributions in binary form must reproduce the above copyright
1187866Ssheldonh *    notice, this list of conditions and the following disclaimer in the
1287866Ssheldonh *    documentation and/or other materials provided with the distribution.
1387866Ssheldonh * 3. All advertising materials mentioning features or use of this software
1487866Ssheldonh *    must display the following acknowledgement:
1587866Ssheldonh *    This product includes software developed by Boris Popov.
1687866Ssheldonh * 4. Neither the name of the author nor the names of any co-contributors
1787866Ssheldonh *    may be used to endorse or promote products derived from this software
1887866Ssheldonh *    without specific prior written permission.
1987866Ssheldonh *
2087866Ssheldonh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2187866Ssheldonh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2287866Ssheldonh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2387866Ssheldonh * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2487866Ssheldonh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2587866Ssheldonh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2687866Ssheldonh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2787866Ssheldonh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2887866Ssheldonh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2987866Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3087866Ssheldonh * SUCH DAMAGE.
3187866Ssheldonh *
3287866Ssheldonh * $Id: nb_net.c,v 1.4 2001/02/16 02:46:12 bp Exp $
33125130Stjr * $FreeBSD$
3487866Ssheldonh */
3587866Ssheldonh#include <sys/param.h>
3687866Ssheldonh#include <sys/socket.h>
3787866Ssheldonh
3887866Ssheldonh#include <net/if.h>
3987866Ssheldonh
4087866Ssheldonh#include <ctype.h>
4187866Ssheldonh#include <netdb.h>
4287866Ssheldonh#include <err.h>
4387866Ssheldonh#include <errno.h>
4487866Ssheldonh#include <stdlib.h>
4587866Ssheldonh#include <string.h>
4687866Ssheldonh#include <stdio.h>
4787866Ssheldonh#include <unistd.h>
48126269Stjr#include <ifaddrs.h>
4987866Ssheldonh
5087866Ssheldonh#include <netsmb/netbios.h>
5187866Ssheldonh#include <netsmb/smb_lib.h>
5287866Ssheldonh#include <netsmb/nb_lib.h>
5387866Ssheldonh
5487866Ssheldonhint
5587866Ssheldonhnb_getlocalname(char *name)
5687866Ssheldonh{
5787866Ssheldonh	char buf[1024], *cp;
5887866Ssheldonh
5987866Ssheldonh	if (gethostname(buf, sizeof(buf)) != 0)
6087866Ssheldonh		return errno;
6187866Ssheldonh	cp = strchr(buf, '.');
6287866Ssheldonh	if (cp)
6387866Ssheldonh		*cp = 0;
6487866Ssheldonh	strcpy(name, buf);
6587866Ssheldonh	return 0;
6687866Ssheldonh}
6787866Ssheldonh
6887866Ssheldonhint
69150802Sbpnb_resolvehost_in(const char *name, struct sockaddr **dest, long smbtcpport)
7087866Ssheldonh{
7187866Ssheldonh	struct hostent* h;
7287866Ssheldonh	struct sockaddr_in *sinp;
7387866Ssheldonh	int len;
7487866Ssheldonh
7587866Ssheldonh	h = gethostbyname(name);
7687866Ssheldonh	if (!h) {
7787866Ssheldonh		warnx("can't get server address `%s': ", name);
7887866Ssheldonh		herror(NULL);
7987866Ssheldonh		return ENETDOWN;
8087866Ssheldonh	}
8187866Ssheldonh	if (h->h_addrtype != AF_INET) {
8287866Ssheldonh		warnx("address for `%s' is not in the AF_INET family", name);
8387866Ssheldonh		return EAFNOSUPPORT;
8487866Ssheldonh	}
8587866Ssheldonh	if (h->h_length != 4) {
8687866Ssheldonh		warnx("address for `%s' has invalid length", name);
8787866Ssheldonh		return EAFNOSUPPORT;
8887866Ssheldonh	}
8987866Ssheldonh	len = sizeof(struct sockaddr_in);
9087866Ssheldonh	sinp = malloc(len);
9187866Ssheldonh	if (sinp == NULL)
9287866Ssheldonh		return ENOMEM;
9387866Ssheldonh	bzero(sinp, len);
9487866Ssheldonh	sinp->sin_len = len;
9587866Ssheldonh	sinp->sin_family = h->h_addrtype;
9687866Ssheldonh	memcpy(&sinp->sin_addr.s_addr, h->h_addr, 4);
97150802Sbp	sinp->sin_port = htons(smbtcpport);
9887866Ssheldonh	*dest = (struct sockaddr*)sinp;
9987866Ssheldonh	return 0;
10087866Ssheldonh}
10187866Ssheldonh
10287866Ssheldonhint
10387866Ssheldonhnb_enum_if(struct nb_ifdesc **iflist, int maxif)
10487866Ssheldonh{
10587866Ssheldonh	struct nb_ifdesc *ifd;
106126269Stjr	struct ifaddrs *ifp, *p;
107126269Stjr	int i;
10887866Ssheldonh
109126269Stjr	if (getifaddrs(&ifp) < 0)
11087866Ssheldonh		return errno;
11187866Ssheldonh
112126269Stjr	*iflist = NULL;
113126269Stjr	i = 0;
114126269Stjr	for (p = ifp; p; p = p->ifa_next) {
11587866Ssheldonh
116126269Stjr		if (i >= maxif)
117126269Stjr			break;
118125130Stjr
119126269Stjr		if ((p->ifa_addr->sa_family != AF_INET) ||
120126269Stjr		    ((p->ifa_flags & (IFF_UP|IFF_BROADCAST))
121126269Stjr		     != (IFF_UP|IFF_BROADCAST)))
122126269Stjr			continue;
123126269Stjr		if (strlen(p->ifa_name) >= sizeof(ifd->id_name))
124126269Stjr			continue;
12587866Ssheldonh
12687866Ssheldonh		ifd = malloc(sizeof(struct nb_ifdesc));
127126269Stjr		if (ifd == NULL) {
128126269Stjr			freeifaddrs(ifp);
129126269Stjr			/* XXX should free stuff already in *iflist */
13087866Ssheldonh			return ENOMEM;
131126269Stjr		}
13287866Ssheldonh		bzero(ifd, sizeof(struct nb_ifdesc));
133126269Stjr		strcpy(ifd->id_name, p->ifa_name);
134126269Stjr		ifd->id_flags = p->ifa_flags;
135126269Stjr		ifd->id_addr = ((struct sockaddr_in *)p->ifa_addr)->sin_addr;
136126269Stjr		ifd->id_mask = ((struct sockaddr_in *)p->ifa_netmask)->sin_addr;
13787866Ssheldonh		ifd->id_next = *iflist;
13887866Ssheldonh		*iflist = ifd;
139126269Stjr		i++;
14087866Ssheldonh	}
14187866Ssheldonh
142126269Stjr	freeifaddrs(ifp);
143126269Stjr	return 0;
144126269Stjr}
145126269Stjr
14687866Ssheldonh/*ARGSUSED*/
14787866Ssheldonh/*int
14887866Ssheldonhnbns_resolvename(const char *name, struct sockaddr **dest)
14987866Ssheldonh{
15087866Ssheldonh	printf("NetBIOS name resolver is not included in this distribution.\n");
15187866Ssheldonh	printf("Please use '-I' option to specify an IP address of server.\n");
15287866Ssheldonh	return EHOSTUNREACH;
15387866Ssheldonh}*/
15487866Ssheldonh/*
15587866Ssheldonhint
15687866Ssheldonhnb_hostlookup(struct nb_name *np, const char *server, const char *hint,
15787866Ssheldonh	struct sockaddr_nb **dst)
15887866Ssheldonh{
15987866Ssheldonh	struct sockaddr_nb *snb;
16087866Ssheldonh	int error;
16187866Ssheldonh
16287866Ssheldonh	error = nb_sockaddr(NULL, np, &snb);
16387866Ssheldonh	if (error)
16487866Ssheldonh		return error;
16587866Ssheldonh	do {
16687866Ssheldonh		if (hint) {
167150802Sbp			error = nb_resolvehost_in(host, snb, SMB_TCP_PORT);
16887866Ssheldonh			if (error)
16987866Ssheldonh				break;
17087866Ssheldonh		} else {
17187866Ssheldonh			error = nb_resolvename(server);
17287866Ssheldonh		}
17387866Ssheldonh	} while(0);
17487866Ssheldonh	if (!error) {
17587866Ssheldonh		*dst = snb;
17687866Ssheldonh	} else
17787866Ssheldonh		nb_snbfree(snb);
17887866Ssheldonh	return error;
17987866Ssheldonh}
180125130Stjr*/
181