📄 ip_arp_udp_tcp.c
字号:
make_eth(buf); make_ip(buf); buf[ICMP_TYPE_P]=ICMP_TYPE_ECHOREPLY_V; // we changed only the icmp.type field from request(=8) to reply(=0). // we can therefore easily correct the checksum: if (buf[ICMP_CHECKSUM_P] > (0xff-0x08)){ buf[ICMP_CHECKSUM_P+1]++; } buf[ICMP_CHECKSUM_P]+=0x08; // enc28j60PacketSend(len,buf);}// you can send a max of 220 bytes of datavoid make_udp_reply_from_request(unsigned char *buf,char *data,unsigned char datalen,unsigned char port){ unsigned char i=0; unsigned char ck; make_eth(buf); if (datalen>220){ datalen=220; } // total length field in the IP header must be set: buf[IP_TOTLEN_H_P]=0; buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+UDP_HEADER_LEN+datalen; make_ip(buf); buf[UDP_DST_PORT_H_P]=port>>8; buf[UDP_DST_PORT_L_P]=port & 0xff; // source port does not matter and is what the sender used. // calculte the udp length: buf[UDP_LEN_H_P]=0; buf[UDP_LEN_L_P]=UDP_HEADER_LEN+datalen; // zero the checksum buf[UDP_CHECKSUM_H_P]=0; buf[UDP_CHECKSUM_L_P]=0; // copy the data: while(i<datalen){ buf[UDP_DATA_P+i]=data[i]; i++; } ck=checksum(&buf[IP_SRC_P], 16 + datalen,1); buf[UDP_CHECKSUM_H_P]=ck>>8; buf[UDP_CHECKSUM_L_P]=ck& 0xff; enc28j60PacketSend(UDP_HEADER_LEN+IP_HEADER_LEN+ETH_HEADER_LEN+datalen,buf);}void make_tcp_synack_from_syn(unsigned char *buf){ unsigned char ck; make_eth(buf); // total length field in the IP header must be set: // 20 bytes IP + 24 bytes (20tcp+4tcp options) buf[IP_TOTLEN_H_P]=0; buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4; make_ip(buf); buf[TCP_FLAG_P]=TCP_FLAGS_SYNACK_V; make_tcphead(buf,1,1,0); // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + 4 (one option: mss) 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; // add 4 for option mss: enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4+ETH_HEADER_LEN,buf);}// get a pointer to the start of tcp data in buf// Returns 0 if there is no data// You must call init_len_info once before calling this functionunsigned int get_tcp_data_pointer(void){ if (info_data_len)
{ return ((unsigned char)TCP_SRC_PORT_H_P+info_hdr_len); }
else
{ return(0); }}// do some basic length calculations and store the result in static varibalesvoid init_len_info(unsigned char *buf){ 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; // generate len in bytes; info_data_len-=info_hdr_len; if (info_data_len<=0){ info_data_len=0; }}// fill in tcp data at position pos. pos=0 means start of// tcp data. Returns the position at which the string after// this string could be filled.unsigned int fill_tcp_data_p(unsigned char *buf,unsigned int pos,unsigned char *progmem_s){ char c; // fill in tcp data at position pos // // with no options the data starts after the checksum + 2 more bytes (urgent ptr) while ((c = *(progmem_s++))) { buf[TCP_CHECKSUM_L_P+3+pos]=c; pos++; } return(pos);}// fill in tcp data at position pos. pos=0 means start of// tcp data. Returns the position at which the string after// this string could be filled.unsigned int fill_tcp_data(unsigned char *buf,unsigned int pos, unsigned char *s){ // fill in tcp data at position pos // // with no options the data starts after the checksum + 2 more bytes (urgent ptr) while (*s)
{ buf[TCP_CHECKSUM_L_P+3+pos]=*s; pos++; s++; } return(pos);}// Make just an ack packet with no tcp data inside// This will modify the eth/ip/tcp header void make_tcp_ack_from_any(unsigned char *buf){ unsigned char j; make_eth(buf); // fill the header: buf[TCP_FLAG_P]=TCP_FLAG_ACK_V; if (info_data_len==0){ // if there is no data then we must still acknoledge one packet make_tcphead(buf,1,0,1); // no options }else{ make_tcphead(buf,info_data_len,0,1); // no options } // total length field in the IP header must be set: // 20 bytes IP + 20 bytes tcp (when no options) 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); // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len 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);}// you must have called init_len_info at some time before calling this function// dlen is the amount of tcp data (http data) we send in this packet// You can use this function only immediately after make_tcp_ack_from_any// This is because this function will NOT modify the eth/ip/tcp header except for// length and checksumvoid make_tcp_ack_with_data(unsigned char *buf,unsigned char dlen){ unsigned char j; // fill the header: // This code requires that we send only one data packet // because we keep no state information. We must therefore set // the fin here: buf[TCP_FLAG_P]=TCP_FLAG_ACK_V|TCP_FLAG_PUSH_V|TCP_FLAG_FIN_V; // total length field in the IP header must be set: // 20 bytes IP + 20 bytes tcp (when no options) + len of data 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); // zero the checksum buf[TCP_CHECKSUM_H_P]=0; buf[TCP_CHECKSUM_L_P]=0; // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len 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);}/* new functions for web client interface */void make_arp_request(unsigned char *buf, unsigned char *server_ip){ unsigned char i=0; while(i<6) { buf[ETH_DST_MAC +i]=0xff; buf[ETH_SRC_MAC +i]=macaddr[i]; i++; } buf[ ETH_TYPE_H_P ] = ETHTYPE_ARP_H_V; buf[ ETH_TYPE_L_P ] = ETHTYPE_ARP_L_V; // generate arp packet buf[ARP_OPCODE_H_P]=ARP_OPCODE_REQUEST_H_V; buf[ARP_OPCODE_L_P]=ARP_OPCODE_REQUEST_L_V; // fill in arp request packet // setup hardware type to ethernet 0x0001 buf[ ARP_HARDWARE_TYPE_H_P ] = ARP_HARDWARE_TYPE_H_V; buf[ ARP_HARDWARE_TYPE_L_P ] = ARP_HARDWARE_TYPE_L_V; // setup protocol type to ip 0x0800 buf[ ARP_PROTOCOL_H_P ] = ARP_PROTOCOL_H_V; buf[ ARP_PROTOCOL_L_P ] = ARP_PROTOCOL_L_V; // setup hardware length to 0x06 buf[ ARP_HARDWARE_SIZE_P ] = ARP_HARDWARE_SIZE_V; // setup protocol length to 0x04 buf[ ARP_PROTOCOL_SIZE_P ] = ARP_PROTOCOL_SIZE_V; // setup arp destination and source mac address for ( i=0; i<6; i++) { buf[ ARP_DST_MAC_P + i ] = 0x00; buf[ ARP_SRC_MAC_P + i ] = macaddr[i]; } // setup arp destination and source ip address for ( i=0; i<4; i++) { buf[ ARP_DST_IP_P + i ] = server_ip[i]; buf[ ARP_SRC_IP_P + i ] = ipaddr[i]; } // eth+arp is 42 bytes: enc28j60PacketSend(42,buf);}unsigned char arp_packet_is_myreply_arp ( unsigned char *buf ){ unsigned char i; // if packet type is not arp packet exit from function if( buf[ ETH_TYPE_H_P ] != ETHTYPE_ARP_H_V || buf[ ETH_TYPE_L_P ] != ETHTYPE_ARP_L_V) return 0; // check arp request opcode if ( buf[ ARP_OPCODE_H_P ] != ARP_OPCODE_REPLY_H_V || buf[ ARP_OPCODE_L_P ] != ARP_OPCODE_REPLY_L_V ) return 0; // if destination ip address in arp packet not match with avr ip address for(i=0; i<4; i++){ if(buf[ETH_ARP_DST_IP_P+i] != ipaddr[i]){ return 0; } } return 1;}// make a tcp headervoid tcp_client_send_packet(unsigned char *buf,unsigned char dest_port, unsigned char src_port, unsigned char flags, unsigned char max_segment_size, unsigned char clear_seqack, unsigned char next_ack_num, unsigned char dlength, unsigned char *dest_mac, unsigned char *dest_ip){ unsigned char i=0; unsigned char tseq; unsigned char ck; make_eth_ip_new(buf, dest_mac); buf[TCP_DST_PORT_H_P]= (unsigned char) ( (dest_port>>8) & 0xff); buf[TCP_DST_PORT_L_P]= (unsigned char) (dest_port & 0xff); buf[TCP_SRC_PORT_H_P]= (unsigned char) ( (src_port>>8) & 0xff); buf[TCP_SRC_PORT_L_P]= (unsigned char) (src_port & 0xff); // sequence numbers: // add the rel ack num to SEQACK if(next_ack_num) { for(i=4; i>0; i--) { next_ack_num=buf[TCP_SEQ_H_P+i-1]+next_ack_num; tseq=buf[TCP_SEQACK_H_P+i-1]; buf[TCP_SEQACK_H_P+i-1]=0xff&next_ack_num; // copy the acknum sent to us into the sequence number buf[TCP_SEQ_P + i - 1 ] = tseq; next_ack_num>>=8; } } // initial tcp sequence number,require to setup for first transmit/receive if(max_segment_size) { // 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; // setup maximum segment size buf[TCP_OPTIONS_P]=2; buf[TCP_OPTIONS_P+1]=4; buf[TCP_OPTIONS_P+2]=0x05; buf[TCP_OPTIONS_P+3]=0x80; // 24 bytes: buf[TCP_HEADER_LEN_P]=0x60; dlength +=4; } else{ // no options: // 20 bytes: buf[TCP_HEADER_LEN_P]=0x50; } make_ip_tcp_new(buf,IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlength, dest_ip); // clear sequence ack numer before send tcp SYN packet if(clear_seqack) { buf[TCP_SEQACK_P] = 0; buf[TCP_SEQACK_P+1] = 0; buf[TCP_SEQACK_P+2] = 0; buf[TCP_SEQACK_P+3] = 0; } // zero the checksum buf[TCP_CHECKSUM_H_P]=0; buf[TCP_CHECKSUM_L_P]=0; // set up flags buf[TCP_FLAG_P] = flags; // setup maximum windows size buf[ TCP_WINDOWSIZE_H_P ] = ((600 - IP_HEADER_LEN - ETH_HEADER_LEN)>>8) & 0xff; buf[ TCP_WINDOWSIZE_L_P ] = (600 - IP_HEADER_LEN - ETH_HEADER_LEN) & 0xff; // setup urgend pointer (not used -> 0) buf[ TCP_URGENT_PTR_H_P ] = 0; buf[ TCP_URGENT_PTR_L_P ] = 0; // check sum ck=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+dlength,2); buf[TCP_CHECKSUM_H_P]=ck>>8; buf[TCP_CHECKSUM_L_P]=ck& 0xff; // add 4 for option mss: enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlength+ETH_HEADER_LEN,buf);}unsigned int tcp_get_dlength(unsigned char *buf){ int dlength, hlength; dlength = ( buf[ IP_TOTLEN_H_P ] <<8 ) | ( buf[ IP_TOTLEN_L_P ] ); dlength -= IP_HEADER_LEN; hlength = (buf[ TCP_HEADER_LEN_P ]>>4) * 4; // generate len in bytes; dlength -= hlength; if ( dlength <= 0 ) dlength=0; return ((unsigned int)dlength);}/* end of ip_arp_udp.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -