#include #include #include #include #include #include #include #include #include #include #define __USE_GNU #include #undef __USE_GNU #include "ldp_struct.h" #include "ldp_global.h" #include "ldp_prefix.h" #include "ldp_peer.h" #include "ldp_if.h" #include "ldp_range.h" #include "ldp_entity.h" #include "ldp_cfg.h" #include "ldp_pdu.h" #include "ldp_tree_impl.h" #include "ldp_state_machine.h" #include "ldp_linux.h" extern void _ldp_timer_linux_ensort(ldp_timer_linux* t); extern void ldp_mm_results(); uint8_t trace_buffer[16834]; int trace_buffer_len = 0; uint32_t _trace_flags = 0; struct timeval _global_timeval; static ldp_cfg_handle cfg_handle = 0; extern fd_set _global_write_set; extern fd_set _global_read_set; extern uint32_t _global_high_fd; extern struct ldp_socket_linux **_global_socket_array; extern uint32_t _globale_socket_array_size; extern struct ldp_timer_linux_list* _global_timer_list; extern ldp_fib_callback _netlink_fib_callback; extern ldp_tree_handle _fib_tree; #define CMD_NEXT 1 #define CMD_EXEC 2 typedef struct commandS commandT; struct commandS { char *full_token; char *token; int type; void (*handler)(char*,int,int); commandT* next; }; int parser_debug = 0; extern void help(char *buf,int size,int offset); void quit(char *buf,int size,int offset) { ldp_mm_results(); exit(1); } void del_interface(char *buf,int size,int offset) { ldp_entity *entity = NULL; ldp_if *iff = NULL; ldp_return_enum retval; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } entity = ldp_entity_create(); iff = ldp_if_create(); iff->index = atoi(&buf[offset]); retval = ldp_cfg_if_get(cfg_handle,iff,0xFFFFFFFF); entity->index = iff->entity_index; entity->admin_state = LDP_DOWN; entity->sub_index = iff->index; entity->entity_type = LDP_DIRECT; retval = ldp_cfg_entity_set(cfg_handle,entity,LDP_ENTITY_CFG_ADMIN_STATE); retval = ldp_cfg_entity_set(cfg_handle,entity,LDP_CFG_DEL); retval = ldp_cfg_if_set(cfg_handle,iff,LDP_CFG_DEL); fprintf(stderr,"Deleting interface with index %d\n",iff->index); free(iff); free(entity); } void del_route(char *buf,int size,int offset) { ldp_prefix *dest = NULL; ldp_prefix *dumb; char *net_str,*len_str,*nh_str; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } dest = ldp_prefix_create(); net_str = strtok(&buf[offset],"/"); len_str = strtok(NULL," "); nh_str = strtok(NULL," "); if(!net_str || !len_str || !nh_str) { fprintf(stderr,"Invalid input: del route / \n"); return; } dest->network.protocol = AF_INET; dest->network.u.ipv4 = ntohl(inet_addr(net_str)); dest->next_hop.protocol = AF_INET; dest->next_hop.u.ipv4 = ntohl(inet_addr(net_str)); dest->prefix_len = atoi(len_str); fprintf(stderr,"Deleting route %08x/%d via %d\n",dest->network.u.ipv4, dest->prefix_len,dest->out_if_handle); ldp_tree_remove(_fib_tree,dest->network.u.ipv4,dest->prefix_len,(void**)&dumb); _netlink_fib_callback(cfg_handle,LDP_DEL,dest); } void add_route(char *buf,int size,int offset) { ldp_prefix *dest = NULL; char *net_str,*len_str,*nh_str; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } dest = ldp_prefix_create(); net_str = strtok(&buf[offset],"/"); len_str = strtok(NULL," "); nh_str = strtok(NULL," "); if(!net_str || !len_str || !nh_str) { fprintf(stderr,"Invalid input: add route / \n"); return; } dest->network.protocol = AF_INET; dest->network.u.ipv4 = ntohl(inet_addr(net_str)); dest->next_hop.protocol = AF_INET; dest->next_hop.u.ipv4 = ntohl(inet_addr(net_str)); dest->prefix_len = atoi(len_str); dest->out_if_handle = 0; fprintf(stderr,"Adding route %08x/%d via %d\n",dest->network.u.ipv4, dest->prefix_len,dest->out_if_handle); ldp_tree_insert(_fib_tree,dest->network.u.ipv4,dest->prefix_len,(void*)dest); _netlink_fib_callback(cfg_handle,LDP_ADD,dest); } void add_interface(char *buf,int size,int offset) { ldp_entity* entity = NULL; ldp_if* iff = NULL; int label_space = 0; int retval; char *if_str; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } entity = ldp_entity_create(); if_str = strtok(&buf[offset]," "); if(!if_str) { fprintf(stderr,"Invalid input: add interface \n"); return; } iff = ldp_if_create(); /* * not setting iff->index will force it to use the name below to * find the "index" */ strcpy(iff->name,&buf[offset]); iff->label_space = label_space; retval = ldp_cfg_if_set(cfg_handle,iff,LDP_CFG_ADD|LDP_IF_CFG_LABEL_SPACE); /* * since we sent in iff->index = 0, ldp_cfg_if_set was kind enough to * set iff->index = to the index it found */ entity->sub_index = iff->index; entity->entity_type = LDP_DIRECT; entity->admin_state = LDP_UP; retval = ldp_cfg_entity_set(cfg_handle,entity, LDP_CFG_ADD|LDP_ENTITY_CFG_SUB_INDEX|LDP_ENTITY_CFG_ADMIN_STATE); fprintf(stderr,"Adding interface %s\n",iff->name); free(iff); free(entity); } void del_global(char *buf,int size,int offset) { int label_space = 0; ldp_global global; ldp_range* range = NULL; int retval; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } range = ldp_range_create(label_space,LDP_GENERIC); retval = ldp_cfg_range_set(cfg_handle,range,LDP_CFG_DEL); global.admin_state = LDP_DOWN; retval = ldp_cfg_global_set(cfg_handle,&global,LDP_GLOBAL_CFG_ADMIN_STATE); free(range); ldp_cfg_close(cfg_handle); cfg_handle = 0; fprintf(stderr,"Deleting global object\n"); } void add_global(char *buf,int size,int offset) { ldp_global global; ldp_range* range = NULL; int label_space = 0; int retval; if(!isdigit(buf[offset])) { fprintf(stderr,"Invalid input: add global \n"); return; } cfg_handle = ldp_cfg_open(1); global.admin_state = LDP_UP; global.lsr_identifier.protocol = AF_INET; global.lsr_identifier.u.ipv4 = ntohl(inet_addr(&buf[offset])); retval = ldp_cfg_global_set(cfg_handle,&global,LDP_GLOBAL_CFG_ADMIN_STATE| LDP_GLOBAL_CFG_LSR_IDENTIFIER); range = ldp_range_create(label_space,LDP_GENERIC); retval = ldp_cfg_range_set(cfg_handle,range,LDP_CFG_ADD); fprintf(stderr,"Adding global object with LSRID %08x\n", global.lsr_identifier.u.ipv4); free(range); } void del_peer(char *buf,int size,int offset) { ldp_entity *entity = NULL; ldp_peer *peer = NULL; ldp_return_enum retval; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } entity = ldp_entity_create(); peer = ldp_peer_create(); peer->index = atoi(&buf[offset]); retval = ldp_cfg_peer_get(cfg_handle,peer,0xFFFFFFFF); entity->index = peer->entity_index; entity->admin_state = LDP_DOWN; entity->sub_index = peer->index; entity->entity_type = LDP_INDIRECT; retval = ldp_cfg_entity_set(cfg_handle,entity,LDP_ENTITY_CFG_ADMIN_STATE); retval = ldp_cfg_entity_set(cfg_handle,entity,LDP_CFG_DEL); retval = ldp_cfg_peer_set(cfg_handle,peer,LDP_CFG_DEL); fprintf(stderr,"Deleting in-direct peer with index %d\n",peer->index); free(peer); free(entity); } void add_peer(char *buf,int size,int offset) { ldp_entity* entity = NULL; ldp_peer* peer = NULL; int label_space = 0; int retval; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } entity = ldp_entity_create(); peer = ldp_peer_create(); peer->label_space = label_space; peer->dest.addr.protocol = AF_INET; peer->dest.addr.u.ipv4 = ntohl(inet_addr(&buf[offset])); retval = ldp_cfg_peer_set(cfg_handle,peer,LDP_CFG_ADD| LDP_PEER_CFG_LABEL_SPACE|LDP_PEER_CFG_DEST_ADDR); /* * since we sent in peer->index = 0, ldp_cfg_peer_set was kind enough to * set peer->index = to the index it generated */ entity->sub_index = peer->index; entity->entity_type = LDP_INDIRECT; entity->admin_state = LDP_UP; retval = ldp_cfg_entity_set(cfg_handle,entity, LDP_CFG_ADD|LDP_ENTITY_CFG_SUB_INDEX|LDP_ENTITY_CFG_ADMIN_STATE); fprintf(stderr,"Adding in-direct LDP peer %08x\n",peer->dest.addr.u.ipv4); free(peer); free(entity); } void set_trace(char *buf,int size,int offset) { unsigned int trace; trace = strtol(&buf[offset],NULL,16); _trace_flags = trace; fprintf(stderr,"Set tracing flag to %08x\n",trace); } void show_session(char *buf,int size,int offset) { ldp_session session; int count = 0; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } session.index = 0; fprintf(stderr,"\n"); while(ldp_cfg_session_getnext(cfg_handle,&session,0xFFFFFFFF) == LDP_SUCCESS) { count++; fprintf(stderr,"%-2d %08x %-3d %d\n",session.index, session.remote_dest.addr.u.ipv4,session.oper_keepalive,session.state); } if(count == 0) { fprintf(stderr," no established sessions\n"); } fprintf(stderr,"\n"); } void show_peer(char *buf,int size,int offset) { ldp_peer peer; int count = 0; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } peer.index = 0; fprintf(stderr,"\n"); while(ldp_cfg_peer_getnext(cfg_handle,&peer,0xFFFFFFFF) != LDP_END_OF_LIST) { count++; fprintf(stderr,"%-2d %08x %d\n",peer.index,peer.dest.addr.u.ipv4, peer.oper_state); } if(count == 0) { fprintf(stderr," no configured peers\n"); } fprintf(stderr,"\n"); } void show_database(char *buf,int size,int offset) { ldp_attr attr; int count = 0; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } attr.index = 0; fprintf(stderr,"\n"); while(ldp_cfg_attr_getnext(cfg_handle,&attr,0xFFFFFFFF) != LDP_END_OF_LIST) { count++; fprintf(stderr,"%-2d %08x/%d %d via %d\n",attr.index, attr.fecTlv.fecElArray[0].addressEl.address, attr.fecTlv.fecElArray[0].addressEl.preLen,attr.state,attr.session_index); } if(count == 0) { fprintf(stderr," no estblished mappings\n"); } fprintf(stderr,"\n"); } void show_interface(char *buf,int size,int offset) { ldp_if iff; int count = 0; if(!cfg_handle) { fprintf(stderr,"You need to create a global object (add global)\n"); return; } iff.index = 0; fprintf(stderr,"\n"); while(ldp_cfg_if_getnext(cfg_handle,&iff,0xFFFFFFFF) != LDP_END_OF_LIST) { count++; fprintf(stderr,"%-2d %s\n",iff.index,iff.name); } if(count == 0) { fprintf(stderr," no configured interfaces\n"); } fprintf(stderr,"\n"); } commandT set_level[2] = {{"trace","t",CMD_EXEC,set_trace,NULL}, /* trace */ {NULL,NULL,0,NULL,NULL}}; commandT del_level[5] = {{"interface","i",CMD_EXEC,del_interface,NULL}, /* if */ {"global","g",CMD_EXEC,del_global,NULL}, /* global */ {"peer","p",CMD_EXEC,del_peer,NULL}, /* peer */ {"route","r",CMD_EXEC,del_route,NULL}, /* route */ {NULL,NULL,0,NULL,NULL}}; commandT show_level[5] = {{"session","s",CMD_EXEC,show_session,NULL},/*session*/ {"peer","p",CMD_EXEC,show_peer,NULL}, /* peer */ {"interface","i",CMD_EXEC,show_interface,NULL},/* if */ {"database","d",CMD_EXEC,show_database,NULL}, /* db */ {NULL,NULL,0,NULL,NULL}}; commandT add_level[5] = {{"interface","i",CMD_EXEC,add_interface,NULL}, /* if */ {"global","g",CMD_EXEC,add_global,NULL}, /* global */ {"peer","p",CMD_EXEC,add_peer,NULL}, /* peer */ {"route","r",CMD_EXEC,add_route,NULL}, /* route */ {NULL,NULL,0,NULL,NULL}}; commandT first_level[10] = {{"quit","q",CMD_EXEC,quit,NULL}, /* quit */ {"?","?",CMD_EXEC,help,NULL}, /* help */ {"help","h",CMD_EXEC,help,NULL}, /* help */ {"end","en",CMD_EXEC,quit,NULL}, /* end */ {"exit","ex",CMD_EXEC,quit,NULL}, /* exit */ {"show","sh",CMD_NEXT,NULL,show_level}, /* show */ {"add","a",CMD_NEXT,NULL,add_level}, /* add */ {"set","se",CMD_NEXT,NULL,set_level}, /* set */ {"del","d",CMD_NEXT,NULL,del_level}, /* del */ {NULL,NULL,0,NULL,NULL}}; void help(char *buf,int size,int offset) { int j; int stack[16]; char* string[16]; int depth = 0; commandT* command[16]; command[0] = first_level; memset(stack,0,sizeof(stack)); again: for(;command[depth][stack[depth]].type != 0;stack[depth]++) { if(command[depth][stack[depth]].type == CMD_NEXT) { string[depth] = command[depth][stack[depth]].full_token; command[depth+1] = command[depth][stack[depth]].next; stack[depth+1] = 0; stack[depth]++; depth++; goto again; } else { for(j=0;j 0) { if(*(command_buffer+command_size) == '\n') { int cur,ncur = -1; char ws = 0; /* trim this string down */ *(command_buffer+command_size) = '\0'; for(cur=0;cur"); command_size = 0; } else { command_size += result; } } } int32_t timeval_diff(struct timeval* a,struct timeval* b,struct timeval* c) { c->tv_usec = b->tv_usec - a->tv_usec; c->tv_sec = b->tv_sec - a->tv_sec; if(c->tv_usec < 0 && c->tv_sec > 0) { c->tv_sec--; c->tv_usec += 1000000; } return c->tv_sec * 1000000 + c->tv_usec; } int main(int argc, char **argv) { ldp_timer_linux* next = NULL; struct timeval* sleep; struct timeval _sleep; fd_set write_set; fd_set read_set; int32_t diff = 0; int i; gettimeofday(&_global_timeval,NULL); setbuf(stdin,NULL); fcntl(stdin->_fileno,F_SETFL,O_NONBLOCK); while(1) { gettimeofday(&_global_timeval,NULL); if(_global_timer_list && (next = LDP_LIST_HEAD(_global_timer_list))) { if((diff = timeval_diff(&_global_timeval,&next->event,&_sleep)) < 5000) { if(next->type == LDP_REOCCURRING) { LDP_LIST_REMOVE(_global_timer_list,next,_timer); next->event.tv_sec = _global_timeval.tv_sec + next->length.tv_sec; next->event.tv_usec = _global_timeval.tv_usec + next->length.tv_usec; _ldp_timer_linux_ensort(next); } next->callback(next,next->extra,next->global); } sleep = &_sleep; } else { sleep = NULL; } memcpy(&write_set,&_global_write_set,sizeof(fd_set)); memcpy(&read_set,&_global_read_set,sizeof(fd_set)); FD_SET(stdin->_fileno,&read_set); if(select(_global_high_fd+1,&read_set,&write_set,NULL,sleep) <= 0) continue; for(i=0;i<_global_high_fd+1;i++) { ldp_socket_linux *lsl = NULL; ldp_pdu *pdu = NULL; #if 0 uint8_t *buffer = NULL; uint32_t size; #endif if(i == stdin->_fileno && FD_ISSET(i,&read_set)) { ldp_linux_console(i); } else { lsl = _global_socket_array[i]; if(FD_ISSET(i,&read_set)) { switch(lsl->type) { case LDP_TCP_DATA: ldp_event(cfg_handle,lsl->socket,NULL,0,NULL,lsl->extra, LDP_EVENT_TCP_DATA); break; case LDP_TCP_LISTEN: ldp_event(cfg_handle,lsl->socket,NULL,0,NULL,lsl->extra, LDP_EVENT_TCP_LISTEN); break; case LDP_UDP_DATA: ldp_event(cfg_handle,lsl->socket,NULL,0,NULL,lsl->extra, LDP_EVENT_UDP_DATA); break; default: assert(0); } } if(FD_ISSET(i,&write_set)) { if(lsl->type != LDP_TCP_CONNECT) assert(0); ldp_event(cfg_handle,lsl->socket,NULL,0,pdu,lsl->extra, LDP_EVENT_TCP_CONNECT); } } } } return 0; }