1/* 2 * Copyright (c) 2000, Boris Popov 3 * All rights reserved. 4 * 5 * Portions Copyright (C) 2005 - 2010 Apple Inc. All rights reserved 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Boris Popov. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35#include <sys/param.h> 36#include <sys/errno.h> 37#include <sys/stat.h> 38#include <sys/socket.h> 39#include <err.h> 40#include <stdio.h> 41#include <unistd.h> 42#include <strings.h> 43#include <stdlib.h> 44#include <sysexits.h> 45 46#include <SMBClient/smbclient.h> 47#include <SMBClient/netbios.h> 48#include <arpa/inet.h> 49 50#include "common.h" 51 52/* 53 * Make a copy of the name and if request unpercent escape the name 54 */ 55static char * 56getHostName(const char *name, Boolean escapeNames) 57{ 58 char *newName = strdup(name); 59 CFStringRef nameRef = NULL; 60 CFStringRef newNameRef = NULL; 61 62 /* They don't want it escape or the strdup failed */ 63 if (!escapeNames || !newName) { 64 return newName; 65 } 66 /* Get a CFString */ 67 nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8); 68 69 /* unpercent escape out the CFString */ 70 if (nameRef) { 71 newNameRef = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, 72 nameRef, CFSTR(" "), kCFStringEncodingUTF8); 73 } 74 /* Now create an unpercent escape out c style string */ 75 if (newNameRef) { 76 int maxlen = (int)CFStringGetLength(newNameRef)+1; 77 char *tempName = malloc(maxlen); 78 79 if (tempName) { 80 free(newName); 81 newName = tempName; 82 CFStringGetCString(newNameRef, newName, maxlen, kCFStringEncodingUTF8); 83 } 84 } 85 86 if (nameRef) { 87 CFRelease(nameRef); 88 } 89 if (newNameRef) { 90 CFRelease(newNameRef); 91 } 92 return newName; 93} 94 95 96int 97cmd_lookup(int argc, char *argv[]) 98{ 99 char *hostname; 100 int opt; 101 struct sockaddr_storage *startAddr = NULL, *listAddr = NULL; 102 const char *winsServer = NULL; 103 int32_t ii, count = 0; 104 struct sockaddr_storage respAddr; 105 struct sockaddr_in *in4 = NULL; 106 struct sockaddr_in6 *in6 = NULL; 107 char addrStr[INET6_ADDRSTRLEN+1]; 108 uint8_t nodeType = kNetBIOSFileServerService; 109 Boolean escapeNames= FALSE; 110 111 bzero(&respAddr, sizeof(respAddr)); 112 if (argc < 2) 113 lookup_usage(); 114 while ((opt = getopt(argc, argv, "ew:t:")) != EOF) { 115 switch(opt) { 116 case 'e': 117 escapeNames = TRUE; 118 break; 119 case 'w': 120 winsServer = optarg; 121 break; 122 case 't': 123 errno = 0; 124 nodeType = (uint8_t)strtol(optarg, NULL, 0); 125 if (errno) 126 errx(EX_DATAERR, "invalid value for node type"); 127 break; 128 default: 129 lookup_usage(); 130 /*NOTREACHED*/ 131 } 132 } 133 if (optind >= argc) 134 lookup_usage(); 135 136 hostname = getHostName(argv[argc - 1], escapeNames); 137 if (!hostname) { 138 err(EX_OSERR, "failed to resolve %s", argv[argc - 1]); 139 } 140 141 startAddr = listAddr = SMBResolveNetBIOSNameEx(hostname, nodeType, winsServer, 142 0, &respAddr, &count); 143 if (startAddr == NULL) { 144 err(EX_NOHOST, "unable to resolve %s", hostname); 145 } 146 147 if (respAddr.ss_family == AF_INET) { 148 in4 = (struct sockaddr_in *)&respAddr; 149 inet_ntop(respAddr.ss_family, &in4->sin_addr, addrStr, sizeof(addrStr)); 150 } else if (respAddr.ss_family == AF_INET6) { 151 in6 = (struct sockaddr_in6 *)&respAddr; 152 inet_ntop(respAddr.ss_family, &in6->sin6_addr, addrStr, sizeof(addrStr)); 153 } else { 154 strcpy(addrStr, "unknown address family"); 155 } 156 157 fprintf(stdout, "Got response from %s\n", addrStr); 158 159 for (ii=0; ii < count; ii++) { 160 if (listAddr->ss_family == AF_INET) { 161 in4 = (struct sockaddr_in *)listAddr; 162 inet_ntop(listAddr->ss_family, &in4->sin_addr, addrStr, sizeof(addrStr)); 163 } else if (respAddr.ss_family == AF_INET6) { 164 in6 = (struct sockaddr_in6 *)listAddr; 165 inet_ntop(respAddr.ss_family, &in6->sin6_addr, addrStr, sizeof(addrStr)); 166 } else { 167 strcpy(addrStr, "unknown address family"); 168 } 169 fprintf(stdout, "IP address of %s: %s\n", hostname, addrStr); 170 listAddr++; 171 } 172 if (startAddr) { 173 free(startAddr); 174 } 175 if (hostname) { 176 free(hostname); 177 } 178 return 0; 179} 180 181 182void 183lookup_usage(void) 184{ 185 fprintf(stderr, "usage: smbutil lookup [-e] [-w host] [-t node type] name\n"); 186 exit(1); 187} 188