Beispiel #1
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 #2
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);
}
Beispiel #3
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);
}