1ae326725SJun-ichiro itojun Hagino /* $FreeBSD$ */ 2fa19f9beSHajimu UMEMOTO /* $KAME: timer.c,v 1.9 2002/06/10 19:59:47 itojun Exp $ */ 3b26e03e9SKris Kennaway 49a4365d0SYoshinobu Inoue /* 59a4365d0SYoshinobu Inoue * Copyright (C) 1998 WIDE Project. 6*37241896SHiroki Sato * Copyright (C) 2011 Hiroki Sato <hrs@FreeBSD.org> 79a4365d0SYoshinobu Inoue * All rights reserved. 89a4365d0SYoshinobu Inoue * 99a4365d0SYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 109a4365d0SYoshinobu Inoue * modification, are permitted provided that the following conditions 119a4365d0SYoshinobu Inoue * are met: 129a4365d0SYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 139a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 149a4365d0SYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 159a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 169a4365d0SYoshinobu Inoue * documentation and/or other materials provided with the distribution. 179a4365d0SYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 189a4365d0SYoshinobu Inoue * may be used to endorse or promote products derived from this software 199a4365d0SYoshinobu Inoue * without specific prior written permission. 209a4365d0SYoshinobu Inoue * 219a4365d0SYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 229a4365d0SYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239a4365d0SYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249a4365d0SYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 259a4365d0SYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269a4365d0SYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279a4365d0SYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289a4365d0SYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299a4365d0SYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309a4365d0SYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319a4365d0SYoshinobu Inoue * SUCH DAMAGE. 329a4365d0SYoshinobu Inoue */ 339a4365d0SYoshinobu Inoue 349a4365d0SYoshinobu Inoue #include <sys/time.h> 35db82af41SHiroki Sato #include <sys/queue.h> 36*37241896SHiroki Sato #include <sys/socket.h> 37*37241896SHiroki Sato 38*37241896SHiroki Sato #include <net/if.h> 39*37241896SHiroki Sato #include <net/if_dl.h> 40*37241896SHiroki Sato #include <netinet/in.h> 419a4365d0SYoshinobu Inoue 429a4365d0SYoshinobu Inoue #include <unistd.h> 439a4365d0SYoshinobu Inoue #include <syslog.h> 449a4365d0SYoshinobu Inoue #include <stdlib.h> 459a4365d0SYoshinobu Inoue #include <string.h> 4672286081SSUZUKI Shinsuke #include <search.h> 47*37241896SHiroki Sato #include <netdb.h> 489a4365d0SYoshinobu Inoue 49*37241896SHiroki Sato #include "rtadvd.h" 50*37241896SHiroki Sato #include "timer_subr.h" 51*37241896SHiroki Sato #include "timer.h" 529a4365d0SYoshinobu Inoue 53db82af41SHiroki Sato struct rtadvd_timer_head_t ra_timer = 54db82af41SHiroki Sato TAILQ_HEAD_INITIALIZER(ra_timer); 55db82af41SHiroki Sato static struct timeval tm_limit = {0x7fffffff, 0x7fffffff}; 56db82af41SHiroki Sato static struct timeval tm_max; 579a4365d0SYoshinobu Inoue 589a4365d0SYoshinobu Inoue void 59db82af41SHiroki Sato rtadvd_timer_init(void) 609a4365d0SYoshinobu Inoue { 619a4365d0SYoshinobu Inoue 62db82af41SHiroki Sato tm_max = tm_limit; 63db82af41SHiroki Sato TAILQ_INIT(&ra_timer); 649a4365d0SYoshinobu Inoue } 659a4365d0SYoshinobu Inoue 66*37241896SHiroki Sato void 67*37241896SHiroki Sato rtadvd_update_timeout_handler(void) 68*37241896SHiroki Sato { 69*37241896SHiroki Sato struct ifinfo *ifi; 70*37241896SHiroki Sato 71*37241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 72*37241896SHiroki Sato switch (ifi->ifi_state) { 73*37241896SHiroki Sato case IFI_STATE_CONFIGURED: 74*37241896SHiroki Sato case IFI_STATE_TRANSITIVE: 75*37241896SHiroki Sato if (ifi->ifi_ra_timer != NULL) 76*37241896SHiroki Sato continue; 77*37241896SHiroki Sato 78*37241896SHiroki Sato syslog(LOG_DEBUG, "<%s> add timer for %s (idx=%d)", 79*37241896SHiroki Sato __func__, ifi->ifi_ifname, ifi->ifi_ifindex); 80*37241896SHiroki Sato ifi->ifi_ra_timer = rtadvd_add_timer(ra_timeout, 81*37241896SHiroki Sato ra_timer_update, ifi, ifi); 82*37241896SHiroki Sato ra_timer_update((void *)ifi, 83*37241896SHiroki Sato &ifi->ifi_ra_timer->rat_tm); 84*37241896SHiroki Sato rtadvd_set_timer(&ifi->ifi_ra_timer->rat_tm, 85*37241896SHiroki Sato ifi->ifi_ra_timer); 86*37241896SHiroki Sato break; 87*37241896SHiroki Sato case IFI_STATE_UNCONFIGURED: 88*37241896SHiroki Sato if (ifi->ifi_ra_timer == NULL) 89*37241896SHiroki Sato continue; 90*37241896SHiroki Sato 91*37241896SHiroki Sato syslog(LOG_DEBUG, 92*37241896SHiroki Sato "<%s> remove timer for %s (idx=%d)", __func__, 93*37241896SHiroki Sato ifi->ifi_ifname, ifi->ifi_ifindex); 94*37241896SHiroki Sato rtadvd_remove_timer(ifi->ifi_ra_timer); 95*37241896SHiroki Sato ifi->ifi_ra_timer = NULL; 96*37241896SHiroki Sato break; 97*37241896SHiroki Sato } 98*37241896SHiroki Sato } 99*37241896SHiroki Sato 100*37241896SHiroki Sato return; 101*37241896SHiroki Sato } 102*37241896SHiroki Sato 1039a4365d0SYoshinobu Inoue struct rtadvd_timer * 104784bddbcSKevin Lo rtadvd_add_timer(struct rtadvd_timer *(*timeout)(void *), 105784bddbcSKevin Lo void (*update)(void *, struct timeval *), 1069a4365d0SYoshinobu Inoue void *timeodata, void *updatedata) 1079a4365d0SYoshinobu Inoue { 108db82af41SHiroki Sato struct rtadvd_timer *rat; 1099a4365d0SYoshinobu Inoue 1109a4365d0SYoshinobu Inoue if (timeout == NULL) { 1119a4365d0SYoshinobu Inoue syslog(LOG_ERR, 112fa19f9beSHajimu UMEMOTO "<%s> timeout function unspecified", __func__); 1139a4365d0SYoshinobu Inoue exit(1); 1149a4365d0SYoshinobu Inoue } 115db82af41SHiroki Sato 116db82af41SHiroki Sato rat = malloc(sizeof(*rat)); 117db82af41SHiroki Sato if (rat == NULL) { 118db82af41SHiroki Sato syslog(LOG_ERR, 119db82af41SHiroki Sato "<%s> can't allocate memory", __func__); 120db82af41SHiroki Sato exit(1); 121db82af41SHiroki Sato } 122db82af41SHiroki Sato memset(rat, 0, sizeof(*rat)); 123db82af41SHiroki Sato 124db82af41SHiroki Sato rat->rat_expire = timeout; 125db82af41SHiroki Sato rat->rat_update = update; 126db82af41SHiroki Sato rat->rat_expire_data = timeodata; 127db82af41SHiroki Sato rat->rat_update_data = updatedata; 128db82af41SHiroki Sato rat->rat_tm = tm_max; 1299a4365d0SYoshinobu Inoue 1309a4365d0SYoshinobu Inoue /* link into chain */ 131db82af41SHiroki Sato TAILQ_INSERT_TAIL(&ra_timer, rat, rat_next); 1329a4365d0SYoshinobu Inoue 133db82af41SHiroki Sato return (rat); 1349a4365d0SYoshinobu Inoue } 1359a4365d0SYoshinobu Inoue 1369a4365d0SYoshinobu Inoue void 137db82af41SHiroki Sato rtadvd_remove_timer(struct rtadvd_timer *rat) 138b26e03e9SKris Kennaway { 139db82af41SHiroki Sato 140db82af41SHiroki Sato if (rat == NULL) 141db82af41SHiroki Sato return; 142db82af41SHiroki Sato 143db82af41SHiroki Sato TAILQ_REMOVE(&ra_timer, rat, rat_next); 144db82af41SHiroki Sato free(rat); 145b26e03e9SKris Kennaway } 146b26e03e9SKris Kennaway 1479a4365d0SYoshinobu Inoue /* 1480a5f3ef4SHajimu UMEMOTO * Check expiration for each timer. If a timer expires, 1499a4365d0SYoshinobu Inoue * call the expire function for the timer and update the timer. 1509a4365d0SYoshinobu Inoue * Return the next interval for select() call. 1519a4365d0SYoshinobu Inoue */ 1529a4365d0SYoshinobu Inoue struct timeval * 153db82af41SHiroki Sato rtadvd_check_timer(void) 1549a4365d0SYoshinobu Inoue { 1559a4365d0SYoshinobu Inoue static struct timeval returnval; 1569a4365d0SYoshinobu Inoue struct timeval now; 157db82af41SHiroki Sato struct rtadvd_timer *rat; 1589a4365d0SYoshinobu Inoue 1599a4365d0SYoshinobu Inoue gettimeofday(&now, NULL); 160db82af41SHiroki Sato tm_max = tm_limit; 161db82af41SHiroki Sato TAILQ_FOREACH(rat, &ra_timer, rat_next) { 162db82af41SHiroki Sato if (TIMEVAL_LEQ(&rat->rat_tm, &now)) { 163db82af41SHiroki Sato if (((*rat->rat_expire)(rat->rat_expire_data) == NULL)) 1640a5f3ef4SHajimu UMEMOTO continue; /* the timer was removed */ 165db82af41SHiroki Sato if (rat->rat_update) 166db82af41SHiroki Sato (*rat->rat_update)(rat->rat_update_data, &rat->rat_tm); 167db82af41SHiroki Sato TIMEVAL_ADD(&rat->rat_tm, &now, &rat->rat_tm); 1689a4365d0SYoshinobu Inoue } 169db82af41SHiroki Sato if (TIMEVAL_LT(&rat->rat_tm, &tm_max)) 170db82af41SHiroki Sato tm_max = rat->rat_tm; 1719a4365d0SYoshinobu Inoue } 172db82af41SHiroki Sato if (TIMEVAL_EQUAL(&tm_max, &tm_limit)) { 173b26e03e9SKris Kennaway /* no need to timeout */ 174b26e03e9SKris Kennaway return (NULL); 175db82af41SHiroki Sato } else if (TIMEVAL_LT(&tm_max, &now)) { 1769a4365d0SYoshinobu Inoue /* this may occur when the interval is too small */ 1779a4365d0SYoshinobu Inoue returnval.tv_sec = returnval.tv_usec = 0; 178fa19f9beSHajimu UMEMOTO } else 179db82af41SHiroki Sato TIMEVAL_SUB(&tm_max, &now, &returnval); 1809a4365d0SYoshinobu Inoue return (&returnval); 1819a4365d0SYoshinobu Inoue } 1829a4365d0SYoshinobu Inoue 183*37241896SHiroki Sato void 184*37241896SHiroki Sato rtadvd_set_timer(struct timeval *tm, struct rtadvd_timer *rat) 1859a4365d0SYoshinobu Inoue { 186*37241896SHiroki Sato struct timeval now; 1879a4365d0SYoshinobu Inoue 188*37241896SHiroki Sato /* reset the timer */ 1899a4365d0SYoshinobu Inoue gettimeofday(&now, NULL); 190*37241896SHiroki Sato TIMEVAL_ADD(&now, tm, &rat->rat_tm); 1919a4365d0SYoshinobu Inoue 192*37241896SHiroki Sato /* update the next expiration time */ 193*37241896SHiroki Sato if (TIMEVAL_LT(&rat->rat_tm, &tm_max)) 194*37241896SHiroki Sato tm_max = rat->rat_tm; 1959a4365d0SYoshinobu Inoue 196*37241896SHiroki Sato return; 1979a4365d0SYoshinobu Inoue } 198