Ejemplo n.º 1
0
/*
 * bound: This argument is used when udhcpc moves from an unbound, to
 * a bound state. All of the paramaters are set in enviromental
 * variables, The script should configure the interface, and set any
 * other relavent parameters (default gateway, dns server, etc).
*/
static int
bound_lan(void)
{
	char *lan_ifname = safe_getenv("interface");
	char *value;
	int flags;
	unsigned long addr, netmask;
	struct in_addr in_addr, in_netmask;

	if ((value = getenv("ip")))
		nvram_set("lan_ipaddr", value);
	if ((value = getenv("subnet")))
		nvram_set("lan_netmask", value);
	if ((value = getenv("router")))
		nvram_set("lan_gateway", value);
	if ((value = getenv("lease")))
		expires_lan(lan_ifname, atoi(value));

	/* Check if we do need to do ifconfig */
	if (ifconfig_get(lan_ifname, &flags, &addr, &netmask) == 0) {
		inet_aton(nvram_safe_get("lan_ipaddr"), &in_addr);
		inet_aton(nvram_safe_get("lan_netmask"), &in_netmask);
		if ((flags & IFUP) && addr == in_addr.s_addr && netmask == in_netmask.s_addr)
			goto done;
	}

	ifconfig(lan_ifname, IFUP, nvram_safe_get("lan_ipaddr"),
		nvram_safe_get("lan_netmask"));

	lan_up(lan_ifname);

#ifdef __CONFIG_WPS__
	start_wps();
#endif

done:
	dprintf("done\n");
	return 0;
}
Ejemplo n.º 2
0
static void *igmp_thread()
{
    char if_ip[16] = {0};
    char if_status[16];
	int sock, opt;
	struct sockaddr_in sin;
	int sizeof_sin = -1;
    struct ip_mreq ipmreq;
    int multicast_failed_sleep = 7;
    
	struct timeval now;
	struct timespec outtime;
	int retcode = 0;
	
	char multi_ip[16];
	int multi_port = 3000;
	
	char tmp_recv_buf[TMP_RECV_BUF_SIZE];
	int tmp_write = 0;	//p_write还要被其他线程使用,因此写完数据后,将p_write一次性修改完毕,write位置的中间值用tmp_write表示
	int free_size = 0;	//空闲区域的总大小
	int recv_size = 0;	//可用的接收大小,<=free_size
    int recv_len = 0;
	

MULTITASK_START:
	DEBUG("%s waiting cond_net_rely_condition\n",__FUNCTION__ );
	pthread_mutex_lock(&mtx_net_rely_condition);
#if 0
	pthread_cond_wait(&cond_net_rely_condition,&mtx_net_rely_condition); //wait
#else
	gettimeofday(&now, NULL);
	outtime.tv_sec = now.tv_sec + 180;
	outtime.tv_nsec = now.tv_usec;
	retcode = pthread_cond_timedwait(&cond_net_rely_condition, &mtx_net_rely_condition, &outtime);
	if(ETIMEDOUT!=retcode){
		DEBUG("igmp thread is awaked by external signal\n");
	}
	else
		DEBUG("igmp thread is awaked timeout\n");
#endif
	pthread_mutex_unlock(&mtx_net_rely_condition);
	
	/*
	 只要具备网络条件即可启动组播业务,不需要等待硬盘。因为升级不需要硬盘,有flash即可。
	*/
	
	sleep(2);
	DEBUG("igmp thread will goto its main loop\n");
	
	memset(multi_ip, 0, sizeof(multi_ip));
	if(-1==igmp_simple_check(multi_addr_get(), multi_ip, &multi_port)){
		DEBUG("check multi addr: %s invalid\n", multi_addr_get());
		goto MULTITASK_START;
	}
	DEBUG("multicast ip: %s, port: %d\n", multi_ip, multi_port);
	
	
	while(1){
		while(1){
			pthread_mutex_lock(&mtx_getip);
			
			memset(if_ip, 0, sizeof(if_ip));
			memset(if_status, 0, sizeof(if_status));
			if(0==ifconfig_get("eth0", if_ip, if_status, NULL)){
#if 0	// have any ip is OK
				if(0==ipv4_simple_check(if_ip)){
					pthread_mutex_unlock(&mtx_getip);
					break;
				}
				else
					DEBUG("ip(%s) of eth0 is invalid\n", if_ip);
#else
				DEBUG("get ip: %s, status: %s\n", if_ip, if_status);
				if(0==strcmp(if_status, "UP")){
					pthread_mutex_unlock(&mtx_getip);
					break;
				}
				else
					DEBUG("eth0 is DOWN\n");
#endif
			}
			else{
				DEBUG("get eth0 ip failed\n");
			}
			
			gettimeofday(&now, NULL);
			outtime.tv_sec = now.tv_sec + 17;
			outtime.tv_nsec = now.tv_usec;
			retcode = pthread_cond_timedwait(&cond_getip, &mtx_getip, &outtime);
			if(ETIMEDOUT!=retcode){
				DEBUG("igmp thread is canceled by external signal\n");
				pthread_mutex_unlock(&mtx_getip);
				return NULL;
			}
			pthread_mutex_unlock(&mtx_getip);
		}
		DEBUG("get eth0 ip: %s\n", if_ip);
		sleep(13);
	
		bzero((char *)&sin, sizeof(sin));
		sin.sin_family = AF_INET;
		sin.sin_addr.s_addr = inet_addr( multi_ip );
		sin.sin_port = htons(multi_port);
	
		if ((sock = socket( AF_INET, SOCK_DGRAM, 0)) == -1) {
			DEBUG("Error opening igmp socket\n");
		}
		else{
			DEBUG("create igmp socket %d\n", sock);
		
			opt = 1;
			if( ioctl( sock,  FIONBIO, (int)&opt ) < 0 ){
				DEBUG("set nonblock mode failed!\n");
			}
			else{
				if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&opt, sizeof(opt)) < 0) {
					DEBUG("setsockopt(allow multiple socket use) failed\n");
				}
				else{
					if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
						DEBUG("call to bind failed\n");
					}
					else{
						DEBUG("set FIONBIO, setsockopt(SO_REUSEADDR), bind, ok\n");
						
						socklen_t opt_len = sizeof(opt);
						if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&opt, &opt_len) < 0){
							DEBUG("can not get recvbuf size of socket\n");
						}
						else{
							DEBUG("1 get origine recvbuf size of socket: %d\n", opt);
						}

#if 0						
						opt = 32*1024*1024;
						if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&opt, sizeof(opt)) < 0){
							DEBUG("Can't change system network size (wanted size = %d)\n", opt);
						}
						
						opt_len = sizeof(opt);
						if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&opt, &opt_len) < 0){
							DEBUG("2 can not get recvbuf size of socket\n");
						}
						else{
							DEBUG("2 get processed recvbuf size of socket: %d\n", opt);
						}
