nb_net.c revision 125130
1219820Sjeff/*
2219820Sjeff * Copyright (c) 2000, Boris Popov
3219820Sjeff * All rights reserved.
4219820Sjeff *
5219820Sjeff * Redistribution and use in source and binary forms, with or without
6219820Sjeff * modification, are permitted provided that the following conditions
7219820Sjeff * are met:
8219820Sjeff * 1. Redistributions of source code must retain the above copyright
9219820Sjeff *    notice, this list of conditions and the following disclaimer.
10219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright
11219820Sjeff *    notice, this list of conditions and the following disclaimer in the
12219820Sjeff *    documentation and/or other materials provided with the distribution.
13219820Sjeff * 3. All advertising materials mentioning features or use of this software
14219820Sjeff *    must display the following acknowledgement:
15219820Sjeff *    This product includes software developed by Boris Popov.
16219820Sjeff * 4. Neither the name of the author nor the names of any co-contributors
17219820Sjeff *    may be used to endorse or promote products derived from this software
18219820Sjeff *    without specific prior written permission.
19219820Sjeff *
20219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21219820Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23219820Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24219820Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25219820Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26219820Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28219820Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29219820Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30219820Sjeff * SUCH DAMAGE.
31219820Sjeff *
32219820Sjeff * $Id: nb_net.c,v 1.4 2001/02/16 02:46:12 bp Exp $
33219820Sjeff * $FreeBSD: head/contrib/smbfs/lib/smb/nb_net.c 125130 2004-01-28 05:55:13Z tjr $
34219820Sjeff */
35219820Sjeff#include <sys/param.h>
36219820Sjeff#include <sys/socket.h>
37219820Sjeff#include <sys/ioctl.h>
38219820Sjeff
39219820Sjeff#include <net/if.h>
40219820Sjeff
41219820Sjeff#include <ctype.h>
42219820Sjeff#include <netdb.h>
43219820Sjeff#include <err.h>
44219820Sjeff#include <errno.h>
45219820Sjeff#include <stdlib.h>
46219820Sjeff#include <string.h>
47219820Sjeff#include <stdio.h>
48219820Sjeff#include <unistd.h>
49219820Sjeff
50219820Sjeff#include <netsmb/netbios.h>
51219820Sjeff#include <netsmb/smb_lib.h>
52219820Sjeff#include <netsmb/nb_lib.h>
53219820Sjeff
54219820Sjeffint
55219820Sjeffnb_getlocalname(char *name)
56219820Sjeff{
57219820Sjeff	char buf[1024], *cp;
58219820Sjeff
59219820Sjeff	if (gethostname(buf, sizeof(buf)) != 0)
60219820Sjeff		return errno;
61219820Sjeff	cp = strchr(buf, '.');
62219820Sjeff	if (cp)
63219820Sjeff		*cp = 0;
64219820Sjeff	strcpy(name, buf);
65219820Sjeff	return 0;
66219820Sjeff}
67219820Sjeff
68219820Sjeffint
69219820Sjeffnb_resolvehost_in(const char *name, struct sockaddr **dest)
70219820Sjeff{
71219820Sjeff	struct hostent* h;
72219820Sjeff	struct sockaddr_in *sinp;
73219820Sjeff	int len;
74219820Sjeff
75219820Sjeff	h = gethostbyname(name);
76219820Sjeff	if (!h) {
77219820Sjeff		warnx("can't get server address `%s': ", name);
78219820Sjeff		herror(NULL);
79219820Sjeff		return ENETDOWN;
80219820Sjeff	}
81219820Sjeff	if (h->h_addrtype != AF_INET) {
82219820Sjeff		warnx("address for `%s' is not in the AF_INET family", name);
83219820Sjeff		return EAFNOSUPPORT;
84219820Sjeff	}
85219820Sjeff	if (h->h_length != 4) {
86219820Sjeff		warnx("address for `%s' has invalid length", name);
87219820Sjeff		return EAFNOSUPPORT;
88219820Sjeff	}
89219820Sjeff	len = sizeof(struct sockaddr_in);
90219820Sjeff	sinp = malloc(len);
91219820Sjeff	if (sinp == NULL)
92219820Sjeff		return ENOMEM;
93219820Sjeff	bzero(sinp, len);
94219820Sjeff	sinp->sin_len = len;
95219820Sjeff	sinp->sin_family = h->h_addrtype;
96219820Sjeff	memcpy(&sinp->sin_addr.s_addr, h->h_addr, 4);
97219820Sjeff	sinp->sin_port = htons(SMB_TCP_PORT);
98219820Sjeff	*dest = (struct sockaddr*)sinp;
99219820Sjeff	return 0;
100219820Sjeff}
101219820Sjeff
102219820Sjeffint
103219820Sjeffnb_enum_if(struct nb_ifdesc **iflist, int maxif)
104219820Sjeff{
105219820Sjeff	struct ifconf ifc;
106219820Sjeff	struct ifreq *ifrqp;
107219820Sjeff	struct nb_ifdesc *ifd;
108219820Sjeff	struct in_addr iaddr, imask;
109219820Sjeff	char *ifrdata, *iname;
110219820Sjeff	int s, rdlen, ifcnt, error, iflags, i;
111219820Sjeff	size_t ifrlen;
112219820Sjeff
113219820Sjeff	*iflist = NULL;
114219820Sjeff	s = socket(AF_INET, SOCK_DGRAM, 0);
115219820Sjeff	if (s == -1)
116219820Sjeff		return errno;
117219820Sjeff
118219820Sjeff	rdlen = maxif * sizeof(struct ifreq);
119219820Sjeff	ifrdata = malloc(rdlen);
120219820Sjeff	if (ifrdata == NULL) {
121219820Sjeff		error = ENOMEM;
122219820Sjeff		goto bad;
123219820Sjeff	}
124219820Sjeff	ifc.ifc_len = rdlen;
125219820Sjeff	ifc.ifc_buf = ifrdata;
126219820Sjeff	if (ioctl(s, SIOCGIFCONF, &ifc) != 0) {
127219820Sjeff		error = errno;
128219820Sjeff		goto bad;
129219820Sjeff	}
130219820Sjeff	ifrqp = ifc.ifc_req;
131219820Sjeff	ifcnt = ifc.ifc_len / sizeof(struct ifreq);
132219820Sjeff	error = 0;
133219820Sjeff	for (i = 0; i < ifcnt; i++) {
134219820Sjeff		ifrlen = sizeof(struct ifreq);
135219820Sjeff		if (ifrqp->ifr_addr.sa_len > sizeof(struct sockaddr))
136219820Sjeff			ifrlen += ifrqp->ifr_addr.sa_len
137219820Sjeff				- sizeof(struct sockaddr);
138219820Sjeff
139219820Sjeff		if (ifrqp->ifr_addr.sa_family != AF_INET)
140219820Sjeff			goto next;
141219820Sjeff		iname = ifrqp->ifr_name;
142219820Sjeff		if (strlen(iname) >= sizeof(ifd->id_name))
143219820Sjeff			goto next;
144219820Sjeff
145219820Sjeff		iaddr = (*(struct sockaddr_in *)&ifrqp->ifr_addr).sin_addr;
146219820Sjeff
147219820Sjeff		if (ioctl(s, SIOCGIFNETMASK, ifrqp) != 0)
148219820Sjeff			goto next;
149219820Sjeff		imask = ((struct sockaddr_in *)&ifrqp->ifr_addr)->sin_addr;
150219820Sjeff
151219820Sjeff		if (ioctl(s, SIOCGIFFLAGS, ifrqp) != 0)
152219820Sjeff			goto next;
153219820Sjeff		iflags = ifrqp->ifr_flags;
154219820Sjeff		if ((iflags & IFF_UP) == 0 || (iflags & IFF_BROADCAST) == 0)
155219820Sjeff			goto next;
156219820Sjeff
157219820Sjeff		ifd = malloc(sizeof(struct nb_ifdesc));
158219820Sjeff		if (ifd == NULL)
159219820Sjeff			return ENOMEM;
160219820Sjeff		bzero(ifd, sizeof(struct nb_ifdesc));
161219820Sjeff		strcpy(ifd->id_name, iname);
162219820Sjeff		ifd->id_flags = iflags;
163219820Sjeff		ifd->id_addr = iaddr;
164219820Sjeff		ifd->id_mask = imask;
165219820Sjeff		ifd->id_next = *iflist;
166219820Sjeff		*iflist = ifd;
167219820Sjeff
168219820Sjeffnext:
169219820Sjeff		ifrqp = (struct ifreq *)((caddr_t)ifrqp + ifrlen);
170219820Sjeff	}
171219820Sjeffbad:
172219820Sjeff	free(ifrdata);
173219820Sjeff	close(s);
174219820Sjeff	return error;
175219820Sjeff}
176219820Sjeff
177219820Sjeff/*ARGSUSED*/
178219820Sjeff/*int
179219820Sjeffnbns_resolvename(const char *name, struct sockaddr **dest)
180219820Sjeff{
181219820Sjeff	printf("NetBIOS name resolver is not included in this distribution.\n");
182219820Sjeff	printf("Please use '-I' option to specify an IP address of server.\n");
183219820Sjeff	return EHOSTUNREACH;
184219820Sjeff}*/
185219820Sjeff/*
186219820Sjeffint
187219820Sjeffnb_hostlookup(struct nb_name *np, const char *server, const char *hint,
188219820Sjeff	struct sockaddr_nb **dst)
189219820Sjeff{
190219820Sjeff	struct sockaddr_nb *snb;
191219820Sjeff	int error;
192219820Sjeff
193219820Sjeff	error = nb_sockaddr(NULL, np, &snb);
194219820Sjeff	if (error)
195219820Sjeff		return error;
196219820Sjeff	do {
197219820Sjeff		if (hint) {
198219820Sjeff			error = nb_resolvehost_in(host, snb);
199219820Sjeff			if (error)
200219820Sjeff				break;
201219820Sjeff		} else {
202219820Sjeff			error = nb_resolvename(server);
203219820Sjeff		}
204219820Sjeff	} while(0);
205219820Sjeff	if (!error) {
206219820Sjeff		*dst = snb;
207219820Sjeff	} else
208219820Sjeff		nb_snbfree(snb);
209219820Sjeff	return error;
210219820Sjeff}
211219820Sjeff*/
212219820Sjeff