/********************************************************************************* * Copyright: (C) 2012 Guo Wenxue * All rights reserved. * * Filename: cp_network.c * Description: This file is the high level network library API * * Version: 1.0.0(10/31/2012~) * Author: Guo Wenxue * ChangeLog: 1, Release initial version on "10/31/2012 11:22:38 AM" * ********************************************************************************/ #include #include #include #include #include "cp_sock.h" #include "cp_fds.h" #include "cp_network.h" #include "cp_network.h" #include "cp_proc.h" /* Description: Configure the NIC MAC/IP address * Input args: $nic: configure for which NIC(Network Interface Card): eth0, eth1 * $mac: MAC address $ip: IP address * Return Value: 0: Test OK, <0: Failed */ int nic_network_config(char *nic, char *mac, char *ip) { if(!nic) return -1; /*MAC address format: aa:bb:cc:dd:ee:ff */ if(mac && 17==strlen(mac)) { /* shutdown the ethernet and clear the original IP address */ exec_system_cmd("ifconfig %s down", nic, nic); sleep(1); exec_system_cmd("ifconfig %s hw ether %s up", nic, mac); } /* IP address specified and valid */ if(ip && inet_addr(ip)) { exec_system_cmd("ifconfig %s down && ifconfig %s 0.0.0.0", nic, nic); sleep(2); exec_system_cmd("ifconfig %s %s up", nic, ip); } return 0; } int nic_get_ipaddr(char *nic, char *ipaddr) { int fd; struct ifreq ifr; struct sockaddr_in *sin; if( !nic || !ipaddr ) return -1; fd = socket(AF_INET, SOCK_DGRAM, 0); strcpy(ifr.ifr_name, nic); if ((ioctl(fd, SIOCGIFADDR, (caddr_t)&ifr, sizeof(struct ifreq))) < 0) { log_fatal("System call ioctl() with SIOCGIFADDR get %s IP address failure.\n", nic); return -2; } sin = (struct sockaddr_in *)&ifr.ifr_addr; strcpy(ipaddr, (const char *)inet_ntoa(sin->sin_addr)); log_dbg("Get %s local IP address: %s\n", nic, ipaddr); return 0; } int nic_get_ptpaddr(char *nic, char *ptpaddr) { int fd; struct ifreq ifr; struct sockaddr_in *sin; fd = socket(AF_INET, SOCK_DGRAM, 0); strcpy(ifr.ifr_name, nic); if ((ioctl(fd, SIOCGIFDSTADDR, (caddr_t) & ifr, sizeof(struct ifreq))) < 0) { log_fatal("System call ioctl() with SIOCGIFDSTADDR get %s IP address failure.\n", nic); return -1; } sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; strcpy(ptpaddr, (const char *)inet_ntoa(sin->sin_addr)); log_dbg("Get %s remote IP address: %s\n", nic, ptpaddr); return 0; } /* Description: Use ping do network test * Input args: $from: : use which NIC(Network Interface Card: eth0, eth1) or * source IP address do ping test. if it's NULL, use default route * $ping_ip: The ping test destination IP address * Output args: NONE * Return Value: >=0 ping test packet lost percent, <0: failure */ int network_ping_test(char *from, char *ping_ip) { FILE *fp; char cmd[256]; char buf[512]; int lost_percent = 100; unsigned long tx_packets = 0; unsigned long rx_packets = 0; memset(cmd, 0, sizeof(cmd)); if(from) { snprintf(cmd, sizeof(cmd), "ping -W1 -c5 -s4 %s -I %s", ping_ip, from); } else { snprintf(cmd, sizeof(cmd), "ping -W1 -c5 -s4 %s", ping_ip); } if (NULL == (fp = popen(cmd, "r"))) { return -2; } while (NULL != fgets(buf, sizeof(buf), fp)) { if (strstr(buf, "transmitted")) { split_string_to_value(buf, "%l,%l,%d", &tx_packets, &rx_packets, &lost_percent); break; } } pclose(fp); return lost_percent; } int cp_sock_accept_regist(CP_SOCK *serv_sock) { CP_SOCK *new_sock = NULL; int rv = 0; if(!serv_sock) { log_err("Invalude input arguments\n"); return -1; } log_dbg("Accept and regist new client from server [%d] on [%s:%d] now\n", serv_sock->fd, serv_sock->laddr, serv_sock->lport); if(serv_sock->accept_cnt >= serv_sock->max_client) { log_err("No more client resource aviable on server socket [%d]\n", serv_sock->fd); goto exit_out; } if( !(new_sock=cp_sock_init(NULL, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) ) { log_err("Create a new socket contex for accept new client failed.\n"); goto exit_out; } new_sock->serv_sock = serv_sock; new_sock->fds = serv_sock->fds; new_sock->privt = serv_sock->privt; new_sock->cbfunc = serv_sock->client_func; new_sock->mode = CP_SOCK_MODE_ACCEPT; /* add accept new client into the socket registry list */ if( cp_fds_add_sock_registry(new_sock) ) { rv = -2; goto term_sock; } /* accept the new client from server socket */ if( cp_sock_accept(serv_sock, new_sock) ) { rv = -3; goto del_regist; } if( cp_add_epoll_event(new_sock) ) { rv = -4; goto del_regist; } log_dbg("Accept and regist new client from server [%d] on [%s:%d] ok\n", serv_sock->fd, serv_sock->laddr, serv_sock->lport); return 0; del_regist: cp_fds_del_sock_registry(new_sock); term_sock: if(new_sock) cp_sock_term_clear(new_sock); exit_out: log_err("Accept and regist new client from server [%d] on [%s:%d] failed\n", serv_sock->fd, serv_sock->laddr, serv_sock->lport); cp_fds_del_sock_task(serv_sock); return rv; } CP_SOCK *cp_sock_connect_regist(CP_FDS *fds, CP_SOCK *sock, char *raddr, int rport, int lport, CP_SOCK_EVENT_CALLBACK service_route) { if(!fds || !raddr || rport<0) { log_err("Invalude input arguments\n"); goto exit_out; } if( !sock && !(sock=cp_sock_init(sock, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) ) { goto exit_out; } if( SOCK_STAT_CONNECTED == sock->status ) return sock; /* already ok now */ if( !(sock->flag&FLAG_SOCK_REGISTRY) ) { sock->fds = fds; sock->cbfunc = service_route; sock->mode = CP_SOCK_MODE_CONNECT; strncpy(sock->laddr, "0.0.0.0", sizeof(sock->laddr)); log_dbg("Connect and regist socket to remote [%s:%d] now\n", raddr, rport); if( cp_fds_add_sock_registry( sock) ) goto term_sock; /* regist to the list failed */ } if ( cp_sock_connect(sock, raddr, rport, lport) ) { log_dbg("socket [%d] connect failed, start to remove registry it now.\n", sock->fd); goto del_regist; } else { if( cp_add_epoll_event(sock) ) goto del_regist; } return sock; del_regist: cp_fds_del_sock_registry(sock); term_sock: cp_fds_del_sock_task(sock); if(sock) cp_sock_term(sock); exit_out: log_err("Connect and regist new socket to remote server [%s:%d] failed\n", raddr, rport); return NULL; } CP_SOCK *cp_sock_server_regist(CP_FDS *fds, char *addr, int port, int max_client, CP_SOCK_EVENT_CALLBACK service_route, void *data) { int rv = 0; CP_SOCK *sock = NULL; log_dbg("Regist socket server listen on [%s:%d] now\n", addr?addr:"local", port); if(!fds || port < 0) { rv = -1; log_err("Invalude input arguments\n"); goto exit_out; } if( !(sock=cp_sock_init(NULL, CP_SOCK_RCVBUF, CP_SOCK_SNDBUF, CP_SOCK_KEEPINTVL, CP_SOCK_KEEPCNT)) ) { rv = -2; goto exit_out; } INIT_LIST_HEAD(&sock->accept_list); sock->fds = fds; sock->cbfunc = cp_sock_accept_regist; sock->client_func = service_route; sock->privt = data; sock->mode = CP_SOCK_MODE_LISTEN; if( cp_fds_add_sock_registry(sock) ) { rv = -3; goto term_sock; } /* If specified maximum clients <=0, then use the default one */ sock->max_client = max_client<=0 ? CP_DEF_MAX_CLIENTS : max_client; /* If specified maximum clients larger than FDS monitor maxevents, then use the default one */ sock->max_client = max_clientmax_event ? sock->max_client : CP_DEF_MAX_CLIENTS; if( cp_sock_listen(sock, addr, port, sock->max_client) ) { rv = -4; goto del_regist; } /* Add server socket FD to the epoll monitor list */ if( cp_add_epoll_event(sock) ) { rv = -5; goto del_regist; } log_nrml("Registe socket[%d] server listen on [%s:%d] ok.\n", sock->fd, sock->laddr, sock->lport); return sock; del_regist: cp_fds_del_sock_registry(sock); term_sock: cp_fds_del_sock_task(sock); if(sock) cp_sock_term_clear(sock); exit_out: log_err("Registe socket server listen on [%s:%d] failed.\n", addr, port); return NULL; } void cp_sock_term_all_service(CP_FDS *fds) { if(!fds) return; log_dbg("Terminate all the service now\n"); cp_sock_term_all_task(fds); cp_sock_term_all_server(fds); cp_sock_term_all_client(fds); cp_fds_term(fds); log_warn("Terminate all the service ok\n"); }