#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc.h" #include "ipconfig.h" /* call ioctl system call */ ret_code if_ioctl(unsigned long request, caddr_t ifreq, int *ret) { int sock; int err = 0; if(ret) { *ret = 0; } sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { rpc_log_error("Cannot create UDP socket"); return RET_SOCKERR; } if ((err = ioctl(sock, request, ifreq)) < 0) { rpc_log_error("Ioctl error: %s\n", strerror(errno)); } close(sock); if (err < 0) { if(ret) { *ret = err; } return RET_SYSERR; } return RET_OK; } /* Set a certain interface flag. */ static int if_set_flag(char *ifname, short flag, int *code) { struct ifreq ifr = {0}; ret_code ret = RET_OK; strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); ret = if_ioctl(SIOCGIFFLAGS, &ifr, code); ASSERT_RET(ret); strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); ifr.ifr_flags |= flag; ret = if_ioctl(SIOCSIFFLAGS, &ifr, code); ASSERT_RET(ret); return ret; } /* Clear a certain interface flag. */ static int if_clear_flag(char *ifname, short flag, int *code) { struct ifreq ifr = {0}; ret_code ret; safe_strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); ret = if_ioctl(SIOCGIFFLAGS, &ifr, code); ASSERT_RET(ret); safe_strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); ifr.ifr_flags &= ~flag; ret = if_ioctl(SIOCSIFFLAGS, &ifr) ASSERT_RET(ret); return ret; } ret_code if_set_prefix(ip_config_t *ip_conf, int *code) { ret_code ret; struct ifreq ifreq = {0}; struct sockaddr_in addr; struct sockaddr_in mask; strncpy(ifreq.ifr_name, ip_conf->ifname, sizeof(ifreq.ifr_name) - 1); addr.sin_addr = ip_conf->prefix; addr.sin_family = ip_conf->family; memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq, code); ASSERT_RET(ret); if(ip_conf->prefix.s_addr != 0) { masklen2ip(ip_conf->prefixlen, &mask.sin_addr); mask.sin_family = ip_conf->family; memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq, code); ASSERT_RET(ret); } return RET_OK; } ret_code if_get_prefix_all(pointer output, int *output_len, int *code) { struct ifreq ifreq[MAX_IF_NUM]; struct sockaddr_in *addr; struct ifreq netmask; ip_config_t *ip_conf; struct ifconf ifc; int if_count = 0; ret_code ret; int mask_ret; int i; memset(&ifc, 0, sizeof(struct ifconf)); memset(&ifreq, 0, MAX_IF_NUM * sizeof(struct ifreq)); ifc.ifc_len = MAX_IF_NUM * sizeof(struct ifreq); ifc.ifc_buf = (char *)ifreq; ret = if_ioctl(SIOCGIFCONF, (caddr_t)&ifc, code); ASSERT_RET(ret); if_count = ifc.ifc_len / (sizeof(struct ifreq)); rpc_log_info("if num is %d\n", if_count); if((if_count * sizeof(ip_config_t) > CM_BUFF_SIZE) || (if_count == 0)) { ret = RET_NOMEM; ASSERT_RET(ret); } ip_conf = rpc_new(ip_config_t, MAX_IF_NUM); if(ip_conf == NULL) { return RET_NOMEM; } memset(ip_conf, 0, MAX_IF_NUM * sizeof(ip_config_t)); for(i = 0; i < if_count; i++) { rpc_log_info("get interface %s info\n", ifreq[i].ifr_name); strncpy(ip_conf[i].ifname, ifreq[i].ifr_name, INTERFACE_NAMSIZ - 1); ip_conf[i].family = AF_INET; ip_conf[i].prefix = ((struct sockaddr_in *)&(ifreq[i].ifr_addr))->sin_addr; memset(&netmask, 0, sizeof(netmask)); strncpy(netmask.ifr_name, ifreq[i].ifr_name, sizeof(netmask.ifr_name) - 1); ret = if_ioctl(SIOCGIFNETMASK, (caddr_t)&netmask, &mask_ret); ASSERT_RET_NO(ret); addr = ( struct sockaddr_in * )&(netmask.ifr_netmask ); ip_conf[i].prefixlen = ip_masklen(addr->sin_addr); } ip_config_format_json_array(CM_CONFIG_GET, ip_conf, if_count, output, output_len); rpc_free(ip_conf); return RET_OK; } ret_code if_get_prefix(ip_config_t *ip_conf, int *code) { struct sockaddr_in *addr; struct ifreq netmask; struct ifreq ifreq; ret_code ret = RET_OK; int mask_ret; int i; if(ip_conf->family != AF_INET) { ret = RET_INPUTERR; } ASSERT_RET(ret); memset(&ifreq, 0, sizeof(struct ifreq)); rpc_log_info("get interface %s info\n", ip_conf->ifname); strncpy(ifreq.ifr_name, ip_conf->ifname, sizeof(ifreq.ifr_name) - 1); ret = if_ioctl(SIOCGIFADDR, (caddr_t)&ifreq, code); ASSERT_RET(ret); ip_conf->prefix = ((struct sockaddr_in *)&(ifreq.ifr_addr))->sin_addr; memset(&ifreq, 0, sizeof(ifreq)); strncpy(ifreq.ifr_name, ip_conf->ifname, sizeof(ifreq.ifr_name) - 1); ret = if_ioctl(SIOCGIFNETMASK, (caddr_t)&ifreq, &mask_ret); ASSERT_RET_NO(ret); addr = ( struct sockaddr_in * )&(ifreq.ifr_netmask); ip_conf->prefixlen = ip_masklen(addr->sin_addr); return ret; } ret_code if_set_up(char *ifname, int *code) { return if_set_flag(ifname, (IFF_UP | IFF_RUNNING), code); } ret_code if_set_down(char *ifname, int *code) { return if_clear_flag(ifname, IFF_UP, code); }