Пример #1
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;

    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;

}
Пример #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_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;
}
Пример #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;
}
Пример #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;
}
Пример #5
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;

}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
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;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #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;
}
Пример #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);
}
Пример #14
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);
}
Пример #15
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));
*/
}