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