]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/address.c
4 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 #include "ldp_debug.h"
27 static void send_address(struct nbr
*, int, struct if_addr_head
*,
29 static int gen_address_list_tlv(struct ibuf
*, uint16_t, int,
30 struct if_addr_head
*, unsigned int);
31 static void address_list_add(struct if_addr_head
*, struct if_addr
*);
32 static void address_list_clr(struct if_addr_head
*);
35 send_address(struct nbr
*nbr
, int af
, struct if_addr_head
*addr_list
,
36 unsigned int addr_count
, int withdraw
)
41 struct if_addr
*if_addr
;
43 unsigned int tlv_addr_count
= 0;
47 if (LIST_EMPTY(addr_list
))
51 msg_type
= MSG_TYPE_ADDR
;
53 msg_type
= MSG_TYPE_ADDRWITHDRAW
;
57 addr_size
= sizeof(struct in_addr
);
60 addr_size
= sizeof(struct in6_addr
);
63 fatalx("send_address: unknown af");
66 while ((if_addr
= LIST_FIRST(addr_list
)) != NULL
) {
68 * Send as many addresses as possible - respect the session's
69 * negotiated maximum pdu length.
71 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ ADDR_LIST_SIZE
;
72 if (size
+ addr_count
* addr_size
<= nbr
->max_pdu_len
)
73 tlv_addr_count
= addr_count
;
75 tlv_addr_count
= (nbr
->max_pdu_len
- size
) / addr_size
;
76 size
+= tlv_addr_count
* addr_size
;
77 addr_count
-= tlv_addr_count
;
79 if ((buf
= ibuf_open(size
)) == NULL
)
82 err
|= gen_ldp_hdr(buf
, size
);
84 err
|= gen_msg_hdr(buf
, msg_type
, size
);
86 err
|= gen_address_list_tlv(buf
, size
, af
, addr_list
,
89 address_list_clr(addr_list
);
94 while ((if_addr
= LIST_FIRST(addr_list
)) != NULL
) {
95 debug_msg_send("%s: lsr-id %s address %s",
96 msg_name(msg_type
), inet_ntoa(nbr
->id
),
97 log_addr(af
, &if_addr
->addr
));
99 LIST_REMOVE(if_addr
, entry
);
101 if (--tlv_addr_count
== 0)
105 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
108 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
112 send_address_single(struct nbr
*nbr
, struct if_addr
*if_addr
, int withdraw
)
114 struct if_addr_head addr_list
;
116 LIST_INIT(&addr_list
);
117 address_list_add(&addr_list
, if_addr
);
118 send_address(nbr
, if_addr
->af
, &addr_list
, 1, withdraw
);
122 send_address_all(struct nbr
*nbr
, int af
)
124 struct if_addr_head addr_list
;
125 struct if_addr
*if_addr
;
126 unsigned int addr_count
= 0;
128 LIST_INIT(&addr_list
);
129 LIST_FOREACH(if_addr
, &global
.addr_list
, entry
) {
130 if (if_addr
->af
!= af
)
133 address_list_add(&addr_list
, if_addr
);
137 send_address(nbr
, af
, &addr_list
, addr_count
, 0);
141 recv_address(struct nbr
*nbr
, char *buf
, uint16_t len
)
145 struct address_list_tlv alt
;
147 struct lde_addr lde_addr
;
149 memcpy(&msg
, buf
, sizeof(msg
));
153 /* Address List TLV */
154 if (len
< ADDR_LIST_SIZE
) {
155 session_shutdown(nbr
, S_BAD_MSG_LEN
, msg
.id
, msg
.type
);
159 memcpy(&alt
, buf
, sizeof(alt
));
160 if (ntohs(alt
.length
) != len
- TLV_HDR_SIZE
) {
161 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
164 if (ntohs(alt
.type
) != TLV_TYPE_ADDRLIST
) {
165 session_shutdown(nbr
, S_UNKNOWN_TLV
, msg
.id
, msg
.type
);
168 switch (ntohs(alt
.family
)) {
170 if (!nbr
->v4_enabled
)
171 /* just ignore the message */
175 if (!nbr
->v6_enabled
)
176 /* just ignore the message */
180 send_notification_nbr(nbr
, S_UNSUP_ADDR
, msg
.id
, msg
.type
);
186 msg_type
= ntohs(msg
.type
);
187 if (msg_type
== MSG_TYPE_ADDR
)
188 type
= IMSG_ADDRESS_ADD
;
190 type
= IMSG_ADDRESS_DEL
;
193 switch (ntohs(alt
.family
)) {
195 if (len
< sizeof(struct in_addr
)) {
196 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
201 memset(&lde_addr
, 0, sizeof(lde_addr
));
202 lde_addr
.af
= AF_INET
;
203 memcpy(&lde_addr
.addr
, buf
, sizeof(struct in_addr
));
205 buf
+= sizeof(struct in_addr
);
206 len
-= sizeof(struct in_addr
);
209 if (len
< sizeof(struct in6_addr
)) {
210 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
215 memset(&lde_addr
, 0, sizeof(lde_addr
));
216 lde_addr
.af
= AF_INET6
;
217 memcpy(&lde_addr
.addr
, buf
, sizeof(struct in6_addr
));
219 buf
+= sizeof(struct in6_addr
);
220 len
-= sizeof(struct in6_addr
);
223 fatalx("recv_address: unknown af");
226 debug_msg_recv("%s: lsr-id %s address %s", msg_name(msg_type
),
227 inet_ntoa(nbr
->id
), log_addr(lde_addr
.af
, &lde_addr
.addr
));
229 ldpe_imsg_compose_lde(type
, nbr
->peerid
, 0, &lde_addr
,
237 gen_address_list_tlv(struct ibuf
*buf
, uint16_t size
, int af
,
238 struct if_addr_head
*addr_list
, unsigned int tlv_addr_count
)
240 struct address_list_tlv alt
;
242 struct if_addr
*if_addr
;
245 memset(&alt
, 0, sizeof(alt
));
246 alt
.type
= TLV_TYPE_ADDRLIST
;
247 alt
.length
= htons(size
- TLV_HDR_SIZE
);
251 alt
.family
= htons(AF_IPV4
);
252 addr_size
= sizeof(struct in_addr
);
255 alt
.family
= htons(AF_IPV6
);
256 addr_size
= sizeof(struct in6_addr
);
259 fatalx("gen_address_list_tlv: unknown af");
262 err
|= ibuf_add(buf
, &alt
, sizeof(alt
));
263 LIST_FOREACH(if_addr
, addr_list
, entry
) {
264 err
|= ibuf_add(buf
, &if_addr
->addr
, addr_size
);
265 if (--tlv_addr_count
== 0)
273 address_list_add(struct if_addr_head
*addr_list
, struct if_addr
*if_addr
)
277 new = malloc(sizeof(*new));
282 LIST_INSERT_HEAD(addr_list
, new, entry
);
286 address_list_clr(struct if_addr_head
*addr_list
)
288 struct if_addr
*if_addr
;
290 while ((if_addr
= LIST_FIRST(addr_list
)) != NULL
) {
291 LIST_REMOVE(if_addr
, entry
);