📄 ip_arp_udp_tcp.c
字号:
/********************************************* * vim:sw=8:ts=8:si:et * To use the above modeline in vim you must have "set modeline" in your .vimrc * * Author: Guido Socher * Copyright: GPL V2 * See http://www.gnu.org/licenses/gpl.html * * IP, Arp, UDP and TCP functions. * * The TCP implementation uses some size optimisations which are valid * only if all data can be sent in one single packet. This is however * not a big limitation for a microcontroller as you will anyhow use * small web-pages. The TCP stack is therefore a SDP-TCP stack (single data packet TCP). * * Chip type : ATMEGA88 with ENC28J60 *********************************************/#include <avr/io.h>#include <avr/pgmspace.h>#include "avr_compat.h"#include "net.h"#include "enc28j60.h"static uint8_t wwwport=80;static uint8_t macaddr[6];static uint8_t ipaddr[4];static int16_t info_hdr_len=0;static int16_t info_data_len=0;static uint8_t seqnum=0xa; // my initial tcp sequence number// The Ip checksum is calculated over the ip header only starting// with the header length field and a total length of 20 bytes// unitl ip.dst// You must set the IP checksum field to zero before you start// the calculation.// len for ip is 20.//// For UDP/TCP we do not make up the required pseudo header. Instead we // use the ip.src and ip.dst fields of the real packet:// The udp checksum calculation starts with the ip.src field// Ip.src=4bytes,Ip.dst=4 bytes,Udp header=8bytes + data length=16+len// In other words the len here is 8 + length over which you actually// want to calculate the checksum.// You must set the checksum field to zero before you start// the calculation.// len for udp is: 8 + 8 + data length// len for tcp is: 4+4 + 20 + option len + data length//// For more information on how this algorithm works see:// http://www.netfor2.com/checksum.html// http://www.msc.uky.edu/ken/cs471/notes/chap3.htm// The RFC has also a C code example: http://www.faqs.org/rfcs/rfc1071.htmluint16_t checksum(uint8_t *buf, uint16_t len,uint8_t type){ // type 0=ip // 1=udp // 2=tcp uint32_t sum = 0; //if(type==0){ // // do not add anything //} if(type==1){ sum+=IP_PROTO_UDP_V; // protocol udp // the length here is the length of udp (data+header len) // =length given to this function - (IP.scr+IP.dst length) sum+=len-8; // = real tcp len } if(type==2){ sum+=IP_PROTO_TCP_V; // the length here is the length of tcp (data+header len) // =length given to this function - (IP.scr+IP.dst length) sum+=len-8; // = real tcp len } // build the sum of 16bit words while(len >1){ sum += 0xFFFF & (*buf<<8|*(buf+1)); buf+=2; len-=2; } // if there is a byte left then add it (padded with zero) if (len){ sum += (0xFF & *buf)<<8; } // now calculate the sum over the bytes in the sum // until the result is only 16bit long while (sum>>16){ sum = (sum & 0xFFFF)+(sum >> 16); } // build 1's complement: return( (uint16_t) sum ^ 0xFFFF);}// you must call this function once before you use any of the other functions:void init_ip_arp_udp_tcp(uint8_t *mymac,uint8_t *myip,uint8_t wwwp){ uint8_t i=0; wwwport=wwwp; while(i<4){ ipaddr[i]=myip[i]; i++; } i=0; while(i<6){ macaddr[i]=mymac[i]; i++; }}uint8_t eth_type_is_arp_and_my_ip(uint8_t *buf,uint16_t len){ uint8_t i=0; // if (len<41){ return(0); } if(buf[ETH_TYPE_H_P] != ETHTYPE_ARP_H_V || buf[ETH_TYPE_L_P] != ETHTYPE_ARP_L_V){ return(0); } while(i<4){ if(buf[ETH_ARP_DST_IP_P+i] != ipaddr[i]){ return(0); } i++; } return(1);}uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len){ uint8_t i=0; //eth+ip+udp header is 42 if (len<42){ return(0); } if(buf[ETH_TYPE_H_P]!=ETHTYPE_IP_H_V || buf[ETH_TYPE_L_P]!=ETHTYPE_IP_L_V){ return(0); } if (buf[IP_HEADER_LEN_VER_P]!=0x45){ // must be IP V4 and 20 byte header return(0); } while(i<4){ if(buf[IP_DST_P+i]!=ipaddr[i]){ return(0); } i++; } return(1);}// make a return eth header from a received eth packetvoid make_eth(uint8_t *buf){ uint8_t i=0; // //copy the destination mac from the source and fill my mac into src while(i<6){ buf[ETH_DST_MAC +i]=buf[ETH_SRC_MAC +i]; buf[ETH_SRC_MAC +i]=macaddr[i]; i++; }}void fill_ip_hdr_checksum(uint8_t *buf){ uint16_t ck; // clear the 2 byte checksum buf[IP_CHECKSUM_P]=0; buf[IP_CHECKSUM_P+1]=0; buf[IP_FLAGS_P]=0x40; // don't fragment buf[IP_FLAGS_P+1]=0; // fragement offset buf[IP_TTL_P]=64; // ttl // calculate the checksum: ck=checksum(&buf[IP_P], IP_HEADER_LEN,0); buf[IP_CHECKSUM_P]=ck>>8; buf[IP_CHECKSUM_P+1]=ck& 0xff;}// make a return ip header from a received ip packetvoid make_ip(uint8_t *buf){ uint8_t i=0; while(i<4){ buf[IP_DST_P+i]=buf[IP_SRC_P+i]; buf[IP_SRC_P+i]=ipaddr[i]; i++; } fill_ip_hdr_checksum(buf);}// make a return tcp header from a received tcp packet// rel_ack_num is how much we must step the seq number received from the// other side. We do not send more than 255 bytes of text (=data) in the tcp packet.// If mss=1 then mss is included in the options list//// After calling this function you can fill in the first data byte at TCP_OPTIONS_P+4// If cp_seq=0 then an initial sequence number is used (should be use in synack)// otherwise it is copied from the packet we receivedvoid make_tcphead(uint8_t *buf,uint16_t rel_ack_num,uint8_t mss,uint8_t cp_seq){ uint8_t i=0; uint8_t tseq; while(i<2){ buf[TCP_DST_PORT_H_P+i]=buf[TCP_SRC_PORT_H_P+i]; buf[TCP_SRC_PORT_H_P+i]=0; // clear source port i++; } // set source port (http): buf[TCP_SRC_PORT_L_P]=wwwport; i=4; // sequence numbers: // add the rel ack num to SEQACK while(i>0){ rel_ack_num=buf[TCP_SEQ_H_P+i-1]+rel_ack_num; tseq=buf[TCP_SEQACK_H_P+i-1]; buf[TCP_SEQACK_H_P+i-1]=0xff&rel_ack_num; if (cp_seq){ // copy the acknum sent to us into the sequence number buf[TCP_SEQ_H_P+i-1]=tseq; }else{ buf[TCP_SEQ_H_P+i-1]= 0; // some preset vallue } rel_ack_num=rel_ack_num>>8; i--; } if (cp_seq==0){ // put inital seq number buf[TCP_SEQ_H_P+0]= 0; buf[TCP_SEQ_H_P+1]= 0; // we step only the second byte, this allows us to send packts // with 255 bytes or 512 (if we step the initial seqnum by 2) buf[TCP_SEQ_H_P+2]= seqnum; buf[TCP_SEQ_H_P+3]= 0; // step the inititial seq num by something we will not use // during this tcp session: seqnum+=2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -