xref: /openbsd-src/usr.sbin/bgpd/timer.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
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