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