blob: c2d03d8b2cb53a613dfc0b8c21afc5885ff60fca [file] [log] [blame]
/*******************************************************************************
* (c) Copyright 2009 Actel Corporation,All Rights Reserved.
*
* tcpip.c:TCP/IP implementation for webserver.
*/
#include "../port_config/cpu_types.h"
#include "nettype.h"
#include "../mss_ethernet_mac/mss_ethernet_mac.h"
#include "../mss_ethernet_mac/mss_ethernet_mac_regs.h"
#include "tcpip.h"
#include <string.h>
#include <stdio.h>
#include <math.h>
#define OK 0
#define ERR 1
#define MAC_BASE_ADDRESS 0x40003000
extern char ethAddr[6];
unsigned char my_ip[IP_ADDR_LEN]={192,168,0,14};
unsigned char my_mac[ETH_ADDR_LEN]={0xAA,0xBB,0xCC,0x11,0x22,0x33};
unsigned char tcp_packet[1532];
unsigned char ip_known;
unsigned char dhcp_ip_found;
unsigned short int ip_id;
unsigned char selected_mode = 0;
unsigned char selectedwaveform = 0;
unsigned char rtc_count[5]={0,0,0,0,0};
unsigned char rtc_match_count[5]={0,5,0,0,0};
unsigned char get_count[5];
unsigned int num_pkt_tx = 0,num_pkt_rx = 0;
#define TCP_START_SEQ 0x10203040
static const unsigned char g_client_ip[IP_ADDR_LEN] = { 192, 168, 1, 10 };
unsigned char oled_string[20];
tcp_control_block_t tcb;
MAC_instance_t g_mac;
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char send_arp_reply(unsigned char *buf)
{
/* Modify the packet in place */
arp_pkt_xp arp_pkt = (arp_pkt_xp )(buf + sizeof(ether_hdr_t));
eth_hdr_xp eth_hdr = (eth_hdr_xp ) buf;
memcpy(eth_hdr->da, eth_hdr->sa, ETH_ADDR_LEN);
memcpy(eth_hdr->sa, my_mac, ETH_ADDR_LEN);
arp_pkt->opcode[1] = ARP_OPCODE_REPLY_1;
memcpy(arp_pkt->mac_ta, arp_pkt->mac_sa, ETH_ADDR_LEN);
memcpy(arp_pkt->ip_ta, arp_pkt->ip_sa, IP_ADDR_LEN);
memcpy(arp_pkt->mac_sa, my_mac, ETH_ADDR_LEN);
memcpy(arp_pkt->ip_sa, my_ip, IP_ADDR_LEN);
num_pkt_tx++;
MSS_MAC_tx_packet(buf,42, MSS_MAC_BLOCKING);
return OK;
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
void send_gratuitous_arp(unsigned char *buf)
{
arp_pkt_xp arp_pkt = (arp_pkt_xp )(buf + sizeof(ether_hdr_t));
eth_hdr_xp eth_hdr = (eth_hdr_xp ) buf;
memset(eth_hdr->da, 0xFF, ETH_ADDR_LEN); /* broadcast */
memcpy(eth_hdr->sa, my_mac, ETH_ADDR_LEN);
eth_hdr->type_code[0] = ETH_TYPE_0;
eth_hdr->type_code[1] = ETH_TYPE_ARP_1;
arp_pkt->hw_type[0] = ARP_HW_TYPE_0;
arp_pkt->hw_type[1] = ARP_HW_TYPE_1;
arp_pkt->proto_type[0] = ETH_TYPE_0;
arp_pkt->proto_type[1] = ETH_TYPE_IP_1;
arp_pkt->hw_addr_len = ETH_ADDR_LEN;
arp_pkt->proto_addr_len = IP_ADDR_LEN;
arp_pkt->opcode[0] = ARP_OPCODE_0;
arp_pkt->opcode[1] = ARP_OPCODE_REQ_1;
memcpy(arp_pkt->mac_sa, my_mac, ETH_ADDR_LEN);
memcpy(arp_pkt->ip_sa, my_ip, IP_ADDR_LEN);
memset(arp_pkt->mac_ta, 0x00, ETH_ADDR_LEN);
memcpy(arp_pkt->ip_ta, my_ip, IP_ADDR_LEN);
//mac_tx_send(buf,42,0);
num_pkt_tx++;
MSS_MAC_tx_packet(buf,42, MSS_MAC_BLOCKING);
}
/***************************************************************************//**
* See tcpip.h for more information.
*
*/
unsigned short int get_checksum(unsigned char *buf, unsigned short int len, unsigned short int pos)
{
unsigned int sum; /* our accumulated sum */
unsigned short int delta; /* the next 16-bit quantity to add */
unsigned short int i;
unsigned short int ilen;
sum = (unsigned int) 0;
ilen=(len&1)?len-1:len;
for (i = 0; i < ilen; i += 2) {
if (i == pos) continue;
delta = (unsigned short int)buf[i+1] + (unsigned short int)((unsigned short int)buf[i] << 8);
sum += delta;
if (sum & (unsigned int) 0x10000) { /* if there's a carry... */
sum &= 0xffff; /* get rid of the carry bit */
sum++; /* and move it down here */
}
}
if ( len & 1) {
delta = (unsigned short int)((unsigned short int)buf[i] << 8);
sum += delta;
if (sum & (unsigned int) 0x10000) { /* if there's a carry... */
sum &= 0xffff; /* get rid of the carry bit */
sum++; /* and move it down here */
}
}
sum = ~sum;
return sum;
} //end calc_checksum
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char fix_checksum(unsigned char *buf, unsigned short int len, unsigned short int pos)
{
unsigned short int sum = get_checksum(buf,len,pos);
buf[pos] = (unsigned char)(sum >> 8);
buf[pos+1] = (unsigned char)sum;
return OK;
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char check_checksum(unsigned char *buf, unsigned short int len, unsigned short int pos, char type)
{
unsigned short int sum = get_checksum(buf,len,pos);
if ((buf[pos] != (unsigned char)(sum >> 8)) ||
(buf[pos+1] != (unsigned char) sum)) {
type = 0; /* get around compiler warning */
return ERR;
} else {
return OK;
}
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char send_icmp_echo_reply(unsigned char *buf)
{
eth_hdr_xp eth_hdr = (eth_hdr_xp ) buf;
ip_hdr_xp ip_hdr = (ip_hdr_xp ) (buf + sizeof (ether_hdr_t));
icmp_hdr_xp icmp_hdr = (icmp_hdr_xp )
(buf + sizeof (ether_hdr_t) + sizeof(ip_hdr_t));
unsigned short int elen = ((unsigned short int)ip_hdr->tlen[0] << 8) + (unsigned short int)ip_hdr->tlen[1] - sizeof(ip_hdr_t);
memcpy(eth_hdr->da, eth_hdr->sa, ETH_ADDR_LEN);
memcpy(eth_hdr->sa, my_mac, ETH_ADDR_LEN);
memcpy(ip_hdr->da, ip_hdr->sa, IP_ADDR_LEN);
memcpy(ip_hdr->sa, my_ip, IP_ADDR_LEN);
ip_hdr->ttl--;
fix_checksum((unsigned char *)ip_hdr, (unsigned short int) 20, (unsigned short int) 10);
icmp_hdr->type = ICMP_TYPE_ECHO_REPLY;
if (elen & 1) {
((unsigned char *)icmp_hdr)[elen] = 0;
}
fix_checksum((unsigned char *)icmp_hdr, (unsigned short int) elen, (unsigned short int) 2);
num_pkt_tx++;
MSS_MAC_tx_packet(buf,elen + sizeof(ether_hdr_t) + sizeof(ip_hdr_t), MSS_MAC_BLOCKING);
return OK;
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
void dtoa_reverse(unsigned short int n, unsigned char *buf)
{
buf--;
if (n == 0) {
*buf = '0';
return;
}
while (n > 0) {
*buf-- = (n % 10) + '0';
n = n / 10;
}
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
void send_bootp_packet (unsigned char *buf)
{
/* output packet */
eth_hdr_xp eth_hdr = (eth_hdr_xp ) tcp_packet;
ip_hdr_xp ip_hdr = (ip_hdr_xp ) (tcp_packet + sizeof(ether_hdr_t));
udp_hdr_xp udp_hdr = (udp_hdr_xp ) (tcp_packet + sizeof(ether_hdr_t) + sizeof(ip_hdr_t));
bootp_pkt_xp bootp_pkt = (bootp_pkt_xp )((unsigned char *)udp_hdr + sizeof(udp_hdr_t));
unsigned char *opts = bootp_pkt->vend;
/* input packet */
// eth_hdr_xp ieth_hdr = (eth_hdr_xp ) buf;
// ip_hdr_xp iip_hdr = (ip_hdr_xp ) (buf + sizeof(ether_hdr_t));
udp_hdr_xp iudp_hdr = (udp_hdr_xp ) (buf + sizeof(ether_hdr_t) + sizeof(ip_hdr_t));
bootp_pkt_xp ibootp_pkt = (bootp_pkt_xp )((unsigned char *)iudp_hdr + sizeof(udp_hdr_t));
unsigned short int plen;
/* Set up Bootp */
memset(bootp_pkt, 0, sizeof(bootp_pkt_t));
bootp_pkt->op = BOOTP_OP_REQUEST;
bootp_pkt->hwtype = BOOTP_HWTYPE_ETH;
bootp_pkt->hlen = ETH_ADDR_LEN;
bootp_pkt->secs[1] = 0x64;
memcpy(bootp_pkt->chaddr, my_mac, ETH_ADDR_LEN);
bootp_pkt->flags[0] = 0x80; /* ask for a broadcast */
if (buf) {
if (memcmp(my_mac, ibootp_pkt->chaddr, ETH_ADDR_LEN)) /* not for me ignore */
return;
memcpy(my_ip, ibootp_pkt->yiaddr, IP_ADDR_LEN);
ip_known = 1;
dhcp_ip_found = 1;
memcpy(bootp_pkt->ciaddr, ibootp_pkt->yiaddr, IP_ADDR_LEN);
memcpy(bootp_pkt->xid, ibootp_pkt->xid, BOOTP_XID_LEN);
} else {
bootp_pkt->xid[0] = 0x90;
}
*opts++ = 99; /* magic number */
*opts++ = 130;
*opts++ = 83;
*opts++ = 99;
*opts++ = BOOTP_OPTCODE_DHCP_TYPE;
*opts++ = 1;
if (buf) {
*opts++ = DHCP_TYPE_REQUEST;
*opts++ = BOOTP_OPTCODE_DHCP_SID;
*opts++ = 4;
*opts++ = ibootp_pkt->siaddr[0];
*opts++ = ibootp_pkt->siaddr[1];
*opts++ = ibootp_pkt->siaddr[2];
*opts++ = ibootp_pkt->siaddr[3];
} else {
*opts++ = DHCP_TYPE_DISCOVER;
}
*opts++ = BOOTP_OPTCODE_END;
/* Set up Udp */
memset(udp_hdr, 0, sizeof(udp_hdr_t));
udp_hdr->sp[1] = BOOTP_CLIENT_PORT;
udp_hdr->dp[1] = BOOTP_SERVER_PORT;
plen = sizeof(udp_hdr_t) + sizeof(bootp_pkt_t);
udp_hdr->len[0] = plen >> 8;
udp_hdr->len[1] = (unsigned char) plen;
/* leave csum 0 */
/* Set up IP */
memset(ip_hdr, 0, sizeof(ip_hdr_t));
ip_hdr->ver_hlen = 0x45; /* IPv4 with 20 byte header */
plen += sizeof(ip_hdr_t);
ip_hdr->tlen[0] = plen >> 8;
ip_hdr->tlen[1] = (unsigned char) plen;
ip_hdr->id[0] = ip_id >> 8;
ip_hdr->id[1] = (unsigned char) ip_id;
ip_id++;
ip_hdr->ttl = 32; /* max 32 hops */
ip_hdr->proto = UDP_PROTO;
memset(ip_hdr->da, 0xFF, IP_ADDR_LEN);
fix_checksum((unsigned char *)ip_hdr, sizeof(ip_hdr_t), 10);
/* Set up Ethernet */
eth_hdr->type_code[0] = ETH_TYPE_0;
eth_hdr->type_code[1] = ETH_TYPE_IP_1;
memcpy(eth_hdr->sa, my_mac, ETH_ADDR_LEN);
memset(eth_hdr->da, 0xFF, ETH_ADDR_LEN); /* broadcast */
num_pkt_tx++;
MSS_MAC_tx_packet(tcp_packet,plen + sizeof(ether_hdr_t), MSS_MAC_BLOCKING);
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
void send_dhcp_server_packet (unsigned char *buf)
{
unsigned char * tcp_packet = tcp_packet;
/* output packet */
eth_hdr_xp eth_hdr = (eth_hdr_xp ) tcp_packet;
ip_hdr_xp ip_hdr = (ip_hdr_xp ) (tcp_packet + sizeof(ether_hdr_t));
udp_hdr_xp udp_hdr = (udp_hdr_xp ) (tcp_packet + sizeof(ether_hdr_t) + sizeof(ip_hdr_t));
bootp_pkt_xp bootp_pkt = (bootp_pkt_xp )((unsigned char *)udp_hdr + sizeof(udp_hdr_t));
unsigned char *opts = bootp_pkt->vend;
/* input packet */
eth_hdr_xp ieth_hdr = (eth_hdr_xp ) buf;
// ip_hdr_xp iip_hdr = (ip_hdr_xp ) (buf + sizeof(ether_hdr_t));
udp_hdr_xp iudp_hdr = (udp_hdr_xp ) (buf + sizeof(ether_hdr_t) + sizeof(ip_hdr_t));
bootp_pkt_xp ibootp_pkt = (bootp_pkt_xp )((unsigned char *)iudp_hdr + sizeof(udp_hdr_t));
unsigned char *iopts = ibootp_pkt->vend;
unsigned short int plen;
/* Set up Bootp */
memset(bootp_pkt, 0, sizeof(bootp_pkt_t));
bootp_pkt->op = BOOTP_OP_REPLY;
bootp_pkt->hwtype = BOOTP_HWTYPE_ETH;
bootp_pkt->hlen = ETH_ADDR_LEN;
bootp_pkt->secs[1] = 0x64;
memcpy(bootp_pkt->chaddr, ieth_hdr->sa, ETH_ADDR_LEN);
bootp_pkt->flags[0] = 0x00;
if (buf) {
memcpy(bootp_pkt->ciaddr, ibootp_pkt->yiaddr, IP_ADDR_LEN);
memcpy(bootp_pkt->yiaddr, g_client_ip, IP_ADDR_LEN);
memcpy(bootp_pkt->xid, ibootp_pkt->xid, BOOTP_XID_LEN);
} else {
bootp_pkt->xid[0] = 0x90;
}
*opts++ = 99; /* magic number */
*opts++ = 130;
*opts++ = 83;
*opts++ = 99;
*opts++ = BOOTP_OPTCODE_DHCP_TYPE;
*opts++ = 1;
if (iopts[6] == DHCP_TYPE_DISCOVER)
{
*opts++ = DHCP_TYPE_OFFER;
}
else
{
*opts++ = DHCP_TYPE_ACK;
}
/* Server ID */
*opts++ = BOOTP_OPTCODE_DHCP_SID;
*opts++ = 4;
*opts++ = my_ip[0];
*opts++ = my_ip[1];
*opts++ = my_ip[2];
*opts++ = my_ip[3];
/* Lease time (1 our) */
*opts++ = BOOTP_OPTCODE_DHCP_LEASE;
*opts++ = 4;
*opts++ = 0x00;
*opts++ = 0x00;
*opts++ = 0x0E;
*opts++ = 0x10;
/* Renewal time */
*opts++ = BOOTP_OPTCODE_DHCP_RENEW;
*opts++ = 4;
*opts++ = 0x00;
*opts++ = 0x00;
*opts++ = 0x07;
*opts++ = 0x08;
/* Rebinding time */
*opts++ = BOOTP_OPTCODE_DHCP_REBIND;
*opts++ = 4;
*opts++ = 0x00;
*opts++ = 0x00;
*opts++ = 0x0C;
*opts++ = 0x4E;
/* Subnet mask */
*opts++ = BOOTP_OPTCODE_DHCP_SUBNET;
*opts++ = 4;
*opts++ = 0xFF;
*opts++ = 0xFF;
*opts++ = 0xFF;
*opts++ = 0x00;
/* Router */
*opts++ = BOOTP_OPTCODE_DHCP_ROUTER;
*opts++ = 4;
*opts++ = my_ip[0];
*opts++ = my_ip[1];
*opts++ = my_ip[2];
*opts++ = my_ip[3];
/* Domain */
*opts++ = BOOTP_OPTCODE_DHCP_DOMAIN;
*opts++ = 4;
*opts++ = my_ip[0];
*opts++ = my_ip[1];
*opts++ = my_ip[2];
*opts++ = my_ip[3];
*opts++ = BOOTP_OPTCODE_END;
/* Set up Udp */
memset(udp_hdr, 0, sizeof(udp_hdr_t));
udp_hdr->sp[1] = BOOTP_SERVER_PORT;
udp_hdr->dp[1] = BOOTP_CLIENT_PORT;
plen = sizeof(udp_hdr_t) + sizeof(bootp_pkt_t);
udp_hdr->len[0] = plen >> 8;
udp_hdr->len[1] = (unsigned char) plen;
/* leave csum 0 */
/* Set up IP */
memset(ip_hdr, 0, sizeof(ip_hdr_t));
ip_hdr->ver_hlen = 0x45; /* IPv4 with 20 byte header */
plen += sizeof(ip_hdr_t);
ip_hdr->tlen[0] = plen >> 8;
ip_hdr->tlen[1] = (unsigned char) plen;
ip_hdr->id[0] = ip_id >> 8;
ip_hdr->id[1] = (unsigned char) ip_id;
ip_id++;
ip_hdr->ttl = 255;
ip_hdr->proto = UDP_PROTO;
memcpy(ip_hdr->sa, my_ip, IP_ADDR_LEN);
memset(ip_hdr->da, 0xFF, IP_ADDR_LEN);
fix_checksum((unsigned char *)ip_hdr, sizeof(ip_hdr_t), 10);
/* Set up Ethernet */
eth_hdr->type_code[0] = ETH_TYPE_0;
eth_hdr->type_code[1] = ETH_TYPE_IP_1;
memcpy(eth_hdr->sa, my_mac, ETH_ADDR_LEN);
memset(eth_hdr->da, 0xFF, ETH_ADDR_LEN); /* broadcast */
num_pkt_tx++;
MSS_MAC_tx_packet(tcp_packet,plen + sizeof(ether_hdr_t), MSS_MAC_BLOCKING);
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char process_udp_packet (unsigned char *buf)
{
udp_hdr_xp udp_hdr = (udp_hdr_xp ) (buf + sizeof(ether_hdr_t) + sizeof(ip_hdr_t));
if (udp_hdr->dp[1] != BOOTP_CLIENT_PORT) {
send_dhcp_server_packet( buf );
return OK;
}
if (ip_known) {
return ERR;
}
/* some more error checking here? */
send_bootp_packet(buf);
return OK;
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
void send_tcp_packet (unsigned char control_bits,unsigned short int buflen)
{
eth_hdr_xp eth_hdr = (eth_hdr_xp ) tcp_packet;
ip_hdr_xp ip_hdr = (ip_hdr_xp ) (tcp_packet + sizeof(ether_hdr_t));
tcp_hdr_xp tcp_hdr = (tcp_hdr_xp )
(tcp_packet + sizeof(ether_hdr_t) + sizeof(ip_hdr_t));
tcp_pseudo_hdr_xp tcp_pseudo_hdr = (tcp_pseudo_hdr_xp )
(((unsigned char *)tcp_hdr) - sizeof(tcp_pseudo_hdr_t));
unsigned char *tcp_data = tcp_packet + sizeof(ether_hdr_t) + sizeof(ip_hdr_t) + sizeof (tcp_hdr_t);
unsigned char *seqp = (unsigned char *)(&tcb.local_seq);
unsigned short int plen;
memset(tcp_hdr, 0, sizeof(tcp_hdr_t));
memcpy(tcp_hdr->sp, tcb.local_port, TCP_PORT_LEN);
memcpy(tcp_hdr->dp, tcb.remote_port, TCP_PORT_LEN);
tcp_hdr->seqnum[0] = seqp[3];
tcp_hdr->seqnum[1] = seqp[2];
tcp_hdr->seqnum[2] = seqp[1];
tcp_hdr->seqnum[3] = seqp[0];
tcb.local_seq++;
if (buflen) {
tcb.local_seq += buflen - 1;
}
if (control_bits & TCP_CNTRL_ACK) {
seqp = (unsigned char *)(&tcb.remote_seq);
tcp_hdr->acknum[3] = seqp[0];
tcp_hdr->acknum[2] = seqp[1];
tcp_hdr->acknum[1] = seqp[2];
tcp_hdr->acknum[0] = seqp[3];
}
tcp_hdr->data_off = 0x50; /* always 5 32 bit words for us */
tcp_hdr->urg_ack_psh_rst_syn_fin = control_bits;
tcp_hdr->wsize[0] = 0x08; /* this is 0x0800, which is 2K */
if (buflen & 1) {
tcp_data[buflen] = 0;
}
/* memset(tcp_pseudo_hdr, 0, sizeof(tcp_pseudo_hdr_t)); */
memcpy(tcp_pseudo_hdr->sa, my_ip, IP_ADDR_LEN);
memcpy(tcp_pseudo_hdr->da, tcb.remote_addr, IP_ADDR_LEN);
tcp_pseudo_hdr->zero = 0;
tcp_pseudo_hdr->proto = TCP_PROTO;
plen = buflen + sizeof(tcp_hdr_t);
tcp_pseudo_hdr->plen[0] = plen >> 8;
tcp_pseudo_hdr->plen[1] = (unsigned char)plen;
fix_checksum((unsigned char *)tcp_pseudo_hdr,
(unsigned short int)(plen + sizeof(tcp_pseudo_hdr_t)), (unsigned short int)28);
memset(ip_hdr, 0, sizeof(ip_hdr_t));
ip_hdr->ver_hlen = 0x45; /* IPv4 with 20 byte header */
plen += sizeof(ip_hdr_t); /* add the size of the IP Header */
ip_hdr->tlen[0] = plen >> 8;
ip_hdr->tlen[1] = (unsigned char) plen;
ip_hdr->id[0] = ip_id >> 8;
ip_hdr->id[1] = (unsigned char) ip_id;
ip_id++;
ip_hdr->ttl = 32; /* max 32 hops */
ip_hdr->proto = TCP_PROTO;
memcpy(ip_hdr->sa, my_ip, IP_ADDR_LEN);
memcpy(ip_hdr->da, tcb.remote_addr, IP_ADDR_LEN);
fix_checksum((unsigned char *)ip_hdr, sizeof(ip_hdr_t), 10);
/* Fix the Ethernet Header */
eth_hdr->type_code[0] = ETH_TYPE_0;
eth_hdr->type_code[1] = ETH_TYPE_IP_1;
memcpy(eth_hdr->sa, my_mac, ETH_ADDR_LEN);
memcpy(eth_hdr->da, tcb.remote_mac, ETH_ADDR_LEN); /* should be table lookup */
num_pkt_tx++;
MSS_MAC_tx_packet(tcp_packet,plen + sizeof(ether_hdr_t), MSS_MAC_BLOCKING);
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char tcp_init(void)
{
memset(&tcb,0,sizeof(tcp_control_block_t));
tcb.state = TCP_STATE_LISTEN;
ip_id = 0;
ip_known = 0;
return OK;
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char hex_digits_to_byte(unsigned char u, unsigned char l)
{
if (u > '9')
u = u - 'A' + 10;
else
u = u - '0';
if (l > '9')
l = l - 'A' + 10;
else
l = l - '0';
return (u << 4) + l;
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char process_icmp_packet(unsigned char *buf)
{
ip_hdr_xp ip_hdr = (ip_hdr_xp ) (buf + sizeof (ether_hdr_t));
icmp_hdr_xp icmp_hdr = (icmp_hdr_xp )
(buf + sizeof (ether_hdr_t) + sizeof(ip_hdr_t));
unsigned short int elen = ((unsigned short int)ip_hdr->tlen[0] << 8) + (unsigned short int)ip_hdr->tlen[1] - sizeof(ip_hdr_t);
if (check_checksum((unsigned char *)icmp_hdr, (unsigned short int) elen, (unsigned short int) 2, 'M') != OK)
return ERR;
if (icmp_hdr->type != ICMP_TYPE_ECHO_REQUEST) {
return ERR;
}
return send_icmp_echo_reply(buf);
}
/* See tcpip.h for more information.
*/
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char process_tcp_packet(unsigned char *buf)
{
eth_hdr_xp eth_hdr = (eth_hdr_xp )buf;
ip_hdr_xp ip_hdr = (ip_hdr_xp ) (buf + sizeof (ether_hdr_t));
tcp_hdr_xp tcp_hdr = (tcp_hdr_xp )
(buf + sizeof (ether_hdr_t) + sizeof(ip_hdr_t));
unsigned short int elen = ((unsigned short int)ip_hdr->tlen[0] << 8) + (unsigned short int)ip_hdr->tlen[1] - sizeof(ip_hdr_t);
unsigned char state;
if ( !memcmp(tcb.remote_addr, ip_hdr->sa, IP_ADDR_LEN) && /* same source IP */
!memcmp(tcb.remote_port, tcp_hdr->sp, TCP_PORT_LEN) && /* same source port */
!memcmp(tcb.local_port, tcp_hdr->dp, TCP_PORT_LEN)) { /* same dest port */
state = tcb.state;
} else { /* copy it over, a new IP wants in */
memcpy(tcb.remote_addr, ip_hdr->sa, IP_ADDR_LEN);
memcpy(tcb.remote_port, tcp_hdr->sp, TCP_PORT_LEN);
memcpy(tcb.local_port, tcp_hdr->dp, TCP_PORT_LEN);
memcpy(tcb.remote_mac, eth_hdr->sa, ETH_ADDR_LEN);
state = TCP_STATE_LISTEN;
}
switch (state) {
case TCP_STATE_LISTEN:
if (tcp_hdr->urg_ack_psh_rst_syn_fin & TCP_CNTRL_SYN) {
/* recd SYN : new connection; send SYN+ACK */
tcb.local_seq = TCP_START_SEQ;
tcb.remote_seq = 0;
tcb.remote_seq = (tcb.remote_seq | tcp_hdr->seqnum[0]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[1]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[2]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[3]);
tcb.remote_seq++;
send_tcp_packet( TCP_CNTRL_SYN | TCP_CNTRL_ACK, 0);
tcb.state = TCP_STATE_SYN_RECVD;
}
break;
case TCP_STATE_SYN_RECVD:
if (tcp_hdr->urg_ack_psh_rst_syn_fin & TCP_CNTRL_ACK) {
/* recd ack; send nothing */
tcb.state = TCP_STATE_ESTABLISHED;
}
else {
tcb.state = TCP_STATE_LISTEN;
}
break;
case TCP_STATE_ESTABLISHED:
if (tcp_hdr->urg_ack_psh_rst_syn_fin & TCP_CNTRL_FIN) {
/* recd fin; send ack */
/* skip CLOSE_WAIT state; send fin along with ack */
tcb.remote_seq = 0;
tcb.remote_seq = (tcb.remote_seq | tcp_hdr->seqnum[0]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[1]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[2]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[3]);
tcb.remote_seq++;
send_tcp_packet(TCP_CNTRL_ACK | TCP_CNTRL_FIN, 0);
tcb.state = TCP_STATE_LAST_ACK;
/* Default scroll message on OLED */
}
else if (tcp_hdr->dp[0] != 0 || \
tcp_hdr->dp[1] != 80) { /* HTTP Port */
break;
}
else if (elen > sizeof(tcp_hdr_t)) { /* dont respond to empty packets*/
tcb.remote_seq = 0;
tcb.remote_seq = (tcb.remote_seq | tcp_hdr->seqnum[0]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[1]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[2]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[3]);
tcb.remote_seq += (unsigned long) (elen - sizeof(tcp_hdr_t));
//send_http_response(((unsigned char *)(tcp_hdr)) + sizeof (tcp_hdr_t));
tcb.state = TCP_STATE_MY_LAST;
}
break;
case TCP_STATE_MY_LAST:
if (tcp_hdr->urg_ack_psh_rst_syn_fin & TCP_CNTRL_FIN) {
/* sent fin, got fin, ack the fin */
tcb.remote_seq = 0;
tcb.remote_seq = (tcb.remote_seq | tcp_hdr->seqnum[0]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[1]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[2]);
tcb.remote_seq = ((tcb.remote_seq << 8) |tcp_hdr->seqnum[3]);
tcb.remote_seq++;
send_tcp_packet(TCP_CNTRL_ACK, 0);
tcb.state = TCP_STATE_CLOSED;
}
break;
case TCP_STATE_LAST_ACK:
if (tcp_hdr->urg_ack_psh_rst_syn_fin & TCP_CNTRL_ACK) {
/* recd ack; send nothing */
tcb.state = TCP_STATE_CLOSED;
}
/* no break here... go on to CLOSED directly */
case TCP_STATE_CLOSED:
memset (&tcb, 0, sizeof (tcp_control_block_t));
break;
default:
break;
}
return 0;
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char process_ip_packet(unsigned char *buf)
{
ip_hdr_xp ip_hdr = (ip_hdr_xp ) (buf + sizeof (ether_hdr_t));
/* Is the incoming pkt for me?
(either explicity addressed to me or a broadcast address) */
if (memcmp(my_ip, ip_hdr->da, IP_ADDR_LEN)) /* not my IP */ {
if (ip_known) {
return ERR;
}
if (ip_hdr->da[0] != 0xFF || ip_hdr->da[1] != 0xFF ||
ip_hdr->da[2] != 0xFF || ip_hdr->da[3] != 0xFF) {
return ERR;
}
}
if (check_checksum((unsigned char *)ip_hdr, (unsigned short int) 20, (unsigned short int) 10, 'I') != OK)
return ERR;
switch (ip_hdr->proto)
{
case TCP_PROTO:
return process_tcp_packet(buf);
case ICMP_PROTO:
return process_icmp_packet(buf);
case UDP_PROTO:
return process_udp_packet(buf);
default: {
return ERR;
}
}
return ERR;
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char process_arp_packet(unsigned char *buf)
{
arp_pkt_xp arp_pkt = (arp_pkt_xp )(buf + sizeof(ether_hdr_t));
if (arp_pkt->opcode[1] != ARP_OPCODE_REQ_1) {
if (arp_pkt->opcode[1] == ARP_OPCODE_REPLY_1)
{
if (!memcmp(my_ip, arp_pkt->ip_sa, IP_ADDR_LEN))
{
//printf("IP conflict with MAC");
//printf("%02x:%02x:%02x:%02x:%02x:%02x",arp_pkt->mac_sa[0],arp_pkt->mac_sa[1],arp_pkt->mac_sa[2],arp_pkt->mac_sa[3],arp_pkt->mac_sa[4],arp_pkt->mac_sa[5]);
}
}
return ERR;
}
if (memcmp(my_ip, arp_pkt->ip_ta, IP_ADDR_LEN)) {
return ERR;
}
return send_arp_reply(buf);
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char process_packet( unsigned char * buf )
{
eth_hdr_xp eth_hdr;
unsigned char typ;
eth_hdr = (eth_hdr_xp ) buf;
typ = eth_hdr->type_code[0];
if (typ != ETH_TYPE_0)
{
return ERR;
}
typ = eth_hdr->type_code[1];
if (typ == ETH_TYPE_ARP_1)
{
return process_arp_packet(buf);
}
else if (typ == ETH_TYPE_IP_1) {
return process_ip_packet(buf);
}
else
{
return ERR;
}
return ERR;
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
unsigned char *xstrcpy(unsigned char *d, const unsigned char *s)
{
unsigned char c;
while ((c = *s++))
(*d++ = c) ;
return d;
}
/***************************************************************************//**
* See tcpip.h for more information.
*/
// updated html page with fusion board link on page: