PageRenderTime 277ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 1ms

/ip_arp_udp_tcp.c

https://github.com/electronic-dudeness/EnergyMeter
C | 1514 lines | 1032 code | 64 blank | 418 comment | 112 complexity | 410576dd6d1cbf2fed9fc026142e2093 MD5 | raw file
  1. /*********************************************
  2. * vim:sw=8:ts=8:si:et
  3. * To use the above modeline in vim you must have "set modeline" in your .vimrc
  4. *
  5. * Author: Guido Socher
  6. * Copyright:LGPL V2
  7. * See http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html
  8. *
  9. * IP, Arp, UDP and TCP functions.
  10. *
  11. * The TCP implementation uses some size optimisations which are valid
  12. * only if all data can be sent in one single packet. This is however
  13. * not a big limitation for a microcontroller as you will anyhow use
  14. * small web-pages. The web server must send the entire web page in one
  15. * packet. The client "web browser" as implemented here can also receive
  16. * large pages.
  17. *
  18. * Chip type : ATMEGA88/168/328/644 with ENC28J60
  19. *********************************************/
  20. #include <avr/io.h>
  21. // http://www.nongnu.org/avr-libc/changes-1.8.html:
  22. #define __PROG_TYPES_COMPAT__
  23. #include <avr/pgmspace.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include <stdlib.h>
  27. #include "net.h"
  28. #include "enc28j60.h"
  29. #include "ip_config.h"
  30. // I use them to debug stuff:
  31. #define LEDOFF PORTB|=(1<<PORTB1)
  32. #define LEDON PORTB&=~(1<<PORTB1)
  33. //
  34. static uint8_t macaddr[6];
  35. static uint8_t ipaddr[4]={0,0,0,0};
  36. static uint8_t seqnum=0xa; // my initial tcp sequence number
  37. static void (*icmp_callback)(uint8_t *ip);
  38. //
  39. #if defined (NTP_client) || defined (UDP_client) || defined (TCP_client) || defined (PING_client)
  40. #define ARP_MAC_resolver_client 1
  41. #define ALL_clients 1
  42. #endif
  43. #if defined (WWW_client) || defined (TCP_client)
  44. // just lower byte, the upper byte is TCPCLIENT_SRC_PORT_H:
  45. static uint8_t tcpclient_src_port_l=1;
  46. static uint8_t tcp_fd=0; // a file descriptor, will be encoded into the port
  47. static uint8_t tcp_otherside_ip[4];
  48. static uint8_t tcp_dst_mac[6]; // normally the gateway via which we want to send
  49. static uint8_t tcp_client_state=0;
  50. static uint16_t tcp_client_port=0;
  51. // This function will be called if we ever get a result back from the
  52. // TCP connection to the sever:
  53. // close_connection= your_client_tcp_result_callback(uint8_t fd, uint8_t statuscode,uint16_t data_start_pos_in_buf, uint16_t len_of_data){...your code}
  54. // statuscode=0 means the buffer has valid data
  55. static uint8_t (*client_tcp_result_callback)(uint8_t,uint8_t,uint16_t,uint16_t);
  56. // len_of_data_filled_in=your_client_tcp_datafill_callback(uint8_t fd){...your code}
  57. static uint16_t (*client_tcp_datafill_callback)(uint8_t);
  58. #endif
  59. #define TCPCLIENT_SRC_PORT_H 11
  60. #if defined (WWW_client)
  61. // WWW_client uses TCP_client
  62. #define TCP_client 1
  63. static uint8_t www_fd=0;
  64. static uint8_t browsertype=0; // 0 = get, 1 = post
  65. static void (*client_browser_callback)(uint16_t,uint16_t,uint16_t); // the fields are: uint16_t webstatuscode,uint16_t datapos,uint16_t len; datapos is start of http data and len the the length of that data
  66. static const prog_char *client_additionalheaderline;
  67. static char *client_postval;
  68. static const prog_char *client_urlbuf;
  69. static const char *client_urlbuf_var;
  70. static const char *client_hoststr;
  71. static uint8_t *bufptr=0; // ugly workaround for backward compatibility
  72. #endif
  73. #ifdef ARP_MAC_resolver_client
  74. // This function will be called if we ever get a result back from the
  75. // the arp request we sent out.
  76. void (*client_arp_result_callback)(uint8_t*,uint8_t,uint8_t*);
  77. static int16_t arp_delaycnt=1;
  78. static uint8_t arpip[4]; // IP to find via arp
  79. static uint8_t arpip_state=0; // 0 at poweron, 1=req sent no answer yet, 2=have mac, 8=ready to accept an arp reply
  80. static uint8_t arp_reference_number=0;
  81. #define WGW_INITIAL_ARP 1
  82. #define WGW_HAVE_MAC 2
  83. #define WGW_ACCEPT_ARP_REPLY 8
  84. #endif
  85. #ifdef WWW_server
  86. static uint8_t wwwport_l=80; // server port
  87. static uint8_t wwwport_h=0; // Note: never use same as TCPCLIENT_SRC_PORT_H
  88. static uint16_t info_data_len=0;
  89. #endif
  90. #if defined (ALL_clients)
  91. static uint8_t ipnetmask[4]={255,255,255,255};
  92. static uint8_t ipid=0x2; // IP-identification, it works as well if you do not change it but it is better to fill the field, we count this number up and wrap.
  93. const char iphdr[] PROGMEM ={0x45,0,0,0x82,0,0,0x40,0,0x20}; // 0x82 is the total len on ip, 0x20 is ttl (time to live), the second 0,0 is IP-identification and may be changed.
  94. #endif
  95. #define CLIENTMSS 750
  96. #define TCP_DATA_START ((uint16_t)TCP_SRC_PORT_H_P+(buf[TCP_HEADER_LEN_P]>>4)*4)
  97. const char arpreqhdr[] PROGMEM ={0,1,8,0,6,4,0,1};
  98. #ifdef NTP_client
  99. const char ntpreqhdr[] PROGMEM ={0xe3,0,4,0xfa,0,1,0,0,0,1};
  100. #endif
  101. // The Ip checksum is calculated over the ip header only starting
  102. // with the header length field and a total length of 20 bytes
  103. // unitl ip.dst
  104. // You must set the IP checksum field to zero before you start
  105. // the calculation.
  106. // len for ip is 20.
  107. //
  108. // For UDP/TCP we do not make up the required pseudo header. Instead we
  109. // use the ip.src and ip.dst fields of the real packet:
  110. // The udp checksum calculation starts with the ip.src field
  111. // Ip.src=4bytes,Ip.dst=4 bytes,Udp header=8bytes + data length=16+len
  112. // In other words the len here is 8 + length over which you actually
  113. // want to calculate the checksum.
  114. // You must set the checksum field to zero before you start
  115. // the calculation.
  116. // The same algorithm is also used for udp and tcp checksums.
  117. // len for udp is: 8 + 8 + data length
  118. // len for tcp is: 4+4 + 20 + option len + data length
  119. //
  120. // For more information on how this algorithm works see:
  121. // http://www.netfor2.com/checksum.html
  122. // http://www.msc.uky.edu/ken/cs471/notes/chap3.htm
  123. // The RFC has also a C code example: http://www.faqs.org/rfcs/rfc1071.html
  124. uint16_t checksum(uint8_t *buf, uint16_t len,uint8_t type){
  125. // type 0=ip , icmp
  126. // 1=udp
  127. // 2=tcp
  128. uint32_t sum = 0;
  129. //if(type==0){
  130. // // do not add anything, standard IP checksum as described above
  131. // // Usable for ICMP and IP header
  132. //}
  133. if(type==1){
  134. sum+=IP_PROTO_UDP_V; // protocol udp
  135. // the length here is the length of udp (data+header len)
  136. // =length given to this function - (IP.scr+IP.dst length)
  137. sum+=len-8; // = real udp len
  138. }
  139. if(type==2){
  140. sum+=IP_PROTO_TCP_V;
  141. // the length here is the length of tcp (data+header len)
  142. // =length given to this function - (IP.scr+IP.dst length)
  143. sum+=len-8; // = real tcp len
  144. }
  145. // build the sum of 16bit words
  146. while(len >1){
  147. sum += 0xFFFF & (((uint32_t)*buf<<8)|*(buf+1));
  148. buf+=2;
  149. len-=2;
  150. }
  151. // if there is a byte left then add it (padded with zero)
  152. if (len){
  153. sum += ((uint32_t)(0xFF & *buf))<<8;
  154. }
  155. // now calculate the sum over the bytes in the sum
  156. // until the result is only 16bit long
  157. while (sum>>16){
  158. sum = (sum & 0xFFFF)+(sum >> 16);
  159. }
  160. // build 1's complement:
  161. return( (uint16_t) sum ^ 0xFFFF);
  162. }
  163. void init_mac(uint8_t *mymac){
  164. if (mymac){
  165. memcpy(macaddr,mymac,6);
  166. }
  167. }
  168. #if defined (ALL_clients)
  169. void client_ifconfig(uint8_t *ip,uint8_t *netmask)
  170. {
  171. uint8_t i;
  172. if (ip){
  173. i=0;while(i<4){ipaddr[i]=ip[i];i++;}
  174. }
  175. if (netmask){
  176. i=0;while(i<4){ipnetmask[i]=netmask[i];i++;}
  177. }
  178. }
  179. // returns 1 if destip must be routed via the GW. Returns 0 if destip is on the local LAN
  180. uint8_t route_via_gw(uint8_t *destip)
  181. {
  182. uint8_t i=0;
  183. while(i<4){
  184. if ((destip[i] & ipnetmask[i]) != (ipaddr[i] & ipnetmask[i])){
  185. return(1);
  186. }
  187. i++;
  188. }
  189. return(0);
  190. }
  191. #endif
  192. uint8_t check_ip_message_is_from(uint8_t *buf,uint8_t *ip)
  193. {
  194. uint8_t i=0;
  195. while(i<4){
  196. if(buf[IP_SRC_P+i]!=ip[i]){
  197. return(0);
  198. }
  199. i++;
  200. }
  201. return(1);
  202. }
  203. uint8_t eth_type_is_arp_and_my_ip(uint8_t *buf,uint16_t len){
  204. uint8_t i=0;
  205. //
  206. if (len<41){
  207. return(0);
  208. }
  209. if(buf[ETH_TYPE_H_P] != ETHTYPE_ARP_H_V ||
  210. buf[ETH_TYPE_L_P] != ETHTYPE_ARP_L_V){
  211. return(0);
  212. }
  213. while(i<4){
  214. if(buf[ETH_ARP_DST_IP_P+i] != ipaddr[i]){
  215. return(0);
  216. }
  217. i++;
  218. }
  219. return(1);
  220. }
  221. uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len){
  222. uint8_t i=0;
  223. //eth+ip+udp header is 42
  224. if (len<42){
  225. return(0);
  226. }
  227. if(buf[ETH_TYPE_H_P]!=ETHTYPE_IP_H_V ||
  228. buf[ETH_TYPE_L_P]!=ETHTYPE_IP_L_V){
  229. return(0);
  230. }
  231. if (buf[IP_HEADER_LEN_VER_P]!=0x45){
  232. // must be IP V4 and 20 byte header
  233. return(0);
  234. }
  235. while(i<4){
  236. if(buf[IP_DST_P+i]!=ipaddr[i]){
  237. return(0);
  238. }
  239. i++;
  240. }
  241. return(1);
  242. }
  243. // make a return eth header from a received eth packet
  244. void make_eth(uint8_t *buf)
  245. {
  246. uint8_t i=0;
  247. //
  248. //copy the destination mac from the source and fill my mac into src
  249. while(i<6){
  250. buf[ETH_DST_MAC +i]=buf[ETH_SRC_MAC +i];
  251. buf[ETH_SRC_MAC +i]=macaddr[i];
  252. i++;
  253. }
  254. }
  255. void fill_ip_hdr_checksum(uint8_t *buf)
  256. {
  257. uint16_t ck;
  258. // clear the 2 byte checksum
  259. buf[IP_CHECKSUM_P]=0;
  260. buf[IP_CHECKSUM_P+1]=0;
  261. buf[IP_FLAGS_P]=0x40; // don't fragment
  262. buf[IP_FLAGS_P+1]=0; // fragement offset
  263. buf[IP_TTL_P]=64; // ttl
  264. // calculate the checksum:
  265. ck=checksum(&buf[IP_P], IP_HEADER_LEN,0);
  266. buf[IP_CHECKSUM_P]=ck>>8;
  267. buf[IP_CHECKSUM_P+1]=ck& 0xff;
  268. }
  269. // make a return ip header from a received ip packet
  270. void make_ip(uint8_t *buf)
  271. {
  272. uint8_t i=0;
  273. while(i<4){
  274. buf[IP_DST_P+i]=buf[IP_SRC_P+i];
  275. buf[IP_SRC_P+i]=ipaddr[i];
  276. i++;
  277. }
  278. fill_ip_hdr_checksum(buf);
  279. }
  280. // swap seq and ack number and count ack number up
  281. void step_seq(uint8_t *buf,uint16_t rel_ack_num,uint8_t cp_seq)
  282. {
  283. uint8_t i;
  284. uint8_t tseq;
  285. i=4;
  286. // sequence numbers:
  287. // add the rel ack num to SEQACK
  288. while(i>0){
  289. rel_ack_num=buf[TCP_SEQ_H_P+i-1]+rel_ack_num;
  290. tseq=buf[TCP_SEQACK_H_P+i-1];
  291. buf[TCP_SEQACK_H_P+i-1]=0xff&rel_ack_num;
  292. if (cp_seq){
  293. // copy the acknum sent to us into the sequence number
  294. buf[TCP_SEQ_H_P+i-1]=tseq;
  295. }else{
  296. buf[TCP_SEQ_H_P+i-1]= 0; // some preset value
  297. }
  298. rel_ack_num=rel_ack_num>>8;
  299. i--;
  300. }
  301. }
  302. // make a return tcp header from a received tcp packet
  303. // rel_ack_num is how much we must step the seq number received from the
  304. // other side. We do not send more than 765 bytes of text (=data) in the tcp packet.
  305. // No mss is included here.
  306. //
  307. // After calling this function you can fill in the first data byte at TCP_OPTIONS_P+4
  308. // If cp_seq=0 then an initial sequence number is used (should be use in synack)
  309. // otherwise it is copied from the packet we received
  310. void make_tcphead(uint8_t *buf,uint16_t rel_ack_num,uint8_t cp_seq)
  311. {
  312. uint8_t i;
  313. // copy ports:
  314. i=buf[TCP_DST_PORT_H_P];
  315. buf[TCP_DST_PORT_H_P]=buf[TCP_SRC_PORT_H_P];
  316. buf[TCP_SRC_PORT_H_P]=i;
  317. //
  318. i=buf[TCP_DST_PORT_L_P];
  319. buf[TCP_DST_PORT_L_P]=buf[TCP_SRC_PORT_L_P];
  320. buf[TCP_SRC_PORT_L_P]=i;
  321. step_seq(buf,rel_ack_num,cp_seq);
  322. // zero the checksum
  323. buf[TCP_CHECKSUM_H_P]=0;
  324. buf[TCP_CHECKSUM_L_P]=0;
  325. // no options:
  326. // 20 bytes:
  327. // The tcp header length is only a 4 bit field (the upper 4 bits).
  328. // It is calculated in units of 4 bytes.
  329. // E.g 20 bytes: 20/4=6 => 0x50=header len field
  330. buf[TCP_HEADER_LEN_P]=0x50;
  331. }
  332. void make_arp_answer_from_request(uint8_t *buf)
  333. {
  334. uint8_t i=0;
  335. //
  336. make_eth(buf);
  337. buf[ETH_ARP_OPCODE_H_P]=ETH_ARP_OPCODE_REPLY_H_V;
  338. buf[ETH_ARP_OPCODE_L_P]=ETH_ARP_OPCODE_REPLY_L_V;
  339. // fill the mac addresses:
  340. while(i<6){
  341. buf[ETH_ARP_DST_MAC_P+i]=buf[ETH_ARP_SRC_MAC_P+i];
  342. buf[ETH_ARP_SRC_MAC_P+i]=macaddr[i];
  343. i++;
  344. }
  345. i=0;
  346. while(i<4){
  347. buf[ETH_ARP_DST_IP_P+i]=buf[ETH_ARP_SRC_IP_P+i];
  348. buf[ETH_ARP_SRC_IP_P+i]=ipaddr[i];
  349. i++;
  350. }
  351. // eth+arp is 42 bytes:
  352. enc28j60PacketSend(42,buf);
  353. }
  354. void make_echo_reply_from_request(uint8_t *buf,uint16_t len)
  355. {
  356. make_eth(buf);
  357. make_ip(buf);
  358. buf[ICMP_TYPE_P]=ICMP_TYPE_ECHOREPLY_V;
  359. // we changed only the icmp.type field from request(=8) to reply(=0).
  360. // we can therefore easily correct the checksum:
  361. if (buf[ICMP_CHECKSUM_P] > (0xff-0x08)){
  362. buf[ICMP_CHECKSUM_P+1]++;
  363. }
  364. buf[ICMP_CHECKSUM_P]+=0x08;
  365. //
  366. enc28j60PacketSend(len,buf);
  367. }
  368. // do some basic length calculations
  369. uint16_t get_tcp_data_len(uint8_t *buf)
  370. {
  371. int16_t i;
  372. i=(((int16_t)buf[IP_TOTLEN_H_P])<<8)|(buf[IP_TOTLEN_L_P]&0xff);
  373. i-=IP_HEADER_LEN;
  374. i-=(buf[TCP_HEADER_LEN_P]>>4)*4; // generate len in bytes;
  375. if (i<=0){
  376. i=0;
  377. }
  378. return((uint16_t)i);
  379. }
  380. // fill in tcp data at position pos. pos=0 means start of
  381. // tcp data. Returns the position at which the string after
  382. // this string could be filled.
  383. uint16_t fill_tcp_data_p(uint8_t *buf,uint16_t pos, const prog_char *progmem_s)
  384. {
  385. char c;
  386. // fill in tcp data at position pos
  387. //
  388. // with no options the data starts after the checksum + 2 more bytes (urgent ptr)
  389. while ((c = pgm_read_byte(progmem_s++))) {
  390. buf[TCP_CHECKSUM_L_P+3+pos]=c;
  391. pos++;
  392. }
  393. return(pos);
  394. }
  395. // fill a binary string of len data into the tcp packet
  396. uint16_t fill_tcp_data_len(uint8_t *buf,uint16_t pos, const uint8_t *s, uint8_t len)
  397. {
  398. // fill in tcp data at position pos
  399. //
  400. // with no options the data starts after the checksum + 2 more bytes (urgent ptr)
  401. while (len) {
  402. buf[TCP_CHECKSUM_L_P+3+pos]=*s;
  403. pos++;
  404. s++;
  405. len--;
  406. }
  407. return(pos);
  408. }
  409. // fill in tcp data at position pos. pos=0 means start of
  410. // tcp data. Returns the position at which the string after
  411. // this string could be filled.
  412. uint16_t fill_tcp_data(uint8_t *buf,uint16_t pos, const char *s)
  413. {
  414. return(fill_tcp_data_len(buf,pos,(uint8_t*)s,strlen(s)));
  415. }
  416. // Make just an ack packet with no tcp data inside
  417. // This will modify the eth/ip/tcp header
  418. void make_tcp_ack_from_any(uint8_t *buf,int16_t datlentoack,uint8_t addflags)
  419. {
  420. uint16_t j;
  421. make_eth(buf);
  422. // fill the header:
  423. buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V|addflags;
  424. if (addflags==TCP_FLAGS_RST_V){
  425. make_tcphead(buf,datlentoack,1);
  426. }else{
  427. if (datlentoack==0){
  428. // if there is no data then we must still acknoledge one packet
  429. datlentoack=1;
  430. }
  431. // normal case, ack the data:
  432. make_tcphead(buf,datlentoack,1); // no options
  433. }
  434. // total length field in the IP header must be set:
  435. // 20 bytes IP + 20 bytes tcp (when no options)
  436. j=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN;
  437. buf[IP_TOTLEN_H_P]=j>>8;
  438. buf[IP_TOTLEN_L_P]=j& 0xff;
  439. make_ip(buf);
  440. // use a low window size otherwise we have to have
  441. // timers and can not just react on every packet.
  442. buf[TCP_WIN_SIZE]=0x4; // 1024=0x400, 1280=0x500 2048=0x800 768=0x300
  443. buf[TCP_WIN_SIZE+1]=0;
  444. // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len
  445. j=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN,2);
  446. buf[TCP_CHECKSUM_H_P]=j>>8;
  447. buf[TCP_CHECKSUM_L_P]=j& 0xff;
  448. enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+ETH_HEADER_LEN,buf);
  449. }
  450. // dlen is the amount of tcp data (http data) we send in this packet
  451. // You can use this function only immediately after make_tcp_ack_from_any
  452. // This is because this function will NOT modify the eth/ip/tcp header except for
  453. // length and checksum
  454. // You must set TCP_FLAGS before calling this
  455. void make_tcp_ack_with_data_noflags(uint8_t *buf,uint16_t dlen)
  456. {
  457. uint16_t j;
  458. // total length field in the IP header must be set:
  459. // 20 bytes IP + 20 bytes tcp (when no options) + len of data
  460. j=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlen;
  461. buf[IP_TOTLEN_H_P]=j>>8;
  462. buf[IP_TOTLEN_L_P]=j& 0xff;
  463. fill_ip_hdr_checksum(buf);
  464. // zero the checksum
  465. buf[TCP_CHECKSUM_H_P]=0;
  466. buf[TCP_CHECKSUM_L_P]=0;
  467. // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len
  468. j=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+dlen,2);
  469. buf[TCP_CHECKSUM_H_P]=j>>8;
  470. buf[TCP_CHECKSUM_L_P]=j& 0xff;
  471. enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlen+ETH_HEADER_LEN,buf);
  472. }
  473. #if defined (UDP_server)
  474. // a udp server
  475. void make_udp_reply_from_request_udpdat_ready(uint8_t *buf,uint16_t datalen,uint16_t port)
  476. {
  477. uint16_t j;
  478. make_eth(buf);
  479. if (datalen>220){
  480. datalen=220;
  481. }
  482. // total length field in the IP header must be set:
  483. j=IP_HEADER_LEN+UDP_HEADER_LEN+datalen;
  484. buf[IP_TOTLEN_H_P]=j>>8;
  485. buf[IP_TOTLEN_L_P]=j& 0xff;
  486. make_ip(buf);
  487. // send to port:
  488. //buf[UDP_DST_PORT_H_P]=port>>8;
  489. //buf[UDP_DST_PORT_L_P]=port & 0xff;
  490. // sent to port of sender and use "port" as own source:
  491. buf[UDP_DST_PORT_H_P]=buf[UDP_SRC_PORT_H_P];
  492. buf[UDP_DST_PORT_L_P]= buf[UDP_SRC_PORT_L_P];
  493. buf[UDP_SRC_PORT_H_P]=port>>8;
  494. buf[UDP_SRC_PORT_L_P]=port & 0xff;
  495. // calculte the udp length:
  496. j=UDP_HEADER_LEN+datalen;
  497. buf[UDP_LEN_H_P]=j>>8;
  498. buf[UDP_LEN_L_P]=j& 0xff;
  499. // zero the checksum
  500. buf[UDP_CHECKSUM_H_P]=0;
  501. buf[UDP_CHECKSUM_L_P]=0;
  502. j=checksum(&buf[IP_SRC_P], 16 + datalen,1);
  503. buf[UDP_CHECKSUM_H_P]=j>>8;
  504. buf[UDP_CHECKSUM_L_P]=j& 0xff;
  505. enc28j60PacketSend(UDP_HEADER_LEN+IP_HEADER_LEN+ETH_HEADER_LEN+datalen,buf);
  506. }
  507. // you can send a max of 220 bytes of data because we use only one
  508. // byte for the data but udp messages are normally small.
  509. void make_udp_reply_from_request(uint8_t *buf,char *data,uint8_t datalen,uint16_t port)
  510. {
  511. uint8_t i=0;
  512. // copy the data:
  513. while(i<datalen){
  514. buf[UDP_DATA_P+i]=data[i];
  515. i++;
  516. }
  517. make_udp_reply_from_request_udpdat_ready(buf,datalen,port);
  518. }
  519. #endif // UDP_server
  520. #if defined (UDP_server) || defined (WWW_server)
  521. // This initializes server
  522. // you must call this function once before you use any of the other functions:
  523. // mymac may be NULL and can be used if you did already call init_mac
  524. void init_udp_or_www_server(uint8_t *mymac,uint8_t *myip){
  525. uint8_t i=0;
  526. if (myip){
  527. while(i<4){
  528. ipaddr[i]=myip[i];
  529. i++;
  530. }
  531. }
  532. if (mymac) init_mac(mymac);
  533. }
  534. #endif // UDP_server || WWW_server
  535. #ifdef WWW_server
  536. // not needed if you want port 80 (the default is port 80):
  537. void www_server_port(uint16_t port){
  538. wwwport_h=(port>>8)&0xff;
  539. wwwport_l=(port&0xff);
  540. }
  541. // this is for the server not the client:
  542. void make_tcp_synack_from_syn(uint8_t *buf)
  543. {
  544. uint16_t ck;
  545. make_eth(buf);
  546. // total length field in the IP header must be set:
  547. // 20 bytes IP + 24 bytes (20tcp+4tcp options)
  548. buf[IP_TOTLEN_H_P]=0;
  549. buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4;
  550. make_ip(buf);
  551. buf[TCP_FLAGS_P]=TCP_FLAGS_SYNACK_V;
  552. make_tcphead(buf,1,0);
  553. // put an inital seq number
  554. buf[TCP_SEQ_H_P+0]= 0;
  555. buf[TCP_SEQ_H_P+1]= 0;
  556. // we step only the second byte, this allows us to send packts
  557. // with 255 bytes, 512 or 765 (step by 3) without generating
  558. // overlapping numbers.
  559. buf[TCP_SEQ_H_P+2]= seqnum;
  560. buf[TCP_SEQ_H_P+3]= 0;
  561. // step the inititial seq num by something we will not use
  562. // during this tcp session:
  563. seqnum+=3;
  564. // add an mss options field with MSS to 1280:
  565. // 1280 in hex is 0x500
  566. buf[TCP_OPTIONS_P]=2;
  567. buf[TCP_OPTIONS_P+1]=4;
  568. buf[TCP_OPTIONS_P+2]=0x05;
  569. buf[TCP_OPTIONS_P+3]=0x0;
  570. // The tcp header length is only a 4 bit field (the upper 4 bits).
  571. // It is calculated in units of 4 bytes.
  572. // E.g 24 bytes: 24/4=6 => 0x60=header len field
  573. buf[TCP_HEADER_LEN_P]=0x60;
  574. // here we must just be sure that the web browser contacting us
  575. // will send only one get packet
  576. buf[TCP_WIN_SIZE]=0x0a; // was 1400=0x578, 2560=0xa00 suggested by Andras Tucsni to be able to receive bigger packets
  577. buf[TCP_WIN_SIZE+1]=0; //
  578. // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + 4 (one option: mss)
  579. ck=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+4,2);
  580. buf[TCP_CHECKSUM_H_P]=ck>>8;
  581. buf[TCP_CHECKSUM_L_P]=ck& 0xff;
  582. // add 4 for option mss:
  583. enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4+ETH_HEADER_LEN,buf);
  584. }
  585. // you must have initialized info_data_len at some time before calling this function
  586. //
  587. // This info_data_len initialisation is done automatically if you call
  588. // packetloop_icmp_tcp(buf,enc28j60PacketReceive(BUFFER_SIZE, buf));
  589. // and test the return value for non zero.
  590. //
  591. // dlen is the amount of tcp data (http data) we send in this packet
  592. // You can use this function only immediately after make_tcp_ack_from_any
  593. // This is because this function will NOT modify the eth/ip/tcp header except for
  594. // length and checksum
  595. void www_server_reply(uint8_t *buf,uint16_t dlen)
  596. {
  597. make_tcp_ack_from_any(buf,info_data_len,0); // send ack for http get
  598. // fill the header:
  599. // This code requires that we send only one data packet
  600. // because we keep no state information. We must therefore set
  601. // the fin here:
  602. buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V|TCP_FLAGS_PUSH_V|TCP_FLAGS_FIN_V;
  603. make_tcp_ack_with_data_noflags(buf,dlen); // send data
  604. }
  605. #endif // WWW_server
  606. #if defined (ALL_clients)
  607. // fill buffer with a prog-mem string
  608. void fill_buf_p(uint8_t *buf,uint16_t len, const prog_char *progmem_s)
  609. {
  610. while (len){
  611. *buf= pgm_read_byte(progmem_s);
  612. buf++;
  613. progmem_s++;
  614. len--;
  615. }
  616. }
  617. #endif
  618. #ifdef PING_client
  619. // icmp echo, matchpat is a pattern that has to be sent back by the
  620. // host answering the ping.
  621. // The ping is sent to destip and mac dstmac
  622. void client_icmp_request(uint8_t *buf,uint8_t *destip,uint8_t *dstmac)
  623. {
  624. uint8_t i=0;
  625. uint16_t ck;
  626. //
  627. while(i<6){
  628. buf[ETH_DST_MAC +i]=dstmac[i]; // gw mac in local lan or host mac
  629. buf[ETH_SRC_MAC +i]=macaddr[i];
  630. i++;
  631. }
  632. buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  633. buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  634. fill_buf_p(&buf[IP_P],9,iphdr);
  635. buf[IP_ID_L_P]=ipid; ipid++;
  636. buf[IP_TOTLEN_L_P]=0x54;
  637. buf[IP_PROTO_P]=IP_PROTO_ICMP_V;
  638. i=0;
  639. while(i<4){
  640. buf[IP_DST_P+i]=destip[i];
  641. buf[IP_SRC_P+i]=ipaddr[i];
  642. i++;
  643. }
  644. fill_ip_hdr_checksum(buf);
  645. buf[ICMP_TYPE_P]=ICMP_TYPE_ECHOREQUEST_V;
  646. buf[ICMP_TYPE_P+1]=0; // code
  647. // zero the checksum
  648. buf[ICMP_CHECKSUM_H_P]=0;
  649. buf[ICMP_CHECKSUM_L_P]=0;
  650. // a possibly unique id of this host:
  651. buf[ICMP_IDENT_H_P]=5; // some number
  652. buf[ICMP_IDENT_L_P]=ipaddr[3]; // last byte of my IP
  653. //
  654. buf[ICMP_IDENT_L_P+1]=0; // seq number, high byte
  655. buf[ICMP_IDENT_L_P+2]=1; // seq number, low byte, we send only 1 ping at a time
  656. // copy the data:
  657. i=0;
  658. while(i<56){
  659. buf[ICMP_DATA_P+i]=PINGPATTERN;
  660. i++;
  661. }
  662. //
  663. ck=checksum(&buf[ICMP_TYPE_P], 56+8,0);
  664. buf[ICMP_CHECKSUM_H_P]=ck>>8;
  665. buf[ICMP_CHECKSUM_L_P]=ck& 0xff;
  666. enc28j60PacketSend(98,buf);
  667. }
  668. #endif // PING_client
  669. #ifdef NTP_client
  670. // ntp udp packet
  671. // See http://tools.ietf.org/html/rfc958 for details
  672. //
  673. void client_ntp_request(uint8_t *buf,uint8_t *ntpip,uint8_t srcport,uint8_t *dstmac)
  674. {
  675. uint8_t i=0;
  676. uint16_t ck;
  677. //
  678. while(i<6){
  679. buf[ETH_DST_MAC +i]=dstmac[i]; // gw mac in local lan or host mac
  680. buf[ETH_SRC_MAC +i]=macaddr[i];
  681. i++;
  682. }
  683. buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  684. buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  685. fill_buf_p(&buf[IP_P],9,iphdr);
  686. buf[IP_ID_L_P]=ipid; ipid++;
  687. buf[IP_TOTLEN_L_P]=0x4c;
  688. buf[IP_PROTO_P]=IP_PROTO_UDP_V;
  689. i=0;
  690. while(i<4){
  691. buf[IP_DST_P+i]=ntpip[i];
  692. buf[IP_SRC_P+i]=ipaddr[i];
  693. i++;
  694. }
  695. fill_ip_hdr_checksum(buf);
  696. buf[UDP_DST_PORT_H_P]=0;
  697. buf[UDP_DST_PORT_L_P]=0x7b; // ntp=123
  698. buf[UDP_SRC_PORT_H_P]=10;
  699. buf[UDP_SRC_PORT_L_P]=srcport; // lower 8 bit of src port
  700. buf[UDP_LEN_H_P]=0;
  701. buf[UDP_LEN_L_P]=56; // fixed len
  702. // zero the checksum
  703. buf[UDP_CHECKSUM_H_P]=0;
  704. buf[UDP_CHECKSUM_L_P]=0;
  705. // copy the data:
  706. i=0;
  707. // most fields are zero, here we zero everything and fill later
  708. while(i<48){
  709. buf[UDP_DATA_P+i]=0;
  710. i++;
  711. }
  712. fill_buf_p(&buf[UDP_DATA_P],10,ntpreqhdr);
  713. //
  714. ck=checksum(&buf[IP_SRC_P], 16 + 48,1);
  715. buf[UDP_CHECKSUM_H_P]=ck>>8;
  716. buf[UDP_CHECKSUM_L_P]=ck& 0xff;
  717. enc28j60PacketSend(90,buf);
  718. }
  719. // process the answer from the ntp server:
  720. // if dstport==0 then accept any port otherwise only answers going to dstport
  721. // return 1 on sucessful processing of answer
  722. uint8_t client_ntp_process_answer(uint8_t *buf,uint32_t *time,uint8_t dstport_l){
  723. if (dstport_l){
  724. if (buf[UDP_DST_PORT_L_P]!=dstport_l){
  725. return(0);
  726. }
  727. }
  728. if (buf[UDP_LEN_H_P]!=0 || buf[UDP_LEN_L_P]!=56 || buf[UDP_SRC_PORT_L_P]!=0x7b){
  729. // not ntp
  730. return(0);
  731. }
  732. // copy time from the transmit time stamp field:
  733. *time=((uint32_t)buf[0x52]<<24)|((uint32_t)buf[0x53]<<16)|((uint32_t)buf[0x54]<<8)|((uint32_t)buf[0x55]);
  734. return(1);
  735. }
  736. #endif
  737. #ifdef UDP_client
  738. // -------------------- send a spontanious UDP packet to a server
  739. // There are two ways of using this:
  740. // 1) you call send_udp_prepare, you fill the data yourself into buf starting at buf[UDP_DATA_P],
  741. // you send the packet by calling send_udp_transmit
  742. //
  743. // 2) You just allocate a large enough buffer for you data and you call send_udp and nothing else
  744. // needs to be done.
  745. //
  746. void send_udp_prepare(uint8_t *buf,uint16_t sport, const uint8_t *dip, uint16_t dport,const uint8_t *dstmac)
  747. {
  748. uint8_t i=0;
  749. //
  750. while(i<6){
  751. buf[ETH_DST_MAC +i]=dstmac[i]; // gw mac in local lan or host mac
  752. buf[ETH_SRC_MAC +i]=macaddr[i];
  753. i++;
  754. }
  755. buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  756. buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  757. fill_buf_p(&buf[IP_P],9,iphdr);
  758. buf[IP_ID_L_P]=ipid; ipid++;
  759. // total length field in the IP header must be set:
  760. buf[IP_TOTLEN_H_P]=0;
  761. // done in transmit: buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+UDP_HEADER_LEN+datalen;
  762. buf[IP_PROTO_P]=IP_PROTO_UDP_V;
  763. i=0;
  764. while(i<4){
  765. buf[IP_DST_P+i]=dip[i];
  766. buf[IP_SRC_P+i]=ipaddr[i];
  767. i++;
  768. }
  769. // done in transmit: fill_ip_hdr_checksum(buf);
  770. buf[UDP_DST_PORT_H_P]=(dport>>8);
  771. buf[UDP_DST_PORT_L_P]=0xff&dport;
  772. buf[UDP_SRC_PORT_H_P]=(sport>>8);
  773. buf[UDP_SRC_PORT_L_P]=sport&0xff;
  774. buf[UDP_LEN_H_P]=0;
  775. // done in transmit: buf[UDP_LEN_L_P]=UDP_HEADER_LEN+datalen;
  776. // zero the checksum
  777. buf[UDP_CHECKSUM_H_P]=0;
  778. buf[UDP_CHECKSUM_L_P]=0;
  779. // copy the data:
  780. // now starting with the first byte at buf[UDP_DATA_P]
  781. //
  782. }
  783. void send_udp_transmit(uint8_t *buf,uint16_t datalen)
  784. {
  785. uint16_t tmp16;
  786. tmp16=IP_HEADER_LEN+UDP_HEADER_LEN+datalen;
  787. buf[IP_TOTLEN_L_P]=tmp16& 0xff;
  788. buf[IP_TOTLEN_H_P]=tmp16>>8;
  789. fill_ip_hdr_checksum(buf);
  790. tmp16=UDP_HEADER_LEN+datalen;
  791. buf[UDP_LEN_L_P]=tmp16& 0xff;
  792. buf[UDP_LEN_H_P]=tmp16>>8;
  793. //
  794. tmp16=checksum(&buf[IP_SRC_P], 16 + datalen,1);
  795. buf[UDP_CHECKSUM_L_P]=tmp16& 0xff;
  796. buf[UDP_CHECKSUM_H_P]=tmp16>>8;
  797. enc28j60PacketSend(UDP_HEADER_LEN+IP_HEADER_LEN+ETH_HEADER_LEN+datalen,buf);
  798. }
  799. void send_udp(uint8_t *buf,char *data,uint8_t datalen,uint16_t sport, const uint8_t *dip, uint16_t dport,const uint8_t *dstmac)
  800. {
  801. send_udp_prepare(buf,sport, dip, dport,dstmac);
  802. uint8_t i=0;
  803. // limit the length:
  804. if (datalen>220){
  805. datalen=220;
  806. }
  807. // copy the data:
  808. i=0;
  809. while(i<datalen){
  810. buf[UDP_DATA_P+i]=data[i];
  811. i++;
  812. }
  813. //
  814. send_udp_transmit(buf,datalen);
  815. }
  816. #endif // UDP_client
  817. #ifdef WOL_client
  818. // -------------------- special code to make a WOL packet
  819. // A WOL (Wake on Lan) packet is a UDP packet to the broadcast
  820. // address and UDP port 9. The data part contains 6x FF followed by
  821. // 16 times the mac address of the host to wake-up
  822. //
  823. void send_wol(uint8_t *buf,uint8_t *wolmac)
  824. {
  825. uint8_t i=0;
  826. uint8_t m=0;
  827. uint8_t pos=0;
  828. uint16_t ck;
  829. //
  830. while(i<6){
  831. buf[ETH_DST_MAC +i]=0xff;
  832. buf[ETH_SRC_MAC +i]=macaddr[i];
  833. i++;
  834. }
  835. buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  836. buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  837. fill_buf_p(&buf[IP_P],9,iphdr);
  838. buf[IP_ID_L_P]=ipid; ipid++;
  839. buf[IP_TOTLEN_L_P]=0x82; // fixed len
  840. buf[IP_PROTO_P]=IP_PROTO_UDP_V; // wol uses udp
  841. i=0;
  842. while(i<4){
  843. buf[IP_SRC_P+i]=ipaddr[i];
  844. buf[IP_DST_P+i]=0xff;
  845. i++;
  846. }
  847. fill_ip_hdr_checksum(buf);
  848. buf[UDP_DST_PORT_H_P]=0;
  849. buf[UDP_DST_PORT_L_P]=0x9; // wol=normally 9
  850. buf[UDP_SRC_PORT_H_P]=10;
  851. buf[UDP_SRC_PORT_L_P]=0x42; // source port does not matter
  852. buf[UDP_LEN_H_P]=0;
  853. buf[UDP_LEN_L_P]=110; // fixed len
  854. // zero the checksum
  855. buf[UDP_CHECKSUM_H_P]=0;
  856. buf[UDP_CHECKSUM_L_P]=0;
  857. // copy the data (102 bytes):
  858. i=0;
  859. while(i<6){
  860. buf[UDP_DATA_P+i]=0xff;
  861. i++;
  862. }
  863. m=0;
  864. pos=UDP_DATA_P+6;
  865. while (m<16){
  866. i=0;
  867. while(i<6){
  868. buf[pos]=wolmac[i];
  869. i++;
  870. pos++;
  871. }
  872. m++;
  873. }
  874. //
  875. ck=checksum(&buf[IP_SRC_P], 16+ 102,1);
  876. buf[UDP_CHECKSUM_H_P]=ck>>8;
  877. buf[UDP_CHECKSUM_L_P]=ck& 0xff;
  878. enc28j60PacketSend(pos,buf);
  879. }
  880. #endif // WOL_client
  881. #if defined GRATARP
  882. // Send a Gratuitous arp, this is to refresh the arp
  883. // cash of routers and switches. It can improve the response
  884. // time in wifi networks as some wifi equipment expects the initial
  885. // communication to not start from the network side. That is wrong
  886. // but some consumer devices are made like this.
  887. //
  888. // A Gratuitous ARP can be a request or a reply.
  889. // A request frame is as well called Unsolicited ARP
  890. uint8_t gratutious_arp(uint8_t *buf)
  891. {
  892. uint8_t i=0;
  893. if (!enc28j60linkup()){
  894. return(0);
  895. }
  896. //
  897. while(i<6){
  898. buf[ETH_DST_MAC +i]=0xff;
  899. buf[ETH_SRC_MAC +i]=macaddr[i];
  900. i++;
  901. }
  902. buf[ETH_TYPE_H_P] = ETHTYPE_ARP_H_V;
  903. buf[ETH_TYPE_L_P] = ETHTYPE_ARP_L_V;
  904. // arp request and reply are the same execept for
  905. // the opcode:
  906. fill_buf_p(&buf[ETH_ARP_P],8,arpreqhdr);
  907. //buf[ETH_ARP_OPCODE_L_P]=ETH_ARP_OPCODE_REPLY_L_V; // reply
  908. i=0;
  909. while(i<6){
  910. buf[ETH_ARP_SRC_MAC_P +i]=macaddr[i];
  911. buf[ETH_ARP_DST_MAC_P+i]=0xff;
  912. i++;
  913. }
  914. i=0;
  915. while(i<4){
  916. buf[ETH_ARP_DST_IP_P+i]=ipaddr[i];
  917. buf[ETH_ARP_SRC_IP_P+i]=ipaddr[i];
  918. i++;
  919. }
  920. // 0x2a=42=len of packet
  921. enc28j60PacketSend(0x2a,buf);
  922. return(1);
  923. }
  924. #endif // GRATARP
  925. #if ARP_MAC_resolver_client
  926. // make a arp request
  927. // Note: you must have initialized the stack with
  928. // init_udp_or_www_server or client_ifconfig
  929. // before you can use this function
  930. void client_arp_whohas(uint8_t *buf,uint8_t *ip_we_search)
  931. {
  932. uint8_t i=0;
  933. if (ipaddr[0]==0) return; // error ipaddr not set
  934. //
  935. while(i<6){
  936. buf[ETH_DST_MAC +i]=0xff;
  937. buf[ETH_SRC_MAC +i]=macaddr[i];
  938. i++;
  939. }
  940. buf[ETH_TYPE_H_P] = ETHTYPE_ARP_H_V;
  941. buf[ETH_TYPE_L_P] = ETHTYPE_ARP_L_V;
  942. fill_buf_p(&buf[ETH_ARP_P],8,arpreqhdr);
  943. i=0;
  944. while(i<6){
  945. buf[ETH_ARP_SRC_MAC_P +i]=macaddr[i];
  946. buf[ETH_ARP_DST_MAC_P+i]=0;
  947. i++;
  948. }
  949. i=0;
  950. while(i<4){
  951. buf[ETH_ARP_DST_IP_P+i]=*(ip_we_search +i);
  952. buf[ETH_ARP_SRC_IP_P+i]=ipaddr[i];
  953. i++;
  954. }
  955. // 0x2a=42=len of packet
  956. enc28j60PacketSend(0x2a,buf);
  957. }
  958. // return zero when current transaction is finished
  959. uint8_t get_mac_with_arp_wait(void)
  960. {
  961. if (arpip_state == WGW_HAVE_MAC){
  962. return(0);
  963. }
  964. return(1);
  965. }
  966. // reference_number is something that is just returned in the callback
  967. // to make matching and waiting for a given ip/mac address pair easier
  968. // Note: you must have initialized the stack with
  969. // init_udp_or_www_server or client_ifconfig
  970. // before you can use this function
  971. void get_mac_with_arp(uint8_t *ip, uint8_t reference_number,void (*arp_result_callback)(uint8_t *ip,uint8_t reference_number,uint8_t *mac))
  972. {
  973. uint8_t i=0;
  974. client_arp_result_callback=arp_result_callback;
  975. arpip_state=WGW_INITIAL_ARP; // causes an arp request in the packet loop
  976. arp_reference_number=reference_number;
  977. while(i<4){
  978. arpip[i]=ip[i];
  979. i++;
  980. }
  981. }
  982. #endif
  983. #if defined (TCP_client)
  984. // Make a tcp syn packet
  985. void tcp_client_syn(uint8_t *buf,uint8_t srcport,uint16_t dstport)
  986. {
  987. uint16_t ck;
  988. uint8_t i=0;
  989. // -- make the main part of the eth/IP/tcp header:
  990. while(i<6){
  991. buf[ETH_DST_MAC +i]=tcp_dst_mac[i]; // gw mac in local lan or host mac
  992. buf[ETH_SRC_MAC +i]=macaddr[i];
  993. i++;
  994. }
  995. buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  996. buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  997. fill_buf_p(&buf[IP_P],9,iphdr);
  998. buf[IP_TOTLEN_L_P]=44; // good for syn
  999. buf[IP_ID_L_P]=ipid; ipid++;
  1000. buf[IP_PROTO_P]=IP_PROTO_TCP_V;
  1001. i=0;
  1002. while(i<4){
  1003. buf[IP_DST_P+i]=tcp_otherside_ip[i];
  1004. buf[IP_SRC_P+i]=ipaddr[i];
  1005. i++;
  1006. }
  1007. fill_ip_hdr_checksum(buf);
  1008. buf[TCP_DST_PORT_H_P]=(dstport>>8)&0xff;
  1009. buf[TCP_DST_PORT_L_P]=(dstport&0xff);
  1010. buf[TCP_SRC_PORT_H_P]=TCPCLIENT_SRC_PORT_H;
  1011. buf[TCP_SRC_PORT_L_P]=srcport; // lower 8 bit of src port
  1012. i=0;
  1013. // zero out sequence number and acknowledgement number
  1014. while(i<8){
  1015. buf[TCP_SEQ_H_P+i]=0;
  1016. i++;
  1017. }
  1018. // -- header ready
  1019. // put inital seq number
  1020. // we step only the second byte, this allows us to send packts
  1021. // with 255 bytes 512 (if we step the initial seqnum by 2)
  1022. // or 765 (step by 3)
  1023. buf[TCP_SEQ_H_P+2]= seqnum;
  1024. // step the inititial seq num by something we will not use
  1025. // during this tcp session:
  1026. seqnum+=3;
  1027. buf[TCP_HEADER_LEN_P]=0x60; // 0x60=24 len: (0x60>>4) * 4
  1028. buf[TCP_FLAGS_P]=TCP_FLAGS_SYN_V;
  1029. // use a low window size otherwise we have to have
  1030. // timers and can not just react on every packet.
  1031. buf[TCP_WIN_SIZE]=0x3; // 1024=0x400 768=0x300, initial window
  1032. buf[TCP_WIN_SIZE+1]=0x0;
  1033. // zero the checksum
  1034. buf[TCP_CHECKSUM_H_P]=0;
  1035. buf[TCP_CHECKSUM_L_P]=0;
  1036. // urgent pointer
  1037. buf[TCP_CHECKSUM_L_P+1]=0;
  1038. buf[TCP_CHECKSUM_L_P+2]=0;
  1039. // MSS= max IP len that we want to have:
  1040. buf[TCP_OPTIONS_P]=2;
  1041. buf[TCP_OPTIONS_P+1]=4;
  1042. buf[TCP_OPTIONS_P+2]=(CLIENTMSS>>8);
  1043. buf[TCP_OPTIONS_P+3]=CLIENTMSS & 0xff;
  1044. ck=checksum(&buf[IP_SRC_P], 8 +TCP_HEADER_LEN_PLAIN+4,2);
  1045. buf[TCP_CHECKSUM_H_P]=ck>>8;
  1046. buf[TCP_CHECKSUM_L_P]=ck& 0xff;
  1047. // 4 is the tcp mss option:
  1048. enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+ETH_HEADER_LEN+4,buf);
  1049. }
  1050. #endif // TCP_client
  1051. #if defined (TCP_client)
  1052. // This is how to use the tcp client:
  1053. //
  1054. // Declare a callback function to get the result (tcp data from the server):
  1055. //
  1056. // uint8_t your_client_tcp_result_callback(uint8_t fd, uint8_t statuscode,uint16_t data_start_pos_in_buf, uint16_t len_of_data){...your code;return(close_tcp_session);}
  1057. //
  1058. // statuscode=0 means the buffer has valid data, otherwise len and pos_in_buf
  1059. // are invalid. That is: do to use data_start_pos_in_buf and len_of_data
  1060. // if statuscode!=0.
  1061. //
  1062. // This callback gives you access to the TCP data of the first
  1063. // packet returned from the server. You should aim to minimize the server
  1064. // output such that this will be the only packet.
  1065. //
  1066. // close_tcp_session=1 means close the session now. close_tcp_session=0
  1067. // read all data and leave it to the other side to close it.
  1068. // If you connect to a web server then you want close_tcp_session=0.
  1069. // If you connect to a modbus/tcp equipment then you want close_tcp_session=1
  1070. //
  1071. // Declare a callback function to be called in order to fill in the
  1072. //
  1073. // request (tcp data sent to the server):
  1074. // uint16_t your_client_tcp_datafill_callback(uint8_t fd){...your code;return(len_of_data_filled_in);}
  1075. //
  1076. // Now call:
  1077. // fd=client_tcp_req(&your_client_tcp_result_callback,&your_client_tcp_datafill_callback,portnumber);
  1078. //
  1079. // fd is a file descriptor like number that you get back in the fill and result
  1080. // function so you know to which call of client_tcp_req this callback belongs.
  1081. //
  1082. // You can not start different clients (e.g modbus and web) at the
  1083. // same time but you can start them one after each other. That is
  1084. // when the request has timed out or when the result_callback was
  1085. // executed then you can start a new one. The fd makes it still possible to
  1086. // distinguish in the callback code the different types you started.
  1087. //
  1088. // Note that you might never get called back if the other side does
  1089. // not answer. A timer would be needed to recongnize such a condition.
  1090. //
  1091. // We use callback functions because that saves memory and a uC is very
  1092. // limited in memory
  1093. //
  1094. uint8_t client_tcp_req(uint8_t (*result_callback)(uint8_t fd,uint8_t statuscode,uint16_t data_start_pos_in_buf, uint16_t len_of_data),uint16_t (*datafill_callback)(uint8_t fd),uint16_t port,uint8_t *dstip,uint8_t *dstmac)
  1095. {
  1096. uint8_t i=0;
  1097. client_tcp_result_callback=result_callback;
  1098. client_tcp_datafill_callback=datafill_callback;
  1099. while(i<4){tcp_otherside_ip[i]=dstip[i];i++;}
  1100. i=0;
  1101. while(i<6){tcp_dst_mac[i]=dstmac[i];i++;}
  1102. tcp_client_port=port;
  1103. tcp_client_state=1; // send a syn
  1104. tcp_fd++;
  1105. if (tcp_fd>7){
  1106. tcp_fd=0;
  1107. }
  1108. return(tcp_fd);
  1109. }
  1110. #endif // TCP_client
  1111. #if defined (WWW_client)
  1112. uint16_t www_client_internal_datafill_callback(uint8_t fd){
  1113. char strbuf[5];
  1114. uint16_t len=0;
  1115. if (fd==www_fd){
  1116. if (browsertype==0){
  1117. // GET
  1118. len=fill_tcp_data_p(bufptr,0,PSTR("GET "));
  1119. len=fill_tcp_data_p(bufptr,len,client_urlbuf);
  1120. len=fill_tcp_data(bufptr,len,client_urlbuf_var);
  1121. // I would prefer http/1.0 but there is a funny
  1122. // bug in some apache webservers which causes
  1123. // them to send two packets (fragmented PDU)
  1124. // if we don't use HTTP/1.1 + Connection: close
  1125. len=fill_tcp_data_p(bufptr,len,PSTR(" HTTP/1.1\r\nHost: "));
  1126. len=fill_tcp_data(bufptr,len,client_hoststr);
  1127. len=fill_tcp_data_p(bufptr,len,PSTR("\r\nUser-Agent: tgr/1.1\r\nAccept: text/html\r\nConnection: close\r\n\r\n"));
  1128. }else{
  1129. // POST
  1130. len=fill_tcp_data_p(bufptr,0,PSTR("POST "));
  1131. len=fill_tcp_data_p(bufptr,len,client_urlbuf);
  1132. len=fill_tcp_data(bufptr,len,client_urlbuf_var);
  1133. len=fill_tcp_data_p(bufptr,len,PSTR(" HTTP/1.1\r\nHost: "));
  1134. len=fill_tcp_data(bufptr,len,client_hoststr);
  1135. if (client_additionalheaderline){
  1136. len=fill_tcp_data_p(bufptr,len,PSTR("\r\n"));
  1137. len=fill_tcp_data_p(bufptr,len,client_additionalheaderline);
  1138. }
  1139. len=fill_tcp_data_p(bufptr,len,PSTR("\r\nUser-Agent: tgr/1.1\r\nAccept: */*\r\nConnection: close\r\n"));
  1140. len=fill_tcp_data_p(bufptr,len,PSTR("Content-Length: "));
  1141. itoa(strlen(client_postval),strbuf,10);
  1142. len=fill_tcp_data(bufptr,len,strbuf);
  1143. len=fill_tcp_data_p(bufptr,len,PSTR("\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n"));
  1144. len=fill_tcp_data(bufptr,len,client_postval);
  1145. }
  1146. return(len);
  1147. }
  1148. return(0);
  1149. }
  1150. uint8_t www_client_internal_result_callback(uint8_t fd, uint8_t statuscode, uint16_t datapos, uint16_t len_of_data){
  1151. uint16_t web_statuscode=0; // tcp status is OK but we need to check http layer too
  1152. uint8_t i=0;
  1153. if (fd!=www_fd){
  1154. (*client_browser_callback)(500,0,0);
  1155. return(0);
  1156. }
  1157. if (statuscode==0 && len_of_data>12){
  1158. // we might have a http status code
  1159. // http status codes are 3digit numbers as ascii text. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
  1160. // The buffer would look like this: HTTP/1.1 200 OK\r\n
  1161. // web_statuscode=0 means we got a corrupted answer
  1162. if (client_browser_callback){
  1163. if (isblank(bufptr[datapos+8]) && isdigit(bufptr[datapos+9])&& isdigit(bufptr[datapos+11])){ // e.g 200 OK, a status code has 3 digits from datapos+9 to datapos+11, copy over the web/http status code to web_statuscode:
  1164. while(i<2){
  1165. web_statuscode+=bufptr[datapos+9+i]-'0';
  1166. web_statuscode*=10;
  1167. i++;
  1168. }
  1169. web_statuscode+=bufptr[datapos+11]-'0';
  1170. }
  1171. //(*client_browser_callback)(web_statuscode,((uint16_t)TCP_SRC_PORT_H_P+(bufptr[TCP_HEADER_LEN_P]>>4)*4),len_of_data);
  1172. (*client_browser_callback)(web_statuscode,datapos,len_of_data);
  1173. }
  1174. }
  1175. return(0);
  1176. }
  1177. // call this function externally like this:
  1178. //
  1179. // Declare a callback function: void browserresult(uint8_t webstatuscode,uint16_t datapos,uint16_t len){...your code}
  1180. // The variable datapos is the index in the packet buffer.
  1181. // Now call client_browser_url:
  1182. // client_browser_url(PSTR("/cgi-bin/checkip"),NULL,"tuxgraphics.org",&browserresult,other_side_ip,gwmac);
  1183. // urlbuf_varpart is a pointer to a string buffer that contains the second
  1184. // non constant part of the url. You must keep this buffer allocated until the
  1185. // callback function is executed or until you can be sure that the server side
  1186. // has timed out.
  1187. // hoststr is the name of the host. This is needed because many sites host several
  1188. // sites on the same physical machine with only one IP address. The web server needs
  1189. // to know to which site you want to go.
  1190. // webstatuscode is zero if there was no proper reply from the server (garbage message total communication failure, this is rare).
  1191. // webstatuscode is the http status code (e.g webstatuscode=200 for 200 OK);
  1192. // webstatuscode is zero if there was a garbage answer received from the server.
  1193. // For possible status codes look at http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
  1194. // Basically 2xx is success and any 5xx, 4xx is a failure.
  1195. // The string buffers to which urlbuf_varpart and hoststr are pointing
  1196. // must not be changed until the callback is executed.
  1197. //
  1198. void client_browse_url(const prog_char *urlbuf,const char *urlbuf_varpart,const char *hoststr,void (*callback)(uint16_t,uint16_t,uint16_t),uint8_t *dstip,uint8_t *dstmac)
  1199. {
  1200. if (!enc28j60linkup())return;
  1201. client_urlbuf=urlbuf;
  1202. client_urlbuf_var=urlbuf_varpart;
  1203. client_hoststr=hoststr;
  1204. browsertype=0;
  1205. client_browser_callback=callback;
  1206. www_fd=client_tcp_req(&www_client_internal_result_callback,&www_client_internal_datafill_callback,80,dstip,dstmac);
  1207. }
  1208. // client web browser using http POST operation:
  1209. // additionalheaderline must be set to NULL if not used.
  1210. // The string buffers to which urlbuf_varpart and hoststr are pointing
  1211. // must not be changed until the callback is executed.
  1212. // postval is a string buffer which can only be de-allocated by the caller
  1213. // when the post operation was really done (e.g when callback was executed).
  1214. // postval must be urlencoded.
  1215. void client_http_post(const prog_char *urlbuf, const char *urlbuf_varpart,const char *hoststr, const prog_char *additionalheaderline,char *postval,void (*callback)(uint16_t,uint16_t,uint16_t),uint8_t *dstip,uint8_t *dstmac)
  1216. {
  1217. if (!enc28j60linkup())return;
  1218. client_urlbuf=urlbuf;
  1219. client_hoststr=hoststr;
  1220. client_urlbuf_var=urlbuf_varpart;
  1221. client_additionalheaderline=additionalheaderline;
  1222. client_postval=postval;
  1223. browsertype=1;
  1224. client_browser_callback=callback;
  1225. www_fd=client_tcp_req(&www_client_internal_result_callback,&www_client_internal_datafill_callback,80,dstip,dstmac);
  1226. }
  1227. #endif // WWW_client
  1228. void register_ping_rec_callback(void (*callback)(uint8_t *srcip))
  1229. {
  1230. icmp_callback=callback;
  1231. }
  1232. #ifdef PING_client
  1233. // loop over this to check if we get a ping reply:
  1234. uint8_t packetloop_icmp_checkreply(uint8_t *buf,uint8_t *ip_monitoredhost)
  1235. {
  1236. if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREPLY_V){
  1237. if (buf[ICMP_DATA_P]== PINGPATTERN){
  1238. if (check_ip_message_is_from(buf,ip_monitoredhost)){
  1239. return(1);
  1240. // ping reply is from monitored host and ping was from us
  1241. }
  1242. }
  1243. }
  1244. return(0);
  1245. }
  1246. #endif // PING_client
  1247. // return 0 to just continue in the packet loop and return the position
  1248. // of the tcp data if there is tcp data part
  1249. uint16_t packetloop_arp_icmp_tcp(uint8_t *buf,uint16_t plen)
  1250. {
  1251. uint16_t len;
  1252. #if defined (TCP_client)
  1253. uint8_t send_fin=0;
  1254. uint16_t tcpstart;
  1255. uint16_t save_len;
  1256. #endif
  1257. #ifdef ARP_MAC_resolver_client
  1258. //plen will be unequal to zero if there is a valid
  1259. // packet (without crc error):
  1260. if(plen==0){
  1261. if (arpip_state == (WGW_ACCEPT_ARP_REPLY|WGW_INITIAL_ARP) && arp_delaycnt==0 ){
  1262. // arp_delaycnt has wrapped no arp reply yet
  1263. if (enc28j60linkup()) client_arp_whohas(buf,arpip);
  1264. }
  1265. if (arpip_state == WGW_INITIAL_ARP && enc28j60linkup()){
  1266. client_arp_whohas(buf,arpip);
  1267. arpip_state|=WGW_ACCEPT_ARP_REPLY; // WGW_INITIAL_ARP and WGW_ACCEPT_ARP_REPLY set
  1268. arp_delaycnt=0; // this is like a timer, not so precise but good enough, it wraps in about 2 sec
  1269. }
  1270. arp_delaycnt++;
  1271. #if defined (TCP_client)
  1272. if (tcp_client_state==1 && enc28j60linkup()){ // send a syn
  1273. tcp_client_state=2;
  1274. tcpclient_src_port_l++; // allocate a new port
  1275. // we encode our 3 bit fd into the src port this
  1276. // way we get it back in every message that comes
  1277. // from the server:
  1278. tcp_client_syn(buf,((tcp_fd<<5) | (0x1f & tcpclient_src_port_l)),tcp_client_port);
  1279. }
  1280. #endif
  1281. return(0);
  1282. }
  1283. #endif // ARP_MAC_resolver_client
  1284. // arp is broadcast if unknown but a host may also
  1285. // verify the mac address by sending it to
  1286. // a unicast address.
  1287. if(eth_type_is_arp_and_my_ip(buf,plen)){
  1288. if (buf[ETH_ARP_OPCODE_L_P]==ETH_ARP_OPCODE_REQ_L_V){
  1289. // is it an arp request
  1290. make_arp_answer_from_request(buf);
  1291. }
  1292. #ifdef ARP_MAC_resolver_client
  1293. if ((arpip_state & WGW_ACCEPT_ARP_REPLY) && (buf[ETH_ARP_OPCODE_L_P]==ETH_ARP_OPCODE_REPLY_L_V)){
  1294. // is it an arp reply
  1295. if (memcmp(&buf[ETH_ARP_SRC_IP_P],arpip,4)!=0) return(0); // not an arp reply for the IP we were searching
  1296. (*client_arp_result_callback)(arpip,arp_reference_number,buf+ETH_ARP_SRC_MAC_P);
  1297. arpip_state=WGW_HAVE_MAC;
  1298. }
  1299. #endif // ARP_MAC_resolver_client
  1300. return(0);
  1301. }
  1302. // check if ip packets are for us:
  1303. if(eth_type_is_ip_and_my_ip(buf,plen)==0){
  1304. return(0);
  1305. }
  1306. if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V){
  1307. if (icmp_callback){
  1308. (*icmp_callback)(&(buf[IP_SRC_P]));
  1309. }
  1310. // a ping packet, let's send pong
  1311. make_echo_reply_from_request(buf,plen);
  1312. return(0);
  1313. }
  1314. if (plen<54 && buf[IP_PROTO_P]!=IP_PROTO_TCP_V ){
  1315. // smaller than the smallest TCP packet and not tcp port
  1316. return(0);
  1317. }
  1318. #if defined (TCP_client)
  1319. // a message for the tcp client, tcp_client_state is zero if client was never used
  1320. if ( buf[TCP_DST_PORT_H_P]==TCPCLIENT_SRC_PORT_H){
  1321. #if defined (WWW_client)
  1322. // workaround to pass pointer to www_client_internal..
  1323. bufptr=buf;
  1324. #endif // WWW_client
  1325. if (check_ip_message_is_from(buf,tcp_otherside_ip)==0){
  1326. return(0);
  1327. }
  1328. // if we get a reset:
  1329. if (buf[TCP_FLAGS_P] & TCP_FLAGS_RST_V){
  1330. if (client_tcp_result_callback){
  1331. // parameters in client_tcp_result_callback: fd, status, buf_start, len
  1332. (*client_tcp_result_callback)((buf[TCP_DST_PORT_L_P]>>5)&0x7,3,0,0);
  1333. }
  1334. tcp_client_state=5;
  1335. return(0);
  1336. }
  1337. len=get_tcp_data_len(buf);
  1338. if (tcp_client_state==2){
  1339. if ((buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V) && (buf[TCP_FLAGS_P] &TCP_FLAGS_ACK_V)){
  1340. // synack, answer with ack
  1341. make_tcp_ack_from_any(buf,0,0);
  1342. buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V|TCP_FLAGS_PUSH_V;
  1343. // Make a tcp message with data. When calling this function we must
  1344. // still have a valid tcp-ack in the buffer. In other words
  1345. // you have just called make_tcp_ack_from_any(buf,0).
  1346. if (client_tcp_datafill_callback){
  1347. // in this case it is src port because the above
  1348. // make_tcp_ack_from_any swaps the dst and src port:
  1349. len=(*client_tcp_datafill_callback)((buf[TCP_SRC_PORT_L_P]>>5)&0x7);
  1350. }else{
  1351. // this is just to prevent a crash
  1352. len=0;
  1353. }
  1354. tcp_client_state=3;
  1355. make_tcp_ack_with_data_noflags(buf,len);
  1356. return(0);
  1357. }else{
  1358. // reset only if we have sent a syn and don't get syn-ack back.
  1359. // If we connect to a non listen port then we get a RST
  1360. // which will be handeled above. In other words there is
  1361. // normally no danger for an endless loop.
  1362. tcp_client_state=1; // retry
  1363. // do not inform application layer as we retry.
  1364. len++;
  1365. if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V){
  1366. // if packet was an ack then do not step the ack number
  1367. len=0;
  1368. }
  1369. // refuse and reset the connection
  1370. make_tcp_ack_from_any(buf,len,TCP_FLAGS_RST_V);
  1371. return(0);
  1372. }
  1373. }
  1374. // in tcp_client_state==3 we will normally first get an empty
  1375. // ack-packet and then a ack-packet with data.
  1376. if (tcp_client_state==3 && len>0){
  1377. // our first real data packet
  1378. tcp_client_state=4;
  1379. // return the data we received
  1380. if (client_tcp_result_callback){
  1381. tcpstart=TCP_DATA_START; // TCP_DATA_START is a formula
  1382. // out of buffer bounds check, needed in case of fragmented IP packets
  1383. if (tcpstart>plen-8){
  1384. tcpstart=plen-8; // dummy but save
  1385. }
  1386. save_len=len;
  1387. if (tcpstart+len>plen){
  1388. save_len=plen-tcpstart;
  1389. }
  1390. send_fin=(*client_tcp_result_callback)((buf[TCP_DST_PORT_L_P]>>5)&0x7,0,tcpstart,save_len);
  1391. }
  1392. if (send_fin){
  1393. make_tcp_ack_from_any(buf,len,TCP_FLAGS_PUSH_V|TCP_FLAGS_FIN_V);
  1394. tcp_client_state=5;
  1395. return(0);
  1396. }
  1397. }
  1398. if(tcp_client_state==5){
  1399. // no more ack
  1400. return(0);
  1401. }
  1402. if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V){
  1403. make_tcp_ack_from_any(buf,len+1,TCP_FLAGS_PUSH_V|TCP_FLAGS_FIN_V);
  1404. tcp_client_state=5; // connection terminated
  1405. return(0);
  1406. }
  1407. // ack all data (the web page may be long):
  1408. // if we just get a fragment then len will be zero
  1409. // and we ack only once we have the full packet
  1410. if (len>0){
  1411. make_tcp_ack_from_any(buf,len,0);
  1412. }
  1413. return(0);
  1414. }
  1415. #endif // TCP_client
  1416. //
  1417. #ifdef WWW_server
  1418. // tcp port web server start
  1419. if (buf[IP_PROTO_P]==IP_PROTO_TCP_V && buf[TCP_DST_PORT_H_P]==wwwport_h && buf[TCP_DST_PORT_L_P]==wwwport_l){
  1420. if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V){
  1421. make_tcp_synack_from_syn(buf);
  1422. // make_tcp_synack_from_syn does already send the syn,ack
  1423. return(0);
  1424. }
  1425. if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V){
  1426. info_data_len=get_tcp_data_len(buf);
  1427. // we can possibly have no data, just ack:
  1428. // Here we misuse plen for something else to save a variable.
  1429. // plen is now the position of start of the tcp user data.
  1430. if (info_data_len==0){
  1431. if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V){
  1432. // finack, answer with ack
  1433. make_tcp_ack_from_any(buf,0,0);
  1434. }
  1435. // just an ack with no data, wait for next packet
  1436. return(0);
  1437. }
  1438. // Here we misuse len for something else to save a variable
  1439. len=TCP_DATA_START; // TCP_DATA_START is a formula
  1440. // check for data corruption
  1441. if (len>plen-8){
  1442. return(0);
  1443. }
  1444. return(len);
  1445. }
  1446. }
  1447. #endif // WWW_server
  1448. return(0);
  1449. }
  1450. /* end of ip_arp_udp.c */