/************************************************************************* * * Send a PADT * *************************************************************************/ int session_disconnect(struct session *ses){ struct pppoe_packet padt; memset(&padt,0,sizeof(struct pppoe_packet)); memcpy(&padt.addr, &ses->remote, sizeof(struct sockaddr_ll)); padt.hdr = (struct pppoe_hdr*) ses->curr_pkt.buf; padt.hdr->ver = 1; padt.hdr->type = 1; padt.hdr->code = PADT_CODE; padt.hdr->sid = ses->sp.sa_addr.pppoe.sid; if (padt.hdr->sid == 0) { int i; int retval; int addr[ETH_ALEN]; int sid; /* If session ID = 0, we still need to disconnect old session */ retval = sscanf(oldsession, "%02x%02x%02x%02x%02x%02x/%04x", addr, addr+1, addr+2, addr+3, addr+4, addr+5, &sid); if (retval == 7) { for(i = 0; i < ETH_ALEN ; i++ ){ padt.addr.sll_addr[i]=addr[i]; } padt.hdr->sid = sid; } } send_disc(ses,&padt); ses->sp.sa_addr.pppoe.sid = 0 ; ses->state = PADO_CODE; return 0; }
static int std_rcv_pado(struct session* ses, struct pppoe_packet *p_in, struct pppoe_packet **p_out){ if( verify_packet(ses, p_in) < 0) return -1; if(ses->state != PADO_CODE ){ poe_error(ses,"Unexpected packet: %P",p_in); return 0; } if (DEB_DISC2) { poe_dbglog (ses,"PADO received: %P", p_in); } memcpy(&ses->remote, &p_in->addr, sizeof(struct sockaddr_ll)); memcpy( &ses->curr_pkt.addr, &ses->remote , sizeof(struct sockaddr_ll)); ses->curr_pkt.hdr->code = PADR_CODE; /* The HOST_UNIQ has been verified already... there's no "if" about this */ /* if(ses->filt->htag) */ copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_HOST_UNIQ)); if (ses->filt->ntag) { ses->curr_pkt.tags[TAG_AC_NAME]=NULL; } // copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_AC_NAME)); if(ses->filt->stag) { ses->curr_pkt.tags[TAG_SRV_NAME]=NULL; } copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_SRV_NAME)); copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_AC_COOKIE)); copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_RELAY_SID)); ses->state = PADS_CODE; create_msg(BCM_PPPOE_CLIENT_STATE_PADS); syslog(LOG_CRIT,"PPP server detected.\n"); ses->retransmits = 0; send_disc(ses, &ses->curr_pkt); (*p_out) = &ses->curr_pkt; if (ses->np) return 1; return 0; }
static int relay_rcv_padi(struct session* ses, struct pppoe_packet *p_in, struct pppoe_packet **p_out){ char tag_buf[32]; struct pppoe_con *newpc = NULL; struct pppoe_tag *tag = (struct pppoe_tag *) tag_buf; tag->tag_type = PTT_RELAY_SID; tag->tag_len = htons(ETH_ALEN + sizeof(struct session *)); memcpy(tag->tag_data, p_in->addr.sll_addr, ETH_ALEN); memcpy(tag->tag_data + ETH_ALEN, &ses, sizeof(struct session *)); if(! p_in->tags[TAG_RELAY_SID] ){ copy_tag(p_in, tag); } poe_dbglog(ses, "Recv'd PADI: %P",p_in); poe_dbglog(ses, "Recv'd packet: %P",p_in); newpc = get_con( ntohs(tag->tag_len), tag->tag_data ); if(!newpc){ newpc = (struct pppoe_con *) malloc(sizeof(struct pppoe_con)); memset(newpc , 0, sizeof(struct pppoe_con)); newpc->id = pcid++; newpc->key_len = ntohs(p_in->tags[TAG_RELAY_SID]->tag_len); memcpy(newpc->key, p_in->tags[TAG_RELAY_SID]->tag_data, newpc->key_len); memcpy(newpc->client, p_in->addr.sll_addr, ETH_ALEN); memcpy(newpc->server, MAC_BCAST_ADDR, ETH_ALEN); store_con(newpc); } ++newpc->ref_count; memset(p_in->addr.sll_addr, 0xff, ETH_ALEN); p_in->addr.sll_ifindex = ses->remote.sll_ifindex; send_disc(ses, p_in); return 0; }
static int std_init_disc(struct session* ses, struct pppoe_packet *p_in, struct pppoe_packet **p_out){ /* Check if already connected */ if( ses->state != PADO_CODE ){ return -1; } memset(&ses->curr_pkt,0, sizeof(struct pppoe_packet)); ses->curr_pkt.hdr = (struct pppoe_hdr*) ses->curr_pkt.buf; ses->curr_pkt.hdr->ver = 1; ses->curr_pkt.hdr->type = 1; ses->curr_pkt.hdr->code = PADI_CODE; memcpy( &ses->curr_pkt.addr, &ses->remote , sizeof(struct sockaddr_ll)); poe_info (ses,"Sending PADI"); //if (DEB_DISC) // poe_dbglog (ses,"Sending PADI"); fprintf(stderr,"Sending PADI\n"); ses->retransmits = 0 ; if(ses->filt->ntag) { ses->curr_pkt.tags[TAG_AC_NAME]=ses->filt->ntag; poe_info(ses,"overriding AC name\n"); } if(ses->filt->stag) ses->curr_pkt.tags[TAG_SRV_NAME]=ses->filt->stag; if(ses->filt->htag) ses->curr_pkt.tags[TAG_HOST_UNIQ]=ses->filt->htag; ses->retransmits = 0 ; send_disc(ses, &ses->curr_pkt); (*p_out)= &ses->curr_pkt; if (DEB_DISC) poe_dbglog (ses,"Sent PADI: %P", *p_out); return 0; }
/************************************************************************* * * Send a PADT * *************************************************************************/ int session_disconnect(struct session *ses){ struct pppoe_packet padt; memset(&padt,0,sizeof(struct pppoe_packet)); memcpy(&padt.addr, &ses->remote, sizeof(struct sockaddr_ll)); padt.hdr = (struct pppoe_hdr*) ses->curr_pkt.buf; padt.hdr->ver = 1; padt.hdr->type = 1; padt.hdr->code = PADT_CODE; padt.hdr->sid = ses->sp.sa_addr.pppoe.sid; send_disc(ses,&padt); ses->sp.sa_addr.pppoe.sid = 0 ; ses->state = PADO_CODE; return 0; }
int llclose(int fd, unsigned int flag) { if (!initialized) { printf("THIS IS ALREADY CLOSE\n"); return -1; } if (flag == SENDER) { if (send_disc(fd, flag)) return -1; if (rec_disc(fd, flag)) return -1; if (send_ua(fd, flag)) return -1; } if (close_port_file(fd)) return -1; return 0; }
static int relay_rcv_pkt(struct session* ses, struct pppoe_packet *p_in, struct pppoe_packet **p_out){ struct pppoe_con *pc; // char tag_buf[32]; struct pppoe_tag *tag = p_in->tags[TAG_RELAY_SID]; if( !tag ) return 0; pc = get_con(ntohs(tag->tag_len),tag->tag_data); if( !pc ) return 0; poe_dbglog(ses, "Recv'd packet: %P",p_in); if( memcmp(pc->client , p_in->addr.sll_addr , ETH_ALEN ) == 0 ){ memcpy(p_in->addr.sll_addr, pc->server, ETH_ALEN); p_in->addr.sll_ifindex = ses->remote.sll_ifindex; }else{ if( memcmp(pc->server, MAC_BCAST_ADDR, ETH_ALEN) == 0 ){ memcpy(pc->server, p_in->addr.sll_addr, ETH_ALEN); }else if( memcmp(pc->server, p_in->addr.sll_addr, ETH_ALEN) !=0){ return 0; } memcpy(p_in->addr.sll_addr, pc->client, ETH_ALEN); p_in->addr.sll_ifindex = ses->local.sll_ifindex; } send_disc(ses, p_in); return 0; }
/************************************************************************* * * Make a connection -- behaviour depends on callbacks specified in "ses" * *************************************************************************/ int session_connect(struct session *ses) { struct pppoe_packet *p_out=NULL; struct pppoe_packet rcv_packet; int ret; if(ses->init_disc){ ret = (*ses->init_disc)(ses, NULL, &p_out); if( ret != 0 ) return ret; } /* main discovery loop */ while(ses->retransmits < ses->retries || ses->retries==-1 ){ fd_set in; struct timeval tv; FD_ZERO(&in); FD_SET(disc_sock,&in); if(ses->retransmits < 0) ret = select(disc_sock+1, &in, NULL, NULL, NULL); else { ++ses->retransmits; tv.tv_sec = 1 << ses->retransmits; //tv.tv_sec = retransmit_time; tv.tv_usec = 0; again: ret = select(disc_sock+1, &in, NULL, NULL, &tv); } if( ret < 0 && errno != EINTR){ return -1; } else if( ret == 0 ) { if( DEB_DISC ) poe_dbglog(ses, "Re-sending ..."); if( ses->timeout ) { ret = (*ses->timeout)(ses, NULL, &p_out); if( ret != 0 ) return ret; } else if(p_out) send_disc(ses,p_out); continue; } ret = recv_disc(ses, &rcv_packet); /* Should differentiate between system errors and bad packets and the like... */ if( ret < 0 && errno ) return -1; switch (rcv_packet.hdr->code) { case PADI_CODE: { if(ses->rcv_padi){ ret = (*ses->rcv_padi)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } } break; } case PADO_CODE: /* wait for PADO */ { if(ses->rcv_pado){ ret = (*ses->rcv_pado)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } else goto again; } break; } case PADR_CODE: { if(ses->rcv_padr){ ret = (*ses->rcv_padr)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } } break; } case PADS_CODE: /* wait for PADS */ { if(ses->rcv_pads){ ret = (*ses->rcv_pads)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } else goto again; } break; } case PADT_CODE: { if( rcv_packet.hdr->sid != ses->sp.sa_addr.pppoe.sid ){ --ses->retransmits; continue; } if(ses->rcv_padt){ ret = (*ses->rcv_padt)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } else goto again; }else{ poe_error (ses,"connection terminated"); return (-1); } break; } default: poe_error(ses,"invalid packet %P",&rcv_packet); return (-1); } } return (0); }
static int std_rcv_pado(struct session* ses, struct pppoe_packet *p_in, struct pppoe_packet **p_out){ if( verify_packet(ses, p_in) < 0) return -1; if(ses->state != PADO_CODE ){ poe_error(ses,"Unexpected packet: %P",p_in); return 0; } if (DEB_DISC2) { poe_dbglog (ses,"PADO received: %P", p_in); } // brcm: add code to get service name and put it in the /var/fyi/wan/servicename file if (p_in->tags[0]->tag_type == PTT_SRV_NAME) { char sName[255]=""; char path[64]=""; char cmd[320]=""; memset(sName, 0, p_in->tags[0]->tag_len+1); strncpy(sName, p_in->tags[0]->tag_data, p_in->tags[0]->tag_len); #ifdef BRCM_CMS_BUILD extern char servicename[BUFLEN_264]; /* service name from the connection, defined in options.c */ cmsLog_debug("servicename=%s", sName); strncpy(servicename, sName, sizeof(servicename)); #else //printf("PPPoE Service Name: %s\n", sName); sprintf(path, "%s/%s/%s", "/proc/var/fyi/wan", session_path, "servicename"); sprintf(cmd, "echo %s > %s", sName, path); system(cmd); #endif } memcpy(&ses->remote, &p_in->addr, sizeof(struct sockaddr_ll)); memcpy( &ses->curr_pkt.addr, &ses->remote , sizeof(struct sockaddr_ll)); ses->curr_pkt.hdr->code = PADR_CODE; /* The HOST_UNIQ has been verified already... there's no "if" about this */ /* if(ses->filt->htag) */ copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_HOST_UNIQ)); if (ses->filt->ntag) { ses->curr_pkt.tags[TAG_AC_NAME]=NULL; } // copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_AC_NAME)); #if 1 //brcm /* Our service name has been verified against the service name tags offered by * the server in the call to verify_packet(). We can just use it. */ copy_tag(&ses->curr_pkt, ses->filt->stag); #else if(ses->filt->stag) { ses->curr_pkt.tags[TAG_SRV_NAME]=NULL; } copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_SRV_NAME)); #endif copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_AC_COOKIE)); copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_RELAY_SID)); ses->state = PADS_CODE; create_msg(BCM_PPPOE_CLIENT_STATE_PADS, MDMVS_ERROR_NONE); syslog(LOG_CRIT,"PPP server detected.\n"); ses->retransmits = 0; send_disc(ses, &ses->curr_pkt); (*p_out) = &ses->curr_pkt; if (ses->np) return 1; return 0; }
int rec_data(int fd, unsigned char * buffer) { unsigned char addr = 0; unsigned char ctrl = 0; unsigned int dataCount = 0; unsigned char stuffed_buffer[MAX_SIZE]; int i = START_FLAG; STOP = FALSE; while (STOP == FALSE) { unsigned char c = 0; //printf("start while \n"); if (read(fd, &c, 1)) { //printf("received a: %x\n",c); switch (i) { case START_FLAG: //printf("start\n"); if (c == FLAG) i = ADDR; break; case ADDR: //printf("adr\n"); if (c == ADDR_TRANS) { addr = c; i = CTRL; } else if (c != FLAG) { i = START_FLAG; } break; case CTRL: //printf("ctrl\n"); if (c == NEXT_CTRL_INDEX(linklayer.sequenceNumber) || c == CTRL_DISC) { ctrl = c; i = BCC1; } else if (c == FLAG) { i = ADDR; } else { i = FLAG; } break; case BCC1: //printf("bcc1\n"); ; int headerErrorProb = rand() % 100; if (headerErrorProb < linklayer.her) { i = START_FLAG; } else { if (c == (addr ^ ctrl)) { i = DATA; } else if (c == FLAG) { i = ADDR; } else { i = START_FLAG; } } break; case DATA: //printf("data\n"); if (c != FLAG) { stuffed_buffer[dataCount] = c; //printf("stuffed: %x\n",stuffed_buffer[dataCount]); dataCount++; } else { //printf("else\n"); if (ctrl == CTRL_DISC) { printf("send disc\n"); if (send_disc(fd, RECEIVER)) return -1; printf("rec ua\n"); if (rec_ua(fd, RECEIVER)) return -1; linklayer.openLink = 0; return DISCONECTED; } else { //printf("else data lenght\n"); unsigned int dataLength = 0; //printf("data count: %d",dataCount); if ((dataLength = byteDestuffing(stuffed_buffer, dataCount, buffer)) == -1) return -1; unsigned char bcc2_received = buffer[dataLength - 1]; //printf("bcc2 received: %x\n", bcc2_received); unsigned char bcc2 = 0; //printf("bcc2\n"); generate_bcc2(buffer, dataLength - 1, &bcc2); //printf("bcc generated: %x\n",bcc2); int frameErrorProb = rand() % 100; if (frameErrorProb < linklayer.fer) { printf("send rej\n"); send_rej(fd); i = START_FLAG; dataCount = 0; } else { //printf("else bcc2\n"); if (bcc2 == bcc2_received) { printf("same bcc2\n"); if (ctrl != NEXT_CTRL_INDEX(linklayer.sequenceNumber)) { printf("send rr1\n"); send_rr(fd); i = START_FLAG; dataCount = 0; } else { printf("send rr 2\n"); linklayer.sequenceNumber = NEXT_INDEX(linklayer.sequenceNumber); send_rr(fd); return (dataLength - 1); } } else { printf("not the same bcc2\n"); if (ctrl != NEXT_CTRL_INDEX(linklayer.sequenceNumber)) send_rr(fd); else send_rej(fd); i = START_FLAG; dataCount = 0; } } } } break; } } } printf("return\n"); return 0; }
int rec_ua(int fd, unsigned int flag) { setAlarm(); unsigned int addr = 0; unsigned int ctrl = 0; int i = START_FLAG; STOP = FALSE; while (STOP == FALSE) { unsigned char c = 0; if (alarmCount >= linklayer.numTransmissions) { printf("EXCEDED NUMBER OF TRIES!\n"); close_port_file(fd); return -1; } else if (alarmFlag == 1) { printf("RE-SEND UA!!!\n"); if (flag == SENDER) { send_set(fd); } else if (flag == RECEIVER) { send_disc(fd, flag); } alarmFlag = 0; alarm(linklayer.timeout); } if (read(fd, &c, 1)) { switch (i) { case START_FLAG: if (c == FLAG) i = ADDR; break; case ADDR: if ((flag == SENDER && c == ADDR_REC_RESP) || (flag == RECEIVER && c == ADDR_TRANS_RESP)) { addr = c; i = CTRL; } else if (c != FLAG) { i = START_FLAG; } break; case CTRL: if (c == CTRL_UA) { ctrl = c; i = BCC1; } else if (c == FLAG) { i = ADDR; } else { i = START_FLAG; } break; case BCC1: if (c == (addr ^ ctrl)) { i = END_FLAG; } else if (c == FLAG) { i = ADDR; } else { i = START_FLAG; } break; case END_FLAG: if (c == FLAG) { STOP = TRUE; } else { i = START_FLAG; } break; } } } return 0; }
static int std_rcv_pado(struct session* ses, struct pppoe_packet *p_in, struct pppoe_packet **p_out){ struct pppoe_tag *ac_name, *srv_name; char ac[1024], srv[1024]; if(ses->state != PADO_CODE ){ poe_error(ses,"Unexpected packet: %P",p_in); return 0; } if( verify_packet(ses, p_in) < 0) return 0; if (DEB_DISC2) poe_dbglog (ses,"PADO received: %P", p_in); memcpy(&ses->remote, &p_in->addr, sizeof(struct sockaddr_ll)); memcpy(&ses->curr_pkt.addr, &ses->remote , sizeof(struct sockaddr_ll)); ses->curr_pkt.hdr->code = PADR_CODE; /* The HOST_UNIQ has been verified already... there's no "if" about this */ /* if(ses->filt->htag) */ copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_HOST_UNIQ)); if (ses->filt->ntag) { ses->curr_pkt.tags[TAG_AC_NAME]=NULL; } ac_name = get_tag(p_in->hdr,PTT_AC_NAME); srv_name = get_tag(p_in->hdr,PTT_SRV_NAME); memset(ac, 0, sizeof(ac)); memset(srv, 0, sizeof(srv)); strncpy(ac, ac_name->tag_data, ntohs(ac_name->tag_len)); strncpy(srv, srv_name->tag_data, ntohs(srv_name->tag_len)); script_setenv("AC_NAME", ac, 1); script_setenv("SRV_NAME", srv, 1); if(ses->filt->stag) { ses->curr_pkt.tags[TAG_SRV_NAME]=NULL; } copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_SRV_NAME)); copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_AC_COOKIE)); copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_RELAY_SID)); ses->state = PADS_CODE; ses->retransmits = 0; send_disc(ses, &ses->curr_pkt); (*p_out) = &ses->curr_pkt; if (DEB_DISC) poe_dbglog (ses,"Sent PADR: %P", *p_out); if (ses->np) return 1; return 0; }
/************************************************************************* * * Make a connection -- behaviour depends on callbacks specified in "ses" * *************************************************************************/ int session_connect(struct session *ses) { int pkt_size=0; int ret_pkt_size=0; struct pppoe_tag *tags = NULL; struct pppoe_packet *p_out=NULL; struct pppoe_packet rcv_packet; int ret; int i=0; #ifdef AUTODISCONN if ((redisconn) || ((!redisconn)&&(strlen(oldsession)))) { while (i++ < 2) { usleep(300000); session_disconnect_pppoe(ses); } usleep(100000); } #endif if(ses->init_disc){ ret = (*ses->init_disc)(ses, NULL, &p_out); if( ret != 0 ) return ret; } /* main discovery loop */ while(ses->retransmits < ses->retries || ses->retries==-1 ){ fd_set in; struct timeval tv; FD_ZERO(&in); FD_SET(disc_sock,&in); if(ses->retransmits>=0){ ++ses->retransmits; //tv.tv_sec = 6; tv.tv_sec = 1 << ses->retransmits; if (tv.tv_sec > 3) tv.tv_sec = 3; tv.tv_usec = 0; ret = select(disc_sock+1, &in, NULL, NULL, &tv); }else{ ret = select(disc_sock+1, &in, NULL, NULL, NULL); } if( ret == 0 ){ if( DEB_DISC ){ poe_dbglog(ses, "Re-sending ..."); } if( ses->timeout ){ ret = (*ses->timeout)(ses, NULL, &p_out); if( ret != 0 ) return ret; }else if(p_out){ send_disc(ses,p_out); } continue; } ret = recv_disc(ses, &rcv_packet); /* Should differentiate between system errors and bad packets and the like... */ if( ret < 0 && errno != EINTR){ return -1; } switch (rcv_packet.hdr->code) { case PADI_CODE: { if(ses->rcv_padi){ ret = (*ses->rcv_padi)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } } break; } case PADO_CODE: /* wait for PADO */ { if(ses->rcv_pado){ ret = (*ses->rcv_pado)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } } break; } case PADR_CODE: { if(ses->rcv_padr){ ret = (*ses->rcv_padr)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } } break; } case PADS_CODE: { if(ses->rcv_pads){ ret = (*ses->rcv_pads)(ses,&rcv_packet,&p_out); memcpy(&old_ses, ses, sizeof(struct session)); if( ret != 0){ return ret; } } break; } case PADT_CODE: { if( rcv_packet.hdr->sid != ses->sp.sa_addr.pppoe.sid ){ --ses->retransmits; continue; } if(ses->rcv_padt){ ret = (*ses->rcv_padt)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } }else{ poe_error (ses,"connection terminated"); return (-1); } break; } default: poe_error(ses,"invalid packet %P",&rcv_packet); } } return (0); }
/************************************************************************* * * Make a connection -- behaviour depends on callbacks specified in "ses" * *************************************************************************/ int session_connect(struct session *ses) { struct pppoe_packet *p_out=NULL; struct pppoe_packet rcv_packet; int ret; if(ses->init_disc){ ret = (*ses->init_disc)(ses, NULL, &p_out); if( ret != 0 ) return ret; } /* main discovery loop */ while(ses->retransmits <= ses->retries || ses->retries==-1 ){ fd_set in; struct timeval tv; FD_ZERO(&in); FD_SET(disc_sock,&in); if(ses->retransmits>=0){ ++ses->retransmits; tv.tv_sec = 1 << ses->retransmits; tv.tv_usec = 0; ret = select(disc_sock+1, &in, NULL, NULL, &tv); }else{ ret = select(disc_sock+1, &in, NULL, NULL, NULL); } if( ret == 0 ){ if((DEB_DISC) && (ses->retransmits <= ses->retries) ){ poe_dbglog(ses, "Re-sending ..."); } if( ses->timeout ){ ret = (*ses->timeout)(ses, NULL, &p_out); if ( ret != 0 ) { poe_info(ses, "returning - %d", ret); return ret; } } else if (p_out) { send_disc(ses,p_out); } continue; } ret = recv_disc(ses, &rcv_packet); /* Should differentiate between system errors and bad packets and the like... */ if( ret < 0 && errno != EINTR){ poe_info(ses, "couldn't rcv packet"); return -1; } if (DEB_DISC2) syslog(LOG_ERR, "Recieved packet=%x\n", rcv_packet.hdr->code); switch (rcv_packet.hdr->code) { case PADI_CODE: { if(ses->rcv_padi){ ret = (*ses->rcv_padi)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } } break; } case PADO_CODE: /* wait for PADO */ { if(ses->rcv_pado){ ret = (*ses->rcv_pado)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } } break; } case PADR_CODE: { if(ses->rcv_padr){ ret = (*ses->rcv_padr)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } } break; } case PADS_CODE: { if(ses->rcv_pads){ ret = (*ses->rcv_pads)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } } break; } case PADT_CODE: { if( rcv_packet.hdr->sid != ses->sp.sa_addr.pppoe.sid ){ --ses->retransmits; continue; } if(ses->rcv_padt){ ret = (*ses->rcv_padt)(ses,&rcv_packet,&p_out); if( ret != 0){ return ret; } }else{ poe_error (ses,"connection terminated"); return (-1); } break; } case 0: /*receiving normal seesion frames*/ { poe_error(ses, "Already in data stream, sending PADT %P\n", &rcv_packet); if (ses->pppoe_kill) { memcpy(&ses->remote,&rcv_packet.addr, sizeof(struct sockaddr_ll)); ses->sp.sa_addr.pppoe.sid = rcv_packet.hdr->sid; session_disconnect(ses); continue; } return (-1); } default: poe_error(ses,"invalid packet %P",&rcv_packet); return (-1); } } if (ses->retransmits > ses->retries) { errno = 62; return -1; } return (0); }
/** add by [email protected] call it before do connection */ static void pre_connect_pppoe_ses(void) { //add by [email protected] unsigned int mac[6]; unsigned int sID; FILE* sfile; int n; //disconnect before. added by [email protected] if (access (SESSION_FILE, F_OK) != 0) { return; } client_init_ses(ses,devnam); strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); sfile = fopen(SESSION_FILE, "r"); n = fscanf(sfile, "%u:%2x:%2x:%2x:%2x:%2x:%2x", &sID, &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); fclose(sfile); if (n < 7) { poe_info(ses, "Read PPPoE Session error!"); return; } struct pppoe_packet padt; memset(&padt, 0, sizeof(struct pppoe_packet)); ses->remote.sll_addr[0] = mac[0]; ses->remote.sll_addr[1] = mac[1]; ses->remote.sll_addr[2] = mac[2]; ses->remote.sll_addr[3] = mac[3]; ses->remote.sll_addr[4] = mac[4]; ses->remote.sll_addr[5] = mac[5]; memcpy(&padt.addr, &ses->remote, sizeof(struct sockaddr_ll)); padt.hdr = (struct pppoe_hdr*) ses->curr_pkt.buf; padt.hdr->ver = 1; padt.hdr->type = 1; padt.hdr->code = PADT_CODE; padt.hdr->sid = htons(sID); send_disc(ses, &padt); ses->sp.sa_addr.pppoe.sid = 0; connect(ses->fd, (struct sockaddr*)&ses->sp, sizeof(struct sockaddr_pppox)); usleep(2000000); /** int ret; warn("Doing pre-disconnect"); session_disconnect(ses); ses->sp.sa_addr.pppoe.sid = 0; ret = connect(ses->fd, (struct sockaddr*)&ses->sp, sizeof(struct sockaddr_pppox)); */ }