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