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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * sock_test.c. Implementing a CLI for inetboot testing. 27 */ 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <sys/types.h> 31 #include "socket_impl.h" 32 #include "socket_inet.h" 33 #include <sys/socket.h> 34 #include <sys/sysmacros.h> 35 #include <netinet/in_systm.h> 36 #include <sys/promif.h> 37 #include <sys/salib.h> 38 #include <ctype.h> 39 #include <errno.h> 40 #include <netinet/in.h> 41 #include "tcp_inet.h" 42 #include "ipv4.h" 43 #include <netinet/tcp.h> 44 45 static int atoi(const char *); 46 static int st_accept(void); 47 static int st_bind(void); 48 static int st_connect(void); 49 static int st_echo(void); 50 static int st_getsockname(void); 51 static int st_getsockopt(void); 52 static int st_get_addr_and_port(in_addr_t *, unsigned short *); 53 static int st_get_buf_and_cnt(char **, int *); 54 static int st_listen(void); 55 static int st_match_option(char *, int *, int *); 56 static int st_send(void); 57 static int st_sendto(void); 58 static int st_recv(void); 59 static int st_recvfrom(void); 60 static int st_set_addr(void); 61 static int st_set_netmask(void); 62 static int st_set_router(void); 63 static int st_setsockopt(void); 64 static int st_socket(void); 65 static int st_sock_close(void); 66 static int st_tcp_tw_report(void); 67 static int st_toggle_promiscuous(void); 68 static int st_use_obp(void); 69 70 /* Wrapper for socket calls. */ 71 static int st_local_accept(int, struct sockaddr *, socklen_t *); 72 static int st_local_bind(int, const struct sockaddr *, socklen_t); 73 static int st_local_connect(int, const struct sockaddr *, socklen_t); 74 static int st_local_getsockname(int, struct sockaddr *, socklen_t *); 75 static int st_local_getsockopt(int, int, int, void *, socklen_t *); 76 static int st_local_listen(int, int); 77 static int st_local_recv(int, void *, size_t, int); 78 static int st_local_recvfrom(int, void *, size_t, int, struct sockaddr *, 79 socklen_t *); 80 static int st_local_send(int, const void *, size_t, int); 81 static int st_local_sendto(int, const void *, size_t, int, 82 const struct sockaddr *, socklen_t); 83 static int st_local_setsockopt(int, int, int, const void *, socklen_t); 84 static int st_local_socket(int, int, int); 85 static int st_local_socket_close(int); 86 87 struct sock_test_cmd_s { 88 char *st_cmd; 89 int (*st_fn)(void); 90 }; 91 92 static struct sock_test_cmd_s st_cmds[] = { 93 { "set_addr", st_set_addr}, 94 { "set_netmask", st_set_netmask}, 95 { "set_router", st_set_router}, 96 { "socket", st_socket }, 97 { "bind", st_bind }, 98 { "accept", st_accept }, 99 { "connect", st_connect }, 100 { "listen", st_listen }, 101 { "send", st_send }, 102 { "sendto", st_sendto }, 103 { "recv", st_recv }, 104 { "recvfrom", st_recvfrom }, 105 { "setsockopt", st_setsockopt }, 106 { "getsockopt", st_getsockopt }, 107 { "getsockname", st_getsockname }, 108 { "close", st_sock_close }, 109 { "echo", st_echo }, 110 { "toggle_promiscous", st_toggle_promiscuous}, 111 { "use_obp", st_use_obp}, 112 { "tcp_tw_report", st_tcp_tw_report}, 113 { NULL, NULL } 114 }; 115 116 struct so_option_string_s { 117 char *so_name; 118 int so_opt; 119 int so_opt_level; 120 } so_option_array[] = { 121 { "rcvtimeo", SO_RCVTIMEO, SOL_SOCKET }, 122 { "dontroute", SO_DONTROUTE, SOL_SOCKET }, 123 { "reuseaddr", SO_REUSEADDR, SOL_SOCKET }, 124 { "rcvbuf", SO_RCVBUF, SOL_SOCKET }, 125 { "sndbuf", SO_SNDBUF, SOL_SOCKET }, 126 { NULL, 0 } 127 }; 128 129 #define NO_OPENED_SOCKET -1 130 131 /* Right now, we only allow one socket at one time. */ 132 static int g_sock_fd = NO_OPENED_SOCKET; 133 static int save_g_sock_fd = NO_OPENED_SOCKET; 134 135 /* Boolean to decide if OBP network routines should be used. */ 136 static boolean_t use_obp = B_FALSE; 137 138 139 /* 140 * The following routines are wrappers for the real socket routines. The 141 * boolean use_obp is used to decide whether the real socket routines is 142 * called or the "equivalent" OBP provided routines should be called. 143 */ 144 static int 145 st_local_socket(int domain, int type, int protocol) 146 { 147 if (!use_obp) { 148 return (socket(domain, type, protocol)); 149 } else { 150 return (0); 151 } 152 } 153 154 static int 155 st_local_socket_close(int sd) 156 { 157 if (!use_obp) { 158 return (socket_close(sd)); 159 } else { 160 return (0); 161 } 162 } 163 164 static int 165 st_local_accept(int sd, struct sockaddr *addr, socklen_t *addr_len) 166 { 167 if (!use_obp) { 168 return (accept(sd, addr, addr_len)); 169 } else { 170 return (0); 171 } 172 } 173 174 static int 175 st_local_bind(int sd, const struct sockaddr *name, socklen_t namelen) 176 { 177 if (!use_obp) { 178 return (bind(sd, name, namelen)); 179 } else { 180 return (0); 181 } 182 } 183 184 static int 185 st_local_connect(int sd, const struct sockaddr *addr, socklen_t addr_len) 186 { 187 if (!use_obp) { 188 return (connect(sd, addr, addr_len)); 189 } else { 190 return (0); 191 } 192 } 193 194 static int 195 st_local_listen(int sd, int backlog) 196 { 197 if (!use_obp) { 198 return (listen(sd, backlog)); 199 } else { 200 return (0); 201 } 202 } 203 204 static int 205 st_local_send(int sd, const void *msg, size_t len, int flags) 206 { 207 if (!use_obp) { 208 return (send(sd, msg, len, flags)); 209 } else { 210 return (0); 211 } 212 } 213 214 static int 215 st_local_sendto(int sd, const void *msg, size_t len, int flags, 216 const struct sockaddr *to, socklen_t tolen) 217 { 218 if (!use_obp) { 219 return (sendto(sd, msg, len, flags, to, tolen)); 220 } else { 221 return (0); 222 } 223 } 224 225 static int 226 st_local_recv(int sd, void *buf, size_t len, int flags) 227 { 228 if (!use_obp) { 229 return (recv(sd, buf, len, flags)); 230 } else { 231 return (0); 232 } 233 } 234 235 static int 236 st_local_recvfrom(int sd, void *buf, size_t len, int flags, 237 struct sockaddr *from, socklen_t *fromlen) 238 { 239 if (!use_obp) { 240 return (recvfrom(sd, buf, len, flags, from, fromlen)); 241 } else { 242 return (0); 243 } 244 } 245 246 static int 247 st_local_getsockname(int sd, struct sockaddr *name, socklen_t *namelen) 248 { 249 if (!use_obp) { 250 return (getsockname(sd, name, namelen)); 251 } else { 252 return (0); 253 } 254 } 255 256 257 static int 258 st_local_getsockopt(int sd, int level, int option, void *optval, 259 socklen_t *optlen) 260 { 261 if (!use_obp) { 262 return (getsockopt(sd, level, option, optval, optlen)); 263 } else { 264 return (0); 265 } 266 } 267 268 static int 269 st_local_setsockopt(int sd, int level, int option, const void *optval, 270 socklen_t optlen) 271 { 272 if (!use_obp) { 273 return (setsockopt(sd, level, option, optval, optlen)); 274 } else { 275 return (0); 276 } 277 } 278 279 static int 280 atoi(const char *p) 281 { 282 int n; 283 int c = *p++, neg = 0; 284 285 while (isspace(c)) { 286 c = *p++; 287 } 288 if (!isdigit(c)) { 289 switch (c) { 290 case '-': 291 neg++; 292 /* FALLTHROUGH */ 293 case '+': 294 c = *p++; 295 } 296 } 297 for (n = 0; isdigit(c); c = *p++) { 298 n *= 10; /* two steps to avoid unnecessary overflow */ 299 n += '0' - c; /* accum neg to avoid surprises at MAX */ 300 } 301 return (neg ? n : -n); 302 } 303 304 int 305 st_interpret(char *buf) 306 { 307 char *cmd; 308 int i; 309 310 if ((cmd = strtok(buf, " ")) == NULL) 311 return (-1); 312 313 for (i = 0; st_cmds[i].st_cmd != NULL; i++) { 314 if (strcmp(cmd, st_cmds[i].st_cmd) == 0) { 315 return (st_cmds[i].st_fn()); 316 } 317 } 318 printf("! Unknown command: %s\n", cmd); 319 return (-1); 320 } 321 322 323 static int 324 st_socket(void) 325 { 326 char *type; 327 328 if ((type = strtok(NULL, " ")) == NULL) { 329 printf("! usage: socket type\n"); 330 return (-1); 331 } 332 if (g_sock_fd != NO_OPENED_SOCKET) { 333 printf("! Cannot open more than 1 socket\n"); 334 return (-1); 335 } 336 337 if (strcmp(type, "stream") == 0) { 338 if ((g_sock_fd = st_local_socket(AF_INET, SOCK_STREAM, 339 0)) < 0) { 340 printf("! Error in opening TCP socket: %d\n", errno); 341 return (-1); 342 } else { 343 printf("@ TCP socket opened\n"); 344 } 345 } else if (strcmp(type, "dgram") == 0) { 346 if ((g_sock_fd = st_local_socket(AF_INET, SOCK_DGRAM, 347 0)) < 0) { 348 printf("! Error in opening UDP socket: %d\n", errno); 349 return (-1); 350 } else { 351 printf("@ UDP socket opened\n"); 352 } 353 } else if (strcmp(type, "raw") == 0) { 354 if ((g_sock_fd = st_local_socket(AF_INET, SOCK_RAW, 0)) < 0) { 355 printf("! Error in opening RAW socket: %d\n", errno); 356 return (-1); 357 } else { 358 printf("@ RAW socket opened\n"); 359 } 360 } else { 361 printf("! Unknown socket type: %s\n", type); 362 return (-1); 363 } 364 365 return (0); 366 } 367 368 static int 369 st_set_addr(void) 370 { 371 char *tmp; 372 struct in_addr addr; 373 374 tmp = strtok(NULL, " "); 375 if (tmp == NULL) { 376 printf("! No address given\n"); 377 return (-1); 378 } 379 if ((addr.s_addr = inet_addr(tmp)) == (uint32_t)-1) { 380 printf("! Malformed address\n"); 381 return (-1); 382 } 383 384 ipv4_setipaddr(&addr); 385 printf("@ IP address %s set\n", inet_ntoa(addr)); 386 387 return (0); 388 } 389 390 static int 391 st_set_netmask(void) 392 { 393 char *tmp; 394 struct in_addr addr; 395 396 tmp = strtok(NULL, " "); 397 if (tmp == NULL) { 398 printf("! No netmask given\n"); 399 return (-1); 400 } 401 if ((addr.s_addr = inet_addr(tmp)) == (uint32_t)-1) { 402 printf("! Malformed netmask\n"); 403 return (-1); 404 } 405 406 ipv4_setnetmask(&addr); 407 printf("@ Netmask %s set\n", inet_ntoa(addr)); 408 409 return (0); 410 } 411 412 static int 413 st_set_router(void) 414 { 415 char *tmp; 416 struct in_addr addr; 417 418 tmp = strtok(NULL, " "); 419 if (tmp == NULL) { 420 printf("! No router address given\n"); 421 return (-1); 422 } 423 if ((addr.s_addr = inet_addr(tmp)) == (uint32_t)-1) { 424 printf("! Malformed router address\n"); 425 return (-1); 426 } 427 428 ipv4_setdefaultrouter(&addr); 429 if (ipv4_route(IPV4_ADD_ROUTE, RT_DEFAULT, NULL, &addr) < 0) { 430 printf("! Cannot add default route\n"); 431 } else { 432 printf("@ Default router %s set\n", inet_ntoa(addr)); 433 } 434 435 return (0); 436 } 437 438 static int 439 st_get_addr_and_port(in_addr_t *addr, unsigned short *port) 440 { 441 char *tmp; 442 443 if (g_sock_fd == NO_OPENED_SOCKET) { 444 printf("! No socket opened\n"); 445 return (-1); 446 } 447 448 tmp = strtok(NULL, "/"); 449 if (tmp == NULL) { 450 printf("! No address given\n"); 451 return (-1); 452 } 453 if ((*addr = inet_addr(tmp)) == (uint32_t)-1) { 454 printf("! Malformed address\n"); 455 return (-1); 456 } 457 458 tmp = strtok(NULL, " "); 459 if (tmp == NULL) { 460 printf("! No port given\n"); 461 return (-1); 462 } 463 *port = htons(atoi(tmp)); 464 465 return (0); 466 } 467 468 static int 469 st_bind(void) 470 { 471 struct sockaddr_in local_addr; 472 473 if (st_get_addr_and_port(&(local_addr.sin_addr.s_addr), 474 &(local_addr.sin_port)) < 0) { 475 return (-1); 476 } 477 478 local_addr.sin_family = AF_INET; 479 if (st_local_bind(g_sock_fd, (struct sockaddr *)&local_addr, 480 sizeof (local_addr)) < 0) { 481 printf("! Bind failed: %d\n", errno); 482 return (-1); 483 } 484 printf("@ Socket bound to %s/%d\n", inet_ntoa(local_addr.sin_addr), 485 ntohs(local_addr.sin_port)); 486 return (0); 487 } 488 489 static int 490 st_listen(void) 491 { 492 char *tmp; 493 494 if (g_sock_fd == NO_OPENED_SOCKET) { 495 printf("! No socket opened\n"); 496 return (-1); 497 } 498 if ((tmp = strtok(NULL, " ")) == NULL) { 499 printf("! No backlog given\n"); 500 return (-1); 501 } 502 if (st_local_listen(g_sock_fd, atoi(tmp)) < 0) { 503 printf("! Listen failed: %d\n", errno); 504 return (-1); 505 } 506 printf("@ Listen succeeded\n"); 507 return (0); 508 } 509 510 static int 511 st_accept(void) 512 { 513 struct sockaddr_in addr; 514 socklen_t addr_len; 515 int sd; 516 517 if (g_sock_fd == NO_OPENED_SOCKET) { 518 printf("! No socket opened\n"); 519 return (-1); 520 } 521 addr_len = sizeof (struct sockaddr_in); 522 if ((sd = st_local_accept(g_sock_fd, (struct sockaddr *)&addr, 523 &addr_len)) < 0) { 524 printf("! Accept failed: %d\n", errno); 525 return (-1); 526 } 527 printf("@ Accept succeeded from %s:%d. Socket descriptor saved\n", 528 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 529 save_g_sock_fd = g_sock_fd; 530 g_sock_fd = sd; 531 return (0); 532 } 533 534 static int 535 st_connect(void) 536 { 537 struct sockaddr_in peer_addr; 538 539 if (st_get_addr_and_port(&(peer_addr.sin_addr.s_addr), 540 &(peer_addr.sin_port)) < 0) { 541 return (-1); 542 } 543 544 peer_addr.sin_family = AF_INET; 545 if (st_local_connect(g_sock_fd, (struct sockaddr *)&peer_addr, 546 sizeof (peer_addr)) < 0) { 547 printf("! Connect failed: %d\n", errno); 548 return (-1); 549 } 550 printf("@ Socket connected to %s/%d\n", inet_ntoa(peer_addr.sin_addr), 551 ntohs(peer_addr.sin_port)); 552 553 return (0); 554 } 555 556 static int 557 st_get_buf_and_cnt(char **buf, int *send_cnt) 558 { 559 char *cnt; 560 561 if ((*buf = strtok(NULL, " ")) == NULL) { 562 printf("! No send buffer\n"); 563 return (-1); 564 } 565 if ((cnt = strtok(NULL, " ")) == NULL) { 566 printf("! Missing send length\n"); 567 return (-1); 568 } 569 570 if ((*send_cnt = atoi(cnt)) < 0) { 571 printf("! Invalid send count\n"); 572 return (-1); 573 } 574 return (0); 575 } 576 577 static int 578 st_send(void) 579 { 580 char *buf; 581 int send_cnt; 582 583 if (g_sock_fd == NO_OPENED_SOCKET) { 584 printf("! No socket opened\n"); 585 return (-1); 586 } 587 588 if (st_get_buf_and_cnt(&buf, &send_cnt) < 0) 589 return (-1); 590 591 if ((send_cnt = st_local_send(g_sock_fd, buf, send_cnt, 0)) < 0) { 592 printf("! Send failed: %d\n", errno); 593 return (-1); 594 } 595 printf("@ Send %d bytes\n", send_cnt); 596 597 return (0); 598 } 599 600 static int 601 st_sendto(void) 602 { 603 struct sockaddr_in peer_addr; 604 char *buf; 605 int send_cnt; 606 607 if (st_get_addr_and_port(&(peer_addr.sin_addr.s_addr), 608 &(peer_addr.sin_port)) < 0) { 609 return (-1); 610 } 611 peer_addr.sin_family = AF_INET; 612 613 if (st_get_buf_and_cnt(&buf, &send_cnt) < 0) 614 return (-1); 615 616 if ((send_cnt = st_local_sendto(g_sock_fd, buf, send_cnt, 0, 617 (struct sockaddr *)&peer_addr, sizeof (peer_addr))) < 0) { 618 printf("! Sendto failed: %d\n", errno); 619 return (-1); 620 } 621 printf("@ Send %d bytes\n", send_cnt); 622 623 return (0); 624 } 625 626 static int 627 st_recv(void) 628 { 629 char *tmp; 630 char *buf; 631 int buf_len, ret; 632 633 if (g_sock_fd == NO_OPENED_SOCKET) { 634 printf("! No socket opened\n"); 635 return (-1); 636 } 637 638 if ((tmp = strtok(NULL, " ")) == NULL) { 639 printf("! No buffer len given\n"); 640 return (-1); 641 } 642 buf_len = atoi(tmp); 643 644 if ((buf = bkmem_zalloc(buf_len)) == NULL) { 645 printf("! Cannot allocate buffer: %d\n", errno); 646 return (-1); 647 } 648 if ((ret = st_local_recv(g_sock_fd, buf, buf_len, 0)) <= 0) { 649 if (ret == 0) { 650 printf("@ EOF received: %d\n", errno); 651 return (0); 652 } 653 printf("! Cannot recv: %d\n", errno); 654 return (-1); 655 } 656 printf("@ Bytes received: %d\n", ret); 657 hexdump(buf, ret); 658 bkmem_free(buf, buf_len); 659 return (0); 660 } 661 662 static int 663 st_recvfrom(void) 664 { 665 char *tmp; 666 char *buf; 667 int buf_len, ret; 668 struct sockaddr_in from; 669 socklen_t fromlen; 670 671 if (g_sock_fd == NO_OPENED_SOCKET) { 672 printf("! No socket opened\n"); 673 return (-1); 674 } 675 676 if ((tmp = strtok(NULL, " ")) == NULL) { 677 printf("! No buffer len given\n"); 678 return (-1); 679 } 680 buf_len = atoi(tmp); 681 682 if ((buf = bkmem_zalloc(buf_len)) == NULL) { 683 printf("! Cannot allocate buffer: %d\n", errno); 684 return (-1); 685 } 686 fromlen = sizeof (from); 687 if ((ret = st_local_recvfrom(g_sock_fd, buf, buf_len, 0, 688 (struct sockaddr *)&from, &fromlen)) <= 0) { 689 if (ret == 0) { 690 printf("@ EOF received: %d\n", errno); 691 return (0); 692 } 693 printf("! Cannot recv: %d\n", errno); 694 return (-1); 695 } 696 printf("@ Bytes received from %s/%d: %d\n", 697 inet_ntoa(from.sin_addr), ntohs(from.sin_port), ret); 698 hexdump(buf, ret); 699 bkmem_free(buf, buf_len); 700 return (0); 701 } 702 703 /* 704 * To act as an echo server. Note that it assumes the address and 705 * netmask have been set. 706 */ 707 static int 708 st_echo(void) 709 { 710 char *tmp; 711 int listen_fd, newfd; 712 int echo_port; 713 struct sockaddr_in addr; 714 socklen_t addr_size; 715 int backlog = 20; 716 char *buf; 717 int buf_len, ret, snd_cnt; 718 719 tmp = strtok(NULL, " "); 720 if (tmp == NULL) { 721 printf("! No echo port given\n"); 722 return (-1); 723 } 724 echo_port = atoi(tmp); 725 tmp = strtok(NULL, " "); 726 if (tmp == NULL) { 727 printf("! No buffer size given\n"); 728 return (-1); 729 } 730 buf_len = atoi(tmp); 731 732 /* Create local socket for echo server */ 733 if ((listen_fd = st_local_socket(AF_INET, SOCK_STREAM, 0)) < 0) { 734 printf("! Error in opening TCP socket: %d\n", errno); 735 return (-1); 736 } else { 737 printf("@ Local TCP socket opened\n"); 738 } 739 740 /* Bind local socket */ 741 addr.sin_family = AF_INET; 742 addr.sin_port = htons(echo_port); 743 addr.sin_addr.s_addr = INADDR_ANY; 744 745 if (st_local_bind(listen_fd, (struct sockaddr *)&addr, 746 sizeof (addr)) < 0) { 747 printf("! Bind failed: %d\n", errno); 748 return (-1); 749 } 750 if (st_local_listen(listen_fd, backlog) < 0) { 751 printf("! Listen failed: %d\n", errno); 752 return (-1); 753 } 754 755 addr_size = sizeof (addr); 756 if ((newfd = st_local_accept(listen_fd, (struct sockaddr *)&addr, 757 &addr_size)) < 0) { 758 printf("! Accept failed: %d\n", errno); 759 (void) st_local_socket_close(listen_fd); 760 return (-1); 761 } 762 printf("@ Accepted connection: %s/%d\n", inet_ntoa(addr.sin_addr), 763 ntohs(addr.sin_port)); 764 (void) st_local_socket_close(listen_fd); 765 766 if ((buf = bkmem_zalloc(buf_len)) == NULL) { 767 printf("! Cannot allocate buffer: %d\n", errno); 768 (void) st_local_socket_close(newfd); 769 return (-1); 770 } 771 while ((ret = st_local_recv(newfd, buf, buf_len, 0)) > 0) { 772 printf("@ Bytes received: %d\n", ret); 773 hexdump(buf, ret); 774 if ((snd_cnt = st_local_send(newfd, buf, ret, 0)) < ret) { 775 printf("! Send failed: %d\n", errno); 776 bkmem_free(buf, buf_len); 777 return (-1); 778 } 779 printf("@ Sent %d bytes\n", snd_cnt); 780 } 781 (void) st_local_socket_close(newfd); 782 if (ret < 0) { 783 printf("! Cannot recv: %d\n", errno); 784 bkmem_free(buf, buf_len); 785 return (-1); 786 } else { 787 return (0); 788 } 789 } 790 791 static int 792 st_match_option(char *opt_s, int *opt, int *opt_level) 793 { 794 int i; 795 796 for (i = 0; so_option_array[i].so_name != NULL; i++) { 797 if (strcmp(so_option_array[i].so_name, opt_s) == 0) { 798 *opt = so_option_array[i].so_opt; 799 *opt_level = so_option_array[i].so_opt_level; 800 return (0); 801 } 802 } 803 printf("! Unknown option\n"); 804 return (-1); 805 } 806 807 static int 808 st_setsockopt(void) 809 { 810 char *tmp; 811 int opt, opt_level, opt_val; 812 813 if (g_sock_fd == NO_OPENED_SOCKET) { 814 printf("! No socket opened\n"); 815 return (-1); 816 } 817 818 if ((tmp = strtok(NULL, " ")) == NULL) { 819 printf("! No option given\n"); 820 return (-1); 821 } 822 if (st_match_option(tmp, &opt, &opt_level) < 0) { 823 return (-1); 824 } 825 826 /* We only support integer option for the moment. */ 827 if ((tmp = strtok(NULL, " ")) == NULL) { 828 printf("! No option value given\n"); 829 return (-1); 830 } 831 opt_val = atoi(tmp); 832 833 if (st_local_setsockopt(g_sock_fd, opt_level, opt, &opt_val, 834 sizeof (int)) < 0) { 835 printf("! Cannot set option: %d\n", errno); 836 return (-1); 837 } 838 printf("@ Option set successfully\n"); 839 return (0); 840 } 841 842 static int 843 st_getsockname(void) 844 { 845 struct sockaddr_in addr; 846 socklen_t len; 847 848 if (g_sock_fd == NO_OPENED_SOCKET) { 849 printf("! No socket opened\n"); 850 return (-1); 851 } 852 853 len = sizeof (addr); 854 if (st_local_getsockname(g_sock_fd, (struct sockaddr *)&addr, 855 &len) < 0) { 856 printf("! getsockname failed: %d\n", errno); 857 return (-1); 858 } 859 printf("@ Local socket name: %s/%d\n", inet_ntoa(addr.sin_addr), 860 ntohs(addr.sin_port)); 861 return (0); 862 } 863 864 static int 865 st_getsockopt(void) 866 { 867 char *tmp; 868 int opt, opt_level, opt_val; 869 socklen_t opt_len; 870 871 if (g_sock_fd == NO_OPENED_SOCKET) { 872 printf("! No socket opened\n"); 873 return (-1); 874 } 875 876 if ((tmp = strtok(NULL, " ")) == NULL) { 877 printf("! No option given\n"); 878 return (-1); 879 } 880 if (st_match_option(tmp, &opt, &opt_level) < 0) { 881 return (-1); 882 } 883 884 opt_len = sizeof (opt_val); 885 if (st_local_getsockopt(g_sock_fd, opt_level, opt, &opt_val, 886 &opt_len) < 0) { 887 printf("! Cannot get option: %d\n", errno); 888 return (-1); 889 } 890 printf("@ Option value is %d\n", opt_val); 891 return (-1); 892 } 893 894 static int 895 st_sock_close(void) 896 { 897 if (g_sock_fd == NO_OPENED_SOCKET) { 898 printf("! No socket opened\n"); 899 return (-1); 900 } 901 if (st_local_socket_close(g_sock_fd) < 0) { 902 printf("! Error in closing socket: %d\n", errno); 903 return (-1); 904 } 905 printf("@ Socket closed"); 906 if (save_g_sock_fd != NO_OPENED_SOCKET) { 907 g_sock_fd = save_g_sock_fd; 908 save_g_sock_fd = NO_OPENED_SOCKET; 909 printf(", switching to saved socket descriptor\n"); 910 } else { 911 g_sock_fd = NO_OPENED_SOCKET; 912 printf("\n"); 913 } 914 return (0); 915 } 916 917 static int 918 st_toggle_promiscuous(void) 919 { 920 /* We always start with non-promiscuous mode. */ 921 static boolean_t promiscuous = B_FALSE; 922 923 promiscuous = !promiscuous; 924 (void) ipv4_setpromiscuous(promiscuous); 925 printf("@ Setting promiscuous to %d\n", promiscuous); 926 return (0); 927 } 928 929 static int 930 st_use_obp(void) 931 { 932 if ((use_obp = !use_obp) == B_TRUE) { 933 printf("@ Now using OBP routines\n"); 934 } else { 935 printf("@ Now using socket routines\n"); 936 } 937 return (0); 938 } 939 940 static int 941 st_tcp_tw_report(void) 942 { 943 printf("@ TCP Time Wait report\n"); 944 tcp_time_wait_report(); 945 return (0); 946 } 947