]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/notification.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.
19 #include <sys/types.h>
20 #include <arpa/inet.h>
29 send_notification_full(struct tcp_conn
*tcp
, struct notify_msg
*nm
)
36 size
= LDP_HDR_SIZE
+ LDP_MSG_SIZE
+ STATUS_SIZE
;
37 if (nm
->flags
& F_NOTIF_PW_STATUS
)
38 size
+= PW_STATUS_TLV_SIZE
;
39 if (nm
->flags
& F_NOTIF_FEC
) {
41 switch (nm
->fec
.type
) {
43 size
+= FEC_PWID_ELM_MIN_LEN
;
44 if (nm
->fec
.flags
& F_MAP_PW_ID
)
45 size
+= sizeof(uint32_t);
50 if ((buf
= ibuf_open(size
)) == NULL
)
53 err
|= gen_ldp_hdr(buf
, size
);
55 err
|= gen_msg_hdr(buf
, MSG_TYPE_NOTIFICATION
, size
);
56 err
|= gen_status_tlv(buf
, nm
->status_code
, nm
->msg_id
, nm
->msg_type
);
58 if (nm
->flags
& F_NOTIF_PW_STATUS
)
59 err
|= gen_pw_status_tlv(buf
, nm
->pw_status
);
60 if (nm
->flags
& F_NOTIF_FEC
)
61 err
|= gen_fec_tlv(buf
, &nm
->fec
);
68 log_debug("msg-out: notification: lsr-id %s, status %s%s",
69 inet_ntoa(tcp
->nbr
->id
), status_code_name(nm
->status_code
),
70 (nm
->status_code
& STATUS_FATAL
) ? " (fatal)" : "");
72 evbuf_enqueue(&tcp
->wbuf
, buf
);
75 /* send a notification without optional tlvs */
77 send_notification(uint32_t status_code
, struct tcp_conn
*tcp
, uint32_t msg_id
,
82 memset(&nm
, 0, sizeof(nm
));
83 nm
.status_code
= status_code
;
85 nm
.msg_type
= msg_type
;
87 send_notification_full(tcp
, &nm
);
91 send_notification_nbr(struct nbr
*nbr
, uint32_t status_code
, uint32_t msg_id
,
94 send_notification(status_code
, nbr
->tcp
, msg_id
, msg_type
);
95 nbr_fsm(nbr
, NBR_EVT_PDU_SENT
);
99 recv_notification(struct nbr
*nbr
, char *buf
, uint16_t len
)
102 struct status_tlv st
;
103 struct notify_msg nm
;
106 memcpy(&msg
, buf
, sizeof(msg
));
110 if (len
< STATUS_SIZE
) {
111 session_shutdown(nbr
, S_BAD_MSG_LEN
, msg
.id
, msg
.type
);
114 memcpy(&st
, buf
, sizeof(st
));
116 if (ntohs(st
.length
) > STATUS_SIZE
- TLV_HDR_SIZE
||
117 ntohs(st
.length
) > len
- TLV_HDR_SIZE
) {
118 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
124 memset(&nm
, 0, sizeof(nm
));
125 nm
.status_code
= ntohl(st
.status_code
);
127 /* Optional Parameters */
132 if (len
< sizeof(tlv
)) {
133 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
137 memcpy(&tlv
, buf
, TLV_HDR_SIZE
);
138 tlv_len
= ntohs(tlv
.length
);
139 if (tlv_len
+ TLV_HDR_SIZE
> len
) {
140 session_shutdown(nbr
, S_BAD_TLV_LEN
, msg
.id
, msg
.type
);
146 switch (ntohs(tlv
.type
)) {
147 case TLV_TYPE_EXTSTATUS
:
148 case TLV_TYPE_RETURNEDPDU
:
149 case TLV_TYPE_RETURNEDMSG
:
150 /* TODO is there any use for this? */
152 case TLV_TYPE_PW_STATUS
:
154 session_shutdown(nbr
, S_BAD_TLV_LEN
,
159 nm
.pw_status
= ntohl(*(uint32_t *)buf
);
160 nm
.flags
|= F_NOTIF_PW_STATUS
;
163 if ((tlen
= tlv_decode_fec_elm(nbr
, &msg
, buf
,
164 tlv_len
, &nm
.fec
)) == -1)
166 /* allow only one fec element */
167 if (tlen
!= tlv_len
) {
168 session_shutdown(nbr
, S_BAD_TLV_VAL
,
172 nm
.flags
|= F_NOTIF_FEC
;
175 if (!(ntohs(tlv
.type
) & UNKNOWN_FLAG
))
176 send_notification_nbr(nbr
, S_UNKNOWN_TLV
,
178 /* ignore unknown tlv */
185 if (nm
.status_code
== S_PW_STATUS
) {
186 if (!(nm
.flags
& (F_NOTIF_PW_STATUS
|F_NOTIF_FEC
))) {
187 send_notification_nbr(nbr
, S_MISS_MSG
,
192 switch (nm
.fec
.type
) {
196 send_notification_nbr(nbr
, S_BAD_TLV_VAL
,
202 log_warnx("msg-in: notification: lsr-id %s, status %s%s",
203 inet_ntoa(nbr
->id
), status_code_name(ntohl(st
.status_code
)),
204 (st
.status_code
& htonl(STATUS_FATAL
)) ? " (fatal)" : "");
206 if (st
.status_code
& htonl(STATUS_FATAL
)) {
207 if (nbr
->state
== NBR_STA_OPENSENT
)
208 nbr_start_idtimer(nbr
);
210 nbr_fsm(nbr
, NBR_EVT_CLOSE_SESSION
);
214 if (nm
.status_code
== S_PW_STATUS
)
215 ldpe_imsg_compose_lde(IMSG_NOTIFICATION
, nbr
->peerid
, 0,
222 gen_status_tlv(struct ibuf
*buf
, uint32_t status_code
, uint32_t msg_id
,
225 struct status_tlv st
;
227 memset(&st
, 0, sizeof(st
));
228 st
.type
= htons(TLV_TYPE_STATUS
);
229 st
.length
= htons(STATUS_TLV_LEN
);
230 st
.status_code
= htonl(status_code
);
232 * For convenience, msg_id and msg_type are already in network
236 st
.msg_type
= msg_type
;
238 return (ibuf_add(buf
, &st
, STATUS_SIZE
));