10Sstevel@tonic-gate/* $NetBSD$ */ 20Sstevel@tonic-gate 30Sstevel@tonic-gate/*++ 40Sstevel@tonic-gate/* NAME 50Sstevel@tonic-gate/* postscreen_dict 3 60Sstevel@tonic-gate/* SUMMARY 70Sstevel@tonic-gate/* postscreen table access wrappers 80Sstevel@tonic-gate/* SYNOPSIS 90Sstevel@tonic-gate/* #include <postscreen.h> 100Sstevel@tonic-gate/* 110Sstevel@tonic-gate/* int psc_addr_match_list_match(match_list, client_addr) 120Sstevel@tonic-gate/* ADDR_MATCH_LIST *match_list; 130Sstevel@tonic-gate/* const char *client_addr; 140Sstevel@tonic-gate/* 150Sstevel@tonic-gate/* const char *psc_cache_lookup(DICT_CACHE *cache, const char *key) 160Sstevel@tonic-gate/* DICT_CACHE *cache; 170Sstevel@tonic-gate/* const char *key; 180Sstevel@tonic-gate/* 190Sstevel@tonic-gate/* void psc_cache_update(cache, key, value) 200Sstevel@tonic-gate/* DICT_CACHE *cache; 210Sstevel@tonic-gate/* const char *key; 220Sstevel@tonic-gate/* const char *value; 230Sstevel@tonic-gate/* 240Sstevel@tonic-gate/* void psc_dict_get(dict, key) 250Sstevel@tonic-gate/* DICT *dict; 260Sstevel@tonic-gate/* const char *key; 270Sstevel@tonic-gate/* 280Sstevel@tonic-gate/* void psc_maps_find(maps, key, flags) 290Sstevel@tonic-gate/* MAPS *maps; 300Sstevel@tonic-gate/* const char *key; 310Sstevel@tonic-gate/* int flags; 320Sstevel@tonic-gate/* DESCRIPTION 330Sstevel@tonic-gate/* This module implements wrappers around time-critical table 340Sstevel@tonic-gate/* access functions. The functions log a warning when table 350Sstevel@tonic-gate/* access takes a non-trivial amount of time. 360Sstevel@tonic-gate/* 370Sstevel@tonic-gate/* psc_addr_match_list_match() is a wrapper around 380Sstevel@tonic-gate/* addr_match_list_match(). 390Sstevel@tonic-gate/* 400Sstevel@tonic-gate/* psc_cache_lookup() and psc_cache_update() are wrappers around 410Sstevel@tonic-gate/* the corresponding dict_cache() methods. 420Sstevel@tonic-gate/* 430Sstevel@tonic-gate/* psc_dict_get() and psc_maps_find() are wrappers around 440Sstevel@tonic-gate/* dict_get() and maps_find(), respectively. 450Sstevel@tonic-gate/* LICENSE 460Sstevel@tonic-gate/* .ad 470Sstevel@tonic-gate/* .fi 480Sstevel@tonic-gate/* The Secure Mailer license must be distributed with this software. 490Sstevel@tonic-gate/* AUTHOR(S) 500Sstevel@tonic-gate/* Wietse Venema 510Sstevel@tonic-gate/* IBM T.J. Watson Research 520Sstevel@tonic-gate/* P.O. Box 704 530Sstevel@tonic-gate/* Yorktown Heights, NY 10598, USA 542139Sjp161948/*--*/ 552139Sjp161948 562139Sjp161948/* System library. */ 572139Sjp161948 582139Sjp161948#include <sys_defs.h> 590Sstevel@tonic-gate 600Sstevel@tonic-gate/* Utility library. */ 610Sstevel@tonic-gate 620Sstevel@tonic-gate#include <msg.h> 630Sstevel@tonic-gate#include <dict.h> 640Sstevel@tonic-gate 650Sstevel@tonic-gate/* Global library. */ 660Sstevel@tonic-gate 670Sstevel@tonic-gate#include <maps.h> 680Sstevel@tonic-gate 690Sstevel@tonic-gate/* Application-specific. */ 700Sstevel@tonic-gate 710Sstevel@tonic-gate#include <postscreen.h> 720Sstevel@tonic-gate 730Sstevel@tonic-gate /* 740Sstevel@tonic-gate * Monitor time-critical operations. 750Sstevel@tonic-gate * 760Sstevel@tonic-gate * XXX Averaging support was added during a stable release candidate, so it 770Sstevel@tonic-gate * provides only the absolute minimum necessary. A complete implementation 780Sstevel@tonic-gate * should maintain separate statistics for each table, and it should not 790Sstevel@tonic-gate * complain when the access latency is less than the time between accesses. 800Sstevel@tonic-gate */ 810Sstevel@tonic-gate#define PSC_GET_TIME_BEFORE_LOOKUP { \ 820Sstevel@tonic-gate struct timeval _before, _after; \ 830Sstevel@tonic-gate DELTA_TIME _delta; \ 840Sstevel@tonic-gate double _new_delta_ms; \ 850Sstevel@tonic-gate GETTIMEOFDAY(&_before); 860Sstevel@tonic-gate 870Sstevel@tonic-gate#define PSC_DELTA_MS(d) ((d).dt_sec * 1000.0 + (d).dt_usec / 1000.0) 880Sstevel@tonic-gate 890Sstevel@tonic-gate#define PSC_AVERAGE(new, old) (0.1 * (new) + 0.9 * (old)) 900Sstevel@tonic-gate 910Sstevel@tonic-gate#ifndef PSC_THRESHOLD_MS 920Sstevel@tonic-gate#define PSC_THRESHOLD_MS 100 /* nag if latency > 100ms */ 930Sstevel@tonic-gate#endif 940Sstevel@tonic-gate 952139Sjp161948#ifndef PSC_WARN_LOCKOUT_S 960Sstevel@tonic-gate#define PSC_WARN_LOCKOUT_S 60 /* don't nag for 60s */ 970Sstevel@tonic-gate#endif 980Sstevel@tonic-gate 990Sstevel@tonic-gate /* 1000Sstevel@tonic-gate * Shared warning lock, so that we don't spam the logfile when the system 1010Sstevel@tonic-gate * becomes slow. 1020Sstevel@tonic-gate */ 1030Sstevel@tonic-gatestatic time_t psc_last_warn = 0; 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate#define PSC_CHECK_TIME_AFTER_LOOKUP(table, action, average) \ 1060Sstevel@tonic-gate GETTIMEOFDAY(&_after); \ 1070Sstevel@tonic-gate PSC_CALC_DELTA(_delta, _after, _before); \ 1080Sstevel@tonic-gate _new_delta_ms = PSC_DELTA_MS(_delta); \ 1090Sstevel@tonic-gate if ((average = PSC_AVERAGE(_new_delta_ms, average)) > PSC_THRESHOLD_MS \ 1100Sstevel@tonic-gate && psc_last_warn < _after.tv_sec - PSC_WARN_LOCKOUT_S) { \ 1110Sstevel@tonic-gate msg_warn("%s: %s %s average delay is %.0f ms", \ 1120Sstevel@tonic-gate myname, (table), (action), average); \ 1130Sstevel@tonic-gate psc_last_warn = _after.tv_sec; \ 1140Sstevel@tonic-gate } \ 1150Sstevel@tonic-gate} 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate/* psc_addr_match_list_match - time-critical address list lookup */ 1180Sstevel@tonic-gate 1190Sstevel@tonic-gateint psc_addr_match_list_match(ADDR_MATCH_LIST *addr_list, 1200Sstevel@tonic-gate const char *addr_str) 1210Sstevel@tonic-gate{ 1220Sstevel@tonic-gate const char *myname = "psc_addr_match_list_match"; 1230Sstevel@tonic-gate int result; 1240Sstevel@tonic-gate static double latency_ms; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate PSC_GET_TIME_BEFORE_LOOKUP; 1270Sstevel@tonic-gate result = addr_match_list_match(addr_list, addr_str); 1280Sstevel@tonic-gate PSC_CHECK_TIME_AFTER_LOOKUP("address list", "lookup", latency_ms); 1290Sstevel@tonic-gate return (result); 1300Sstevel@tonic-gate} 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate/* psc_cache_lookup - time-critical cache lookup */ 1330Sstevel@tonic-gate 1340Sstevel@tonic-gateconst char *psc_cache_lookup(DICT_CACHE *cache, const char *key) 1350Sstevel@tonic-gate{ 1362139Sjp161948 const char *myname = "psc_cache_lookup"; 1370Sstevel@tonic-gate const char *result; 1380Sstevel@tonic-gate static double latency_ms; 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate PSC_GET_TIME_BEFORE_LOOKUP; 1410Sstevel@tonic-gate result = dict_cache_lookup(cache, key); 1420Sstevel@tonic-gate PSC_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "lookup", latency_ms); 1430Sstevel@tonic-gate return (result); 1440Sstevel@tonic-gate} 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate/* psc_cache_update - time-critical cache update */ 1470Sstevel@tonic-gate 1480Sstevel@tonic-gatevoid psc_cache_update(DICT_CACHE *cache, const char *key, const char *value) 1490Sstevel@tonic-gate{ 1500Sstevel@tonic-gate const char *myname = "psc_cache_update"; 1510Sstevel@tonic-gate static double latency_ms; 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate PSC_GET_TIME_BEFORE_LOOKUP; 1540Sstevel@tonic-gate dict_cache_update(cache, key, value); 1550Sstevel@tonic-gate PSC_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "update", latency_ms); 1560Sstevel@tonic-gate} 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate/* psc_dict_get - time-critical table lookup */ 1590Sstevel@tonic-gate 1600Sstevel@tonic-gateconst char *psc_dict_get(DICT *dict, const char *key) 1610Sstevel@tonic-gate{ 1620Sstevel@tonic-gate const char *myname = "psc_dict_get"; 1630Sstevel@tonic-gate const char *result; 1642139Sjp161948 static double latency_ms; 1652139Sjp161948 1660Sstevel@tonic-gate PSC_GET_TIME_BEFORE_LOOKUP; 1670Sstevel@tonic-gate result = dict_get(dict, key); 1680Sstevel@tonic-gate PSC_CHECK_TIME_AFTER_LOOKUP(dict->name, "lookup", latency_ms); 1690Sstevel@tonic-gate return (result); 1700Sstevel@tonic-gate} 1712139Sjp161948 1722139Sjp161948/* psc_maps_find - time-critical table lookup */ 1732139Sjp161948 1742139Sjp161948const char *psc_maps_find(MAPS *maps, const char *key, int flags) 1752139Sjp161948{ 1762139Sjp161948 const char *myname = "psc_maps_find"; 1772139Sjp161948 const char *result; 1782139Sjp161948 static double latency_ms; 1792139Sjp161948 1802139Sjp161948 PSC_GET_TIME_BEFORE_LOOKUP; 1812139Sjp161948 result = maps_find(maps, key, flags); 1822139Sjp161948 PSC_CHECK_TIME_AFTER_LOOKUP(maps->title, "lookup", latency_ms); 1832139Sjp161948 return (result); 1842139Sjp161948} 1852139Sjp161948