/* * 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; }
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; }