#endif
						
						/*
						opt = 1316 * 8;
						if (osex_setsockopt(sock, SOL_SOCKET, SO_RCVLOWAT, (void*)&opt, sizeof(opt)) < 0){
							TDY_PERROR("Can't change system csv  lowat(wanted size = %d)", opt);
						}
						*/
						/*
						if(1 == yx_pppoe_status()){
							if( osex_ipaddr_get("pppoe0", if_ip)==0 ){
								ipmreq.imr_multiaddr.s_addr = inet_addr(multiaddr);
								ipmreq.imr_interface.s_addr = inet_addr(if_ip);
								TDY_DEBUG(("PPPOE IPTV ENTER %s\n", inet_ntoa((struct in_addr)(ipmreq.imr_interface))));
								if (osex_setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ipmreq, sizeof(ipmreq)) < 0){
									TDY_PERROR("Error in setsocket(add membership)");
									osex_close( sock );
									return -1;
								}
								return sock;
							}		
						}
						*/
					
						ipmreq.imr_multiaddr.s_addr = inet_addr(multi_ip);
						ipmreq.imr_interface.s_addr = inet_addr(if_ip);
						if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ipmreq, sizeof(ipmreq)) < 0){
							DEBUG("Error in setsocket(add membership)\n");
						}
						else
							break;
					}
				}
			}
		}
		
		pthread_mutex_lock(&mtx_getip);
		multicast_failed_sleep = multicast_failed_sleep << 1;
		if(multicast_failed_sleep>60*60)
			multicast_failed_sleep = 60*60;
			
		gettimeofday(&now, NULL);
		outtime.tv_sec = now.tv_sec + multicast_failed_sleep;
		outtime.tv_nsec = now.tv_usec;
		retcode = pthread_cond_timedwait(&cond_getip, &mtx_getip, &outtime);
		if(ETIMEDOUT!=retcode){
			DEBUG("igmp thread is canceled by external signal\n");
			pthread_mutex_unlock(&mtx_getip);
			return NULL;
		}
		pthread_mutex_unlock(&mtx_getip);
	}
	DEBUG("add membership OK\n");

	sizeof_sin = sizeof(sin);
	
	if(-1==igmp_recvbuf_init())
		return NULL;
	
	s_igmp_running = 1;
	s_igmp_restart = 0;
	
	while(1==s_igmp_running){
        if (p_write >= p_read)
        {
        	recv_size = MULTI_BUF_SIZE - p_write;
        	free_size = recv_size + p_read - IGMP_BUF_GAP;
        }
        else
        {
        	recv_size = p_read - p_write - IGMP_BUF_GAP;  //not let p_write = p_read 
        	free_size = recv_size;
        }
        
        if(free_size<=RECVFROM_MIN)
        {
        	//PRINTF("free_size=%d, %d,%d, multi buf is full\n", free_size, p_read, p_write);
        	usleep(20000);
        	continue;
        }
        //PRINTF("free_size=%d",free_size);
        
		if(recv_size>=RECVFROM_MIN){
			recv_len = recvfrom(sock, p_buf+p_write, recv_size, 0, (struct sockaddr *)&sin, (socklen_t*)&sizeof_sin);
			if(recv_len > 0)
			{
				s_data_stream_status = 8;
				
				tmp_write = p_write + recv_len;
				if(tmp_write >= MULTI_BUF_SIZE){	// actually, p_write is equal with MULTI_BUF_SIZE
					p_write = 0;
				}
				else
					p_write = tmp_write;
			}
			else{
				if(s_data_stream_status>0)
					s_data_stream_status --;
			}
		}
		else{
			//PRINTF("free_size=%d(%d),\tp_read=%d,\tp_write=%d\n", free_size,recv_size,p_read, p_write);
			//memset(tmp_recv_buf,0,sizeof(tmp_recv_buf));
			recv_len = recvfrom(sock, tmp_recv_buf, TMP_RECV_BUF_SIZE, 0, (struct sockaddr *)&sin, (socklen_t*)&sizeof_sin);
			//PRINTF("free_size=%d(%d),\t\t\t\t\trecv_len=%d\n", free_size,recv_size,recv_len);
			
			if(recv_len > 0)
			{
				s_data_stream_status = 8;
				
				if(recv_len>recv_size){
					memcpy(p_buf+p_write,tmp_recv_buf,recv_size);
					
					memcpy(p_buf,tmp_recv_buf+recv_size,recv_len-recv_size);
					p_write = recv_len-recv_size;
				}
				else{
					memcpy(p_buf+p_write,tmp_recv_buf,recv_len);
					tmp_write = p_write + recv_len;
					if(tmp_write >= MULTI_BUF_SIZE)
						p_write = 0;
				}
				PRINTF("free_size=%d(%d),\t\t\t\t\trecv_len=%d,p_write=%d\n", free_size,recv_size,recv_len,p_write);
			}
			else{
				if(s_data_stream_status>0)
					s_data_stream_status --;
			}
		}
		
		if (recv_len < 16)
		{
            usleep(10000);
            if(1==s_igmp_restart){
            	DEBUG("will restart igmp thread loop\n");
            	break;
            }
		}
	}
	
	// do igmp leave
	if(sock>=0){
		if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&ipmreq, sizeof(ipmreq)) < 0) {
			perror("Error in setsocket(add membership)");
		}
		else
			DEBUG("do igmp leave\n");
	
		close(sock);
		DEBUG("close igmp socket: %d\n", sock);
		
		s_data_stream_status = 0;
	}
	sock = -1;
	
	s_igmp_running = 0;
	
	if(1==s_igmp_restart)
		goto MULTITASK_START;
	
	free(p_buf);
	p_buf = NULL;

	DEBUG("igmp join thread exit\n");
	return NULL;
}