1*6af85cd7Srenato /* $OpenBSD: init.c,v 1.28 2016/06/08 21:28:09 renato Exp $ */ 2ab0c2486Smichele 3ab0c2486Smichele /* 4ab0c2486Smichele * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> 5ab0c2486Smichele * 6ab0c2486Smichele * Permission to use, copy, modify, and distribute this software for any 7ab0c2486Smichele * purpose with or without fee is hereby granted, provided that the above 8ab0c2486Smichele * copyright notice and this permission notice appear in all copies. 9ab0c2486Smichele * 10ab0c2486Smichele * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11ab0c2486Smichele * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12ab0c2486Smichele * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13ab0c2486Smichele * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14ab0c2486Smichele * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15ab0c2486Smichele * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16ab0c2486Smichele * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17ab0c2486Smichele */ 18ab0c2486Smichele 19ab0c2486Smichele #include <sys/types.h> 20ab0c2486Smichele #include <arpa/inet.h> 21ab0c2486Smichele #include <string.h> 22ab0c2486Smichele 23ab0c2486Smichele #include "ldpd.h" 24ab0c2486Smichele #include "ldpe.h" 255411bbb6Srenato #include "log.h" 26ab0c2486Smichele 27c28a25a1Srenato static int gen_init_prms_tlv(struct ibuf *, struct nbr *, uint16_t); 28c28a25a1Srenato static int tlv_decode_opt_init_prms(char *, uint16_t); 29ab0c2486Smichele 30a6fc12d8Smichele void 31ab0c2486Smichele send_init(struct nbr *nbr) 32ab0c2486Smichele { 33e39620e5Snicm struct ibuf *buf; 343de94509Srenato uint16_t size; 35ab0c2486Smichele 36d99a8fc3Srenato log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); 37ab0c2486Smichele 389277622bSrenato size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE; 399277622bSrenato if ((buf = ibuf_open(size)) == NULL) 40b7b4db73Srenato fatal(__func__); 41ab0c2486Smichele 42122f143eSclaudio gen_ldp_hdr(buf, size); 43ab0c2486Smichele size -= LDP_HDR_SIZE; 449277622bSrenato gen_msg_hdr(buf, MSG_TYPE_INIT, size); 459277622bSrenato size -= LDP_MSG_SIZE; 46ab0c2486Smichele gen_init_prms_tlv(buf, nbr, size); 47ab0c2486Smichele 48699b7d06Sclaudio evbuf_enqueue(&nbr->tcp->wbuf, buf); 49ab0c2486Smichele } 50ab0c2486Smichele 51ab0c2486Smichele int 523de94509Srenato recv_init(struct nbr *nbr, char *buf, uint16_t len) 53ab0c2486Smichele { 5489f23408Sclaudio struct ldp_msg init; 5589f23408Sclaudio struct sess_prms_tlv sess; 56feeedd8aSrenato uint16_t max_pdu_len; 57ab0c2486Smichele 58d99a8fc3Srenato log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); 59ab0c2486Smichele 603de94509Srenato memcpy(&init, buf, sizeof(init)); 613de94509Srenato buf += LDP_MSG_SIZE; 623de94509Srenato len -= LDP_MSG_SIZE; 63ab0c2486Smichele 6489f23408Sclaudio if (len < SESS_PRMS_SIZE) { 6589f23408Sclaudio session_shutdown(nbr, S_BAD_MSG_LEN, init.msgid, init.type); 6689f23408Sclaudio return (-1); 6789f23408Sclaudio } 683de94509Srenato memcpy(&sess, buf, sizeof(sess)); 693de94509Srenato if (ntohs(sess.keepalive_time) < MIN_KEEPALIVE) { 703de94509Srenato session_shutdown(nbr, S_KEEPALIVE_BAD, init.msgid, init.type); 713de94509Srenato return (-1); 723de94509Srenato } 739277622bSrenato if (ntohs(sess.length) != SESS_PRMS_SIZE - TLV_HDR_LEN) { 7489f23408Sclaudio session_shutdown(nbr, S_BAD_TLV_LEN, init.msgid, init.type); 75ab0c2486Smichele return (-1); 76ab0c2486Smichele } 7735791d36Srenato if (ntohs(sess.proto_version) != LDP_VERSION) { 7835791d36Srenato session_shutdown(nbr, S_BAD_PROTO_VER, init.msgid, init.type); 7935791d36Srenato return (-1); 8035791d36Srenato } 81*6af85cd7Srenato if (sess.lsr_id != leconf->rtr_id.s_addr || 82*6af85cd7Srenato ntohs(sess.lspace_id) != 0) { 83*6af85cd7Srenato session_shutdown(nbr, S_NO_HELLO, init.msgid, init.type); 84*6af85cd7Srenato return (-1); 85*6af85cd7Srenato } 8635791d36Srenato 87080776f3Sclaudio buf += SESS_PRMS_SIZE; 88080776f3Sclaudio len -= SESS_PRMS_SIZE; 89080776f3Sclaudio 90080776f3Sclaudio /* just ignore all optional TLVs for now */ 91080776f3Sclaudio if (tlv_decode_opt_init_prms(buf, len) == -1) { 92080776f3Sclaudio session_shutdown(nbr, S_BAD_TLV_VAL, init.msgid, init.type); 93080776f3Sclaudio return (-1); 94080776f3Sclaudio } 9589f23408Sclaudio 96a8c39dc0Srenato nbr->keepalive = min(nbr_get_keepalive(nbr->af, nbr->id), 973d39db89Srenato ntohs(sess.keepalive_time)); 98ab0c2486Smichele 99feeedd8aSrenato max_pdu_len = ntohs(sess.max_pdu_len); 100feeedd8aSrenato /* 101feeedd8aSrenato * RFC 5036 - Section 3.5.3: 102feeedd8aSrenato * "A value of 255 or less specifies the default maximum length of 103feeedd8aSrenato * 4096 octets". 104feeedd8aSrenato */ 105feeedd8aSrenato if (max_pdu_len <= 255) 106feeedd8aSrenato max_pdu_len = LDP_MAX_LEN; 107feeedd8aSrenato nbr->max_pdu_len = min(max_pdu_len, LDP_MAX_LEN); 108feeedd8aSrenato 109ab0c2486Smichele nbr_fsm(nbr, NBR_EVT_INIT_RCVD); 110ab0c2486Smichele 1119277622bSrenato return (0); 112ab0c2486Smichele } 113ab0c2486Smichele 114c28a25a1Srenato static int 1153de94509Srenato gen_init_prms_tlv(struct ibuf *buf, struct nbr *nbr, uint16_t size) 116ab0c2486Smichele { 117ab0c2486Smichele struct sess_prms_tlv parms; 118ab0c2486Smichele 1193de94509Srenato memset(&parms, 0, sizeof(parms)); 120ab0c2486Smichele parms.type = htons(TLV_TYPE_COMMONSESSION); 1213de94509Srenato parms.length = htons(size - TLV_HDR_LEN); 122ab0c2486Smichele parms.proto_version = htons(LDP_VERSION); 123a8c39dc0Srenato parms.keepalive_time = htons(nbr_get_keepalive(nbr->af, nbr->id)); 124ab0c2486Smichele parms.reserved = 0; 125ab0c2486Smichele parms.pvlim = 0; 126ab0c2486Smichele parms.max_pdu_len = 0; 127ab0c2486Smichele parms.lsr_id = nbr->id.s_addr; 128ab0c2486Smichele parms.lspace_id = 0; 129ab0c2486Smichele 130e39620e5Snicm return (ibuf_add(buf, &parms, SESS_PRMS_SIZE)); 131ab0c2486Smichele } 132080776f3Sclaudio 133c28a25a1Srenato static int 1343de94509Srenato tlv_decode_opt_init_prms(char *buf, uint16_t len) 135080776f3Sclaudio { 136080776f3Sclaudio struct tlv tlv; 1373de94509Srenato uint16_t tlv_len; 1383de94509Srenato int total = 0; 139080776f3Sclaudio 140080776f3Sclaudio while (len >= sizeof(tlv)) { 1413de94509Srenato memcpy(&tlv, buf, sizeof(tlv)); 142080776f3Sclaudio tlv_len = ntohs(tlv.length); 143080776f3Sclaudio switch (ntohs(tlv.type)) { 144080776f3Sclaudio case TLV_TYPE_ATMSESSIONPAR: 145080776f3Sclaudio log_warnx("ATM session parameter present"); 146080776f3Sclaudio return (-1); 147080776f3Sclaudio case TLV_TYPE_FRSESSION: 148080776f3Sclaudio log_warnx("FR session parameter present"); 149080776f3Sclaudio return (-1); 150080776f3Sclaudio default: 151080776f3Sclaudio /* if unknown flag set, ignore TLV */ 152080776f3Sclaudio if (!(ntohs(tlv.type) & UNKNOWN_FLAG)) 153080776f3Sclaudio return (-1); 154080776f3Sclaudio break; 155080776f3Sclaudio } 156080776f3Sclaudio buf += TLV_HDR_LEN + tlv_len; 157080776f3Sclaudio len -= TLV_HDR_LEN + tlv_len; 1582d825b92Srenato total += TLV_HDR_LEN + tlv_len; 159080776f3Sclaudio } 160080776f3Sclaudio 1612d825b92Srenato return (total); 162080776f3Sclaudio } 163