/* * Copyright (C) James R. Leu 2000 * jleu@mindspring.com * * This software is covered under the LGPL, for more * info check out http://www.gnu.org/copyleft/lgpl.html */ #include #include "ldp_struct.h" #include "ldp_assert.h" #include "ldp_global.h" #include "ldp_session.h" #include "ldp_entity.h" #include "ldp_fec.h" #include "ldp_adj.h" #include "ldp_attr.h" #include "ldp_msg.h" #include "ldp_hello.h" #include "ldp_init.h" #include "ldp_label_rel_with.h" #include "ldp_label_mapping.h" #include "ldp_label_request.h" #include "ldp_addr.h" #include "ldp_keepalive.h" #include "ldp_tree_impl.h" #include "ldp_trace_impl.h" #include "ldp_socket_impl.h" #include "ldp_label_request.h" #include "ldp_label_mapping.h" ldp_return_enum ldp_state_new_adjacency(ldp_global *g,ldp_session *s,ldp_adj *a, ldp_entity *e,uint32_t event,ldp_msg *msg,ldp_dest *from) { ldp_inet_addr traddr,lsraddr, *addr; ldp_adj* local_a = NULL; int labelspace; int hellotime; int request = 0; int target = 0; uint32_t csn = 0; LDP_ASSERT(msg != NULL && msg->hdr != NULL && msg->body != NULL && e != NULL); LDP_ENTER(g->user_data,"ldp_state_new_adjacency"); if(ldp_msg_hello_get_hellotime(msg,&hellotime) == LDP_FAILURE || ldp_msg_hdr_get_labelspace(msg,&labelspace) == LDP_FAILURE || ldp_msg_hdr_get_lsraddr(msg,&lsraddr) == LDP_FAILURE) { LDP_EXIT(g->user_data,"ldp_state_new_adjacency-error"); return LDP_FAILURE; } ldp_msg_hello_get_request(msg,&request); ldp_msg_hello_get_targeted(msg,&target); ldp_msg_hello_get_csn(msg,&csn); if(ldp_msg_hello_get_traddr(msg,&traddr) == LDP_FAILURE) { addr = NULL; } else { addr = &traddr; } if((local_a = ldp_adj_create(&from->addr,&lsraddr,labelspace,hellotime,addr, csn)) == NULL) { LDP_EXIT(g->user_data,"ldp_state_new_adjacency-error"); return LDP_FAILURE; } if(ldp_entity_add_adj(e,local_a) == LDP_FAILURE) { ldp_adj_delete(local_a); LDP_EXIT(g->user_data,"ldp_state_new_adjacency-error"); return LDP_FAILURE; } ldp_hello_process(g,local_a,hellotime,csn,addr,target,request); if(ldp_adj_startup(g,local_a,request) == LDP_FAILURE) { ldp_entity_del_adj(e,local_a); ldp_adj_delete(local_a); LDP_EXIT(g->user_data,"ldp_state_new_adjacency-error"); return LDP_FAILURE; } LDP_EXIT(g->user_data,"ldp_state_new_adjacency"); return LDP_SUCCESS; } ldp_return_enum ldp_state_maintainance(ldp_global *g,ldp_session *s,ldp_adj *a, ldp_entity *e,uint32_t event,ldp_msg *msg,ldp_dest *from) { ldp_inet_addr traddr, *addr; int hellotime; int request = 0; int target = 0; uint32_t csn = 0; ldp_return_enum retval = LDP_FAILURE; LDP_ASSERT(msg != NULL && msg->hdr != NULL && msg->body != NULL && e != NULL); LDP_ENTER(g->user_data,"ldp_state_maintainance"); if(ldp_msg_hello_get_hellotime(msg,&hellotime) == LDP_FAILURE) { LDP_PRINT(g->user_data,"ldp_state_maintainance: failed\n"); return retval; } ldp_msg_hello_get_request(msg,&request); ldp_msg_hello_get_targeted(msg,&target); /* if there isn't a csn in the msg, then csn stays 0 */ ldp_msg_hello_get_csn(msg,&csn); if(ldp_msg_hello_get_traddr(msg,&traddr) == LDP_FAILURE) { addr = NULL; } else { addr = &traddr; } ldp_hello_process(g,a,hellotime,csn,addr,target,request); retval = ldp_adj_maintain_timer(g,a); LDP_EXIT(g->user_data,"ldp_state_maintainance"); return retval; } ldp_return_enum ldp_state_recv_init(ldp_global *g,ldp_session *s,ldp_adj *a, ldp_entity *e,uint32_t event,ldp_msg *msg,ldp_dest *from) { ldp_inet_addr lsraddr; int labelspace = 0; LDP_ASSERT(msg != NULL && msg->hdr != NULL && msg->body != NULL && s != NULL); LDP_ENTER(g->user_data,"ldp_state_recv_init"); if(s->adj == NULL) { ldp_adj* a = NULL; /* we haven't tied this session to an adj yet */ if(ldp_msg_hdr_get_lsraddr(msg,&lsraddr) == LDP_FAILURE || ldp_msg_hdr_get_labelspace(msg,&labelspace) == LDP_FAILURE) { LDP_PRINT(g->user_data,"ldp_state_recv_init: invalid message\n"); goto ldp_state_recv_init_shutdown; } if((a = ldp_global_find_adj_ldpid(g,&lsraddr,labelspace)) == NULL) { LDP_PRINT(g->user_data,"ldp_state_recv_init: cannot find adj\n"); goto ldp_state_recv_init_shutdown; } ldp_adj_add_session(a,s); } if(ldp_init_process(g,s,msg) == LDP_FAILURE) { LDP_PRINT(g->user_data,"ldp_state_recv_init: invalid INIT parameters\n"); goto ldp_state_recv_init_shutdown; } s->state = LDP_STATE_OPENREC; LDP_TRACE_LOG(g->user_data,LDP_TRACE_STATE_ALL,LDP_TRACE_FLAG_DEBUG, "ldp_state_recv_init: (%d) changed to OPENREC\n",s->index); if(s->adj && s->adj->role == LDP_PASSIVE) { if(ldp_init_send(g,s) == LDP_FAILURE) { LDP_PRINT(g->user_data,"ldp_state_recv_init: unable to send INIT\n"); goto ldp_state_recv_init_shutdown; } } ldp_keepalive_send(g,s); LDP_EXIT(g->user_data,"ldp_state_recv_init"); return LDP_SUCCESS; ldp_state_recv_init_shutdown: /* JLEU send notification */ ldp_session_shutdown(g,s,1); LDP_EXIT(g->user_data,"ldp_state_recv_init-error"); return LDP_FAILURE; } ldp_return_enum ldp_state_connect(ldp_global *g,ldp_session *s,ldp_adj *a, ldp_entity *e,uint32_t event,ldp_msg *msg,ldp_dest *from) { LDP_ENTER(g->user_data,"ldp_state_connect"); ldp_socket_readlist_add(g->socket_handle,s->socket,(void*)s,LDP_TCP_DATA); s->state = LDP_STATE_INITIALIZED; LDP_TRACE_LOG(g->user_data,LDP_TRACE_STATE_ALL,LDP_TRACE_FLAG_DEBUG, "ldp_state_connect: (%d) changed to INITIALIZED\n",s->index); if(s->adj && s->adj->role == LDP_ACTIVE) { if(ldp_init_send(g,s) == LDP_SUCCESS) { s->state = LDP_STATE_OPENSENT; LDP_TRACE_LOG(g->user_data,LDP_TRACE_STATE_ALL,LDP_TRACE_FLAG_DEBUG, "ldp_state_connect: (%d) changed to OPENSENT\n",s->index); } else { return LDP_FAILURE; } } else { if(from != NULL) { memcpy(&s->remote_dest,from,sizeof(ldp_dest)); } } LDP_EXIT(g->user_data,"ldp_state_connect"); return LDP_SUCCESS; } ldp_return_enum ldp_state_finish_init(ldp_global *g,ldp_session *s,ldp_adj *a, ldp_entity *e,uint32_t event,ldp_msg *msg,ldp_dest *from) { LDP_ASSERT(s != NULL && (a = s->adj) != NULL); LDP_ENTER(g->user_data,"ldp_state_finish_init"); ldp_session_startup(g,s); LDP_EXIT(g->user_data,"ldp_state_finish_init"); return LDP_SUCCESS; } ldp_return_enum ldp_state_process(ldp_global *g,ldp_session *s,ldp_adj *a, ldp_entity *e,uint32_t event,ldp_msg *msg,ldp_dest *from) { ldp_attr* r_attr; ldp_fec fec; int i; LDP_ASSERT(s != NULL && msg != NULL); LDP_ENTER(g->user_data,"ldp_state_process"); switch(((mplsLdpMsg_t*)msg->body)->flags.flags.msgType) { case MPLS_LBLWITH_MSGTYPE: { mplsLdpLbl_W_R_Msg_t* rw = (mplsLdpLbl_W_R_Msg_t*)msg->body; for(i = 0;i < rw->fecTlv.numberFecElements;i++) { fec_tlv2ldp_fec(&rw->fecTlv,i,&fec); r_attr = ldp_attr_create(&fec); if(r_attr == NULL) { return LDP_FAILURE; } LDP_REFCNT_HOLD(r_attr); rel_with2attr(rw,r_attr); if(ldp_label_withdraw_process(g,s,a,e,r_attr,&fec) == LDP_FAILURE) { if(r_attr->in_tree == LDP_TRUE) { ldp_attr_remove_complete(g,r_attr); } LDP_REFCNT_RELEASE(r_attr,ldp_attr_delete); return LDP_FAILURE; } LDP_REFCNT_RELEASE(r_attr,ldp_attr_delete); } return LDP_SUCCESS; } case MPLS_LBLREL_MSGTYPE: { mplsLdpLbl_W_R_Msg_t* rw = (mplsLdpLbl_W_R_Msg_t*)msg->body; for(i = 0;i < rw->fecTlv.numberFecElements;i++) { fec_tlv2ldp_fec(&rw->fecTlv,i,&fec); r_attr = ldp_attr_create(&fec); if(r_attr == NULL) { return LDP_FAILURE; } LDP_REFCNT_HOLD(r_attr); rel_with2attr(rw,r_attr); if(ldp_label_release_process(g,s,a,e,r_attr,&fec) == LDP_FAILURE) { if(r_attr->in_tree == LDP_TRUE) { ldp_attr_remove_complete(g,r_attr); } LDP_REFCNT_RELEASE(r_attr,ldp_attr_delete); return LDP_FAILURE; } LDP_REFCNT_RELEASE(r_attr,ldp_attr_delete); } return LDP_SUCCESS; } case MPLS_LBLREQ_MSGTYPE: { mplsLdpLblReqMsg_t* req = (mplsLdpLblReqMsg_t*)msg->body; LDP_ASSERT(req->fecTlv.numberFecElements == 1); for(i = 0;i < req->fecTlv.numberFecElements;i++) { fec_tlv2ldp_fec(&req->fecTlv,i,&fec); r_attr = ldp_attr_create(&fec); if(r_attr == NULL) { return LDP_FAILURE; } LDP_REFCNT_HOLD(r_attr); req2attr(req,r_attr,LDP_ATTR_ALL); if(ldp_label_request_process(g,s,a,e,r_attr,&fec) == LDP_FAILURE) { if(r_attr->in_tree == LDP_TRUE) { ldp_attr_remove_complete(g,r_attr); } LDP_REFCNT_RELEASE(r_attr,ldp_attr_delete); return LDP_FAILURE; } LDP_REFCNT_RELEASE(r_attr,ldp_attr_delete); } return LDP_SUCCESS; } case MPLS_LBLMAP_MSGTYPE: { mplsLdpLblMapMsg_t* map = (mplsLdpLblMapMsg_t*)msg->body; for(i = 0;i < map->fecTlv.numberFecElements;i++) { fec_tlv2ldp_fec(&map->fecTlv,i,&fec); r_attr = ldp_attr_create(&fec); if(r_attr == NULL) { return LDP_FAILURE; } LDP_REFCNT_HOLD(r_attr); map2attr(map,r_attr,LDP_ATTR_ALL); if(ldp_label_mapping_process(g,s,a,e,r_attr,&fec) == LDP_FAILURE) { if(r_attr->in_tree == LDP_TRUE) { ldp_attr_remove_complete(g,r_attr); } LDP_REFCNT_RELEASE(r_attr,ldp_attr_delete); return LDP_FAILURE; } LDP_REFCNT_RELEASE(r_attr,ldp_attr_delete); } return LDP_SUCCESS; } case MPLS_LBLABORT_MSGTYPE: LDP_ASSERT(0); case MPLS_ADDRWITH_MSGTYPE: case MPLS_ADDR_MSGTYPE: if(ldp_addr_process(g,s,e,msg) == LDP_FAILURE) { return LDP_FAILURE; } return LDP_SUCCESS; default: LDP_ASSERT(0); break; } LDP_EXIT(g->user_data,"ldp_state_process"); return LDP_FAILURE; } ldp_return_enum ldp_state_ignore(ldp_global *g,ldp_session *session, ldp_adj *adj,ldp_entity *entity,uint32_t event,ldp_msg *msg,ldp_dest *from) { LDP_ASSERT(0); return LDP_FAILURE; } ldp_return_enum ldp_state_close(ldp_global *g,ldp_session *s,ldp_adj *a, ldp_entity *e,uint32_t event,ldp_msg *msg,ldp_dest *from) { LDP_ENTER(g->user_data,"ldp_state_close"); /* JLEU: this need more work */ if(s != NULL) ldp_session_shutdown(g,s,0); LDP_EXIT(g->user_data,"ldp_state_close"); return LDP_SUCCESS; } ldp_return_enum ldp_state_keepalive_maintainance(ldp_global *g,ldp_session *s, ldp_adj *a,ldp_entity *e,uint32_t event,ldp_msg *msg,ldp_dest *from) { ldp_return_enum result = LDP_FAILURE; LDP_ASSERT(s != NULL); LDP_ENTER(g->user_data,"ldp_state_keepalive_maintainance"); result = ldp_session_maintain_timer(g,s,LDP_KEEPALIVE_RECV); LDP_EXIT(g->user_data,"ldp_state_keepalive_maintainance"); return result; } ldp_return_enum ldp_state_notification(ldp_global *g,ldp_session *session, ldp_adj *adj,ldp_entity *entity,uint32_t event,ldp_msg *msg,ldp_dest *from) { LDP_ENTER(g->user_data,"ldp_state_notification"); LDP_ASSERT(0); return LDP_FAILURE; }