]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/address.c
1 // SPDX-License-Identifier: ISC
5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
14 #include "ldp_debug.h"
16 static void send_address(struct nbr
*, int, struct if_addr_head
*,
18 static int gen_address_list_tlv(struct ibuf
*, int, struct if_addr_head
*,
20 static int gen_mac_list_tlv(struct ibuf
*, uint8_t *);
21 static void address_list_add(struct if_addr_head
*, struct if_addr
*);
22 static void address_list_clr(struct if_addr_head
*);
23 static void log_msg_address(int, uint16_t, struct nbr
*, int,
25 static void log_msg_mac_withdrawal(int, struct nbr
*, uint8_t *);
28 send_address(struct nbr
*nbr
, int af
, struct if_addr_head
*addr_list
,
29 unsigned int addr_count
, int withdraw
)
34 struct if_addr
*if_addr
;
36 unsigned int tlv_addr_count
= 0;
40 if (LIST_EMPTY(addr_list
))
44 msg_type
= MSG_TYPE_ADDR
;
46 msg_type
= MSG_TYPE_ADDRWITHDRAW
;
50 addr_size
= sizeof(struct in_addr
);
53 addr_size
= sizeof(struct in6_addr
);
56 fatalx("send_address: unknown af");
59 while (LIST_FIRST(addr_list
) != NULL
) {
61 * Send as many addresses as possible - respect the session's
62 * negotiated maximum pdu length.
64 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ ADDR_LIST_SIZE
;
65 if (size
+ addr_count
* addr_size
<= nbr
->max_pdu_len
)
66 tlv_addr_count
= addr_count
;
68 tlv_addr_count
= (nbr
->max_pdu_len
- size
) / addr_size
;
69 size
+= tlv_addr_count
* addr_size
;
70 addr_count
-= tlv_addr_count
;
72 if ((buf
= ibuf_open(size
)) == NULL
)
75 err
|= gen_ldp_hdr(buf
, size
);
77 err
|= gen_msg_hdr(buf
, msg_type
, size
);
79 err
|= gen_address_list_tlv(buf
, af
, addr_list
, tlv_addr_count
);
82 address_list_clr(addr_list
);
87 while ((if_addr
= LIST_FIRST(addr_list
)) != NULL
) {
88 log_msg_address(1, msg_type
, nbr
, af
, &if_addr
->addr
);
90 LIST_REMOVE(if_addr
, entry
);
91 assert(if_addr
!= LIST_FIRST(addr_list
));
93 if (--tlv_addr_count
== 0)
97 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
99 /* no errors - update per neighbor message counters */
102 nbr
->stats
.addr_sent
++;
104 case MSG_TYPE_ADDRWITHDRAW
:
105 nbr
->stats
.addrwdraw_sent
++;
112 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
116 send_address_single(struct nbr
*nbr
, struct if_addr
*if_addr
, int withdraw
)
118 struct if_addr_head addr_list
;
120 LIST_INIT(&addr_list
);
121 address_list_add(&addr_list
, if_addr
);
122 send_address(nbr
, if_addr
->af
, &addr_list
, 1, withdraw
);
126 send_address_all(struct nbr
*nbr
, int af
)
128 struct if_addr_head addr_list
;
129 struct if_addr
*if_addr
;
130 unsigned int addr_count
= 0;
132 LIST_INIT(&addr_list
);
133 LIST_FOREACH(if_addr
, &global
.addr_list
, entry
) {
134 if (if_addr
->af
!= af
)
137 address_list_add(&addr_list
, if_addr
);
141 send_address(nbr
, af
, &addr_list
, addr_count
, 0);
145 send_mac_withdrawal(struct nbr
*nbr
, struct map
*fec
, uint8_t *mac
)
151 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ ADDR_LIST_SIZE
+ len_fec_tlv(fec
) +
156 if ((buf
= ibuf_open(size
)) == NULL
)
159 err
= gen_ldp_hdr(buf
, size
);
160 size
-= LDP_HDR_SIZE
;
161 err
|= gen_msg_hdr(buf
, MSG_TYPE_ADDRWITHDRAW
, size
);
162 err
|= gen_address_list_tlv(buf
, AF_INET
, NULL
, 0);
163 err
|= gen_fec_tlv(buf
, fec
);
164 err
|= gen_mac_list_tlv(buf
, mac
);
170 log_msg_mac_withdrawal(1, nbr
, mac
);
172 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
174 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
178 recv_address(struct nbr
*nbr
, char *buf
, uint16_t len
)
183 struct address_list_tlv alt
;
186 struct lde_addr lde_addr
;
188 memcpy(&msg
, buf
, sizeof(msg
));
189 msg_type
= ntohs(msg
.type
);
192 type
= IMSG_ADDRESS_ADD
;
194 case MSG_TYPE_ADDRWITHDRAW
:
195 type
= IMSG_ADDRESS_DEL
;
198 fatalx("recv_address: unexpected msg type");
203 /* Address List TLV */
204 if (len
< ADDR_LIST_SIZE
) {
205 session_shutdown(nbr
, S_BAD_MSG_LEN
, msg
.id
, msg
.type
);
208 memcpy(&alt
, buf
, sizeof(alt
));
209 alt_len
= ntohs(alt
.length
);
210 alt_family
= ntohs(alt
.family
);
211 if (alt_len
> len
- TLV_HDR_SIZE
) {
212 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
215 if (ntohs(alt
.type
) != TLV_TYPE_ADDRLIST
) {
216 send_notification(nbr
->tcp
, S_MISS_MSG
, msg
.id
, msg
.type
);
219 switch (alt_family
) {
221 if (!nbr
->v4_enabled
)
222 /* just ignore the message */
226 if (!nbr
->v6_enabled
)
227 /* just ignore the message */
231 send_notification(nbr
->tcp
, S_UNSUP_ADDR
, msg
.id
, msg
.type
);
234 alt_len
-= sizeof(alt
.family
);
238 /* Process all received addresses */
239 while (alt_len
> 0) {
240 switch (alt_family
) {
242 if (alt_len
< sizeof(struct in_addr
)) {
243 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
248 memset(&lde_addr
, 0, sizeof(lde_addr
));
249 lde_addr
.af
= AF_INET
;
250 memcpy(&lde_addr
.addr
, buf
, sizeof(struct in_addr
));
252 buf
+= sizeof(struct in_addr
);
253 len
-= sizeof(struct in_addr
);
254 alt_len
-= sizeof(struct in_addr
);
257 if (alt_len
< sizeof(struct in6_addr
)) {
258 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
263 memset(&lde_addr
, 0, sizeof(lde_addr
));
264 lde_addr
.af
= AF_INET6
;
265 memcpy(&lde_addr
.addr
, buf
, sizeof(struct in6_addr
));
267 buf
+= sizeof(struct in6_addr
);
268 len
-= sizeof(struct in6_addr
);
269 alt_len
-= sizeof(struct in6_addr
);
272 fatalx("recv_address: unknown af");
275 log_msg_address(0, msg_type
, nbr
, lde_addr
.af
, &lde_addr
.addr
);
277 ldpe_imsg_compose_lde(type
, nbr
->peerid
, 0, &lde_addr
,
281 /* Optional Parameters */
287 if (len
< sizeof(tlv
)) {
288 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
292 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
293 tlv_type
= ntohs(tlv
.type
);
294 tlv_len
= ntohs(tlv
.length
);
295 if (tlv_len
+ TLV_HDR_SIZE
> len
) {
296 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
304 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
305 send_notification_rtlvs(nbr
, S_UNKNOWN_TLV
,
306 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
307 /* ignore unknown tlv */
318 gen_address_list_tlv(struct ibuf
*buf
, int af
, struct if_addr_head
*addr_list
,
319 unsigned int tlv_addr_count
)
321 struct address_list_tlv alt
;
323 struct if_addr
*if_addr
;
326 memset(&alt
, 0, sizeof(alt
));
327 alt
.type
= htons(TLV_TYPE_ADDRLIST
);
331 alt
.family
= htons(AF_IPV4
);
332 addr_size
= sizeof(struct in_addr
);
335 alt
.family
= htons(AF_IPV6
);
336 addr_size
= sizeof(struct in6_addr
);
339 fatalx("gen_address_list_tlv: unknown af");
341 alt
.length
= htons(sizeof(alt
.family
) + addr_size
* tlv_addr_count
);
343 err
|= ibuf_add(buf
, &alt
, sizeof(alt
));
344 if (addr_list
== NULL
)
347 LIST_FOREACH(if_addr
, addr_list
, entry
) {
348 err
|= ibuf_add(buf
, &if_addr
->addr
, addr_size
);
349 if (--tlv_addr_count
== 0)
357 gen_mac_list_tlv(struct ibuf
*buf
, uint8_t *mac
)
362 memset(&tlv
, 0, sizeof(tlv
));
363 tlv
.type
= htons(TLV_TYPE_MAC_LIST
);
365 tlv
.length
= htons(ETH_ALEN
);
366 err
= ibuf_add(buf
, &tlv
, sizeof(tlv
));
368 err
|= ibuf_add(buf
, mac
, ETH_ALEN
);
374 address_list_add(struct if_addr_head
*addr_list
, struct if_addr
*if_addr
)
378 new = malloc(sizeof(*new));
383 LIST_INSERT_HEAD(addr_list
, new, entry
);
387 address_list_clr(struct if_addr_head
*addr_list
)
389 struct if_addr
*if_addr
;
391 while ((if_addr
= LIST_FIRST(addr_list
)) != NULL
) {
392 LIST_REMOVE(if_addr
, entry
);
393 assert(if_addr
!= LIST_FIRST(addr_list
));
399 log_msg_address(int out
, uint16_t msg_type
, struct nbr
*nbr
, int af
,
400 union ldpd_addr
*addr
)
402 debug_msg(out
, "%s: lsr-id %pI4, address %s", msg_name(msg_type
),
403 &nbr
->id
, log_addr(af
, addr
));
407 log_msg_mac_withdrawal(int out
, struct nbr
*nbr
, uint8_t *mac
)
409 char buf
[ETHER_ADDR_STRLEN
];
411 debug_msg(out
, "mac withdrawal: lsr-id %pI4, mac %s", &nbr
->id
,
412 (mac
) ? prefix_mac2str((struct ethaddr
*)mac
, buf
, sizeof(buf
)) :