/* * 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 "ldp_struct.h" #include "ldp_assert.h" #include "ldp_msg.h" #include "ldp_nortel.h" #include "ldp_pdu.h" #include "ldp_pdu_setup.h" #include "ldp_socket_impl.h" #include "ldp_trace_impl.h" ldp_msg* ldp_init_create(ldp_global* g,uint32_t msgid,ldp_session* s) { mplsLdpInitMsg_t *init = NULL; ldp_entity* e = NULL; ldp_adj* a = NULL; ldp_msg* msg = NULL; uint8_t len = 0; uint8_t merge = 0, direction = 0; uint32_t loop,remote_lsraddr,remote_labelspace,path_vector_limit; LDP_ASSERT(s != NULL); e = s->entity; LDP_ASSERT(e != NULL); a = s->adj; LDP_ASSERT(a != NULL && s->entity->p.iff != NULL); LDP_ENTER(g->user_data,"ldp_init_create"); msg = ldp_msg_create(MPLS_INIT_MSGTYPE,msgid); if(msg != NULL) { init = (mplsLdpInitMsg_t*)msg->body; remote_lsraddr = a->remote_lsr_address.u.ipv4; remote_labelspace = a->remote_label_space; loop = (g->loop_detection_mode == LDP_LOOP_NONE)?(0):(1); if(loop == LDP_LOOP_NONE) { path_vector_limit = 0; } else { path_vector_limit = s->oper_path_vector_limit; } init->cspExists = 1; init->baseMsg.msgLength += setupCspTlv(&(init->csp),s->oper_keepalive, s->oper_distribution_mode,loop,path_vector_limit,s->oper_max_pdu, remote_lsraddr,remote_labelspace,0); init->aspExists = 0; init->fspExists = 0; if(e->entity_type != LDP_INDIRECT) { switch(e->p.iff->range->type) { case LDP_ATM_VP: LDP_ASSERT(0); case LDP_ATM_VC: case LDP_ATM_VP_VC: init->aspExists = 1; init->baseMsg.msgLength += setupAspTlv(&(init->asp),merge,direction); init->baseMsg.msgLength += addLblRng2AspTlv(&(init->asp), e->p.iff->range->min.atm.vpi, e->p.iff->range->min.atm.vci, e->p.iff->range->max.atm.vpi, e->p.iff->range->max.atm.vci); break; case LDP_FR_10: len = 0; /* Section 3.5.3 fspTlv */ case LDP_FR_24: init->fspExists = 1; if(e->p.iff->range->type == LDP_FR_24) len = 2; /* Section 3.5.3 fspTlv */ init->baseMsg.msgLength += setupFspTlv(&(init->fsp),merge,direction); init->baseMsg.msgLength += addLblRng2FspTlv(&(init->fsp),0,len, e->p.iff->range->min.fr,0, e->p.iff->range->max.fr); break; case LDP_GENERIC: break; } } } LDP_EXIT(g->user_data,"ldp_init_create"); return msg; } ldp_return_enum ldp_init_send(ldp_global* g,ldp_session* s) { ldp_msg* init = NULL; ldp_return_enum result = LDP_FAILURE; LDP_ASSERT(s != NULL); LDP_ENTER(g->user_data,"ldp_init_send"); if((init = ldp_init_create(g,g->message_identifier++,s)) == NULL) return LDP_FAILURE; LDP_TRACE_LOG(g->user_data,LDP_TRACE_STATE_SEND,LDP_TRACE_FLAG_INIT, "Init Send: session(%d)\n",s->index); result = ldp_msg_send_tcp(g,s,init); ldp_msg_delete(init); LDP_EXIT(g->user_data,"ldp_init_send"); return result; } ldp_return_enum ldp_init_process(ldp_global* g,ldp_session* s,ldp_msg* msg) { uint16_t label_space; ldp_range* range = NULL; ldp_entity* e = NULL; MPLS_MSGPTR(Init); LDP_ASSERT(s != NULL); e = s->entity; LDP_ASSERT(e != NULL); LDP_ENTER(g->user_data,"ldp_init_process"); LDP_TRACE_LOG(g->user_data,LDP_TRACE_STATE_RECV,LDP_TRACE_FLAG_INIT, "Init Recv: session(%d)\n",s->index); MPLS_MSGCAST(Init,msg->body); switch(s->entity->entity_type) { case LDP_DIRECT: label_space = s->entity->p.iff->label_space; range = s->entity->p.iff->range; break; case LDP_INDIRECT: label_space = s->entity->p.peer->label_space; range = s->entity->p.peer->range; break; default: LDP_ASSERT(0); } if(MPLS_MSGPARAM(Init)->csp.rcvLsrAddress != g->lsr_identifier.u.ipv4 || MPLS_MSGPARAM(Init)->csp.rcvLsId != label_space) { LDP_EXIT(g->user_data,"ldp_init_process-error"); return LDP_FAILURE; } if(MPLS_MSGPARAM(Init)->csp.holdTime == 0) { LDP_EXIT(g->user_data,"ldp_init_process-error"); return LDP_FAILURE; } if(MPLS_MSGPARAM(Init)->csp.maxPduLen <= 255) MPLS_MSGPARAM(Init)->csp.maxPduLen = 4096; /* Section 3.5.3. */ s->remote_max_pdu = MPLS_MSGPARAM(Init)->csp.maxPduLen; s->remote_keepalive = MPLS_MSGPARAM(Init)->csp.holdTime; s->remote_path_vector_limit = MPLS_MSGPARAM(Init)->csp.flags.flags.pvl; s->remote_distribution_mode = (ldp_distribution_mode)MPLS_MSGPARAM(Init)->csp.flags.flags.lad; if(MPLS_MSGPARAM(Init)->csp.flags.flags.ld == 0) { s->remote_loop_detection = LDP_FALSE; } else { s->remote_loop_detection = LDP_TRUE; } if(s->remote_max_pdu < e->max_pdu) s->oper_max_pdu = s->remote_max_pdu; if(s->remote_distribution_mode != e->label_distribution_mode) { if(!range || (range->type == LDP_GENERIC)) { s->oper_distribution_mode = LDP_DISTRIBUTION_UNSOLICITED; } else { s->oper_distribution_mode = LDP_DISTRIBUTION_ONDEMAND; } } if((s->remote_loop_detection == LDP_TRUE) && (g->loop_detection_mode != LDP_LOOP_NONE)) { s->oper_loop_detection = g->loop_detection_mode; } else { s->oper_loop_detection = LDP_LOOP_NONE; } if(MPLS_MSGPARAM(Init)->aspExists) { if(range && (range->type >= LDP_ATM_VP && range->type <= LDP_ATM_VP_VC)) { LDP_ASSERT(0); } else { return LDP_FAILURE; } } else if(MPLS_MSGPARAM(Init)->fspExists) { if(range && (range->type >= LDP_FR_10 && range->type <= LDP_FR_24)) { LDP_ASSERT(0); } else { return LDP_FAILURE; } } LDP_EXIT(g->user_data,"ldp_init_process"); return LDP_SUCCESS; }