1 /* $NetBSD: quota.h,v 1.10 2024/02/21 22:52:31 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #pragma once 17 18 /***** 19 ***** Module Info 20 *****/ 21 22 /*! \file isc/quota.h 23 * 24 * \brief The isc_quota_t object is a simple helper object for implementing 25 * quotas on things like the number of simultaneous connections to 26 * a server. It keeps track of the amount of quota in use, and 27 * encapsulates the locking necessary to allow multiple tasks to 28 * share a quota. 29 */ 30 31 /*** 32 *** Imports. 33 ***/ 34 35 #include <isc/atomic.h> 36 #include <isc/lang.h> 37 #include <isc/magic.h> 38 #include <isc/mutex.h> 39 #include <isc/types.h> 40 41 /***** 42 ***** Types. 43 *****/ 44 45 ISC_LANG_BEGINDECLS 46 47 /*% isc_quota_cb - quota callback structure */ 48 typedef struct isc_quota_cb isc_quota_cb_t; 49 typedef void (*isc_quota_cb_func_t)(isc_quota_t *quota, void *data); 50 struct isc_quota_cb { 51 int magic; 52 isc_quota_cb_func_t cb_func; 53 void *data; 54 ISC_LINK(isc_quota_cb_t) link; 55 }; 56 57 /*% isc_quota structure */ 58 struct isc_quota { 59 int magic; 60 atomic_uint_fast32_t max; 61 atomic_uint_fast32_t used; 62 atomic_uint_fast32_t soft; 63 atomic_uint_fast32_t waiting; 64 isc_mutex_t cblock; 65 ISC_LIST(isc_quota_cb_t) cbs; 66 ISC_LINK(isc_quota_t) link; 67 }; 68 69 void 70 isc_quota_init(isc_quota_t *quota, unsigned int max); 71 /*%< 72 * Initialize a quota object. 73 */ 74 75 void 76 isc_quota_destroy(isc_quota_t *quota); 77 /*%< 78 * Destroy a quota object. 79 */ 80 81 void 82 isc_quota_soft(isc_quota_t *quota, unsigned int soft); 83 /*%< 84 * Set a soft quota. 85 */ 86 87 void 88 isc_quota_max(isc_quota_t *quota, unsigned int max); 89 /*%< 90 * Re-set a maximum quota. 91 */ 92 93 unsigned int 94 isc_quota_getmax(isc_quota_t *quota); 95 /*%< 96 * Get the maximum quota. 97 */ 98 99 unsigned int 100 isc_quota_getsoft(isc_quota_t *quota); 101 /*%< 102 * Get the soft quota. 103 */ 104 105 unsigned int 106 isc_quota_getused(isc_quota_t *quota); 107 /*%< 108 * Get the current usage of quota. 109 */ 110 111 isc_result_t 112 isc_quota_attach(isc_quota_t *quota, isc_quota_t **p); 113 /*%< 114 * 115 * Attempt to reserve one unit of 'quota', and also attaches '*p' to the quota 116 * if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA). 117 * 118 * Returns: 119 * \li #ISC_R_SUCCESS Success 120 * \li #ISC_R_SOFTQUOTA Success soft quota reached 121 * \li #ISC_R_QUOTA Quota is full 122 */ 123 124 isc_result_t 125 isc_quota_attach_cb(isc_quota_t *quota, isc_quota_t **p, isc_quota_cb_t *cb); 126 /*%< 127 * 128 * Like isc_quota_attach(), but if there's no quota left then cb->cb_func will 129 * be called when we are attached to quota. 130 * 131 * Note: It's the caller's responsibility to make sure that we don't end up 132 * with a huge number of callbacks waiting, making it easy to create a 133 * resource exhaustion attack. For example, in the case of TCP listening, 134 * we simply don't accept new connections when the quota is exceeded, so 135 * the number of callbacks waiting in the queue will be limited by the 136 * listen() backlog. 137 * 138 * Returns: 139 * \li #ISC_R_SUCCESS Success 140 * \li #ISC_R_SOFTQUOTA Success soft quota reached 141 * \li #ISC_R_QUOTA Quota is full 142 */ 143 144 void 145 isc_quota_cb_init(isc_quota_cb_t *cb, isc_quota_cb_func_t cb_func, void *data); 146 /*%< 147 * Initialize isc_quota_cb_t - setup the list, set the callback and data. 148 */ 149 150 void 151 isc_quota_detach(isc_quota_t **p); 152 /*%< 153 * Release one unit of quota, and also detaches '*p' from the quota. 154 */ 155 156 ISC_LANG_ENDDECLS 157