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
12 #include <sys/socket.h>
13 #include "ldp_struct.h"
14 #include "ldp_session.h"
15 #include "ldp_entity.h"
16 #include "ldp_pdu_setup.h"
21 #include "mpls_ifmgr_impl.h"
22 #include "mpls_mm_impl.h"
23 #include "mpls_trace_impl.h"
24 #include "mpls_tree_impl.h"
26 static uint32_t _ldp_addr_next_index
= 1;
28 ldp_addr
*ldp_addr_create(mpls_inet_addr
* address
)
30 ldp_addr
*a
= (ldp_addr
*) mpls_malloc(sizeof(ldp_addr
));
33 MPLS_REFCNT_INIT(a
, 0);
34 mpls_link_list_init(&a
->session_root
);
35 MPLS_LIST_INIT(&a
->l2cc_root
, ldp_l2cc
);
36 memcpy(&a
->address
, address
, sizeof(mpls_inet_addr
));
37 a
->index
= _ldp_addr_get_next_index();
42 void ldp_addr_delete(ldp_addr
* a
)
44 LDP_PRINT(g
->user_data
,"addr delete\n");
48 mpls_return_enum
_ldp_addr_add_session(ldp_addr
* a
, ldp_session
* s
)
52 if (mpls_link_list_add_tail(&a
->session_root
, s
) == MPLS_SUCCESS
) {
55 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
59 void _ldp_addr_del_session(ldp_addr
* a
, ldp_session
* s
)
62 mpls_link_list_remove_data(&a
->session_root
, s
);
63 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
66 void ldp_addr_add_l2cc(ldp_addr
* a
, ldp_l2cc
* l
)
72 lp
= MPLS_LIST_HEAD(&a
->l2cc_root
);
74 if (lp
->index
> l
->index
) {
75 MPLS_LIST_INSERT_BEFORE(&a
->l2cc_root
, lp
, l
, _addr
);
78 lp
= MPLS_LIST_NEXT(&a
->l2cc_root
, lp
, _addr
);
80 MPLS_LIST_ADD_TAIL(&a
->l2cc_root
, l
, _addr
, ldp_l2cc
);
83 void ldp_addr_del_l2cc(ldp_addr
* a
, ldp_l2cc
* l
)
86 MPLS_LIST_REMOVE(&a
->l2cc_root
, l
, _addr
);
87 MPLS_REFCNT_RELEASE(l
, ldp_l2cc_delete
);
90 uint32_t _ldp_addr_get_next_index()
92 uint32_t retval
= _ldp_addr_next_index
;
94 _ldp_addr_next_index
++;
95 if (retval
> _ldp_addr_next_index
) {
96 _ldp_addr_next_index
= 1;
101 void ldp_addr_mesg_prepare(ldp_mesg
* msg
, ldp_global
* g
, uint32_t msgid
,
102 mpls_inet_addr
* addr
)
106 LDP_ENTER(g
->user_data
, "ldp_addr_mesg_prepare");
108 ldp_mesg_prepare(msg
, MPLS_ADDR_MSGTYPE
, msgid
);
109 MPLS_MSGPARAM(Adr
) = &msg
->u
.addr
;
111 MPLS_MSGPARAM(Adr
)->adrListTlvExists
= 1;
112 MPLS_MSGPARAM(Adr
)->baseMsg
.msgLength
+=
113 setupAddrTlv(&(MPLS_MSGPARAM(Adr
)->addressList
));
115 MPLS_MSGPARAM(Adr
)->baseMsg
.msgLength
+=
116 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr
)->addressList
), addr
->u
.ipv4
);
118 LDP_EXIT(g
->user_data
, "ldp_addr_mesg_prepare");
121 void ldp_waddr_mesg_prepare(ldp_mesg
* msg
, ldp_global
* g
, uint32_t msgid
,
122 mpls_inet_addr
* addr
)
126 LDP_ENTER(g
->user_data
, "ldp_waddr_mesg_prepare");
128 ldp_mesg_prepare(msg
, MPLS_ADDRWITH_MSGTYPE
, msgid
);
129 MPLS_MSGPARAM(Adr
) = &msg
->u
.addr
;
131 MPLS_MSGPARAM(Adr
)->adrListTlvExists
= 1;
132 MPLS_MSGPARAM(Adr
)->baseMsg
.msgLength
+=
133 setupAddrTlv(&(MPLS_MSGPARAM(Adr
)->addressList
));
135 MPLS_MSGPARAM(Adr
)->baseMsg
.msgLength
+=
136 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr
)->addressList
), addr
->u
.ipv4
);
138 LDP_EXIT(g
->user_data
, "ldp_waddr_mesg_prepare");
141 mpls_return_enum
ldp_addr_send(ldp_global
* g
, ldp_session
* s
,
144 mpls_return_enum result
= MPLS_FAILURE
;
148 LDP_ENTER(g
->user_data
, "ldp_addr_send");
150 ldp_addr_mesg_prepare(s
->tx_message
, g
, g
->message_identifier
++, a
);
152 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_ADDRESS
,
153 "Addr Send: session(%d)\n", s
->index
);
155 result
= ldp_mesg_send_tcp(g
, s
, s
->tx_message
);
157 LDP_EXIT(g
->user_data
, "ldp_addr_send");
162 mpls_return_enum
ldp_waddr_send(ldp_global
* g
, ldp_session
* s
,
165 mpls_return_enum result
= MPLS_FAILURE
;
169 LDP_ENTER(g
->user_data
, "ldp_waddr_send");
171 ldp_waddr_mesg_prepare(s
->tx_message
, g
, g
->message_identifier
++, a
);
173 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_ADDRESS
,
174 "Addr Withdraw Send: session(%d)\n", s
->index
);
176 result
= ldp_mesg_send_tcp(g
, s
, s
->tx_message
);
178 LDP_EXIT(g
->user_data
, "ldp_waddr_send");
183 mpls_return_enum
ldp_addr_process(ldp_global
* g
, ldp_session
* s
,
184 ldp_entity
* e
, ldp_mesg
* msg
)
186 mplsLdpAdrMsg_t
*body
= &msg
->u
.addr
;
188 ldp_addr
*addr
= NULL
;
189 int len
= (body
->addressList
.baseTlv
.length
- MPLS_ADDFAMFIXLEN
) /
193 LDP_ENTER(g
->user_data
, "ldp_addr_process");
195 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_RECV
, LDP_TRACE_FLAG_ADDRESS
,
196 "Addr Recv: session(%d)\n", s
->index
);
198 for (i
= 0; i
< len
; i
++) {
199 inet
.type
= MPLS_FAMILY_IPV4
;
200 inet
.u
.ipv4
= body
->addressList
.address
[i
];
202 if (msg
->u
.generic
.flags
.flags
.msgType
== MPLS_ADDR_MSGTYPE
) {
203 if (mpls_tree_get(g
->addr_tree
, inet
.u
.ipv4
, 32, (void **)&addr
) ==
205 /* it's not in the tree, put it there! */
206 if ((addr
= ldp_addr_create(&inet
)) == NULL
) {
207 LDP_PRINT(g
->user_data
, "ldp_addr_process: error creating address\n");
208 goto ldp_addr_process_end
;
210 MPLS_REFCNT_HOLD(addr
);
211 if (mpls_tree_insert(g
->addr_tree
, inet
.u
.ipv4
, 32, (void *)addr
) ==
213 LDP_PRINT(g
->user_data
, "ldp_addr_process: error adding addr\n");
214 goto ldp_addr_process_end
;
218 /* the addr is in the tree */
219 if (ldp_session_add_addr(s
, addr
) == MPLS_FAILURE
) {
220 LDP_PRINT(g
->user_data
,
221 "ldp_addr_process: error adding address to session\n");
226 if (mpls_tree_get(g
->addr_tree
, inet
.u
.ipv4
, 32, (void **)&addr
) ==
228 ldp_session_del_addr(s
, addr
);
229 if (MPLS_REFCNT_VALUE(addr
) == 1) {
230 /* the tree is the last one holding a ref to this addr */
231 mpls_tree_remove(g
->addr_tree
, inet
.u
.ipv4
, 32, (void **)&addr
);
232 MPLS_REFCNT_RELEASE(addr
, ldp_addr_delete
);
238 LDP_EXIT(g
->user_data
, "ldp_addr_process");
242 ldp_addr_process_end
:
244 ldp_addr_delete(addr
);
246 LDP_EXIT(g
->user_data
, "ldp_addr_process-error");