]>
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
*, int, struct if_addr_head
*,
31 static int gen_mac_list_tlv(struct ibuf
*, uint8_t *);
32 static void address_list_add(struct if_addr_head
*, struct if_addr
*);
33 static void address_list_clr(struct if_addr_head
*);
34 static void log_msg_address(int, uint16_t, struct nbr
*, int,
36 static void log_msg_mac_withdrawal(int, struct nbr
*, uint8_t *);
39 send_address(struct nbr
*nbr
, int af
, struct if_addr_head
*addr_list
,
40 unsigned int addr_count
, int withdraw
)
45 struct if_addr
*if_addr
;
47 unsigned int tlv_addr_count
= 0;
51 if (LIST_EMPTY(addr_list
))
55 msg_type
= MSG_TYPE_ADDR
;
57 msg_type
= MSG_TYPE_ADDRWITHDRAW
;
61 addr_size
= sizeof(struct in_addr
);
64 addr_size
= sizeof(struct in6_addr
);
67 fatalx("send_address: unknown af");
70 while ((if_addr
= LIST_FIRST(addr_list
)) != NULL
) {
72 * Send as many addresses as possible - respect the session's
73 * negotiated maximum pdu length.
75 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ ADDR_LIST_SIZE
;
76 if (size
+ addr_count
* addr_size
<= nbr
->max_pdu_len
)
77 tlv_addr_count
= addr_count
;
79 tlv_addr_count
= (nbr
->max_pdu_len
- size
) / addr_size
;
80 size
+= tlv_addr_count
* addr_size
;
81 addr_count
-= tlv_addr_count
;
83 if ((buf
= ibuf_open(size
)) == NULL
)
86 err
|= gen_ldp_hdr(buf
, size
);
88 err
|= gen_msg_hdr(buf
, msg_type
, size
);
90 err
|= gen_address_list_tlv(buf
, af
, addr_list
, tlv_addr_count
);
92 address_list_clr(addr_list
);
97 while ((if_addr
= LIST_FIRST(addr_list
)) != NULL
) {
98 log_msg_address(1, msg_type
, nbr
, af
, &if_addr
->addr
);
100 LIST_REMOVE(if_addr
, entry
);
102 if (--tlv_addr_count
== 0)
106 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
109 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
113 send_address_single(struct nbr
*nbr
, struct if_addr
*if_addr
, int withdraw
)
115 struct if_addr_head addr_list
;
117 LIST_INIT(&addr_list
);
118 address_list_add(&addr_list
, if_addr
);
119 send_address(nbr
, if_addr
->af
, &addr_list
, 1, withdraw
);
123 send_address_all(struct nbr
*nbr
, int af
)
125 struct if_addr_head addr_list
;
126 struct if_addr
*if_addr
;
127 unsigned int addr_count
= 0;
129 LIST_INIT(&addr_list
);
130 LIST_FOREACH(if_addr
, &global
.addr_list
, entry
) {
131 if (if_addr
->af
!= af
)
134 address_list_add(&addr_list
, if_addr
);
138 send_address(nbr
, af
, &addr_list
, addr_count
, 0);
142 send_mac_withdrawal(struct nbr
*nbr
, struct map
*fec
, uint8_t *mac
)
148 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ ADDR_LIST_SIZE
+ len_fec_tlv(fec
) +
151 size
+= ETHER_ADDR_LEN
;
153 if ((buf
= ibuf_open(size
)) == NULL
)
156 err
= gen_ldp_hdr(buf
, size
);
157 size
-= LDP_HDR_SIZE
;
158 err
|= gen_msg_hdr(buf
, MSG_TYPE_ADDRWITHDRAW
, size
);
159 size
-= LDP_MSG_SIZE
;
160 err
|= gen_address_list_tlv(buf
, AF_INET
, NULL
, 0);
161 err
|= gen_fec_tlv(buf
, fec
);
162 err
|= gen_mac_list_tlv(buf
, mac
);
168 log_msg_mac_withdrawal(1, nbr
, mac
);
170 evbuf_enqueue(&nbr
->tcp
->wbuf
, buf
);
172 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
176 recv_address(struct nbr
*nbr
, char *buf
, uint16_t len
)
181 struct address_list_tlv alt
;
184 struct lde_addr lde_addr
;
186 memcpy(&msg
, buf
, sizeof(msg
));
187 msg_type
= ntohs(msg
.type
);
190 type
= IMSG_ADDRESS_ADD
;
192 case MSG_TYPE_ADDRWITHDRAW
:
193 type
= IMSG_ADDRESS_DEL
;
196 fatalx("recv_address: unexpected msg type");
201 /* Address List TLV */
202 if (len
< ADDR_LIST_SIZE
) {
203 session_shutdown(nbr
, S_BAD_MSG_LEN
, msg
.id
, msg
.type
);
206 memcpy(&alt
, buf
, sizeof(alt
));
207 alt_len
= ntohs(alt
.length
);
208 alt_family
= ntohs(alt
.family
);
209 if (alt_len
> len
- TLV_HDR_SIZE
) {
210 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
213 if (ntohs(alt
.type
) != TLV_TYPE_ADDRLIST
) {
214 send_notification(nbr
->tcp
, S_MISS_MSG
, msg
.id
, msg
.type
);
217 switch (alt_family
) {
219 if (!nbr
->v4_enabled
)
220 /* just ignore the message */
224 if (!nbr
->v6_enabled
)
225 /* just ignore the message */
229 send_notification(nbr
->tcp
, S_UNSUP_ADDR
, msg
.id
, msg
.type
);
232 alt_len
-= sizeof(alt
.family
);
236 /* Process all received addresses */
237 while (alt_len
> 0) {
238 switch (alt_family
) {
240 if (alt_len
< sizeof(struct in_addr
)) {
241 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
246 memset(&lde_addr
, 0, sizeof(lde_addr
));
247 lde_addr
.af
= AF_INET
;
248 memcpy(&lde_addr
.addr
, buf
, sizeof(struct in_addr
));
250 buf
+= sizeof(struct in_addr
);
251 len
-= sizeof(struct in_addr
);
252 alt_len
-= sizeof(struct in_addr
);
255 if (alt_len
< sizeof(struct in6_addr
)) {
256 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
,
261 memset(&lde_addr
, 0, sizeof(lde_addr
));
262 lde_addr
.af
= AF_INET6
;
263 memcpy(&lde_addr
.addr
, buf
, sizeof(struct in6_addr
));
265 buf
+= sizeof(struct in6_addr
);
266 len
-= sizeof(struct in6_addr
);
267 alt_len
-= sizeof(struct in6_addr
);
270 fatalx("recv_address: unknown af");
273 log_msg_address(0, msg_type
, nbr
, lde_addr
.af
, &lde_addr
.addr
);
275 ldpe_imsg_compose_lde(type
, nbr
->peerid
, 0, &lde_addr
,
279 /* Optional Parameters */
285 if (len
< sizeof(tlv
)) {
286 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
290 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
291 tlv_type
= ntohs(tlv
.type
);
292 tlv_len
= ntohs(tlv
.length
);
293 if (tlv_len
+ TLV_HDR_SIZE
> len
) {
294 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
302 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
303 send_notification_rtlvs(nbr
, S_UNKNOWN_TLV
,
304 msg
.id
, msg
.type
, tlv_type
, tlv_len
, buf
);
305 /* ignore unknown tlv */
316 gen_address_list_tlv(struct ibuf
*buf
, int af
, struct if_addr_head
*addr_list
,
317 unsigned int tlv_addr_count
)
319 struct address_list_tlv alt
;
321 struct if_addr
*if_addr
;
324 memset(&alt
, 0, sizeof(alt
));
325 alt
.type
= htons(TLV_TYPE_ADDRLIST
);
329 alt
.family
= htons(AF_IPV4
);
330 addr_size
= sizeof(struct in_addr
);
333 alt
.family
= htons(AF_IPV6
);
334 addr_size
= sizeof(struct in6_addr
);
337 fatalx("gen_address_list_tlv: unknown af");
339 alt
.length
= htons(sizeof(alt
.family
) + addr_size
* tlv_addr_count
);
341 err
|= ibuf_add(buf
, &alt
, sizeof(alt
));
342 if (addr_list
== NULL
)
345 LIST_FOREACH(if_addr
, addr_list
, entry
) {
346 err
|= ibuf_add(buf
, &if_addr
->addr
, addr_size
);
347 if (--tlv_addr_count
== 0)
355 gen_mac_list_tlv(struct ibuf
*buf
, uint8_t *mac
)
360 memset(&tlv
, 0, sizeof(tlv
));
361 tlv
.type
= htons(TLV_TYPE_MAC_LIST
);
363 tlv
.length
= htons(ETHER_ADDR_LEN
);
364 err
= ibuf_add(buf
, &tlv
, sizeof(tlv
));
366 err
|= ibuf_add(buf
, mac
, ETHER_ADDR_LEN
);
372 address_list_add(struct if_addr_head
*addr_list
, struct if_addr
*if_addr
)
376 new = malloc(sizeof(*new));
381 LIST_INSERT_HEAD(addr_list
, new, entry
);
385 address_list_clr(struct if_addr_head
*addr_list
)
387 struct if_addr
*if_addr
;
389 while ((if_addr
= LIST_FIRST(addr_list
)) != NULL
) {
390 LIST_REMOVE(if_addr
, entry
);
396 log_msg_address(int out
, uint16_t msg_type
, struct nbr
*nbr
, int af
,
397 union ldpd_addr
*addr
)
399 debug_msg(out
, "%s: lsr-id %s, address %s", msg_name(msg_type
),
400 inet_ntoa(nbr
->id
), log_addr(af
, addr
));
404 log_msg_mac_withdrawal(int out
, struct nbr
*nbr
, uint8_t *mac
)
406 char buf
[ETHER_ADDR_STRLEN
];
408 debug_msg(out
, "mac withdrawal: lsr-id %s, mac %s", inet_ntoa(nbr
->id
),
409 (mac
) ? prefix_mac2str((struct ethaddr
*)mac
, buf
, sizeof(buf
)) :