Merge branch 'vendor/OPENSSH'
[dragonfly.git] / contrib / bind / lib / isc / unix / resource.c
1 /*
2  * Copyright (C) 2004, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000, 2001  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: resource.c,v 1.14.128.9 2009/02/13 23:46:42 tbox Exp $ */
19
20 #include <config.h>
21
22 #include <sys/types.h>
23 #include <sys/time.h>   /* Required on some systems for <sys/resource.h>. */
24 #include <sys/resource.h>
25
26 #include <isc/platform.h>
27 #include <isc/resource.h>
28 #include <isc/result.h>
29 #include <isc/util.h>
30
31 #ifdef __linux__
32 #include <linux/fs.h>   /* To get the large NR_OPEN. */
33 #endif
34
35 #if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
36 #include <sys/dyntune.h>
37 #endif
38
39 #include "errno2result.h"
40
41 static isc_result_t
42 resource2rlim(isc_resource_t resource, int *rlim_resource) {
43         isc_result_t result = ISC_R_SUCCESS;
44
45         switch (resource) {
46         case isc_resource_coresize:
47                 *rlim_resource = RLIMIT_CORE;
48                 break;
49         case isc_resource_cputime:
50                 *rlim_resource = RLIMIT_CPU;
51                 break;
52         case isc_resource_datasize:
53                 *rlim_resource = RLIMIT_DATA;
54                 break;
55         case isc_resource_filesize:
56                 *rlim_resource = RLIMIT_FSIZE;
57                 break;
58         case isc_resource_lockedmemory:
59 #ifdef RLIMIT_MEMLOCK
60                 *rlim_resource = RLIMIT_MEMLOCK;
61 #else
62                 result = ISC_R_NOTIMPLEMENTED;
63 #endif
64                 break;
65         case isc_resource_openfiles:
66 #ifdef RLIMIT_NOFILE
67                 *rlim_resource = RLIMIT_NOFILE;
68 #else
69                 result = ISC_R_NOTIMPLEMENTED;
70 #endif
71                 break;
72         case isc_resource_processes:
73 #ifdef RLIMIT_NPROC
74                 *rlim_resource = RLIMIT_NPROC;
75 #else
76                 result = ISC_R_NOTIMPLEMENTED;
77 #endif
78                 break;
79         case isc_resource_residentsize:
80 #ifdef RLIMIT_RSS
81                 *rlim_resource = RLIMIT_RSS;
82 #else
83                 result = ISC_R_NOTIMPLEMENTED;
84 #endif
85                 break;
86         case isc_resource_stacksize:
87                 *rlim_resource = RLIMIT_STACK;
88                 break;
89         default:
90                 /*
91                  * This test is not very robust if isc_resource_t
92                  * changes, but generates a clear assertion message.
93                  */
94                 REQUIRE(resource >= isc_resource_coresize &&
95                         resource <= isc_resource_stacksize);
96
97                 result = ISC_R_RANGE;
98                 break;
99         }
100
101         return (result);
102 }
103
104 isc_result_t
105 isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
106         struct rlimit rl;
107         ISC_PLATFORM_RLIMITTYPE rlim_value;
108         int unixresult;
109         int unixresource;
110         isc_result_t result;
111
112         result = resource2rlim(resource, &unixresource);
113         if (result != ISC_R_SUCCESS)
114                 return (result);
115
116         if (value == ISC_RESOURCE_UNLIMITED)
117                 rlim_value = RLIM_INFINITY;
118
119         else {
120                 /*
121                  * isc_resourcevalue_t was chosen as an unsigned 64 bit
122                  * integer so that it could contain the maximum range of
123                  * reasonable values.  Unfortunately, this exceeds the typical
124                  * range on Unix systems.  Ensure the range of
125                  * ISC_PLATFORM_RLIMITTYPE is not overflowed.
126                  */
127                 isc_resourcevalue_t rlim_max;
128                 isc_boolean_t rlim_t_is_signed =
129                         ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0);
130
131                 if (rlim_t_is_signed)
132                         rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 <<
133                                      (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1));
134                 else
135                         rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1;
136
137                 if (value > rlim_max)
138                         value = rlim_max;
139
140                 rlim_value = value;
141         }
142
143         rl.rlim_cur = rl.rlim_max = rlim_value;
144         unixresult = setrlimit(unixresource, &rl);
145
146         if (unixresult == 0)
147                 return (ISC_R_SUCCESS);
148
149 #if defined(OPEN_MAX) && defined(__APPLE__)
150         /*
151          * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the
152          * maximum possible value is OPEN_MAX.  BIND8 used to use
153          * sysconf(_SC_OPEN_MAX) for such a case, but this value is much
154          * smaller than OPEN_MAX and is not really effective.
155          */
156         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
157                 rl.rlim_cur = OPEN_MAX;
158                 unixresult = setrlimit(unixresource, &rl);
159                 if (unixresult == 0)
160                         return (ISC_R_SUCCESS);
161         }
162 #elif defined(__linux__)
163 #ifndef NR_OPEN
164 #define NR_OPEN (1024*1024)
165 #endif
166
167         /*
168          * Some Linux kernels don't accept RLIM_INFINIT; the maximum
169          * possible value is the NR_OPEN defined in linux/fs.h.
170          */
171         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
172                 rl.rlim_cur = rl.rlim_max = NR_OPEN;
173                 unixresult = setrlimit(unixresource, &rl);
174                 if (unixresult == 0)
175                         return (ISC_R_SUCCESS);
176         }
177 #elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
178         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
179                 uint64_t maxfiles;
180                 if (gettune("maxfiles_lim", &maxfiles) == 0) {
181                         rl.rlim_cur = rl.rlim_max = maxfiles;
182                         unixresult = setrlimit(unixresource, &rl);
183                         if (unixresult == 0)
184                                 return (ISC_R_SUCCESS);
185                 }
186         }
187 #endif
188         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
189                 if (getrlimit(unixresource, &rl) == 0) {
190                         rl.rlim_cur = rl.rlim_max;
191                         unixresult = setrlimit(unixresource, &rl);
192                         if (unixresult == 0)
193                                 return (ISC_R_SUCCESS);
194                 }
195         }
196         return (isc__errno2result(errno));
197 }
198
199 isc_result_t
200 isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
201         int unixresult;
202         int unixresource;
203         struct rlimit rl;
204         isc_result_t result;
205
206         result = resource2rlim(resource, &unixresource);
207         if (result == ISC_R_SUCCESS) {
208                 unixresult = getrlimit(unixresource, &rl);
209                 INSIST(unixresult == 0);
210                 *value = rl.rlim_max;
211         }
212
213         return (result);
214 }
215
216 isc_result_t
217 isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
218         int unixresult;
219         int unixresource;
220         struct rlimit rl;
221         isc_result_t result;
222
223         result = resource2rlim(resource, &unixresource);
224         if (result == ISC_R_SUCCESS) {
225                 unixresult = getrlimit(unixresource, &rl);
226                 INSIST(unixresult == 0);
227                 *value = rl.rlim_cur;
228         }
229
230         return (result);
231 }