#include #include #include #include #include #include #include #include #include #include #include "ldp_struct.h" #include "ldp_ifmgr_impl.h" #include "ldp_mm_impl.h" #include "ldp_linux.h" #include "ldp_netlink.h" ldp_ifmgr_callback _netlink_ifmgr_callback = NULL; int _netlink_fd = 0; struct ldp_if_linux_list* _global_if_list = NULL; ldp_if_handle _ldp_ifmgr_open_if(ldp_ifmgr_handle handle,char* name); ldp_if_handle _ldp_ifmgr_find_name(ldp_ifmgr_handle handle,char* name); ldp_bool ldp_ifmgr_handle_verify(ldp_ifmgr_handle handle) { return LDP_TRUE; } ldp_bool ldp_if_handle_verify(ldp_ifmgr_handle ifmgr_handle,ldp_if_handle iff) { if(iff != 0) { return LDP_TRUE; } return LDP_FALSE; } ldp_ifmgr_handle ldp_ifmgr_open(ldp_instance_handle handle,ldp_cfg_handle cfg, ldp_ifmgr_callback callback) { FILE *file = fopen("/proc/net/dev", "r"); uint8_t* buffer = (uint8_t*)malloc(256); char *name = NULL; char *sep = NULL; int fd = socket(AF_INET,SOCK_STREAM,0); _global_if_list = malloc(sizeof(struct ldp_if_linux_list)); memset(_global_if_list,0,sizeof(struct ldp_if_linux_list)); LDP_LIST_INIT(_global_if_list,ldp_if_linux); fgets(buffer,256,file); fgets(buffer,256,file); while(!feof(file)) { name = buffer; if(fgets(buffer,256,file) == NULL) break; sep = strrchr(buffer,':'); if (sep) *sep = 0; while (*name == ' ') name++; if(!strncmp(name,"lo",2)) continue; _ldp_ifmgr_open_if(fd,name); } fclose(file); free(buffer); if(_netlink_fd == 0) { _netlink_fd = rtnl_open(); } _netlink_ifmgr_callback = callback; return fd; } void ldp_ifmgr_close(ldp_ifmgr_handle ifmgr_handle) { ldp_if_linux *iff = LDP_LIST_HEAD(_global_if_list); close(ifmgr_handle); while(iff) { LDP_LIST_REMOVE(_global_if_list,iff,_if); free(iff); iff = LDP_LIST_HEAD(_global_if_list); } free(_global_if_list); _global_if_list = NULL; _netlink_ifmgr_callback = NULL; close(_netlink_fd); } ldp_if_handle ldp_ifmgr_open_if(ldp_ifmgr_handle ifmgr_handle, const char* name) { ldp_if_handle retval = 0; retval = _ldp_ifmgr_find_name(ifmgr_handle,(char*)name); if(retval == 0) retval = _ldp_ifmgr_open_if(ifmgr_handle,(char*)name); return retval; } ldp_if_linux* _ldp_ifmgr_find_handle(ldp_ifmgr_handle ifmgr_handle, ldp_if_handle if_handle) { ldp_if_linux* iff = LDP_LIST_HEAD(_global_if_list); while(iff != NULL) { if(iff->handle == if_handle) return iff; iff = LDP_LIST_NEXT(_global_if_list,iff,_if); } return NULL; } ldp_if_handle _ldp_ifmgr_find_name(ldp_ifmgr_handle ifmgr_handle,char* name) { ldp_if_linux* iff = LDP_LIST_HEAD(_global_if_list); while(iff != NULL) { if(!strcmp(iff->name,name)) return iff->handle; iff = LDP_LIST_NEXT(_global_if_list,iff,_if); } return 0; } ldp_if_handle _ldp_ifmgr_open_if(ldp_ifmgr_handle ifmgr_handle,char* name) { struct ifreq ifr; ldp_if_linux *iff = NULL; if(!name) assert(0); iff = (ldp_if_linux*)malloc(sizeof(ldp_if_linux)); if(iff == NULL) return 0; memset(iff,0,sizeof(ldp_if_linux)); LDP_LIST_ELEM_INIT(iff,_if); strcpy(ifr.ifr_name,name); strcpy(iff->name,name); if(ioctl(ifmgr_handle,SIOCGIFFLAGS,&ifr) < 0) { free(iff); return 0; } iff->flags = ifr.ifr_flags; if(ioctl(ifmgr_handle,SIOCGIFADDR,&ifr) < 0) { free(iff); return 0; } iff->addr = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr; if(IFF_POINTOPOINT & iff->flags) { if(ioctl(ifmgr_handle,SIOCGIFDSTADDR,&ifr) < 0) { perror("IFDSTADDR"); free(iff); return 0; } iff->dstaddr = ((struct sockaddr_in*)&ifr.ifr_dstaddr)->sin_addr.s_addr; } else { if(ioctl(ifmgr_handle,SIOCGIFNETMASK,&ifr) < 0) { perror("IFIFNETMASK"); free(iff); return 0; } iff->netmask = ((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr; } if(ioctl(ifmgr_handle,SIOCGIFINDEX,&ifr) < 0) { perror("IFINDEX"); free(iff); return 0; } iff->handle = ifr.ifr_ifindex; fprintf(stderr,"Adding interface %s\n",name); LDP_LIST_ADD_HEAD(_global_if_list,iff,_if,ldp_if_linux); return iff->handle; } ldp_return_enum ldp_ifmgr_get_address(ldp_ifmgr_handle ifmgr_handle, ldp_if_handle if_handle,ldp_inet_addr* addr,ldp_inet_addr* mask, uint32_t* flags) { ldp_if_linux *iff = NULL; iff = _ldp_ifmgr_find_handle(ifmgr_handle,if_handle); if(iff == NULL) { fprintf(stderr,"ldp_ifmgr_get_address: failure(find)\n"); return LDP_FAILURE; } if(addr) { addr->protocol = AF_INET; addr->u.ipv4 = ntohl(iff->addr); } if(mask) { mask->protocol = AF_INET; mask->u.ipv4 = ntohl(iff->netmask); } if(flags) *flags = iff->flags; return LDP_SUCCESS; } ldp_return_enum ldp_ifmgr_get_mtu(ldp_ifmgr_handle ifmgr_handle, ldp_if_handle if_handle,int* mtu) { struct ifreq ifr; ifr.ifr_ifindex = if_handle; if(ioctl(ifmgr_handle,SIOCGIFNETMASK,&ifr) < 0) { perror("IFMTU"); return LDP_FAILURE; } if(!mtu) assert(0); *mtu = ifr.ifr_mtu; return LDP_SUCCESS; } void ldp_ifmgr_close_if(ldp_ifmgr_handle ifmgr_handle,ldp_if_handle if_handle) { ldp_if_linux *iff = NULL; iff = LDP_LIST_HEAD(_global_if_list); while(iff != NULL) { if(iff->handle == if_handle) { LDP_LIST_REMOVE(_global_if_list,iff,_if); return; } iff = LDP_LIST_NEXT(_global_if_list,iff,_if); } } ldp_if_handle ldp_ifmgr_getfirst(ldp_ifmgr_handle ifmgr_handle) { ldp_if_linux *iff = NULL; if((iff = LDP_LIST_HEAD(_global_if_list)) != NULL) { return iff->handle; } return 0; } ldp_if_handle ldp_ifmgr_getnext(ldp_ifmgr_handle ifmgr_handle, ldp_if_handle handle) { ldp_if_linux *iff = NULL; iff = LDP_LIST_HEAD(_global_if_list); while(iff != NULL) { if(iff->handle == handle) { if((iff = LDP_LIST_NEXT(_global_if_list,iff,_if)) != NULL) { return iff->handle; } return 0; } iff = LDP_LIST_NEXT(_global_if_list,iff,_if); } return 0; }