Fixed next hop processing
[mpls-ldp-portable.git] / ldp / ldp_addr.c
blob58a318689fadb4122d06bb8080ad54bb4009711b
2 /*
3 * Copyright (C) James R. Leu 2000
4 * jleu@mindspring.com
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
8 */
10 #include <stdlib.h>
11 #include <string.h>
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"
17 #include "ldp_addr.h"
18 #include "ldp_l2cc.h"
19 #include "ldp_buf.h"
20 #include "ldp_mesg.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));
32 if (a) {
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();
39 return a;
42 void ldp_addr_delete(ldp_addr * a)
44 LDP_PRINT(g->user_data,"addr delete\n");
45 mpls_free(a);
48 mpls_return_enum _ldp_addr_add_session(ldp_addr * a, ldp_session * s)
50 MPLS_ASSERT(a && s);
51 MPLS_REFCNT_HOLD(s);
52 if (mpls_link_list_add_tail(&a->session_root, s) == MPLS_SUCCESS) {
53 return MPLS_SUCCESS;
55 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
56 return MPLS_FAILURE;
59 void _ldp_addr_del_session(ldp_addr * a, ldp_session * s)
61 MPLS_ASSERT(a && 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)
68 ldp_l2cc *lp = NULL;
70 MPLS_ASSERT(a && l);
71 MPLS_REFCNT_HOLD(l);
72 lp = MPLS_LIST_HEAD(&a->l2cc_root);
73 while (lp != NULL) {
74 if (lp->index > l->index) {
75 MPLS_LIST_INSERT_BEFORE(&a->l2cc_root, lp, l, _addr);
76 return;
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)
85 MPLS_ASSERT(a && 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;
98 return retval;
101 void ldp_addr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
102 mpls_inet_addr * addr)
104 MPLS_MSGPTR(Adr);
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)
124 MPLS_MSGPTR(Adr);
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,
142 mpls_inet_addr * a)
144 mpls_return_enum result = MPLS_FAILURE;
146 MPLS_ASSERT(s && a);
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");
159 return result;
162 mpls_return_enum ldp_waddr_send(ldp_global * g, ldp_session * s,
163 mpls_inet_addr * a)
165 mpls_return_enum result = MPLS_FAILURE;
167 MPLS_ASSERT(s && a);
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");
180 return result;
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;
187 mpls_inet_addr inet;
188 ldp_addr *addr = NULL;
189 int len = (body->addressList.baseTlv.length - MPLS_ADDFAMFIXLEN) /
190 MPLS_IPv4LEN;
191 int i;
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) ==
204 MPLS_FAILURE) {
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) ==
212 MPLS_FAILURE) {
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");
222 return MPLS_FAILURE;
224 } else {
225 /* addr withdrawl */
226 if (mpls_tree_get(g->addr_tree, inet.u.ipv4, 32, (void **)&addr) ==
227 MPLS_SUCCESS) {
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");
240 return MPLS_SUCCESS;
242 ldp_addr_process_end:
243 if (addr != NULL)
244 ldp_addr_delete(addr);
246 LDP_EXIT(g->user_data, "ldp_addr_process-error");
248 return MPLS_FAILURE;