init.c revision 1.24
1/*	$OpenBSD: init.c,v 1.24 2016/05/23 17:43:42 renato Exp $ */
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 <sys/types.h>
20#include <sys/socket.h>
21#include <sys/uio.h>
22
23#include <netinet/in.h>
24#include <netinet/ip.h>
25#include <arpa/inet.h>
26#include <net/if_dl.h>
27#include <unistd.h>
28
29#include <errno.h>
30#include <event.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include "ldpd.h"
35#include "ldp.h"
36#include "log.h"
37#include "ldpe.h"
38
39extern struct ldpd_conf        *leconf;
40
41int	gen_init_prms_tlv(struct ibuf *, struct nbr *, uint16_t);
42int	tlv_decode_opt_init_prms(char *, uint16_t);
43
44void
45send_init(struct nbr *nbr)
46{
47	struct ibuf		*buf;
48	uint16_t		 size;
49
50	log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
51
52	size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE;
53	if ((buf = ibuf_open(size)) == NULL)
54		fatal(__func__);
55
56	gen_ldp_hdr(buf, size);
57	size -= LDP_HDR_SIZE;
58	gen_msg_hdr(buf, MSG_TYPE_INIT, size);
59	size -= LDP_MSG_SIZE;
60	gen_init_prms_tlv(buf, nbr, size);
61
62	evbuf_enqueue(&nbr->tcp->wbuf, buf);
63}
64
65int
66recv_init(struct nbr *nbr, char *buf, uint16_t len)
67{
68	struct ldp_msg		init;
69	struct sess_prms_tlv	sess;
70	uint16_t		max_pdu_len;
71
72	log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
73
74	memcpy(&init, buf, sizeof(init));
75	buf += LDP_MSG_SIZE;
76	len -= LDP_MSG_SIZE;
77
78	if (len < SESS_PRMS_SIZE) {
79		session_shutdown(nbr, S_BAD_MSG_LEN, init.msgid, init.type);
80		return (-1);
81	}
82	memcpy(&sess, buf, sizeof(sess));
83	if (ntohs(sess.keepalive_time) < MIN_KEEPALIVE) {
84		session_shutdown(nbr, S_KEEPALIVE_BAD, init.msgid, init.type);
85		return (-1);
86	}
87
88	if (ntohs(sess.length) != SESS_PRMS_SIZE - TLV_HDR_LEN) {
89		session_shutdown(nbr, S_BAD_TLV_LEN, init.msgid, init.type);
90		return (-1);
91	}
92
93	if (ntohs(sess.proto_version) != LDP_VERSION) {
94		session_shutdown(nbr, S_BAD_PROTO_VER, init.msgid, init.type);
95		return (-1);
96	}
97
98	buf += SESS_PRMS_SIZE;
99	len -= SESS_PRMS_SIZE;
100
101	/* just ignore all optional TLVs for now */
102	if (tlv_decode_opt_init_prms(buf, len) == -1) {
103		session_shutdown(nbr, S_BAD_TLV_VAL, init.msgid, init.type);
104		return (-1);
105	}
106
107	nbr->keepalive = min(nbr_get_keepalive(nbr->raddr),
108	    ntohs(sess.keepalive_time));
109
110	max_pdu_len = ntohs(sess.max_pdu_len);
111	/*
112	 * RFC 5036 - Section 3.5.3:
113	 * "A value of 255 or less specifies the default maximum length of
114	 * 4096 octets".
115	 */
116	if (max_pdu_len <= 255)
117		max_pdu_len = LDP_MAX_LEN;
118	nbr->max_pdu_len = min(max_pdu_len, LDP_MAX_LEN);
119
120	nbr_fsm(nbr, NBR_EVT_INIT_RCVD);
121
122	return (0);
123}
124
125int
126gen_init_prms_tlv(struct ibuf *buf, struct nbr *nbr, uint16_t size)
127{
128	struct sess_prms_tlv	parms;
129
130	memset(&parms, 0, sizeof(parms));
131	parms.type = htons(TLV_TYPE_COMMONSESSION);
132	parms.length = htons(size - TLV_HDR_LEN);
133	parms.proto_version = htons(LDP_VERSION);
134	parms.keepalive_time = htons(nbr_get_keepalive(nbr->raddr));
135	parms.reserved = 0;
136	parms.pvlim = 0;
137	parms.max_pdu_len = 0;
138	parms.lsr_id = nbr->id.s_addr;
139	parms.lspace_id = 0;
140
141	return (ibuf_add(buf, &parms, SESS_PRMS_SIZE));
142}
143
144int
145tlv_decode_opt_init_prms(char *buf, uint16_t len)
146{
147	struct tlv	tlv;
148	uint16_t	tlv_len;
149	int		total = 0;
150
151	 while (len >= sizeof(tlv)) {
152		memcpy(&tlv, buf, sizeof(tlv));
153		tlv_len = ntohs(tlv.length);
154		switch (ntohs(tlv.type)) {
155		case TLV_TYPE_ATMSESSIONPAR:
156			log_warnx("ATM session parameter present");
157			return (-1);
158		case TLV_TYPE_FRSESSION:
159			log_warnx("FR session parameter present");
160			return (-1);
161		default:
162			/* if unknown flag set, ignore TLV */
163			if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
164				return (-1);
165			break;
166		}
167		buf += TLV_HDR_LEN + tlv_len;
168		len -= TLV_HDR_LEN + tlv_len;
169		total += TLV_HDR_LEN + tlv_len;
170	}
171
172	return (total);
173}
174