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