1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 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. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME 80** 81** twr_np.c 82** 83** FACILITY: 84** 85** Protocol Tower Services for the internet address family 86** 87** ABSTRACT: 88** 89** The protocol tower service provides routines that: 90** 91** o convert a socket address to the lower floors of 92** a protocol tower 93** 94** o convert a protocol tower to a socket address 95** 96** 97*/ 98 99#include <commonp.h> /* Common declarations for all RPC runtime */ 100#include <com.h> /* Common communications services */ 101#include <twrp.h> /* Private tower services */ 102#include <npnaf.h> 103 104/* 105 * Include the Internet specific socket address 106 */ 107#if HAVE_SYS_UN_H 108#include <sys/un.h> 109#else 110#include <un.h> 111#endif 112#include <sys/param.h> 113#include <netdb.h> 114#include <ctype.h> 115 116/* 117**++ 118** 119** ROUTINE NAME: twr_np_lower_flrs_from_sa 120** 121** SCOPE: PUBLIC - declared in twr.idl 122** 123** DESCRIPTION: 124** 125** Creates the canonical representation of an internet protocol tower's 126** lower floors from a sockaddr. The canonical form can be transmitted 127** on the wire, or included in a DNS tower. 128** 129** INPUTS: 130** 131** trans_prot Integer value specifying the transport layer 132** protocol for the Internet address family. 133** For address family RPC_C_NAF_ID_NP specify: 134** 135** RPC_C_NETWORK_PROTOCOL_ID_NP for udp 136** 137** sa Internet-specific socket address data 138** structure. 139** 140** INPUTS/OUTPUTS: none 141** 142** OUTPUTS: 143** 144** lower_flrs Returns the lower tower floors in a twr_t 145** structure (includes the floor count in the 146** "tower_octet_string" member). 147** 148** status A value indicating the return status of the routine: 149** twr_s_ok 150** twr_s_unknown_sa 151** 152** IMPLICIT INPUTS: none 153** 154** IMPLICIT OUTPUTS: none 155** 156** FUNCTION VALUE: void 157** 158** SIDE EFFECTS: none 159** 160**-- 161**/ 162 163PUBLIC void twr_np_lower_flrs_from_sa 164( 165 sockaddr_p_t sa, 166 twr_p_t *lower_flrs, 167 unsigned32 *status 168) 169{ 170 unsigned8 protocol_id[TWR_C_NUM_NP_LOWER_FLRS]; 171 unsigned16 id_size = TWR_C_TOWER_PROT_ID_SIZE, 172 floor_count, 173 related_data_size[TWR_C_NUM_NP_LOWER_FLRS], 174 twr_rep_16; 175 unsigned32 count, 176 twr_t_length; 177 byte_p_t related_data_ptr[TWR_C_NUM_NP_LOWER_FLRS], 178 tmp_tower; 179 char hostname[MAXHOSTNAMELEN], *p; 180 181 CODING_ERROR (status); 182 RPC_VERIFY_INIT (); 183 184 RPC_DBG_GPRINTF(("(twr_np_lower_flrs_from_sa) called\n")); 185 186 if (sa->family == RPC_C_NAF_ID_UXD) 187 { 188 protocol_id[0] = TWR_C_FLR_PROT_ID_NP; 189 protocol_id[1] = TWR_C_FLR_PROT_ID_NB; 190 } 191 else 192 { 193 *status = twr_s_unknown_sa; 194 return; 195 } 196 197 /* 198 * Since we now know the socket address we're dealing with, 199 * collect the sizes of each field to allocate memory, and 200 * remember the pointers to the fields so we can copy the 201 * data once we have allocated the tower string. 202 */ 203 floor_count = TWR_C_NUM_NP_LOWER_FLRS; 204 205 /* 206 * related_data[0] contains the pipe name (eg. \PIPE\lsass) 207 */ 208 related_data_ptr[0] = (unsigned char*) ((struct sockaddr_un *)sa)->sun_path; 209 if (strncmp((char*) related_data_ptr[0], (char*) RPC_C_NP_DIR"/", RPC_C_NP_DIR_LEN + 1) == 0) 210 { 211 /* Path is relative, but do not chop off first /. */ 212 related_data_ptr[0] += RPC_C_NP_DIR_LEN; 213 } 214 related_data_size[0] = strlen((char*) related_data_ptr[0]) + 1; 215 216 /* 217 * related_data[1] contains the NetBIOS name (eg. \\MYSERVER) 218 */ 219 hostname[0] = '\\'; 220 hostname[1] = '\\'; 221 gethostname(&hostname[2], MAXHOSTNAMELEN - 3); 222 hostname[MAXHOSTNAMELEN - 1] = '\0'; 223 for (p = &hostname[2]; *p != '\0'; p++) 224 *p = toupper((int)*p); 225 related_data_size[1] = strlen(hostname) + 1; 226 related_data_ptr[1] = (unsigned char*) hostname; 227 228 /* 229 * Calculate the length of the tower floors. 230 */ 231 232 twr_t_length = TWR_C_TOWER_FLR_COUNT_SIZE; /* to store floor count */ 233 234 for ( count = 0; count < floor_count; count++ ) 235 { 236 twr_t_length += TWR_C_FLR_OVERHEAD; 237 twr_t_length += related_data_size[count]; 238 } 239 240 /* 241 * Next allocate space for the tower structure 242 */ 243 RPC_MEM_ALLOC ( 244 *lower_flrs, 245 twr_p_t, 246 sizeof (twr_t) + (twr_t_length - 1), 247 RPC_C_MEM_TOWER, 248 RPC_C_MEM_WAITOK ); 249 250 /* 251 * Copy the length of the tower octet string into the tower structure 252 */ 253 (*lower_flrs)->tower_length = twr_t_length; 254 255 /* 256 * Copy the floor information into the tower octet string 257 */ 258 259 /* 260 * Use a temporary for the octet string since we need 261 * to increment the pointer. 262 */ 263 tmp_tower = (*lower_flrs)->tower_octet_string; 264 265 /* 266 * Copy the number of floors into the tower octet string 267 */ 268 twr_rep_16 = floor_count; 269 RPC_RESOLVE_ENDIAN_INT16 (twr_rep_16); 270 memcpy ((char *)tmp_tower, (char *)&twr_rep_16, 271 TWR_C_TOWER_FLR_COUNT_SIZE); 272 273 tmp_tower += TWR_C_TOWER_FLR_COUNT_SIZE; 274 275 /* 276 * Convert the protocol identifier size to its proper 277 * representation for use in the following loop. 278 */ 279 RPC_RESOLVE_ENDIAN_INT16 (id_size); 280 281 for ( count = 0; count < floor_count; count++ ) 282 { 283 /* 284 * Copy the length of the protocol identifier field into 285 * tower octet string. (Converted before the loop.) 286 */ 287 memcpy ((char *)tmp_tower, (char *)&id_size, 288 TWR_C_TOWER_FLR_LHS_COUNT_SIZE); 289 290 tmp_tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE; 291 292 /* 293 * Copy the protocol identifier into tower octet string 294 * (1 byte so no need to convert endian representation). 295 */ 296 memcpy ((char *)tmp_tower, (char *)&(protocol_id[count]), 297 TWR_C_TOWER_PROT_ID_SIZE); 298 299 tmp_tower += TWR_C_TOWER_PROT_ID_SIZE; 300 301 /* 302 * Copy the length of the address data field into 303 * tower octet string. 304 */ 305 twr_rep_16 = related_data_size[count]; 306 RPC_RESOLVE_ENDIAN_INT16 (twr_rep_16); 307 memcpy ((char *)tmp_tower, (char *)&twr_rep_16, 308 TWR_C_TOWER_FLR_RHS_COUNT_SIZE); 309 310 tmp_tower += TWR_C_TOWER_FLR_RHS_COUNT_SIZE; 311 312 /* 313 * If there is addressing data, copy the address data field into 314 * tower octet string 315 */ 316 if (related_data_size[count]) 317 { 318 memcpy ((char *)tmp_tower, (char *)related_data_ptr[count], 319 related_data_size[count]); 320 321 /* Convert slashes */ 322 for (p = (char*) tmp_tower; *p != '\0'; p++) { 323 if (*p == '/') 324 *p = '\\'; 325 } 326 327 /* 328 * Set up for the next floor. 329 */ 330 tmp_tower += related_data_size[count]; 331 } 332 } 333 334 *status = twr_s_ok; 335} 336 337/* 338**++ 339** 340** ROUTINE NAME: twr_np_lower_flrs_to_sa 341** 342** SCOPE: PUBLIC - declared in twr.idl 343** 344** DESCRIPTION: 345** 346** Creates an internet sockaddr from the canonical representation of an 347** internet protocol tower's lower floors. 348** 349** INPUTS: 350** 351** tower_octet_string 352** The protocol tower to convert to a sockaddr. 353** 354** INPUTS/OUTPUTS: none 355** 356** OUTPUTS: 357** 358** sa Returns a pointer to the created sockaddr structure. 359** 360** sa_len Returns the length, in bytes, of the returned 361** "sa" argument. 362** 363** status A value indicating the return status of the routine: 364** twr_s_ok 365** twr_s_unknown_tower 366** 367** IMPLICIT INPUTS: none 368** 369** IMPLICIT OUTPUTS: none 370** 371** FUNCTION VALUE: void 372** 373** SIDE EFFECTS: none 374** 375**-- 376**/ 377 378PUBLIC void twr_np_lower_flrs_to_sa 379( 380 byte_p_t tower_octet_string, 381 sockaddr_p_t *sa, 382 unsigned32 *sa_len, 383 unsigned32 *status 384) 385{ 386 unsigned8 id; 387 byte_p_t tower; 388 unsigned16 count, 389 floor_count, 390 id_size, 391 addr_size; 392 unsigned32 length; 393 char *p; 394 395 CODING_ERROR (status); 396 RPC_VERIFY_INIT (); 397 398 id_size = 0; 399 400 /* 401 * Make sure we have a pointer to some data structure. 402 */ 403 if ( !(tower = tower_octet_string)) 404 { 405 *status = twr_s_unknown_tower; 406 return; 407 } 408 409 RPC_DBG_GPRINTF(("(twr_np_lower_flrs_to_sa) called\n")); 410 411 /* 412 * Get the tower floor count 413 */ 414 memcpy ((char *)&floor_count, (char *)tower, TWR_C_TOWER_FLR_COUNT_SIZE); 415 RPC_RESOLVE_ENDIAN_INT16 (floor_count); 416 417 tower += TWR_C_TOWER_FLR_COUNT_SIZE; 418 419 /* 420 * Skip over the (application's) upper floors while we look for the 421 * beginning of the np-specific lower floors. 422 */ 423 for ( count = 0; count < floor_count; count++ ) 424 { 425 /* 426 * Get the length of this floor's protocol id field (don't advance 427 * the pointer). 428 */ 429 memcpy ((char *)&id_size, (char *)tower, 430 TWR_C_TOWER_FLR_LHS_COUNT_SIZE); 431 RPC_RESOLVE_ENDIAN_INT16 (id_size); 432 433 /* 434 * Get the protocol id (don't advance the pointer). 435 * Expect one byte; no need to convert. 436 */ 437 memcpy ((char *)&id, (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE), 438 TWR_C_TOWER_PROT_ID_SIZE); 439 440 /* 441 * See if we support the protocol id. 442 */ 443 if ( (id_size == TWR_C_TOWER_PROT_ID_SIZE) && 444 (id == TWR_C_FLR_PROT_ID_NP)) 445 { 446 /* 447 * Indicate we found the beginning of the np floors. 448 */ 449 *status = twr_s_ok; 450 451 break; 452 } 453 else 454 { 455 /* 456 * Skip this floor. Get the address size in order 457 * to know how much to skip. 458 */ 459 memcpy ((char *)&addr_size, 460 (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE + 461 id_size), TWR_C_TOWER_FLR_RHS_COUNT_SIZE); 462 RPC_RESOLVE_ENDIAN_INT16 (addr_size); 463 464 tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size + 465 TWR_C_TOWER_FLR_RHS_COUNT_SIZE + addr_size; 466 467 /* 468 * For now, assume we don't find the floors we're looking for. 469 */ 470 *status = twr_s_unknown_tower; 471 } 472 } 473 474 if (*status != twr_s_ok) 475 { 476 return; 477 } 478 479 /* 480 * Skip the floor's protocol id field length and protocol id 481 * (now move the pointer). We already know it's 482 * TWR_C_FLR_PROT_ID_NP. 483 */ 484 tower += (TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size); 485 486 /* 487 * Allocate space for sockaddr 488 */ 489 length = sizeof(struct sockaddr_un); 490 491 RPC_MEM_ALLOC ( 492 *sa, 493 sockaddr_p_t, 494 length, 495 RPC_C_MEM_SOCKADDR, 496 RPC_C_MEM_WAITOK ); 497 498 *sa_len = length; 499 500 /* 501 * make sure unused bytes are null 502 */ 503 memset ((char *) *sa, 0, length); 504 505 /* 506 * define this as an internet family socket 507 */ 508 ((struct sockaddr_un *)(*sa))->sun_family = RPC_C_NAF_ID_UXD; 509 510 /* 511 * Get the length of pipe name 512 */ 513 memcpy ((char *)&addr_size, (char *)tower, RPC_C_TOWER_FLR_RHS_COUNT_SIZE); 514 RPC_RESOLVE_ENDIAN_INT16 (addr_size); 515 tower += RPC_C_TOWER_FLR_RHS_COUNT_SIZE; 516 517 /* 518 * Copy the pipe name to the sockaddr 519 */ 520 tower[addr_size - 1] = '\0'; 521 addr_size += RPC_C_NP_DIR_LEN + 1; 522 if ((size_t)addr_size + 1 > sizeof(((struct sockaddr_un *)(*sa))->sun_path)) 523 { 524 *status = rpc_s_no_memory; 525 RPC_MEM_FREE (*sa, RPC_C_MEM_SOCKADDR); 526 return; 527 } 528 snprintf(((struct sockaddr_un *)(*sa))->sun_path, length, "%s/%s", 529 RPC_C_NP_DIR, tower); 530 for (p = ((struct sockaddr_un *)(*sa))->sun_path; *p != '\0'; p++) 531 { 532 if (*p == '\\') 533 *p = '/'; 534 } 535 536 *status = twr_s_ok; 537 538 /* For now, disregard the NetBIOS address. */ 539} 540