1 /* $OpenBSD: init.c,v 1.2 2009/06/05 22:34:45 michele 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/in_systm.h> 25 #include <netinet/ip.h> 26 #include <arpa/inet.h> 27 #include <net/if_dl.h> 28 #include <unistd.h> 29 30 #include <errno.h> 31 #include <event.h> 32 #include <stdlib.h> 33 #include <string.h> 34 35 #include "ldpd.h" 36 #include "ldp.h" 37 #include "log.h" 38 #include "ldpe.h" 39 40 int gen_init_prms_tlv(struct buf *, struct nbr *, u_int16_t); 41 42 int 43 send_init(struct nbr *nbr) 44 { 45 struct buf *buf; 46 u_int16_t size; 47 48 if (nbr->iface->passive) 49 return (0); 50 51 log_debug("send_init: neighbor ID %s", inet_ntoa(nbr->id)); 52 53 if ((buf = buf_open(LDP_MAX_LEN)) == NULL) 54 fatal("send_init"); 55 56 size = LDP_HDR_SIZE + sizeof(struct ldp_msg) + SESS_PRMS_SIZE; 57 58 gen_ldp_hdr(buf, nbr->iface, size); 59 60 size -= LDP_HDR_SIZE; 61 62 gen_msg_tlv(buf, MSG_TYPE_INIT, size); 63 64 size -= sizeof(struct ldp_msg); 65 66 gen_init_prms_tlv(buf, nbr, size); 67 68 bufferevent_write(nbr->bev, buf->buf, buf->wpos); 69 buf_free(buf); 70 71 return (0); 72 } 73 74 int 75 recv_init(struct nbr *nbr, char *buf, u_int16_t len) 76 { 77 struct ldp_msg *init; 78 struct sess_prms_tlv *sess_tlv; 79 80 log_debug("recv_init: neighbor ID %s", inet_ntoa(nbr->id)); 81 82 init = (struct ldp_msg *)buf; 83 84 if ((len - TLV_HDR_LEN) < ntohs(init->length)) { 85 session_shutdown(nbr, S_BAD_MSG_LEN, init->msgid, init->type); 86 return (-1); 87 } 88 89 buf += sizeof(struct ldp_msg); 90 len -= sizeof(struct ldp_msg); 91 92 sess_tlv = (struct sess_prms_tlv *)buf; 93 94 if (len < SESS_PRMS_SIZE || 95 ntohs(sess_tlv->length) != (SESS_PRMS_SIZE - TLV_HDR_LEN)) { 96 session_shutdown(nbr, S_BAD_TLV_LEN, init->msgid, init->type); 97 return (-1); 98 } 99 100 if (nbr->iface->keepalive < ntohs(sess_tlv->keepalive_time)) 101 nbr->keepalive = nbr->iface->keepalive; 102 else 103 nbr->keepalive = ntohs(sess_tlv->keepalive_time); 104 105 nbr_fsm(nbr, NBR_EVT_INIT_RCVD); 106 107 return (ntohs(init->length)); 108 } 109 110 int 111 gen_init_prms_tlv(struct buf *buf, struct nbr *nbr, u_int16_t size) 112 { 113 struct sess_prms_tlv parms; 114 115 /* We want just the size of the value */ 116 size -= TLV_HDR_LEN; 117 118 bzero(&parms, sizeof(parms)); 119 parms.type = htons(TLV_TYPE_COMMONSESSION); 120 parms.length = htons(size); 121 parms.proto_version = htons(LDP_VERSION); 122 parms.keepalive_time = htons(nbr->iface->keepalive); 123 parms.reserved = 0; 124 parms.pvlim = 0; 125 parms.max_pdu_len = 0; 126 parms.lsr_id = nbr->id.s_addr; 127 /* XXX: nbr lspace */ 128 parms.lspace_id = 0; 129 130 return (buf_add(buf, &parms, SESS_PRMS_SIZE)); 131 } 132