#include #include "net.h" #include "enc28j60.h" static uint8_t macaddr[6]; static uint8_t ipaddr[4]; uint16_t checksum(uint8_t *buf, uint16_t len,uint8_t type); void init_ip_arp(uint8_t *mymac,uint8_t *myip); uint8_t eth_type_is_arp_and_my_ip(uint8_t *buf,uint16_t len); uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len); void make_eth(uint8_t *buf); void fill_ip_hdr_checksum(uint8_t *buf); void make_ip(uint8_t *buf); void make_arp_answer_from_request(uint8_t *buf); void make_echo_reply_from_request(uint8_t *buf,uint16_t len); void make_udp_reply_from_request(uint8_t *buf,char *data,uint8_t datalen,uint16_t port); uint16_t checksum(uint8_t *buf, uint16_t len,uint8_t type) { uint32_t sum = 0; if(type==1){ sum+=IP_PROTO_UDP_V; sum+=len-8; } // переведем сумму в 16-битные слова 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_udp_reply_from_request(uint8_t *buf,char *data,uint8_t datalen,uint16_t port)//функция ответа на UDP-запрос { uint8_t i=0;//объявляем переменную i и приравниваем ее к нулю uint16_t ck;//объявляем переменную ck make_eth(buf);// заполним ethernet-заголовок if (datalen>220)//определим максимальный размер данных для ответа (220 байт) { datalen=220; } buf[IP_TOTLEN_H_P]=0;//обнуляем старший байт поля "общая длина" заголовка IP buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+UDP_HEADER_LEN+datalen;//устанавливаем младший байт поля "общая длина" заголовка IP make_ip(buf);//заполним ip-заголовок buf[UDP_DST_PORT_H_P]=port>>8;//установим старший байт поля "порт назначения" заголовка UDP buf[UDP_DST_PORT_L_P]=port & 0xff;//установим младший байт поля "порт назначения" заголовка UDP buf[UDP_LEN_H_P]=0;//обнуляем старший байт поля "длина дейтаграммы" заголовка UDP buf[UDP_LEN_L_P]=UDP_HEADER_LEN+datalen;//устанавливаем младший байт поля "длина дейтаграммы" заголовка UDP buf[UDP_CHECKSUM_H_P]=0;//обнуляем поле "контрольная сумма" заголовка UDP buf[UDP_CHECKSUM_L_P]=0; while(i>8;//записываем вычисленную контрольную сумму в буфер buf[UDP_CHECKSUM_L_P]=ck& 0xff; enc28j60PacketSend(UDP_HEADER_LEN+IP_HEADER_LEN+ETH_HEADER_LEN+datalen,buf);//отправляем ответ UDP }