nb_net.c revision 87867
1169695Skan/*
2169695Skan * Copyright (c) 2000, Boris Popov
3169695Skan * All rights reserved.
4169695Skan *
5169695Skan * Redistribution and use in source and binary forms, with or without
6169695Skan * modification, are permitted provided that the following conditions
7169695Skan * are met:
8169695Skan * 1. Redistributions of source code must retain the above copyright
9169695Skan *    notice, this list of conditions and the following disclaimer.
10169695Skan * 2. Redistributions in binary form must reproduce the above copyright
11169695Skan *    notice, this list of conditions and the following disclaimer in the
12169695Skan *    documentation and/or other materials provided with the distribution.
13169695Skan * 3. All advertising materials mentioning features or use of this software
14169695Skan *    must display the following acknowledgement:
15169695Skan *    This product includes software developed by Boris Popov.
16169695Skan * 4. Neither the name of the author nor the names of any co-contributors
17169695Skan *    may be used to endorse or promote products derived from this software
18169695Skan *    without specific prior written permission.
19169695Skan *
20169695Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21169695Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22169695Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23169695Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24169695Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25169695Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26169695Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27169695Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28169695Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29169695Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30169695Skan * SUCH DAMAGE.
31169695Skan *
32169695Skan * $Id: nb_net.c,v 1.4 2001/02/16 02:46:12 bp Exp $
33169695Skan */
34169695Skan#include <sys/param.h>
35169695Skan#include <sys/socket.h>
36169695Skan#include <sys/ioctl.h>
37169695Skan
38169695Skan#include <net/if.h>
39169695Skan
40169695Skan#include <ctype.h>
41169695Skan#include <netdb.h>
42169695Skan#include <err.h>
43169695Skan#include <errno.h>
44169695Skan#include <stdlib.h>
45169695Skan#include <string.h>
46169695Skan#include <stdio.h>
47169695Skan#include <unistd.h>
48169695Skan
49169695Skan#include <netsmb/netbios.h>
50169695Skan#include <netsmb/smb_lib.h>
51169695Skan#include <netsmb/nb_lib.h>
52169695Skan
53169695Skanint
54169695Skannb_getlocalname(char *name)
55169695Skan{
56169695Skan	char buf[1024], *cp;
57169695Skan
58169695Skan	if (gethostname(buf, sizeof(buf)) != 0)
59169695Skan		return errno;
60169695Skan	cp = strchr(buf, '.');
61169695Skan	if (cp)
62169695Skan		*cp = 0;
63169695Skan	strcpy(name, buf);
64169695Skan	return 0;
65169695Skan}
66169695Skan
67169695Skanint
68169695Skannb_resolvehost_in(const char *name, struct sockaddr **dest)
69169695Skan{
70169695Skan	struct hostent* h;
71169695Skan	struct sockaddr_in *sinp;
72169695Skan	int len;
73169695Skan
74169695Skan	h = gethostbyname(name);
75169695Skan	if (!h) {
76169695Skan		warnx("can't get server address `%s': ", name);
77169695Skan		herror(NULL);
78169695Skan		return ENETDOWN;
79169695Skan	}
80169695Skan	if (h->h_addrtype != AF_INET) {
81169695Skan		warnx("address for `%s' is not in the AF_INET family", name);
82169695Skan		return EAFNOSUPPORT;
83169695Skan	}
84169695Skan	if (h->h_length != 4) {
85169695Skan		warnx("address for `%s' has invalid length", name);
86169695Skan		return EAFNOSUPPORT;
87169695Skan	}
88169695Skan	len = sizeof(struct sockaddr_in);
89169695Skan	sinp = malloc(len);
90169695Skan	if (sinp == NULL)
91169695Skan		return ENOMEM;
92169695Skan	bzero(sinp, len);
93169695Skan	sinp->sin_len = len;
94169695Skan	sinp->sin_family = h->h_addrtype;
95169695Skan	memcpy(&sinp->sin_addr.s_addr, h->h_addr, 4);
96169695Skan	sinp->sin_port = htons(SMB_TCP_PORT);
97169695Skan	*dest = (struct sockaddr*)sinp;
98169695Skan	return 0;
99169695Skan}
100169695Skan
101169695Skanint
102169695Skannb_enum_if(struct nb_ifdesc **iflist, int maxif)
103169695Skan{
104169695Skan	struct ifconf ifc;
105169695Skan	struct ifreq *ifrqp;
106169695Skan	struct nb_ifdesc *ifd;
107169695Skan	struct in_addr iaddr, imask;
108169695Skan	char *ifrdata, *iname;
109169695Skan	int s, rdlen, ifcnt, error, iflags, i;
110169695Skan
111169695Skan	*iflist = NULL;
112169695Skan	s = socket(AF_INET, SOCK_DGRAM, 0);
113169695Skan	if (s == -1)
114169695Skan		return errno;
115169695Skan
116169695Skan	rdlen = maxif * sizeof(struct ifreq);
117169695Skan	ifrdata = malloc(rdlen);
118169695Skan	if (ifrdata == NULL) {
119169695Skan		error = ENOMEM;
120169695Skan		goto bad;
121169695Skan	}
122169695Skan	ifc.ifc_len = rdlen;
123169695Skan	ifc.ifc_buf = ifrdata;
124169695Skan	if (ioctl(s, SIOCGIFCONF, &ifc) != 0) {
125169695Skan		error = errno;
126169695Skan		goto bad;
127169695Skan	}
128169695Skan	ifrqp = ifc.ifc_req;
129169695Skan	ifcnt = ifc.ifc_len / sizeof(struct ifreq);
130169695Skan	error = 0;
131169695Skan	for (i = 0; i < ifcnt; i++, ifrqp++) {
132169695Skan		if (ioctl(s, SIOCGIFFLAGS, ifrqp) != 0)
133169695Skan			continue;
134169695Skan		iflags = ifrqp->ifr_flags;
135169695Skan		if ((iflags & IFF_UP) == 0 || (iflags & IFF_BROADCAST) == 0)
136169695Skan			continue;
137169695Skan
138169695Skan		if (ioctl(s, SIOCGIFADDR, ifrqp) != 0 ||
139169695Skan		    ifrqp->ifr_addr.sa_family != AF_INET)
140169695Skan			continue;
141169695Skan		iname = ifrqp->ifr_name;
142169695Skan		if (strlen(iname) >= sizeof(ifd->id_name))
143169695Skan			continue;
144169695Skan		iaddr = (*(struct sockaddr_in *)&ifrqp->ifr_addr).sin_addr;
145169695Skan
146169695Skan		if (ioctl(s, SIOCGIFNETMASK, ifrqp) != 0)
147169695Skan			continue;
148169695Skan		imask = ((struct sockaddr_in *)&ifrqp->ifr_addr)->sin_addr;
149169695Skan
150169695Skan		ifd = malloc(sizeof(struct nb_ifdesc));
151169695Skan		if (ifd == NULL)
152169695Skan			return ENOMEM;
153169695Skan		bzero(ifd, sizeof(struct nb_ifdesc));
154169695Skan		strcpy(ifd->id_name, iname);
155169695Skan		ifd->id_flags = iflags;
156169695Skan		ifd->id_addr = iaddr;
157169695Skan		ifd->id_mask = imask;
158169695Skan		ifd->id_next = *iflist;
159169695Skan		*iflist = ifd;
160169695Skan	}
161169695Skanbad:
162169695Skan	free(ifrdata);
163169695Skan	close(s);
164169695Skan	return error;
165169695Skan}
166169695Skan
167169695Skan/*ARGSUSED*/
168169695Skan/*int
169169695Skannbns_resolvename(const char *name, struct sockaddr **dest)
170169695Skan{
171169695Skan	printf("NetBIOS name resolver is not included in this distribution.\n");
172169695Skan	printf("Please use '-I' option to specify an IP address of server.\n");
173169695Skan	return EHOSTUNREACH;
174169695Skan}*/
175169695Skan/*
176169695Skanint
177169695Skannb_hostlookup(struct nb_name *np, const char *server, const char *hint,
178169695Skan	struct sockaddr_nb **dst)
179169695Skan{
180169695Skan	struct sockaddr_nb *snb;
181169695Skan	int error;
182169695Skan
183169695Skan	error = nb_sockaddr(NULL, np, &snb);
184169695Skan	if (error)
185169695Skan		return error;
186169695Skan	do {
187169695Skan		if (hint) {
188169695Skan			error = nb_resolvehost_in(host, snb);
189169695Skan			if (error)
190169695Skan				break;
191169695Skan		} else {
192169695Skan			error = nb_resolvename(server);
193169695Skan		}
194169695Skan	} while(0);
195169695Skan	if (!error) {
196169695Skan		*dst = snb;
197169695Skan	} else
198169695Skan		nb_snbfree(snb);
199169695Skan	return error;
200169695Skan}
201169695Skan*/