* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: eth.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
* structs & functions to access ethernet packet fields...
* Note, for when ip.verlen = 0x45, ie standard 5-word (20-uchar) ip-header,
* and when tcp.?? = ??, ie standard 20-uchar tcp header:
* min eth-pkt = 64 uchars
* -4 (eth-tailer CRC) = 46 min eth-data
* -20 (ip-header) = 26 min padding for "empty" ip-pkt
* -20 (tcp-header) = 6 min padding for "empty" tcp-pkt
* max eth-pkt = 1518 uchars
* - 4 (eth-trailer CRC) = 1500 max eth-data-MTU
* - 20 (ip-header) = 1480 max ip-data-MTU
* - 20 (tcp-header) = 1460 max tcp-data-MTU
* all of the "word" sized fields are UN-aligned, Argh!!!...
* @@@ Danger Will Robinson, Danger:
* -1 and -2 seem to be valid ip addresses ???
typedef unsigned char uchar
;
typedef unsigned short ushort
;
typedef unsigned int uword
;
#define ETH_MAX 1518 /* the whole thing, including header and CRC */
#define ETH_BUF_MAX 1514 /* without the CRC */
#define ETH_DATA_MAX 1500 /* without the CRC or the header, aka `MTU' */
#define ETHHDRSZ 14 /* ethernet packet header size */
#define ETH_MIN 64 /* the whole thing, including header and CRC */
#define IP_DATA_MAX 1480 /* eth minus the 20-uchar ip header */
#define TCP_DATA_MAX 1460 /* ip minus the 20-uchar tcp header */
#define IP_ICMP 0x01 /* Inet Control Message Prot <--- */
#define IP_IGMP 0x02 /* Inet Gateway Message Prot <--- */
#define IP_GGP 0x03 /* Gateway-to-Gateway Prot */
#define IP_IP 0x04 /* IP-in-IP-encapsulation Prot */
#define IP_ST 0x05 /* Stream Prot */
#define IP_TCP 0x06 /* Transmission Control Prot <--- */
#define IP_EGP 0x08 /* Exterior-Gateway Prot */
#define IP_IGP 0x09 /* Interior-Gateway Prot */
#define IP_UDP 0x11 /* User Datagram Prot <--- */
/* (some) ICMP message Types */
#define ICMP_UNREACHABLE 3
#define ICMP_ROUTERREPLY 9
#define ICMP_ROUTERREQST 10
#define ICMP_TIMESTAMP 13
#define ICMP_TSTAMPREPLY 14
#define ICMP_INFOREPLY 16
#define ICMP_MASKREPLY 18
#define ICMP_DOMNAMREQST 37
#define ICMP_DOMNAMREPLY 38
uchar dstMAC
[6]; /* all 1's for a broadcast Request 0*/
ushort frametype
; /* 0x0800 => ET_IPv4 6*/
/* 0x0806 => ARP, 0x0835 => RARP */
char eth_data
[ ETH_DATA_MAX
];
ushort hardtype
; /* 1 => Ethernet 7*/
ushort prottype
; /* 0x0800 => IP 8*/
uchar hardsize
; /* 6, mac size 9*/
uchar protsize
; /* 4, ip size */
ushort op
; /* 1 => ARP, 2 => reply,
3 => RARP, 4 => reply 10*/
/* ARP-Request ARP-Reply */
uchar srcMAC
[6]; /* requestor -----> replyor 11*/
uchar srcIP
[4]; /* requestor / ----> replyor 14*/
uchar dstMAC
[6]; /* <empty>----- / 16*/
uchar dstIP
[4]; /* specified----- 19*/
uchar verlen
; /* 0x45 -> IPv4 and std 5-word header */
ushort iplen
; /* ipheader + ipdata, NOT incl eth hdr*/
uchar protocol
; /* 0x06=>TCP, 0x11=>UDP, 0x01=> ICMP */
char ip_data
[ IP_DATA_MAX
];
uchar data
[6]; /*min padding for "empty" pkt*/
char guard
[120]; /* protect from buffer overflow... */
typedef struct { /*offset*/
ushort frametype
; /* 0x0800 -> ET_IPv4 6*/
uchar verlen
; /* 0x45 -> std IP hdr 7*/
ushort iplen
; /* 20 for empty data packet */
uchar protocol
; /* 0xff -> netsim connect packet 11*/
inline uint16_t eth_short (uchar
* x
)
{ return ((unsigned short*)(x
))[0]; }
inline uint32_t eth_int (uchar
* x
)
{ return (((unsigned short*)(x
))[0])<<16
| (((unsigned short*)(x
))[1]); }
inline uint64_t eth_long (uchar
* x
)
{ return ((uint64_t)(((unsigned short*)(x
))[0])<<32)
| ((uint64_t)(((unsigned short*)(x
))[1])<<16)
| (uint64_t)(((unsigned short*)(x
))[2]); }
inline bool eth_isbroadcast(ethpacket_t
* x
)
{ return eth_short (&x
->dstMAC
[0]) == 0xffff
&& eth_short (&x
->dstMAC
[2]) == 0xffff
&& eth_short (&x
->dstMAC
[4]) == 0xffff; }
inline int eth_length (ethpacket_t
* x
)
if (x
->frametype
== ET_ARP
) return 42;
else if (x
->frametype
== ET_IPv4
)
return ETHHDRSZ
+ x
->u
.ip
.iplen
;
inline unsigned short eth_type (ethpacket_t
* x
) /* arp, ipv4, ... */
inline unsigned short eth_arpop (ethpacket_t
* x
) /* reqest, reply, */
inline unsigned char eth_ipproto (ethpacket_t
* x
) /* tcp, upd, icmp,...*/
{ return x
->u
.ip
.protocol
; }
inline unsigned char eth_ipversion (ethpacket_t
* x
)
{ return x
->u
.ip
.verlen
>> 4; }
inline unsigned char eth_iphdrlen (ethpacket_t
* x
)
{ return 4 * (x
->u
.ip
.verlen
& 0xf); }
inline unsigned char eth_ipverlen (ethpacket_t
* x
)
{ return x
->u
.ip
.verlen
; }
inline unsigned char eth_icmptype (ethpacket_t
* x
)
{ return x
->u
.ip
.u
.icmp
.type
; }
inline unsigned char eth_icmpcode (ethpacket_t
* x
)
{ return x
->u
.ip
.u
.icmp
.code
; }
inline unsigned char eth_tcptype (ethpacket_t * x)
{ return x->u.ip.u.tcp.protocol; }
* I think we have to look for "known" tcp port numbers... *
inline bool eth_tcpzlenack (ethpacket_t
* x
)
{ return (x
->frametype
== ET_IPv4
)
&& (x
->u
.ip
.protocol
== IP_TCP
)
&& (x
->u
.ip
.u
.tcp
.flags
& 0x10); }
/* fetch MAC addresses */
inline uint64_t eth_srcMAC(ethpacket_t
* x
)
{ return eth_long (x
->srcMAC
); }
inline uint64_t eth_dstMAC(ethpacket_t
* x
)
{ return eth_long (x
->dstMAC
); }
inline void sprint_MACaddr (char * buf
, uint64_t mac
)
sprintf (buf
, "%02x:%02x:%02x:%02x:%02x:%02x", /* char buf[18] */
(int)(mac
>>40)&0xff, (int)(mac
>>32)&0xff, (int)(mac
>>24)&0xff,
(int)(mac
>>16)&0xff, (int)(mac
>>8)&0xff, (int)(mac
>>0)&0xff);
inline uint32_t eth_srcIP(ethpacket_t
* x
)
if (eth_type (x
) == ET_ARP
) return eth_int (x
->u
.arp
.srcIP
);
else if (eth_type (x
) == ET_IPv4
)
return eth_int (x
->u
.ip
.srcIP
);
inline uint32_t eth_dstIP(ethpacket_t
* x
)
if (eth_type (x
) == ET_ARP
) return eth_int (x
->u
.arp
.dstIP
);
else if (eth_type (x
) == ET_IPv4
)
return eth_int (x
->u
.ip
.dstIP
);
inline void sprint_IPaddr (char * buf
, uint32_t ip
) /* char buf[16] */
sprintf (buf
, "%d:%d:%d:%d",
(ip
>>24)&0xff, (ip
>>16)&0xff, (ip
>>8)&0xff, (ip
>>0)&0xff);
inline uint32_t sscan_IPaddr (char * buf
)
unsigned int i1
,i2
,i3
,i4
;
if (sscanf (buf
, "%d:%d:%d:%d", &i1
, &i2
, &i3
, &i4
) == 4) {
return (i1
&0xff)<<24 | (i2
&0xff)<<16 | (i3
&0xff)<<8 | (i4
&0xff)<<0;
/* fetch TCP addresses */
inline uint32_t eth_srcPORT(ethpacket_t
* x
)
if (eth_type (x
) == ET_IPv4
&& eth_ipverlen (x
) == 0x45
&& eth_ipproto (x
) == IP_TCP
)
return x
->u
.ip
.u
.tcp
.srcPORT
;
inline uint32_t eth_dstPORT(ethpacket_t
* x
)
if (eth_type (x
) == ET_IPv4
&& eth_ipverlen (x
) == 0x45
&& eth_ipproto (x
) == IP_TCP
)
return x
->u
.ip
.u
.tcp
.dstPORT
;
const char * eth_tcp_string (int tcptype
);
const char * eth_icmp_string (int icmptype
, int icmpcode
);
#else /*** see "netsim.cc" ***/
char * eth_tcp_string (int tcptype
)
case TCP_ECHO
: return "echo";
case TCP_FTPDATA
: return "ftpdata";
case TCP_FTP
: return "ftp";
case TCP_SSH
: return "ssh";
case TCP_TELNET
: return "telnet";
case TCP_TIME
: return "time";
case TCP_DNS
: return "dns";
case TCP_HTTP
: return "http";
case TCP_HTTPS
: return "https";
case TCP_SUNRPC
: return "sunrpc";
case TCP_LDAP
: return "ldap";
case TCP_REXEC
: return "rexec";
case TCP_RLOGIN
: return "rlogin";
case TCP_RSHELL
: return "rshell";
sprintf(&buf
[0], "%d", tcptype
);
char * eth_icmp_string (int icmptype
, int icmpcode
)
case ICMP_ECHOREPLY
: return "echo_reply";
case 0: return "network_unreachable";
case 1: return "host_unreachable";
case 2: return "protocol_unreachable";
case 3: return "port_unreachable";
case 4: return "fragment_unreachable";
case 5: return "route_unreachable";
case 6: return "network_unknown";
case 7: return "host_unknown";
case 8: return "obsolete_unreachable";
case 9: return "network_prohibited";
case 10: return "host_prohibited";
case 11: return "network_tos_unreachable";
case 12: return "host_tos_unreachable";
default: return "unreachable_?";
case ICMP_SRCQUENCH
: return "source_quench";
case 0: return "redirect_network";
case 1: return "redirect_host";
case 2: return "redirect_tos_network";
case 3: return "redirect_tos_host";
default: return "redirect_?";
case ICMP_ECHO
: return "echo_request";
case ICMP_ROUTERREPLY
: return "router_reply";
case ICMP_ROUTERREQST
: return "router_request";
case ICMP_TIMEOUT
: return "time_exceeded";
case ICMP_INVARG
: return "invalid_parameter";
case ICMP_TIMESTAMP
: return "timestamp_request";
case ICMP_TSTAMPREPLY
: return "timestamp_reply";
case ICMP_INFO
: return "obsolete_request";
case ICMP_INFOREPLY
: return "obsolete_reply";
case ICMP_MASK
: return "mask_request";
case ICMP_MASKREPLY
: return "mask_reply";
sprintf(&buf
[0], "%d", icmptype
);
#if 0 /*** see "netsim.cc"/netsim_dbgpacket() ***/
et
= eth_type(&buffer
.packet
);
fprintf (stderr
, "eth{%02x->%02x,%s",
eth_srcMAC(&buffer
.packet
) & 0xff,
eth_dstMAC(&buffer
.packet
) & 0xff,
et
== ET_RARP
: "rarp" ? "?") );
ipt
= eth_ipproto(&buffer
.packet
);
fprintf (stderr
, "{%d.%d->%d.%d,%s",
eth_srcIP(&buffer
.packet
) & 0xff,
eth_dstIP(&buffer
.packet
) & 0xff,