WIZnet PPPoE application library
How to use??
1. Set MAC address, IP address, Subnet mask, gateway address.
2. Run ppp_start function.
End~
Revision 0:7a9cde4dbf0b, committed 2014-10-29
- Comitter:
- hjjeon
- Date:
- Wed Oct 29 06:17:02 2014 +0000
- Commit message:
- WIZnet PPPoE application library
Changed in this revision
diff -r 000000000000 -r 7a9cde4dbf0b PPPoE.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PPPoE.cpp Wed Oct 29 06:17:02 2014 +0000 @@ -0,0 +1,1658 @@ +#include <stdint.h> +#include "PPPoE.h" + + +// ID and Password for PAP from main.c +extern uint8_t pppoe_id[];//={}; +extern uint8_t pppoe_id_len; +extern uint8_t pppoe_ip[];//={}; +extern uint8_t pppoe_pdns[];//={}; +extern uint8_t pppoe_sdns[];//={}; +extern uint8_t pppoe_pw[];//={}; +extern uint8_t pppoe_pw_len; + + +//IPCP Reject flag +uint8_t ip_rjt; +uint8_t pdns_rjt; +uint8_t sdns_rjt; + + +// PPPoE Frame structure for send +PPPMSG PPPMSG_req; // PPPoE frame +PROTOCOL PPPPROTO; // Tag and Protocol data + +// TxRx Buffers pointer from main +uint8_t* buf; + +// Server MAC and Assigned Session ID and IP address from NAS using PPPoE +uint8_t NAS_mac[6]; +uint16_t NAS_sessionid = 0; + +// kind of authentication protocol and algorithm; decided by LCP phase +// Authentication protocol : PAP - 0xC023, CHAP - 0xC223 +// Algorithm : MD5 - 0x05, MS-CHAP - 0x80, MS-CHAP-V2 - 0x81 +uint16_t auth_protocol; +uint8_t chap_algorithm; + +// For MD5 calculation +MD5_CTX context; +uint8_t digest[16]; + +// Identifier for PPPoE Protocols (increase per message sending) +uint8_t protocol_id = 0x01; + + + +uint16_t pppoe_state = PPPoE_DISCOVERY; +// PPPoE stage control flags +uint16_t pppoe_control_flag = 0; + +//PPPoE retry count and send retry count +uint8_t pppoe_retry_send_count = 0; +extern uint16_t pppoe_retry_count; +uint8_t pppoe_recv_count = 0; + + +// Tmp variable +uint16_t tmp_protocol; +uint8_t tmp_pcode; + +PPPOEClient::PPPOEClient() +{ + eth = WIZnet_Chip::getInstance(); +} + + +void PPPOEClient::set_pppinfo(uint8_t * nas_mac, uint8_t * ppp_ip, uint16_t nas_sessionid) +{ + +#ifdef __DEF_PPP_DBG1__ + uint8_t str[8];//debug var + uint16_t psid; + + printf("set_pppinfo() Start...\r\n"); +#endif + /* Set PPPoE bit in MR(Common Mode Register) : enable PPPoE */ + eth->setMR(eth->getMR() | MR_PPPOE); + + // Write PPPoE server's MAC address, Session ID and IP address. + // must be setted these value. +#ifdef __DEF_PPP_DBG1__ + printf("Server's MAC : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\r\n", nas_mac[0], nas_mac[1], nas_mac[2], nas_mac[3], nas_mac[4], nas_mac[5]); + printf("PPPoE IP : %.3d.%.3d.%.3d.%.3d\r\n", ppp_ip[0], ppp_ip[1], ppp_ip[2], ppp_ip[3]); + printf("Session ID : 0x%.2x%.2x\r\n", (uint8_t)(nas_sessionid >> 8), (uint8_t)nas_sessionid); +#endif + + eth->setPHAR(nas_mac); + eth->setSIPR(ppp_ip); + eth->setPSID(nas_sessionid); + +#ifdef __DEF_PPP_DBG1__ + eth->getPHAR(str); + printf( "Read PHAR register : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\r\n", str[0], str[1], str[2], str[3], str[4], str[5]); + eth->getSIPR(str); + printf( "Read SIP register : %.3d.%.3d.%.3d.%.3d\r\n", str[0], str[1], str[2], str[3]); + psid = eth->getPSID(); + printf("Read PSID register : %x\r\n", psid); +#endif + + //open socket in pppoe mode + eth->setPTIMER(0); + + +#ifdef __DEF_PPP_DBG1__ + printf("set_pppinfo() End...\r\n"); +#endif +#ifdef __DEF_PPP_DBG1__ + printf("pppoe PDNS : %.3d.%.3d.%.3d.%.3d\r\n", pppoe_pdns[0], pppoe_pdns[1], pppoe_pdns[2], pppoe_pdns[3]); + printf("pppoe SDNS : %.3d.%.3d.%.3d.%.3d\r\n", pppoe_sdns[0], pppoe_sdns[1], pppoe_sdns[2], pppoe_sdns[3]); +#endif + +} + + +void PPPOEClient::ppp_send(void) +{ + uint8_t *ptr; + uint8_t sn = 0; + uint16_t tmp16 = 0; + uint16_t txbuf_len = 0; + + txbuf_len = sizeof(PPPMSG_req); + + + + if(pppoe_state == PPPoE_DISCOVERY) + ptr = (uint8_t *)&PPPPROTO.opt; + else + ptr = (uint8_t *)&PPPPROTO; + + + // Fill the Tx buffer + //memcpy(txbuf, (uint8_t *)&PPPMSG_req, txbuf_len); + memcpy(buf, (uint8_t *)&PPPMSG_req, txbuf_len); + //change MSB and LSB because of different endian. + tmp16 = 0; + tmp16 = (PPPMSG_req.len & 0xFF) << 8; + tmp16 |= ((PPPMSG_req.len >> 8) & 0xFF); + + //memcpy(txbuf + txbuf_len, ptr, tmp16); + memcpy(buf + txbuf_len, ptr, tmp16); + txbuf_len += tmp16; + +#ifdef __DEF_PPP_DBG2__ + printf("Send data : "); + for(i=0; i<txbuf_len; i++) + { + if((i % 16) == 0) printf("\r\n"); + printf("%.2x ", buf[i]); + } + printf("\r\n\r\n"); +#endif + // Send MACRAW data + eth->send(sn, (char*)buf, txbuf_len); + //setSn_CR(sn, Sn_CR_SEND); + eth->setSn_CR(sn, Sn_CR_SEND); + while( eth->getSn_CR(sn) ) ; +} + + +void PPPOEClient::ppp_recv( uint16_t received_len ) +{ + + uint16_t i; + uint8_t sn = 0; + uint8_t head[2] ={0,}; + + uint16_t ethertype = 0; + uint8_t pppoecode = 0; + uint16_t taglen = 0; + uint16_t tagname; + + uint8_t get_protocol_id = 0; + uint16_t t_idx = 0, acknak_idx = 0, rjt_idx = 0; + uint16_t ppp_tag_len = 0, getlen = 0, opt_len = 0; + uint8_t acknak_opt[OPTMSG_LEN]; + uint8_t rjt_opt[OPTMSG_LEN]; + uint8_t opt_code; + uint8_t ppp_code; + + uint8_t str[OPTMSG_LEN]; + uint16_t str_len = 0; + uint8_t tmp8 = 0; + uint8_t mac[6]; + + //reset servicename flag + pppoe_control_flag = pppoe_control_flag & ~FLAG_PADO_SERVICENAME; + + + //getSHAR(mac); + eth->getSHAR(mac); + + // MACRAW Receive + //receive header(packet length) of macraw packet + + eth->recv(sn, (char*) head, 2); + + eth->setSn_CR(sn,Sn_CR_RECV); + + while( eth->getSn_CR(sn) ) ; + + received_len = 0; + received_len = head[0] << 8; + received_len = received_len | head[1]; + received_len = received_len - 2; + + + eth->recv(sn, (char*) buf, received_len); + + eth->setSn_CR(sn,Sn_CR_RECV); + + while( eth->getSn_CR(sn) ) ; + + + // Check the MAC in received packet + tmp8 = buf[0] - mac[0] + buf[1] - mac[1] + buf[2] - mac[2] + buf[3] - mac[3] + buf[4] - mac[4] + buf[5] - mac[5]; + + if(tmp8==0) + { +#ifdef __DEF_PPP_DBG2__ + printf("Received packet :"); + for(i = 0; i < received_len; i++) + { + if((i % 16) == 0) printf("\r\n"); + printf("%.2x ", buf[i]); + } + printf("\r\n"); +#endif + ethertype = buf[12]; + ethertype = (ethertype << 8) + buf[13]; + + pppoecode = buf[15]; + + taglen = buf[18]; + taglen = (taglen << 8) + buf[19]; + ppp_code = buf[22]; + + //Check the Ether-Type and Code in received packet + t_idx = 20; + switch (ethertype) + { + case PPPoE_DISCOVERY : + if (pppoecode == PPPoE_PADO) + { +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Discovery: PADO received\r\n\r\n"); +#endif + for(i = 0; i < 6; i++) NAS_mac[i] = buf[6+i]; + // PPPoE Frame + while(taglen) + { + tagname = buf[t_idx]; + tagname = (tagname << 8) + buf[t_idx+1]; + + ppp_tag_len = buf[t_idx+2]; + ppp_tag_len = (ppp_tag_len << 8) + buf[t_idx+3]; + + // Check option field overflow + // (OPTMSG_LEN defined maximum option field length.) + if((acknak_idx + (ppp_tag_len+4)) > OPTMSG_LEN) + { +#ifdef __DEF_PPP_DBG__ + printf("PPPoE Protocol option field overflow occuerd!\r\n"); +#endif + break; + } + else + { + switch(tagname) + { + case PPPoED_SERVICE_NAME : + if ((pppoe_control_flag & FLAG_PADO_SERVICENAME) == 0) + { + memcpy(&acknak_opt[acknak_idx], &buf[t_idx], ppp_tag_len+4); + acknak_idx += (ppp_tag_len+4); + pppoe_control_flag = pppoe_control_flag | FLAG_PADO_SERVICENAME; + } + break; + case PPPoED_HOST_UNIQ : + case PPPoED_AC_COOKIE : + memcpy(&acknak_opt[acknak_idx], &buf[t_idx], ppp_tag_len+4); + acknak_idx += (ppp_tag_len+4); + break; + default : + //case PPPoED_AC_NAME : + break; + } + } + t_idx += (ppp_tag_len+4); + taglen -= (ppp_tag_len+4); + } + + memcpy(&PPPPROTO.opt[0], &acknak_opt[0], acknak_idx); + + for(i = 0; i < 6; i++) + { + PPPMSG_req.dst_mac[i] = NAS_mac[i]; // NAS MAC address + } + PPPMSG_req.frame_code = PPPoE_PADR; + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = (acknak_idx & 0xFF) << 8; + PPPMSG_req.len |= ((acknak_idx >> 8) & 0xFF); + +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Discovery : PADR send\r\n"); +#endif + ppp_send(); + pppoe_control_flag = pppoe_control_flag | FLAG_DISCOVERY_RCV_PADO; + + + } + else if(pppoecode == PPPoE_PADS) + { +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Discovery: PADS received\r\n\r\n"); +#endif + pppoe_control_flag = pppoe_control_flag | FLAG_DISCOVERY_RCV_PADS; + + NAS_sessionid = buf[16]; + NAS_sessionid = (NAS_sessionid << 8) + buf[17]; + } +#ifdef __DEF_PPP_DBG1__ + else printf("Not necessary packet received\r\n"); +#endif + break; + case PPPoE_SESSION : + + // Process LCP + if ((buf[20] == 0xc0) && (buf[21] == 0x21)) + { + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_LCP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_LCP >> 8) & 0xFF); + + switch (ppp_code) + { + // when lcp_cr_rcv flag set && lcp_cr_sent flag set, goto PAP or CHAP + case PPP_CONFIG_REQ : //Configuration Request receive, and then ack or reject send + // when ack sent, lcp_cr_rcv flag set +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Session LCP: Configure-Request received\r\n\r\n"); +#endif + get_protocol_id = buf[23]; + getlen = buf[24]; + getlen = (getlen<<8) + buf[25]; + + getlen -= 4; + t_idx = 26; + while (getlen) + { + opt_code = buf[t_idx]; + opt_len = buf[t_idx+1]; + // Check option field overflow + // (OPTMSG_LEN defined maximum option field length.) + if((acknak_idx + opt_len) > OPTMSG_LEN || (rjt_idx + opt_len) > OPTMSG_LEN) + { +#ifdef __DEF_PPP_DBG__ + printf("PPPoE Protocol option field overflow occuerd!\r\n"); +#endif + break; + } + else + { + switch (opt_code) + { + case LCP_AUTH : // Authentication-Protocol + auth_protocol = buf[t_idx+2]; + auth_protocol = (auth_protocol << 8) + buf[t_idx+3]; + chap_algorithm = buf[t_idx+4]; + memcpy(&acknak_opt[acknak_idx], &buf[t_idx], opt_len); + acknak_idx += opt_len; + break; + case LCP_MRU : // MRU (Maximum-Receive-Unit) + memcpy(&acknak_opt[acknak_idx], &buf[t_idx], opt_len); + acknak_idx += opt_len; + break; + case LCP_MAGICNUM : // Magic-Number + // opt_code : 0x01, 0x03, 0x05 shared process part + memcpy(&acknak_opt[acknak_idx], &buf[t_idx], opt_len); + acknak_idx += opt_len; + + break; + default : + memcpy(&rjt_opt[rjt_idx], &buf[t_idx], opt_len); + rjt_idx += opt_len; + break; + } + } + t_idx += opt_len; + getlen -= opt_len; + } + + + + if (rjt_idx) + { + // reject send, then wait cr + PPPPROTO.pcode = PPP_CONFIG_REJ; // Reject + memcpy(&PPPPROTO.opt[0], &rjt_opt[0], rjt_idx); + PPPPROTO.id = get_protocol_id; + + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = ((rjt_idx+4) & 0xFF) << 8; + PPPPROTO.len |= (((rjt_idx+4) >> 8) & 0xFF); + + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = ((rjt_idx+6) & 0xFF) << 8; + PPPMSG_req.len |= (((rjt_idx+6) >> 8) & 0xFF); + + ppp_send(); + } + else + { + // ack send, lcp_cr_rcv flag set + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_LCP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_LCP >> 8) & 0xFF); + + PPPPROTO.pcode = PPP_CONFIG_ACK; // ack + memcpy(&PPPPROTO.opt[0], &acknak_opt[0], acknak_idx); + PPPPROTO.id = get_protocol_id; + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = ((acknak_idx+4) & 0xFF) << 8; + PPPPROTO.len |= (((acknak_idx+4) >> 8) & 0xFF); + + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = ((acknak_idx+6) & 0xFF) << 8; + PPPMSG_req.len |= (((acknak_idx+6) >> 8) & 0xFF); +#ifdef __DEF_PPP_DBG1__ + printf("LCP Configuration Ack send\r\n"); +#endif + ppp_send();//ack send + pppoe_control_flag = pppoe_control_flag | FLAG_LCP_CR_RCV; + + } + break; + + + case PPP_CONFIG_ACK : //ack, then lcp_cr_sent flag set +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Session LCP: Configuration Ack received\r\n\r\n"); +#endif + pppoe_control_flag = pppoe_control_flag | FLAG_LCP_CR_SNT; + break; + + + case PPP_TERM_ACK : +#ifdef __DEF_PPP_DBG1__ + printf("Termination Ack received\r\n\r\n"); +#endif + pppoe_control_flag = pppoe_control_flag | FLAG_TERMINATION_ACK_RCV; + + break; + + + case PPP_TERM_REQ: +#ifdef __DEF_PPP_DBG1__ + printf("Termination request received\r\n\r\n"); +#endif + + //change MSB and LSB because of different endian. + PPPMSG_req.ether_type = 0; + PPPMSG_req.ether_type = (PPPoE_SESSION & 0xFF) << 8; + PPPMSG_req.ether_type |= ((PPPoE_SESSION >> 8) & 0xFF);// session + + PPPMSG_req.frame_code = 0x00; // session data + //change MSB and LSB because of different endian. + PPPMSG_req.session_id = 0; + PPPMSG_req.session_id = (NAS_sessionid & 0xFF) << 8; + PPPMSG_req.session_id |= ((NAS_sessionid >> 8) & 0xFF); + + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_LCP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_LCP >> 8) & 0xFF); + + PPPPROTO.pcode = PPP_TERM_ACK; // Terminate-ack + + PPPPROTO.opt[0] = 0x00; // Magic number + PPPPROTO.opt[1] = 0x01; + PPPPROTO.opt[2] = 0x02; + PPPPROTO.opt[3] = 0x03; + + PPPPROTO.id = protocol_id++; + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = (8 & 0xFF) << 8; + PPPPROTO.len |= ((8 >> 8) & 0xFF); + + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = (10 & 0xFF) << 8; + PPPMSG_req.len |= ((10 >> 8) & 0xFF); + + pppoe_control_flag = pppoe_control_flag | FLAG_TERMINATION_REQ_RCV; + +#ifdef __DEF_PPP_DBG1__ + printf("Termination ack send\r\n"); +#endif + ppp_send(); + + break; + + +/* +* Notice : This part is not implemented. +* If necessary, please implement more for reply for request from NAS. +* + case 0x04 : //reject + break; + + case 0x09 : // Echo-Response + // Backup + tmp_protocol = PPPPROTO.protocol; + tmp_pcode = PPPPROTO.pcode; + + PPPPROTO.protocol = PPPoE_LCP; + PPPPROTO.pcode = PPP_ECHO_REP; + + PPPPROTO.id = buf[23]; + + PPPPROTO.len = buf[24]; + PPPPROTO.len = (PPPPROTO.len << 8) + buf[25]; + + memcpy(&PPPPROTO.opt[0], &buf[26], PPPPROTO.len-4); + ppp_send(); + + // Recover + PPPPROTO.protocol = tmp_protocol; + PPPPROTO.pcode = tmp_pcode; + break; +*/ + + default: +#ifdef __DEF_PPP_DBG1__ + printf("Not necessary packet received\r\n"); +#endif + break; + } + } + // Process PAP + else if ((buf[20] == 0xc0) && (buf[21] == 0x23)) + { + if(ppp_code == PPP_CONFIG_ACK) // PPP_CONFIG_ACK = 0x02 + { + pppoe_control_flag = pppoe_control_flag | FLAG_PAP_ACK_RCV;// receice ack + +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Session PAP: Authentication ACK received\r\n\r\n"); +#endif + } + else if(ppp_code == PPP_TERM_ACK) + { +#ifdef __DEF_PPP_DBG1__ + printf("Termination Ack received\r\n\r\n"); +#endif + pppoe_control_flag = pppoe_control_flag | FLAG_TERMINATION_ACK_RCV; + } + } + // Process CHAP + + else if ((buf[20] == 0xc2) && (buf[21] == 0x23)) + { + switch(chap_algorithm) + { + case MD5 : // 0x05, MD5 + + get_protocol_id = buf[23]; + // length of [code ~ packet end] + getlen = buf[24]; + getlen = (getlen<<8) + buf[25]; + // so, 'CHAP data' length is getlen - length of [code(1), ID(1), Length(2)]. + getlen -= 4; //PPP CHAP total(getlen) - 4(header) = data length(value size(1) + value + name ) + t_idx = 26; + + switch(ppp_code) + { + case 0x01 : +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Session CHAP: CHAP Challenge received\r\n\r\n"); +#endif + // Challenge, parse the packet and return 'Response' to NAS + //-- MD5 calc input consist of ID(1), password(pwlen) and Challenge value(16). + + //-- buf[t_idx] => CV(challenge value) size, buf[t_idx+1] => start byte of CV + + memcpy(&str[str_len], &get_protocol_id, 1); // ID(value) + str_len += 1; + memcpy(&str[str_len], &pppoe_pw[0], pppoe_pw_len); // user password + str_len += pppoe_pw_len; + memcpy(&str[str_len], &buf[t_idx+1], buf[t_idx]); // CV(value) + str_len += buf[t_idx]; + + /* + memcpy(&str[str_len], &buf[t_idx+1], buf[t_idx]); // CV(value) + str_len += buf[t_idx]; + memcpy(&str[str_len], &pppoe_pw, pppoe_pw_len); // user password + str_len += pppoe_pw_len; + memcpy(&str[str_len], &pppoe_id, pppoe_id_len); // user id + str_len += pppoe_id_len; + */ + + /* + MD5Init(&context); + MD5Update(&context, str, str_len); + MD5Final(digest, &context); + */ + + + MD5Init(&context); + MD5Update(&context, &get_protocol_id, 1); + MD5Update(&context, pppoe_pw, pppoe_pw_len); + MD5Update(&context, (unsigned char *)(&buf[t_idx+1]), 16); + MD5Final(digest, &context); + + // making response msg + acknak_opt[acknak_idx++] = CV_HV_LEN; // fixed value, 16 + memcpy(&acknak_opt[acknak_idx], &digest, CV_HV_LEN); + acknak_idx += CV_HV_LEN; + + + memcpy(&acknak_opt[acknak_idx], &pppoe_id, pppoe_id_len); // Name: User ID + acknak_idx += pppoe_id_len; + + + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_CHAP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_CHAP >> 8) & 0xFF); + + PPPPROTO.pcode = 0x02; // response + PPPPROTO.id = get_protocol_id; + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = ((acknak_idx + 4) & 0xFF) << 8; + PPPPROTO.len |= (((acknak_idx + 4) >> 8) & 0xFF); + + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = ((acknak_idx + 6) & 0xFF) << 8; + PPPMSG_req.len |= (((acknak_idx + 6) >> 8) & 0xFF); + + + memcpy(&PPPPROTO.opt[0], &acknak_opt[0], acknak_idx); +#ifdef __DEF_PPP_DBG1__ + printf("CHAP response MSG send \r\n\r\n"); +#endif + ppp_send(); + break; + + + case 0x03 : // PPP_SUCCESS +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Session CHAP: CHAP Succeed packet received\r\n\r\n"); +#endif + pppoe_control_flag = pppoe_control_flag | FLAG_CHAP_SUC_RCV; + + break; + + + case 0x04 : // PPP_FAIL +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Session CHAP: CHAP failure packet received\r\n\r\n"); +#endif + + break; + + default : + break; + } + break; +#ifdef __DEF_PPP_DBG1__ + case MS_CHAP : // 0x80, MS-CHAP + case MS_CHAP_V2 : // 0x81, MS-CHAP-V2 + printf("This CHAP Algorithm is not supported : "); + if(chap_algorithm == MS_CHAP) printf("MS-CHAP\r\n"); + else printf("MS-CHAP-V2\r\n"); + break; +#endif + default : + break; + } + } + // Process IPCP + else if ((buf[20] == 0x80) && (buf[21] == 0x21)) + { + switch(ppp_code) + { + case PPP_CONFIG_REQ : // cr, send ack + case PPP_CONFIG_NAK : // nak, save ip addr and send config requset + +#ifdef __DEF_PPP_DBG1__ + if(ppp_code == 0x01) printf("PPPoE Session IPCP: Configure-Request received\r\n\r\n"); + else if (ppp_code == 0x03) printf("PPPoE Session IPCP: Configure-Nak received\r\n\r\n"); +#endif + get_protocol_id = buf[23]; + getlen = buf[24]; + getlen = (getlen<<8) + buf[25]; + + getlen -= 4; + t_idx = 26; + + while (getlen) + { + opt_code = buf[t_idx]; + opt_len = buf[t_idx+1]; + + // Check option field overflow + // (OPTMSG_LEN defined maximum option field length.) + if((acknak_idx + opt_len) > OPTMSG_LEN || (rjt_idx + opt_len) > OPTMSG_LEN) + { +#ifdef __DEF_PPP_DBG__ + printf("PPPoE Protocol option field overflow occuerd!\r\n"); +#endif + break; + } + else + { + switch (opt_code) + { + //case 0x02 : // type : ip compression protocol + case 0x03 : // type : ip address + memcpy(&acknak_opt[acknak_idx], &buf[t_idx], opt_len); + memcpy(&pppoe_ip, &buf[t_idx+2], opt_len-2); + + acknak_idx += opt_len; + break; + case 0x81 : //PDNS + memcpy(&acknak_opt[acknak_idx], &buf[t_idx], opt_len); + memcpy(&pppoe_pdns, &buf[t_idx+2], opt_len-2); + + acknak_idx += opt_len; + break; + case 0x83 : //SDNS + memcpy(&acknak_opt[acknak_idx], &buf[t_idx], opt_len); + memcpy(&pppoe_sdns, &buf[t_idx+2], opt_len-2); + + acknak_idx += opt_len; + break; + default : // reject + memcpy(&rjt_opt[rjt_idx], &buf[t_idx], opt_len); + rjt_idx += opt_len; + break; + } + } + t_idx += opt_len; + getlen -= opt_len; + } + + + + if (rjt_idx)//if reject + { +#ifdef __DEF_PPP_DBG1__ + printf("reject send!\r\n"); +#endif + // reject send, then wait cr + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_IPCP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_IPCP >> 8) & 0xFF); + + PPPPROTO.pcode = 0x04; // Reject + + memcpy(&PPPPROTO.opt[0], &rjt_opt[0], rjt_idx); + + PPPPROTO.id = get_protocol_id; + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = ((rjt_idx+4) & 0xFF) << 8; + PPPPROTO.len |= (((rjt_idx+4) >> 8) & 0xFF); + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = ((rjt_idx+6) & 0xFF) << 8; + PPPMSG_req.len |= (((rjt_idx+6) >> 8) & 0xFF); + + ppp_send(); + } + else // if not reject + { + // ack send, lcp_cr_rcv flag set + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_IPCP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_IPCP >> 8) & 0xFF); + + if(ppp_code == PPP_CONFIG_REQ) + { + PPPPROTO.pcode = 0x02; // if configuration request MSG received, send ack +#ifdef __DEF_PPP_DBG1__ + printf("IPCP configuration ack send!\r\n"); +#endif + } + else + { + PPPPROTO.pcode = 0x01; // if nak received, send cr +#ifdef __DEF_PPP_DBG1__ + printf("IPCP Configuration Request send!\r\n"); +#endif + } + + memcpy(&PPPPROTO.opt[0], &acknak_opt[0], acknak_idx); + + PPPPROTO.id = get_protocol_id; + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = ((acknak_idx+4) & 0xFF) << 8; + PPPPROTO.len |= (((acknak_idx+4) >> 8) & 0xFF); + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = ((acknak_idx+6) & 0xFF) << 8; + PPPMSG_req.len |= (((acknak_idx+6) >> 8) & 0xFF); + + ppp_send(); + if(ppp_code == 0x01) pppoe_control_flag = pppoe_control_flag | FLAG_IPCP_CR_RCV; + else pppoe_control_flag = pppoe_control_flag | FLAG_IPCP_NAK_RCV; + } + break; + + + case PPP_CONFIG_REJ : // Reject receive. +#ifdef __DEF_PPP_DBG1__ + printf("IPCP reject message received!!\r\n"); +#endif + + get_protocol_id = buf[23]; + getlen = buf[24]; + getlen = (getlen<<8) + buf[25]; + + getlen -= 4; + t_idx = 26; + + ip_rjt = 0; + pdns_rjt =0; + sdns_rjt = 0; + + while (getlen) + { + opt_code = buf[t_idx]; + opt_len = buf[t_idx+1]; + + switch (opt_code) + { + //case 0x02 : // type : ip compression protocol + case 0x03 : // ip address + ip_rjt = 1; + break; + case 0x81 : // PDNS + pdns_rjt = 1; + break; + case 0x83 : // SDNS + sdns_rjt = 1; + break; + default : + break; + } + t_idx += opt_len; + getlen -= opt_len; + } + + // Configuration send without reject protocol. + + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_IPCP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_IPCP >> 8) & 0xFF); + + PPPPROTO.pcode = PPP_CONFIG_REQ ; + t_idx = 0; + if( ip_rjt == 0 ) + { + PPPPROTO.opt[t_idx++] = 0x03; // option code, IP address + PPPPROTO.opt[t_idx++] = 0x06; // option len + PPPPROTO.opt[t_idx++] = 0x00; + PPPPROTO.opt[t_idx++] = 0x00; + PPPPROTO.opt[t_idx++] = 0x00; + PPPPROTO.opt[t_idx++] = 0x00; + } + + if( pdns_rjt == 0 ) + { + PPPPROTO.opt[t_idx++] = 0x81; // option code, PDNS address + PPPPROTO.opt[t_idx++] = 0x06; // option len + PPPPROTO.opt[t_idx++] = 0x00; + PPPPROTO.opt[t_idx++] = 0x00; + PPPPROTO.opt[t_idx++] = 0x00; + PPPPROTO.opt[t_idx++] = 0x00; + } + + if( sdns_rjt == 0 ) + { + PPPPROTO.opt[t_idx++] = 0x83; // option code, SDNS address + PPPPROTO.opt[t_idx++] = 0x06; // option len + PPPPROTO.opt[t_idx++] = 0x00; + PPPPROTO.opt[t_idx++] = 0x00; + PPPPROTO.opt[t_idx++] = 0x00; + PPPPROTO.opt[t_idx++] = 0x00; + } + + PPPPROTO.id = get_protocol_id; + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = ((t_idx+4) & 0xFF) << 8; + PPPPROTO.len |= (((t_idx+4) >> 8) & 0xFF); + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = ((t_idx+6) & 0xFF) << 8; + PPPMSG_req.len |= (((t_idx+6) >> 8) & 0xFF); + + if( ip_rjt && pdns_rjt && sdns_rjt) + { +#ifdef __DEF_PPP_DBG1__ + printf("IPCP session : All IPCP options are rejected!!\r\n"); +#endif + do_lcp_terminate(); + } + else + { +#ifdef __DEF_PPP_DBG1__ + printf("IPCP configuration request send without reject protocol\r\n"); +#endif + ppp_send(); + } + + + break; + case PPP_CONFIG_ACK : // ack, then ipcp_cr_snt flag set +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Session IPCP: Configure-Ack received\r\n"); +#endif + if((pppoe_control_flag & FLAG_IPCP_NAK_RCV) == FLAG_IPCP_NAK_RCV) pppoe_control_flag = pppoe_control_flag | FLAG_IPCP_CR_SNT; + break; + } + } + break; + default: + break; + } + } +} + + + +void PPPOEClient::do_discovery(void) +{ + uint16_t i = 0; + uint8_t mac[6] = {0,}; + //getSHAR(mac); + eth->getSHAR(mac); + + // PPPoE Frame + for(i = 0; i < 6; i++) + { + PPPMSG_req.dst_mac[i] = 0xFF; // Broadcast MAC address + PPPMSG_req.src_mac[i] = mac[i]; // Source MAC address + //-- Opt. Device MAC Address + PPPPROTO.opt[10+i] = mac[i]; + } + //Reset control flag. + pppoe_control_flag = 0; + + //change MSB and LSB because of different endian. + PPPMSG_req.ether_type = 0; + PPPMSG_req.ether_type = (PPPoE_DISCOVERY & 0xFF) << 8;//session data + PPPMSG_req.ether_type |= ((PPPoE_DISCOVERY >> 8) & 0xFF);//session data + + PPPMSG_req.version_type = PPPoE_VER_TYPE; // Ver : 0001, Type : 0001 + PPPMSG_req.frame_code = PPPoE_PADI; // PADI + + PPPMSG_req.session_id = 0; + + + // Tag name : PPPoED_SERVICE_NAME + PPPPROTO.opt[0] = 0x01; + PPPPROTO.opt[1] = 0x01; + // Tag len + PPPPROTO.opt[2] = 0x00; + PPPPROTO.opt[3] = 0x00; + + // Tag name : PPPoED_HOST_UNIQ + PPPPROTO.opt[4] = 0x01; + PPPPROTO.opt[5] = 0x03; + // Tag len (2bytes) + PPPPROTO.opt[6] = 0x00; + PPPPROTO.opt[7] = 0x08; + // Fill the Host-Uniq field using MAC address + PPPPROTO.opt[8] = 0x00; + PPPPROTO.opt[9] = 0x00; + //PPPPROTO.opt[10~15] refer to "//-- Opt. Device MAC Address" + + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = (16 & 0xFF) << 8; + PPPMSG_req.len |= ((16 >> 8) & 0xFF);//size of opt[0-9]+ opt[10-15] + +#ifdef __DEF_PPP_DBG1__ + printf("PPPoE Discovery : PADI send\r\n"); +#endif + ppp_send(); + +} + +void PPPOEClient::do_lcp(void) +{ + + //change MSB and LSB because of different endian. + PPPMSG_req.ether_type = 0; + PPPMSG_req.ether_type = (PPPoE_SESSION & 0xFF) << 8; + PPPMSG_req.ether_type |= ((PPPoE_SESSION >> 8) & 0xFF);//session data + + PPPMSG_req.frame_code = 0x00; //session data + //change MSB and LSB because of different endian. + PPPMSG_req.session_id = 0; + PPPMSG_req.session_id = (NAS_sessionid & 0xFF) << 8; + PPPMSG_req.session_id |= ((NAS_sessionid >> 8) & 0xFF);//session data + + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_LCP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_LCP >> 8) & 0xFF); + + + PPPPROTO.pcode = PPP_CONFIG_REQ; // CR + + PPPPROTO.opt[0] = 0x05; + PPPPROTO.opt[1] = 0x06; + PPPPROTO.opt[2] = 0x00; + PPPPROTO.opt[3] = 0x01; + PPPPROTO.opt[4] = 0x02; + PPPPROTO.opt[5] = 0x03; + + PPPPROTO.id = protocol_id++; + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = (10 & 0xFF) << 8; + PPPPROTO.len |= ((10 >> 8) & 0xFF); + + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = (12 & 0xFF) << 8; + PPPMSG_req.len |= ((12 >> 8) & 0xFF); + +#ifdef __DEF_PPP_DBG1__ + printf("LCP configuration Request send\r\n"); +#endif + ppp_send(); + +} + +void PPPOEClient::do_lcp_echo(void) +{ + + //change MSB and LSB because of different endian. + PPPMSG_req.ether_type = 0; + PPPMSG_req.ether_type = (PPPoE_SESSION & 0xFF) << 8; + PPPMSG_req.ether_type |= ((PPPoE_SESSION >> 8) & 0xFF);// session + + PPPMSG_req.frame_code = 0x00; // session data + //change MSB and LSB because of different endian. + PPPMSG_req.session_id = 0; + PPPMSG_req.session_id = (NAS_sessionid & 0xFF) << 8; + PPPMSG_req.session_id |= ((NAS_sessionid >> 8) & 0xFF);// session id + + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_LCP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_LCP >> 8) & 0xFF); + + PPPPROTO.pcode = PPP_ECHO_REQ; // Echo-Requset + + PPPPROTO.opt[0] = 0x00; // Magic number + PPPPROTO.opt[1] = 0x01; + PPPPROTO.opt[2] = 0x02; + PPPPROTO.opt[3] = 0x03; + + PPPPROTO.id = protocol_id++; + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = (8 & 0xFF) << 8; + PPPPROTO.len |= ((8 >> 8) & 0xFF); + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = (10 & 0xFF) << 8; + PPPMSG_req.len |= ((10 >> 8) & 0xFF); +#ifdef __DEF_PPP_DBG1__ + printf("LCP echo request send\r\n"); +#endif + ppp_send(); + +} + +//return -- 1 : success, 0 : failed +uint8_t PPPOEClient::do_lcp_terminate(void) +{ + uint16_t received_len = 0; + uint8_t sock_num = 0; + + + pppoe_retry_count = 0; + + //while( (pppoe_control_flag & FLAG_TERMINATION_ACK_RCV) == 0 ) + while(1) + { + //change MSB and LSB because of different endian. + PPPMSG_req.ether_type = 0; + PPPMSG_req.ether_type = (PPPoE_SESSION & 0xFF) << 8; + PPPMSG_req.ether_type |= ((PPPoE_SESSION >> 8) & 0xFF);// session + + PPPMSG_req.frame_code = 0x00; // session data + //change MSB and LSB because of different endian. + PPPMSG_req.session_id = 0; + PPPMSG_req.session_id = (NAS_sessionid & 0xFF) << 8; + PPPMSG_req.session_id |= ((NAS_sessionid >> 8) & 0xFF); + + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_LCP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_LCP >> 8) & 0xFF); + + PPPPROTO.pcode = PPP_TERM_REQ; // Terminate-Requset + + PPPPROTO.opt[0] = 0x00; // Magic number + PPPPROTO.opt[1] = 0x01; + PPPPROTO.opt[2] = 0x02; + PPPPROTO.opt[3] = 0x03; + + PPPPROTO.id = protocol_id++; + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = (8 & 0xFF) << 8; + PPPPROTO.len |= ((8 >> 8) & 0xFF); + + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = (10 & 0xFF) << 8; + PPPMSG_req.len |= ((10 >> 8) & 0xFF); + + +#ifdef __DEF_PPP_DBG1__ + printf("Termination Request send\r\n"); +#endif + ppp_send(); + pppoe_retry_count++; + + + if(pppoe_retry_count > PPP_MAX_RETRY_COUNT) + { + printf("Termination Failed\r\n"); + return 0;//termination fail + } + + + pppoe_recv_count = 0; + while((pppoe_control_flag & FLAG_TERMINATION_ACK_RCV) == 0 && pppoe_recv_count < PPP_MAX_RETRYRECV_COUNT) + { + wait(0.4); + pppoe_recv_count ++; + + + received_len = eth->getSn_RX_RSR(sock_num); + + if(received_len > 0) + { + ppp_recv(received_len); + if((pppoe_control_flag & FLAG_TERMINATION_ACK_RCV) == FLAG_TERMINATION_ACK_RCV) // Termination success + { + pppoe_state = PPPoE_FAILED; + + // Flags reset + pppoe_control_flag = 0; + // Clear Session ID for new PPPoE Discovery process + NAS_sessionid = 0; + + NAS_mac[0] = 0; + NAS_mac[1] = 0; + NAS_mac[2] = 0; + NAS_mac[3] = 0; + NAS_mac[4] = 0; + NAS_mac[5] = 0; + + pppoe_ip[0] = 0; + pppoe_ip[1] = 0; + pppoe_ip[2] = 0; + pppoe_ip[3] = 0; + + printf("Termination completed\r\n"); + return 1;//termination success + } + } + } + + } + +} + + +void PPPOEClient::do_pap(void) +{ + + uint16_t i=0, j=0; + + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_PAP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_PAP >> 8) & 0xFF); + + PPPPROTO.pcode = PPP_CONFIG_REQ; // cr + PPPPROTO.opt[i++] = pppoe_id_len; + + for(j = 0; j < pppoe_id_len; j++) + { + PPPPROTO.opt[i++] = pppoe_id[j]; + } + + PPPPROTO.opt[i++] = pppoe_pw_len; + for(j = 0; j < pppoe_pw_len; j++) + { + PPPPROTO.opt[i++] = pppoe_pw[j]; + } + + PPPPROTO.id = protocol_id++; + //change MSB and LSB because of different endian. + PPPPROTO.len = 0; + PPPPROTO.len = ((i+4) & 0xFF) << 8; + PPPPROTO.len |= (((i+4) >> 8) & 0xFF); + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = (((i+4)+2) & 0xFF) << 8; + PPPMSG_req.len |= ((((i+4)+2) >> 8) & 0xFF); + +#ifdef __DEF_PPP_DBG1__ + printf("PAP authenticate-Request send\r\n"); +#endif + + ppp_send(); + +} + +void PPPOEClient::do_ipcp(void) +{ + + //change MSB and LSB because of different endian. + PPPPROTO.protocol = 0; + PPPPROTO.protocol = (PPPoE_IPCP & 0xFF) << 8; + PPPPROTO.protocol |= ((PPPoE_IPCP >> 8) & 0xFF); + + PPPPROTO.pcode = PPP_CONFIG_REQ; // configuration-req + + PPPPROTO.opt[0] = 0x03; // option code, IP address + PPPPROTO.opt[1] = 0x06; // option len + PPPPROTO.opt[2] = 0x00; + PPPPROTO.opt[3] = 0x00; + PPPPROTO.opt[4] = 0x00; + PPPPROTO.opt[5] = 0x00; + //Option PDNS + PPPPROTO.opt[6] = 0x81; //op code, PDNS + PPPPROTO.opt[7] = 0x06; //option len + PPPPROTO.opt[8] = 0x00; + PPPPROTO.opt[9] = 0x00; + PPPPROTO.opt[10] = 0x00; + PPPPROTO.opt[11] = 0x00; + //Option SDNS + PPPPROTO.opt[12] = 0x83; //op code, SDNS + PPPPROTO.opt[13] = 0x06; //option len + PPPPROTO.opt[14] = 0x00; + PPPPROTO.opt[15] = 0x00; + PPPPROTO.opt[16] = 0x00; + PPPPROTO.opt[17] = 0x00; + + + PPPPROTO.id = protocol_id++; + + //change MSB and LSB because of different endian. + /* + PPPPROTO.len = 0; + PPPPROTO.len = (10 & 0xFF) << 8; + PPPPROTO.len |= ((10 >> 8) & 0xFF); + + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = (12 & 0xFF) << 8; + PPPMSG_req.len |= ((12 >> 8) & 0xFF); + */ + PPPPROTO.len = 0; + PPPPROTO.len = (22 & 0xFF) << 8; + PPPPROTO.len |= ((22 >> 8) & 0xFF); + + //change MSB and LSB because of different endian. + PPPMSG_req.len = 0; + PPPMSG_req.len = (24 & 0xFF) << 8; + PPPMSG_req.len |= ((24 >> 8) & 0xFF); +#ifdef __DEF_PPP_DBG1__ + printf("IPCP Configuration request send\r\n"); +#endif + + ppp_send(); + +} + + + +// PPPoE start +//ret = Success : 1, Fail : 0, continue : 2 +uint8_t PPPOEClient::ppp_start(uint8_t * pppoe_buf) +{ + uint8_t sock_num; + uint8_t mFlag; + uint16_t dummyPort; + uint8_t ret = 2; + uint16_t received_len = 0; + + buf = pppoe_buf; + //-- Init. param + sock_num = 0; + dummyPort = 0; + mFlag = 0x80; //MAC filter enable in MACRAW + + + switch(eth->getSn_SR(sock_num)) + { + case WIZnet_Chip::SOCK_CLOSED: + eth->close(sock_num); // Close the SOCKET + eth->Socket_macraw(sock_num, dummyPort, mFlag); // Open the SOCKET with MACRAW mode +#ifdef __DEF_PPP_DBG1__ + printf("No.%d socket is opened with MACRAW and flag is 0x%2x\r\n", sock_num, mFlag); +#endif +#ifdef __DEF_PPP_DBG__ + printf("\r\n=======================================\r\n"); + printf("PHASE 0. PPPoE setup\r\n"); + printf("=======================================\r\n"); +#endif + break; + + case SOCK_MACRAW: + + if(pppoe_retry_send_count > PPP_MAX_RETRYSEND_COUNT) pppoe_state = PPPoE_FAILED; + + switch(pppoe_state) + { + case PPPoE_DISCOVERY : // Discovery + // PPPoE Discoveryecv( + //if((pppoe_control_flag & FLAG_DISCOVERY_RCV_PADO) == 0) + if((pppoe_control_flag & FLAG_DISCOVERY_RCV_PADO) == 0 || (pppoe_control_flag & FLAG_DISCOVERY_RCV_PADS) == 0) //Not recv PADO or PADS + { +#ifdef __DEF_PPP_DBG__ + printf("\r\n=======================================\r\n"); + printf("PHASE 1. PPPoE Discovery\r\n"); + printf("=======================================\r\n"); +#endif +#ifdef __DEF_PPP_DBG1__ + printf("Retry send count : %d\r\n", pppoe_retry_send_count); +#endif + do_discovery(); // Send PADI + pppoe_retry_send_count++; + } + + pppoe_recv_count = 0; + while((pppoe_control_flag & FLAG_DISCOVERY_RCV_PADS) == 0 && pppoe_recv_count < (PPP_MAX_RETRYRECV_COUNT) * 2) + { + wait(0.2); + pppoe_recv_count ++; + + received_len = eth->getSn_RX_RSR(sock_num); + + if(received_len > 0) + { + ppp_recv(received_len); + + + if((pppoe_control_flag & FLAG_DISCOVERY_RCV_PADS) == FLAG_DISCOVERY_RCV_PADS)// Discovery success + { + pppoe_state = PPPoE_LCP; + pppoe_retry_send_count = 0;//reset + } + } + } + + break; + + case PPPoE_LCP : // LCP + if((pppoe_control_flag & FLAG_LCP_CR_RCV) == 0) + { +#ifdef __DEF_PPP_DBG__ + printf("\r\n=======================================\r\n"); + printf("PHASE 2. PPPoE LCP\r\n"); + printf("=======================================\r\n"); +#endif + do_lcp_echo(); + +#ifdef __DEF_PPP_DBG1__ + printf("Retry send count : %d\r\n", pppoe_retry_send_count); +#endif + pppoe_retry_send_count++; + } + + pppoe_recv_count = 0; + while((pppoe_control_flag & FLAG_LCP_CR_RCV) == 0 && pppoe_recv_count < PPP_MAX_RETRYRECV_COUNT) + { + wait(0.2); + pppoe_recv_count++; + + received_len = eth->getSn_RX_RSR(sock_num); + if(received_len > 0) + { + ppp_recv(received_len); + if((pppoe_control_flag & FLAG_LCP_CR_RCV) == FLAG_LCP_CR_RCV) pppoe_retry_send_count = 0;//reset + } + } + + + if((pppoe_control_flag & FLAG_LCP_CR_RCV) == FLAG_LCP_CR_RCV) + { + do_lcp(); + +#ifdef __DEF_PPP_DBG1__ + printf("Retry send count : %d\r\n", pppoe_retry_send_count); +#endif + pppoe_retry_send_count++; + + pppoe_recv_count = 0; + while((pppoe_control_flag & FLAG_LCP_CR_SNT) == 0 && pppoe_recv_count < PPP_MAX_RETRYRECV_COUNT) + { + wait(0.2); + pppoe_recv_count++; + + received_len = eth->getSn_RX_RSR(sock_num); + if(received_len > 0) + { + ppp_recv(received_len); + if((pppoe_control_flag & FLAG_LCP_CR_SNT) == FLAG_LCP_CR_SNT) + { + // PAP + if(auth_protocol == PPPoE_PAP) + { + pppoe_state = PPPoE_PAP; + pppoe_retry_send_count = 0;//reset + } + // CHAP + else if(auth_protocol == PPPoE_CHAP) + { + pppoe_state = PPPoE_CHAP; + pppoe_retry_send_count = 0;//reset + } + // unknown auth protocol + else + { +#ifdef __DEF_PPP_DBG1__ + printf("\r\nError : Unknown authentication protocol"); +#endif + pppoe_state = PPPoE_FAILED; + } + + } + } + } + } + break; + + case PPPoE_PAP : // PAP +#ifdef __DEF_PPP_DBG__ + printf("\r\n=======================================\r\n"); + printf("PHASE 3. PPPoE PAP\r\n"); + printf("=======================================\r\n"); +#endif + + + if((pppoe_control_flag & FLAG_PAP_ACK_RCV) == 0 ) + { + do_pap(); + pppoe_retry_send_count++; +#ifdef __DEF_PPP_DBG1__ + printf("Retry send count : %d\r\n", pppoe_retry_send_count ); +#endif + } + + pppoe_recv_count = 0; + while((pppoe_control_flag & FLAG_PAP_ACK_RCV) == 0 && pppoe_recv_count < PPP_MAX_RETRYRECV_COUNT) + { + wait(0.4); + pppoe_recv_count++; + + received_len = eth->getSn_RX_RSR(sock_num); + if(received_len > 0) + { + ppp_recv(received_len); + + if((pppoe_control_flag & FLAG_PAP_ACK_RCV) == FLAG_PAP_ACK_RCV)// pap auth success + { + pppoe_state = PPPoE_IPCP; + pppoe_retry_send_count = 0;//reset + } + } + } + break; + + case PPPoE_CHAP : // CHAP +#ifdef __DEF_PPP_DBG__ + printf("\r\n=======================================\r\n"); + printf("PHASE 3. PPPoE CHAP\r\n"); + printf("=======================================\r\n"); +#endif + + + pppoe_recv_count = 0; + while((pppoe_control_flag & FLAG_CHAP_SUC_RCV) == 0 && pppoe_recv_count < 50) + { + wait(0.4); + pppoe_recv_count++; + + printf("test\r\n"); + + received_len = eth->getSn_RX_RSR(sock_num); + if(received_len > 0) + { + ppp_recv(received_len); + + if((pppoe_control_flag & FLAG_CHAP_SUC_RCV) == FLAG_CHAP_SUC_RCV) + { + pppoe_state = PPPoE_IPCP; + } + + if((pppoe_control_flag & FLAG_TERMINATION_REQ_RCV) == FLAG_TERMINATION_REQ_RCV) + { + pppoe_state = PPPoE_FAILED; + + break; + } + } + } + + if( pppoe_recv_count >= 50) + { + if(do_lcp_terminate() == 0) //if termination is failed. + return 0; + } + + break; + + case PPPoE_IPCP : // IPCP +#ifdef __DEF_PPP_DBG__ + printf("\r\n=======================================\r\n"); + printf("PHASE 4. PPPoE IPCP\r\n"); + printf("=======================================\r\n"); +#endif + + pppoe_recv_count = 0; + while((pppoe_control_flag & FLAG_IPCP_CR_RCV) == 0 && pppoe_recv_count < PPP_MAX_RETRYRECV_COUNT) + { + wait(1); + pppoe_recv_count++; + + received_len = eth->getSn_RX_RSR(sock_num); + if(received_len > 0) + { + ppp_recv(received_len); + + if((pppoe_control_flag & FLAG_IPCP_CR_RCV) == FLAG_IPCP_CR_RCV) pppoe_retry_send_count = 0;//reset + + } + + } + // After received IPCP Configuration-Request and sent ACK, + // User device have to send IPCP Configuration-Request and receive ACK. + if((pppoe_control_flag & FLAG_IPCP_CR_RCV) == FLAG_IPCP_CR_RCV) + { + do_ipcp(); + pppoe_retry_send_count++; + + pppoe_recv_count = 0; + while((pppoe_control_flag & FLAG_IPCP_CR_SNT) == 0 && pppoe_recv_count < PPP_MAX_RETRYRECV_COUNT) + { + wait(1); + pppoe_recv_count++; + + received_len = eth->getSn_RX_RSR(sock_num); + if(received_len > 0) + { + ppp_recv(received_len); + + if((pppoe_control_flag & FLAG_IPCP_CR_SNT) == FLAG_IPCP_CR_SNT) + { + pppoe_retry_send_count = 0;//reset +#ifdef __DEF_PPP_DBG__ + printf("\r\n=======================================\r\n"); + printf("PHASE 5. PPPoE Socket open\r\n"); + printf("=======================================\r\n"); +#endif + set_pppinfo(NAS_mac, pppoe_ip, NAS_sessionid); + ret = PPP_SUCCESS; + } + else if( (pppoe_control_flag & FLAG_TERMINATION_ACK_RCV) == FLAG_TERMINATION_ACK_RCV) + { + return 0; + } + else if( (pppoe_control_flag & FLAG_TERMINATION_REQ_RCV) == FLAG_TERMINATION_REQ_RCV) + { + return 0; + } + } + } + } + break; + + case PPPoE_FAILED : + pppoe_retry_count++; +#ifdef __DEF_PPP_DBG__ + printf("\r\nPPPoE FAILED !!!\r\n"); +#endif +#ifdef __DEF_PPP_DBG1__ + printf("Retry count : %d\r\n", pppoe_retry_count); +#endif + // All flags reset + pppoe_control_flag = 0; + + // Clear Session ID for new PPPoE Discovery process + //NAS_sessionid = 0; + + pppoe_retry_send_count = 0; + pppoe_state = PPPoE_DISCOVERY; + + break; + + + default : +#ifdef __DEF_PPP_DBG__ + printf("\r\nUndefined state!\r\n"); +#endif + pppoe_state = PPPoE_FAILED; + break; + } + + // PPPoE packet send count over : connection terminate + if(pppoe_retry_send_count >= PPP_MAX_RETRYSEND_COUNT) pppoe_state = PPPoE_FAILED; + break; + + default: + break; + } + return ret; +} +/* +void PPPOEClient::delay_ms(uint32_t time) +{ + uint32_t i; + + for(i=0; i<time; i++) + { + xSysCtlDelay((xSysCtlClockGet()/1000)); // wait 1ms + } +} +*/ \ No newline at end of file
diff -r 000000000000 -r 7a9cde4dbf0b PPPoE.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PPPoE.h Wed Oct 29 06:17:02 2014 +0000 @@ -0,0 +1,167 @@ +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include "W5500.h" +#include "Socket.h" +#include "md5.h" + + + + + + +#define __DEF_PPP_DBG__ // debug message for [Phase] and [Network Init] +//#define __DEF_PPP_DBG1__ // debug message for checking 'Txbuf overflow' and etc. +//#define __DEF_PPP_DBG2__ // debug received and send packet. + + + +//PPPoE retry count value +//#define PPP_MAX_RETRYRECV_COUNT 50 +#define PPP_MAX_RETRYSEND_COUNT 5 +#define PPP_MAX_RETRYRECV_COUNT 32 +#define PPP_MAX_RETRY_COUNT 5 +// PPPoE EtherType definition +#define PPPoE_DISCOVERY 0x8863 +#define PPPoE_SESSION 0x8864 + +// PPPoE Frame field definition +#define PPPoE_VER_TYPE 0x11 + +// PPPoE Code definition +#define PPPoE_PADI 0x09 +#define PPPoE_PADO 0x07 +#define PPPoE_PADR 0x19 +#define PPPoE_PADS 0x65 +#define PPPoE_PADT 0xa7 +#define PPPoE_SESSIONDATA 0x00 + +// PPPoE Discovery Tag type definition +#define PPPoED_END_OF_LIST 0x0000 +#define PPPoED_SERVICE_NAME 0x0101 +#define PPPoED_AC_NAME 0x0102 +#define PPPoED_HOST_UNIQ 0x0103 +#define PPPoED_AC_COOKIE 0x0104 +#define PPPoED_VENDER_SPECIFIC 0x0105 + +// PPPoE Protocol definition +#define PPPoE_LCP 0xC021 +#define PPPoE_PAP 0xC023 +#define PPPoE_CHAP 0xC223 +#define PPPoE_IPCP 0x8021 + +// PPPoE Protocol Code definition + // LCP using 0x01 ~ 0x0b + // PAP using 0x01 ~ 0x03 + // IPCP using 0x01 ~ 0x07 +#define PPP_CONFIG_REQ 0x01 +#define PPP_CONFIG_ACK 0x02 +#define PPP_CONFIG_NAK 0x03 +#define PPP_CONFIG_REJ 0x04 +#define PPP_TERM_REQ 0x05 +#define PPP_TERM_ACK 0x06 +#define PPP_CODE_REJ 0x07 +#define PPP_PROT_REJ 0x08 +#define PPP_ECHO_REQ 0x09 +#define PPP_ECHO_REP 0x0a +#define PPP_DIS_REQ 0x0b + +// PPPoE LCP Type definition +#define LCP_MRU 0x01 +#define LCP_AUTH 0x03 +#define LCP_MAGICNUM 0x05 +#define LCP_PROTOCOMP 0x07 +#define LCP_ADDRCOMP 0x08 + +// PPPoE CHAP Algorithm +#define MD5 0x05 +#define MS_CHAP 0x80 +#define MS_CHAP_V2 0x81 + +// PPPoE stage control flags +#define FLAG_DISCOVERY_RCV_PADO 0x0001 +#define FLAG_DISCOVERY_RCV_PADS 0x0002 +#define FLAG_LCP_CR_RCV 0x0004 +#define FLAG_LCP_CR_SNT 0x0008 +#define FLAG_PAP_ACK_RCV 0x0010 +#define FLAG_CHAP_SUC_RCV 0x0020 +#define FLAG_IPCP_CR_SNT 0x0040 +#define FLAG_IPCP_CR_RCV 0x0080 +#define FLAG_IPCP_NAK_RCV 0x0100 +#define FLAG_TERMINATION_ACK_RCV 0x0200 +#define FLAG_TERMINATION_REQ_RCV 0x0400 +#define FLAG_PADO_SERVICENAME 0x0800 + +/* +// PPPoE Field value definition +// -> not used. +#define PPPoE_SESSION_ID 0x0000 +#define LCP_MAGICNUM_VAL 0x00112299 +*/ + +// Logical variable definition +#define PPP_SUCCESS 1 +//#define PPP_FAIL 0 +#define PPP_RETRY 2 + +#define OPTMSG_LEN 80 +#define CV_HV_LEN 16 + + +#define PPPoE_FAILED 0 + + +#define PPP_FRAME_SIZE 128 +#define PPP_RXFRAME_SIZE 1514 + + + +class PPPOEClient +{ +public: + PPPOEClient(); + void set_pppinfo(uint8_t * nas_mac, uint8_t * ppp_ip, uint16_t nas_sessionid); + void ppp_send(void); + void ppp_recv( uint16_t received_len ); + void do_discovery(void); + void do_lcp(void); + void do_lcp_echo(void); + uint8_t do_lcp_terminate(void); + void do_pap(void); + void do_ipcp(void); + uint8_t ppp_start(uint8_t * pppoe_buf); + //void delay_ms(uint32_t time); + + + +private: + WIZnet_Chip* eth; + +}; + +// PPPoE message +typedef struct _PPPMSG +{ + uint8_t dst_mac[6]; + uint8_t src_mac[6]; + uint16_t ether_type; // 0x8863 : PPPoE Discovery, 0x8864 : PPPoE Session + uint8_t version_type; // 4-bit 'version' = 0001, 4-bit 'type' = 0001 default + uint8_t frame_code; + uint16_t session_id; + uint16_t len; +}PPPMSG; + +// PPPoE Protocol +typedef struct _PROTOCOL +{ + uint16_t protocol; + uint8_t pcode; + uint8_t id; + uint16_t len; + uint8_t opt[OPTMSG_LEN]; +}PROTOCOL; + +// PPPoE Start function +uint8_t ppp_start(uint8_t * pppoe_buf); +//PPPoE termination function +uint8_t do_lcp_terminate(void);
diff -r 000000000000 -r 7a9cde4dbf0b md5.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/md5.cpp Wed Oct 29 06:17:02 2014 +0000 @@ -0,0 +1,319 @@ +/* + *********************************************************************** + ** md5.c -- the source code for MD5 routines ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + +//#include "lwip/opt.h" + +//#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +//#if CHAP_SUPPORT || MD5_SUPPORT + +//#include "ppp.h" +//#include "pppdebug.h" + +#include "md5.h" + +#include <string.h> + +/* + *********************************************************************** + ** Message-digest routines: ** + ** To form the message digest for a message M ** + ** (1) Initialize a context buffer mdContext using MD5Init ** + ** (2) Call MD5Update on mdContext and M ** + ** (3) Call MD5Final on mdContext ** + ** The message digest is now in mdContext->digest[0...15] ** + *********************************************************************** + */ + +/* forward declaration */ +static void Transform (uint32_t *buf, uint32_t *in); + +static unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G, H and I are basic MD5 functions */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +#ifdef __STDC__ +#define UL(x) x##UL +#else +#ifdef WIN32 +#define UL(x) x##UL +#else +#define UL(x) x +#endif +#endif + +/* The routine MD5Init initializes the message-digest context + mdContext. All fields are set to zero. + */ +void +MD5Init (MD5_CTX *mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (uint32_t)0; + + /* Load magic initialization constants. */ + mdContext->buf[0] = (uint32_t)0x67452301UL; + mdContext->buf[1] = (uint32_t)0xefcdab89UL; + mdContext->buf[2] = (uint32_t)0x98badcfeUL; + mdContext->buf[3] = (uint32_t)0x10325476UL; +} + +/* The routine MD5Update updates the message-digest context to + account for the presence of each of the characters inBuf[0..inLen-1] + in the message whose digest is being computed. + */ +void +MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) +{ + uint32_t in[16]; + int mdi; + unsigned int i, ii; + +#if 0 + PPPDEBUG(LOG_INFO, ("MD5Update: %u:%.*H\n", inLen, LWIP_MIN(inLen, 20) * 2, inBuf)); + PPPDEBUG(LOG_INFO, ("MD5Update: %u:%s\n", inLen, inBuf)); +#endif + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((uint32_t)inLen << 3)) < mdContext->i[0]) { + mdContext->i[1]++; + } + mdContext->i[0] += ((uint32_t)inLen << 3); + mdContext->i[1] += ((uint32_t)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) { + in[i] = (((uint32_t)mdContext->in[ii+3]) << 24) | + (((uint32_t)mdContext->in[ii+2]) << 16) | + (((uint32_t)mdContext->in[ii+1]) << 8) | + ((uint32_t)mdContext->in[ii]); + } + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +/* The routine MD5Final terminates the message-digest computation and + ends with the desired message digest in mdContext->digest[0...15]. + */ +void +MD5Final (unsigned char hash[], MD5_CTX *mdContext) +{ + uint32_t in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) { + in[i] = (((uint32_t)mdContext->in[ii+3]) << 24) | + (((uint32_t)mdContext->in[ii+2]) << 16) | + (((uint32_t)mdContext->in[ii+1]) << 8) | + ((uint32_t)mdContext->in[ii]); + } + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } + //SMEMCPY(hash, mdContext->digest, 16); + memcpy(hash, mdContext->digest, 16); +} + +/* Basic MD5 step. Transforms buf based on in. + */ +static void +Transform (uint32_t *buf, uint32_t *in) +{ + uint32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ + FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ + FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ + FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ + FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ + FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ + FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ + GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ + GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ + GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ + GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ + GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ + GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ + HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ + HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ + HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ + HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ + HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ + HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ + II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ + II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ + II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ + II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ + II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ + II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ + II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ + II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ + II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ + II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ + II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ + II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ + II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ + II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ + II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +
diff -r 000000000000 -r 7a9cde4dbf0b md5.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/md5.h Wed Oct 29 06:17:02 2014 +0000 @@ -0,0 +1,59 @@ +/** + @file md5.h + */ +/* + *********************************************************************** + ** md5.h -- header file for implementation of MD5 ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ** Revised (for MD5): RLR 4/27/91 ** + ** -- G modified to have y&~z instead of y&z ** + ** -- FF, GG, HH modified to add in last register done ** + ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** + ** -- distinct additive constant for each step ** + ** -- round 4 added, working mod 7 ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + +#include <stdint.h> +#ifndef __MD5_H +#define __MD5_H + +/* Data structure for MD5 (Message-Digest) computation */ +typedef struct { + uint32_t i[2]; /* number of _bits_ handled mod 2^64 */ + uint32_t buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD5Final call */ +} MD5_CTX; + +void MD5Init ( MD5_CTX *mdContext); +void MD5Update( MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen); +void MD5Final ( unsigned char hash[], MD5_CTX *mdContext); + +#endif /* MD5_H */