Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / netsim.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: netsim.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/* icq:
22 * SNOOP
23 *
24 * "netsim.cc", low level communications between blaze and switchsim, syncsim.
25 *
26 * There are two major service types:
27 *
28 * Global-Time-Sync packets (simple C strings)
29 * Network packets (network-packet plus 8-byte switchsim header
30 * containing length and timing info)
31 *
32 * There are three major implementations:
33 *
34 * Socket-based,
35 * Mmap-based,
36 * Snoop-based.
37 *
38 *
39 * Someday the UI for disconnect/reconnect will be moved here too, no
40 * need to duplicate that in every net-device-sim...
41 *
42 * netsim_connect() name parsing:
43 *
44 * "sync:host/port"
45 * "switch:host/port"
46 *
47 * currently we only support socket-based, and it is not yet part of the
48 * name parsing...
49 */
50
51/* --->> NOTICE THERE ARE NO BLAZE INCLUDES HERE, KEEP IT THAT WAY !!! <<--- */
52
53/* standard C includes */
54#include <stdio.h>
55#include <stdlib.h>
56#include <errno.h>
57#include <unistd.h>
58#include <strings.h>
59#include <assert.h>
60#include <stdarg.h>
61
62/* unix/Solaris includes */
63#include <signal.h>
64#include <sys/types.h>
65#include <sys/socket.h>
66#include <sys/stat.h>
67#include <sys/mman.h>
68#include <sys/utsname.h>
69#include <net/if.h>
70#include <netinet/if_ether.h>
71#include <rpc/xdr.h>
72#include <synch.h>
73#include <fcntl.h>
74#include <netdb.h>
75#include <stropts.h> /* strbuf, getmsg, putmsg */
76#include <sys/dlpi.h> /* dlbindack, dlokack, etc..., DL_ defines... */
77
78/* this file's public include */
79#include "netsim.h"
80
81/* private includes */
82#include "eth.h" /* general purpose ethernet packet decoder */
83
84
85
86/* bogus legacy globals ---------------------------------------- */
87int netsim_switch_flag = 1;
88char netsim_switch_server_name[MAXPATHLEN] = {'\0'};
89char netsim_switch_ipc_type[MAXPATHLEN] = {'\0'};
90char netsim_mmap_dir[MAXPATHLEN] = {'\0'};
91int netsim_ipc_type = NETSIM_IPC_SOCKET;
92
93
94
95
96
97
98
99/* configuration for this file */
100#define SIMGE_SWITCH_VERSION "1.0" /* expecting switchsim to support */
101#define USE_POLL 1 /* cant see why this is used, PAL*/
102
103int netsim_debug = 0; /* debug level */
104
105
106
107
108
109/* swtchdr.pkt_type values -------------------------------------- */
110
111#define PKT_DATA 0
112#define PKT_CTRL_VERSION 1
113#define PKT_CTRL_IPC_TYPE 2
114#define PKT_CTRL_KEY_TYPE 3
115#define PKT_CTRL_INIT_END 4
116
117#define PKT_CTRL_ACK_BASE 100
118
119#define PKT_CTRL_VERSION_OK (PKT_CTRL_ACK_BASE + PKT_CTRL_VERSION)
120#define PKT_CTRL_IPC_TYPE_OK (PKT_CTRL_ACK_BASE + PKT_CTRL_IPC_TYPE)
121#define PKT_CTRL_KEY_TYPE_OK (PKT_CTRL_ACK_BASE + PKT_CTRL_KEY_TYPE)
122#define PKT_CTRL_INIT_END_OK (PKT_CTRL_ACK_BASE + PKT_CTRL_INIT_END)
123
124#define PKT_CTRL_ERROR 400
125
126#define PKT_CTRL_IPC_SOCKET 0
127#define PKT_CTRL_IPC_MMAP 1
128
129#define PKT_CTRL_KEY_ETH 0
130#define PKT_CTRL_KEY_IP 1
131
132
133
134
135/*
136 * forward decls -----------------------------------------------------
137 */
138void vargs_error(int thresh, const char *fmt, ...);
139static int
140switch_negotiate(int fd, int ipc_type, int key_type, char *mmap_idstr, int mmap_file_size);
141static int
142ipc_socket_read_pkt(int fd, char *pkt, int maxlen, swtchdr *hdr, int timout);
143static int
144ipc_mmap_read_pkt(int fd, char *pkt, int maxlen, swtchdr *hdr, int timout);
145static int
146ipc_socket_write_pkt(int fd, char *pkt, int len, swtchdr *hdr);
147static int
148ipc_mmap_write_pkt(int fd, char *pkt, int pktlen, swtchdr *hdr);
149
150
151
152/*
153 * -------- global variables --------------------------------------------------
154 */
155
156enum { _NONE=0, _SWITCH, _SYNC }; // service types
157enum { _CLOSED=0, _SOCKET, _MMAP, _SNOOP }; // service implementations
158
159static struct {
160 int service; /* _SWITCH, _SYNC */
161 int implt; /* _SOCKET, _MMAP, _SNOOP */
162
163} info[ FD_SETSIZE ]; /* indexed by `fd' of open socket/mmap/snoop file */
164
165
166
167
168
169
170
171
172
173////////////////////////////////////////////////////////////////////////////////
174// //
175// These are the four public interface functions connect, get, put, close //
176// //
177////////////////////////////////////////////////////////////////////////////////
178
179
180
181/* ------------------------------ simplified ----------------------------------
182 * ...currently only handles socket, not mmap, not snoop...
183 *
184 */
185int netsim_connect(const char *switchandport)
186{
187 int ipc_type = PKT_CTRL_IPC_SOCKET; /* vs mmap */
188 int key_type = 0; /* ip vs mac routing in switchsim */
189
190 const char * p, * q;
191 int i, portno, service;
192
193 char host[ MAXPATHLEN ];
194 struct hostent *server;
195 struct sockaddr_in serv_addr;
196 int sockfd;
197
198
199 p = switchandport;
200 if (strncmp (switchandport, "sync:", 5) == 0) { // "sync:"
201 service = _SYNC;
202 p += 5;
203 } else if (strncmp (switchandport, "switch:", 7) == 0) { // "switch:"
204 service = _SWITCH;
205 p += 7;
206 } else {
207 service = _SWITCH;
208 }
209
210 if ((q = strrchr (p, '/')) != NULL) { // "host/port"
211 i = q - p;
212 strncpy (host, p, MAXPATHLEN);
213 host[ i ] = '\0';
214 portno = atoi (&host[ i+1 ]);
215 } else {
216 strncpy (host, p, MAXPATHLEN);
217 if (service == _SYNC)
218 portno = SYNC_DEFAULT_PORT;
219 else
220 portno = SWITCH_DEFAULT_PORT;
221 }
222
223 if (netsim_debug) fprintf(stderr,"netsim_connect %s: \"%s\", %d\n",
224 (service == _SYNC ? "sync" : "switch"), host, portno);
225
226
227 sockfd = socket(AF_INET, SOCK_STREAM, 0); /*--SOCKET--*/
228 if (sockfd < 0) {
229 fprintf(stderr, "ERROR: tryconnect: socket: %s \n", strerror(errno));
230 return -1;
231 }
232
233 server = gethostbyname(host); /*--GETHOSTBYNAME--*/
234 if (server == NULL) {
235 fprintf(stderr, "ERROR: tryconnect: gethostbyname: %s \n", strerror(h_errno));
236 close(sockfd);
237 return -1;
238 }
239
240 bzero((char *) &serv_addr, sizeof(struct sockaddr_in));
241 serv_addr.sin_family = AF_INET;
242 bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
243 serv_addr.sin_port = htons(portno); /*--CONNECT--*/
244 if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
245 fprintf(stderr, "ERROR: tryconnect: connect: %s \n", strerror(errno));
246 close(sockfd);
247 return -1;
248 }
249
250 if (netsim_debug) fprintf(stderr,"netsim_connect fd = %d\n", sockfd);
251
252 if (service == _SYNC) {
253 info[ sockfd ].service = _SYNC;
254
255 } else /*service == _SWITCH*/ { /*--negotiate--*/
256 if (switch_negotiate(sockfd, ipc_type, key_type, NULL, 0) < 0) {
257 fprintf(stderr, "ERROR: tryconnect: negotiate: with %s failed. \n",
258 host);
259 close(sockfd);
260 return -1;
261 }
262 info[ sockfd ].service = _SWITCH;
263 }
264
265 info[ sockfd ].implt = _SOCKET;
266 return sockfd;
267}
268
269
270
271/* ------------------------------ simplified ----------------------------------
272 */
273int netsim_close (int fd)
274{
275 close (fd);
276 info[ fd ].service = _NONE;
277 info[ fd ].implt = _CLOSED;
278 return 0;
279}
280
281
282
283
284
285/* ------------------------------ simplified ----------------------------------
286 * result < 0 error
287 * result = 0 connection closed, or errno = EINTR (from SIGUSR1)
288 * result > 0 success, --> actual bytes read is returned in hdr->pkt_len <--
289 */
290
291int
292netsim_getmsg(int fd, char * buf, int maxlen, swtchdr * hdr)
293{
294 int result;
295
296 if (info[ fd ].service == _SYNC) {
297
298 if (info[fd].implt == _SOCKET) {
299 /* ? read, ? fread, ? fgets, ? getmsg, ? ... */
300 int flags = 0;
301 struct strbuf ctrlbuf;
302 struct strbuf databuf;
303 databuf.maxlen = maxlen;
304 databuf.buf = buf;
305 result = getmsg (fd, NULL/*ctrlbuf*/, &databuf, NULL/*flagsp*/);
306 /* man says 0 => full message copied,
307 + => partial message copied,
308 - => error
309 but does not say how to tell if connection closed remotely ??? */
310 if (result >= 0)
311 result = databuf.len; /* actual num bytes copied */
312 else if (errno == EINTR)
313 result = 0; /* our convention */
314 else {
315 perror ("netsim: get sync msg: ");
316 result = -1;
317 }
318 } else
319 result = -1;
320
321 } else /* _SWITCH */ {
322
323 if (info[fd].implt == _SOCKET) {
324 result = ipc_socket_read_pkt(fd, buf, maxlen, hdr, -1);
325 } else if (info[fd].implt == _MMAP) {
326 result = ipc_mmap_read_pkt(fd, buf, maxlen, NULL, -1);
327 } else
328 result = -1;
329 }
330
331 return result;
332}
333
334
335/* ------------------------------ simplified ----------------------------------
336 * result < 0 error, including connection closed, errno = EINTR (SIGUSR1) ???
337 * result = 0 ???
338 * result > 0 success, result bytes written
339 */
340int
341netsim_putmsg(int fd, char * buf, int len, swtchdr * hdr)
342{
343 int result;
344
345 errno = 0;
346
347 if (info[fd].service == _SYNC) {
348
349 if (info[fd].implt == _SOCKET) {
350 /* ? write, ? fwrite, ? fputs, ? putmsg, ? ... */
351 int flags = 0;
352 struct strbuf ctrlbuf;
353 struct strbuf databuf;
354 databuf.buf = buf;
355 databuf.len = len;
356 result = putmsg (fd, NULL/*ctrlbuf*/, &databuf, NULL/*flagsp*/);
357 /* man says 0 => full message copied,
358 - => error
359 but does not say how to tell if connection closed remotely ??? */
360 if (result >= 0)
361 result = databuf.len; /* actual num bytes copied */
362 else if (errno == EINTR)
363 result = -1; /* our (confused!) convention */
364 else {
365 perror ("netsim: put sync msg: ");
366 result = -1;
367 }
368 } else
369 result = -1;
370
371 } else /* _SWITCH */ {
372
373 if (info[fd].implt == _SOCKET) {
374 result = ipc_socket_write_pkt(fd, buf, len, hdr);
375
376 } else if (info[fd].implt == _MMAP) {
377 result = ipc_mmap_write_pkt(fd, buf, len, hdr);
378
379 } else if (info[fd].implt == _SNOOP){
380 struct strbuf data;
381 data.buf = (char *) buf;
382 data.maxlen = MAXDLBUF;
383 data.len = len;
384 result = putmsg(fd, NULL, &data, 0);
385 if (result == 0) result = sizeof(hdr) + len;
386
387 } else
388 result = -1;
389 }
390 return result;
391}
392
393
394
395
396
397
398
399
400
401
402
403
404
405////////////////////////////////////////////////////////////////////////////////
406// //
407// The following section is for Socket-based //
408// ^^^^^^ //
409////////////////////////////////////////////////////////////////////////////////
410
411
412
413#define ETHER_ADDR_LEN 6
414#define ETHER_HDR_LEN (6 + 6 + 2)
415
416#define SWITCH_PKT_HDR_SIZE 8
417#define SWITCH_ETHERMTU (ETHERMTU + ETHER_HDR_LEN)
418#define MAX_SWITCH_PKT_SIZE (SWITCH_ETHERMTU + SWITCH_PKT_HDR_SIZE + sizeof(ushort_t))
419
420
421
422
423/*note that timout==-1 means wait forever, which is the only value used...
424 *change: returns 0 for socket closed at other end, PAL.
425 */
426static int
427read_all(int fd, char *buf, int len, int timout)
428{
429 int result, saved_len;
430
431 struct pollfd pfd;
432
433 int index = 0;
434
435 if (len == 0)
436 return 0;
437
438 saved_len = len;
439
440 while (len > 0) {
441
442#if USE_POLL
443 /* I can't see any reason for using poll here, either we wait in poll
444 * or we wait in read, what's the difference...???...
445 * its just going to cost more syscalls...
446 */
447 pfd.fd = fd;
448 pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
449 result = poll(&pfd, 1, timout);
450 /*
451 * poll results:
452 * 0 => timeout (can't happen with -1 as the timeout value passed in)
453 * >0 => number of `active' files in polling list
454 * <0 => chech errno for {EAGAIN, EFAULT, EINTR, EINVAL}
455 *
456 * what the rest of simge wants:
457 * 0 => socket closed (either from other end, indicated by zero-length
458 * packet received, or from this end by the UI,
459 * indicated by EINTR (SIGUSR1).
460 * <0 => other error
461 * >0 => that many bytes read
462 */
463 if (result <= 0) {
464 if (result < 0 && (errno == EINTR)) {
465 return 0; /* this is the SIGUSR1 from our UI case, this thread
466 * is being interrupted because the UI is closing
467 * the socket from this end */
468 } else if (result == 0) {
469 fprintf(stderr, "ERROR: read_all: poll(fd=%d) timedout \n", fd);
470 return -1;
471 } else {
472 fprintf(stderr, "ERROR: read_all: poll: %s \n", strerror(errno));
473 return -1;
474 }
475 }
476 assert(result == 1);
477
478#endif /* USE_POLL */
479
480 result = read(fd, &buf[index], len);
481 if (result == len) {
482 return saved_len;
483 }
484 if (result > 0) {
485 index += result;
486 len -= result;
487 } else if (result < 0) {
488 fprintf(stderr, "ERROR: read_all: read: %s \n", strerror(errno));
489 return -1;
490 } else if (result == 0) {
491 fprintf(stderr, "INFO: read_all: read: connection closed on the socket. \n");
492 return 0; /*
493 * this is the "socket closed from the other end" case
494 */
495 }
496 }
497
498 /* NOT REACHED */
499
500 return -1;
501}
502
503
504static int
505write_all(int fd, char *buf, int len)
506{
507 int result;
508
509 int index = 0;
510 int saved_len = len;
511
512 while (len > 0) {
513
514 result = write(fd, &buf[index], len);
515 if (result == len)
516 return saved_len;
517
518 if (result > 0) {
519 index += result;
520 len -= result;
521 } else if (result < 0) {
522 fprintf(stderr, "ERROR: write_all: write: %s \n", strerror(errno));
523 return -1;
524 } else if (result == 0) {
525 fprintf(stderr, "ERROR: write_all: write: returned 0 instead of writing %d bytes \n", len);
526 return -1;
527 }
528 }
529
530 /* NOT REACHED */
531
532 return -1;
533}
534
535
536/*
537 * now returns (buf_len *PLUS* hdr_len) !!! PAL.
538 * so that 0 can be the unambiguous indicator of socket closed at other end.
539 *
540 * on successful read store actual length read into hdr->pkt_len. PAL.
541 */
542static int
543ipc_socket_read_pkt(int fd, char *pkt, int maxlen, swtchdr *hdr, int timout)
544{
545 int pktlen, result;
546 swtchdr local_hdr, *hptr;
547
548 if (hdr == NULL)
549 hptr = &local_hdr;
550 else
551 hptr = hdr;
552
553 result = read_all(fd, (char *) hptr, sizeof(swtchdr), timout);
554 if (result <= 0) { /* was < 0), PAL*/
555 return result;
556 }
557 assert(result == sizeof(swtchdr));
558
559 pktlen = ntohl(hptr->pkt_len); /* real eth-packet len from switchsim hdr */
560
561 if (pktlen > maxlen) {
562 fprintf(stderr, "ERROR: ipc_socket_read_pkt: pktlen %d > maxlen %d \n",
563 pktlen, maxlen);
564 return -1;
565 }
566
567 if (pktlen == 0) {
568 hptr->pkt_len = pktlen; /*PAL*/
569 return pktlen + sizeof(swtchdr); /*was: pktlen; PAL*/
570 }
571
572 if ((result = read_all(fd, pkt, pktlen, timout)) <= 0) { /*was: <0, PAL*/
573 return result;
574 }
575 assert(result == pktlen);
576
577 hptr->pkt_len = pktlen; /*PAL*/
578 return pktlen + sizeof(swtchdr); /*was: pktlen; PAL*/
579}
580
581/*
582 * result = result-from-writev-syscall:
583 * <0 error
584 * =0 ?
585 * >0 success, number of bytes written
586 */
587static int
588ipc_socket_write_pkt(int fd, char *pkt, int len, swtchdr *hdr)
589{
590 int result;
591 swtchdr *hptr, local_hdr;
592 struct iovec wiovec[2];
593
594 if (hdr == NULL) {
595 hptr = &local_hdr;
596 hptr->pkt_type = htonl(PKT_DATA);
597 } else {
598 hptr = hdr;
599 }
600
601 hptr->pkt_len = htonl(len);
602
603 wiovec[0].iov_base = (char *) hptr;
604 wiovec[0].iov_len = sizeof(swtchdr);
605
606 if (len == 0) {
607 result = writev(fd, wiovec, 1);
608 return result;
609 } else {
610 wiovec[1].iov_base = pkt;
611 wiovec[1].iov_len = len;
612 result = writev(fd, wiovec, 2);
613 return result;
614 }
615
616 /* NOT REACHED */
617 return -1;
618}
619
620
621/* more swtchdr stuff -------------------------------------- */
622
623
624
625
626typedef struct pkt_ctrl_ipc_type {
627 int ipc_type;
628 char *mmap_idstr;
629 int mmap_file_size;
630} pkt_ctrl_ipc_type_t;
631
632
633
634typedef struct pkt_ctrl_key_type {
635 int key_type;
636} pkt_ctrl_key_type_t;
637
638
639
640static int
641process_ack(int fd, int type)
642{
643 int result;
644 swtchdr hdr;
645
646 char pkt[SWITCH_ETHERMTU];
647
648 result = ipc_socket_read_pkt(fd, pkt, SWITCH_ETHERMTU, &hdr, TIMEOUT_FIVE_SECOND);
649 if (result <= 0) { /* was < 0, PAL*/
650 return -1;
651 }
652
653 switch (hdr.pkt_type) {
654 case PKT_CTRL_VERSION_OK:
655 case PKT_CTRL_IPC_TYPE_OK:
656 case PKT_CTRL_KEY_TYPE_OK:
657 case PKT_CTRL_INIT_END_OK:
658 if (type == hdr.pkt_type)
659 result = 0;
660 else
661 result = -1;
662 break;
663 case PKT_CTRL_ERROR:
664 result = -1;
665 break;
666 default:
667 result = -1;
668 break;
669 }
670
671 return result;
672}
673
674
675static int
676process_version(int fd)
677{
678 XDR xdr;
679 char *ptr;
680 union {
681 char pkt[SWITCH_ETHERMTU];
682 uint64_t force_alignment;
683 } aligned_pkt;
684 swtchdr hdr;
685 int len, result;
686
687 ptr = (char *) SIMGE_SWITCH_VERSION;
688 xdrmem_create(&xdr, aligned_pkt.pkt, SWITCH_ETHERMTU, XDR_ENCODE);
689 result = xdr_string(&xdr, &ptr, 64);
690 if (!result) {
691 xdr_destroy(&xdr);
692 return -1;
693 }
694 len = xdr_getpos(&xdr);
695 xdr_destroy(&xdr);
696
697 hdr.pkt_type = htonl(PKT_CTRL_VERSION);
698 hdr.pkt_len = htonl(len);
699
700 result = ipc_socket_write_pkt(fd, aligned_pkt.pkt, len, &hdr);
701 if (result < 0)
702 return result;
703
704 result = process_ack(fd, PKT_CTRL_VERSION_OK);
705 if (result < 0) {
706 fprintf(stderr, "ERROR: libswitch: version %s not accepted by switch. \n", ptr);
707 return -1;
708 }
709
710 return 0;
711}
712
713
714static int
715process_ipc_type(int fd, int ipc_type, char *mmap_idstr, int mmap_file_size)
716{
717 int len;
718 swtchdr hdr;
719 XDR xdr;
720 union {
721 char pkt[SWITCH_ETHERMTU];
722 uint64_t force_alignment;
723 } aligned_pkt;
724
725 pkt_ctrl_ipc_type_t data;
726
727 int result = 0;
728
729 data.ipc_type = ipc_type;
730 if (mmap_idstr == NULL)
731 data.mmap_idstr = (char *) "";
732 else
733 data.mmap_idstr = mmap_idstr;
734 data.mmap_file_size = mmap_file_size;
735
736 xdrmem_create(&xdr, aligned_pkt.pkt, SWITCH_ETHERMTU, XDR_ENCODE);
737 result = xdr_int(&xdr, &data.ipc_type);
738 if (!result) {
739 xdr_destroy(&xdr);
740 return -1;
741 }
742 result = xdr_string(&xdr, &data.mmap_idstr, MAXPATHLEN);
743 if (!result) {
744 xdr_destroy(&xdr);
745 return -1;
746 }
747 result = xdr_int(&xdr, &data.mmap_file_size);
748 if (!result) {
749 xdr_destroy(&xdr);
750 return -1;
751 }
752 len = xdr_getpos(&xdr);
753
754 xdr_destroy(&xdr);
755
756 hdr.pkt_type = htonl(PKT_CTRL_IPC_TYPE);
757 hdr.pkt_len = htonl(len);
758
759 result = ipc_socket_write_pkt(fd, aligned_pkt.pkt, len, &hdr);
760 if (result < 0)
761 return result;
762
763 result = process_ack(fd, PKT_CTRL_IPC_TYPE_OK);
764 if (result < 0) {
765 fprintf(stderr, "ERROR: libswitch: ipc_type %d not accepted by switch. \n", ipc_type);
766 }
767
768 return 0;
769}
770
771
772static int
773process_key_type(int fd, int key_type)
774{
775 int len;
776 swtchdr hdr;
777 XDR xdr;
778 union {
779 char pkt[SWITCH_ETHERMTU];
780 uint64_t force_alignment;
781 } aligned_pkt;
782
783 pkt_ctrl_key_type_t data;
784
785 int result = 0;
786
787 data.key_type = key_type;
788
789 xdrmem_create(&xdr, aligned_pkt.pkt, SWITCH_ETHERMTU, XDR_ENCODE);
790 result = xdr_int(&xdr, &data.key_type);
791 if (!result) {
792 xdr_destroy(&xdr);
793 return -1;
794 }
795 len = xdr_getpos(&xdr);
796 xdr_destroy(&xdr);
797
798 hdr.pkt_type = htonl(PKT_CTRL_KEY_TYPE);
799 hdr.pkt_len = htonl(len);
800
801 result = ipc_socket_write_pkt(fd, aligned_pkt.pkt, len, &hdr);
802 if (result < 0)
803 return result;
804
805 result = process_ack(fd, PKT_CTRL_KEY_TYPE_OK);
806 if (result < 0) {
807 fprintf(stderr, "ERROR: libswitch: key_type %d not accepted by switch. \n", key_type);
808 return -1;
809 }
810
811 return 0;
812}
813
814
815static int
816process_init_end(int fd)
817{
818 swtchdr hdr;
819
820 int result = 0;
821
822 hdr.pkt_type = htonl(PKT_CTRL_INIT_END);
823 hdr.pkt_len = 0;
824
825 result = ipc_socket_write_pkt(fd, NULL, 0, &hdr);
826 if (result < 0) {
827 return -1;
828 }
829 return 0;
830}
831
832
833
834static int
835switch_negotiate(int fd, int ipc_type, int key_type, char *mmap_idstr, int mmap_file_size)
836{
837 int result;
838
839 result = process_version(fd);
840 if (result < 0) {
841 return -1;
842 }
843 result = process_ipc_type(fd, ipc_type, mmap_idstr, mmap_file_size);
844 if (result < 0) {
845 return -1;
846 }
847 result = process_key_type(fd, key_type);
848 if (result < 0) {
849 return -1;
850 }
851 result = process_init_end(fd);
852 if (result < 0) {
853 return -1;
854 }
855
856 return 0;
857}
858
859
860
861
862/*
863 * some more forward decls --------------------------------------------------
864 */
865static void mmap_data_table_init(void);
866static int ipc_create_mmap_files(const char *mmap_dir, char *mmap_idstr, int mmap_file_size);
867int mmap_data_table_initialized = 0;
868
869
870
871
872
873
874/*
875 * the old "make a connection" (either socket or mmap) function
876 *
877 * returns the socket fd on success, -1 otherwise.
878 */
879int
880ipc_init(const char *switch_server, const char *ipc_type_string, int key_type, const char *mmap_dir, int mmap_file_size)
881{
882 int mmap_fd, ipc_type, result;
883 int sockfd, server_port;
884
885 struct hostent *server;
886 struct sockaddr_in serv_addr;
887 struct utsname host_utsname;
888
889 const char *server_name;
890
891 char mmap_idstr[MAXPATHLEN];
892
893
894 if (strcmp(ipc_type_string, "socket") == 0) {
895 ipc_type = PKT_CTRL_IPC_SOCKET;
896 } else if (strcmp(ipc_type_string, "mmap") == 0) {
897 ipc_type = PKT_CTRL_IPC_MMAP;
898 } else if (strcmp(ipc_type_string, "") == 0) {
899 ipc_type = PKT_CTRL_IPC_SOCKET;
900 } else {
901 fprintf(stderr, "ERROR: libswitch: unknown switch ipc type specified: %s \n", ipc_type_string);
902 return -1;
903 }
904
905 if (uname(&host_utsname) == -1) {
906 fprintf(stderr, "ERROR: libswitch: uname: %s \n", strerror(errno));
907 return -1;
908 }
909
910 server_name = host_utsname.nodename;
911
912 /* TBD: System with multiple interfaces with different hostnames */
913
914 if (switch_server != NULL) {
915 if (strcmp(switch_server, server_name) != 0) {
916 if (ipc_type == PKT_CTRL_IPC_MMAP) {
917 fprintf(stderr, "ERROR:libswitch: mmap can't be used for ipc "
918 "between the machines %s and %s \n",
919 switch_server, server_name);
920 return -1;
921 }
922 server_name = switch_server;
923 }
924 }
925
926 sockfd = socket(AF_INET, SOCK_STREAM, 0);
927 if (sockfd < 0) {
928 fprintf(stderr, "ERROR: libswitch: socket: %s \n", strerror(errno));
929 return -1;
930 }
931
932 server = gethostbyname(server_name);
933 if (server == NULL) {
934 fprintf(stderr, "ERROR: libswitch: gethostbyname: %s \n", strerror(h_errno));
935 close(sockfd);
936 return -1;
937 }
938
939 server_port = SWITCH_DEFAULT_PORT;
940
941 bzero((char *) &serv_addr, sizeof(struct sockaddr_in));
942 serv_addr.sin_family = AF_INET;
943 bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
944 serv_addr.sin_port = htons(server_port);
945
946 if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
947 fprintf(stderr, "ERROR: libswitch: connect: %s \n", strerror(errno));
948 close(sockfd);
949 return -1;
950 }
951
952 if (ipc_type == PKT_CTRL_IPC_MMAP) {
953 if (mmap_data_table_initialized == 0)
954 mmap_data_table_init();
955 mmap_fd = ipc_create_mmap_files(mmap_dir, mmap_idstr, mmap_file_size);
956 if (mmap_fd < 0) {
957 fprintf(stderr, "ERROR: libswitch: failed to create mmap files for ipc \n");
958 close(sockfd);
959 return -1;
960 }
961 }
962
963 result = switch_negotiate(sockfd, ipc_type, key_type, mmap_idstr, mmap_file_size);
964 if (result < 0) {
965 fprintf(stderr, "ERROR: libswitch: negotiation with switch server %s failed. \n", server_name);
966 close(sockfd);
967 return result;
968 }
969
970 if (ipc_type == PKT_CTRL_IPC_MMAP) {
971 close(sockfd);
972 info[ mmap_fd ].implt = _MMAP;
973 result = mmap_fd;
974 } else {
975 info[ sockfd ].implt = _SOCKET;
976 result = sockfd;
977 }
978
979 return result;
980}
981
982
983
984
985
986
987
988////////////////////////////////////////////////////////////////////////////////
989// //
990// The following is for Mmap-based blaze networking... //
991// ^^^^ //
992////////////////////////////////////////////////////////////////////////////////
993
994
995
996
997#define FIRST_MMAP_FD 1000
998
999#define MMAP_DATA_TABLE_SIZE 32
1000
1001typedef struct mmap_data {
1002
1003 int fd;
1004
1005 char *snd_mmap_addr;
1006 int snd_mmap_index;
1007 int snd_mmap_size;
1008
1009 char *rcv_mmap_addr;
1010 int rcv_mmap_index;
1011 int rcv_mmap_size;
1012
1013} mmap_data_t;
1014
1015mmap_data_t mmap_data_table[MMAP_DATA_TABLE_SIZE];
1016
1017int mmap_data_table_index;
1018/*int mmap_data_table_initialized; is moved up above */
1019mutex_t mmap_data_table_lock;
1020
1021static void
1022mmap_data_table_init(void)
1023{
1024 int index;
1025
1026 mutex_init(&mmap_data_table_lock, USYNC_THREAD, NULL);
1027
1028 for (index=0; index<MMAP_DATA_TABLE_SIZE; index++) {
1029 mmap_data_table[index].fd = -1;
1030 }
1031
1032 mmap_data_table_initialized = 1;
1033
1034 return;
1035}
1036
1037static mmap_data_t *
1038mmap_data_alloc(void)
1039{
1040 int index;
1041
1042 int found = 0;
1043
1044 mutex_lock(&mmap_data_table_lock);
1045 for (index=0; index<MMAP_DATA_TABLE_SIZE; index++) {
1046 if (mmap_data_table[index].fd == -1) {
1047 mmap_data_table[index].fd = index + FIRST_MMAP_FD;
1048 found = 1;
1049 break;
1050 }
1051 }
1052 mutex_unlock(&mmap_data_table_lock);
1053
1054 if (found == 0)
1055 return NULL;
1056
1057 return &mmap_data_table[index];
1058}
1059
1060#define SWITCH_LIB_PAGE_SIZE 8192
1061
1062static int
1063ipc_mmap_init_file(int fd, int mmap_file_size)
1064{
1065 char *buf;
1066 int index, page_count, count;
1067
1068 int result = 0;
1069
1070 page_count = mmap_file_size / SWITCH_LIB_PAGE_SIZE;
1071
1072 buf = (char *) calloc(1, SWITCH_LIB_PAGE_SIZE);
1073 if (buf == NULL) {
1074 fprintf(stderr, "ERROR: libswitch: calloc SWITCH_LIB_PAGE_SIZE returned NULL \n");
1075 return -1;
1076 }
1077 for (index=0; index<page_count; index++) {
1078 result = write(fd, buf, SWITCH_LIB_PAGE_SIZE);
1079 if (result < 0) {
1080 fprintf(stderr, "ERROR: libswitch: failed to initialize mmap file : %s \n", strerror(errno));
1081 return -1;
1082 }
1083 }
1084
1085 count = mmap_file_size % SWITCH_LIB_PAGE_SIZE;
1086 for (index=0; index<count; index++) {
1087 result = write(fd, buf, count);
1088 if (result < 0) {
1089 fprintf(stderr, "ERROR: libswitch: failed to initialize mmap file : %s \n", strerror(errno));
1090 return -1;
1091 }
1092 }
1093
1094 free(buf);
1095
1096 return 0;
1097}
1098
1099static int
1100ipc_create_mmap_files(const char *mmap_dir, char *mmap_idstr, int mmap_file_size)
1101{
1102 int fd, result;
1103 pid_t pid;
1104 caddr_t addr;
1105 char send_filename[MAXPATHLEN];
1106 char recv_filename[MAXPATHLEN];
1107
1108 mmap_data_t *mdp;
1109
1110 pid = getpid();
1111
1112 mdp = mmap_data_alloc();
1113 if (mdp == NULL) {
1114 fprintf(stderr, "ERROR: libswitch: ran out of mmap ipc file descriptors. \n");
1115 return -1;
1116 }
1117
1118 if (mmap_dir == NULL) {
1119 strcpy(send_filename, "/tmp/SAM/send_to_switch.");
1120 } else {
1121 strcpy(send_filename, mmap_dir);
1122 strcat(send_filename, "/send_to_switch.");
1123 }
1124 sprintf(mmap_idstr, "%d_%d", getpid(), mdp->fd);
1125 strcat(send_filename, mmap_idstr);
1126
1127 fd = open(send_filename, O_RDWR|O_CREAT|O_TRUNC, 0777);
1128 if (fd == -1) {
1129 fprintf(stderr, "ERROR: libswitch: open: ( filename %s ) %s \n", send_filename, strerror(errno));
1130 return -1;
1131 }
1132
1133 fchmod(fd, 0777);
1134
1135 result = ipc_mmap_init_file(fd, mmap_file_size);
1136 if (result < 0) {
1137 close(fd);
1138 unlink(send_filename);
1139 return -1;
1140 }
1141
1142 addr = NULL;
1143
1144 addr = mmap(addr, mmap_file_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
1145 if (addr == (caddr_t ) -1) {
1146 close(fd);
1147 unlink(send_filename);
1148 fprintf(stderr, "ERROR: libswitch: mmap(%s): %s \n", send_filename, strerror(errno));
1149 return -1;
1150 }
1151
1152 mdp->snd_mmap_addr = (char *) addr;
1153 mdp->snd_mmap_size = mmap_file_size;
1154 mdp->snd_mmap_index = 0;
1155 close(fd);
1156
1157 if (mmap_dir == NULL) {
1158 strcpy(recv_filename, "/tmp/SAM/recv_from_switch.");
1159 } else {
1160 strcpy(recv_filename, mmap_dir);
1161 strcat(recv_filename, "/recv_from_switch.");
1162 }
1163 strcat(recv_filename, mmap_idstr);
1164
1165 fd = open(recv_filename, O_RDWR|O_CREAT|O_TRUNC, 0777);
1166 if (fd == -1) {
1167 munmap(mdp->snd_mmap_addr, mmap_file_size);
1168 unlink(send_filename);
1169 fprintf(stderr, "ERROR: libswitch: open: ( filename %s ) %s \n", recv_filename, strerror(errno));
1170 return -1;
1171 }
1172
1173 fchmod(fd, 0777);
1174
1175 result = ipc_mmap_init_file(fd, mmap_file_size);
1176 if (result < 0) {
1177 close(fd);
1178 unlink(recv_filename);
1179 munmap(mdp->snd_mmap_addr, mmap_file_size);
1180 unlink(send_filename);
1181 return -1;
1182 }
1183
1184 addr = NULL;
1185
1186 addr = mmap(addr, mmap_file_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
1187 if (addr == (caddr_t ) -1) {
1188 close(fd);
1189 unlink(recv_filename);
1190 unlink(send_filename);
1191 munmap(mdp->snd_mmap_addr, mmap_file_size);
1192 fprintf(stderr, "ERROR: libswitch: mmap(%s): %s \n", recv_filename, strerror(errno));
1193 return -1;
1194 }
1195
1196 mdp->rcv_mmap_addr = (char *) addr;
1197 mdp->rcv_mmap_size = mmap_file_size;
1198 mdp->rcv_mmap_index = 0;
1199 close(fd);
1200
1201 return mdp->fd;
1202}
1203
1204
1205#define MMAP_PKT_OFFSET SWITCH_PKT_HDR_SIZE
1206#define MMAP_CLOSE -1
1207
1208
1209static int
1210ipc_mmap_read_pkt(int fd, char *pkt, int maxlen, swtchdr *hdr, int timout)
1211{
1212 int pktlen;
1213 swtchdr *hptr;
1214
1215 char *src;
1216 mmap_data_t *mdp;
1217
1218
1219 if (0) {
1220 fprintf(stderr, "INFO: ipc_mmap_read_pkt called with timout %d \n", timout);
1221 }
1222
1223 if ((fd - FIRST_MMAP_FD) >= MMAP_DATA_TABLE_SIZE)
1224 return -1;
1225
1226 mdp = &mmap_data_table[fd - FIRST_MMAP_FD];
1227
1228 hptr = (swtchdr *) (mdp->rcv_mmap_addr + mdp->rcv_mmap_index);
1229 for (;;) {
1230 pktlen = hptr->pkt_len;
1231 if (pktlen != 0) {
1232 pktlen = ntohl(pktlen);
1233 if (pktlen == MMAP_CLOSE) {
1234 return -1;
1235 } else {
1236 if (hdr != NULL) {
1237 hdr->pkt_type = ntohl(hptr->pkt_type);
1238 hdr->pkt_len = pktlen;
1239 }
1240
1241 if (pktlen > maxlen) {
1242 fprintf(stderr, "ERROR: libswitch: ipc_mmap_read_pkt: pktlen %d > maxlen %d \n", pktlen, maxlen);
1243 return -1;
1244 }
1245
1246 src = (mdp->rcv_mmap_addr + mdp->rcv_mmap_index) + MMAP_PKT_OFFSET;
1247
1248 bcopy(src, pkt, pktlen);
1249
1250 mdp->rcv_mmap_index += MAX_SWITCH_PKT_SIZE;
1251
1252 if ((mdp->rcv_mmap_index + MAX_SWITCH_PKT_SIZE) > mdp->rcv_mmap_size) {
1253 mdp->rcv_mmap_index = 0;
1254 }
1255
1256 hptr->pkt_len = 0;
1257 return pktlen;
1258 }
1259 }
1260 }
1261
1262 /* NOT REACHED */
1263}
1264
1265
1266static int
1267ipc_mmap_write_pkt(int fd, char *pkt, int pktlen, swtchdr *hdr)
1268{
1269 char *dst;
1270 mmap_data_t *mdp;
1271 swtchdr *hptr;
1272
1273 if (pktlen > SWITCH_ETHERMTU) {
1274 fprintf(stderr, "ERROR: libswitch: ipc_mmap_write_pkt: pktlen %d > maxlen %d \n", pktlen, SWITCH_ETHERMTU);
1275 return -1;
1276 }
1277
1278 if ((fd - FIRST_MMAP_FD) >= MMAP_DATA_TABLE_SIZE)
1279 return -1;
1280
1281 mdp = &mmap_data_table[fd - FIRST_MMAP_FD];
1282
1283 hptr = (swtchdr *) (mdp->snd_mmap_addr + mdp->snd_mmap_index);
1284 if (hdr == NULL) {
1285 hptr->pkt_type = htonl(PKT_DATA);
1286 } else {
1287 hptr->pkt_type = htonl(hdr->pkt_type);
1288 }
1289
1290 dst = (mdp->snd_mmap_addr + mdp->snd_mmap_index) + MMAP_PKT_OFFSET;
1291
1292 bcopy(pkt, dst, pktlen);
1293
1294 mdp->snd_mmap_index += MAX_SWITCH_PKT_SIZE;
1295
1296 if ((mdp->snd_mmap_index + MAX_SWITCH_PKT_SIZE) > mdp->snd_mmap_size) {
1297 mdp->snd_mmap_index = 0;
1298 }
1299
1300 hptr->pkt_len = htonl(pktlen);
1301
1302 return pktlen;
1303}
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314////////////////////////////////////////////////////////////////////////////////
1315// //
1316// The following section is for Snoop-based blaze networking... //
1317// ^^^^^ //
1318////////////////////////////////////////////////////////////////////////////////
1319
1320
1321
1322
1323/*#include <dlpi.h> is up above */
1324
1325/* usage:
1326 * fd = init_snoop_device ("ge", 1); <--- implemented here, this is
1327 * the only non-static ftn.
1328 * getmsg (fd,... <--- std Solaris syscall
1329 * putmsg (fd,... <--- std Solaris syscall
1330 * close (fd)
1331 */
1332
1333/* forward decls for this section ------------------------------------
1334 */
1335static int snoop_dlattachreq(int fd, ulong_t ppa);
1336static int snoop_dlokack(int fd, char *bufp);
1337static int snoop_dlpromisconreq(int fd, ulong_t level);
1338static int snoop_dlbindreq(int fd, ulong_t sap, ulong_t max_conind,
1339 ulong_t service_mode, ulong_t conn_mgmt, ulong_t xidtest);
1340static int snoop_dlbindack(int fd, char *bufp);
1341static int snoop_strioctl(int fd, int cmd, int timout, int len, char *dp);
1342static int snoop_strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap,
1343 int *flagsp, const char *caller);
1344static int snoop_expecting (int prim, union DL_primitives *dlp);
1345static const char * snoop_dlprim(ulong_t prim);
1346
1347
1348#if 0 /*
1349 * Someday we may have to resurrect this, or maybe we'll get lucky...
1350 * Here is the code that used to be in "main.cc" for parsing the
1351 * "-N 0=ge0,1=ge0" host device snooping specifications. That
1352 * string, without the -N, is now accessable through the function
1353 * call SYSTEM_get_hostconfig ("snoop.args");
1354 */
1355 int num_matches;
1356 int nic0, nic1, minor0, minor1;
1357 char devname0[32+4];
1358 char devname1[32+4];
1359 char devbuf[64];
1360 char *arg, comma;
1361
1362 if (argndx == argc) {
1363 fprintf(stderr, "ERROR: No argument specified to -N \n");
1364 exit(4);
1365 }
1366
1367 arg = argv[argndx++];
1368
1369 nic0 = minor0 = nic1 = minor1 = 0;
1370
1371 num_matches = sscanf(arg, "%d=%32[a-zA-Z]%d%c%d=%32[a-zA-Z]%d",
1372 &nic0, devname0, &minor0, &comma, &nic1, devname1, &minor1);
1373
1374
1375 if ( (num_matches != 3) && (num_matches != 7) ) {
1376 switch (num_matches) {
1377 case 0:
1378 case 4:
1379 fprintf(stderr, "ERROR: Bad argument (%s) to -N \n", arg);
1380 break;
1381
1382 case 1:
1383 case 5:
1384 fprintf(stderr, "ERROR: Bad argument (%s) to -N. <digit>=<string><digit> expected. \n", arg);
1385 break;
1386
1387 case 2:
1388 case 6:
1389 fprintf(stderr, "ERROR: Bad argument (%s) to -N. device minor number incorrectly specified.\n", arg);
1390 break;
1391
1392 default:
1393 fprintf(stderr, "ERROR: Bad argument (%s) to -N \n", arg);
1394 break;
1395 }
1396
1397 exit(4);
1398 }
1399
1400 if (num_matches > 3) {
1401 if (comma != ',') {
1402 fprintf(stdout, "WARNING: Processing -N argument: comma expected between multiple snoop device specification.\n");
1403 }
1404 }
1405
1406 if (nic0 >= NUM_SIMGE) {
1407 fprintf(stderr, "ERROR: Bad GE NIC number ( %d ) specified. allowed range 0 to %d \n", nic0, (NUM_SIMGE-1));
1408 exit(4);
1409 }
1410
1411 if (num_matches > 4) {
1412 if (nic1 >= NUM_SIMGE) {
1413 fprintf(stderr, "ERROR: Bad GE NIC number ( %d ) specified. allowed range 0 to %d \n", nic1, (NUM_SIMGE-1));
1414 exit(4);
1415 }
1416 }
1417
1418
1419 devbuf[0] = 0;
1420 strcat(devbuf, "/dev/");
1421 strcat(devbuf, devname0);
1422 network_device_to_snoop[nic0] = strdup(devbuf);
1423 if (network_device_to_snoop[nic0] == NULL) {
1424 fprintf(stderr, "ERROR: Ran out of memory while duplicating string %s. \n", devbuf);
1425 exit(4);
1426 }
1427 network_device_minor_num[nic0] = minor0;
1428
1429 fprintf(stdout, "Will snoop device %s%d for NIC ge%d \n", network_device_to_snoop[nic0], minor0, nic0);
1430
1431 if (num_matches == 7) {
1432 devbuf[0] = 0;
1433 strcat(devbuf, "/dev/");
1434 strcat(devbuf, devname1);
1435 network_device_to_snoop[nic1] = strdup(devbuf);
1436 if (network_device_to_snoop[nic1] == NULL) {
1437 fprintf(stderr, "ERROR: Ran out of memory while duplicating string %s. \n", devbuf);
1438 exit(4);
1439 }
1440 network_device_minor_num[nic1] = minor1;
1441
1442 fprintf(stdout, "Will snoop device %s%d for NIC ge%d \n", network_device_to_snoop[nic1], minor1, nic1);
1443 }
1444#endif
1445
1446
1447
1448/*
1449 * inputs: name is eg "ce", minor is eg 1, to snoop physical device "ce1".
1450 * returns filedescr, or -1 on error
1451 */
1452int init_snoop_device(const char * name, int minor)
1453{
1454 int fd;
1455 char buf[MAXDLBUF];
1456
1457 /* Open the device */
1458
1459 if ((fd = open(name, O_RDWR)) < 0) {
1460 printf("FYI: Unable to snoop \"%s\" (try runing as root?)\n", name);
1461 return -1;
1462 }
1463
1464
1465 /* Attach */
1466
1467 if (snoop_dlattachreq(fd, minor) < 0) goto nogood;
1468 if (snoop_dlokack(fd, buf) < 0) goto nogood;
1469
1470 /* pick up everything on the wire */
1471
1472#if 0
1473 if (snoop_dlpromisconreq(fd, DL_PROMISC_PHYS) < 0) goto nogood;
1474#endif
1475
1476 if (snoop_dlpromisconreq(fd, DL_PROMISC_SAP) < 0) goto nogood;
1477 if (snoop_dlokack(fd, buf) < 0) goto nogood;
1478
1479 /* Bind: use 2 as sap for token ring and 0 for else */
1480
1481 if (snoop_dlbindreq(fd, 0, 0, DL_CLDLS, 0, 0) < 0) goto nogood;
1482 if (snoop_dlbindack(fd, buf) < 0) goto nogood;
1483
1484 if (snoop_strioctl(fd, DLIOCRAW, -1, 0, (char *) NULL) < 0) {
1485 perror("init_snoop_device: DLIOCRAW");
1486 goto nogood;
1487 }
1488
1489 /* Flush the read side of the Stream */
1490
1491 if (ioctl(fd, I_FLUSH, FLUSHR) < 0) {
1492 perror("init_snoop_device: I_FLUSH");
1493 goto nogood;
1494 }
1495
1496good:
1497#if 0
1498 {
1499 char hostname[256];
1500 struct hostent *hp;
1501 uint_t host_ipaddr;
1502 /* get host ipaddr for filtering */
1503 /* this looks bogus, what if the host machine has multiple NICs... */
1504 gethostname(hostname, sizeof (hostname));
1505 if ((hp = gethostbyname(hostname)) == NULL) {
1506 perror("gethostbyname error\n");
1507 return;
1508 }
1509 *** this needs to be saved (for use by getmsg) in the info[fd] array ***
1510 host_ipaddr = *(uint_t *) hp->h_addr;
1511 }
1512#endif
1513 return fd;
1514
1515nogood:
1516 close (fd);
1517 return -1;
1518}
1519
1520
1521int snoop_getmsg (int fd, char * buf, int maxlen)
1522{
1523 return -1;
1524}
1525
1526int snoop_putmsg (int fd, char * buf, int len)
1527{
1528 return -1;
1529}
1530
1531
1532/* dlpi routines */
1533
1534static int
1535snoop_dlattachreq(int fd, ulong_t ppa)
1536{
1537 dl_attach_req_t attach_req;
1538 int flags;
1539 struct strbuf ctl;
1540
1541 attach_req.dl_primitive = DL_ATTACH_REQ;
1542 attach_req.dl_ppa = ppa;
1543
1544 ctl.maxlen = 0;
1545 ctl.len = sizeof(attach_req);
1546 ctl.buf = (char *) &attach_req;
1547
1548 flags = 0;
1549
1550 if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
1551 perror("dlattachreq: putmsg");
1552 return -1;
1553 }
1554
1555 return 0;
1556}
1557
1558
1559static int
1560snoop_dlokack(int fd, char *bufp)
1561{
1562 int flags;
1563 struct strbuf ctl;
1564 union DL_primitives *dlp;
1565
1566 ctl.maxlen = MAXDLBUF;
1567 ctl.len = 0;
1568 ctl.buf = bufp;
1569
1570 if (snoop_strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack")
1571 < 0)
1572 return -1;
1573
1574 dlp = (union DL_primitives *) ctl.buf;
1575
1576 if (snoop_expecting(DL_OK_ACK, dlp) < 0)
1577 return -1;
1578
1579 if (ctl.len < sizeof(dl_ok_ack_t)) {
1580 vargs_error(0, "snoop_dlokack: response len too short: %d", ctl.len);
1581 return -1;
1582 }
1583
1584 if (flags != RS_HIPRI) {
1585 vargs_error(0, "snoop_dlokack: DL_OK_ACK was not M_PCPROTO");
1586 return -1;
1587 }
1588
1589 return 0;
1590}
1591
1592
1593static int
1594snoop_dlpromisconreq(int fd, ulong_t level)
1595{
1596 dl_promiscon_req_t promiscon_req;
1597 int flags;
1598 struct strbuf ctl;
1599
1600 promiscon_req.dl_primitive = DL_PROMISCON_REQ;
1601 promiscon_req.dl_level = level;
1602
1603 ctl.maxlen = 0;
1604 ctl.len = sizeof(promiscon_req);
1605 ctl.buf = (char *) &promiscon_req;
1606
1607 flags = 0;
1608
1609 if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
1610 vargs_error(0, "snoop_dlpromisconreq: putmsg");
1611 return -1;
1612 }
1613
1614 return 0;
1615}
1616
1617
1618void
1619snoop_dlpromiscoff(int fd, ulong_t level)
1620{
1621 dl_promiscoff_req_t promiscoff_req;
1622 struct strbuf ctl;
1623 int flags;
1624
1625 promiscoff_req.dl_primitive = DL_PROMISCOFF_REQ;
1626 promiscoff_req.dl_level = level;
1627
1628 ctl.maxlen = 0;
1629 ctl.len = sizeof (promiscoff_req);
1630 ctl.buf = (char *) &promiscoff_req;
1631
1632 flags = 0;
1633
1634 if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0)
1635 vargs_error(0, "dlpromiscoff: putmsg");
1636
1637 return;
1638}
1639
1640
1641static int
1642snoop_dlbindreq(int fd,
1643 ulong_t sap,
1644 ulong_t max_conind,
1645 ulong_t service_mode,
1646 ulong_t conn_mgmt,
1647 ulong_t xidtest)
1648{
1649 dl_bind_req_t bind_req;
1650 int flags;
1651 struct strbuf ctl;
1652
1653 bind_req.dl_primitive = DL_BIND_REQ;
1654 bind_req.dl_sap = sap;
1655 bind_req.dl_max_conind = max_conind;
1656 bind_req.dl_service_mode = service_mode;
1657 bind_req.dl_conn_mgmt = conn_mgmt;
1658 bind_req.dl_xidtest_flg = xidtest;
1659
1660 ctl.maxlen = 0;
1661 ctl.len = sizeof (bind_req);
1662 ctl.buf = (char *) &bind_req;
1663
1664 flags = 0;
1665
1666 if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
1667 perror("snoop_dlbindreq: putmsg");
1668 return -1;
1669 }
1670
1671 return 0;
1672}
1673
1674
1675static int
1676snoop_dlbindack(int fd, char *bufp)
1677{
1678 int flags;
1679 struct strbuf ctl;
1680 union DL_primitives *dlp;
1681
1682 ctl.maxlen = MAXDLBUF;
1683 ctl.len = 0;
1684 ctl.buf = bufp;
1685
1686 if (snoop_strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack")
1687 < 0)
1688 return -1;
1689
1690 dlp = (union DL_primitives *) ctl.buf;
1691
1692 if (snoop_expecting(DL_BIND_ACK, dlp) < 0)
1693 return -1;
1694
1695 if (flags != RS_HIPRI) {
1696 vargs_error(0, "dlbindack: DL_OK_ACK was not M_PCPROTO");
1697 return -1;
1698 }
1699
1700 if (ctl.len < sizeof (dl_bind_ack_t)) {
1701 vargs_error(0, "dlbindack: short response ctl.len: %d", ctl.len);
1702 return -1;
1703 }
1704
1705 return 0;
1706}
1707
1708
1709static int
1710snoop_strioctl(int fd, int cmd, int timout, int len, char *dp)
1711{
1712 int rc;
1713 struct strioctl sioc;
1714
1715 sioc.ic_cmd = cmd;
1716 sioc.ic_timout = timout;
1717 sioc.ic_len = len;
1718 sioc.ic_dp = dp;
1719
1720 rc = ioctl(fd, I_STR, &sioc);
1721
1722 if (rc < 0)
1723 return (rc);
1724 else
1725 return (sioc.ic_len);
1726}
1727
1728
1729#define MAXWAIT 15
1730
1731#ifdef __cplusplus
1732extern "C" {
1733#endif
1734
1735static void snoop_sigalrm (int);
1736
1737#ifdef __cplusplus
1738}
1739#endif
1740
1741static void
1742snoop_sigalrm(int i)
1743{
1744 (void) printf("snoop_sigalrm (%d) : TIMEOUT", i);
1745
1746 return;
1747}
1748
1749
1750
1751static int
1752snoop_strgetmsg(int fd,
1753 struct strbuf *ctlp,
1754 struct strbuf *datap,
1755 int *flagsp,
1756 const char *caller)
1757{
1758 int rc;
1759 char errmsg[80];
1760
1761 /*
1762 * Start timer.
1763 */
1764
1765 (void) signal(SIGALRM, snoop_sigalrm);
1766
1767 if (alarm(MAXWAIT) < 0) {
1768 (void) snprintf(errmsg, 80, "%s: alarm", caller);
1769 perror(errmsg);
1770 return -1;
1771 }
1772
1773 /*
1774 * Set flags argument and issue getmsg().
1775 */
1776
1777 *flagsp = 0;
1778
1779 if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
1780 (void) snprintf(errmsg, 80, "%s: getmsg", caller);
1781 perror(errmsg);
1782 return -1;
1783 }
1784
1785 /*
1786 * Stop timer.
1787 */
1788
1789 if (alarm(0) < 0) {
1790 (void) snprintf(errmsg, 80, "%s: alarm", caller);
1791 perror(errmsg);
1792 return -1;
1793 }
1794
1795 /*
1796 * Check for MOREDATA and/or MORECTL.
1797 */
1798
1799 if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) {
1800 vargs_error(0, "%s: MORECTL|MOREDATA", caller);
1801 return -1;
1802 }
1803
1804 if (rc & MORECTL) {
1805 vargs_error(0, "%s: MORECTL", caller);
1806 return -1;
1807 }
1808
1809 if (rc & MOREDATA) {
1810 vargs_error(0, "%s: MOREDATA", caller);
1811 return -1;
1812 }
1813
1814 /*
1815 * Check for at least sizeof(long) control data portion.
1816 */
1817
1818 if (ctlp->len < sizeof(long)) {
1819 vargs_error(0, "getmsg: control portion length < sizeof(long): %d", ctlp->len);
1820 return -1;
1821 }
1822
1823 return 0;
1824}
1825
1826
1827static const char *
1828snoop_dlprim(ulong_t prim)
1829{
1830#define CASERET(s) case s: return (#s)
1831
1832 switch ((int)prim) {
1833
1834 CASERET(DL_INFO_REQ);
1835 CASERET(DL_INFO_ACK);
1836 CASERET(DL_ATTACH_REQ);
1837 CASERET(DL_DETACH_REQ);
1838 CASERET(DL_BIND_REQ);
1839 CASERET(DL_BIND_ACK);
1840 CASERET(DL_UNBIND_REQ);
1841 CASERET(DL_OK_ACK);
1842 CASERET(DL_ERROR_ACK);
1843 CASERET(DL_SUBS_BIND_REQ);
1844 CASERET(DL_SUBS_BIND_ACK);
1845 CASERET(DL_UNITDATA_REQ);
1846 CASERET(DL_UNITDATA_IND);
1847 CASERET(DL_UDERROR_IND);
1848 CASERET(DL_UDQOS_REQ);
1849 CASERET(DL_CONNECT_REQ);
1850 CASERET(DL_CONNECT_IND);
1851 CASERET(DL_CONNECT_RES);
1852 CASERET(DL_CONNECT_CON);
1853 CASERET(DL_TOKEN_REQ);
1854 CASERET(DL_TOKEN_ACK);
1855 CASERET(DL_DISCONNECT_REQ);
1856 CASERET(DL_DISCONNECT_IND);
1857 CASERET(DL_RESET_REQ);
1858 CASERET(DL_RESET_IND);
1859 CASERET(DL_RESET_RES);
1860 CASERET(DL_RESET_CON);
1861
1862 default:
1863 fprintf(stderr, "snoop_dlprim: unknown primitive 0x%x", prim);
1864 return "unknown primitive";
1865 }
1866}
1867
1868
1869static int
1870snoop_expecting (int prim, union DL_primitives *dlp)
1871{
1872 if (dlp->dl_primitive != (ulong_t) prim) {
1873 fprintf(stderr, "Failed to initialize device for snooping \n");
1874 vargs_error(0, "expected %s got %s", snoop_dlprim(prim),
1875 snoop_dlprim(dlp->dl_primitive));
1876 return -1;
1877 }
1878
1879 return 0;
1880}
1881
1882
1883
1884
1885
1886void
1887vargs_error(int thresh, const char *fmt, ...)
1888{
1889 if (netsim_debug >= thresh) {
1890 va_list ap;
1891
1892 va_start(ap, fmt);
1893 vfprintf(stderr, fmt, ap);
1894 (void) fprintf(stderr, "\n");
1895 va_end(ap);
1896/* exit(1); NOT ACCEPTABLE !!! */
1897 }
1898}
1899
1900
1901
1902
1903
1904
1905
1906////////////////////////////////////////////////////////////////////////////////
1907// //
1908// The following section is for Common utility functions //
1909// //
1910////////////////////////////////////////////////////////////////////////////////
1911
1912
1913
1914/*
1915 * this ether_cksum function was copied from Gigabit Ethernet driver,
1916 * which does not inspire much confidence, look at the mish-mash of
1917 * indexed and pointed memory references...
1918 */
1919#if 1
1920uint16_t
1921ether_chksum(char *buf, int offset, int len)
1922{
1923 int index, count;
1924 uint_t csum;
1925 ushort_t *shortP, value;
1926
1927 value = 0;
1928 csum = 0;
1929
1930 count = len & (~0x1);
1931 shortP = (ushort_t *) (buf + offset);
1932
1933 if (((unsigned long ) shortP) & 0x1) {
1934 fprintf(stderr, "ERROR: ether_cksum odd address. src %p \n", shortP);
1935 return -1; exit(1);
1936 }
1937
1938 for (index=offset; index<(count+offset); index += sizeof(ushort_t))
1939 csum += *shortP++;
1940
1941 if (len & 0x1) {
1942 value = buf[index] << 8;
1943 csum += value;
1944 }
1945
1946 while (csum>>16)
1947 csum = (csum & 0xffff) + (csum >> 16);
1948
1949 csum = ~csum;
1950 csum = csum & 0x0000FFFF;
1951
1952 return csum;
1953}
1954#else
1955//
1956// a little bit simpler version!
1957//
1958uint16_t
1959ether_chksum(char *buf, int offset, int len)
1960{
1961 ushort_t *p = (ushort_t*) (buf + offset);
1962 int csum = 0;
1963
1964 // add up all the whole double-bytes...
1965 for (; len>1; len-=2)
1966 csum += *p++;
1967
1968 // and if there is an odd byte at the end...
1969 if (len)
1970 csum += (*((unsigned char *)p)) & 0xff00; // big-endian !!!
1971
1972 // now wrap around the checksum overflow
1973 while (csum>>16)
1974 csum = (csum & 0xffff) + (csum >> 16);
1975
1976 // finish by taking the 1's complement
1977 csum = (~csum) & 0x0000ffff;
1978
1979 return csum;
1980}
1981#endif
1982
1983
1984
1985//
1986// TCP checksum including the "pseudo header" of fields from ip header
1987//
1988int tcp_chksum (ethpacket_t * pkt)
1989{
1990 ushort_t *p = (ushort_t*) pkt;
1991 int hdrcsum = 0;
1992 int csum = 0;
1993 int bytes = ETHHDRSZ + pkt->u.ip.iplen; // Total pkt-len Incl ether hdr.
1994 int i;
1995
1996 // IP protocol
1997 csum = (p[11] & 0x00ff);
1998
1999 // IP data length
2000 csum += (pkt->u.ip.iplen - 4*(pkt->u.ip.verlen & 0x0f));
2001
2002 // IP src and dest addrs
2003 csum += p[13] + p[14] + p[15] + p[16];
2004
2005 // now the TCP header and data
2006 for (i=17; i<(bytes/2); i++)
2007 csum += p[i];
2008
2009 // and if there is an odd byte at the end...
2010 if (bytes & 0x1)
2011 csum += p[i] & 0xff00;
2012
2013 // now wrap the checksum overflow back around
2014 while (csum>>16)
2015 csum = (csum & 0xffff) + (csum >> 16);
2016
2017 // finish by taking the 1's complement
2018 csum = (~csum) & 0x0000ffff;
2019
2020 return csum;
2021}
2022
2023
2024
2025// compute the raw checksum of just the tcp pseudo header
2026//
2027int tcp_pseudocs (ethpacket_t * pkt)
2028{
2029 ushort_t *p = (ushort_t*) pkt;
2030 int csum = 0;
2031 int bytes = ETHHDRSZ + pkt->u.ip.iplen; // Total pkt-len Incl ether hdr.
2032 int i;
2033
2034 // IP protocol
2035 csum = (p[11] & 0x00ff);
2036
2037 // IP data length
2038 csum += (pkt->u.ip.iplen - 4*(pkt->u.ip.verlen & 0x0f));
2039
2040 // IP src and dest addrs
2041 csum += p[13] + p[14] + p[15] + p[16];
2042
2043
2044 // now wrap the checksum overflow back around
2045 while (csum>>16)
2046 csum = (csum & 0xffff) + (csum >> 16);
2047
2048 // raw checksum, no 1's complement of the result here...
2049
2050 return csum;
2051}
2052
2053
2054
2055
2056
2057
2058
2059
2060uint16_t
2061ether_reverse_hword(uint16_t value)
2062{
2063 char reverse_buf[2];
2064
2065 reverse_buf[0] = value & 0x00FF;
2066 reverse_buf[1] = (value >> 8) & 0x00FF;
2067
2068 return *(uint16_t *) reverse_buf;
2069}
2070
2071
2072uint32_t
2073ether_reverse_word(uint32_t value)
2074{
2075 char reverse_buf[4];
2076
2077 reverse_buf[0] = value & 0x00FF;
2078 reverse_buf[1] = (value >> 8) & 0x00FF;
2079 reverse_buf[2] = (value >> 16) & 0x00FF;
2080 reverse_buf[3] = (value >> 24) & 0x00FF;
2081
2082 return *(uint32_t *) reverse_buf;
2083}
2084
2085
2086uint64_t
2087ether_reverse_lword(uint64_t value)
2088{
2089 char reverse_buf[8];
2090
2091 reverse_buf[0] = value & 0x00FF;
2092 reverse_buf[1] = (value >> 8) & 0x00FF;
2093 reverse_buf[2] = (value >> 16) & 0x00FF;
2094 reverse_buf[3] = (value >> 24) & 0x00FF;
2095 reverse_buf[4] = (value >> 32) & 0x00FF;
2096 reverse_buf[5] = (value >> 40) & 0x00FF;
2097 reverse_buf[6] = (value >> 48) & 0x00FF;
2098 reverse_buf[7] = (value >> 56) & 0x00FF;
2099
2100 return *(uint64_t *) reverse_buf;
2101}
2102
2103
2104
2105
2106// ---------------------------------------------------------------------------
2107// SNOOP
2108// debug levels: 0= nada; 1= decoded; 2= raw hex
2109//
2110int
2111netsim_snoop (char * buf, int buflen, int dbglevel)
2112{
2113 int cs, pktlen;
2114 if (dbglevel >= 1) { // -------------------------------
2115
2116 ethpacket_t * packet = (ethpacket_t*) buf;
2117 int et,ipp;
2118 et = eth_type(packet);
2119 fprintf (stderr, "eth/%d{mac:%02x->%02x, ", buflen,
2120 eth_srcMAC(packet) & 0xff,
2121 eth_dstMAC(packet) & 0xff);
2122 switch (et) {
2123 case ET_IPv4: {
2124 pktlen = ETHHDRSZ + packet->u.ip.iplen;
2125 fprintf(stderr,"ip/%d", packet->u.ip.iplen);
2126 ipp = eth_ipproto(packet);
2127 fprintf (stderr, "{ip:%d->%d, ",
2128 eth_srcIP(packet) & 0xff,
2129 eth_dstIP(packet) & 0xff);
2130 switch (ipp) {
2131 case IP_TCP: {
2132 fprintf(stderr,"tcp");
2133 if (eth_tcpzlenack(packet)) { /* happens a lot */
2134 fprintf(stderr, "-ack(%s)\n",
2135 eth_tcp_string(eth_srcPORT(packet)));
2136 break;
2137 }
2138 if (packet->u.ip.u.tcp.flags & 0x0002/*TCP_SYN_FLAG*/)
2139 fprintf(stderr, "connect(");
2140 if (packet->u.ip.u.tcp.flags & 0x0001/*TCP_FIN_FLAG*/)
2141 fprintf(stderr, "disconn(");
2142
2143 fprintf(stderr," %s->%d",
2144 eth_tcp_string(eth_srcPORT(packet)),
2145 eth_tcp_string(eth_dstPORT(packet)));
2146
2147 if (packet->u.ip.u.tcp.flags & 0x0002/*TCP_SYN_FLAG*/)
2148 fprintf(stderr, ")");
2149 if (packet->u.ip.u.tcp.flags & 0x0001/*TCP_FIN_FLAG*/)
2150 fprintf(stderr, ")");
2151 if ((cs = tcp_chksum (packet)) != 0)
2152 fprintf(stderr," ***chksum error 0x%04x*** ", cs);
2153 } break;
2154
2155 case IP_UDP: {
2156 fprintf(stderr,"udp/%d", packet->u.ip.u.udp.udplen);
2157 fprintf(stderr," %d->%d", packet->u.ip.u.udp.srcPORT,
2158 packet->u.ip.u.udp.dstPORT);
2159 if ((cs = tcp_chksum (packet)) != 0)
2160 fprintf(stderr," ***chksum error 0x%04x*** ", cs);
2161 } break;
2162
2163 case IP_IP: {
2164 fprintf(stderr," %s", "ip-encaps");/*ip-encapsulation*/
2165 } break;
2166
2167 case IP_ICMP: {
2168 fprintf(stderr," %s", eth_icmp_string (
2169 eth_icmptype (packet), eth_icmpcode (packet)));
2170 } break;
2171
2172 case IP_IGMP: {
2173 fprintf(stderr," %s", "igmp");/*gateway-management-prot*/
2174 } break;
2175
2176 case IP_GGP: {
2177 fprintf(stderr," %s", "ggp");/*gateway-to-gateway-prot*/
2178 } break;
2179
2180 case IP_EGP: {
2181 fprintf(stderr," %s", "ext-gateway");/*exterior-gw-prot*/
2182 } break;
2183
2184 case IP_IGP: {
2185 fprintf(stderr," %s", "int-gateway");/*interior-gw-prot*/
2186 } break;
2187
2188 default: { // unknown ip-header-protocol field
2189 fprintf (stderr, " %d", ipp);
2190 } break;
2191 }
2192 } break;
2193 case ET_ARP: {
2194 pktlen = ETHHDRSZ + sizeof(packet->u.arp);
2195 if (packet->u.arp.op == 1)
2196 fprintf (stderr, "arp rqst %d", packet->u.arp.dstIP[3]);
2197 else if (packet->u.arp.op == 2)
2198 fprintf (stderr, "arp reply %d", packet->u.arp.dstIP[3]);
2199 else
2200 fprintf (stderr, "arp ???");
2201 } break;
2202 case ET_RARP: {
2203 pktlen = ETHHDRSZ + sizeof(packet->u.arp);
2204 if (packet->u.arp.op == 3)
2205 fprintf (stderr, "rarp rqst %d", packet->u.arp.dstIP[3]);
2206 else if (packet->u.arp.op == 4)
2207 fprintf (stderr, "rarp reply %d",packet->u.arp.dstIP[3]);
2208 else
2209 fprintf (stderr, "rarp ???");
2210 } break;
2211 default: { // unknown ether-header-type field
2212 pktlen = buflen;
2213 fprintf (stderr, " %d", et);
2214 } break;
2215 }
2216 fprintf (stderr, "}\n");
2217
2218 }
2219 if (dbglevel >= 2) {
2220 if (pktlen != buflen) {
2221 fprintf(stderr,"------ length of buf/%d != pkt/%d \n", buflen, pktlen);
2222 }
2223 }
2224
2225
2226 if (dbglevel >= 3) { // --------------------------------------
2227 int i;
2228
2229 fprintf(stderr, "\n");
2230 for (i=0; i<pktlen; i+=16) {
2231 int j,lim;
2232 char out[17];
2233 lim = pktlen-i;
2234 if (lim>16) lim = 16;
2235 fprintf(stderr, "%04x :",i);
2236 for (j=0; j<lim; j++) {
2237 int c = *(unsigned char *)&(buf[i+j]);
2238 fprintf(stderr, " %02x",c);
2239 out[j] = c>=32 && c<127 ? c : '.';
2240 }
2241 out[j] = 0;
2242 for (; j<16; j++) fprintf(stderr, " ..");
2243 fprintf(stderr, "\t: %s\n",out);
2244 }
2245 fprintf(stderr, "\n");
2246 }
2247
2248 if (dbglevel >= 4) { // --------------------------------------
2249 }
2250 return 1;
2251}
2252
2253
2254
2255
2256
2257// these aren't appropriate for inlining, but they have to go somewhere...
2258
2259const char * eth_tcp_string (int tcptype)
2260{
2261 static char buf[10];
2262
2263 switch (tcptype) {
2264 case TCP_ECHO: return "echo";
2265 case TCP_FTPDATA: return "ftpdata";
2266 case TCP_FTP: return "ftp";
2267 case TCP_SSH: return "ssh";
2268 case TCP_TELNET: return "telnet";
2269 case TCP_TIME: return "time";
2270 case TCP_DNS: return "dns";
2271 case TCP_HTTP: return "http";
2272 case TCP_HTTPS: return "https";
2273 case TCP_SUNRPC: return "sunrpc";
2274 case TCP_LDAP: return "ldap";
2275 case TCP_REXEC: return "rexec";
2276 case TCP_RLOGIN: return "rlogin";
2277 case TCP_RSHELL: return "rshell";
2278 default:
2279 sprintf(&buf[0], "%d", tcptype);
2280 return &buf[0];
2281 }
2282}
2283
2284const char * eth_icmp_string (int icmptype, int icmpcode)
2285{
2286 static char buf[10];
2287
2288 switch (icmptype) {
2289 case ICMP_ECHOREPLY: return "echo_reply";
2290 case ICMP_UNREACHABLE:
2291 switch (icmpcode) {
2292 case 0: return "network_unreachable";
2293 case 1: return "host_unreachable";
2294 case 2: return "protocol_unreachable";
2295 case 3: return "port_unreachable";
2296 case 4: return "fragment_unreachable";
2297 case 5: return "route_unreachable";
2298 case 6: return "network_unknown";
2299 case 7: return "host_unknown";
2300 case 8: return "obsolete_unreachable";
2301 case 9: return "network_prohibited";
2302 case 10: return "host_prohibited";
2303 case 11: return "network_tos_unreachable";
2304 case 12: return "host_tos_unreachable";
2305 default: return "unreachable_?";
2306 }
2307 case ICMP_SRCQUENCH: return "source_quench";
2308 case ICMP_REDIRECT:
2309 switch (icmpcode) {
2310 case 0: return "redirect_network";
2311 case 1: return "redirect_host";
2312 case 2: return "redirect_tos_network";
2313 case 3: return "redirect_tos_host";
2314 default: return "redirect_?";
2315 }
2316 case ICMP_ECHO: return "echo_request";
2317 case ICMP_ROUTERREPLY: return "router_reply";
2318 case ICMP_ROUTERREQST: return "router_request";
2319 case ICMP_TIMEOUT: return "time_exceeded";
2320 case ICMP_INVARG: return "invalid_parameter";
2321 case ICMP_TIMESTAMP: return "timestamp_request";
2322 case ICMP_TSTAMPREPLY: return "timestamp_reply";
2323 case ICMP_INFO: return "obsolete_request";
2324 case ICMP_INFOREPLY: return "obsolete_reply";
2325 case ICMP_MASK: return "mask_request";
2326 case ICMP_MASKREPLY: return "mask_reply";
2327 default:
2328 sprintf(&buf[0], "%d", icmptype);
2329 return &buf[0];
2330 }
2331}
2332