1*43509a12Srenato /* $OpenBSD: rtp.c,v 1.1 2015/10/02 04:26:47 renato Exp $ */ 2*43509a12Srenato 3*43509a12Srenato /* 4*43509a12Srenato * Copyright (c) 2015 Renato Westphal <renato@openbsd.org> 5*43509a12Srenato * 6*43509a12Srenato * Permission to use, copy, modify, and distribute this software for any 7*43509a12Srenato * purpose with or without fee is hereby granted, provided that the above 8*43509a12Srenato * copyright notice and this permission notice appear in all copies. 9*43509a12Srenato * 10*43509a12Srenato * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11*43509a12Srenato * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12*43509a12Srenato * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13*43509a12Srenato * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14*43509a12Srenato * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15*43509a12Srenato * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16*43509a12Srenato * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17*43509a12Srenato */ 18*43509a12Srenato 19*43509a12Srenato #include <stdlib.h> 20*43509a12Srenato #include <string.h> 21*43509a12Srenato #include <arpa/inet.h> 22*43509a12Srenato 23*43509a12Srenato #include "eigrpd.h" 24*43509a12Srenato #include "eigrp.h" 25*43509a12Srenato #include "eigrpe.h" 26*43509a12Srenato #include "rde.h" 27*43509a12Srenato #include "log.h" 28*43509a12Srenato 29*43509a12Srenato void rtp_retrans_timer(int, short, void *); 30*43509a12Srenato void rtp_retrans_start_timer(struct packet *); 31*43509a12Srenato void rtp_retrans_stop_timer(struct packet *); 32*43509a12Srenato 33*43509a12Srenato struct pbuf * 34*43509a12Srenato rtp_buf_new(struct ibuf *buf) 35*43509a12Srenato { 36*43509a12Srenato struct pbuf *pbuf; 37*43509a12Srenato 38*43509a12Srenato if ((pbuf = calloc(1, sizeof(*pbuf))) == NULL) 39*43509a12Srenato fatal("rtp_buf_new"); 40*43509a12Srenato pbuf->buf = buf; 41*43509a12Srenato 42*43509a12Srenato return (pbuf); 43*43509a12Srenato } 44*43509a12Srenato 45*43509a12Srenato struct pbuf * 46*43509a12Srenato rtp_buf_hold(struct pbuf *pbuf) 47*43509a12Srenato { 48*43509a12Srenato pbuf->refcnt++; 49*43509a12Srenato return (pbuf); 50*43509a12Srenato } 51*43509a12Srenato 52*43509a12Srenato void 53*43509a12Srenato rtp_buf_release(struct pbuf *pbuf) 54*43509a12Srenato { 55*43509a12Srenato if (--pbuf->refcnt == 0) { 56*43509a12Srenato ibuf_free(pbuf->buf); 57*43509a12Srenato free(pbuf); 58*43509a12Srenato } 59*43509a12Srenato } 60*43509a12Srenato 61*43509a12Srenato struct packet * 62*43509a12Srenato rtp_packet_new(struct nbr *nbr, uint32_t seq_num, struct pbuf *pbuf) 63*43509a12Srenato { 64*43509a12Srenato struct packet *pkt; 65*43509a12Srenato 66*43509a12Srenato if ((pkt = calloc(1, sizeof(struct packet))) == NULL) 67*43509a12Srenato fatal("rtp_packet_new"); 68*43509a12Srenato 69*43509a12Srenato pkt->nbr = nbr; 70*43509a12Srenato pkt->seq_num = seq_num; 71*43509a12Srenato pkt->pbuf = rtp_buf_hold(pbuf); 72*43509a12Srenato pkt->attempts = 1; 73*43509a12Srenato evtimer_set(&pkt->ev_timeout, rtp_retrans_timer, pkt); 74*43509a12Srenato 75*43509a12Srenato return (pkt); 76*43509a12Srenato } 77*43509a12Srenato 78*43509a12Srenato void 79*43509a12Srenato rtp_packet_del(struct packet *pkt) 80*43509a12Srenato { 81*43509a12Srenato TAILQ_REMOVE(&pkt->nbr->retrans_list, pkt, entry); 82*43509a12Srenato rtp_retrans_stop_timer(pkt); 83*43509a12Srenato rtp_buf_release(pkt->pbuf); 84*43509a12Srenato free(pkt); 85*43509a12Srenato } 86*43509a12Srenato 87*43509a12Srenato void 88*43509a12Srenato rtp_process_ack(struct nbr *nbr, uint32_t ack_num) 89*43509a12Srenato { 90*43509a12Srenato struct eigrp *eigrp = nbr->ei->eigrp; 91*43509a12Srenato struct packet *pkt; 92*43509a12Srenato 93*43509a12Srenato /* window size is one */ 94*43509a12Srenato pkt = TAILQ_FIRST(&nbr->retrans_list); 95*43509a12Srenato if (pkt && pkt->seq_num == ack_num) { 96*43509a12Srenato log_debug("%s: nbr %s ack %u", __func__, 97*43509a12Srenato log_addr(eigrp->af, &nbr->addr), ack_num); 98*43509a12Srenato 99*43509a12Srenato /* dequeue packet from retransmission queue */ 100*43509a12Srenato rtp_packet_del(pkt); 101*43509a12Srenato 102*43509a12Srenato /* enqueue next packet from retransmission queue */ 103*43509a12Srenato pkt = TAILQ_FIRST(&nbr->retrans_list); 104*43509a12Srenato if (pkt) 105*43509a12Srenato rtp_send_packet(pkt); 106*43509a12Srenato } 107*43509a12Srenato } 108*43509a12Srenato 109*43509a12Srenato void 110*43509a12Srenato rtp_send_packet(struct packet *pkt) 111*43509a12Srenato { 112*43509a12Srenato rtp_retrans_start_timer(pkt); 113*43509a12Srenato send_packet(pkt->nbr->ei, pkt->nbr, 0, pkt->pbuf->buf); 114*43509a12Srenato } 115*43509a12Srenato 116*43509a12Srenato void 117*43509a12Srenato rtp_enqueue_packet(struct packet *pkt) 118*43509a12Srenato { 119*43509a12Srenato /* only send packet if transmission queue is empty */ 120*43509a12Srenato if (TAILQ_EMPTY(&pkt->nbr->retrans_list)) 121*43509a12Srenato rtp_send_packet(pkt); 122*43509a12Srenato 123*43509a12Srenato TAILQ_INSERT_TAIL(&pkt->nbr->retrans_list, pkt, entry); 124*43509a12Srenato } 125*43509a12Srenato 126*43509a12Srenato static void 127*43509a12Srenato rtp_seq_inc(struct eigrp *eigrp) 128*43509a12Srenato { 129*43509a12Srenato /* automatic wraparound with unsigned arithmetic */ 130*43509a12Srenato eigrp->seq_num++; 131*43509a12Srenato 132*43509a12Srenato /* sequence number 0 is reserved for unreliably transmission */ 133*43509a12Srenato if (eigrp->seq_num == 0) 134*43509a12Srenato eigrp->seq_num = 1; 135*43509a12Srenato } 136*43509a12Srenato 137*43509a12Srenato void 138*43509a12Srenato rtp_send_ucast(struct nbr *nbr, struct ibuf *buf) 139*43509a12Srenato { 140*43509a12Srenato struct eigrp *eigrp = nbr->ei->eigrp; 141*43509a12Srenato struct packet *pkt; 142*43509a12Srenato struct pbuf *pbuf; 143*43509a12Srenato 144*43509a12Srenato pbuf = rtp_buf_new(buf); 145*43509a12Srenato pkt = rtp_packet_new(nbr, eigrp->seq_num, pbuf); 146*43509a12Srenato rtp_enqueue_packet(pkt); 147*43509a12Srenato rtp_seq_inc(eigrp); 148*43509a12Srenato } 149*43509a12Srenato 150*43509a12Srenato void 151*43509a12Srenato rtp_send_mcast(struct eigrp_iface *ei, struct ibuf *buf) 152*43509a12Srenato { 153*43509a12Srenato struct eigrp *eigrp = ei->eigrp; 154*43509a12Srenato struct nbr *nbr; 155*43509a12Srenato int total = 0, pending = 0; 156*43509a12Srenato struct packet *pkt; 157*43509a12Srenato struct pbuf *pbuf; 158*43509a12Srenato uint32_t flags = 0; 159*43509a12Srenato struct seq_addr_entry *sa; 160*43509a12Srenato struct seq_addr_head seq_addr_list; 161*43509a12Srenato 162*43509a12Srenato TAILQ_FOREACH(nbr, &ei->nbr_list, entry) { 163*43509a12Srenato if (nbr->flags & F_EIGRP_NBR_SELF) 164*43509a12Srenato continue; 165*43509a12Srenato if (!TAILQ_EMPTY(&nbr->retrans_list)) 166*43509a12Srenato pending++; 167*43509a12Srenato total++; 168*43509a12Srenato } 169*43509a12Srenato if (total == 0) 170*43509a12Srenato return; 171*43509a12Srenato 172*43509a12Srenato /* 173*43509a12Srenato * send a multicast if there's at least one neighbor with an empty 174*43509a12Srenato * queue on the interface. 175*43509a12Srenato */ 176*43509a12Srenato if (pending < total) { 177*43509a12Srenato /* 178*43509a12Srenato * build a hello packet with a seq tlv indicating all the 179*43509a12Srenato * neighbors that have full queues. 180*43509a12Srenato */ 181*43509a12Srenato if (pending > 0) { 182*43509a12Srenato flags |= EIGRP_HDR_FLAG_CR; 183*43509a12Srenato TAILQ_INIT(&seq_addr_list); 184*43509a12Srenato 185*43509a12Srenato TAILQ_FOREACH(nbr, &ei->nbr_list, entry) { 186*43509a12Srenato if (TAILQ_EMPTY(&nbr->retrans_list)) 187*43509a12Srenato continue; 188*43509a12Srenato if ((sa = calloc(1, sizeof(*sa))) == NULL) 189*43509a12Srenato fatal("rtp_send_mcast"); 190*43509a12Srenato sa->af = eigrp->af; 191*43509a12Srenato memcpy(&sa->addr, &nbr->addr, sizeof(sa->addr)); 192*43509a12Srenato TAILQ_INSERT_TAIL(&seq_addr_list, sa, entry); 193*43509a12Srenato } 194*43509a12Srenato 195*43509a12Srenato send_hello(ei, &seq_addr_list, eigrp->seq_num); 196*43509a12Srenato seq_addr_list_clr(&seq_addr_list); 197*43509a12Srenato } 198*43509a12Srenato send_packet(ei, NULL, flags, buf); 199*43509a12Srenato } 200*43509a12Srenato 201*43509a12Srenato /* schedule an unicast retransmission for each neighbor */ 202*43509a12Srenato pbuf = rtp_buf_new(buf); 203*43509a12Srenato TAILQ_FOREACH(nbr, &ei->nbr_list, entry) { 204*43509a12Srenato pkt = rtp_packet_new(nbr, eigrp->seq_num, pbuf); 205*43509a12Srenato TAILQ_INSERT_TAIL(&nbr->retrans_list, pkt, entry); 206*43509a12Srenato } 207*43509a12Srenato 208*43509a12Srenato rtp_seq_inc(eigrp); 209*43509a12Srenato } 210*43509a12Srenato 211*43509a12Srenato void 212*43509a12Srenato rtp_send(struct eigrp_iface *ei, struct nbr *nbr, struct ibuf *buf) 213*43509a12Srenato { 214*43509a12Srenato if (nbr) 215*43509a12Srenato rtp_send_ucast(nbr, buf); 216*43509a12Srenato else 217*43509a12Srenato rtp_send_mcast(ei, buf); 218*43509a12Srenato } 219*43509a12Srenato 220*43509a12Srenato void 221*43509a12Srenato rtp_send_ack(struct nbr *nbr) 222*43509a12Srenato { 223*43509a12Srenato struct eigrp *eigrp = nbr->ei->eigrp; 224*43509a12Srenato struct ibuf *buf; 225*43509a12Srenato 226*43509a12Srenato if ((buf = ibuf_dynamic(PKG_DEF_SIZE, 227*43509a12Srenato IP_MAXPACKET - sizeof(struct ip))) == NULL) 228*43509a12Srenato fatal("rtp_send_ack"); 229*43509a12Srenato 230*43509a12Srenato /* EIGRP header */ 231*43509a12Srenato if (gen_eigrp_hdr(buf, EIGRP_OPC_HELLO, 0, 0, eigrp->as)) 232*43509a12Srenato goto fail; 233*43509a12Srenato 234*43509a12Srenato /* send unreliably */ 235*43509a12Srenato send_packet(nbr->ei, nbr, 0, buf); 236*43509a12Srenato ibuf_free(buf); 237*43509a12Srenato return; 238*43509a12Srenato fail: 239*43509a12Srenato log_warnx("%s: failed to send message", __func__); 240*43509a12Srenato ibuf_free(buf); 241*43509a12Srenato } 242*43509a12Srenato 243*43509a12Srenato /* timers */ 244*43509a12Srenato 245*43509a12Srenato /* ARGSUSED */ 246*43509a12Srenato void 247*43509a12Srenato rtp_retrans_timer(int fd, short event, void *arg) 248*43509a12Srenato { 249*43509a12Srenato struct packet *pkt = arg; 250*43509a12Srenato struct eigrp *eigrp = pkt->nbr->ei->eigrp; 251*43509a12Srenato 252*43509a12Srenato pkt->attempts++; 253*43509a12Srenato 254*43509a12Srenato if (pkt->attempts > RTP_RTRNS_MAX_ATTEMPTS) { 255*43509a12Srenato log_warnx("%s: retry limit exceeded, nbr %s", __func__, 256*43509a12Srenato log_addr(eigrp->af, &pkt->nbr->addr)); 257*43509a12Srenato nbr_del(pkt->nbr); 258*43509a12Srenato return; 259*43509a12Srenato } 260*43509a12Srenato 261*43509a12Srenato rtp_send_packet(pkt); 262*43509a12Srenato } 263*43509a12Srenato 264*43509a12Srenato void 265*43509a12Srenato rtp_retrans_start_timer(struct packet *pkt) 266*43509a12Srenato { 267*43509a12Srenato struct timeval tv; 268*43509a12Srenato 269*43509a12Srenato timerclear(&tv); 270*43509a12Srenato tv.tv_sec = RTP_RTRNS_INTERVAL; 271*43509a12Srenato if (evtimer_add(&pkt->ev_timeout, &tv) == -1) 272*43509a12Srenato fatal("rtp_retrans_start_timer"); 273*43509a12Srenato } 274*43509a12Srenato 275*43509a12Srenato void 276*43509a12Srenato rtp_retrans_stop_timer(struct packet *pkt) 277*43509a12Srenato { 278*43509a12Srenato if (evtimer_pending(&pkt->ev_timeout, NULL) && 279*43509a12Srenato evtimer_del(&pkt->ev_timeout) == -1) 280*43509a12Srenato fatal("rtp_retrans_stop_timer"); 281*43509a12Srenato } 282*43509a12Srenato 283*43509a12Srenato /* ARGSUSED */ 284*43509a12Srenato void 285*43509a12Srenato rtp_ack_timer(int fd, short event, void *arg) 286*43509a12Srenato { 287*43509a12Srenato struct nbr *nbr = arg; 288*43509a12Srenato 289*43509a12Srenato rtp_send_ack(nbr); 290*43509a12Srenato } 291*43509a12Srenato 292*43509a12Srenato void 293*43509a12Srenato rtp_ack_start_timer(struct nbr *nbr) 294*43509a12Srenato { 295*43509a12Srenato struct timeval tv; 296*43509a12Srenato 297*43509a12Srenato timerclear(&tv); 298*43509a12Srenato tv.tv_usec = RTP_ACK_TIMEOUT; 299*43509a12Srenato if (evtimer_add(&nbr->ev_ack, &tv) == -1) 300*43509a12Srenato fatal("rtp_ack_start_timer"); 301*43509a12Srenato } 302*43509a12Srenato 303*43509a12Srenato void 304*43509a12Srenato rtp_ack_stop_timer(struct nbr *nbr) 305*43509a12Srenato { 306*43509a12Srenato if (evtimer_pending(&nbr->ev_ack, NULL) && 307*43509a12Srenato evtimer_del(&nbr->ev_ack) == -1) 308*43509a12Srenato fatal("rtp_ack_stop_timer"); 309*43509a12Srenato } 310