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_uxd.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 <uxdnaf.h> 103 104/* 105 * Include the Internet specific socket address 106 */ 107#include <sys/un.h> 108 109/* 110**++ 111** 112** ROUTINE NAME: twr_uxd_lower_flrs_from_sa 113** 114** SCOPE: PUBLIC - declared in twr.idl 115** 116** DESCRIPTION: 117** 118** Creates the canonical representation of an internet protocol tower's 119** lower floors from a sockaddr. The canonical form can be transmitted 120** on the wire, or included in a DNS tower. 121** 122** INPUTS: 123** 124** trans_prot Integer value specifying the transport layer 125** protocol for the Internet address family. 126** For address family RPC_C_NAF_ID_UXD specify: 127** 128** RPC_C_NETWORK_PROTOCOL_ID_UXD for udp 129** 130** sa Internet-specific socket address data 131** structure. 132** 133** INPUTS/OUTPUTS: none 134** 135** OUTPUTS: 136** 137** lower_flrs Returns the lower tower floors in a twr_t 138** structure (includes the floor count in the 139** "tower_octet_string" member). 140** 141** status A value indicating the return status of the routine: 142** twr_s_ok 143** twr_s_unknown_sa 144** 145** IMPLICIT INPUTS: none 146** 147** IMPLICIT OUTPUTS: none 148** 149** FUNCTION VALUE: void 150** 151** SIDE EFFECTS: none 152** 153**-- 154**/ 155 156PUBLIC void twr_uxd_lower_flrs_from_sa 157( 158 sockaddr_p_t sa, 159 twr_p_t *lower_flrs, 160 unsigned32 *status 161) 162{ 163 unsigned8 protocol_id[TWR_C_NUM_UXD_LOWER_FLRS]; 164 unsigned16 id_size = TWR_C_TOWER_PROT_ID_SIZE, 165 floor_count, 166 related_data_size[TWR_C_NUM_UXD_LOWER_FLRS], 167 twr_rep_16; 168 unsigned32 count, 169 twr_t_length; 170 byte_p_t related_data_ptr[TWR_C_NUM_UXD_LOWER_FLRS], 171 tmp_tower; 172 char *sun_path; 173 174 CODING_ERROR (status); 175 RPC_VERIFY_INIT (); 176 177 if (sa->family == RPC_C_NAF_ID_UXD) 178 { 179 protocol_id[0] = TWR_C_FLR_PROT_ID_UXD; 180 } 181 else 182 { 183 *status = twr_s_unknown_sa; 184 return; 185 } 186 187 /* 188 * Since we now know the socket address we're dealing with, 189 * collect the sizes of each field to allocate memory, and 190 * remember the pointers to the fields so we can copy the 191 * data once we have allocated the tower string. 192 */ 193 floor_count = TWR_C_NUM_UXD_LOWER_FLRS; 194 195 /* 196 * Not sure whether we need to "canonicalize" this. 197 */ 198 sun_path = ((struct sockaddr_un *)sa)->sun_path; 199 if (strncmp(sun_path, RPC_C_UXD_DIR, RPC_C_UXD_DIR_LEN) == 0) 200 { 201 related_data_ptr[0] = (byte_p_t)&sun_path[RPC_C_UXD_DIR_LEN + 1]; 202 } 203 else 204 { 205 related_data_ptr[0] = (byte_p_t)sun_path; 206 } 207 related_data_size[0] = strlen((char*) related_data_ptr[0]) + 1; 208 209 /* 210 * Calculate the length of the tower floors. 211 */ 212 213 twr_t_length = TWR_C_TOWER_FLR_COUNT_SIZE; /* to store floor count */ 214 215 for ( count = 0; count < floor_count; count++ ) 216 { 217 twr_t_length += TWR_C_FLR_OVERHEAD; 218 twr_t_length += related_data_size[count]; 219 } 220 221 /* 222 * Next allocate space for the tower structure 223 */ 224 RPC_MEM_ALLOC ( 225 *lower_flrs, 226 twr_p_t, 227 sizeof (twr_t) + (twr_t_length - 1), 228 RPC_C_MEM_TOWER, 229 RPC_C_MEM_WAITOK ); 230 231 /* 232 * Copy the length of the tower octet string into the tower structure 233 */ 234 (*lower_flrs)->tower_length = twr_t_length; 235 236 /* 237 * Copy the floor information into the tower octet string 238 */ 239 240 /* 241 * Use a temporary for the octet string since we need 242 * to increment the pointer. 243 */ 244 tmp_tower = (*lower_flrs)->tower_octet_string; 245 246 /* 247 * Copy the number of floors into the tower octet string 248 */ 249 twr_rep_16 = floor_count; 250 RPC_RESOLVE_ENDIAN_INT16 (twr_rep_16); 251 memcpy ((char *)tmp_tower, (char *)&twr_rep_16, 252 TWR_C_TOWER_FLR_COUNT_SIZE); 253 254 tmp_tower += TWR_C_TOWER_FLR_COUNT_SIZE; 255 256 /* 257 * Convert the protocol identifier size to its proper 258 * representation for use in the following loop. 259 */ 260 RPC_RESOLVE_ENDIAN_INT16 (id_size); 261 262 for ( count = 0; count < floor_count; count++ ) 263 { 264 /* 265 * Copy the length of the protocol identifier field into 266 * tower octet string. (Converted before the loop.) 267 */ 268 memcpy ((char *)tmp_tower, (char *)&id_size, 269 TWR_C_TOWER_FLR_LHS_COUNT_SIZE); 270 271 tmp_tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE; 272 273 /* 274 * Copy the protocol identifier into tower octet string 275 * (1 byte so no need to convert endian representation). 276 */ 277 memcpy ((char *)tmp_tower, (char *)&(protocol_id[count]), 278 TWR_C_TOWER_PROT_ID_SIZE); 279 280 tmp_tower += TWR_C_TOWER_PROT_ID_SIZE; 281 282 /* 283 * Copy the length of the address data field into 284 * tower octet string. 285 */ 286 twr_rep_16 = related_data_size[count]; 287 RPC_RESOLVE_ENDIAN_INT16 (twr_rep_16); 288 memcpy ((char *)tmp_tower, (char *)&twr_rep_16, 289 TWR_C_TOWER_FLR_RHS_COUNT_SIZE); 290 291 tmp_tower += TWR_C_TOWER_FLR_RHS_COUNT_SIZE; 292 293 /* 294 * If there is addressing data, copy the address data field into 295 * tower octet string 296 */ 297 if (related_data_size[count]) 298 { 299 memcpy ((char *)tmp_tower, (char *)related_data_ptr[count], 300 related_data_size[count]); 301 302 /* 303 * Set up for the next floor. 304 */ 305 tmp_tower += related_data_size[count]; 306 } 307 } 308 309 *status = twr_s_ok; 310} 311 312/* 313**++ 314** 315** ROUTINE NAME: twr_uxd_lower_flrs_to_sa 316** 317** SCOPE: PUBLIC - declared in twr.idl 318** 319** DESCRIPTION: 320** 321** Creates an internet sockaddr from the canonical representation of an 322** internet protocol tower's lower floors. 323** 324** INPUTS: 325** 326** tower_octet_string 327** The protocol tower to convert to a sockaddr. 328** 329** INPUTS/OUTPUTS: none 330** 331** OUTPUTS: 332** 333** sa Returns a pointer to the created sockaddr structure. 334** 335** sa_len Returns the length, in bytes, of the returned 336** "sa" argument. 337** 338** status A value indicating the return status of the routine: 339** twr_s_ok 340** twr_s_unknown_tower 341** 342** IMPLICIT INPUTS: none 343** 344** IMPLICIT OUTPUTS: none 345** 346** FUNCTION VALUE: void 347** 348** SIDE EFFECTS: none 349** 350**-- 351**/ 352 353PUBLIC void twr_uxd_lower_flrs_to_sa 354( 355 byte_p_t tower_octet_string, 356 sockaddr_p_t *sa, 357 unsigned32 *sa_len, 358 unsigned32 *status 359) 360{ 361 unsigned8 id; 362 byte_p_t tower; 363 unsigned16 count, 364 floor_count, 365 id_size, 366 addr_size; 367 unsigned32 length; 368 369 CODING_ERROR (status); 370 RPC_VERIFY_INIT (); 371 372 id_size = 0; 373 374 /* 375 * Make sure we have a pointer to some data structure. 376 */ 377 if ( !(tower = tower_octet_string)) 378 { 379 *status = twr_s_unknown_tower; 380 return; 381 } 382 383 /* 384 * Get the tower floor count 385 */ 386 memcpy ((char *)&floor_count, (char *)tower, TWR_C_TOWER_FLR_COUNT_SIZE); 387 RPC_RESOLVE_ENDIAN_INT16 (floor_count); 388 389 tower += TWR_C_TOWER_FLR_COUNT_SIZE; 390 391 /* 392 * Skip over the (application's) upper floors while we look for the 393 * beginning of the uxd-specific lower floors. 394 */ 395 for ( count = 0; count < floor_count; count++ ) 396 { 397 /* 398 * Get the length of this floor's protocol id field (don't advance 399 * the pointer). 400 */ 401 memcpy ((char *)&id_size, (char *)tower, 402 TWR_C_TOWER_FLR_LHS_COUNT_SIZE); 403 RPC_RESOLVE_ENDIAN_INT16 (id_size); 404 405 /* 406 * Get the protocol id (don't advance the pointer). 407 * Expect one byte; no need to convert. 408 */ 409 memcpy ((char *)&id, (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE), 410 TWR_C_TOWER_PROT_ID_SIZE); 411 412 /* 413 * See if we support the protocol id. 414 */ 415 if ( (id_size == TWR_C_TOWER_PROT_ID_SIZE) && 416 (id == TWR_C_FLR_PROT_ID_UXD)) 417 { 418 /* 419 * Indicate we found the beginning of the uxd floors. 420 */ 421 *status = twr_s_ok; 422 423 break; 424 } 425 else 426 { 427 /* 428 * Skip this floor. Get the address size in order 429 * to know how much to skip. 430 */ 431 memcpy ((char *)&addr_size, 432 (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE + 433 id_size), TWR_C_TOWER_FLR_RHS_COUNT_SIZE); 434 RPC_RESOLVE_ENDIAN_INT16 (addr_size); 435 436 tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size + 437 TWR_C_TOWER_FLR_RHS_COUNT_SIZE + addr_size; 438 439 /* 440 * For now, assume we don't find the floors we're looking for. 441 */ 442 *status = twr_s_unknown_tower; 443 } 444 } 445 446 if (*status != twr_s_ok) 447 { 448 return; 449 } 450 451 /* 452 * Skip the floor's protocol id field length and protocol id 453 * (now move the pointer). We already know it's 454 * TWR_C_FLR_PROT_ID_UXD. 455 */ 456 tower += (TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size); 457 458 /* 459 * Allocate space for sockaddr 460 */ 461 length = sizeof(struct sockaddr_un); 462 463 RPC_MEM_ALLOC ( 464 *sa, 465 sockaddr_p_t, 466 length, 467 RPC_C_MEM_SOCKADDR, 468 RPC_C_MEM_WAITOK ); 469 470 *sa_len = length; 471 472 /* 473 * make sure unused bytes are null 474 */ 475 memset ((char *) *sa, 0, length); 476 477 /* 478 * define this as an internet family socket 479 */ 480 ((struct sockaddr_un *)(*sa))->sun_family = RPC_C_NAF_ID_UXD; 481 482 /* 483 * Get the length of endpoint address 484 */ 485 memcpy ((char *)&addr_size, (char *)tower, RPC_C_TOWER_FLR_RHS_COUNT_SIZE); 486 RPC_RESOLVE_ENDIAN_INT16 (addr_size); 487 tower += RPC_C_TOWER_FLR_RHS_COUNT_SIZE; 488 489 /* 490 * Copy the endpoint address to the sockaddr. 491 */ 492 tower[addr_size - 1] = '\0'; 493 if (tower[0] != '/') 494 { 495 addr_size += RPC_C_UXD_DIR_LEN + 1; 496 } 497 if (addr_size > sizeof(((struct sockaddr_un *)(*sa))->sun_path)) 498 { 499 *status = rpc_s_no_memory; 500 RPC_MEM_FREE (*sa, RPC_C_MEM_SOCKADDR); 501 *sa = NULL; 502 return; 503 } 504 505 snprintf(((struct sockaddr_un *)(*sa))->sun_path, 506 sizeof(((struct sockaddr_un *)(*sa))->sun_path), 507 "%s%s", (tower[0] == '/') ? "" : RPC_C_UXD_DIR"/", 508 tower); 509 510 *status = twr_s_ok; 511} 512