1/* 2 * Copyright (c) 2008 - 2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25#include <smbclient/smbclient.h> 26#include <smbclient/ntstatus.h> 27#include <smbclient/smbclient_internal.h> 28 29#include <algorithm> 30#include <vector> 31#include <cstdlib> 32#include <assert.h> 33#include <string> 34 35#include "lmshare.h" 36#include "memory.hpp" 37#include "rpc_helpers.hpp" 38 39#define MEMPOOL_DEBUG 0 40 41struct free_function : public std::unary_function<void *, void> 42{ 43 void operator()(void * ptr) const { 44#if MEMPOOL_DEBUG 45 SMBLogInfo("rpc_mempool(%llu): freeing ptr %p", ASL_LEVEL_DEBUG 46 (unsigned long long)pthread_self(), ptr); 47#endif 48 std::free(ptr); 49 } 50}; 51 52#ifndef __clang_analyzer__ 53/* <12135199> Clang static analyzer does not understand the below code */ 54 55rpc_mempool * 56rpc_mempool::allocate( 57 size_t payload_size) 58{ 59 void * ptr; 60 61 ptr = std::calloc(1, rpc_mempool::block_size() + payload_size); 62 if (!ptr) { 63 return NULL; 64 } 65 66 return new (ptr) rpc_mempool(); 67} 68#endif 69 70void 71rpc_mempool::destroy( 72 rpc_mempool * pool) 73{ 74 pool->~rpc_mempool(); 75 std::free(pool); 76} 77 78rpc_mempool::rpc_mempool() 79: ptrs(10) 80{ 81#if MEMPOOL_DEBUG 82 SMBLogInfo("constructing rpc_mempool at %p", ASL_LEVEL_DEBUG, this); 83#endif 84 ptrs.resize(0); 85} 86 87rpc_mempool::~rpc_mempool() 88{ 89#if MEMPOOL_DEBUG 90 SMBLogInfo("destroying rpc_mempool at %p", ASL_LEVEL_DEBUG, this); 91#endif 92 std::for_each(ptrs.begin(), ptrs.end(), free_function()); 93} 94 95void * 96rpc_mempool::alloc( 97 size_t sz) 98{ 99 void * ptr = platform::allocate(NULL, sz); 100 if (ptr) { 101 ptrs.push_back(ptr); 102 } 103 104#if MEMPOOL_DEBUG 105 SMBLogInfo("rpc_mempool(%llu): allocated ptr %p for %u bytes", ASL_LEVEL_DEBUG, 106 (unsigned long long)pthread_self(), ptr, (unsigned)sz); 107#endif 108 return ptr; 109} 110 111void 112rpc_mempool::free( 113 void * ptr) 114{ 115 ptr_list_type::iterator which = 116 std::find(ptrs.begin(), ptrs.end(), ptr); 117 118 assert(which != ptrs.end()); 119 ptrs.erase(which); 120 121#if MEMPOOL_DEBUG 122 SMBLogInfo("rpc_mempool(%llu): freed ptr %p", ASL_LEVEL_DEBUG, 123 (unsigned long long)pthread_self(), ptr); 124#endif 125 free_function f; f(ptr); 126} 127 128idl_void_p_t 129rpc_pool_allocate(idl_void_p_t context, idl_size_t sz) 130{ 131 rpc_mempool * pool = (rpc_mempool *)context; 132 return pool->alloc(sz); 133} 134 135void 136rpc_pool_free(idl_void_p_t context, idl_void_p_t ptr) 137{ 138 rpc_mempool * pool = (rpc_mempool *)context; 139 return pool->free(ptr); 140} 141 142rpc_binding::rpc_binding(const rpc_binding& src) 143{ 144 unsigned32 status; 145 rpc_binding_copy(src.get(), &binding_handle, &status); 146 assert(status == rpc_s_ok); 147} 148 149rpc_binding::rpc_binding(const char * string_binding) 150{ 151 error_status_t status; 152 153 rpc_binding_from_string_binding((idl_char *)string_binding, 154 &binding_handle, &status); 155 if (status != rpc_s_ok) { 156 SMBLogInfo("rpc_binding_from_string_binding failed on <%s> status %#08x", 157 ASL_LEVEL_ERR, 158 string_binding == NULL ? "nullstr" : string_binding, 159 status); 160 binding_handle = NULL; 161 } 162} 163 164rpc_binding::~rpc_binding() 165{ 166 if (binding_handle) { 167 error_status_t status; 168 169 rpc_network_close(binding_handle, &status); 170 rpc_binding_free(&binding_handle, &status); 171 } 172} 173 174// Return an appropriate binding for the given ServerName. 175rpc_binding 176make_rpc_binding( 177 const char * ServerName, 178 const char * EndPoint) 179{ 180 char * binding_string = NULL; 181 char * endpoint_string = NULL; 182 uint32_t status; 183 184 if (!EndPoint) { 185 return rpc_binding(); 186 } 187 188 if (ServerName) { 189 /* add in the "\pipe\" to the endpoint */ 190 asprintf(&endpoint_string, "\\pipe\\%s]", EndPoint); 191 192 rpc_string_binding_compose(NULL, 193 (idl_char *) "ncacn_np", 194 (idl_char *) ServerName, 195 (idl_char *) endpoint_string, 196 NULL, 197 (idl_char **) &binding_string, 198 &status); 199 if (status != 0) { 200 SMBLogInfo("rpc_string_binding_compose failed on <%s>:<%s> status %#08x", 201 ASL_LEVEL_ERR, 202 ServerName == NULL ? "nullstr" : ServerName, 203 EndPoint == NULL ? "nullstr" : EndPoint, 204 status); 205 206 /* fallback to the old way instead */ 207 asprintf(&binding_string, "ncacn_np:%s[%s]", 208 ServerName, endpoint_string); 209 } 210 211 if (endpoint_string != NULL) { 212 free(endpoint_string); 213 } 214 } 215 else { 216 rpc_string_binding_compose(NULL, 217 (idl_char *) "ncalrpc", 218 NULL, 219 (idl_char *) EndPoint, 220 NULL, 221 (idl_char **) &binding_string, 222 &status); 223 if (status != 0) { 224 SMBLogInfo("rpc_string_binding_compose failed on <%s> status %#08x", 225 ASL_LEVEL_ERR, 226 EndPoint == NULL ? "nullstr" : EndPoint, 227 status); 228 229 /* fallback to the old way instead */ 230 asprintf(&binding_string, "ncalrpc:[%s]", EndPoint); 231 } 232 } 233 234 if (!binding_string) { 235 platform::invoke_new_handler(); 236 } 237 238 rpc_binding binding(binding_string); 239 240 if (status == 0) { 241 /* rpc_string_binding_compose worked */ 242 if (binding_string != NULL) { 243 rpc_string_free((idl_char **) &binding_string, &status); 244 if (status != 0) { 245 SMBLogInfo("rpc_string_free failed on <%s> status %#08x", 246 ASL_LEVEL_ERR, 247 binding_string == NULL ? "nullstr" : binding_string, 248 status); 249 } 250 } 251 } 252 else { 253 /* must have used asprintf */ 254 if (binding_string != NULL) { 255 free(binding_string); 256 } 257 } 258 259 return binding; 260} 261 262error_status_t 263rpc_exception_status( 264 dcethread_exc * exc) 265{ 266 int status; 267 268 status = dcethread_exc_getstatus(exc); 269 if (status == -1) { 270 SMBLogInfo("unexpected RPC exception: kind=%#x address=%p %s", ASL_LEVEL_DEBUG, 271 exc->kind, exc->match.address, exc->name); 272 return rpc_m_unexpected_exc; 273 } 274 275 return status; 276} 277 278/* vim: set sw=4 ts=4 tw=79 et: */ 279