Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / include / eth.h
/*
* ========== 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 ============================================
*/
/*
* "eth.h"
*
* 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
* -14 (eth-header)
* -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
* - 14 (eth-header)
* - 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 ???
*/
#ifndef _ETH_H
#define _ETH_H
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 */
/* Ethernet Types */
#define ET_IPv4 0x0800
#define ET_ARP 0x0806
#define ET_RARP 0x0835
/* (some) IP Types */
#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_ECHOREPLY 0
#define ICMP_UNREACHABLE 3
#define ICMP_SRCQUENCH 4
#define ICMP_REDIRECT 5
#define ICMP_ECHO 8
#define ICMP_ROUTERREPLY 9
#define ICMP_ROUTERREQST 10
#define ICMP_TIMEOUT 11
#define ICMP_INVARG 12
#define ICMP_TIMESTAMP 13
#define ICMP_TSTAMPREPLY 14
#define ICMP_INFO 15
#define ICMP_INFOREPLY 16
#define ICMP_MASK 17
#define ICMP_MASKREPLY 18
#define ICMP_DOMNAMREQST 37
#define ICMP_DOMNAMREPLY 38
/* (a few) TCP Types */
#define TCP_ECHO 7
#define TCP_FTPDATA 20
#define TCP_FTP 21
#define TCP_SSH 22
#define TCP_TELNET 23
#define TCP_TIME 37
#define TCP_DNS 53
#define TCP_HTTP 80
#define TCP_HTTPS 443
#define TCP_SUNRPC 111
#define TCP_LDAP 389
#define TCP_REXEC 512
#define TCP_RLOGIN 513
#define TCP_RSHELL 514
typedef struct {
uchar dstMAC[6]; /* all 1's for a broadcast Request 0*/
uchar srcMAC[6]; /* 3*/
ushort frametype; /* 0x0800 => ET_IPv4 6*/
/* 0x0806 => ARP, 0x0835 => RARP */
union {
char eth_data[ ETH_DATA_MAX ];
struct arp_s {
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*/
} arp;
struct ip_s {
uchar verlen; /* 0x45 -> IPv4 and std 5-word header */
uchar TofS;
ushort iplen; /* ipheader + ipdata, NOT incl eth hdr*/
ushort ident;
ushort flags;
uchar time_to_live;
uchar protocol; /* 0x06=>TCP, 0x11=>UDP, 0x01=> ICMP */
ushort hdrchecksum;
uchar srcIP[4]; /* 13*/
uchar dstIP[4]; /* 15*/
union {
char ip_data [ IP_DATA_MAX ];
struct icmp_s {
char type;
char code;
ushort chksum;
} icmp;
struct udp_s {
ushort srcPORT;
ushort dstPORT;
ushort udplen;
ushort checksum;
} udp;
struct tcp_s {
ushort srcPORT; /* 17*/
ushort dstPORT; /* 18*/
uchar SeqNum[4];
uchar AckNum[4];
ushort flags;
ushort win_size;
ushort checksum;
ushort UrgentPtr;
uchar data[6]; /*min padding for "empty" pkt*/
} tcp;
} u;
} ip;
} u;
char CRC[4];
char guard[120]; /* protect from buffer overflow... */
} ethpacket_t;
/* short*/
typedef struct { /*offset*/
uchar dstMAC[6];
uchar srcMAC[6];
ushort frametype; /* 0x0800 -> ET_IPv4 6*/
struct {
uchar verlen; /* 0x45 -> std IP hdr 7*/
uchar TofS;
ushort iplen; /* 20 for empty data packet */
ushort ident;
ushort flags;
uchar time_to_live;
uchar protocol; /* 0xff -> netsim connect packet 11*/
ushort hdrchecksum;
uchar srcIP[4]; /* 13*/
uchar dstIP[4]; /* 15*/
} ip;
} netsim_connect_packet;
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;
else return 0; /* ??? */
}
inline unsigned short eth_type (ethpacket_t * x) /* arp, ipv4, ... */
{ return x->frametype; }
inline unsigned short eth_arpop (ethpacket_t * x) /* reqest, reply, */
{ return x->u.arp.op; }
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.iplen == 40)
&& (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);
}
/* fetch IP addresses */
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);
else return 0;
}
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);
else return 0;
}
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;
} else
return 0xffffffff;
}
/* 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;
else
return -1;
}
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;
else
return -1;
}
#if 1
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)
{
static char buf[10];
switch (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";
default:
sprintf(&buf[0], "%d", tcptype);
return &buf[0];
}
}
char * eth_icmp_string (int icmptype, int icmpcode)
{
static char buf[10];
switch (icmptype) {
case ICMP_ECHOREPLY: return "echo_reply";
case ICMP_UNREACHABLE:
switch (icmpcode) {
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 ICMP_REDIRECT:
switch (icmpcode) {
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";
default:
sprintf(&buf[0], "%d", icmptype);
return &buf[0];
}
}
#endif
#if 0 /*** see "netsim.cc"/netsim_dbgpacket() ***/
void eth_print ()
{
int et,ipt;
et = eth_type(&buffer.packet);
fprintf (stderr, "eth{%02x->%02x,%s",
eth_srcMAC(&buffer.packet) & 0xff,
eth_dstMAC(&buffer.packet) & 0xff,
(et == ET_IPv4 : "ip" ?
et == ET_ARP : "arp" ?
et == ET_RARP : "rarp" ? "?") );
switch (et) {
case ET_IPv4:
ipt = eth_ipproto(&buffer.packet);
fprintf (stderr, "{%d.%d->%d.%d,%s",
eth_srcIP(&buffer.packet) & 0xff,
eth_dstIP(&buffer.packet) & 0xff,
ipt);
break;
case ET_ARP:
fprintf (stderr, "{
break;
case ET_RARP:
break;
}
fprintf (stderr, "}\n");
}
#endif
#endif /*_ETH_H*/