#include #include #include #include #include #include #include "ldp_struct.h" #include "ldp_prefix.h" #include "ldp_netlink.h" #include "ldp_fib_impl.h" #include "ldp_tree_impl.h" extern int _netlink_fd; ldp_fib_callback _netlink_fib_callback = NULL; ldp_tree_handle _fib_tree = NULL; extern uint32_t _ldp_ifmgr_find_name(uint32_t handle,uint8_t* name); int _mask_length(uint32_t bits) { int num = 0; while (bits != 0) { num++; bits &= bits-1; } return num; } void ldp_fib_update_close(ldp_fib_handle handle) { _netlink_fib_callback = NULL; close(_netlink_fd); } ldp_bool ldp_fib_handle_verify(ldp_fib_handle handle) { return LDP_TRUE; } ldp_fib_handle ldp_fib_open(const ldp_instance_handle handle, const ldp_cfg_handle cfg,ldp_fib_callback callback) { ldp_tree_handle t = ldp_tree_create(32); FILE *fp=fopen("/proc/net/route", "r"); char buff[4096],iFace[16]; char gateAddr[128],netAddr[128]; char maskAddr[128]; int num,iFlags,metric,refCnt,use,mss,window,irtt; ldp_prefix* pfx; int temp; _fib_tree = t; fgets(buff,1023,fp); while(fgets(buff,1023,fp)) { memset(iFace, 0, 16); memset(netAddr, 0, 128); memset(gateAddr, 0, 128); memset(maskAddr, 0, 128); metric = 0; num = sscanf(buff,"%16s %128s %128s %X %d %d %d %128s %d %d %d\n", iFace,netAddr,gateAddr, &iFlags,&refCnt,&use,&metric,maskAddr, &mss,&window,&irtt); if(!(iFlags & 1)) continue; pfx = ldp_prefix_create(); pfx->network.protocol = AF_INET; pfx->network.u.ipv4 = ntohl(strtol(netAddr,NULL,16)); pfx->next_hop.protocol = AF_INET; pfx->next_hop.u.ipv4 = ntohl(strtol(gateAddr,NULL,16)); pfx->index = 0; if(!strcmp(maskAddr,"FFFFFFFF")) { pfx->prefix_len = 32; } else { temp = strtol(maskAddr,NULL,16); pfx->prefix_len = _mask_length(temp); } /* find if handle */ pfx->out_if_handle = _ldp_ifmgr_find_name(0,iFace); fprintf(stderr,"Adding route %08x/%d via %d",pfx->network.u.ipv4, pfx->prefix_len,pfx->out_if_handle); if(ldp_tree_insert(t,pfx->network.u.ipv4,pfx->prefix_len,(void*)pfx) == LDP_FAILURE) { fprintf(stderr," - failed"); } fprintf(stderr,"\n"); } fclose(fp); if(_netlink_fd == 0) { _netlink_fd = rtnl_open(); } _netlink_fib_callback = callback; return t; } int ldp_fib_get_route(ldp_fib_handle handle,const int num, const ldp_prefix* dest,ldp_prefix* entry) { ldp_prefix* pfx = NULL; if(dest == NULL) return LDP_FAILURE; if(ldp_tree_get(handle,dest->network.u.ipv4,dest->prefix_len,(void**)&pfx) == LDP_FAILURE) { return LDP_FAILURE; } if(pfx == 0) { return LDP_FAILURE; } memcpy(entry,pfx,sizeof(ldp_prefix)); return 1; } int ldp_fib_get_best_route(ldp_fib_handle handle,const int num, const ldp_prefix* dest,ldp_prefix* entry) { ldp_prefix *pfx = NULL; if(dest == NULL) return 0; if(ldp_tree_get_longest(handle,dest->network.u.ipv4,(void**)&pfx) == LDP_FAILURE) { return 0; } memcpy(entry,pfx,sizeof(ldp_prefix)); return 1; } ldp_return_enum ldp_fib_getfirst_route(ldp_fib_handle handle,ldp_prefix* dest) { return LDP_FAILURE; } ldp_return_enum ldp_fib_getnext_route(ldp_fib_handle handle,ldp_prefix* dest) { return LDP_FAILURE; } void ldp_fib_close(ldp_fib_handle handle) { if(ldp_tree_handle_verify(handle) == LDP_TRUE) { ldp_tree_delete(handle); } }