1/* 2 * Copyright (c) 2000-2007 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 * winscard_msg.c 26 * SmartCardServices 27 */ 28 29/* 30 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 31 * 32 * Copyright (C) 2001-2004 33 * David Corcoran <corcoran@linuxnet.com> 34 * Damien Sauveron <damien.sauveron@labri.fr> 35 * Ludoic Rousseau <ludovic.rousseau@free.fr> 36 * 37 * $Id: winscard_msg.cpp 123 2010-03-27 10:50:42Z ludovic.rousseau@gmail.com $ 38 */ 39 40/** 41 * @file 42 * @brief This is responsible for client/server communication. 43 * 44 * A file based socket (\c commonSocket) is used to send/receive only messages 45 * among clients and server.\n 46 * The messages' data are passed throw a memory mapped file: \c sharedSegmentMsg. 47 */ 48 49#include "config.h" 50#include <fcntl.h> 51#include <unistd.h> 52#include <sys/types.h> 53#include <sys/stat.h> 54#include <sys/socket.h> 55#include <sys/time.h> 56#include <sys/un.h> 57#include <sys/ioctl.h> 58#include <errno.h> 59#include <stdio.h> 60#include <time.h> 61#include <string.h> 62#ifdef HAVE_SYS_FILIO_H 63#include <sys/filio.h> 64#endif 65 66#include "wintypes.h" 67#include "pcsclite.h" 68#include "pcscexport.h" 69#include "winscard.h" 70#include "debug.h" 71#include "winscard_msg.h" 72#include "sys_generic.h" 73 74#include <libkern/OSByteOrder.h> 75/* 76 #define bswap_16 OSSwapInt16 77#define bswap_32 OSSwapInt32 78#define bswap_64 OSSwapInt64 79*/ 80 81#include <security_utilities/debugging.h> 82 83/** 84 * @brief Wrapper for the SHMMessageReceive() function. 85 * 86 * Called by clients to read the server responses. 87 * 88 * @param[out] msgStruct Message read. 89 * @param[in] dwClientID Client socket handle. 90 * @param[in] blockamount Timeout in milliseconds. 91 * 92 * @return Same error codes as SHMMessageReceive(). 93 */ 94INTERNAL int32_t SHMClientRead(psharedSegmentMsg msgStruct, uint32_t dwClientID, int32_t blockamount) 95{ 96 int rv = SHMMessageReceive(msgStruct, sizeof(*msgStruct), dwClientID, blockamount); 97 SHSharedSegmentMsgToHostOrder(msgStruct); 98 return rv; 99} 100 101/** 102 * @brief Wrapper for the SHMMessageReceive() function. 103 * 104 * Called by clients to read the server responses. This reads the exact number of bytes expected for the struct 105 * 106 * @param[out] msgStruct Message read. 107 * @param[in] dwClientID Client socket handle. 108 * @param[in] dataSize Size of the data at msgStruct->data 109 * @param[in] blockamount Timeout in milliseconds. 110 * 111 * @return Same error codes as SHMMessageReceive(). 112 */ 113INTERNAL int32_t SHMClientReadMessage(psharedSegmentMsg msgStruct, uint32_t dwClientID, size_t dataSize, int32_t blockamount) 114{ 115 // Read the basic header first so we know the size of the rest 116 // The special case of "dataSize == 0" means that we should deduce the size of the 117 // data from the header 118 size_t headerSize = sizeof(sharedSegmentMsg) - sizeof(msgStruct->data); 119 Log2(PCSC_LOG_DEBUG, "SHMClientReadMessage: Issuing read for %d bytes (header)", headerSize); 120 secdebug("pcscd", "SHMClientReadMessage: Issuing read for %ld bytes (header)", headerSize); 121 int rv = SHMMessageReceive(msgStruct, headerSize, dwClientID, blockamount); 122 Log3(rv?PCSC_LOG_CRITICAL:PCSC_LOG_DEBUG, "SHMClientReadMessage: read message header error: 0x%08X [0x%08X]", rv, rv); 123 secdebug("pcscd", "SHMClientReadMessage: read message header error: 0x%08X [0x%08X]", rv, rv); 124 if (rv) 125 return rv; 126 SHSharedSegmentMsgToHostOrder(msgStruct); 127 128 // Integrity check 129 if (msgStruct->headerTag != WINSCARD_MSG_HEADER_TAG) 130 { 131 Log3(PCSC_LOG_CRITICAL, "Error: read message header tag of: 0x%08X for possible command 0x%08X", 132 msgStruct->headerTag, msgStruct->command); 133 secdebug("pcscd", "Error: read message header tag of: 0x%08X for possible command 0x%08X", 134 msgStruct->headerTag, msgStruct->command); 135 return SCARD_F_INTERNAL_ERROR; 136 } 137 138 if (dataSize == 0) 139 dataSize = msgStruct->msgSize - headerSize; // message size includes header 140 else 141 if (msgStruct->msgSize != (headerSize + dataSize)) 142 { 143 Log2(PCSC_LOG_CRITICAL, "Error: create on client socket: %s", strerror(errno)); 144 secdebug("pcscd", "Error: create on client socket: %s", strerror(errno)); 145 return SCARD_F_INTERNAL_ERROR; 146 } 147 148 Log2(PCSC_LOG_DEBUG, "SHMClientReadMessage: Issuing read for %d bytes", dataSize); 149 secdebug("pcscd", "SHMClientReadMessage: Issuing read for %ld bytes", dataSize); 150 if (blockamount == 0) 151 blockamount = PCSCLITE_SERVER_ATTEMPTS; 152 rv = SHMMessageReceive(msgStruct->data, dataSize, dwClientID, blockamount); 153 Log3(rv?PCSC_LOG_CRITICAL:PCSC_LOG_DEBUG, "SHMClientReadMessage: read message body error: 0x%08X [0x%08X]", rv, rv); 154 secdebug("pcscd", "SHMClientReadMessage: read message body error: 0x%08X [0x%08X]", rv, rv); 155 156 return rv; 157} 158 159/** 160 * @brief Prepares a communication channel for the client to talk to the server. 161 * 162 * This is called by the application to create a socket for local IPC with the 163 * server. The socket is associated to the file \c PCSCLITE_CSOCK_NAME. 164 * 165 * @param[out] pdwClientID Client Connection ID. 166 * 167 * @retval 0 Success. 168 * @retval -1 Can not create the socket. 169 * @retval -1 The socket can not open a connection. 170 * @retval -1 Can not set the socket to non-blocking. 171 */ 172INTERNAL int SHMClientSetupSession(uint32_t *pdwClientID) 173{ 174 struct sockaddr_un svc_addr; 175 int one; 176 int ret; 177 178 ret = socket(AF_UNIX, SOCK_STREAM, 0); 179 if (ret < 0) 180 { 181 Log2(PCSC_LOG_CRITICAL, "Error: create on client socket: %s", 182 strerror(errno)); 183 return -1; 184 } 185 *pdwClientID = ret; 186 187 svc_addr.sun_family = AF_UNIX; 188 strncpy(svc_addr.sun_path, PCSCLITE_CSOCK_NAME, 189 sizeof(svc_addr.sun_path)); 190 191 if (connect(*pdwClientID, (struct sockaddr *) &svc_addr, 192 sizeof(svc_addr.sun_family) + strlen(svc_addr.sun_path) + 1) < 0) 193 { 194 Log3(PCSC_LOG_CRITICAL, "Error: connect to client socket %s: %s", 195 PCSCLITE_CSOCK_NAME, strerror(errno)); 196 SYS_CloseFile(*pdwClientID); 197 return -1; 198 } 199 200 one = 1; 201 if (ioctl(*pdwClientID, FIONBIO, &one) < 0) 202 { 203 Log3(PCSC_LOG_CRITICAL, "Error: cannot set socket %s nonblocking: %s", 204 PCSCLITE_CSOCK_NAME, strerror(errno)); 205 SYS_CloseFile(*pdwClientID); 206 return -1; 207 } 208 209 return 0; 210} 211 212/** 213 * @brief Closes the socket used by the client to communicate with the server. 214 * 215 * @param[in] dwClientID Client socket handle to be closed. 216 * 217 * @retval 0 Success. 218 */ 219INTERNAL int SHMClientCloseSession(uint32_t dwClientID) 220{ 221 SYS_CloseFile(dwClientID); 222 return 0; 223} 224 225/** 226 * @brief CalculateMessageSize 227 * 228 * @param[in] dataSize Size of the additional data to send in the message. 229 * 230 * @retval total message size. 231 */ 232INTERNAL size_t SHMCalculateMessageSize(size_t dataSize) 233{ 234 // PCSCLITE_MAX_MESSAGE_SIZE == sizeof(sharedSegmentMsg.data) 235 return sizeof(sharedSegmentMsg) - PCSCLITE_MAX_MESSAGE_SIZE + dataSize;; 236} 237 238 239/** 240 * @brief Sends a menssage from client to server or vice-versa. 241 * 242 * Writes the message in the shared file \c filedes. 243 * 244 * @param[in] buffer_void Message to be sent. 245 * @param[in] buffer_size Size of the message to send 246 * @param[in] filedes Socket handle. 247 * @param[in] blockAmount Timeout in milliseconds. 248 * 249 * @retval 0 Success 250 * @retval -1 Timeout. 251 * @retval -1 Socket is closed. 252 * @retval -1 A signal was received. 253 */ 254INTERNAL int SHMMessageSend(void *buffer_void, uint64_t buffer_size, 255 int32_t filedes, int32_t blockAmount) 256{ 257 char *buffer = (char *)buffer_void; 258 259 /* 260 * default is success 261 */ 262 int retval = 0; 263 /* 264 * record the time when we started 265 */ 266 time_t start = time(0); 267 /* 268 * how many bytes remains to be written 269 */ 270 size_t remaining = buffer_size; 271 272 LogXxd(PCSC_LOG_DEBUG, "==> SHMMessageSend:\n", (const unsigned char *)buffer, buffer_size); 273 274 /* 275 * repeat until all data is written 276 */ 277 while (remaining > 0) 278 { 279 fd_set write_fd; 280 struct timeval timeout; 281 int selret; 282 283 FD_ZERO(&write_fd); 284 FD_SET(filedes, &write_fd); 285 286 timeout.tv_usec = 0; 287 if ((timeout.tv_sec = start + blockAmount - time(0)) < 0) 288 { 289 /* 290 * we already timed out 291 */ 292 Log1(PCSC_LOG_ERROR, "SHMMessageReceive: we already timed out"); 293 retval = -1; 294 break; 295 } 296 297 selret = select(filedes + 1, NULL, &write_fd, NULL, &timeout); 298 299 /* 300 * try to write only when the file descriptor is writable 301 */ 302 if (selret > 0) 303 { 304 int written; 305 306 if (!FD_ISSET(filedes, &write_fd)) 307 { 308 /* 309 * very strange situation. it should be an assert really 310 */ 311 Log1(PCSC_LOG_ERROR, "SHMMessageReceive: very strange situation: !FD_ISSET"); 312 retval = -1; 313 break; 314 } 315 written = write(filedes, buffer, remaining); 316 317 if (written > 0) 318 { 319 /* 320 * we wrote something 321 */ 322 buffer += written; 323 remaining -= written; 324 } else if (written == 0) 325 { 326 /* 327 * peer closed the socket 328 */ 329 Log1(PCSC_LOG_ERROR, "SHMMessageReceive: peer closed the socket"); 330 retval = -1; 331 break; 332 } else 333 { 334 /* 335 * we ignore the signals and socket full situations, all 336 * other errors are fatal 337 */ 338 if (errno != EINTR && errno != EAGAIN) 339 { 340 retval = -1; 341 break; 342 } 343 } 344 } else if (selret == 0) 345 { 346 /* 347 * timeout 348 */ 349 Log1(PCSC_LOG_ERROR, "SHMMessageReceive: selret == 0 [timeout]"); 350 retval = -1; 351 break; 352 } else 353 { 354 /* 355 * ignore signals 356 */ 357 if (errno != EINTR) 358 { 359 Log2(PCSC_LOG_ERROR, "select returns with failure: %s", 360 strerror(errno)); 361 retval = -1; 362 break; 363 } 364 } 365 } 366 367 if (remaining > 0) 368 Log3(PCSC_LOG_ERROR, "failure to write all bytes, remaining: %d, err: ", remaining, strerror(errno)); 369 370 return retval; 371} 372 373/** 374 * @brief Called by the Client to get the reponse from the server or vice-versa. 375 * 376 * Reads the message from the file \c filedes. 377 * 378 * @param[out] buffer_void Message read. 379 * @param[in] buffer_size Size to read 380 * @param[in] filedes Socket handle. 381 * @param[in] blockAmount Timeout in milliseconds. 382 * 383 * @retval 0 Success. 384 * @retval -1 Timeout. 385 * @retval -1 Socket is closed. 386 * @retval -1 A signal was received. 387 */ 388INTERNAL int SHMMessageReceive(void *buffer_void, uint64_t buffer_size, 389 int32_t filedes, int32_t blockAmount) 390{ 391 char *buffer = (char *)buffer_void; 392 393 /* 394 * default is success 395 */ 396 int retval = 0; 397 /* 398 * record the time when we started 399 */ 400 time_t start = time(0); 401 /* 402 * how many bytes we must read 403 */ 404 size_t remaining = buffer_size; 405 406 /* 407 * repeat until we get the whole message 408 */ 409 while (remaining > 0) 410 { 411 fd_set read_fd; 412 struct timeval timeout; 413 int selret; 414 415 FD_ZERO(&read_fd); 416 FD_SET(filedes, &read_fd); 417 418 timeout.tv_usec = 0; 419 if ((timeout.tv_sec = start + blockAmount - time(0)) < 0) 420 { 421 /* 422 * we already timed out 423 */ 424 Log1(PCSC_LOG_ERROR, "SHMMessageReceive: we already timed out"); 425 retval = -1; 426 break; 427 } 428 429 selret = select(filedes + 1, &read_fd, NULL, NULL, &timeout); 430 431 /* 432 * try to read only when socket is readable 433 */ 434 if (selret > 0) 435 { 436 int readed; 437 438 if (!FD_ISSET(filedes, &read_fd)) 439 { 440 /* 441 * very strange situation. it should be an assert really 442 */ 443 Log1(PCSC_LOG_ERROR, "SHMMessageReceive: very strange situation: !FD_ISSET"); 444 retval = -1; 445 break; 446 } 447 readed = read(filedes, buffer, remaining); 448 449 if (readed > 0) 450 { 451 /* 452 * we got something 453 */ 454 buffer += readed; 455 remaining -= readed; 456 } else if (readed == 0) 457 { 458 /* 459 * peer closed the socket 460 */ 461 Log1(PCSC_LOG_ERROR, "SHMMessageReceive: peer closed the socket"); 462 retval = -1; 463 break; 464 } else 465 { 466 /* 467 * we ignore the signals and empty socket situations, all 468 * other errors are fatal 469 */ 470 if (errno != EINTR && errno != EAGAIN) 471 { 472 retval = -1; 473 break; 474 } 475 } 476 } else if (selret == 0) 477 { 478 /* 479 * timeout 480 */ 481 Log1(PCSC_LOG_ERROR, "SHMMessageReceive: selret == 0 [timeout]"); 482 retval = -1; 483 break; 484 } else 485 { 486 /* 487 * we ignore signals, all other errors are fatal 488 */ 489 if (errno != EINTR) 490 { 491 Log2(PCSC_LOG_ERROR, "select returns with failure: %s", 492 strerror(errno)); 493 retval = -1; 494 break; 495 } 496 } 497 } 498 499 size_t bytesRead = (buffer_size - remaining); 500 Log3(PCSC_LOG_DEBUG, "SHMMessageReceive errno: 0x%08X: %s", errno, errno?strerror(errno):"no error"); 501 Log3(retval?PCSC_LOG_ERROR:PCSC_LOG_DEBUG, "SHMMessageReceive retval: 0x%08X, bytes read: %d", retval, bytesRead); 502 LogXxd(PCSC_LOG_DEBUG, "<== SHMMessageReceive:\n", (const unsigned char *)buffer_void, bytesRead); 503 return retval; 504} 505 506/** 507 * @brief Wrapper for the SHMMessageSend() function. 508 * 509 * Called by clients to send messages to the server. 510 * The parameters \p command and \p data are set in the \c sharedSegmentMsg 511 * struct in order to be sent. 512 * 513 * @param[in] command Command to be sent. 514 * @param[in] dwClientID Client socket handle. 515 * @param[in] size Size of the message (\p data). 516 * @param[in] blockAmount Timeout to the operation in ms. 517 * @param[in] data_void Data to be sent. 518 * 519 * @return Same error codes as SHMMessageSend(). 520 */ 521INTERNAL int32_t WrapSHMWrite(uint32_t command, uint32_t dwClientID, 522 uint64_t size, uint32_t blockAmount, void *data_void) 523{ 524 char *data = (char *)data_void; 525 526 sharedSegmentMsg msgStruct; 527 int ret; 528 529 /* 530 * Set the appropriate packet parameters 531 */ 532 533 memset(&msgStruct, 0, sizeof(msgStruct)); 534 msgStruct.headerTag = WINSCARD_MSG_HEADER_TAG; 535 msgStruct.msgSize = sizeof(sharedSegmentMsg) - sizeof(msgStruct.data) + size; 536 msgStruct.mtype = (command == CMD_VERSION)?CMD_VERSION:CMD_FUNCTION; 537 msgStruct.user_id = SYS_GetUID(); 538 msgStruct.group_id = SYS_GetGID(); 539 msgStruct.command = command; 540 msgStruct.date = time(NULL); 541 memset(msgStruct.key, 0, sizeof(msgStruct.key)); 542 543 if ((SCARD_TRANSMIT_EXTENDED == command) 544 || (SCARD_CONTROL_EXTENDED == command)) 545 { 546 /* first block */ 547 size_t sizeToSend = (msgStruct.msgSize <= PCSCLITE_MAX_MESSAGE_SIZE)?msgStruct.msgSize:PCSCLITE_MAX_MESSAGE_SIZE; 548 size_t sizeRemaining = (msgStruct.msgSize <= PCSCLITE_MAX_MESSAGE_SIZE)?0: 549 (msgStruct.msgSize - PCSCLITE_MAX_MESSAGE_SIZE); 550 memcpy(msgStruct.data, data, sizeToSend); 551 552 SHSharedSegmentMsgToNetworkOrder(&msgStruct); 553 ret = SHMMessageSend(&msgStruct, sizeToSend, dwClientID, blockAmount); 554 if (ret) 555 return ret; 556 557 // Warning: this code only works for sizes of 2 blocks or less 558 if (sizeRemaining > sizeof(msgStruct.data)) 559 { 560 Log2(PCSC_LOG_ERROR, "WrapSHMWrite: cannot send message of size %d", sizeRemaining); 561 return -1; 562 } 563 564 // Message header already has the correct byte order 565 /* do not send an empty second block */ 566 if (sizeRemaining > 0) 567 { 568 memcpy(msgStruct.data, data, sizeRemaining); 569 ret = SHMMessageSend(&msgStruct, sizeToSend, dwClientID, blockAmount); 570 if (ret) 571 return ret; 572 } 573 } 574 else 575 if (size > sizeof(msgStruct.data)) 576 { 577 Log3(PCSC_LOG_ERROR, "WrapSHMWrite: cannot send message of size %d with this command: %d", size, command); 578 return -1; 579 } 580 else 581 { 582 size_t sizeToSend = msgStruct.msgSize; 583 memcpy(msgStruct.data, data, size); 584 SHSharedSegmentMsgToNetworkOrder(&msgStruct); 585 ret = SHMMessageSend(&msgStruct, sizeToSend, dwClientID, blockAmount); 586 } 587 return ret; 588} 589 590/** 591 * @brief Closes the communications channel used by the server to talk to the 592 * clients. 593 * 594 * The socket used is closed and the file it is bound to is removed. 595 * 596 * @param[in] sockValue Socket to be closed. 597 * @param[in] pcFilePath File used by the socket. 598 */ 599INTERNAL void SHMCleanupSharedSegment(int sockValue, const char *pcFilePath) 600{ 601 SYS_CloseFile(sockValue); 602 SYS_Unlink((char *)pcFilePath); 603} 604 605#pragma mark -------------------- Byte ordering functions -------------------- 606 607/** 608 * @brief Convert fields in the psharedSegmentMsg struct to network byte order for sending 609 * 610 * Call this before each call to SHMMessageSend. Note: the data fields are not processed 611 * and need to be done individually. Also have to look for WrapSHMWrite. 612 * 613 * @param[in/out] msgStruct Message read. 614 * 615 */ 616INTERNAL void SHSharedSegmentMsgToNetworkOrder(psharedSegmentMsg msg) 617{ 618 if (msg) 619 { 620 msg->headerTag = htonl(msg->headerTag); 621 msg->msgSize = htonl(msg->msgSize); 622 msg->mtype = htonl(msg->mtype); 623 msg->user_id = htonl(msg->user_id); 624 msg->group_id = htonl(msg->group_id); 625 msg->command = htonl(msg->command); 626 msg->date = htonl(msg->date); 627 } 628} 629 630/** 631 * @brief Convert fields in the psharedSegmentMsg struct to host byte order on receive 632 * 633 * Call this after each call to SHMMessageReceive. Note: the data fields are not processed 634 * and need to be done individually, e.g. in MSGFunctionDemarshall 635 * 636 * @param[in/out] msgStruct Message read. 637 * 638 */ 639INTERNAL void SHSharedSegmentMsgToHostOrder(psharedSegmentMsg msg) 640{ 641 if (msg) 642 { 643 msg->headerTag = ntohl(msg->headerTag); 644 msg->msgSize = ntohl(msg->msgSize); 645 msg->mtype = ntohl(msg->mtype); 646 msg->user_id = ntohl(msg->user_id); 647 msg->group_id = ntohl(msg->group_id); 648 msg->command = ntohl(msg->command); 649 msg->date = ntohl(msg->date); 650 } 651} 652 653INTERNAL void htonlControlStructExtended(control_struct_extended *cs) 654{ 655 if (cs) 656 { 657 cs->hCard = htonl(cs->hCard); 658 cs->dwControlCode = htonl(cs->dwControlCode); 659 cs->cbSendLength = htonl(cs->cbSendLength); 660 cs->cbRecvLength = htonl(cs->cbRecvLength); 661 cs->size = OSSwapHostToBigInt64(cs->size); 662 cs->rv = htonl(cs->rv); // so we don't forget about it 663 } 664} 665 666INTERNAL void ntohlControlStructExtended(control_struct_extended *cs) 667{ 668 if (cs) 669 { 670 cs->hCard = ntohl(cs->hCard); 671 cs->dwControlCode = ntohl(cs->dwControlCode); 672 cs->cbSendLength = ntohl(cs->cbSendLength); 673 cs->cbRecvLength = ntohl(cs->cbRecvLength); 674 cs->size = OSSwapBigToHostInt64(cs->size); 675 cs->rv = ntohl(cs->rv); 676 } 677} 678 679INTERNAL void htonlTransmitStruct(transmit_struct *ts) 680{ 681 if (ts) 682 { 683 ts->hCard = htonl(ts->hCard); 684 ts->pioSendPciProtocol = htonl(ts->pioSendPciProtocol); 685 ts->pioSendPciLength = htonl(ts->pioSendPciLength); 686 ts->cbSendLength = htonl(ts->cbSendLength); 687 ts->pioRecvPciProtocol = htonl(ts->pioRecvPciProtocol); 688 ts->pioRecvPciLength = htonl(ts->pioRecvPciLength); 689 ts->pcbRecvLength = htonl(ts->pcbRecvLength); 690 ts->rv = htonl(ts->rv); // so we don't forget about it 691 } 692} 693 694INTERNAL void ntohlTransmitStruct(transmit_struct *ts) 695{ 696 if (ts) 697 { 698 ts->hCard = ntohl(ts->hCard); 699 ts->pioSendPciProtocol = ntohl(ts->pioSendPciProtocol); 700 ts->pioSendPciLength = ntohl(ts->pioSendPciLength); 701 ts->cbSendLength = ntohl(ts->cbSendLength); 702 ts->pioRecvPciProtocol = ntohl(ts->pioRecvPciProtocol); 703 ts->pioRecvPciLength = ntohl(ts->pioRecvPciLength); 704 ts->pcbRecvLength = ntohl(ts->pcbRecvLength); 705 ts->rv = ntohl(ts->rv); 706 } 707} 708 709INTERNAL void htonlTransmitStructExtended(transmit_struct_extended *ts) 710{ 711 if (ts) 712 { 713 ts->hCard = htonl(ts->hCard); 714 ts->pioSendPciProtocol = htonl(ts->pioSendPciProtocol); 715 ts->pioSendPciLength = htonl(ts->pioSendPciLength); 716 ts->cbSendLength = htonl(ts->cbSendLength); 717 ts->pioRecvPciProtocol = htonl(ts->pioRecvPciProtocol); 718 ts->pioRecvPciLength = htonl(ts->pioRecvPciLength); 719 ts->pcbRecvLength = htonl(ts->pcbRecvLength); 720 /* Networks generally use big-endian order, and thus it is called network order when sending information over a network in a common format. */ 721 ts->size = OSSwapHostToBigInt64(ts->size); 722 ts->rv = htonl(ts->rv); // so we don't forget about it 723 } 724} 725 726INTERNAL void ntohlTransmitStructExtended(transmit_struct_extended *ts) 727{ 728 if (ts) 729 { 730 ts->hCard = ntohl(ts->hCard); 731 ts->pioSendPciProtocol = ntohl(ts->pioSendPciProtocol); 732 ts->pioSendPciLength = ntohl(ts->pioSendPciLength); 733 ts->cbSendLength = ntohl(ts->cbSendLength); 734 ts->pioRecvPciLength = ntohl(ts->pioRecvPciLength); 735 ts->pcbRecvLength = ntohl(ts->pcbRecvLength); 736 ts->size = OSSwapBigToHostInt64(ts->size); 737 ts->rv = ntohl(ts->rv); 738 } 739} 740 741INTERNAL void htonlEstablishStruct(establish_struct *es) 742{ 743 if (es) 744 { 745 es->dwScope = htonl(es->dwScope); 746 es->phContext = htonl(es->phContext); 747 es->rv = htonl(es->rv); 748 } 749} 750 751INTERNAL void ntohlEstablishStruct(establish_struct *es) 752{ 753 if (es) 754 { 755 es->dwScope = ntohl(es->dwScope); 756 es->phContext = ntohl(es->phContext); 757 es->rv = ntohl(es->rv); 758 } 759} 760 761INTERNAL void htonlReleaseStruct(release_struct *rs) 762{ 763 if (rs) 764 { 765 rs->hContext = htonl(rs->hContext); 766 rs->rv = htonl(rs->rv); 767 } 768} 769 770INTERNAL void ntohlReleaseStruct(release_struct *rs) 771{ 772 if (rs) 773 { 774 rs->hContext = ntohl(rs->hContext); 775 rs->rv = ntohl(rs->rv); 776 } 777} 778 779INTERNAL void htonlConnectStruct(connect_struct *cs) 780{ 781 if (cs) 782 { 783 cs->hContext = htonl(cs->hContext); 784 cs->dwShareMode = htonl(cs->dwShareMode); 785 cs->dwPreferredProtocols = htonl(cs->dwPreferredProtocols); 786 cs->phCard = htonl(cs->phCard); 787 cs->pdwActiveProtocol = htonl(cs->pdwActiveProtocol); 788 cs->rv = htonl(cs->rv); 789 } 790} 791 792INTERNAL void ntohlConnectStruct(connect_struct *cs) 793{ 794 if (cs) 795 { 796 cs->hContext = ntohl(cs->hContext); 797 cs->dwShareMode = ntohl(cs->dwShareMode); 798 cs->dwPreferredProtocols = ntohl(cs->dwPreferredProtocols); 799 cs->phCard = ntohl(cs->phCard); 800 cs->pdwActiveProtocol = ntohl(cs->pdwActiveProtocol); 801 cs->rv = ntohl(cs->rv); 802 } 803} 804 805INTERNAL void htonlReconnectStruct(reconnect_struct *rc) 806{ 807 if (rc) 808 { 809 rc->hCard = htonl(rc->hCard); 810 rc->dwShareMode = htonl(rc->dwShareMode); 811 rc->dwPreferredProtocols = htonl(rc->dwPreferredProtocols); 812 rc->dwInitialization = htonl(rc->dwInitialization); 813 rc->pdwActiveProtocol = htonl(rc->pdwActiveProtocol); 814 rc->rv = htonl(rc->rv); 815 } 816} 817 818INTERNAL void ntohlReconnectStruct(reconnect_struct *rc) 819{ 820 if (rc) 821 { 822 rc->hCard = ntohl(rc->hCard); 823 rc->dwShareMode = ntohl(rc->dwShareMode); 824 rc->dwPreferredProtocols = ntohl(rc->dwPreferredProtocols); 825 rc->dwInitialization = ntohl(rc->dwInitialization); 826 rc->pdwActiveProtocol = ntohl(rc->pdwActiveProtocol); 827 rc->rv = ntohl(rc->rv); 828 } 829} 830 831INTERNAL void htonlDisconnectStruct(disconnect_struct *dc) 832{ 833 if (dc) 834 { 835 dc->hCard = htonl(dc->hCard); 836 dc->dwDisposition = htonl(dc->dwDisposition); 837 dc->rv = htonl(dc->rv); 838 } 839} 840 841INTERNAL void ntohlDisconnectStruct(disconnect_struct *dc) 842{ 843 if (dc) 844 { 845 dc->hCard = ntohl(dc->hCard); 846 dc->dwDisposition = ntohl(dc->dwDisposition); 847 dc->rv = ntohl(dc->rv); 848 } 849} 850 851INTERNAL void htonlBeginStruct(begin_struct *bs) 852{ 853 if (bs) 854 { 855 bs->hCard = htonl(bs->hCard); 856 bs->rv = htonl(bs->rv); 857 } 858} 859 860INTERNAL void ntohlBeginStruct(begin_struct *bs) 861{ 862 if (bs) 863 { 864 bs->hCard = ntohl(bs->hCard); 865 bs->rv = ntohl(bs->rv); 866 } 867} 868 869INTERNAL void htonlCancelStruct(cancel_struct *cs) 870{ 871 if (cs) 872 { 873 cs->hCard = htonl(cs->hCard); 874 cs->rv = htonl(cs->rv); 875 } 876} 877 878INTERNAL void ntohlCancelStruct(cancel_struct *cs) 879{ 880 if (cs) 881 { 882 cs->hCard = ntohl(cs->hCard); 883 cs->rv = ntohl(cs->rv); 884 } 885} 886 887INTERNAL void htonlEndStruct(end_struct *es) 888{ 889 if (es) 890 { 891 es->hCard = htonl(es->hCard); 892 es->dwDisposition = htonl(es->dwDisposition); 893 es->rv = htonl(es->rv); 894 } 895} 896 897INTERNAL void ntohlEndStruct(end_struct *es) 898{ 899 if (es) 900 { 901 es->hCard = ntohl(es->hCard); 902 es->dwDisposition = ntohl(es->dwDisposition); 903 es->rv = ntohl(es->rv); 904 } 905} 906 907INTERNAL void htonlStatusStruct(status_struct *ss) 908{ 909 if (ss) 910 { 911 ss->hCard = htonl(ss->hCard); 912 ss->pcchReaderLen = htonl(ss->pcchReaderLen); 913 ss->pdwState = htonl(ss->pdwState); 914 ss->pdwProtocol = htonl(ss->pdwProtocol); 915 ss->pcbAtrLen = htonl(ss->pcbAtrLen); 916 ss->rv = htonl(ss->rv); 917 } 918} 919 920INTERNAL void ntohlStatusStruct(status_struct *ss) 921{ 922 if (ss) 923 { 924 ss->hCard = ntohl(ss->hCard); 925 ss->pcchReaderLen = ntohl(ss->pcchReaderLen); 926 ss->pdwState = ntohl(ss->pdwState); 927 ss->pdwProtocol = ntohl(ss->pdwProtocol); 928 ss->pcbAtrLen = ntohl(ss->pcbAtrLen); 929 ss->rv = ntohl(ss->rv); 930 } 931} 932 933INTERNAL void htonlControlStruct(control_struct *cs) 934{ 935 if (cs) 936 { 937 cs->hCard = htonl(cs->hCard); 938 cs->dwControlCode = htonl(cs->dwControlCode); 939 cs->cbSendLength = htonl(cs->cbSendLength); 940 cs->cbRecvLength = htonl(cs->cbRecvLength); 941 cs->dwBytesReturned = htonl(cs->dwBytesReturned); 942 cs->rv = htonl(cs->rv); 943 } 944} 945 946INTERNAL void ntohlControlStruct(control_struct *cs) 947{ 948 if (cs) 949 { 950 cs->hCard = ntohl(cs->hCard); 951 cs->dwControlCode = ntohl(cs->dwControlCode); 952 cs->cbSendLength = ntohl(cs->cbSendLength); 953 cs->cbRecvLength = ntohl(cs->cbRecvLength); 954 cs->dwBytesReturned = ntohl(cs->dwBytesReturned); 955 cs->rv = ntohl(cs->rv); 956 } 957} 958 959INTERNAL void htonlGetSetStruct(getset_struct *gs) 960{ 961 if (gs) 962 { 963 gs->hCard = htonl(gs->hCard); 964 gs->dwAttrId = htonl(gs->dwAttrId); 965 gs->cbAttrLen = htonl(gs->cbAttrLen); 966 gs->rv = htonl(gs->rv); 967 } 968} 969 970INTERNAL void ntohlGetSetStruct(getset_struct *gs) 971{ 972 if (gs) 973 { 974 gs->hCard = ntohl(gs->hCard); 975 gs->dwAttrId = ntohl(gs->dwAttrId); 976 gs->cbAttrLen = ntohl(gs->cbAttrLen); 977 gs->rv = ntohl(gs->rv); 978 } 979} 980 981INTERNAL void htonlVersionStruct(version_struct *vs) 982{ 983 if (vs) 984 { 985 vs->major = htonl(vs->major); 986 vs->minor = htonl(vs->minor); 987 vs->rv = htonl(vs->rv); 988 } 989} 990 991INTERNAL void ntohlVersionStruct(version_struct *vs) 992{ 993 if (vs) 994 { 995 vs->major = ntohl(vs->major); 996 vs->minor = ntohl(vs->minor); 997 vs->rv = ntohl(vs->rv); 998 } 999} 1000 1001