static void init_device_pppoe(void) { struct filter *filt; unsigned int size=0; ses=(void *)malloc(sizeof(struct session)); if(!ses){ fatal("No memory for new PPPoE session"); } memset(ses,0,sizeof(struct session)); if ((ses->filt=malloc(sizeof(struct filter))) == NULL) { poe_error (ses,"failed to malloc for Filter "); poe_die (-1); } filt=ses->filt; /* makes the code more readable */ memset(filt,0,sizeof(struct filter)); if (pppoe_ac_name !=NULL) { if (strlen (pppoe_ac_name) > 255) { poe_error (ses," AC name too long (maximum allowed 256 chars)"); poe_die(-1); } ses->filt->ntag = make_filter_tag(PTT_AC_NAME, strlen(pppoe_ac_name), pppoe_ac_name); if ( ses->filt->ntag== NULL) { poe_error (ses,"failed to malloc for AC name"); poe_die(-1); } } if (pppoe_srv_name !=NULL) { if (strlen (pppoe_srv_name) > 255) { poe_error (ses," Service name too long (maximum allowed 256 chars)"); poe_die(-1); } ses->filt->stag = make_filter_tag(PTT_SRV_NAME, strlen(pppoe_srv_name), pppoe_srv_name); if ( ses->filt->stag == NULL) { poe_error (ses,"failed to malloc for service name"); poe_die(-1); } }
static int std_rcv_pads(struct session* ses, struct pppoe_packet *p_in, struct pppoe_packet **p_out){ if(ses->state != PADS_CODE ){ poe_error(ses,"Unexpected packet: %P",p_in); return 0; } if( verify_packet(ses, p_in) < 0) return 0; if (DEB_DISC) poe_dbglog (ses,"PADS received: %P", p_in); ses->sp.sa_family = AF_PPPOX; ses->sp.sa_protocol = PX_PROTO_OE; ses->sp.sa_addr.pppoe.sid = p_in->hdr->sid; memcpy(ses->sp.sa_addr.pppoe.dev,ses->name, IFNAMSIZ); memcpy(ses->sp.sa_addr.pppoe.remote, p_in->addr.sll_addr, ETH_ALEN); if (DEB_DISC) poe_dbglog (ses,"Got connection: %x %s <--->%E", ses->sp.sa_addr.pppoe.sid, ses->sp.sa_addr.pppoe.dev, ses->sp.sa_addr.pppoe.remote); return 1; }
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 connect_pppoe_ses(void) { int err=-1; if( pppoe_server == 1 ){ srv_init_ses(ses,devnam); }else{ client_init_ses(ses,devnam); } #if 0 ses->np=1; /* jamal debug the discovery portion */ #endif strcpy(ppp_devnam, devnam); err= session_connect ( ses ); if(err < 0){ if (!kill_link) poe_error(ses,"Failed to negotiate PPPoE connection: %d - %m", errno,errno); return -1; } poe_info(ses,"Connecting PPPoE socket: %E %04x %s %p", ses->sp.sa_addr.pppoe.remote, ses->sp.sa_addr.pppoe.sid, ses->sp.sa_addr.pppoe.dev,ses); err = connect(ses->fd, (struct sockaddr*)&ses->sp, sizeof(struct sockaddr_pppox)); if( err < 0 ){ poe_fatal(ses,"Failed to connect PPPoE socket: %d %m",errno,errno); return err; } #if 0 if (ses->np) fatal("discovery complete\n"); #endif /* Once the logging is fixed, print a message here indicating connection parameters */ return ses->fd; }
int get_args (int argc, char **argv,struct session *sess) { struct filter *filt; struct host_tag *tg; int opt; sess->opt_debug = 0; DEB_DISC=0; DEB_DISC2=0; sess->log_to_fd = 1; sess->np = 0; sess->opt_daemonize = 0; sess->log_to_fd = fileno (stdout); /* defaults to eth0 */ strcpy (sess->name, "eth0"); if ((sess->filt=malloc(sizeof(struct filter))) == NULL) { poe_error (sess,"failed to malloc for Filter "); poe_die (-1); } filt=sess->filt; /* makes the code more readable */ memset(filt,0,sizeof(struct filter)); filt->num_restart=1; /* set default filters; move this to routine */ /* parse options */ while ((opt = getopt (argc, argv, "A:C:E:d:DR:I:F:L:V:P:SN:GH")) != -1) switch (opt) { case 'R': /* sets number of retries */ filt->num_restart = strtol (optarg, (char **) NULL, 10); filt->num_restart += 1; break; case 'I': /* sets interface */ if (strlen (optarg) >= IFNAMSIZ) { poe_error (sess,"interface name cannot exceed %d characters", IFNAMSIZ - 1); return (-1); } strncpy (sess->name, optarg, strlen(optarg)+1); break; case 'C': /* name of the file in /etc/ppp/peers */ if (NULL != filt->fname) { poe_error (sess,"-F can not be used with -C"); return (-1); } if (strlen(optarg) > MAX_FNAME) { poe_error (sess,"file name cannot exceed %d characters", MAX_FNAME - 1); return (-1); } filt->fname=malloc(strlen(optarg)); strncpy (filt->fname, optarg, strlen(optarg)); filt->peermode=1; break; case 'F': /* sets the options file */ if (NULL != filt->fname) { poe_error (sess,"-F can not be used with -C"); return (-1); } if (strlen(optarg) > MAX_FNAME) { poe_error (sess,"file name cannot exceed %d characters", MAX_FNAME - 1); return (-1); } filt->fname=malloc(strlen(optarg)+1); strncpy (filt->fname, optarg, strlen(optarg)+1); poe_info (sess,"selected %s as filename\n",filt->fname); break; case 'D': /* don't daemonize */ sess->opt_daemonize = 1; detached=0; break; case 'd': /* debug level */ sess->opt_debug = strtol (optarg, (char **) NULL, 10); if (sess->opt_debug & 0x0002) DEB_DISC=1; if (sess->opt_debug & 0x0004) DEB_DISC2=1; break; case 'P': /* sets the pppd binary */ if (strlen(optarg) > MAX_FNAME) { poe_error (sess,"pppd binary cant exceed %d characters", MAX_FNAME - 1); return (-1); } filt->pppd=malloc(strlen(optarg)); strncpy (filt->pppd, optarg, strlen(optarg)); break; case 'H': sess->np = 2; break; case 'G': sess->np = 1; break; case 'V': /* version */ fprintf (stdout,"pppoe version %d.%d build %d", VERSION_MAJOR, VERSION_MINOR, VERSION_DATE); return (0); case 'S': /* server mode */ sess->type = SESSION_SERVER; break; case 'A': /* AC override */ poe_info (sess,"AC name override to %s", optarg); if (strlen (optarg) > 255) { poe_error (sess," AC name too long (maximum allowed 256 chars)"); poe_die(-1); } if ((sess->filt->ntag= malloc (sizeof (struct pppoe_tag) + strlen (optarg)))== NULL) { poe_error (sess,"failed to malloc for AC name"); poe_die(-1); } sess->filt->ntag->tag_len=htons(strlen(optarg)); sess->filt->ntag->tag_type=PTT_AC_NAME; poe_error (sess," pppoe_ac_name: AC name Override %p\n", sess->filt->ntag); strcpy(sess->filt->ntag->tag_data,optarg); break; case 'E': /* AC service name override */ poe_info (sess,"AC service name override to %s", optarg); if (strlen (optarg) > 255) { poe_error (sess," Service name too long (maximum allowed 256 chars)"); poe_die(-1); } if ((filt->stag = malloc (strlen (optarg) + sizeof (struct pppoe_tag))) == NULL) { poe_error (sess,"failed to malloc for service name: %m"); return (-1); } filt->stag->tag_len = htons (strlen (optarg)); filt->stag->tag_type = PTT_SRV_NAME; strcpy ((char *) (filt->stag->tag_data), optarg); break; default: poe_error (sess,"Unknown option '%c'", optopt); print_help (); return (-1); } return (1); }
/************************************************************************* * * 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); }
/************************************************************************* * * Construct and send a discovery message. * ************************************************************************/ int send_disc(struct session *ses, struct pppoe_packet *p) { char buf[MAX_PAYLOAD + sizeof(struct pppoe_hdr)]; int data_len = sizeof(struct pppoe_hdr); struct pppoe_hdr *ph = NULL; struct pppoe_tag *tag = NULL; int i, err = 0; int got_host_uniq = 0; int got_srv_name = 0; int got_ac_name = 0; for (i = 0; i < MAX_TAGS; i++) { if (!p->tags[i]) continue; got_host_uniq |= (p->tags[i]->tag_type == PTT_HOST_UNIQ); /* Relay identifiers qualify as HOST_UNIQ's: we need HOST_UNIQ to uniquely identify the packet, PTT_RELAY_SID is sufficient for us for outgoing packets */ got_host_uniq |= (p->tags[i]->tag_type == PTT_RELAY_SID); got_srv_name |= (p->tags[i]->tag_type == PTT_SRV_NAME); got_ac_name |= (p->tags[i]->tag_type == PTT_AC_NAME); data_len += (ntohs(p->tags[i]->tag_len) + sizeof(struct pppoe_tag)); } ph = (struct pppoe_hdr *) buf; memcpy(ph, p->hdr, sizeof(struct pppoe_hdr)); ph->length = __constant_htons(0); /* if no HOST_UNIQ tags --- add one with process id */ if (!got_host_uniq){ data_len += (sizeof(struct pppoe_tag) + sizeof(struct session *)); tag = next_tag(ph); tag->tag_type = PTT_HOST_UNIQ; tag->tag_len = htons(sizeof(struct session *)); memcpy(tag->tag_data, &ses, sizeof(struct session *)); add_tag(ph, tag); } if( !got_srv_name ){ data_len += sizeof(struct pppoe_tag); tag = next_tag(ph); tag->tag_type = PTT_SRV_NAME; tag->tag_len = 0; add_tag(ph, tag); } if(!got_ac_name && ph->code==PADO_CODE){ data_len += sizeof(struct pppoe_tag); tag = next_tag(ph); tag->tag_type = PTT_AC_NAME; tag->tag_len = 0; add_tag(ph, tag); } for (i = 0; i < MAX_TAGS; i++) { if (!p->tags[i]) continue; tag = next_tag(ph); memcpy(tag, p->tags[i], sizeof(struct pppoe_tag) + ntohs(p->tags[i]->tag_len)); add_tag(ph, tag); } /* Now fixup the packet struct to make sure all of its pointers are self-contained */ memcpy( p->hdr , ph, data_len ); extract_tags( p->hdr, p->tags); err = sendto(disc_sock, buf, data_len, 0, (struct sockaddr*) &p->addr, sizeof(struct sockaddr_ll)); if(err < 0) poe_error(ses,"sendto returned: %m\n"); return err; }
static void init_device_pppoe(void) { struct filter *filt; // unsigned int size=0; ses=(void *)malloc(sizeof(struct session)); if(!ses){ fatal("No memory for new PPPoE session"); } memset(ses,0,sizeof(struct session)); if ((ses->filt=malloc(sizeof(struct filter))) == NULL) { poe_error (ses,"failed to malloc for Filter "); poe_die (-1); } filt=ses->filt; /* makes the code more readable */ memset(filt,0,sizeof(struct filter)); #ifdef AEI_VDSL_CUSTOMER_NCS if (strlen(pppoe_ac_name)) { #else if (pppoe_ac_name !=NULL) { #endif if (strlen (pppoe_ac_name) > 255) { poe_error (ses," AC name too long (maximum allowed 256 chars)"); poe_die(-1); } ses->filt->ntag = make_filter_tag(PTT_AC_NAME, strlen(pppoe_ac_name), pppoe_ac_name); if ( ses->filt->ntag== NULL) { poe_error (ses,"failed to malloc for AC name"); poe_die(-1); } } // cwu if (strlen(pppoe_srv_name)) { if (strlen (pppoe_srv_name) > 255) { poe_error (ses," Service name too long (maximum allowed 256 chars)"); poe_die(-1); } ses->filt->stag = make_filter_tag(PTT_SRV_NAME, strlen(pppoe_srv_name), pppoe_srv_name); if ( ses->filt->stag == NULL) { poe_error (ses,"failed to malloc for service name"); poe_die(-1); } } if (hostuniq) { ses->filt->htag = make_filter_tag(PTT_HOST_UNIQ, strlen(hostuniq), hostuniq); if ( ses->filt->htag == NULL) { poe_error (ses,"failed to malloc for Uniq Host Id "); poe_die(-1); } } if (retries) { ses->retries=retries; } memcpy( ses->name, devnam, IFNAMSIZ); ses->opt_debug=1; } static void pppoe_extra_options() { // int ret; char buf[256]; snprintf(buf, 256, _PATH_ETHOPT "%s",devnam); if(!options_from_file(buf, 0, 0, 1)) exit(EXIT_OPTION_ERROR); }
static void init_device_pppoe(void) { struct filter *filt; unsigned int size=0; ses=(void *)malloc(sizeof(struct session)); if(!ses){ fatal("No memory for new PPPoE session"); } memset(ses,0,sizeof(struct session)); ses->log_to_fd = -1; if ((ses->filt=malloc(sizeof(struct filter))) == NULL) { poe_error (ses,"failed to malloc for Filter "); poe_die (-1); } filt=ses->filt; /* makes the code more readable */ memset(filt,0,sizeof(struct filter)); if (pppoe_ac_name !=NULL) { if (strlen (pppoe_ac_name) > 255) { poe_error (ses," AC name too long (maximum allowed 256 chars)"); poe_die(-1); } ses->filt->ntag = make_filter_tag(PTT_AC_NAME, strlen(pppoe_ac_name), pppoe_ac_name); if ( ses->filt->ntag== NULL) { poe_error (ses,"failed to malloc for AC name"); poe_die(-1); } } if (pppoe_srv_name !=NULL) { if (strlen (pppoe_srv_name) > 255) { poe_error (ses," Service name too long (maximum allowed 256 chars)"); poe_die(-1); } ses->filt->stag = make_filter_tag(PTT_SRV_NAME, strlen(pppoe_srv_name), pppoe_srv_name); if ( ses->filt->stag == NULL) { poe_error (ses,"failed to malloc for service name"); poe_die(-1); } } if (hostuniq) { ses->filt->htag = make_filter_tag(PTT_HOST_UNIQ, strlen(hostuniq), hostuniq); if ( ses->filt->htag == NULL) { poe_error (ses,"failed to malloc for Uniq Host Id "); poe_die(-1); } } if (retries) { ses->retries=retries; } memcpy( ses->name, devnam, IFNAMSIZ); ses->opt_debug=1; }
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; }
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); }
static void init_device_pppoe(void) { struct filter *filt; unsigned int size=0; ses=(void *)malloc(sizeof(struct session)); if(!ses){ fatal("No memory for new PPPoE session"); } memset(ses,0,sizeof(struct session)); ses->log_to_fd = -1; if ((ses->filt=malloc(sizeof(struct filter))) == NULL) { poe_error (ses,"failed to malloc for Filter "); poe_die (-1); } filt=ses->filt; /* makes the code more readable */ memset(filt,0,sizeof(struct filter)); if (pppoe_ac_name !=NULL) { if (strlen (pppoe_ac_name) > 255) { poe_error (ses," AC name too long (maximum allowed 256 chars)"); poe_die(-1); } ses->filt->ntag = make_filter_tag(PTT_AC_NAME, strlen(pppoe_ac_name), pppoe_ac_name); if ( ses->filt->ntag== NULL) { poe_error (ses,"failed to malloc for AC name"); poe_die(-1); } } if (pppoe_srv_name !=NULL) { if (strlen (pppoe_srv_name) > 255) { poe_error (ses," Service name too long (maximum allowed 256 chars)"); poe_die(-1); } ses->filt->stag = make_filter_tag(PTT_SRV_NAME, strlen(pppoe_srv_name), pppoe_srv_name); if ( ses->filt->stag == NULL) { poe_error (ses,"failed to malloc for service name"); poe_die(-1); } } if (hostuniq) { ses->filt->htag = make_filter_tag(PTT_HOST_UNIQ, strlen(hostuniq), hostuniq); if ( ses->filt->htag == NULL) { poe_error (ses,"failed to malloc for Uniq Host Id "); poe_die(-1); } } if (retries > 0) { ses->retries=retries; poe_info(ses, "PPPOE: Setting retries to %d", ses->retries); } else if (retries == 0) { poe_info(ses, "PPPOE: Will retry forever"); ses->retries=-1; } else { ses->retries=CONFIG_USER_PPPD_PPPOE_RETRIES; poe_info(ses, "PPPOE: Setting retries to %d", ses->retries); } if (pppoe_kill) { ses->pppoe_kill = pppoe_kill; poe_info(ses, "Will send PADT if already in data stream"); } memcpy( ses->name, devnam, IFNAMSIZ); ses->opt_debug=1; }