1*3de94509Srenato /* $OpenBSD: init.c,v 1.24 2016/05/23 17:43:42 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 <sys/socket.h> 21ab0c2486Smichele #include <sys/uio.h> 22ab0c2486Smichele 23ab0c2486Smichele #include <netinet/in.h> 24ab0c2486Smichele #include <netinet/ip.h> 25ab0c2486Smichele #include <arpa/inet.h> 26ab0c2486Smichele #include <net/if_dl.h> 27ab0c2486Smichele #include <unistd.h> 28ab0c2486Smichele 29ab0c2486Smichele #include <errno.h> 30ab0c2486Smichele #include <event.h> 31ab0c2486Smichele #include <stdlib.h> 32ab0c2486Smichele #include <string.h> 33ab0c2486Smichele 34ab0c2486Smichele #include "ldpd.h" 35ab0c2486Smichele #include "ldp.h" 36ab0c2486Smichele #include "log.h" 37ab0c2486Smichele #include "ldpe.h" 38ab0c2486Smichele 39a7bbe4e3Sclaudio extern struct ldpd_conf *leconf; 40a7bbe4e3Sclaudio 41*3de94509Srenato int gen_init_prms_tlv(struct ibuf *, struct nbr *, uint16_t); 42*3de94509Srenato int tlv_decode_opt_init_prms(char *, uint16_t); 43ab0c2486Smichele 44a6fc12d8Smichele void 45ab0c2486Smichele send_init(struct nbr *nbr) 46ab0c2486Smichele { 47e39620e5Snicm struct ibuf *buf; 48*3de94509Srenato uint16_t size; 49ab0c2486Smichele 50d99a8fc3Srenato log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); 51ab0c2486Smichele 529277622bSrenato size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE; 539277622bSrenato if ((buf = ibuf_open(size)) == NULL) 54b7b4db73Srenato fatal(__func__); 55ab0c2486Smichele 56122f143eSclaudio gen_ldp_hdr(buf, size); 57ab0c2486Smichele size -= LDP_HDR_SIZE; 589277622bSrenato gen_msg_hdr(buf, MSG_TYPE_INIT, size); 599277622bSrenato size -= LDP_MSG_SIZE; 60ab0c2486Smichele gen_init_prms_tlv(buf, nbr, size); 61ab0c2486Smichele 62699b7d06Sclaudio evbuf_enqueue(&nbr->tcp->wbuf, buf); 63ab0c2486Smichele } 64ab0c2486Smichele 65ab0c2486Smichele int 66*3de94509Srenato recv_init(struct nbr *nbr, char *buf, uint16_t len) 67ab0c2486Smichele { 6889f23408Sclaudio struct ldp_msg init; 6989f23408Sclaudio struct sess_prms_tlv sess; 70feeedd8aSrenato uint16_t max_pdu_len; 71ab0c2486Smichele 72d99a8fc3Srenato log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); 73ab0c2486Smichele 74*3de94509Srenato memcpy(&init, buf, sizeof(init)); 75*3de94509Srenato buf += LDP_MSG_SIZE; 76*3de94509Srenato len -= LDP_MSG_SIZE; 77ab0c2486Smichele 7889f23408Sclaudio if (len < SESS_PRMS_SIZE) { 7989f23408Sclaudio session_shutdown(nbr, S_BAD_MSG_LEN, init.msgid, init.type); 8089f23408Sclaudio return (-1); 8189f23408Sclaudio } 82*3de94509Srenato memcpy(&sess, buf, sizeof(sess)); 83*3de94509Srenato if (ntohs(sess.keepalive_time) < MIN_KEEPALIVE) { 84*3de94509Srenato session_shutdown(nbr, S_KEEPALIVE_BAD, init.msgid, init.type); 85*3de94509Srenato return (-1); 86*3de94509Srenato } 87ab0c2486Smichele 889277622bSrenato if (ntohs(sess.length) != SESS_PRMS_SIZE - TLV_HDR_LEN) { 8989f23408Sclaudio session_shutdown(nbr, S_BAD_TLV_LEN, init.msgid, init.type); 90ab0c2486Smichele return (-1); 91ab0c2486Smichele } 92ab0c2486Smichele 9335791d36Srenato if (ntohs(sess.proto_version) != LDP_VERSION) { 9435791d36Srenato session_shutdown(nbr, S_BAD_PROTO_VER, init.msgid, init.type); 9535791d36Srenato return (-1); 9635791d36Srenato } 9735791d36Srenato 98080776f3Sclaudio buf += SESS_PRMS_SIZE; 99080776f3Sclaudio len -= SESS_PRMS_SIZE; 100080776f3Sclaudio 101080776f3Sclaudio /* just ignore all optional TLVs for now */ 102080776f3Sclaudio if (tlv_decode_opt_init_prms(buf, len) == -1) { 103080776f3Sclaudio session_shutdown(nbr, S_BAD_TLV_VAL, init.msgid, init.type); 104080776f3Sclaudio return (-1); 105080776f3Sclaudio } 10689f23408Sclaudio 10786408800Srenato nbr->keepalive = min(nbr_get_keepalive(nbr->raddr), 1083d39db89Srenato ntohs(sess.keepalive_time)); 109ab0c2486Smichele 110feeedd8aSrenato max_pdu_len = ntohs(sess.max_pdu_len); 111feeedd8aSrenato /* 112feeedd8aSrenato * RFC 5036 - Section 3.5.3: 113feeedd8aSrenato * "A value of 255 or less specifies the default maximum length of 114feeedd8aSrenato * 4096 octets". 115feeedd8aSrenato */ 116feeedd8aSrenato if (max_pdu_len <= 255) 117feeedd8aSrenato max_pdu_len = LDP_MAX_LEN; 118feeedd8aSrenato nbr->max_pdu_len = min(max_pdu_len, LDP_MAX_LEN); 119feeedd8aSrenato 120ab0c2486Smichele nbr_fsm(nbr, NBR_EVT_INIT_RCVD); 121ab0c2486Smichele 1229277622bSrenato return (0); 123ab0c2486Smichele } 124ab0c2486Smichele 125ab0c2486Smichele int 126*3de94509Srenato gen_init_prms_tlv(struct ibuf *buf, struct nbr *nbr, uint16_t size) 127ab0c2486Smichele { 128ab0c2486Smichele struct sess_prms_tlv parms; 129ab0c2486Smichele 130*3de94509Srenato memset(&parms, 0, sizeof(parms)); 131ab0c2486Smichele parms.type = htons(TLV_TYPE_COMMONSESSION); 132*3de94509Srenato parms.length = htons(size - TLV_HDR_LEN); 133ab0c2486Smichele parms.proto_version = htons(LDP_VERSION); 13486408800Srenato parms.keepalive_time = htons(nbr_get_keepalive(nbr->raddr)); 135ab0c2486Smichele parms.reserved = 0; 136ab0c2486Smichele parms.pvlim = 0; 137ab0c2486Smichele parms.max_pdu_len = 0; 138ab0c2486Smichele parms.lsr_id = nbr->id.s_addr; 139ab0c2486Smichele parms.lspace_id = 0; 140ab0c2486Smichele 141e39620e5Snicm return (ibuf_add(buf, &parms, SESS_PRMS_SIZE)); 142ab0c2486Smichele } 143080776f3Sclaudio 144080776f3Sclaudio int 145*3de94509Srenato tlv_decode_opt_init_prms(char *buf, uint16_t len) 146080776f3Sclaudio { 147080776f3Sclaudio struct tlv tlv; 148*3de94509Srenato uint16_t tlv_len; 149*3de94509Srenato int total = 0; 150080776f3Sclaudio 151080776f3Sclaudio while (len >= sizeof(tlv)) { 152*3de94509Srenato memcpy(&tlv, buf, sizeof(tlv)); 153080776f3Sclaudio tlv_len = ntohs(tlv.length); 154080776f3Sclaudio switch (ntohs(tlv.type)) { 155080776f3Sclaudio case TLV_TYPE_ATMSESSIONPAR: 156080776f3Sclaudio log_warnx("ATM session parameter present"); 157080776f3Sclaudio return (-1); 158080776f3Sclaudio case TLV_TYPE_FRSESSION: 159080776f3Sclaudio log_warnx("FR session parameter present"); 160080776f3Sclaudio return (-1); 161080776f3Sclaudio default: 162080776f3Sclaudio /* if unknown flag set, ignore TLV */ 163080776f3Sclaudio if (!(ntohs(tlv.type) & UNKNOWN_FLAG)) 164080776f3Sclaudio return (-1); 165080776f3Sclaudio break; 166080776f3Sclaudio } 167080776f3Sclaudio buf += TLV_HDR_LEN + tlv_len; 168080776f3Sclaudio len -= TLV_HDR_LEN + tlv_len; 1692d825b92Srenato total += TLV_HDR_LEN + tlv_len; 170080776f3Sclaudio } 171080776f3Sclaudio 1722d825b92Srenato return (total); 173080776f3Sclaudio } 174