PPPoE application with W5500
Dependencies: W5500Interface mbed pppoe
- How to connect PPPoE with WIZ550 ioShield and mbed platform (Korean version)
- How to connect ioShield to mbed platform(ST nucleo) of ST Microelectronics via SPI (Korean version)
- Example PPPoE server(RB750) setting (Korean version)
http://hjjeon0608.wordpress.com/2014/10/28/rb750pppoe-server-setting%ED%95%98%EA%B8%B0/
- W5500(PPPoE client) setting (Korean version)
http://hjjeon0608.wordpress.com/2014/10/29/temp/
- PPPoE library
http://developer.mbed.org/teams/EthernetInterfaceW5500-makers/code/pppoe/
pppoe/PPPoE.cpp
- Committer:
- hjjeon
- Date:
- 2014-10-15
- Revision:
- 1:8ef7820bf777
- Child:
- 3:39ed2b6d91b0
File content as of revision 1:8ef7820bf777:
#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 SOCK_CLOSED: eth->close(sock_num); // Close the SOCKET 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 } } */