xref: /titanic_53/usr/src/lib/libsmbfs/smb/getaddr.c (revision 613a2f6ba31e891e3d947a356daf5e563d43c1ce)
1*613a2f6bSGordon Ross /*
2*613a2f6bSGordon Ross  * CDDL HEADER START
3*613a2f6bSGordon Ross  *
4*613a2f6bSGordon Ross  * The contents of this file are subject to the terms of the
5*613a2f6bSGordon Ross  * Common Development and Distribution License (the "License").
6*613a2f6bSGordon Ross  * You may not use this file except in compliance with the License.
7*613a2f6bSGordon Ross  *
8*613a2f6bSGordon Ross  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*613a2f6bSGordon Ross  * or http://www.opensolaris.org/os/licensing.
10*613a2f6bSGordon Ross  * See the License for the specific language governing permissions
11*613a2f6bSGordon Ross  * and limitations under the License.
12*613a2f6bSGordon Ross  *
13*613a2f6bSGordon Ross  * When distributing Covered Code, include this CDDL HEADER in each
14*613a2f6bSGordon Ross  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*613a2f6bSGordon Ross  * If applicable, add the following below this CDDL HEADER, with the
16*613a2f6bSGordon Ross  * fields enclosed by brackets "[]" replaced with your own identifying
17*613a2f6bSGordon Ross  * information: Portions Copyright [yyyy] [name of copyright owner]
18*613a2f6bSGordon Ross  *
19*613a2f6bSGordon Ross  * CDDL HEADER END
20*613a2f6bSGordon Ross  */
21*613a2f6bSGordon Ross 
22*613a2f6bSGordon Ross /*
23*613a2f6bSGordon Ross  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*613a2f6bSGordon Ross  * Use is subject to license terms.
25*613a2f6bSGordon Ross  */
26*613a2f6bSGordon Ross 
27*613a2f6bSGordon Ross /*
28*613a2f6bSGordon Ross  * Functions to get list of addresses (TCP and/or NetBIOS)
29*613a2f6bSGordon Ross  */
30*613a2f6bSGordon Ross 
31*613a2f6bSGordon Ross #include <errno.h>
32*613a2f6bSGordon Ross #include <stdio.h>
33*613a2f6bSGordon Ross #include <stdlib.h>
34*613a2f6bSGordon Ross #include <string.h>
35*613a2f6bSGordon Ross #include <strings.h>
36*613a2f6bSGordon Ross #include <unistd.h>
37*613a2f6bSGordon Ross #include <netdb.h>
38*613a2f6bSGordon Ross #include <libintl.h>
39*613a2f6bSGordon Ross #include <xti.h>
40*613a2f6bSGordon Ross #include <assert.h>
41*613a2f6bSGordon Ross 
42*613a2f6bSGordon Ross #include <sys/types.h>
43*613a2f6bSGordon Ross #include <sys/time.h>
44*613a2f6bSGordon Ross #include <sys/byteorder.h>
45*613a2f6bSGordon Ross #include <sys/socket.h>
46*613a2f6bSGordon Ross #include <sys/fcntl.h>
47*613a2f6bSGordon Ross 
48*613a2f6bSGordon Ross #include <netinet/in.h>
49*613a2f6bSGordon Ross #include <netinet/tcp.h>
50*613a2f6bSGordon Ross #include <arpa/inet.h>
51*613a2f6bSGordon Ross 
52*613a2f6bSGordon Ross #include <netsmb/smb.h>
53*613a2f6bSGordon Ross #include <netsmb/smb_lib.h>
54*613a2f6bSGordon Ross #include <netsmb/netbios.h>
55*613a2f6bSGordon Ross #include <netsmb/nb_lib.h>
56*613a2f6bSGordon Ross #include <netsmb/smb_dev.h>
57*613a2f6bSGordon Ross 
58*613a2f6bSGordon Ross #include "charsets.h"
59*613a2f6bSGordon Ross #include "private.h"
60*613a2f6bSGordon Ross 
61*613a2f6bSGordon Ross void
62*613a2f6bSGordon Ross dump_addrinfo(struct addrinfo *ai)
63*613a2f6bSGordon Ross {
64*613a2f6bSGordon Ross 	int i;
65*613a2f6bSGordon Ross 
66*613a2f6bSGordon Ross 	if (ai == NULL) {
67*613a2f6bSGordon Ross 		printf("ai==NULL\n");
68*613a2f6bSGordon Ross 		return;
69*613a2f6bSGordon Ross 	}
70*613a2f6bSGordon Ross 
71*613a2f6bSGordon Ross 	for (i = 0; ai; i++, ai = ai->ai_next) {
72*613a2f6bSGordon Ross 		printf("ai[%d]: af=%d, len=%d", i,
73*613a2f6bSGordon Ross 		    ai->ai_family, ai->ai_addrlen);
74*613a2f6bSGordon Ross 		dump_sockaddr(ai->ai_addr);
75*613a2f6bSGordon Ross 		if (ai->ai_canonname) {
76*613a2f6bSGordon Ross 			printf("ai[%d]: cname=\"%s\"\n",
77*613a2f6bSGordon Ross 			    i, ai->ai_canonname);
78*613a2f6bSGordon Ross 		}
79*613a2f6bSGordon Ross 	}
80*613a2f6bSGordon Ross }
81*613a2f6bSGordon Ross 
82*613a2f6bSGordon Ross void
83*613a2f6bSGordon Ross dump_sockaddr(struct sockaddr *sa)
84*613a2f6bSGordon Ross {
85*613a2f6bSGordon Ross 	char paddrbuf[INET6_ADDRSTRLEN];
86*613a2f6bSGordon Ross 	struct sockaddr_in *sin;
87*613a2f6bSGordon Ross 	struct sockaddr_in6 *sin6;
88*613a2f6bSGordon Ross 	int af = sa->sa_family;
89*613a2f6bSGordon Ross 	const char *ip;
90*613a2f6bSGordon Ross 
91*613a2f6bSGordon Ross 	printf(" saf=%d,", af);
92*613a2f6bSGordon Ross 	switch (af) {
93*613a2f6bSGordon Ross 	case AF_NETBIOS: /* see nbns_rq.c */
94*613a2f6bSGordon Ross 	case AF_INET:
95*613a2f6bSGordon Ross 		sin = (void *)sa;
96*613a2f6bSGordon Ross 		ip = inet_ntop(AF_INET, &sin->sin_addr,
97*613a2f6bSGordon Ross 		    paddrbuf, sizeof (paddrbuf));
98*613a2f6bSGordon Ross 		break;
99*613a2f6bSGordon Ross 	case AF_INET6:
100*613a2f6bSGordon Ross 		sin6 = (void *)sa;
101*613a2f6bSGordon Ross 		ip = inet_ntop(AF_INET6, &sin6->sin6_addr,
102*613a2f6bSGordon Ross 		    paddrbuf, sizeof (paddrbuf));
103*613a2f6bSGordon Ross 		break;
104*613a2f6bSGordon Ross 	default:
105*613a2f6bSGordon Ross 		ip = "?";
106*613a2f6bSGordon Ross 		break;
107*613a2f6bSGordon Ross 	}
108*613a2f6bSGordon Ross 	printf(" IP=%s\n", ip);
109*613a2f6bSGordon Ross }
110*613a2f6bSGordon Ross 
111*613a2f6bSGordon Ross 
112*613a2f6bSGordon Ross /*
113*613a2f6bSGordon Ross  * SMB client name resolution - normal, and/or NetBIOS.
114*613a2f6bSGordon Ross  * Returns an EAI_xxx error number like getaddrinfo(3)
115*613a2f6bSGordon Ross  */
116*613a2f6bSGordon Ross int
117*613a2f6bSGordon Ross smb_ctx_getaddr(struct smb_ctx *ctx)
118*613a2f6bSGordon Ross {
119*613a2f6bSGordon Ross 	struct nb_ctx	*nbc = ctx->ct_nb;
120*613a2f6bSGordon Ross 	struct addrinfo hints, *res;
121*613a2f6bSGordon Ross 	char *srvaddr_str;
122*613a2f6bSGordon Ross 	int gaierr, gaierr2;
123*613a2f6bSGordon Ross 
124*613a2f6bSGordon Ross 	if (ctx->ct_fullserver == NULL || ctx->ct_fullserver[0] == '\0')
125*613a2f6bSGordon Ross 		return (EAI_NONAME);
126*613a2f6bSGordon Ross 
127*613a2f6bSGordon Ross 	if (ctx->ct_addrinfo != NULL) {
128*613a2f6bSGordon Ross 		freeaddrinfo(ctx->ct_addrinfo);
129*613a2f6bSGordon Ross 		ctx->ct_addrinfo = NULL;
130*613a2f6bSGordon Ross 	}
131*613a2f6bSGordon Ross 
132*613a2f6bSGordon Ross 	/*
133*613a2f6bSGordon Ross 	 * If the user specified an address, use it,
134*613a2f6bSGordon Ross 	 * and don't do NetBIOS lookup.
135*613a2f6bSGordon Ross 	 */
136*613a2f6bSGordon Ross 	if (ctx->ct_srvaddr_s) {
137*613a2f6bSGordon Ross 		srvaddr_str = ctx->ct_srvaddr_s;
138*613a2f6bSGordon Ross 		nbc->nb_flags &= ~NBCF_NS_ENABLE;
139*613a2f6bSGordon Ross 	} else
140*613a2f6bSGordon Ross 		srvaddr_str = ctx->ct_fullserver;
141*613a2f6bSGordon Ross 
142*613a2f6bSGordon Ross 	/*
143*613a2f6bSGordon Ross 	 * Default the server name we'll use in the
144*613a2f6bSGordon Ross 	 * protocol (i.e. NTLM, tree connect).
145*613a2f6bSGordon Ross 	 * If we get a canonical name, we'll
146*613a2f6bSGordon Ross 	 * overwrite this below.
147*613a2f6bSGordon Ross 	 */
148*613a2f6bSGordon Ross 	strlcpy(ctx->ct_srvname, ctx->ct_fullserver,
149*613a2f6bSGordon Ross 	    sizeof (ctx->ct_srvname));
150*613a2f6bSGordon Ross 
151*613a2f6bSGordon Ross 	/*
152*613a2f6bSGordon Ross 	 * Try to lookup the host address using the
153*613a2f6bSGordon Ross 	 * normal name-to-IP address mechanisms.
154*613a2f6bSGordon Ross 	 * If that fails, we MAY try NetBIOS.
155*613a2f6bSGordon Ross 	 */
156*613a2f6bSGordon Ross 	memset(&hints, 0, sizeof (hints));
157*613a2f6bSGordon Ross 	hints.ai_flags = AI_CANONNAME;
158*613a2f6bSGordon Ross 	hints.ai_family = PF_UNSPEC;
159*613a2f6bSGordon Ross 	hints.ai_socktype = SOCK_STREAM;
160*613a2f6bSGordon Ross 	gaierr = getaddrinfo(srvaddr_str, NULL, &hints, &res);
161*613a2f6bSGordon Ross 	if (gaierr == 0) {
162*613a2f6bSGordon Ross #if 1
163*613a2f6bSGordon Ross 		/*
164*613a2f6bSGordon Ross 		 * XXX Temporarily work-around CR 6831339:
165*613a2f6bSGordon Ross 		 * getaddrinfo() sets ai_canonname incorrectly
166*613a2f6bSGordon Ross 		 */
167*613a2f6bSGordon Ross 		char tmphost[256];
168*613a2f6bSGordon Ross 		gaierr2 = getnameinfo(res->ai_addr, res->ai_addrlen,
169*613a2f6bSGordon Ross 		    tmphost, sizeof (tmphost),
170*613a2f6bSGordon Ross 		    NULL, 0, NI_NAMEREQD);
171*613a2f6bSGordon Ross 		if (gaierr2 == 0) {
172*613a2f6bSGordon Ross 			DPRINT("cname: %s", tmphost);
173*613a2f6bSGordon Ross 			strlcpy(ctx->ct_srvname, tmphost,
174*613a2f6bSGordon Ross 			    sizeof (ctx->ct_srvname));
175*613a2f6bSGordon Ross 		}
176*613a2f6bSGordon Ross #else
177*613a2f6bSGordon Ross 		if (res->ai_canonname)
178*613a2f6bSGordon Ross 			strlcpy(ctx->ct_srvname, res->ai_canonname,
179*613a2f6bSGordon Ross 			    sizeof (ctx->ct_srvname));
180*613a2f6bSGordon Ross #endif
181*613a2f6bSGordon Ross 		ctx->ct_addrinfo = res;
182*613a2f6bSGordon Ross 		return (0);
183*613a2f6bSGordon Ross 	}
184*613a2f6bSGordon Ross 
185*613a2f6bSGordon Ross 	/*
186*613a2f6bSGordon Ross 	 * If regular IP name lookup failed, try NetBIOS,
187*613a2f6bSGordon Ross 	 * but only if given a valid NetBIOS name and if
188*613a2f6bSGordon Ross 	 * NetBIOS name lookup is enabled.
189*613a2f6bSGordon Ross 	 *
190*613a2f6bSGordon Ross 	 * Note: we only have ssn_srvname if the full name
191*613a2f6bSGordon Ross 	 * was also a valid NetBIOS name.
192*613a2f6bSGordon Ross 	 */
193*613a2f6bSGordon Ross 	if (nbc->nb_flags & NBCF_NS_ENABLE) {
194*613a2f6bSGordon Ross 		gaierr2 = nbns_getaddrinfo(ctx->ct_fullserver, nbc, &res);
195*613a2f6bSGordon Ross 		if (gaierr2 == 0) {
196*613a2f6bSGordon Ross 			if (res->ai_canonname)
197*613a2f6bSGordon Ross 				strlcpy(ctx->ct_srvname,
198*613a2f6bSGordon Ross 				    res->ai_canonname,
199*613a2f6bSGordon Ross 				    sizeof (ctx->ct_srvname));
200*613a2f6bSGordon Ross 			ctx->ct_addrinfo = res;
201*613a2f6bSGordon Ross 			return (0);
202*613a2f6bSGordon Ross 		}
203*613a2f6bSGordon Ross 	}
204*613a2f6bSGordon Ross 
205*613a2f6bSGordon Ross 	/*
206*613a2f6bSGordon Ross 	 * Return the original error from getaddrinfo
207*613a2f6bSGordon Ross 	 */
208*613a2f6bSGordon Ross 	if (smb_verbose) {
209*613a2f6bSGordon Ross 		smb_error(dgettext(TEXT_DOMAIN,
210*613a2f6bSGordon Ross 		    "getaddrinfo: %s: %s"), 0,
211*613a2f6bSGordon Ross 		    ctx->ct_fullserver,
212*613a2f6bSGordon Ross 		    gai_strerror(gaierr));
213*613a2f6bSGordon Ross 	}
214*613a2f6bSGordon Ross 	return (gaierr);
215*613a2f6bSGordon Ross }
216