1 /* $OpenBSD: timer.c,v 1.16 2015/01/16 06:40:15 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2003-2007 Henning Brauer <henning@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 <stdlib.h> 21 22 #include "bgpd.h" 23 #include "session.h" 24 25 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) 26 27 time_t 28 getmonotime(void) 29 { 30 struct timespec ts; 31 32 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) 33 fatal("clock_gettime"); 34 35 return (ts.tv_sec); 36 } 37 38 struct peer_timer * 39 timer_get(struct peer *p, enum Timer timer) 40 { 41 struct peer_timer *pt; 42 43 TAILQ_FOREACH(pt, &p->timers, entry) 44 if (pt->type == timer) 45 break; 46 47 return (pt); 48 } 49 50 struct peer_timer * 51 timer_nextisdue(struct peer *p) 52 { 53 struct peer_timer *pt; 54 55 pt = TAILQ_FIRST(&p->timers); 56 if (pt != NULL && pt->val > 0 && pt->val <= getmonotime()) 57 return (pt); 58 return (NULL); 59 } 60 61 time_t 62 timer_nextduein(struct peer *p) 63 { 64 struct peer_timer *pt; 65 66 if ((pt = TAILQ_FIRST(&p->timers)) != NULL && pt->val > 0) 67 return (MAXIMUM(pt->val - getmonotime(), 0)); 68 return (-1); 69 } 70 71 int 72 timer_running(struct peer *p, enum Timer timer, time_t *left) 73 { 74 struct peer_timer *pt = timer_get(p, timer); 75 76 if (pt != NULL && pt->val > 0) { 77 if (left != NULL) 78 *left = pt->val - getmonotime(); 79 return (1); 80 } 81 return (0); 82 } 83 84 void 85 timer_set(struct peer *p, enum Timer timer, u_int offset) 86 { 87 struct peer_timer *t, *pt = timer_get(p, timer); 88 89 if (pt == NULL) { /* have to create */ 90 if ((pt = malloc(sizeof(*pt))) == NULL) 91 fatal("timer_set"); 92 pt->type = timer; 93 } else { 94 if (pt->val == getmonotime() + (time_t)offset) 95 return; 96 TAILQ_REMOVE(&p->timers, pt, entry); 97 } 98 99 pt->val = getmonotime() + offset; 100 101 TAILQ_FOREACH(t, &p->timers, entry) 102 if (t->val == 0 || t->val > pt->val) 103 break; 104 if (t != NULL) 105 TAILQ_INSERT_BEFORE(t, pt, entry); 106 else 107 TAILQ_INSERT_TAIL(&p->timers, pt, entry); 108 } 109 110 void 111 timer_stop(struct peer *p, enum Timer timer) 112 { 113 struct peer_timer *pt = timer_get(p, timer); 114 115 if (pt != NULL) { 116 pt->val = 0; 117 TAILQ_REMOVE(&p->timers, pt, entry); 118 TAILQ_INSERT_TAIL(&p->timers, pt, entry); 119 } 120 } 121 122 void 123 timer_remove(struct peer *p, enum Timer timer) 124 { 125 struct peer_timer *pt = timer_get(p, timer); 126 127 if (pt != NULL) { 128 TAILQ_REMOVE(&p->timers, pt, entry); 129 free(pt); 130 } 131 } 132 133 void 134 timer_remove_all(struct peer *p) 135 { 136 struct peer_timer *pt; 137 138 while ((pt = TAILQ_FIRST(&p->timers)) != NULL) { 139 TAILQ_REMOVE(&p->timers, pt, entry); 140 free(pt); 141 } 142 } 143