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