#include #include "net.h" #include "enc28j60.h" #include #include "avr_compat.h" 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; extern void init_ip_arp(uint8_t *mymac,uint8_t *myip); extern uint8_t eth_type_is_arp_and_my_ip(uint8_t *buf,uint16_t len); extern uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len); extern void make_arp_answer_from_request(uint8_t *buf); extern void make_echo_reply_from_request(uint8_t *buf,uint16_t len); extern void make_udp_reply_from_request(uint8_t *buf,char *data,uint8_t datalen,uint16_t port); extern void make_tcp_synack_from_syn(uint8_t *buf); extern void init_len_info(uint8_t *buf); extern uint16_t get_tcp_data_pointer(void); extern uint16_t fill_tcp_data_p(uint8_t *buf,uint16_t pos, const prog_char *progmem_s); extern uint16_t fill_tcp_data(uint8_t *buf,uint16_t pos, const char *s); extern void make_tcp_ack_from_any(uint8_t *buf); extern void make_tcp_ack_with_data(uint8_t *buf,uint16_t dlen); uint16_t checksum(uint8_t *buf, uint16_t len, uint8_t type) // вычисляем контрольную сумму для ip заголовка { uint32_t sum = 0; if(type==1) { sum+=IP_PROTO_UDP_V; sum+=len-8; } if(type==2) { sum+=IP_PROTO_TCP_V; sum+=len-8; } while(len >1) { sum += 0xFFFF & (*buf<<8|*(buf+1)); buf+=2; len-=2; } if (len) { sum += (0xFF & *buf)<<8; } while (sum>>16) { sum = (sum & 0xFFFF)+(sum >> 16); } return( (uint16_t) sum ^ 0xFFFF); } void init_ip_arp(uint8_t *mymac,uint8_t *myip)// функция генерации ip- и MAC-адресов, которые будут переданы в пакет и фрейм соответственно { uint8_t i=0; while(i<4) { ipaddr[i]=myip[i];// присваиваем ip-адресу, который впоследствии будет отправлен в ip- пакете значение нашего ip i++; } i=0; while(i<6) { macaddr[i]=mymac[i];// присваиваем MAC-адресу, который впоследствии будет отправлен в Ethernet-фрейме значение нашего MAC i++; } } uint8_t eth_type_is_arp_and_my_ip(uint8_t *buf,uint16_t len)// функция проверки, является ли полученный пакет ARP-запросом и предназначен ли нам? { 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);//в случае успеха возвращает значение 1 } uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len)// функция проверки, адресован ли полученный IP пакет нам? {uint8_t i=0; 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){ return(0); } while(i<4){ if(buf[IP_DST_P+i]!=ipaddr[i]){ return(0); } i++; } return(1);//если да, то возвращает 1 } void make_eth(uint8_t *buf)//функция замены MAC-адреса источника на МАС-адрес получателя { uint8_t i=0; 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)// функция генерации контрольной суммы, флагов, времени жизни для отправляемого IP пакета { uint16_t ck; buf[IP_CHECKSUM_P]=0; buf[IP_CHECKSUM_P+1]=0; buf[IP_FLAGS_P]=0x40; buf[IP_FLAGS_P+1]=0; buf[IP_TTL_P]=64; ck=checksum(&buf[IP_P], IP_HEADER_LEN,0); buf[IP_CHECKSUM_P]=ck>>8; buf[IP_CHECKSUM_P+1]=ck& 0xff; } void make_ip(uint8_t *buf)//функция генерации ip пакета для отправления { 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); } void make_arp_answer_from_request(uint8_t *buf)// функция генерации ARP-ответа для отправления { uint8_t i=0; make_eth(buf); buf[ETH_ARP_OPCODE_H_P]=ETH_ARP_OPCODE_REPLY_H_V; buf[ETH_ARP_OPCODE_L_P]=ETH_ARP_OPCODE_REPLY_L_V; while(i<6){ buf[ETH_ARP_DST_MAC_P+i]=buf[ETH_ARP_SRC_MAC_P+i]; buf[ETH_ARP_SRC_MAC_P+i]=macaddr[i]; i++; } i=0; while(i<4){ buf[ETH_ARP_DST_IP_P+i]=buf[ETH_ARP_SRC_IP_P+i]; buf[ETH_ARP_SRC_IP_P+i]=ipaddr[i]; i++; } enc28j60PacketSend(42,buf); } void make_echo_reply_from_request(uint8_t *buf,uint16_t len)// функция генерации понг-ответа для отправления { make_eth(buf); make_ip(buf); buf[ICMP_TYPE_P]=ICMP_TYPE_ECHOREPLY_V; if (buf[ICMP_CHECKSUM_P] > (0xff-0x08)){ buf[ICMP_CHECKSUM_P+1]++; } buf[ICMP_CHECKSUM_P]+=0x08; // enc28j60PacketSend(len,buf); } void make_tcphead(uint8_t *buf,uint16_t rel_ack_num,uint8_t mss,uint8_t cp_seq)//функция генерации заголовка TCP для последующей отправки { 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++; } buf[TCP_SRC_PORT_L_P]=80; i=4; 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) { buf[TCP_SEQ_H_P+i-1]=tseq; } else { buf[TCP_SEQ_H_P+i-1]= 0; } rel_ack_num=rel_ack_num>>8; i--; } if (cp_seq==0) { buf[TCP_SEQ_H_P+0]= 0; buf[TCP_SEQ_H_P+1]= 0; buf[TCP_SEQ_H_P+2]= seqnum; buf[TCP_SEQ_H_P+3]= 0; seqnum+=2; } buf[TCP_CHECKSUM_H_P]=0; buf[TCP_CHECKSUM_L_P]=0; if (mss) { buf[TCP_OPTIONS_P]=2; buf[TCP_OPTIONS_P+1]=4; buf[TCP_OPTIONS_P+2]=0x05; buf[TCP_OPTIONS_P+3]=0x80; buf[TCP_HEADER_LEN_P]=0x60; } else { buf[TCP_HEADER_LEN_P]=0x50; } } void make_tcp_synack_from_syn(uint8_t *buf)//функция отправки подтверждения открытия соединения { uint16_t ck; make_eth(buf); buf[IP_TOTLEN_H_P]=0; buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4; make_ip(buf); buf[TCP_FLAGS_P]=TCP_FLAGS_SYNACK_V; make_tcphead(buf,1,1,0); ck=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+4,2); buf[TCP_CHECKSUM_H_P]=ck>>8; buf[TCP_CHECKSUM_L_P]=ck& 0xff; enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4+ETH_HEADER_LEN,buf); } uint16_t get_tcp_data_pointer(void)//функция расчета положения первого октета данных в буфере { if (info_data_len) { return((uint16_t)TCP_SRC_PORT_H_P+info_hdr_len); } else { return(0); } } void init_len_info(uint8_t *buf)//функция определения размера TCP заголовка и принятых данных { info_data_len=(buf[IP_TOTLEN_H_P]<<8)|(buf[IP_TOTLEN_L_P]&0xff); info_data_len-=IP_HEADER_LEN; info_hdr_len=(buf[TCP_HEADER_LEN_P]>>4)*4; info_data_len-=info_hdr_len; if (info_data_len<=0) { info_data_len=0; } } uint16_t fill_tcp_data_p(uint8_t *buf,uint16_t pos, const prog_char *progmem_s)//функция записи строковых данных в буфер { char c; while ((c = pgm_read_byte(progmem_s++))) { buf[TCP_CHECKSUM_L_P+3+pos]=c; pos++; } return(pos); } uint16_t fill_tcp_data(uint8_t *buf,uint16_t pos, const char *s)//функция записи строковых данных в буфер { while (*s) { buf[TCP_CHECKSUM_L_P+3+pos]=*s; pos++; s++; } return(pos); } void make_tcp_ack_from_any(uint8_t *buf)// функция генерации подтверждения любого запроса { uint16_t j; make_eth(buf); buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V; if (info_data_len==0) { make_tcphead(buf,1,0,1); } else { make_tcphead(buf,info_data_len,0,1); } j=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN; buf[IP_TOTLEN_H_P]=j>>8; buf[IP_TOTLEN_L_P]=j& 0xff; make_ip(buf); j=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN,2); buf[TCP_CHECKSUM_H_P]=j>>8; buf[TCP_CHECKSUM_L_P]=j& 0xff; enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+ETH_HEADER_LEN,buf); } void make_tcp_ack_with_data(uint8_t *buf,uint16_t dlen) { uint16_t j; buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V|TCP_FLAGS_PUSH_V|TCP_FLAGS_FIN_V; j=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlen; buf[IP_TOTLEN_H_P]=j>>8; buf[IP_TOTLEN_L_P]=j& 0xff; fill_ip_hdr_checksum(buf); buf[TCP_CHECKSUM_H_P]=0; buf[TCP_CHECKSUM_L_P]=0; j=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+dlen,2); buf[TCP_CHECKSUM_H_P]=j>>8; buf[TCP_CHECKSUM_L_P]=j& 0xff; enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlen+ETH_HEADER_LEN,buf); }