3 * Copyright (C) James R. Leu 2000
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
10 #include <sys/socket.h>
11 #include "ldp_struct.h"
12 #include "ldp_global.h"
13 #include "ldp_session.h"
14 #include "ldp_entity.h"
19 #include "ldp_hello.h"
21 #include "ldp_label_rel_with.h"
22 #include "ldp_label_mapping.h"
23 #include "ldp_label_request.h"
25 #include "ldp_keepalive.h"
26 #include "ldp_label_request.h"
27 #include "ldp_label_mapping.h"
28 #include "ldp_notif.h"
29 #include "ldp_label_abort.h"
30 #include "ldp_inet_addr.h"
32 #include "mpls_assert.h"
33 #include "mpls_tree_impl.h"
34 #include "mpls_trace_impl.h"
35 #include "mpls_socket_impl.h"
37 mpls_return_enum
ldp_state_new_adjacency(ldp_global
* g
, ldp_session
* s
,
38 ldp_adj
* a
, ldp_entity
* e
, uint32_t event
, ldp_mesg
* msg
, mpls_dest
* from
)
40 mpls_inet_addr traddr
, lsraddr
, *addr
;
41 ldp_adj
*local_a
= NULL
;
47 mpls_return_enum retval
= MPLS_FAILURE
;
49 MPLS_ASSERT(msg
&& e
);
51 LDP_ENTER(g
->user_data
, "ldp_state_new_adjacency");
53 ldp_mesg_hdr_get_labelspace(msg
, &labelspace
);
54 ldp_mesg_hdr_get_lsraddr(msg
, &lsraddr
);
55 ldp_mesg_hello_get_hellotime(msg
, &hellotime
);
56 ldp_mesg_hello_get_request(msg
, &request
);
57 ldp_mesg_hello_get_targeted(msg
, &target
);
58 ldp_mesg_hello_get_csn(msg
, &csn
);
60 if (ldp_mesg_hello_get_traddr(msg
, &traddr
) == MPLS_FAILURE
) {
68 if ((local_a
= ldp_adj_create(&from
->addr
, &lsraddr
, labelspace
,
69 hellotime
, addr
, csn
)) == NULL
) {
70 goto ldp_state_new_adjacency_end
;
72 ldp_entity_add_adj(e
, local_a
);
73 _ldp_global_add_adj(g
, local_a
);
74 if (ldp_hello_process(g
, local_a
, e
, hellotime
, csn
, addr
, target
,
75 request
) != MPLS_SUCCESS
) {
76 /* this can fail if we could not create an active session, or
77 * we're getting errored hellos,
78 * if this fails then undo the e<->a linking (which will delete a) */
79 ldp_entity_del_adj(e
, local_a
);
80 _ldp_global_del_adj(g
, local_a
);
81 } else if (ldp_adj_startup(g
, local_a
, request
) != MPLS_SUCCESS
) {
82 /* the only way this fail is if a timer could not be created
83 * if this fails then undo the e<->a linking (which will delete a) */
84 ldp_entity_del_adj(e
, local_a
);
85 _ldp_global_del_adj(g
, local_a
);
87 /* by this time, we will have a e<->a binding, and some timers,
88 * if we're active, there will also be an active session */
89 retval
= MPLS_SUCCESS
;
92 ldp_state_new_adjacency_end
:
94 LDP_EXIT(g
->user_data
, "ldp_state_new_adjacency");
98 mpls_return_enum
ldp_state_maintainance(ldp_global
* g
, ldp_session
* s
,
99 ldp_adj
* a
, ldp_entity
* e
, uint32_t event
, ldp_mesg
* msg
, mpls_dest
* from
)
101 mpls_inet_addr traddr
, *addr
;
106 mpls_return_enum retval
= MPLS_SUCCESS
;
108 MPLS_ASSERT(msg
&& e
);
110 LDP_ENTER(g
->user_data
, "ldp_state_maintainance");
112 if (ldp_mesg_hello_get_hellotime(msg
, &hellotime
) != MPLS_SUCCESS
) {
113 retval
= MPLS_FAILURE
;
114 goto ldp_state_maintainance_end
;
117 ldp_mesg_hello_get_request(msg
, &request
);
118 ldp_mesg_hello_get_targeted(msg
, &target
);
119 /* if there isn't a csn in the msg, then csn stays 0 */
120 ldp_mesg_hello_get_csn(msg
, &csn
);
121 if (ldp_mesg_hello_get_traddr(msg
, &traddr
) != MPLS_SUCCESS
) {
127 if (ldp_hello_process(g
, a
, e
, hellotime
, csn
, addr
, target
,
128 request
) != MPLS_SUCCESS
) {
129 retval
= MPLS_FAILURE
;
130 goto ldp_state_maintainance_end
;
132 retval
= ldp_adj_maintain_timer(g
, a
);
135 ldp_state_maintainance_end
:
137 LDP_EXIT(g
->user_data
, "ldp_state_maintainance");
142 mpls_return_enum
ldp_state_recv_init(ldp_global
* g
, ldp_session
* s
,
143 ldp_adj
* a
, ldp_entity
* e
, uint32_t event
, ldp_mesg
* msg
, mpls_dest
* from
)
145 mpls_inet_addr lsraddr
;
148 mpls_bool match
= MPLS_BOOL_FALSE
;
150 MPLS_ASSERT(msg
&& s
);
152 LDP_ENTER(g
->user_data
, "ldp_state_recv_init");
154 /* we haven't tied this session to an adj yet, at a minimum we can
155 * now stop the backoff timer we started while waiting for this
157 ldp_session_backoff_stop(g
, s
);
159 ldp_mesg_hdr_get_lsraddr(msg
, &lsraddr
);
160 ldp_mesg_hdr_get_labelspace(msg
, &labelspace
);
162 if (s
->oper_role
!= LDP_ACTIVE
) {
163 /* sessions being created from the ACTIVE side of an ADJ have already
164 * bound to the session */
165 /* there may be multiple ADJ that are matched! */
166 ap
= MPLS_LIST_HEAD(&g
->adj
);
168 if ((!mpls_inet_addr_compare(&lsraddr
, &ap
->remote_lsr_address
)) &&
169 labelspace
== ap
->remote_label_space
&& !ap
->session
) {
170 ldp_adj_add_session(ap
, s
);
171 match
= MPLS_BOOL_TRUE
;
173 ap
= MPLS_LIST_NEXT(&g
->adj
, ap
, _global
);
176 if (match
== MPLS_BOOL_FALSE
) {
177 LDP_PRINT(g
->user_data
, "ldp_state_recv_init: cannot find adj\n");
178 s
->shutdown_notif
= LDP_NOTIF_SESSION_REJECTED_NO_HELLO
;
179 s
->shutdown_fatal
= MPLS_BOOL_FALSE
;
180 goto ldp_state_recv_init_shutdown
;
184 if (ldp_init_process(g
, s
, msg
) == MPLS_FAILURE
) {
185 LDP_PRINT(g
->user_data
, "ldp_state_recv_init: invalid INIT parameters\n");
186 /* session shutdown notif info set inside init_process */
187 goto ldp_state_recv_init_shutdown
;
190 s
->state
= LDP_STATE_OPENREC
;
191 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
192 "ldp_state_recv_init: (%d) changed to OPENREC\n", s
->index
);
194 if (s
->oper_role
== LDP_PASSIVE
) {
195 if (ldp_init_send(g
, s
) == MPLS_FAILURE
) {
196 LDP_PRINT(g
->user_data
, "ldp_state_recv_init: unable to send INIT\n");
197 s
->shutdown_notif
= LDP_NOTIF_INTERNAL_ERROR
;
198 s
->shutdown_fatal
= MPLS_BOOL_TRUE
;
199 goto ldp_state_recv_init_shutdown
;
202 ldp_keepalive_send(g
, s
);
204 LDP_EXIT(g
->user_data
, "ldp_state_recv_init");
207 ldp_state_recv_init_shutdown
:
209 LDP_EXIT(g
->user_data
, "ldp_state_recv_init-error");
213 mpls_return_enum
ldp_state_connect(ldp_global
* g
, ldp_session
* s
, ldp_adj
* a
,
214 ldp_entity
* e
, uint32_t event
, ldp_mesg
* msg
, mpls_dest
* from
)
216 mpls_return_enum retval
= MPLS_SUCCESS
;
218 LDP_ENTER(g
->user_data
, "ldp_state_connect");
220 mpls_socket_readlist_add(g
->socket_handle
, s
->socket
, (void *)s
,
221 MPLS_SOCKET_TCP_DATA
);
222 s
->state
= LDP_STATE_INITIALIZED
;
223 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
224 "ldp_state_connect: (%d) changed to INITIALIZED\n", s
->index
);
226 /* even though as part of creating an active session, the remote_dest
227 * was filled in, it had port 646 specified. 'from' now contains the
228 * real port info that our TCP session is connected to */
230 memcpy(&s
->remote_dest
, from
, sizeof(mpls_dest
));
233 if (s
->oper_role
== LDP_ACTIVE
) {
234 if (ldp_init_send(g
, s
) == MPLS_SUCCESS
) {
235 s
->state
= LDP_STATE_OPENSENT
;
236 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
237 "ldp_state_connect: (%d) changed to OPENSENT\n", s
->index
);
239 s
->shutdown_notif
= LDP_NOTIF_INTERNAL_ERROR
;
240 s
->shutdown_fatal
= MPLS_BOOL_TRUE
;
241 retval
= MPLS_FAILURE
;
244 /* if this session is passive, we still are not associated with an
245 * adj. That will happen when we receive an init. There are no timers
246 * running yet, so we need to create a timer, to clean this socket
247 * up, if we do not receive a Init mesg, we'll overload the backoff
248 * timer for this purpose */
249 retval
= ldp_session_backoff_start(g
, s
);
252 LDP_EXIT(g
->user_data
, "ldp_state_connect");
257 mpls_return_enum
ldp_state_finish_init(ldp_global
* g
, ldp_session
* s
,
258 ldp_adj
* a
, ldp_entity
* e
, uint32_t event
, ldp_mesg
* msg
, mpls_dest
* from
)
260 mpls_return_enum retval
;
263 LDP_ENTER(g
->user_data
, "ldp_state_finish_init");
265 retval
= ldp_session_startup(g
, s
);
267 LDP_EXIT(g
->user_data
, "ldp_state_finish_init");
272 mpls_return_enum
ldp_state_process(ldp_global
* g
, ldp_session
* s
, ldp_adj
* a
,
273 ldp_entity
* e
, uint32_t event
, ldp_mesg
* msg
, mpls_dest
* from
)
275 mpls_return_enum retval
= MPLS_SUCCESS
;
280 MPLS_ASSERT(s
&& msg
);
282 LDP_ENTER(g
->user_data
, "ldp_state_process");
284 switch (msg
->u
.generic
.flags
.flags
.msgType
) {
285 case MPLS_LBLWITH_MSGTYPE
:
287 mplsLdpLbl_W_R_Msg_t
*rw
= &msg
->u
.release
;
290 for (i
= 0; i
< rw
->fecTlv
.numberFecElements
; i
++) {
291 fec_tlv2mpls_fec(&rw
->fecTlv
, i
, &fec
);
292 if (!(r_attr
= ldp_attr_create(g
, &fec
))) {
293 goto ldp_state_process_error
;
296 MPLS_REFCNT_HOLD(r_attr
);
298 rel_with2attr(rw
, r_attr
);
299 f
= ldp_fec_find2(g
, &fec
);
302 retval
= ldp_label_withdraw_process(g
, s
, a
, e
, r_attr
, f
);
304 MPLS_REFCNT_RELEASE2(g
, f
, ldp_fec_delete
);
305 MPLS_REFCNT_RELEASE2(g
, r_attr
, ldp_attr_delete
);
306 if (retval
!= MPLS_SUCCESS
)
311 case MPLS_LBLREL_MSGTYPE
:
313 mplsLdpLbl_W_R_Msg_t
*rw
= &msg
->u
.release
;
316 for (i
= 0; i
< rw
->fecTlv
.numberFecElements
; i
++) {
317 fec_tlv2mpls_fec(&rw
->fecTlv
, i
, &fec
);
318 if (!(r_attr
= ldp_attr_create(g
, &fec
))) {
319 goto ldp_state_process_error
;
322 MPLS_REFCNT_HOLD(r_attr
);
324 rel_with2attr(rw
, r_attr
);
325 f
= ldp_fec_find2(g
, &fec
);
328 retval
= ldp_label_release_process(g
, s
, a
, e
, r_attr
, f
);
330 MPLS_REFCNT_RELEASE2(g
, f
, ldp_fec_delete
);
331 MPLS_REFCNT_RELEASE2(g
, r_attr
, ldp_attr_delete
);
332 if (retval
!= MPLS_SUCCESS
)
337 case MPLS_LBLREQ_MSGTYPE
:
339 mplsLdpLblReqMsg_t
*req
= &msg
->u
.request
;
342 MPLS_ASSERT(req
->fecTlv
.numberFecElements
== 1);
344 for (i
= 0; i
< req
->fecTlv
.numberFecElements
; i
++) {
345 fec_tlv2mpls_fec(&req
->fecTlv
, i
, &fec
);
346 if (!(r_attr
= ldp_attr_create(g
, &fec
))) {
347 goto ldp_state_process_error
;
350 MPLS_REFCNT_HOLD(r_attr
);
352 req2attr(req
, r_attr
, LDP_ATTR_ALL
& ~LDP_ATTR_FEC
);
353 f
= ldp_fec_find2(g
, &fec
);
356 retval
= ldp_label_request_process(g
, s
, a
, e
, r_attr
, f
);
358 MPLS_REFCNT_RELEASE2(g
, f
, ldp_fec_delete
);
359 MPLS_REFCNT_RELEASE2(g
, r_attr
, ldp_attr_delete
);
360 if (retval
!= MPLS_SUCCESS
)
365 case MPLS_LBLMAP_MSGTYPE
:
367 mplsLdpLblMapMsg_t
*map
= &msg
->u
.map
;
370 for (i
= 0; i
< map
->fecTlv
.numberFecElements
; i
++) {
371 fec_tlv2mpls_fec(&map
->fecTlv
, i
, &fec
);
372 if (!(r_attr
= ldp_attr_create(g
, &fec
))) {
373 goto ldp_state_process_error
;
376 MPLS_REFCNT_HOLD(r_attr
);
378 map2attr(map
, r_attr
, LDP_ATTR_ALL
& ~LDP_ATTR_FEC
);
379 f
= ldp_fec_find2(g
, &fec
);
382 retval
= ldp_label_mapping_process(g
, s
, a
, e
, r_attr
, f
);
384 MPLS_REFCNT_RELEASE2(g
, f
, ldp_fec_delete
);
385 MPLS_REFCNT_RELEASE2(g
, r_attr
, ldp_attr_delete
);
386 if (retval
!= MPLS_SUCCESS
)
391 case MPLS_LBLABORT_MSGTYPE
:
393 mplsLdpLblAbortMsg_t
*abrt
= &msg
->u
.abort
;
396 for (i
= 0; i
< abrt
->fecTlv
.numberFecElements
; i
++) {
397 fec_tlv2mpls_fec(&abrt
->fecTlv
, i
, &fec
);
398 if (!(r_attr
= ldp_attr_create(g
, &fec
))) {
399 goto ldp_state_process_error
;
402 MPLS_REFCNT_HOLD(r_attr
);
404 abort2attr(abrt
, r_attr
, LDP_ATTR_ALL
& ~LDP_ATTR_FEC
);
405 f
= ldp_fec_find2(g
, &fec
);
408 retval
= ldp_label_abort_process(g
, s
, a
, e
, r_attr
, f
);
410 MPLS_REFCNT_RELEASE2(g
, f
, ldp_fec_delete
);
411 MPLS_REFCNT_RELEASE2(g
, r_attr
, ldp_attr_delete
);
412 if (retval
!= MPLS_SUCCESS
)
417 case MPLS_ADDRWITH_MSGTYPE
:
418 case MPLS_ADDR_MSGTYPE
:
420 retval
= ldp_addr_process(g
, s
, e
, msg
);
430 LDP_EXIT(g
->user_data
, "ldp_state_process");
434 ldp_state_process_error
:
436 LDP_EXIT(g
->user_data
, "ldp_state_process");
438 s
->shutdown_notif
= LDP_NOTIF_INTERNAL_ERROR
;
439 s
->shutdown_fatal
= MPLS_BOOL_TRUE
;
443 mpls_return_enum
ldp_state_ignore(ldp_global
* g
, ldp_session
* session
,
444 ldp_adj
* adj
, ldp_entity
* entity
, uint32_t event
, ldp_mesg
* msg
,
450 mpls_return_enum
ldp_state_close(ldp_global
* g
, ldp_session
* s
, ldp_adj
* a
,
451 ldp_entity
* e
, uint32_t event
, ldp_mesg
* msg
, mpls_dest
* from
)
454 LDP_ENTER(g
->user_data
, "ldp_state_close: a = %p, e = %p s = %p",a
,e
,s
);
456 /* JLEU: this need more work */
458 /* not sure why we got here but we should tear it completely down */
459 if (s
->shutdown_fatal
!= MPLS_BOOL_TRUE
) {
460 ldp_notif_send(g
,s
,NULL
,s
->shutdown_notif
);
462 ldp_session_shutdown(g
, s
, MPLS_BOOL_TRUE
);
465 LDP_EXIT(g
->user_data
, "ldp_state_close");
469 mpls_return_enum
ldp_state_keepalive_maintainance(ldp_global
* g
,
470 ldp_session
* s
, ldp_adj
* a
, ldp_entity
* e
, uint32_t event
, ldp_mesg
* msg
,
473 mpls_return_enum result
;
477 LDP_ENTER(g
->user_data
, "ldp_state_keepalive_maintainance");
478 result
= ldp_session_maintain_timer(g
, s
, LDP_KEEPALIVE_RECV
);
480 LDP_EXIT(g
->user_data
, "ldp_state_keepalive_maintainance");
485 mpls_return_enum
ldp_state_notif(ldp_global
* g
, ldp_session
* s
, ldp_adj
* adj
,
486 ldp_entity
* entity
, uint32_t event
, ldp_mesg
* msg
, mpls_dest
* from
)
489 mpls_return_enum retval
= MPLS_SUCCESS
;
490 ldp_attr
*r_attr
= NULL
;
491 mplsLdpNotifMsg_t
*not = &msg
->u
.notif
;
493 MPLS_ASSERT(s
&& msg
);
495 LDP_ENTER(g
->user_data
, "ldp_state_notif");
497 if (!(r_attr
= ldp_attr_create(g
, NULL
))) {
498 retval
= MPLS_FAILURE
;
499 goto ldp_state_notif_end
;
502 MPLS_REFCNT_HOLD(r_attr
);
504 not2attr(not, r_attr
, LDP_ATTR_ALL
);
505 retval
= ldp_notif_process(g
, s
, adj
, entity
, r_attr
);
507 MPLS_REFCNT_RELEASE2(g
, r_attr
, ldp_attr_delete
);
511 LDP_EXIT(g
->user_data
, "ldp_state_notif");