]> git.ipfire.org Git - thirdparty/squid.git/blame - src/snmp_agent.cc
consistent formatting
[thirdparty/squid.git] / src / snmp_agent.cc
CommitLineData
43d4303e 1
2/*
83704487 3 * $Id: snmp_agent.cc,v 1.77 2000/06/27 22:06:03 hno Exp $
43d4303e 4 *
5 * DEBUG: section 49 SNMP Interface
6 * AUTHOR: Kostas Anagnostakis
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
e25c139f 9 * ----------------------------------------------------------
43d4303e 10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
e25c139f 13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
efd900cb 15 * the Regents of the University of California. Please see the
16 * COPYRIGHT file for full details. Squid incorporates software
17 * developed and/or copyrighted by other sources. Please see the
18 * CREDITS file for full details.
43d4303e 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
43d4303e 34 */
35
36
25c1b8b7 37#include "squid.h"
571c3b88 38#include "cache_snmp.h"
25c1b8b7 39
451b07c5 40extern StatCounters *snmpStatGet(int);
571c3b88 41
571c3b88 42/************************************************************************
25c1b8b7 43
571c3b88 44 SQUID MIB Implementation
25c1b8b7 45
571c3b88 46 ************************************************************************/
25c1b8b7 47
d0e0c8d2 48variable_list *
6f47fbc7 49snmp_sysFn(variable_list * Var, snint * ErrP)
571c3b88 50{
736eb6ad 51 variable_list *Answer = NULL;
f763bb01 52 debug(49, 5) ("snmp_sysFn: Processing request:\n", Var->name[LEN_SQ_SYS]);
43d4303e 53 snmpDebugOid(5, Var->name, Var->name_length);
d0e0c8d2 54 *ErrP = SNMP_ERR_NOERROR;
f763bb01 55 switch (Var->name[LEN_SQ_SYS]) {
d0e0c8d2 56 case SYSVMSIZ:
736eb6ad 57 Answer = snmp_var_new_integer(Var->name, Var->name_length,
58 store_mem_size >> 10,
59 ASN_INTEGER);
d0e0c8d2 60 break;
61 case SYSSTOR:
736eb6ad 62 Answer = snmp_var_new_integer(Var->name, Var->name_length,
63 store_swap_size,
64 ASN_INTEGER);
d0e0c8d2 65 break;
f763bb01 66 case SYS_UPTIME:
736eb6ad 67 Answer = snmp_var_new_integer(Var->name, Var->name_length,
68 tvSubDsec(squid_start, current_time) * 100,
69 SMI_TIMETICKS);
135171fe 70 break;
d0e0c8d2 71 default:
72 *ErrP = SNMP_ERR_NOSUCHNAME;
736eb6ad 73 break;
d0e0c8d2 74 }
d0e0c8d2 75 return Answer;
25c1b8b7 76}
77
d0e0c8d2 78variable_list *
6f47fbc7 79snmp_confFn(variable_list * Var, snint * ErrP)
25c1b8b7 80{
736eb6ad 81 variable_list *Answer = NULL;
d0e0c8d2 82 char *cp = NULL;
d0e0c8d2 83 debug(49, 5) ("snmp_confFn: Processing request with magic %d!\n", Var->name[8]);
d0e0c8d2 84 *ErrP = SNMP_ERR_NOERROR;
f763bb01 85 switch (Var->name[LEN_SQ_CONF]) {
571c3b88 86 case CONF_ADMIN:
736eb6ad 87 Answer = snmp_var_new(Var->name, Var->name_length);
d0e0c8d2 88 Answer->type = ASN_OCTET_STR;
89 Answer->val_len = strlen(Config.adminEmail);
90 Answer->val.string = (u_char *) xstrdup(Config.adminEmail);
91 break;
81d0c856 92 case CONF_VERSION:
736eb6ad 93 Answer = snmp_var_new(Var->name, Var->name_length);
6f47fbc7 94 Answer->type = ASN_OCTET_STR;
197408f6 95 Answer->val_len = strlen(appname);
96 Answer->val.string = (u_char *) xstrdup(appname);
6f47fbc7 97 break;
81d0c856 98 case CONF_VERSION_ID:
736eb6ad 99 Answer = snmp_var_new(Var->name, Var->name_length);
6f47fbc7 100 Answer->type = ASN_OCTET_STR;
736eb6ad 101 Answer->val_len = strlen(SQUID_VERSION);
102 Answer->val.string = (u_char *) xstrdup(SQUID_VERSION);
6f47fbc7 103 break;
571c3b88 104 case CONF_STORAGE:
f763bb01 105 switch (Var->name[LEN_SQ_CONF + 1]) {
571c3b88 106 case CONF_ST_MMAXSZ:
d20b1cd0 107 Answer = snmp_var_new_integer(Var->name, Var->name_length,
736eb6ad 108 (snint) Config.memMaxSize >> 20,
109 ASN_INTEGER);
d0e0c8d2 110 break;
d0e0c8d2 111 case CONF_ST_SWMAXSZ:
d20b1cd0 112 Answer = snmp_var_new_integer(Var->name, Var->name_length,
736eb6ad 113 (snint) Config.Swap.maxSize >> 10,
114 ASN_INTEGER);
d0e0c8d2 115 break;
116 case CONF_ST_SWHIWM:
d20b1cd0 117 Answer = snmp_var_new_integer(Var->name, Var->name_length,
736eb6ad 118 (snint) Config.Swap.highWaterMark,
119 ASN_INTEGER);
d0e0c8d2 120 break;
121 case CONF_ST_SWLOWM:
d20b1cd0 122 Answer = snmp_var_new_integer(Var->name, Var->name_length,
736eb6ad 123 (snint) Config.Swap.lowWaterMark,
124 ASN_INTEGER);
d0e0c8d2 125 break;
571c3b88 126 default:
d0e0c8d2 127 *ErrP = SNMP_ERR_NOSUCHNAME;
736eb6ad 128 break;
571c3b88 129 }
130 break;
81d0c856 131 case CONF_LOG_FAC:
736eb6ad 132 Answer = snmp_var_new(Var->name, Var->name_length);
d0e0c8d2 133 if (!(cp = Config.debugOptions))
134 cp = "None";
135 Answer->type = ASN_OCTET_STR;
136 Answer->val_len = strlen(cp);
137 Answer->val.string = (u_char *) xstrdup(cp);
138 break;
571c3b88 139 default:
d0e0c8d2 140 *ErrP = SNMP_ERR_NOSUCHNAME;
736eb6ad 141 break;
25c1b8b7 142 }
571c3b88 143 return Answer;
144}
25c1b8b7 145
d0e0c8d2 146variable_list *
6f47fbc7 147snmp_meshPtblFn(variable_list * Var, snint * ErrP)
571c3b88 148{
736eb6ad 149 variable_list *Answer = NULL;
81d0c856 150 struct in_addr *laddr;
d0e0c8d2 151 char *cp = NULL;
152 peer *p = NULL;
6f47fbc7 153 int cnt = 0;
f763bb01 154 debug(49, 5) ("snmp_meshPtblFn: peer %d requested!\n", Var->name[LEN_SQ_MESH + 3]);
d0e0c8d2 155 *ErrP = SNMP_ERR_NOERROR;
f763bb01 156 laddr = oid2addr(&Var->name[LEN_SQ_MESH + 3]);
6f47fbc7 157 for (p = Config.peers; p != NULL; p = p->next, cnt++)
158 if (p->in_addr.sin_addr.s_addr == laddr->s_addr)
159 break;
d0e0c8d2 160 if (p == NULL) {
161 *ErrP = SNMP_ERR_NOSUCHNAME;
736eb6ad 162 return NULL;
d0e0c8d2 163 }
f763bb01 164 switch (Var->name[LEN_SQ_MESH + 2]) {
81d0c856 165 case MESH_PTBL_NAME:
d0e0c8d2 166 cp = p->host;
736eb6ad 167 Answer = snmp_var_new(Var->name, Var->name_length);
d0e0c8d2 168 Answer->type = ASN_OCTET_STR;
169 Answer->val_len = strlen(cp);
170 Answer->val.string = (u_char *) xstrdup(cp);
171 break;
81d0c856 172 case MESH_PTBL_IP:
736eb6ad 173 Answer = snmp_var_new_integer(Var->name, Var->name_length,
174 (snint) p->in_addr.sin_addr.s_addr,
175 SMI_IPADDRESS);
d0e0c8d2 176 break;
81d0c856 177 case MESH_PTBL_HTTP:
736eb6ad 178 Answer = snmp_var_new_integer(Var->name, Var->name_length,
179 (snint) p->http_port,
180 ASN_INTEGER);
571c3b88 181 break;
81d0c856 182 case MESH_PTBL_ICP:
736eb6ad 183 Answer = snmp_var_new_integer(Var->name, Var->name_length,
184 (snint) p->icp.port,
185 ASN_INTEGER);
571c3b88 186 break;
81d0c856 187 case MESH_PTBL_TYPE:
736eb6ad 188 Answer = snmp_var_new_integer(Var->name, Var->name_length,
189 (snint) p->type,
190 ASN_INTEGER);
571c3b88 191 break;
81d0c856 192 case MESH_PTBL_STATE:
736eb6ad 193 Answer = snmp_var_new_integer(Var->name, Var->name_length,
194 (snint) neighborUp(p),
195 ASN_INTEGER);
571c3b88 196 break;
81d0c856 197 case MESH_PTBL_SENT:
736eb6ad 198 Answer = snmp_var_new_integer(Var->name, Var->name_length,
199 p->stats.pings_sent,
200 ASN_INTEGER);
6f47fbc7 201 break;
81d0c856 202 case MESH_PTBL_PACKED:
736eb6ad 203 Answer = snmp_var_new_integer(Var->name, Var->name_length,
204 p->stats.pings_acked,
205 ASN_INTEGER);
6f47fbc7 206 break;
81d0c856 207 case MESH_PTBL_FETCHES:
736eb6ad 208 Answer = snmp_var_new_integer(Var->name, Var->name_length,
209 p->stats.fetches,
210 SMI_COUNTER32);
6f47fbc7 211 break;
81d0c856 212 case MESH_PTBL_RTT:
736eb6ad 213 Answer = snmp_var_new_integer(Var->name, Var->name_length,
214 p->stats.rtt,
215 ASN_INTEGER);
6f47fbc7 216 break;
81d0c856 217 case MESH_PTBL_IGN:
736eb6ad 218 Answer = snmp_var_new_integer(Var->name, Var->name_length,
219 p->stats.ignored_replies,
220 SMI_COUNTER32);
6f47fbc7 221 break;
81d0c856 222 case MESH_PTBL_KEEPAL_S:
736eb6ad 223 Answer = snmp_var_new_integer(Var->name, Var->name_length,
224 p->stats.n_keepalives_sent,
225 SMI_COUNTER32);
6f47fbc7 226 break;
81d0c856 227 case MESH_PTBL_KEEPAL_R:
736eb6ad 228 Answer = snmp_var_new_integer(Var->name, Var->name_length,
229 p->stats.n_keepalives_recv,
230 SMI_COUNTER32);
6f47fbc7 231 break;
571c3b88 232 default:
d0e0c8d2 233 *ErrP = SNMP_ERR_NOSUCHNAME;
736eb6ad 234 break;
d0e0c8d2 235 }
236 return Answer;
571c3b88 237}
25c1b8b7 238
d0e0c8d2 239variable_list *
6f47fbc7 240snmp_prfSysFn(variable_list * Var, snint * ErrP)
571c3b88 241{
736eb6ad 242 variable_list *Answer = NULL;
d0e0c8d2 243 static struct rusage rusage;
f763bb01 244 debug(49, 5) ("snmp_prfSysFn: Processing request with magic %d!\n", Var->name[LEN_SQ_PRF + 1]);
d0e0c8d2 245 *ErrP = SNMP_ERR_NOERROR;
f763bb01 246 switch (Var->name[LEN_SQ_PRF + 1]) {
571c3b88 247 case PERF_SYS_PF:
d0e0c8d2 248 squid_getrusage(&rusage);
736eb6ad 249 Answer = snmp_var_new_integer(Var->name, Var->name_length,
250 rusage_pagefaults(&rusage),
251 SMI_COUNTER32);
d0e0c8d2 252 break;
571c3b88 253 case PERF_SYS_NUMR:
736eb6ad 254 Answer = snmp_var_new_integer(Var->name, Var->name_length,
255 IOStats.Http.reads,
256 SMI_COUNTER32);
d0e0c8d2 257 break;
571c3b88 258 case PERF_SYS_MEMUSAGE:
736eb6ad 259 Answer = snmp_var_new_integer(Var->name, Var->name_length,
260 (snint) memTotalAllocated() >> 10,
261 ASN_INTEGER);
d0e0c8d2 262 break;
eba4a24f 263 case PERF_SYS_CPUTIME:
d0e0c8d2 264 squid_getrusage(&rusage);
736eb6ad 265 Answer = snmp_var_new_integer(Var->name, Var->name_length,
266 (snint) rusage_cputime(&rusage),
267 ASN_INTEGER);
d0e0c8d2 268 break;
eba4a24f 269 case PERF_SYS_CPUUSAGE:
270 squid_getrusage(&rusage);
736eb6ad 271 Answer = snmp_var_new_integer(Var->name, Var->name_length,
272 (snint) dpercent(rusage_cputime(&rusage), tvSubDsec(squid_start, current_time)),
273 ASN_INTEGER);
eba4a24f 274 break;
571c3b88 275 case PERF_SYS_MAXRESSZ:
d0e0c8d2 276 squid_getrusage(&rusage);
736eb6ad 277 Answer = snmp_var_new_integer(Var->name, Var->name_length,
278 (snint) rusage_maxrss(&rusage),
279 ASN_INTEGER);
d0e0c8d2 280 break;
571c3b88 281 case PERF_SYS_CURLRUEXP:
a4b8110e 282 /* No global LRU info anymore */
736eb6ad 283 Answer = snmp_var_new_integer(Var->name, Var->name_length,
a4b8110e 284 0,
736eb6ad 285 SMI_TIMETICKS);
d0e0c8d2 286 break;
571c3b88 287 case PERF_SYS_CURUNLREQ:
736eb6ad 288 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 289 (snint) statCounter.unlink.requests,
736eb6ad 290 SMI_COUNTER32);
d0e0c8d2 291 break;
571c3b88 292 case PERF_SYS_CURUNUSED_FD:
736eb6ad 293 Answer = snmp_var_new_integer(Var->name, Var->name_length,
294 (snint) Squid_MaxFD - Number_FD,
295 SMI_GAUGE32);
d0e0c8d2 296 break;
571c3b88 297 case PERF_SYS_CURRESERVED_FD:
736eb6ad 298 Answer = snmp_var_new_integer(Var->name, Var->name_length,
299 (snint) Number_FD,
300 SMI_GAUGE32);
d0e0c8d2 301 break;
571c3b88 302 case PERF_SYS_NUMOBJCNT:
736eb6ad 303 Answer = snmp_var_new_integer(Var->name, Var->name_length,
304 (snint) memInUse(MEM_STOREENTRY),
305 SMI_COUNTER32);
d0e0c8d2 306 break;
571c3b88 307 default:
d0e0c8d2 308 *ErrP = SNMP_ERR_NOSUCHNAME;
736eb6ad 309 break;
d0e0c8d2 310 }
311 return Answer;
25c1b8b7 312}
313
d0e0c8d2 314variable_list *
6f47fbc7 315snmp_prfProtoFn(variable_list * Var, snint * ErrP)
25c1b8b7 316{
736eb6ad 317 variable_list *Answer = NULL;
2ac76861 318 static StatCounters *f = NULL;
319 static StatCounters *l = NULL;
451b07c5 320 double x;
321 int minutes;
f763bb01 322 debug(49, 5) ("snmp_prfProtoFn: Processing request with magic %d!\n", Var->name[LEN_SQ_PRF]);
d0e0c8d2 323 *ErrP = SNMP_ERR_NOERROR;
f763bb01 324 switch (Var->name[LEN_SQ_PRF + 1]) {
2ac76861 325 case PERF_PROTOSTAT_AGGR: /* cacheProtoAggregateStats */
f763bb01 326 switch (Var->name[LEN_SQ_PRF + 2]) {
d0e0c8d2 327 case PERF_PROTOSTAT_AGGR_HTTP_REQ:
736eb6ad 328 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 329 (snint) statCounter.client_http.requests,
736eb6ad 330 SMI_COUNTER32);
d0e0c8d2 331 break;
332 case PERF_PROTOSTAT_AGGR_HTTP_HITS:
736eb6ad 333 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 334 (snint) statCounter.client_http.hits,
736eb6ad 335 SMI_COUNTER32);
d0e0c8d2 336 break;
337 case PERF_PROTOSTAT_AGGR_HTTP_ERRORS:
736eb6ad 338 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 339 (snint) statCounter.client_http.errors,
736eb6ad 340 SMI_COUNTER32);
d0e0c8d2 341 break;
2ac76861 342 case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN:
736eb6ad 343 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 344 (snint) statCounter.client_http.kbytes_in.kb,
736eb6ad 345 SMI_COUNTER32);
2ac76861 346 break;
347 case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT:
736eb6ad 348 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 349 (snint) statCounter.client_http.kbytes_out.kb,
736eb6ad 350 SMI_COUNTER32);
2ac76861 351 break;
d0e0c8d2 352 case PERF_PROTOSTAT_AGGR_ICP_S:
736eb6ad 353 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 354 (snint) statCounter.icp.pkts_sent,
736eb6ad 355 SMI_COUNTER32);
d0e0c8d2 356 break;
357 case PERF_PROTOSTAT_AGGR_ICP_R:
736eb6ad 358 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 359 (snint) statCounter.icp.pkts_recv,
736eb6ad 360 SMI_COUNTER32);
d0e0c8d2 361 break;
362 case PERF_PROTOSTAT_AGGR_ICP_SKB:
736eb6ad 363 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 364 (snint) statCounter.icp.kbytes_sent.kb,
736eb6ad 365 SMI_COUNTER32);
d0e0c8d2 366 break;
367 case PERF_PROTOSTAT_AGGR_ICP_RKB:
736eb6ad 368 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 369 (snint) statCounter.icp.kbytes_recv.kb,
736eb6ad 370 SMI_COUNTER32);
2ac76861 371 break;
372 case PERF_PROTOSTAT_AGGR_REQ:
736eb6ad 373 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 374 (snint) statCounter.server.all.requests,
736eb6ad 375 SMI_INTEGER);
2ac76861 376 break;
377 case PERF_PROTOSTAT_AGGR_ERRORS:
736eb6ad 378 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 379 (snint) statCounter.server.all.errors,
736eb6ad 380 SMI_INTEGER);
2ac76861 381 break;
d0e0c8d2 382 case PERF_PROTOSTAT_AGGR_KBYTES_IN:
736eb6ad 383 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 384 (snint) statCounter.server.all.kbytes_in.kb,
736eb6ad 385 SMI_COUNTER32);
d0e0c8d2 386 break;
387 case PERF_PROTOSTAT_AGGR_KBYTES_OUT:
736eb6ad 388 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 389 (snint) statCounter.server.all.kbytes_out.kb,
736eb6ad 390 SMI_COUNTER32);
d0e0c8d2 391 break;
392 case PERF_PROTOSTAT_AGGR_CURSWAP:
736eb6ad 393 Answer = snmp_var_new_integer(Var->name, Var->name_length,
394 (snint) store_swap_size,
395 SMI_COUNTER32);
d0e0c8d2 396 break;
8a6218c6 397 case PERF_PROTOSTAT_AGGR_CLIENTS:
736eb6ad 398 Answer = snmp_var_new_integer(Var->name, Var->name_length,
83704487 399 (snint) statCounter.client_http.clients,
736eb6ad 400 SMI_COUNTER32);
8a6218c6 401 break;
d0e0c8d2 402 default:
d0e0c8d2 403 *ErrP = SNMP_ERR_NOSUCHNAME;
736eb6ad 404 break;
d0e0c8d2 405 }
2ac76861 406 return Answer;
451b07c5 407 case PERF_PROTOSTAT_MEDIAN:
ec603b25 408 if (Var->name_length == LEN_SQ_PRF + 5)
409 minutes = Var->name[LEN_SQ_PRF + 4];
410 else
411 break;
412 if ((minutes < 1) || (minutes > 60))
413 break;
2ac76861 414 f = snmpStatGet(0);
415 l = snmpStatGet(minutes);
2ac76861 416 debug(49, 8) ("median: min= %d, %d l= %x , f = %x\n", minutes,
f763bb01 417 Var->name[LEN_SQ_PRF + 3], l, f);
2ac76861 418 debug(49, 8) ("median: l= %x , f = %x\n", l, f);
f763bb01 419 switch (Var->name[LEN_SQ_PRF + 3]) {
2ac76861 420 case PERF_MEDIAN_TIME:
421 x = minutes;
422 break;
423 case PERF_MEDIAN_HTTP_ALL:
424 x = statHistDeltaMedian(&l->client_http.all_svc_time,
425 &f->client_http.all_svc_time);
426 break;
427 case PERF_MEDIAN_HTTP_MISS:
428 x = statHistDeltaMedian(&l->client_http.miss_svc_time,
429 &f->client_http.miss_svc_time);
430 break;
431 case PERF_MEDIAN_HTTP_NM:
432 x = statHistDeltaMedian(&l->client_http.nm_svc_time,
433 &f->client_http.nm_svc_time);
434 break;
435 case PERF_MEDIAN_HTTP_HIT:
436 x = statHistDeltaMedian(&l->client_http.hit_svc_time,
437 &f->client_http.hit_svc_time);
438 break;
439 case PERF_MEDIAN_ICP_QUERY:
440 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
441 break;
442 case PERF_MEDIAN_ICP_REPLY:
443 x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time);
444 break;
445 case PERF_MEDIAN_DNS:
446 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
447 break;
8a6218c6 448 case PERF_MEDIAN_RHR:
449 x = statRequestHitRatio(minutes);
450 break;
451 case PERF_MEDIAN_BHR:
452 x = statByteHitRatio(minutes);
453 break;
2ac76861 454 default:
2ac76861 455 *ErrP = SNMP_ERR_NOSUCHNAME;
736eb6ad 456 return NULL;
451b07c5 457 }
736eb6ad 458 return snmp_var_new_integer(Var->name, Var->name_length,
459 (snint) x,
460 SMI_INTEGER);
d0e0c8d2 461 }
451b07c5 462 *ErrP = SNMP_ERR_NOSUCHNAME;
736eb6ad 463 return NULL;
25c1b8b7 464}