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
st_local_socket(int domain,int type,int protocol)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
st_local_socket_close(int sd)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
st_local_accept(int sd,struct sockaddr * addr,socklen_t * addr_len)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
st_local_bind(int sd,const struct sockaddr * name,socklen_t namelen)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
st_local_connect(int sd,const struct sockaddr * addr,socklen_t addr_len)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
st_local_listen(int sd,int backlog)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
st_local_send(int sd,const void * msg,size_t len,int flags)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
st_local_sendto(int sd,const void * msg,size_t len,int flags,const struct sockaddr * to,socklen_t tolen)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
st_local_recv(int sd,void * buf,size_t len,int flags)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
st_local_recvfrom(int sd,void * buf,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen)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
st_local_getsockname(int sd,struct sockaddr * name,socklen_t * namelen)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
st_local_getsockopt(int sd,int level,int option,void * optval,socklen_t * optlen)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
st_local_setsockopt(int sd,int level,int option,const void * optval,socklen_t optlen)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
atoi(const char * p)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
st_interpret(char * buf)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
st_socket(void)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
st_set_addr(void)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
st_set_netmask(void)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
st_set_router(void)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
st_get_addr_and_port(in_addr_t * addr,unsigned short * port)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
st_bind(void)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
st_listen(void)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
st_accept(void)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
st_connect(void)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
st_get_buf_and_cnt(char ** buf,int * send_cnt)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
st_send(void)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
st_sendto(void)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
st_recv(void)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
st_recvfrom(void)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
st_echo(void)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
st_match_option(char * opt_s,int * opt,int * opt_level)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
st_setsockopt(void)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
st_getsockname(void)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
st_getsockopt(void)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
st_sock_close(void)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
st_toggle_promiscuous(void)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
st_use_obp(void)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
st_tcp_tw_report(void)941 st_tcp_tw_report(void)
942 {
943 printf("@ TCP Time Wait report\n");
944 tcp_time_wait_report();
945 return (0);
946 }
947