/************************************************************************* * * Verify that a packet has a tag containint a specific value * ************************************************************************/ static int verify_tag(struct session* ses, struct pppoe_packet* p, unsigned short id, char* data, int data_len) { int len; struct pppoe_tag *pt = p->tags[id]; if( !pt ){ poe_info(ses,"Missing tag %d. Expected %s\n", id,data); return 0; } len = ntohs(pt->tag_len); if(len != data_len){ poe_info(ses,"Length mismatch on tag %d: expect: %d got: %d\n", id, data_len, len); return 0; } if( 0!=memcmp(pt->tag_data,data,data_len)){ poe_info(ses,"Tag data mismatch on tag %d: expect: %s vs %s\n", id, data,pt->tag_data); return 0; } return 1; }
/************************************************************************* * * Verify that a packet is legal * *************************************************************************/ int verify_packet( struct session *ses, struct pppoe_packet *p){ struct session * hu_val; /* This code here should do all of the error checking and validation on the incoming packet */ /* If we receive any error tags, abort */ #define CHECK_TAG(name, val) \ if((NULL==p->tags[name])== val){ \ poe_error(ses,"Tag error: " #name ); \ return -1; \ } /* If packet is not directed to our MAC address, forget it */ if (ses->state == PADS_CODE) { if (memcmp(p->addr.sll_addr, ses->remote.sll_addr, ETH_ALEN)) { poe_info(ses,"ETH_DEST mismatch: %E %E \n",p->addr.sll_addr, ses->remote.sll_addr); return -1; } } CHECK_TAG(TAG_SRV_ERR,0); CHECK_TAG(TAG_SYS_ERR,0); CHECK_TAG(TAG_GEN_ERR,0); /* A HOST_UNIQ must be present */ CHECK_TAG(TAG_HOST_UNIQ,1); hu_val = *TAG_DATA(struct session* ,p->tags[TAG_HOST_UNIQ]); if( hu_val != ses ){ poe_info(ses,"HOST_UNIQ mismatch: %08x %i\n",(int)hu_val,getpid()); return -1; } if(ses->filt->htag && !verify_tag(ses,p,TAG_HOST_UNIQ,ses->filt->htag->tag_data,(int)ntohs(ses->filt->htag->tag_len))) { poe_info(ses,"HOST_UNIQ failure"); return -1; } if(ses->filt->ntag && ses->state == PADO_CODE && !verify_tag(ses,p,TAG_AC_NAME,ses->filt->ntag->tag_data,(int)ntohs(ses->filt->ntag->tag_len))){ poe_info(ses,"AC_NAME failure"); return -1; } if(ses->filt->stag && !verify_tag(ses,p,TAG_SRV_NAME,ses->filt->stag->tag_data,(int)ntohs(ses->filt->stag->tag_len))){ poe_info(ses,"SRV_NAME failure"); return -1; } return 0; }
/************************************************************************* * * Verify that a packet is legal * *************************************************************************/ int verify_packet( struct session *ses, struct pppoe_packet *p){ struct session * hu_val; /* This code here should do all of the error checking and validation on the incoming packet */ /* If we receive any error tags, abort */ #define CHECK_TAG(name, val) \ if((NULL==p->tags[name])== val){ \ char format[sizeof("Tag error: ") + sizeof (#name) + \ sizeof("- %.65535s")]; \ sprintf(format, "Tag error: %s - %%.%ds", #name,\ p->tags[name]->tag_len);\ poe_error(ses,format,p->tags[name]->tag_data);\ return -1; \ } /* This causes an unaligned access here */ CHECK_TAG(TAG_SRV_ERR,0); CHECK_TAG(TAG_SYS_ERR,0); CHECK_TAG(TAG_GEN_ERR,0); /* A HOST_UNIQ must be present */ CHECK_TAG(TAG_HOST_UNIQ,1); hu_val = *TAG_DATA(struct session* ,p->tags[TAG_HOST_UNIQ]); if( hu_val != ses ){ poe_info(ses,"HOST_UNIQ mismatch: %08x %i\n",(int)hu_val,getpid()); return -1; } if(ses->filt->htag && !verify_tag(ses,p,TAG_HOST_UNIQ,ses->filt->htag->tag_data,(int)ntohs(ses->filt->htag->tag_len))) { poe_info(ses, "HOST_NAME failure"); return -1; } if(ses->filt->ntag && !verify_tag(ses,p,TAG_AC_NAME,ses->filt->ntag->tag_data,(int)ntohs(ses->filt->ntag->tag_len))){ poe_info(ses,"AC_NAME failure"); return -1; } if(ses->filt->stag && !verify_tag(ses,p,TAG_SRV_NAME,ses->filt->stag->tag_data,(int)ntohs(ses->filt->stag->tag_len))){ poe_info(ses,"SRV_NAME failure"); return -1; } return 1; }
static int connect_pppoe_ses(void) { int i,err=-1; if( pppoe_server == 1 ){ srv_init_ses(ses,devnam); }else{ client_init_ses(ses,devnam); } strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); err= session_connect ( ses ); if(err < 0){ poe_fatal(ses,"Failed to negotiate PPPoE connection: %d %m",errno,errno); } 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; } /* Once the logging is fixed, print a message here indicating connection parameters */ return ses->fd; }
static void post_disconnect_pppoe_ses(void) { if (access (SESSION_FILE, F_OK) == 0) { poe_info(ses, "Remove PPPoE Session file!"); remove(SESSION_FILE); } }
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; }
/************************************************************************* * * Verify that a packet is legal * *************************************************************************/ int verify_packet( struct session *ses, struct pppoe_packet *p){ struct session * hu_val; /* This code here should do all of the error checking and validation on the incoming packet */ /* If we receive any error tags, abort */ #define CHECK_TAG(name, val) \ if((NULL==p->tags[name])== val){ \ poe_error(ses,"Tag error: " #name ); \ return -1; \ } CHECK_TAG(TAG_SRV_ERR,0); CHECK_TAG(TAG_SYS_ERR,0); CHECK_TAG(TAG_GEN_ERR,0); /* A HOST_UNIQ must be present */ CHECK_TAG(TAG_HOST_UNIQ,1); hu_val = *TAG_DATA(struct session* ,p->tags[TAG_HOST_UNIQ]); if( hu_val != ses ){ poe_info(ses,"HOST_UNIQ mismatch: %08x %i\n",(int)hu_val,getpid()); return -1; } if(ses->filt->htag && !verify_tag(ses,p,TAG_HOST_UNIQ,ses->filt->htag->tag_data,(int)ntohs(ses->filt->htag->tag_len))) return -1; else poe_info(ses,"HOST_UNIQ successful match\n"); if(ses->filt->ntag && !verify_tag(ses,p,TAG_AC_NAME,ses->filt->ntag->tag_data,(int)ntohs(ses->filt->ntag->tag_len))){ poe_info(ses,"AC_NAME failure"); return -1; } if(ses->filt->stag && !verify_tag(ses,p,TAG_SRV_NAME,ses->filt->stag->tag_data,(int)ntohs(ses->filt->stag->tag_len))){ poe_info(ses,"SRV_NAME failure"); return -1; } }
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; }
static int std_rcv_pads(struct session* ses, struct pppoe_packet *p_in, struct pppoe_packet **p_out){ if( verify_packet(ses, p_in) < 0) return -1; if (DEB_DISC) poe_dbglog (ses,"Got connection: %x", ntohs(p_in->hdr->sid)); poe_info (ses,"Got connection: %x", ntohs(p_in->hdr->sid)); 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); create_msg(BCM_PPPOE_CLIENT_STATE_CONFIRMED); syslog(LOG_CRIT,"PPP session established.\n"); return 1; }
static void post_connect_pppoe_ses(void) { FILE* sfile; /** Save session id here. added by [email protected] */ sfile = fopen(SESSION_FILE, "w"); if (sfile) { poe_info(ses, "Save PPPoE Session ID & MAC!"); fprintf(sfile,"%u:%02x:%02x:%02x:%02x:%02x:%02x\n", ntohs(ses->sp.sa_addr.pppoe.sid), ses->sp.sa_addr.pppoe.remote[0], ses->sp.sa_addr.pppoe.remote[1], ses->sp.sa_addr.pppoe.remote[2], ses->sp.sa_addr.pppoe.remote[3], ses->sp.sa_addr.pppoe.remote[4], ses->sp.sa_addr.pppoe.remote[5]); fclose(sfile); } }
static int relay_rcv_pads(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]; struct sockaddr_pppox sp_cl= { AF_PPPOX, PX_PROTO_OE, {{ p_in->hdr->sid, {0,},{0,}}}}; struct sockaddr_pppox sp_sv= { AF_PPPOX, PX_PROTO_OE, {{ p_in->hdr->sid, {0,},{0,}}}}; int ret; if( !tag ) return 0; pc = get_con(ntohs(tag->tag_len),tag->tag_data); if( !pc ) return 0; if(!pc->connected){ pc->sv_sock = socket( AF_PPPOX, SOCK_DGRAM, PX_PROTO_OE); if( pc->sv_sock < 0){ poe_fatal(ses,"Cannot open PPPoE socket: %i",errno); } pc->cl_sock = socket( AF_PPPOX, SOCK_DGRAM, PX_PROTO_OE); if( pc->cl_sock < 0){ poe_fatal(ses,"Cannot open PPPoE socket: %i",errno); } memcpy( sp_sv.sa_addr.pppoe.dev, ses->fwd_name, IFNAMSIZ); memcpy( sp_sv.sa_addr.pppoe.remote, pc->server, ETH_ALEN); ret = connect( pc->sv_sock, (struct sockaddr*)&sp_sv, sizeof(struct sockaddr_pppox)); if( ret < 0){ poe_fatal(ses,"Cannot connect PPPoE socket: %i",errno); } memcpy( sp_cl.sa_addr.pppoe.dev, ses->name, IFNAMSIZ); memcpy( sp_cl.sa_addr.pppoe.remote, pc->client, ETH_ALEN); ret = connect( pc->cl_sock, (struct sockaddr*)&sp_cl, sizeof(struct sockaddr_pppox)); if( ret < 0){ poe_fatal(ses,"Cannot connect PPPoE socket: %i",errno); } ret = ioctl( pc->sv_sock, PPPOEIOCSFWD, &sp_cl); if( ret < 0){ poe_fatal(ses,"Cannot set forwarding on PPPoE socket: %i",errno); } ret = ioctl( pc->cl_sock, PPPOEIOCSFWD, &sp_sv); if( ret < 0){ poe_fatal(ses,"Cannot set forwarding on PPPoE socket: %i",errno); } pc->connected = 1; } poe_info(ses,"PPPoE relay for %E established to %E (sid=%04x)\n", pc->client,pc->server, p_in->hdr->sid); return relay_rcv_pkt(ses,p_in,p_out); }
/************************************************************************* * * 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; }
/** 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)); */ }
int main(int argc, char** argv){ int ret; struct filter *filt; struct session *ses = (struct session *)malloc(sizeof(struct session)); char buf[256]; ses=(void *)malloc(sizeof(struct session)); if(!ses){ return -1; } memset(ses,0,sizeof(struct session)); openlog ("pppoed", LOG_PID | LOG_NDELAY, LOG_PPPOE); setlogmask (LOG_UPTO (ses->opt_debug ? LOG_DEBUG : LOG_INFO)); if ((get_args (argc,(char **) argv,ses)) <1) poe_die(-1); filt=ses->filt; /* makes the code more readable */ if (!ses->np) { poe_create_pidfile (ses); // signal (SIGINT, &sigproc); // signal (SIGTERM, &sigproc); signal (SIGCHLD, &sigchild); } if(ses->type == SESSION_CLIENT){ poe_info(ses,"calling client_init_ses\n"); ret = client_init_ses(ses,ses->name); if( ret < 0 ){ return -1; } while (ses->filt->num_restart > 0) { poe_info(ses,"Restart number %d ",ses->filt->num_restart); ppp_connect (ses); ses->filt->num_restart--; } }else if( ses->type == SESSION_SERVER ){ poe_info(ses,"calling srv_init_ses\n"); ret = srv_init_ses(ses,ses->name); if( ret < 0 ){ return -1; } ret = 1; while(ret>=0) ret = ppp_connect(ses); } poe_info(ses,"ppp_connect came back! %d",ret); exit(0); }
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); }
int client_init_ses (struct session *ses, char* devnam) { int i=0; int retval; char dev[IFNAMSIZ+1]; int addr[ETH_ALEN]; int sid; /* do error checks here; session name etc are valid */ // poe_info (ses,"init_ses: creating socket"); /* Make socket if necessary */ if( disc_sock < 0 ){ disc_sock = socket(PF_PACKET, SOCK_DGRAM, 0); if( disc_sock < 0 ){ poe_fatal(ses, "Cannot create PF_PACKET socket for PPPoE discovery\n"); } } /* Create socket for session frame detection */ if (ses_sock < 0) { ses_sock = socket(PF_PACKET, SOCK_DGRAM, 0); if (ses_sock < 0) { poe_info(ses, "Couldn't create session frame detection socket"); } } /* Check for long format */ retval =sscanf(devnam, FMTSTRING(IFNAMSIZ),addr, addr+1, addr+2, addr+3, addr+4, addr+5,&sid,dev); if( retval != 8 ){ /* Verify the device name , construct ses->local */ retval = get_sockaddr_ll(devnam,&ses->local,0); if (retval < 0) poe_fatal(ses, "client_init_ses: " "Cannot create PF_PACKET socket for PPPoE discovery\n"); ses->state = PADO_CODE; memcpy(&ses->remote, &ses->local, sizeof(struct sockaddr_ll) ); memset( ses->remote.sll_addr, 0xff, ETH_ALEN); }else{ /* long form parsed */ /* Verify the device name , construct ses->local */ retval = get_sockaddr_ll(dev,&ses->local,0); if (retval < 0) poe_fatal(ses,"client_init_ses(2): " "Cannot create PF_PACKET socket for PPPoE discovery\n"); ses->state = PADS_CODE; ses->sp.sa_family = AF_PPPOX; ses->sp.sa_protocol = PX_PROTO_OE; ses->sp.sa_addr.pppoe.sid = sid; memcpy(&ses->remote, &ses->local, sizeof(struct sockaddr_ll) ); for(; i < ETH_ALEN ; ++i ){ ses->sp.sa_addr.pppoe.remote[i] = addr[i]; ses->remote.sll_addr[i]=addr[i]; } memcpy(ses->sp.sa_addr.pppoe.dev, dev, IFNAMSIZ); } if( retval < 0 ) error("bad device name: %s",devnam); retval = bind( disc_sock , (struct sockaddr*)&ses->local, sizeof(struct sockaddr_ll)); if( retval < 0 ){ error("bind to PF_PACKET socket failed: %m"); } ses->local.sll_protocol = ntohs(ETH_P_PPP_SES); retval = bind(ses_sock, (struct sockaddr *)&ses->local, sizeof(struct sockaddr_ll)); if (retval < 0) { poe_info(ses, "Couldn't bind session frame detection socket"); } ses->local.sll_protocol = ntohs(ETH_P_PPP_DISC); ses->fd = socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_OE); if(ses->fd < 0) { poe_fatal(ses,"Failed to create PPPoE socket: %m"); } ses->init_disc = std_init_disc; ses->rcv_pado = std_rcv_pado; ses->rcv_pads = std_rcv_pads; ses->rcv_padt = std_rcv_padt; return ses->fd; }