1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Platform Channel Protocol Library functions on Nigara platforms 28 * (Ontario, Erie, etc..) Solaris applications use these interfaces 29 * to communicate with entities that reside on service processor. 30 */ 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <string.h> 38 #include <assert.h> 39 #include <fcntl.h> 40 #include <errno.h> 41 #include <signal.h> 42 #include <setjmp.h> 43 #include <inttypes.h> 44 #include <umem.h> 45 #include <strings.h> 46 #include <time.h> 47 #include <sys/types.h> 48 #include <sys/stat.h> 49 #include <sys/glvc.h> 50 #include <sys/vldc.h> 51 #include <sys/ldc.h> 52 #include <netinet/in.h> 53 54 #include "libpcp.h" 55 #include "pcp_common.h" 56 #include "pcp_utils.h" 57 58 59 /* 60 * Following libpcp interfaces are exposed to user applications. 61 * 62 * int pcp_init(char *channel_name); 63 * int pcp_send_recv(int channel_fd, pcp_msg_t *req_msg, pcp_msg_t *resp_msg, 64 * uint32_t timeout); 65 * int pcp_close(int channel_fd); 66 * 67 */ 68 69 /* 70 * Forward declarations. 71 */ 72 static int pcp_send_req_msg_hdr(pcp_req_msg_hdr_t *req_hdr); 73 static int pcp_recv_resp_msg_hdr(pcp_resp_msg_hdr_t *resp_hdr); 74 static int pcp_io_op(void *buf, int byte_cnt, int io_op); 75 static uint32_t pcp_get_xid(void); 76 static int pcp_get_prop(int channel_fd, int prop, unsigned int *val); 77 static int pcp_read(uint8_t *buf, int buf_len); 78 static int pcp_write(uint8_t *buf, int buf_len); 79 static int pcp_peek(uint8_t *buf, int buf_len); 80 static int pcp_peek_read(uint8_t *buf, int buf_len); 81 static int pcp_frame_error_handle(void); 82 static int check_magic_byte_presence(int byte_cnt, uint8_t *byte_val, 83 int *ispresent); 84 static uint16_t checksum(uint16_t *addr, int32_t count); 85 static int pcp_cleanup(int channel_fd); 86 87 static int vldc_read(int fd, uint8_t *bufp, int size); 88 static int vldc_write(int fd, uint8_t *bufp, int size); 89 static int pcp_update_read_area(int byte_cnt); 90 static int pcp_vldc_frame_error_handle(void); 91 92 /* 93 * local channel (glvc) file descriptor set by pcp_send_recv() 94 */ 95 static int chnl_fd = -1; 96 97 /* 98 * Message Transaction ID 99 */ 100 static uint32_t msg_xid = 0; 101 102 /* 103 * Channel MTU size. 104 */ 105 static unsigned int mtu_size = PCPL_DEF_MTU_SZ; 106 107 /* 108 * timeout field is supplied by user. timeout field is used to decide 109 * how long to block on glvc driver calls before we return timeout error 110 * to user applications. 111 * 112 * Note: In the current implementation of glvc driver, all glvc calls are 113 * blocking. 114 */ 115 static uint32_t glvc_timeout = 0; 116 117 /* 118 * variables used by setsetjmp/siglongjmp. 119 */ 120 static volatile sig_atomic_t jumpok = 0; 121 static sigjmp_buf jmpbuf; 122 123 /* 124 * To unblock SIGALRM signal incase if it's blocked in libpcp user apps. 125 * Restore it to old state during pcp_close. 126 */ 127 static sigset_t blkset; 128 129 /* 130 * Buffers used for stream reading channel data. When data is read in 131 * stream fashion, first data is copied from channel (glvc) buffers to 132 * these local buffers from which the read requests are serviced. 133 */ 134 #define READ_AREA_SIZE (2*mtu_size) 135 static uint8_t *read_head = NULL; 136 static uint8_t *read_tail = NULL; 137 static uint8_t *read_area = NULL; 138 139 /* 140 * Buffer used for peeking new data available in channel (glvc) buffers. 141 */ 142 #define PEEK_AREA_SIZE (mtu_size) 143 static uint8_t *peek_area = NULL; 144 145 /* 146 * Buffers used for peeking data available either in local buffers or 147 * new data available in channel (glvc) buffers. 148 */ 149 #define PEEK_READ_AREA_SIZE (2*mtu_size) 150 static uint8_t *peek_read_head = NULL; 151 static uint8_t *peek_read_tail = NULL; 152 static uint8_t *peek_read_area = NULL; 153 154 static pcp_req_msg_hdr_t *req_msg_hdr = NULL; 155 static pcp_resp_msg_hdr_t *resp_msg_hdr = NULL; 156 static int req_msg_hdr_sz = 0; 157 static int resp_msg_hdr_sz = 0; 158 159 /* 160 * signal handling variables to handle glvc blocking calls. 161 */ 162 static struct sigaction glvc_act; 163 164 /* To restore old SIGALRM signal handler */ 165 static struct sigaction old_act; 166 167 /* 168 * Variables to support vldc based streaming transport 169 */ 170 static pcp_xport_t xport_type = GLVC_NON_STREAM; 171 #define VLDC_MTU_SIZE (2048) 172 173 static void 174 glvc_timeout_handler(void) 175 { 176 if (jumpok == 0) 177 return; 178 siglongjmp(jmpbuf, 1); 179 } 180 181 /* 182 * Initialize the virtual channel. It basically opens the virtual channel 183 * provided by the host application. 184 * 185 */ 186 187 int 188 pcp_init(char *channel_name) 189 { 190 sigset_t oldset; 191 int channel_fd; 192 char *dev_path; 193 vldc_opt_op_t op; 194 195 if (channel_name == NULL) 196 return (PCPL_INVALID_ARGS); 197 198 /* 199 * Given the argument, try to locate a device in the device tree 200 */ 201 dev_path = platsvc_name_to_path(channel_name, &xport_type); 202 203 /* 204 * Path exists ? 205 */ 206 if (NULL == dev_path) 207 return (PCPL_INVALID_ARGS); 208 209 /* 210 * Open virtual channel name. 211 */ 212 if ((channel_fd = open(dev_path, O_RDWR|O_EXCL)) < 0) { 213 free(dev_path); 214 return (PCPL_GLVC_ERROR); 215 } 216 217 free(dev_path); 218 219 /* 220 * Handle transport-specific processing 221 */ 222 switch (xport_type) { 223 case VLDC_STREAMING: 224 mtu_size = VLDC_MTU_SIZE; 225 226 op.op_sel = VLDC_OP_SET; 227 op.opt_sel = VLDC_OPT_MODE; 228 op.opt_val = LDC_MODE_STREAM; 229 if (ioctl(channel_fd, VLDC_IOCTL_OPT_OP, &op) != 0) { 230 (void) close(channel_fd); 231 return (PCPL_GLVC_ERROR); 232 } 233 break; 234 case GLVC_NON_STREAM: 235 default: 236 /* 237 * Get the Channel MTU size 238 */ 239 240 if (pcp_get_prop(channel_fd, GLVC_XPORT_OPT_MTU_SZ, 241 &mtu_size) != 0) { 242 (void) close(channel_fd); 243 return (PCPL_GLVC_ERROR); 244 } 245 break; 246 } 247 248 /* 249 * Get current signal mask. If SIGALRM is blocked 250 * unblock it. 251 */ 252 (void) sigprocmask(0, NULL, &oldset); 253 254 (void) sigemptyset(&blkset); 255 256 if (sigismember(&oldset, SIGALRM)) { 257 (void) sigaddset(&blkset, SIGALRM); 258 (void) sigprocmask(SIG_UNBLOCK, &blkset, NULL); 259 } 260 /* 261 * signal handler initialization to handle glvc call timeouts. 262 */ 263 glvc_act.sa_handler = glvc_timeout_handler; 264 (void) sigemptyset(&glvc_act.sa_mask); 265 glvc_act.sa_flags = SA_NODEFER; 266 267 if (sigaction(SIGALRM, &glvc_act, &old_act) < 0) { 268 (void) close(channel_fd); 269 return (PCPL_ERROR); 270 } 271 272 return (channel_fd); 273 } 274 275 /* 276 * Function: Close platform channel. 277 * Arguments: 278 * int channel_fd - channel file descriptor. 279 * Returns: 280 * always returns PCPL_OK for now. 281 */ 282 int 283 pcp_close(int channel_fd) 284 { 285 286 if (channel_fd >= 0) { 287 if (xport_type == GLVC_NON_STREAM) 288 (void) pcp_cleanup(channel_fd); 289 (void) close(channel_fd); 290 } else { 291 return (-1); 292 } 293 294 /* 295 * free global buffers 296 */ 297 if (read_area != NULL) { 298 umem_free(read_area, READ_AREA_SIZE); 299 read_area = NULL; 300 } 301 if (peek_area != NULL) { 302 umem_free(peek_area, PEEK_AREA_SIZE); 303 peek_area = NULL; 304 } 305 if (peek_read_area != NULL) { 306 umem_free(peek_read_area, PEEK_READ_AREA_SIZE); 307 peek_read_area = NULL; 308 } 309 if (req_msg_hdr != NULL) { 310 umem_free(req_msg_hdr, req_msg_hdr_sz); 311 req_msg_hdr = NULL; 312 } 313 if (resp_msg_hdr != NULL) { 314 umem_free(resp_msg_hdr, resp_msg_hdr_sz); 315 resp_msg_hdr = NULL; 316 } 317 318 /* 319 * Restore SIGALRM signal mask incase if we unblocked 320 * it during pcp_init. 321 */ 322 if (sigismember(&blkset, SIGALRM)) { 323 (void) sigprocmask(SIG_BLOCK, &blkset, NULL); 324 } 325 326 /* Restore SIGALRM signal handler */ 327 (void) sigaction(SIGALRM, &old_act, NULL); 328 329 return (PCPL_OK); 330 } 331 332 /* 333 * Function: Send and Receive messages on platform channel. 334 * Arguments: 335 * int channel_fd - channel file descriptor. 336 * pcp_msg_t *req_msg - Request Message to send to other end of channel. 337 * pcp_msg_t *resp_msg - Response Message to be received. 338 * uint32_t timeout - timeout field when waiting for data from channel. 339 * Returns: 340 * 0 - success (PCPL_OK). 341 * (-ve) - failure: 342 * PCPL_INVALID_ARGS - invalid args. 343 * PCPL_GLVC_TIMEOUT - glvc call timeout. 344 * PCPL_XPORT_ERROR - transport error in request message 345 * noticed by receiver. 346 * PCPL_MALLOC_FAIL - malloc failure. 347 * PCPL_CKSUM_ERROR - checksum error. 348 */ 349 int 350 pcp_send_recv(int channel_fd, pcp_msg_t *req_msg, pcp_msg_t *resp_msg, 351 uint32_t timeout) 352 { 353 void *datap; 354 void *resp_msg_data = NULL; 355 uint32_t status; 356 uint16_t cksum = 0; 357 int ret; 358 int resp_hdr_ok; 359 #ifdef PCP_CKSUM_ENABLE 360 uint16_t bkup_resp_hdr_cksum; 361 #endif 362 if (channel_fd < 0) { 363 return (PCPL_ERROR); 364 } 365 366 /* copy channel_fd to local fd (chnl_fd) for other functions use */ 367 chnl_fd = channel_fd; 368 369 if (req_msg == NULL) { 370 return (PCPL_INVALID_ARGS); 371 } 372 373 if (timeout > 0) 374 glvc_timeout = timeout; 375 else 376 glvc_timeout = 0; 377 378 if ((req_msg->msg_len != 0) && ((datap = req_msg->msg_data) == NULL)) 379 return (PCPL_INVALID_ARGS); 380 381 if (req_msg_hdr == NULL) { 382 req_msg_hdr_sz = sizeof (pcp_req_msg_hdr_t); 383 req_msg_hdr = (pcp_req_msg_hdr_t *)umem_zalloc(req_msg_hdr_sz, 384 UMEM_DEFAULT); 385 if (req_msg_hdr == NULL) 386 return (PCPL_MALLOC_FAIL); 387 } 388 389 if (req_msg->msg_len != 0) { 390 /* calculate request msg_cksum */ 391 cksum = checksum((uint16_t *)datap, req_msg->msg_len); 392 } 393 394 /* 395 * Fill in the message header for the request packet 396 */ 397 req_msg_hdr->magic_num = PCP_MAGIC_NUM; 398 req_msg_hdr->proto_ver = PCP_PROT_VER_1; 399 req_msg_hdr->msg_type = req_msg->msg_type; 400 req_msg_hdr->sub_type = req_msg->sub_type; 401 req_msg_hdr->rsvd_pad = 0; 402 req_msg_hdr->xid = pcp_get_xid(); 403 req_msg_hdr->msg_len = req_msg->msg_len; 404 req_msg_hdr->timeout = timeout; 405 req_msg_hdr->msg_cksum = cksum; 406 req_msg_hdr->hdr_cksum = 0; 407 408 /* fill request header checksum */ 409 req_msg_hdr->hdr_cksum = checksum((uint16_t *)req_msg_hdr, 410 req_msg_hdr_sz); 411 /* 412 * set sig jmp location 413 */ 414 if (sigsetjmp(jmpbuf, 1)) { 415 return (PCPL_GLVC_TIMEOUT); 416 } 417 jumpok = 1; /* monitor sigalrm from now on */ 418 419 /* 420 * send request message header 421 */ 422 if ((ret = pcp_send_req_msg_hdr(req_msg_hdr))) { 423 424 return (ret); 425 } 426 427 /* 428 * send request message 429 */ 430 if (req_msg->msg_len != 0) { 431 if ((ret = pcp_io_op(datap, req_msg->msg_len, 432 PCPL_IO_OP_WRITE))) { 433 return (ret); 434 } 435 } 436 437 if (timeout == (uint32_t)PCP_TO_NO_RESPONSE) 438 return (PCPL_OK); 439 440 if (resp_msg_hdr == NULL) { 441 resp_msg_hdr_sz = sizeof (pcp_resp_msg_hdr_t); 442 resp_msg_hdr = (pcp_resp_msg_hdr_t *)umem_alloc(resp_msg_hdr_sz, 443 UMEM_DEFAULT); 444 if (resp_msg_hdr == NULL) 445 return (PCPL_MALLOC_FAIL); 446 } 447 448 resp_hdr_ok = 0; 449 while (!resp_hdr_ok) { 450 451 /* 452 * Receive response message header 453 * Note: frame error handling is done in 454 * 'pcp_recv_resp_msg_hdr()'. 455 */ 456 if ((ret = pcp_recv_resp_msg_hdr(resp_msg_hdr))) { 457 return (ret); 458 } 459 460 /* 461 * Check header checksum if it matches with the received hdr 462 * checksum. 463 */ 464 #ifdef PCP_CKSUM_ENABLE 465 bkup_resp_hdr_cksum = resp_msg_hdr->hdr_cksum; 466 resp_msg_hdr->hdr_cksum = 0; 467 cksum = checksum((uint16_t *)resp_msg_hdr, resp_msg_hdr_sz); 468 469 if (cksum != bkup_resp_hdr_cksum) { 470 return (PCPL_CKSUM_ERROR); 471 } 472 #endif 473 /* 474 * Check for matching request and response messages 475 */ 476 if (resp_msg_hdr->xid != req_msg_hdr->xid) { 477 478 continue; /* continue reading response header */ 479 } 480 resp_hdr_ok = 1; 481 } 482 483 /* 484 * check status field for any channel protocol errrors 485 * This field signifies something happend during request 486 * message trasmission. This field is set by the receiver. 487 */ 488 status = resp_msg_hdr->status; 489 if (status != PCP_OK) { 490 return (PCPL_XPORT_ERROR); 491 } 492 493 if (resp_msg_hdr->msg_len != 0) { 494 495 /* libpcp users should free this memory */ 496 if ((resp_msg_data = (uint8_t *)malloc(resp_msg_hdr->msg_len)) 497 == NULL) 498 return (PCPL_MALLOC_FAIL); 499 bzero(resp_msg_data, resp_msg_hdr->msg_len); 500 /* 501 * Receive response message. 502 */ 503 if ((ret = pcp_io_op(resp_msg_data, resp_msg_hdr->msg_len, 504 PCPL_IO_OP_READ))) { 505 free(resp_msg_data); 506 return (ret); 507 } 508 509 #ifdef PCP_CKSUM_ENABLE 510 /* verify response message data checksum */ 511 cksum = checksum((uint16_t *)resp_msg_data, 512 resp_msg_hdr->msg_len); 513 if (cksum != resp_msg_hdr->msg_cksum) { 514 free(resp_msg_data); 515 return (PCPL_CKSUM_ERROR); 516 } 517 #endif 518 } 519 /* Everything is okay put the received data into user */ 520 /* application's resp_msg struct */ 521 resp_msg->msg_len = resp_msg_hdr->msg_len; 522 resp_msg->msg_type = resp_msg_hdr->msg_type; 523 resp_msg->sub_type = resp_msg_hdr->sub_type; 524 resp_msg->msg_data = (uint8_t *)resp_msg_data; 525 526 return (PCPL_OK); 527 528 } 529 530 /* 531 * Function: Get channel property values. 532 * Arguments: 533 * int channel_fd - channel file descriptor. 534 * int prop - property id. 535 * unsigned int *val - property value tobe copied. 536 * Returns: 537 * 0 - success 538 * (-ve) - failure: 539 * PCPL_ERR_GLVC - glvc ioctl failure. 540 */ 541 542 static int 543 pcp_get_prop(int channel_fd, int prop, unsigned int *val) 544 { 545 glvc_xport_opt_op_t channel_op; 546 int ret; 547 548 channel_op.op_sel = GLVC_XPORT_OPT_GET; 549 channel_op.opt_sel = prop; 550 channel_op.opt_val = 0; 551 552 (void) alarm(glvc_timeout); 553 554 if ((ret = ioctl(channel_fd, GLVC_XPORT_IOCTL_OPT_OP, 555 &channel_op)) < 0) { 556 557 (void) alarm(0); 558 return (ret); 559 } 560 (void) alarm(0); 561 562 *val = channel_op.opt_val; 563 564 return (0); 565 } 566 567 /* 568 * Function: wrapper for handling glvc calls (read/write/peek). 569 */ 570 static int 571 pcp_io_op(void *buf, int byte_cnt, int io_op) 572 { 573 int rv; 574 int n; 575 uint8_t *datap; 576 int (*func_ptr)(uint8_t *, int); 577 int io_sz; 578 int try_cnt; 579 580 581 if ((buf == NULL) || (byte_cnt < 0)) { 582 return (PCPL_INVALID_ARGS); 583 } 584 585 switch (io_op) { 586 case PCPL_IO_OP_READ: 587 func_ptr = pcp_read; 588 break; 589 case PCPL_IO_OP_WRITE: 590 func_ptr = pcp_write; 591 break; 592 case PCPL_IO_OP_PEEK: 593 func_ptr = pcp_peek; 594 break; 595 default: 596 return (PCPL_INVALID_ARGS); 597 } 598 599 /* 600 * loop until all I/O done, try limit exceded, or real failure 601 */ 602 603 rv = 0; 604 datap = buf; 605 while (rv < byte_cnt) { 606 io_sz = MIN((byte_cnt - rv), mtu_size); 607 try_cnt = 0; 608 while ((n = (*func_ptr)(datap, io_sz)) < 0) { 609 try_cnt++; 610 if (try_cnt > PCPL_MAX_TRY_CNT) { 611 rv = n; 612 goto done; 613 } 614 (void) sleep(PCPL_GLVC_SLEEP); 615 } /* while trying the io operation */ 616 617 if (n < 0) { 618 rv = n; 619 goto done; 620 } 621 rv += n; 622 datap += n; 623 } /* while still have more data */ 624 625 done: 626 if (rv == byte_cnt) 627 return (0); 628 else 629 return (PCPL_GLVC_ERROR); 630 } 631 632 /* 633 * For peeking 'bytes_cnt' bytes in channel (glvc) buffers. 634 * If data is available, the data is copied into 'buf'. 635 */ 636 static int 637 pcp_peek(uint8_t *buf, int bytes_cnt) 638 { 639 int ret; 640 glvc_xport_msg_peek_t peek_ctrl; 641 int n, m; 642 643 if (bytes_cnt < 0 || bytes_cnt > mtu_size) { 644 return (PCPL_INVALID_ARGS); 645 } 646 647 /* 648 * initialization of buffers used for peeking data in channel buffers. 649 */ 650 if (peek_area == NULL) { 651 peek_area = (uint8_t *)umem_zalloc(PEEK_AREA_SIZE, 652 UMEM_DEFAULT); 653 if (peek_area == NULL) { 654 return (PCPL_MALLOC_FAIL); 655 } 656 } 657 658 /* 659 * peek max MTU size bytes 660 */ 661 peek_ctrl.buf = (caddr_t)peek_area; 662 peek_ctrl.buflen = mtu_size; 663 peek_ctrl.flags = 0; 664 665 (void) alarm(glvc_timeout); 666 667 if ((ret = ioctl(chnl_fd, GLVC_XPORT_IOCTL_DATA_PEEK, &peek_ctrl)) 668 < 0) { 669 (void) alarm(0); 670 return (ret); 671 } 672 (void) alarm(0); 673 674 n = peek_ctrl.buflen; 675 676 if (n < 0) 677 return (PCPL_GLVC_ERROR); 678 679 /* 680 * satisfy request as best as we can 681 */ 682 m = MIN(bytes_cnt, n); 683 (void) memcpy(buf, peek_area, m); 684 685 return (m); 686 } 687 688 /* 689 * Function: write 'byte_cnt' bytes from 'buf' to channel. 690 */ 691 static int 692 pcp_write(uint8_t *buf, int byte_cnt) 693 { 694 695 int ret; 696 697 /* check for valid arguments */ 698 if (buf == NULL || byte_cnt < 0 || byte_cnt > mtu_size) { 699 return (PCPL_INVALID_ARGS); 700 } 701 702 if (xport_type == GLVC_NON_STREAM) { 703 (void) alarm(glvc_timeout); 704 705 if ((ret = write(chnl_fd, buf, byte_cnt)) < 0) { 706 (void) alarm(0); 707 return (ret); 708 } 709 (void) alarm(0); 710 } else { 711 if ((ret = vldc_write(chnl_fd, buf, byte_cnt)) <= 0) { 712 return (ret); 713 } 714 } 715 716 return (ret); 717 } 718 719 /* 720 * In current implementaion of glvc driver, streams reads are not supported. 721 * pcp_read mimics stream reads by first reading all the bytes present in the 722 * channel buffer into a local buffer and from then on read requests 723 * are serviced from local buffer. When read requests are not serviceble 724 * from local buffer, it repeates by first reading data from channel buffers. 725 * 726 * This call may need to be enhanced when glvc supports buffered (stream) 727 * reads - TBD 728 */ 729 730 static int 731 pcp_read(uint8_t *buf, int byte_cnt) 732 { 733 int ret; 734 int n, m, i; 735 736 if (byte_cnt < 0 || byte_cnt > mtu_size) { 737 return (PCPL_INVALID_ARGS); 738 } 739 740 /* 741 * initialization of local read buffer 742 * from which the stream read requests are serviced. 743 */ 744 if (read_area == NULL) { 745 read_area = (uint8_t *)umem_zalloc(READ_AREA_SIZE, 746 UMEM_DEFAULT); 747 if (read_area == NULL) { 748 return (PCPL_MALLOC_FAIL); 749 } 750 read_head = read_area; 751 read_tail = read_area; 752 } 753 754 /* 755 * if we already read this data then copy from local buffer it self 756 * without calling new read. 757 */ 758 if (byte_cnt <= (read_tail - read_head)) { 759 (void) memcpy(buf, read_head, byte_cnt); 760 read_head += byte_cnt; 761 return (byte_cnt); 762 } 763 764 /* 765 * if the request is not satisfied from the buffered data, then move the 766 * remaining data to front of the buffer and read new data. 767 */ 768 for (i = 0; i < (read_tail - read_head); ++i) { 769 read_area[i] = read_head[i]; 770 } 771 read_head = read_area; 772 read_tail = read_head + i; 773 774 /* 775 * do a peek to see how much data is available and read complete data. 776 */ 777 778 if (xport_type == GLVC_NON_STREAM) { 779 if ((m = pcp_peek(read_tail, mtu_size)) < 0) { 780 return (m); 781 } 782 783 (void) alarm(glvc_timeout); 784 if ((ret = read(chnl_fd, read_tail, m)) < 0) { 785 (void) alarm(0); 786 return (ret); 787 } 788 789 (void) alarm(0); 790 } else { 791 /* 792 * Read the extra number of bytes 793 */ 794 m = byte_cnt - (read_tail - read_head); 795 if ((ret = vldc_read(chnl_fd, 796 read_tail, m)) <= 0) { 797 return (ret); 798 } 799 } 800 read_tail += ret; 801 802 /* 803 * copy the requested bytes. 804 */ 805 n = MIN(byte_cnt, (read_tail - read_head)); 806 (void) memcpy(buf, read_head, n); 807 808 read_head += n; 809 810 return (n); 811 } 812 813 /* 814 * Issue read from the driver until byet_cnt number 815 * of bytes are present in read buffer. Do not 816 * move the read head. 817 */ 818 static int 819 pcp_update_read_area(int byte_cnt) 820 { 821 int ret; 822 int n, i; 823 824 if (byte_cnt < 0 || byte_cnt > mtu_size) { 825 return (PCPL_INVALID_ARGS); 826 } 827 828 /* 829 * initialization of local read buffer 830 * from which the stream read requests are serviced. 831 */ 832 if (read_area == NULL) { 833 read_area = (uint8_t *)umem_zalloc(READ_AREA_SIZE, 834 UMEM_DEFAULT); 835 if (read_area == NULL) { 836 return (PCPL_MALLOC_FAIL); 837 } 838 read_head = read_area; 839 read_tail = read_area; 840 } 841 842 /* 843 * if we already have sufficient data in the buffer, 844 * just return 845 */ 846 if (byte_cnt <= (read_tail - read_head)) { 847 return (byte_cnt); 848 } 849 850 /* 851 * if the request is not satisfied from the buffered data, then move the 852 * remaining data to front of the buffer and read new data. 853 */ 854 for (i = 0; i < (read_tail - read_head); ++i) { 855 read_area[i] = read_head[i]; 856 } 857 read_head = read_area; 858 read_tail = read_head + i; 859 860 n = byte_cnt - (read_tail - read_head); 861 862 if ((ret = vldc_read(chnl_fd, 863 read_tail, n)) <= 0) { 864 return (ret); 865 } 866 read_tail += ret; 867 868 /* 869 * Return the number of bytes we could read 870 */ 871 n = MIN(byte_cnt, (read_tail - read_head)); 872 873 return (n); 874 } 875 876 /* 877 * This function is slight different from pcp_peek. The peek requests are first 878 * serviced from local read buffer, if data is available. If the peek request 879 * is not serviceble from local read buffer, then the data is peeked from 880 * channel buffer. This function is mainly used for proper protocol framing 881 * error handling. 882 */ 883 static int 884 pcp_peek_read(uint8_t *buf, int byte_cnt) 885 { 886 int n, m, i; 887 888 if (byte_cnt < 0 || byte_cnt > mtu_size) { 889 return (PCPL_INVALID_ARGS); 890 } 891 892 /* 893 * initialization of peek_read buffer. 894 */ 895 if (peek_read_area == NULL) { 896 peek_read_area = (uint8_t *)umem_zalloc(PEEK_READ_AREA_SIZE, 897 UMEM_DEFAULT); 898 if (peek_read_area == NULL) { 899 return (PCPL_MALLOC_FAIL); 900 } 901 peek_read_head = peek_read_area; 902 peek_read_tail = peek_read_area; 903 } 904 905 /* 906 * if we already have the data in local read buffer then copy 907 * from local buffer it self w/out calling new peek 908 */ 909 if (byte_cnt <= (read_tail - read_head)) { 910 (void) memcpy(buf, read_head, byte_cnt); 911 return (byte_cnt); 912 } 913 914 /* 915 * if the request is not satisfied from local read buffer, then first 916 * copy the remaining data in local read buffer to peek_read_area and 917 * then issue new peek. 918 */ 919 for (i = 0; i < (read_tail - read_head); ++i) { 920 peek_read_area[i] = read_head[i]; 921 } 922 peek_read_head = peek_read_area; 923 peek_read_tail = peek_read_head + i; 924 925 /* 926 * do a peek to see how much data is available and read complete data. 927 */ 928 929 if ((m = pcp_peek(peek_read_tail, mtu_size)) < 0) { 930 return (m); 931 } 932 peek_read_tail += m; 933 934 /* 935 * copy the requested bytes 936 */ 937 n = MIN(byte_cnt, (peek_read_tail - peek_read_head)); 938 (void) memcpy(buf, peek_read_head, n); 939 940 return (n); 941 } 942 943 /* 944 * Send Request Message Header. 945 */ 946 static int 947 pcp_send_req_msg_hdr(pcp_req_msg_hdr_t *req_hdr) 948 { 949 pcp_req_msg_hdr_t *hdrp; 950 int hdr_sz; 951 int ret; 952 953 hdr_sz = sizeof (pcp_req_msg_hdr_t); 954 if ((hdrp = (pcp_req_msg_hdr_t *)umem_zalloc(hdr_sz, 955 UMEM_DEFAULT)) == NULL) { 956 return (PCPL_MALLOC_FAIL); 957 } 958 959 hdrp->magic_num = htonl(req_hdr->magic_num); 960 hdrp->proto_ver = req_hdr->proto_ver; 961 hdrp->msg_type = req_hdr->msg_type; 962 hdrp->sub_type = req_hdr->sub_type; 963 hdrp->rsvd_pad = htons(req_hdr->rsvd_pad); 964 hdrp->xid = htonl(req_hdr->xid); 965 hdrp->timeout = htonl(req_hdr->timeout); 966 hdrp->msg_len = htonl(req_hdr->msg_len); 967 hdrp->msg_cksum = htons(req_hdr->msg_cksum); 968 hdrp->hdr_cksum = htons(req_hdr->hdr_cksum); 969 970 if ((ret = pcp_io_op((char *)hdrp, hdr_sz, PCPL_IO_OP_WRITE)) != 0) { 971 umem_free(hdrp, hdr_sz); 972 return (ret); 973 } 974 umem_free(hdrp, hdr_sz); 975 return (PCP_OK); 976 } 977 978 /* 979 * Receive Response message header. 980 */ 981 static int 982 pcp_recv_resp_msg_hdr(pcp_resp_msg_hdr_t *resp_hdr) 983 { 984 uint32_t magic_num; 985 uint8_t proto_ver; 986 uint8_t msg_type; 987 uint8_t sub_type; 988 uint8_t rsvd_pad; 989 uint32_t xid; 990 uint32_t timeout; 991 uint32_t msg_len; 992 uint32_t status; 993 uint16_t msg_cksum; 994 uint16_t hdr_cksum; 995 int ret; 996 997 if (resp_hdr == NULL) { 998 return (PCPL_INVALID_ARGS); 999 } 1000 1001 /* 1002 * handle protocol framing errors. 1003 * pcp_frame_error_handle() returns when proper frame arrived 1004 * (magic seq) or if an error happens while reading data from 1005 * channel. 1006 */ 1007 if (xport_type == GLVC_NON_STREAM) 1008 ret = pcp_frame_error_handle(); 1009 else 1010 ret = pcp_vldc_frame_error_handle(); 1011 1012 if (ret != 0) 1013 return (PCPL_FRAME_ERROR); 1014 1015 /* read magic number first */ 1016 if ((ret = pcp_io_op(&magic_num, sizeof (magic_num), 1017 PCPL_IO_OP_READ)) != 0) { 1018 return (ret); 1019 } 1020 1021 magic_num = ntohl(magic_num); 1022 1023 if (magic_num != PCP_MAGIC_NUM) { 1024 return (PCPL_FRAME_ERROR); 1025 } 1026 1027 /* read version field */ 1028 if ((ret = pcp_io_op(&proto_ver, sizeof (proto_ver), 1029 PCPL_IO_OP_READ)) != 0) { 1030 return (ret); 1031 } 1032 1033 /* check protocol version */ 1034 if (proto_ver != PCP_PROT_VER_1) { 1035 return (PCPL_PROT_ERROR); 1036 } 1037 1038 /* Read message type */ 1039 if ((ret = pcp_io_op(&msg_type, sizeof (msg_type), 1040 PCPL_IO_OP_READ)) != 0) { 1041 return (ret); 1042 } 1043 1044 /* Read message sub type */ 1045 if ((ret = pcp_io_op(&sub_type, sizeof (sub_type), 1046 PCPL_IO_OP_READ)) != 0) { 1047 return (ret); 1048 } 1049 1050 /* Read rcvd_pad bits */ 1051 if ((ret = pcp_io_op(&rsvd_pad, sizeof (rsvd_pad), 1052 PCPL_IO_OP_READ)) != 0) { 1053 return (ret); 1054 } 1055 1056 /* receive transaction id */ 1057 if ((ret = pcp_io_op(&xid, sizeof (xid), 1058 PCPL_IO_OP_READ)) != 0) { 1059 return (ret); 1060 } 1061 1062 xid = ntohl(xid); 1063 1064 /* receive timeout value */ 1065 if ((ret = pcp_io_op(&timeout, sizeof (timeout), 1066 PCPL_IO_OP_READ)) != 0) { 1067 return (ret); 1068 } 1069 1070 timeout = ntohl(timeout); 1071 1072 /* receive message length */ 1073 if ((ret = pcp_io_op(&msg_len, sizeof (msg_len), 1074 PCPL_IO_OP_READ)) != 0) { 1075 return (ret); 1076 } 1077 1078 msg_len = ntohl(msg_len); 1079 1080 /* receive status field */ 1081 if ((ret = pcp_io_op(&status, sizeof (status), 1082 PCPL_IO_OP_READ)) != 0) { 1083 return (ret); 1084 } 1085 1086 status = ntohl(status); 1087 1088 /* receive message checksum */ 1089 if ((ret = pcp_io_op(&msg_cksum, sizeof (msg_cksum), 1090 PCPL_IO_OP_READ)) != 0) { 1091 return (ret); 1092 } 1093 1094 msg_cksum = ntohs(msg_cksum); 1095 1096 /* receive header checksum */ 1097 if ((ret = pcp_io_op(&hdr_cksum, sizeof (hdr_cksum), 1098 PCPL_IO_OP_READ)) != 0) { 1099 return (ret); 1100 } 1101 1102 hdr_cksum = ntohs(hdr_cksum); 1103 1104 /* copy to resp_hdr */ 1105 1106 resp_hdr->magic_num = magic_num; 1107 resp_hdr->proto_ver = proto_ver; 1108 resp_hdr->msg_type = msg_type; 1109 resp_hdr->sub_type = sub_type; 1110 resp_hdr->rsvd_pad = rsvd_pad; 1111 resp_hdr->xid = xid; 1112 resp_hdr->timeout = timeout; 1113 resp_hdr->msg_len = msg_len; 1114 resp_hdr->status = status; 1115 resp_hdr->msg_cksum = msg_cksum; 1116 resp_hdr->hdr_cksum = hdr_cksum; 1117 1118 return (PCP_OK); 1119 } 1120 1121 /* 1122 * Get next xid for including in request message. 1123 * Every request and response message are matched 1124 * for same xid. 1125 */ 1126 1127 static uint32_t 1128 pcp_get_xid(void) 1129 { 1130 uint32_t ret; 1131 struct timeval tv; 1132 static boolean_t xid_initialized = B_FALSE; 1133 1134 if (xid_initialized == B_FALSE) { 1135 xid_initialized = B_TRUE; 1136 /* 1137 * starting xid is initialized to a different value everytime 1138 * user application is restarted so that user apps will not 1139 * receive previous session's packets. 1140 * 1141 * Note: The algorithm for generating initial xid is partially 1142 * taken from Solaris rpc code. 1143 */ 1144 (void) gettimeofday(&tv, NULL); 1145 msg_xid = (uint32_t)((tv.tv_sec << 20) | 1146 (tv.tv_usec >> 10)); 1147 } 1148 1149 ret = msg_xid++; 1150 1151 /* zero xid is not allowed */ 1152 if (ret == 0) 1153 ret = msg_xid++; 1154 1155 return (ret); 1156 } 1157 1158 /* 1159 * This function handles channel framing errors. It waits until proper 1160 * frame with starting sequence as magic numder (0xAFBCAFA0) 1161 * is arrived. It removes unexpected data (before the magic number sequence) 1162 * on the channel. It returns when proper magic number sequence is seen 1163 * or when any failure happens while reading/peeking the channel. 1164 */ 1165 static int 1166 pcp_frame_error_handle(void) 1167 { 1168 uint8_t magic_num_buf[4]; 1169 int ispresent = 0; 1170 uint32_t net_magic_num; /* magic byte in network byte order */ 1171 uint32_t host_magic_num = PCP_MAGIC_NUM; 1172 uint8_t buf[2]; 1173 1174 net_magic_num = htonl(host_magic_num); 1175 (void) memcpy(magic_num_buf, (uint8_t *)&net_magic_num, 4); 1176 1177 while (!ispresent) { 1178 /* 1179 * Check if next four bytes matches pcp magic number. 1180 * if mathing not found, discard 1 byte and continue checking. 1181 */ 1182 if (!check_magic_byte_presence(4, &magic_num_buf[0], 1183 &ispresent)) { 1184 if (!ispresent) { 1185 /* remove 1 byte */ 1186 (void) pcp_io_op(buf, 1, PCPL_IO_OP_READ); 1187 } 1188 } else { 1189 return (-1); 1190 } 1191 } 1192 1193 return (0); 1194 } 1195 1196 /* 1197 * This function handles channel framing errors. It waits until proper 1198 * frame with starting sequence as magic numder (0xAFBCAFA0) 1199 * is arrived. It removes unexpected data (before the magic number sequence) 1200 * on the channel. It returns when proper magic number sequence is seen 1201 * or when any failure happens while reading/peeking the channel. 1202 */ 1203 static int 1204 pcp_vldc_frame_error_handle(void) 1205 { 1206 uint8_t magic_num_buf[4]; 1207 uint32_t net_magic_num; /* magic byte in network byte order */ 1208 uint32_t host_magic_num = PCP_MAGIC_NUM; 1209 int found_magic = 0; 1210 1211 net_magic_num = htonl(host_magic_num); 1212 (void) memcpy(magic_num_buf, (uint8_t *)&net_magic_num, 4); 1213 1214 /* 1215 * For vldc, we need to read whatever data is available and 1216 * advance the read pointer one byte at a time until we get 1217 * the magic word. When this function is invoked, we do not 1218 * have any byte in the read buffer. 1219 */ 1220 1221 /* 1222 * Keep reading until we find the matching magic number 1223 */ 1224 while (!found_magic) { 1225 while ((read_tail - read_head) < sizeof (host_magic_num)) { 1226 if (pcp_update_read_area(sizeof (host_magic_num)) < 0) 1227 return (-1); 1228 } 1229 1230 /* 1231 * We should have at least 4 bytes in read buffer. Check 1232 * if the magic number can be matched 1233 */ 1234 if (memcmp(read_head, magic_num_buf, 1235 sizeof (host_magic_num))) { 1236 read_head += 1; 1237 } else { 1238 found_magic = 1; 1239 } 1240 } 1241 1242 return (0); 1243 } 1244 1245 /* 1246 * checks whether certain byte sequence is present in the data stream. 1247 */ 1248 static int 1249 check_magic_byte_presence(int byte_cnt, uint8_t *byte_seq, int *ispresent) 1250 { 1251 int ret, i; 1252 uint8_t buf[4]; 1253 1254 if ((ret = pcp_peek_read(buf, byte_cnt)) < 0) { 1255 return (ret); 1256 } 1257 1258 /* 'byte_cnt' bytes not present */ 1259 if (ret != byte_cnt) { 1260 *ispresent = 0; 1261 return (0); 1262 } 1263 1264 for (i = 0; i < byte_cnt; ++i) { 1265 if (buf[i] != byte_seq[i]) { 1266 *ispresent = 0; 1267 return (0); 1268 } 1269 } 1270 *ispresent = 1; 1271 1272 return (0); 1273 } 1274 1275 /* 1276 * 16-bit simple internet checksum 1277 */ 1278 static uint16_t 1279 checksum(uint16_t *addr, int32_t count) 1280 { 1281 /* 1282 * Compute Internet Checksum for "count" bytes 1283 * beginning at location "addr". 1284 */ 1285 1286 register uint32_t sum = 0; 1287 1288 while (count > 1) { 1289 /* This is the inner loop */ 1290 sum += *(unsigned short *)addr++; 1291 count -= 2; 1292 } 1293 1294 /* Add left-over byte, if any */ 1295 if (count > 0) 1296 sum += * (unsigned char *)addr; 1297 1298 /* Fold 32-bit sum to 16 bits */ 1299 while (sum >> 16) 1300 sum = (sum & 0xffff) + (sum >> 16); 1301 1302 sum = (~sum) & 0xffff; 1303 if (sum == 0) 1304 sum = 0xffff; 1305 1306 return (sum); 1307 } 1308 1309 /* 1310 * cleanup the channel if any data is hanging in 1311 * channel buffers. 1312 */ 1313 static int 1314 pcp_cleanup(int channel_fd) 1315 { 1316 int ret; 1317 glvc_xport_msg_peek_t peek_ctrl; 1318 int n, done; 1319 uint8_t *buf = NULL; 1320 int retry = 0; 1321 1322 1323 buf = (uint8_t *)umem_zalloc((mtu_size), UMEM_DEFAULT); 1324 if (buf == NULL) { 1325 return (PCPL_MALLOC_FAIL); 1326 } 1327 1328 peek_ctrl.buf = (caddr_t)buf; 1329 peek_ctrl.buflen = mtu_size; 1330 peek_ctrl.flags = 0; 1331 1332 /* 1333 * set sig jmp location 1334 */ 1335 if (sigsetjmp(jmpbuf, 1)) { 1336 umem_free(buf, mtu_size); 1337 return (PCPL_GLVC_TIMEOUT); 1338 } 1339 1340 done = 0; 1341 while (!done) { 1342 1343 (void) alarm(PCP_CLEANUP_TIMEOUT); 1344 if ((ret = ioctl(channel_fd, GLVC_XPORT_IOCTL_DATA_PEEK, 1345 &peek_ctrl)) < 0) { 1346 (void) alarm(0); 1347 done = 1; 1348 continue; 1349 } 1350 (void) alarm(0); 1351 1352 n = peek_ctrl.buflen; 1353 1354 if (n <= 0 && retry > 2) { 1355 done = 1; 1356 continue; 1357 } else if (n <= 0) { 1358 ++retry; 1359 continue; 1360 } 1361 1362 /* remove data from channel */ 1363 (void) alarm(PCP_CLEANUP_TIMEOUT); 1364 if ((ret = read(channel_fd, buf, n)) < 0) { 1365 (void) alarm(0); 1366 done = 1; 1367 continue; 1368 } 1369 (void) alarm(0); 1370 } 1371 1372 umem_free(buf, mtu_size); 1373 return (ret); 1374 } 1375 1376 static int 1377 vldc_write(int fd, uint8_t *bufp, int size) 1378 { 1379 int res; 1380 int left = size; 1381 pollfd_t pollfd; 1382 1383 pollfd.events = POLLOUT; 1384 pollfd.revents = 0; 1385 pollfd.fd = fd; 1386 1387 /* 1388 * Poll for the vldc channel to be ready 1389 */ 1390 if (poll(&pollfd, 1, glvc_timeout * MILLISEC) <= 0) { 1391 return (-1); 1392 } 1393 1394 do { 1395 if ((res = write(fd, bufp, left)) <= 0) { 1396 if (errno != EWOULDBLOCK) { 1397 return (res); 1398 } 1399 } else { 1400 bufp += res; 1401 left -= res; 1402 } 1403 } while (left > 0); 1404 1405 /* 1406 * Return number of bytes actually written 1407 */ 1408 return (size - left); 1409 } 1410 1411 /* 1412 * Keep reading until we get the specified number of bytes 1413 */ 1414 static int 1415 vldc_read(int fd, uint8_t *bufp, int size) 1416 { 1417 int res; 1418 int left = size; 1419 1420 struct pollfd fds[1]; 1421 1422 fds[0].events = POLLIN | POLLPRI; 1423 fds[0].revents = 0; 1424 fds[0].fd = fd; 1425 1426 if (poll(fds, 1, glvc_timeout * MILLISEC) <= 0) { 1427 return (-1); 1428 } 1429 1430 while (left > 0) { 1431 res = read(fd, bufp, left); 1432 /* return on error or short read */ 1433 if ((res == 0) || ((res < 0) && 1434 (errno == EAGAIN))) { 1435 /* poll until the read is unblocked */ 1436 if ((poll(fds, 1, glvc_timeout * MILLISEC)) < 0) 1437 return (-1); 1438 1439 continue; 1440 } else 1441 if (res < 0) { 1442 /* unrecoverable error */ 1443 1444 return (-1); 1445 } else { 1446 bufp += res; 1447 left -= res; 1448 } 1449 } 1450 1451 return (size - left); 1452 } 1453