]> git.proxmox.com Git - mirror_frr.git/blob - ldpd/init.c
ldpd: adapt the code for Quagga
[mirror_frr.git] / ldpd / init.c
1 /* $OpenBSD$ */
2
3 /*
4 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
5 *
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.
9 *
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.
17 */
18
19 #include <zebra.h>
20
21 #include "ldpd.h"
22 #include "ldpe.h"
23 #include "log.h"
24 #include "ldp_debug.h"
25
26 static int gen_init_prms_tlv(struct ibuf *, struct nbr *);
27
28 void
29 send_init(struct nbr *nbr)
30 {
31 struct ibuf *buf;
32 uint16_t size;
33 int err = 0;
34
35 debug_msg_send("initialization: lsr-id %s", inet_ntoa(nbr->id));
36
37 size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE;
38 if ((buf = ibuf_open(size)) == NULL)
39 fatal(__func__);
40
41 err |= gen_ldp_hdr(buf, size);
42 size -= LDP_HDR_SIZE;
43 err |= gen_msg_hdr(buf, MSG_TYPE_INIT, size);
44 size -= LDP_MSG_SIZE;
45 err |= gen_init_prms_tlv(buf, nbr);
46 if (err) {
47 ibuf_free(buf);
48 return;
49 }
50
51 evbuf_enqueue(&nbr->tcp->wbuf, buf);
52 }
53
54 int
55 recv_init(struct nbr *nbr, char *buf, uint16_t len)
56 {
57 struct ldp_msg msg;
58 struct sess_prms_tlv sess;
59 uint16_t max_pdu_len;
60
61 debug_msg_recv("initialization: lsr-id %s", inet_ntoa(nbr->id));
62
63 memcpy(&msg, buf, sizeof(msg));
64 buf += LDP_MSG_SIZE;
65 len -= LDP_MSG_SIZE;
66
67 if (len < SESS_PRMS_SIZE) {
68 session_shutdown(nbr, S_BAD_MSG_LEN, msg.id, msg.type);
69 return (-1);
70 }
71 memcpy(&sess, buf, sizeof(sess));
72 if (ntohs(sess.length) != SESS_PRMS_LEN) {
73 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
74 return (-1);
75 }
76 if (ntohs(sess.proto_version) != LDP_VERSION) {
77 session_shutdown(nbr, S_BAD_PROTO_VER, msg.id, msg.type);
78 return (-1);
79 }
80 if (ntohs(sess.keepalive_time) < MIN_KEEPALIVE) {
81 session_shutdown(nbr, S_KEEPALIVE_BAD, msg.id, msg.type);
82 return (-1);
83 }
84 if (sess.lsr_id != ldp_rtr_id_get(leconf) ||
85 ntohs(sess.lspace_id) != 0) {
86 session_shutdown(nbr, S_NO_HELLO, msg.id, msg.type);
87 return (-1);
88 }
89
90 buf += SESS_PRMS_SIZE;
91 len -= SESS_PRMS_SIZE;
92
93 /* Optional Parameters */
94 while (len > 0) {
95 struct tlv tlv;
96 uint16_t tlv_len;
97
98 if (len < sizeof(tlv)) {
99 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
100 return (-1);
101 }
102
103 memcpy(&tlv, buf, TLV_HDR_SIZE);
104 tlv_len = ntohs(tlv.length);
105 if (tlv_len + TLV_HDR_SIZE > len) {
106 session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
107 return (-1);
108 }
109 buf += TLV_HDR_SIZE;
110 len -= TLV_HDR_SIZE;
111
112 switch (ntohs(tlv.type)) {
113 case TLV_TYPE_ATMSESSIONPAR:
114 session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
115 return (-1);
116 case TLV_TYPE_FRSESSION:
117 session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
118 return (-1);
119 default:
120 if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
121 send_notification_nbr(nbr, S_UNKNOWN_TLV,
122 msg.id, msg.type);
123 /* ignore unknown tlv */
124 break;
125 }
126 buf += tlv_len;
127 len -= tlv_len;
128 }
129
130 nbr->keepalive = min(nbr_get_keepalive(nbr->af, nbr->id),
131 ntohs(sess.keepalive_time));
132
133 max_pdu_len = ntohs(sess.max_pdu_len);
134 /*
135 * RFC 5036 - Section 3.5.3:
136 * "A value of 255 or less specifies the default maximum length of
137 * 4096 octets".
138 */
139 if (max_pdu_len <= 255)
140 max_pdu_len = LDP_MAX_LEN;
141 nbr->max_pdu_len = min(max_pdu_len, LDP_MAX_LEN);
142
143 nbr_fsm(nbr, NBR_EVT_INIT_RCVD);
144
145 return (0);
146 }
147
148 static int
149 gen_init_prms_tlv(struct ibuf *buf, struct nbr *nbr)
150 {
151 struct sess_prms_tlv parms;
152
153 memset(&parms, 0, sizeof(parms));
154 parms.type = htons(TLV_TYPE_COMMONSESSION);
155 parms.length = htons(SESS_PRMS_LEN);
156 parms.proto_version = htons(LDP_VERSION);
157 parms.keepalive_time = htons(nbr_get_keepalive(nbr->af, nbr->id));
158 parms.reserved = 0;
159 parms.pvlim = 0;
160 parms.max_pdu_len = 0;
161 parms.lsr_id = nbr->id.s_addr;
162 parms.lspace_id = 0;
163
164 return (ibuf_add(buf, &parms, SESS_PRMS_SIZE));
165 }