Beispiel #1
0
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;
}
Beispiel #2
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_dbglog(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;
    
    ses->retransmits = 0;
    
    send_disc(ses, &ses->curr_pkt);
    (*p_out) = &ses->curr_pkt;
    
    if (ses->np)
	return 1;
    
    return 0;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
0
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));
    
    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);
    
    
    return 1;
}
Beispiel #6
0
/*************************************************************************
 *
 * Receive and verify an incoming packet.
 *
 *************************************************************************/
static int recv_disc( struct session *ses,
		      struct pppoe_packet *p){
    int error = 0;
    unsigned int from_len = sizeof(struct sockaddr_ll);
    struct session* hu_val;
    struct pppoe_tag *pt;

    p->hdr = (struct pppoe_hdr*)p->buf;

    error = recvfrom( disc_sock, p->buf, 1500, 0,
		      (struct sockaddr*)&p->addr, &from_len);

    if(error < 0) return error;

    extract_tags(p->hdr,p->tags);

    poe_dbglog(ses,"Recv'd packet: %P",p);

    return 1;
}
Beispiel #7
0
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;
}
Beispiel #8
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;
}
Beispiel #9
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;
}
Beispiel #11
0
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");

//DEB_DISC = 1;
//DEB_DISC2 = 1;
    
    /* 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");
	}
	
    }
    
    /* 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);
	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);
	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);


    if (DEB_DISC)
	poe_dbglog (ses,"Local ETH %E", ses->local.sll_addr);

    
    retval = bind( disc_sock ,
		   (struct sockaddr*)&ses->local,
		   sizeof(struct sockaddr_ll));
    
    
    if( retval < 0 ){
	error("bind to PF_PACKET socket failed: %m");
    }

    /* Make socket if necessary */
    if (ses->fd < 0) {
	    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;
    
    /* this should be filter overridable */
    ses->retries = retry_num;
    
    return ses->fd;
}
Beispiel #12
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;
}
Beispiel #13
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);
}
Beispiel #14
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, error = 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);

    error = sendto(disc_sock, buf, data_len, 0,
		   (struct sockaddr*) &p->addr,
		   sizeof(struct sockaddr_ll));

    poe_dbglog(ses,"Sent packet: %P",p);

    if(error < 0)
	// brcm
	// poe_error(ses,"sendto returned: %m\n");
	;

    return error;
}
Beispiel #15
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);
}