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