Coverage Report

Created: 2026-09-14 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/getinfo.c
Line
Count
Source
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9
 *
10
 * This software is licensed as described in the file COPYING, which
11
 * you should have received as part of this distribution. The terms
12
 * are also available at https://curl.se/docs/copyright.html.
13
 *
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
 * copies of the Software, and permit persons to whom the Software is
16
 * furnished to do so, under the terms of the COPYING file.
17
 *
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
 * KIND, either express or implied.
20
 *
21
 * SPDX-License-Identifier: curl
22
 *
23
 ***************************************************************************/
24
#include "curl_setup.h"
25
26
#include "urldata.h"
27
#include "getinfo.h"
28
#include "cfilters.h"
29
#include "vtls/vtls.h"
30
#include "connect.h" /* Curl_getconnectinfo() */
31
#include "bufref.h"
32
#include "curlx/strparse.h"
33
34
/*
35
 * Initialize statistical and informational data.
36
 *
37
 * This function is called in curl_easy_reset, curl_easy_duphandle and at the
38
 * beginning of a perform session. It must reset the session-info variables,
39
 * in particular all variables in struct PureInfo.
40
 */
41
void Curl_initinfo(struct Curl_easy *data)
42
1.60M
{
43
1.60M
  struct Progress *pro = &data->progress;
44
1.60M
  struct PureInfo *info = &data->info;
45
46
1.60M
  memset(&pro->delta, 0, sizeof(pro->delta));
47
1.60M
  memset(&pro->total, 0, sizeof(pro->total));
48
1.60M
  pro->startransfer_added = FALSE;
49
50
1.60M
  info->httpcode = 0;
51
1.60M
  info->httpproxycode = 0;
52
1.60M
  info->httpversion = 0;
53
1.60M
  info->filetime = -1; /* -1 is an illegal time and thus means unknown */
54
1.60M
  info->timecond = FALSE;
55
56
1.60M
  info->header_size = 0;
57
1.60M
  info->request_size = 0;
58
1.60M
  info->proxyauthavail = 0;
59
1.60M
  info->httpauthavail = 0;
60
1.60M
  info->proxyauthpicked = 0;
61
1.60M
  info->httpauthpicked = 0;
62
1.60M
  info->numconnects = 0;
63
64
1.60M
  curlx_safefree(info->contenttype);
65
1.60M
  curlx_safefree(info->wouldredirect);
66
67
1.60M
  memset(&info->primary, 0, sizeof(info->primary));
68
1.60M
  info->retry_after = 0;
69
70
1.60M
  info->conn_scheme = 0;
71
1.60M
  info->conn_protocol = 0;
72
1.60M
  info->used_proxy = 0;
73
74
1.60M
#ifdef USE_SSL
75
1.60M
  Curl_ssl_free_certinfo(data);
76
1.60M
#endif
77
1.60M
}
78
79
static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
80
                             const char **param_charp)
81
237k
{
82
237k
  switch(info) {
83
236k
  case CURLINFO_EFFECTIVE_URL: {
84
236k
    const char *s = Curl_bufref_ptr(&data->state.url);
85
236k
    *param_charp = s ? s : "";
86
236k
  }
87
236k
    break;
88
37
  case CURLINFO_EFFECTIVE_METHOD: {
89
37
    const char *m = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
90
37
    if(!m) {
91
36
      if(data->set.opt_no_body)
92
2
        m = "HEAD";
93
34
#ifndef CURL_DISABLE_HTTP
94
34
      else {
95
34
        switch(data->state.httpreq) {
96
0
        case HTTPREQ_POST:
97
0
        case HTTPREQ_POST_FORM:
98
11
        case HTTPREQ_POST_MIME:
99
11
          m = "POST";
100
11
          break;
101
4
        case HTTPREQ_PUT:
102
4
          m = "PUT";
103
4
          break;
104
0
        default: /* this should never happen */
105
19
        case HTTPREQ_GET:
106
19
          m = "GET";
107
19
          break;
108
0
        case HTTPREQ_HEAD:
109
0
          m = "HEAD";
110
0
          break;
111
34
        }
112
34
      }
113
36
#endif
114
36
    }
115
37
    *param_charp = m;
116
37
  }
117
0
    break;
118
39
  case CURLINFO_CONTENT_TYPE:
119
39
    *param_charp = data->info.contenttype;
120
39
    break;
121
32
  case CURLINFO_PRIVATE:
122
32
    *param_charp = (const char *)data->set.private_data;
123
32
    break;
124
27
  case CURLINFO_FTP_ENTRY_PATH:
125
    /* Return the entrypath string from the most recent connection.
126
       This pointer was copied from the connectdata structure by FTP.
127
       The actual string may be freed by subsequent libcurl calls so
128
       it must be copied to a safer area before the next libcurl call.
129
       Callers must never free it themselves. */
130
27
    *param_charp = data->state.most_recent_ftp_entrypath;
131
27
    break;
132
32
  case CURLINFO_REDIRECT_URL:
133
    /* Return the URL this request would have been redirected to if that
134
       option had been enabled! */
135
32
    *param_charp = data->info.wouldredirect;
136
32
    break;
137
48
  case CURLINFO_REFERER:
138
    /* Return the referrer header for this request, or NULL if unset */
139
48
    *param_charp = Curl_bufref_ptr(&data->state.referer);
140
48
    break;
141
31
  case CURLINFO_PRIMARY_IP:
142
    /* Return the ip address of the most recent (primary) connection */
143
31
    *param_charp = data->info.primary.remote_ip;
144
31
    break;
145
42
  case CURLINFO_LOCAL_IP:
146
    /* Return the source/local ip address of the most recent (primary)
147
       connection */
148
42
    *param_charp = data->info.primary.local_ip;
149
42
    break;
150
32
  case CURLINFO_RTSP_SESSION_ID:
151
32
#ifndef CURL_DISABLE_RTSP
152
32
    *param_charp = CURL_EASY_STR(data, STRING_RTSP_SESSION_ID);
153
#else
154
    *param_charp = NULL;
155
#endif
156
32
    break;
157
34
  case CURLINFO_SCHEME:
158
34
    *param_charp = data->info.conn_scheme;
159
34
    break;
160
21
  case CURLINFO_CAPATH:
161
#ifdef CURL_CA_PATH
162
    *param_charp = CURL_CA_PATH;
163
#else
164
21
    *param_charp = NULL;
165
21
#endif
166
21
    break;
167
21
  case CURLINFO_CAINFO:
168
#ifdef CURL_CA_BUNDLE
169
    *param_charp = CURL_CA_BUNDLE;
170
#else
171
21
    *param_charp = NULL;
172
21
#endif
173
21
    break;
174
0
  default:
175
0
    return CURLE_UNKNOWN_OPTION;
176
237k
  }
177
178
237k
  return CURLE_OK;
179
237k
}
180
181
static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
182
                             long *param_longp)
183
497k
{
184
497k
  curl_socket_t sockfd;
185
186
497k
  union {
187
497k
    unsigned long *to_ulong;
188
497k
    long          *to_long;
189
497k
  } lptr;
190
191
497k
#ifdef DEBUGBUILD
192
497k
  const char *envstr;
193
194
  /* use another variable for this to allow different values */
195
497k
  switch(info) {
196
29
  case CURLINFO_LOCAL_PORT:
197
29
    envstr = getenv("CURL_TIME");
198
29
    if(envstr) {
199
0
      curl_off_t val;
200
0
      curlx_str_number(&envstr, &val, TIME_T_MAX);
201
0
      *param_longp = (long)val;
202
0
      return CURLE_OK;
203
0
    }
204
29
    break;
205
30
  case CURLINFO_HEADER_SIZE:
206
64
  case CURLINFO_REQUEST_SIZE:
207
64
    envstr = getenv("CURL_DEBUG_SIZE");
208
64
    if(envstr) {
209
0
      curl_off_t val;
210
0
      curlx_str_number(&envstr, &val, LONG_MAX);
211
0
      *param_longp = (long)val;
212
0
      return CURLE_OK;
213
0
    }
214
64
    break;
215
496k
  default:
216
496k
    break;
217
497k
  }
218
497k
#endif
219
220
497k
  switch(info) {
221
236k
  case CURLINFO_RESPONSE_CODE:
222
236k
    *param_longp = data->info.httpcode;
223
236k
    break;
224
45
  case CURLINFO_HTTP_CONNECTCODE:
225
45
    *param_longp = data->info.httpproxycode;
226
45
    break;
227
29
  case CURLINFO_FILETIME:
228
29
    if(data->info.filetime > LONG_MAX)
229
0
      *param_longp = LONG_MAX;
230
29
#if !defined(MSDOS) && !defined(__AMIGA__)
231
29
    else if(data->info.filetime < LONG_MIN)
232
0
      *param_longp = LONG_MIN;
233
29
#endif
234
29
    else
235
29
      *param_longp = (long)data->info.filetime;
236
29
    break;
237
30
  case CURLINFO_HEADER_SIZE:
238
30
    *param_longp = (long)data->info.header_size;
239
30
    break;
240
34
  case CURLINFO_REQUEST_SIZE:
241
34
    *param_longp = (long)data->info.request_size;
242
34
    break;
243
259k
  case CURLINFO_SSL_VERIFYRESULT:
244
259k
    *param_longp = data->set.ssl.certverifyresult;
245
259k
    break;
246
28
  case CURLINFO_PROXY_SSL_VERIFYRESULT:
247
28
#ifndef CURL_DISABLE_PROXY
248
28
    *param_longp = data->set.proxy_ssl.certverifyresult;
249
#else
250
    *param_longp = 0;
251
#endif
252
28
    break;
253
24
  case CURLINFO_REDIRECT_COUNT:
254
24
    *param_longp = data->state.followlocation;
255
24
    break;
256
32
  case CURLINFO_HTTPAUTH_AVAIL:
257
32
    lptr.to_long = param_longp;
258
32
    *lptr.to_ulong = data->info.httpauthavail;
259
32
    break;
260
18
  case CURLINFO_PROXYAUTH_AVAIL:
261
18
    lptr.to_long = param_longp;
262
18
    *lptr.to_ulong = data->info.proxyauthavail;
263
18
    break;
264
11
  case CURLINFO_HTTPAUTH_USED:
265
11
    lptr.to_long = param_longp;
266
11
    *lptr.to_ulong = data->info.httpauthpicked;
267
11
    break;
268
11
  case CURLINFO_PROXYAUTH_USED:
269
11
    lptr.to_long = param_longp;
270
11
    *lptr.to_ulong = data->info.proxyauthpicked;
271
11
    break;
272
27
  case CURLINFO_OS_ERRNO:
273
27
    *param_longp = data->state.os_errno;
274
27
    break;
275
25
  case CURLINFO_NUM_CONNECTS:
276
#if SIZEOF_LONG < SIZEOF_CURL_OFF_T
277
    if(data->info.numconnects > LONG_MAX)
278
      *param_longp = LONG_MAX;
279
    else
280
#endif
281
25
      *param_longp = (long)data->info.numconnects;
282
25
    break;
283
0
  case CURLINFO_LASTSOCKET:
284
0
    sockfd = Curl_getconnectinfo(data, NULL);
285
286
    /* note: this is not a good conversion for systems with 64-bit sockets and
287
       32-bit longs */
288
0
    if(sockfd != CURL_SOCKET_BAD)
289
0
      *param_longp = (long)sockfd;
290
0
    else
291
      /* this interface is documented to return -1 in case of badness, which
292
         may not be the same as the CURL_SOCKET_BAD value */
293
0
      *param_longp = -1;
294
0
    break;
295
42
  case CURLINFO_PRIMARY_PORT:
296
    /* Return the (remote) port of the most recent (primary) connection */
297
42
    if(CUR_IP_QUAD_HAS_PORTS(&data->info.primary))
298
27
      *param_longp = data->info.primary.remote_port;
299
15
    else
300
15
      *param_longp = -1;
301
42
    break;
302
29
  case CURLINFO_LOCAL_PORT:
303
    /* Return the local port of the most recent (primary) connection */
304
29
    if(CUR_IP_QUAD_HAS_PORTS(&data->info.primary))
305
22
      *param_longp = data->info.primary.local_port;
306
7
    else
307
7
      *param_longp = -1;
308
29
    break;
309
18
  case CURLINFO_PROXY_ERROR:
310
18
    *param_longp = (long)data->info.pxcode;
311
18
    break;
312
33
  case CURLINFO_CONDITION_UNMET:
313
33
    if(data->info.httpcode == 304)
314
1
      *param_longp = 1L;
315
32
    else
316
      /* return if the condition prevented the document to get transferred */
317
32
      *param_longp = data->info.timecond ? 1L : 0L;
318
33
    break;
319
0
#ifndef CURL_DISABLE_RTSP
320
31
  case CURLINFO_RTSP_CLIENT_CSEQ:
321
31
    *param_longp = data->state.rtsp_next_client_CSeq;
322
31
    break;
323
23
  case CURLINFO_RTSP_SERVER_CSEQ:
324
23
    *param_longp = data->state.rtsp_next_server_CSeq;
325
23
    break;
326
35
  case CURLINFO_RTSP_CSEQ_RECV:
327
35
    *param_longp = data->state.rtsp_CSeq_recv;
328
35
    break;
329
#else
330
  case CURLINFO_RTSP_CLIENT_CSEQ:
331
  case CURLINFO_RTSP_SERVER_CSEQ:
332
  case CURLINFO_RTSP_CSEQ_RECV:
333
    *param_longp = 0;
334
    break;
335
#endif
336
43
  case CURLINFO_HTTP_VERSION:
337
43
    switch(data->info.httpversion) {
338
2
    case 10:
339
2
      *param_longp = CURL_HTTP_VERSION_1_0;
340
2
      break;
341
6
    case 11:
342
6
      *param_longp = CURL_HTTP_VERSION_1_1;
343
6
      break;
344
1
    case 20:
345
1
      *param_longp = CURL_HTTP_VERSION_2_0;
346
1
      break;
347
0
    case 30:
348
0
      *param_longp = CURL_HTTP_VERSION_3;
349
0
      break;
350
34
    default:
351
34
      *param_longp = CURL_HTTP_VERSION_NONE;
352
34
      break;
353
43
    }
354
43
    break;
355
43
  case CURLINFO_PROTOCOL:
356
0
    *param_longp = (long)data->info.conn_protocol;
357
0
    break;
358
12
  case CURLINFO_USED_PROXY:
359
12
    *param_longp =
360
#ifdef CURL_DISABLE_PROXY
361
      0
362
#else
363
12
      data->info.used_proxy
364
12
#endif
365
12
      ;
366
12
    break;
367
0
  default:
368
0
    return CURLE_UNKNOWN_OPTION;
369
497k
  }
370
371
497k
  return CURLE_OK;
372
497k
}
373
374
237k
#define DOUBLE_SECS(x) ((double)(x) / 1000000)
375
376
static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
377
                             curl_off_t *param_offt)
378
496k
{
379
496k
#ifdef DEBUGBUILD
380
496k
  const char *envstr;
381
496k
  switch(info) {
382
19
  case CURLINFO_TOTAL_TIME_T:
383
28
  case CURLINFO_NAMELOOKUP_TIME_T:
384
45
  case CURLINFO_CONNECT_TIME_T:
385
259k
  case CURLINFO_APPCONNECT_TIME_T:
386
259k
  case CURLINFO_PRETRANSFER_TIME_T:
387
259k
  case CURLINFO_POSTTRANSFER_TIME_T:
388
259k
  case CURLINFO_QUEUE_TIME_T:
389
259k
  case CURLINFO_STARTTRANSFER_TIME_T:
390
259k
  case CURLINFO_REDIRECT_TIME_T:
391
259k
  case CURLINFO_SPEED_DOWNLOAD_T:
392
259k
  case CURLINFO_SPEED_UPLOAD_T:
393
259k
    envstr = getenv("CURL_TIME");
394
259k
    if(envstr) {
395
0
      curl_off_t val;
396
0
      curlx_str_number(&envstr, &val, CURL_OFF_T_MAX);
397
0
      *param_offt = (curl_off_t)val;
398
0
      return CURLE_OK;
399
0
    }
400
259k
    break;
401
259k
  default:
402
237k
    break;
403
496k
  }
404
496k
#endif
405
496k
  switch(info) {
406
20
  case CURLINFO_FILETIME_T:
407
20
    *param_offt = (curl_off_t)data->info.filetime;
408
20
    break;
409
14
  case CURLINFO_SIZE_DELIVERED:
410
14
    *param_offt = data->progress.deliver;
411
14
    break;
412
46
  case CURLINFO_SIZE_UPLOAD_T:
413
46
    *param_offt = data->progress.ul.cur_size;
414
46
    break;
415
236k
  case CURLINFO_SIZE_DOWNLOAD_T:
416
236k
    *param_offt = data->progress.dl.cur_size;
417
236k
    break;
418
18
  case CURLINFO_SPEED_DOWNLOAD_T:
419
18
    *param_offt = data->progress.dl.speed;
420
18
    break;
421
26
  case CURLINFO_SPEED_UPLOAD_T:
422
26
    *param_offt = data->progress.ul.speed;
423
26
    break;
424
20
  case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T:
425
20
    *param_offt = data->progress.dl_size_known ?
426
18
      data->progress.dl.total_size : -1;
427
20
    break;
428
18
  case CURLINFO_CONTENT_LENGTH_UPLOAD_T:
429
18
    *param_offt = data->progress.ul_size_known ?
430
13
      data->progress.ul.total_size : -1;
431
18
    break;
432
19
   case CURLINFO_TOTAL_TIME_T:
433
19
    *param_offt = data->progress.total.spent_us;
434
19
    break;
435
9
  case CURLINFO_NAMELOOKUP_TIME_T:
436
9
    *param_offt = data->progress.total.nslookup_us;
437
9
    break;
438
17
  case CURLINFO_CONNECT_TIME_T:
439
17
    *param_offt = data->progress.total.connect_us;
440
17
    break;
441
259k
  case CURLINFO_APPCONNECT_TIME_T:
442
259k
    *param_offt = data->progress.total.appconnect_us;
443
259k
    break;
444
20
  case CURLINFO_PRETRANSFER_TIME_T:
445
20
    *param_offt = data->progress.total.pretransfer_us;
446
20
    break;
447
14
  case CURLINFO_POSTTRANSFER_TIME_T:
448
14
    *param_offt = data->progress.total.posttransfer_us;
449
14
    break;
450
29
  case CURLINFO_STARTTRANSFER_TIME_T:
451
29
    *param_offt = data->progress.total.starttransfer_us;
452
29
    break;
453
21
  case CURLINFO_QUEUE_TIME_T:
454
21
    *param_offt = data->progress.total.queued_us;
455
21
    break;
456
19
  case CURLINFO_REDIRECT_TIME_T:
457
19
    *param_offt = data->progress.delta.startredirect_us;
458
19
    break;
459
17
  case CURLINFO_RETRY_AFTER:
460
17
    *param_offt = data->info.retry_after;
461
17
    break;
462
19
  case CURLINFO_XFER_ID:
463
19
    *param_offt = data->id;
464
19
    break;
465
14
  case CURLINFO_CONN_ID:
466
14
    *param_offt = data->state.lastconnect_id;
467
14
    break;
468
9
  case CURLINFO_EARLYDATA_SENT_T:
469
9
    *param_offt = data->progress.earlydata_sent;
470
9
    break;
471
0
  default:
472
0
    return CURLE_UNKNOWN_OPTION;
473
496k
  }
474
475
496k
  return CURLE_OK;
476
496k
}
477
478
static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
479
                               double *param_doublep)
480
237k
{
481
237k
#ifdef DEBUGBUILD
482
237k
  const char *envstr;
483
484
237k
  switch(info) {
485
236k
  case CURLINFO_TOTAL_TIME:
486
236k
  case CURLINFO_NAMELOOKUP_TIME:
487
236k
  case CURLINFO_CONNECT_TIME:
488
236k
  case CURLINFO_APPCONNECT_TIME:
489
236k
  case CURLINFO_PRETRANSFER_TIME:
490
236k
  case CURLINFO_STARTTRANSFER_TIME:
491
237k
  case CURLINFO_REDIRECT_TIME:
492
237k
  case CURLINFO_SPEED_DOWNLOAD:
493
237k
  case CURLINFO_SPEED_UPLOAD:
494
237k
    envstr = getenv("CURL_TIME");
495
237k
    if(envstr) {
496
0
      curl_off_t val;
497
0
      curlx_str_number(&envstr, &val, CURL_OFF_T_MAX);
498
0
      *param_doublep = (double)val;
499
0
      return CURLE_OK;
500
0
    }
501
237k
    break;
502
237k
  default:
503
0
    break;
504
237k
  }
505
237k
#endif
506
237k
  switch(info) {
507
236k
  case CURLINFO_TOTAL_TIME:
508
236k
    *param_doublep = DOUBLE_SECS(data->progress.total.spent_us);
509
236k
    break;
510
31
  case CURLINFO_NAMELOOKUP_TIME:
511
31
    *param_doublep = DOUBLE_SECS(data->progress.total.nslookup_us);
512
31
    break;
513
23
  case CURLINFO_CONNECT_TIME:
514
23
    *param_doublep = DOUBLE_SECS(data->progress.total.connect_us);
515
23
    break;
516
39
  case CURLINFO_APPCONNECT_TIME:
517
39
    *param_doublep = DOUBLE_SECS(data->progress.total.appconnect_us);
518
39
    break;
519
29
  case CURLINFO_PRETRANSFER_TIME:
520
29
    *param_doublep = DOUBLE_SECS(data->progress.total.pretransfer_us);
521
29
    break;
522
16
  case CURLINFO_STARTTRANSFER_TIME:
523
16
    *param_doublep = DOUBLE_SECS(data->progress.total.starttransfer_us);
524
16
    break;
525
0
  case CURLINFO_SIZE_UPLOAD:
526
0
    *param_doublep = (double)data->progress.ul.cur_size;
527
0
    break;
528
0
  case CURLINFO_SIZE_DOWNLOAD:
529
0
    *param_doublep = (double)data->progress.dl.cur_size;
530
0
    break;
531
0
  case CURLINFO_SPEED_DOWNLOAD:
532
0
    *param_doublep = (double)data->progress.dl.speed;
533
0
    break;
534
0
  case CURLINFO_SPEED_UPLOAD:
535
0
    *param_doublep = (double)data->progress.ul.speed;
536
0
    break;
537
0
  case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
538
0
    *param_doublep = data->progress.dl_size_known ?
539
0
      (double)data->progress.dl.total_size : -1;
540
0
    break;
541
0
  case CURLINFO_CONTENT_LENGTH_UPLOAD:
542
0
    *param_doublep = data->progress.ul_size_known ?
543
0
      (double)data->progress.ul.total_size : -1;
544
0
    break;
545
25
  case CURLINFO_REDIRECT_TIME:
546
25
    *param_doublep = DOUBLE_SECS(data->progress.delta.startredirect_us);
547
25
    break;
548
549
0
  default:
550
0
    return CURLE_UNKNOWN_OPTION;
551
237k
  }
552
553
237k
  return CURLE_OK;
554
237k
}
555
556
static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
557
                              struct curl_slist **param_slistp)
558
756k
{
559
756k
  union {
560
756k
    struct curl_certinfo *to_certinfo;
561
756k
    struct curl_slist    *to_slist;
562
756k
  } ptr;
563
564
756k
  switch(info) {
565
30
  case CURLINFO_SSL_ENGINES:
566
30
    *param_slistp = Curl_ssl_engines_list(data);
567
30
    break;
568
48
  case CURLINFO_COOKIELIST:
569
48
    *param_slistp = Curl_cookie_list(data);
570
48
    break;
571
496k
  case CURLINFO_CERTINFO:
572
    /* Return the a pointer to the certinfo struct. Not really an slist
573
       pointer but we can pretend it is here */
574
496k
    ptr.to_certinfo = &data->info.certs;
575
496k
    *param_slistp = ptr.to_slist;
576
496k
    break;
577
0
  case CURLINFO_TLS_SESSION:
578
259k
  case CURLINFO_TLS_SSL_PTR: {
579
259k
    int query = (info == CURLINFO_TLS_SSL_PTR) ?
580
259k
      CF_QUERY_SSL_INFO : CF_QUERY_SSL_CTX_INFO;
581
259k
    struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
582
259k
      param_slistp;
583
259k
    struct curl_tlssessioninfo *tsi = &data->tsi;
584
585
    /* we are exposing a pointer to internal memory with unknown
586
     * lifetime here. */
587
259k
    *tsip = tsi;
588
259k
    if(!Curl_conn_get_ssl_info(data, data->conn, FIRSTSOCKET, query, tsi)) {
589
194k
      tsi->backend = Curl_ssl_backend();
590
194k
      tsi->internals = NULL;
591
194k
    }
592
259k
  }
593
259k
    break;
594
0
  default:
595
0
    return CURLE_UNKNOWN_OPTION;
596
756k
  }
597
598
756k
  return CURLE_OK;
599
756k
}
600
601
static CURLcode getinfo_socket(struct Curl_easy *data, CURLINFO info,
602
                               curl_socket_t *param_socketp)
603
236k
{
604
236k
  switch(info) {
605
236k
  case CURLINFO_ACTIVESOCKET:
606
236k
    *param_socketp = Curl_getconnectinfo(data, NULL);
607
236k
    break;
608
0
  default:
609
0
    return CURLE_UNKNOWN_OPTION;
610
236k
  }
611
612
236k
  return CURLE_OK;
613
236k
}
614
615
CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
616
2.46M
{
617
2.46M
  va_list arg;
618
2.46M
  long *param_longp = NULL;
619
2.46M
  double *param_doublep = NULL;
620
2.46M
  curl_off_t *param_offt = NULL;
621
2.46M
  const char **param_charp = NULL;
622
2.46M
  struct curl_slist **param_slistp = NULL;
623
2.46M
  curl_socket_t *param_socketp = NULL;
624
2.46M
  int type;
625
2.46M
  CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
626
627
2.46M
  if(!data)
628
0
    return CURLE_BAD_FUNCTION_ARGUMENT;
629
630
2.46M
  va_start(arg, info);
631
632
2.46M
  type = CURLINFO_TYPEMASK & (int)info;
633
2.46M
  switch(type) {
634
237k
  case CURLINFO_STRING:
635
237k
    param_charp = va_arg(arg, const char **);
636
237k
    if(param_charp)
637
237k
      result = getinfo_char(data, info, param_charp);
638
237k
    break;
639
497k
  case CURLINFO_LONG:
640
497k
    param_longp = va_arg(arg, long *);
641
497k
    if(param_longp)
642
497k
      result = getinfo_long(data, info, param_longp);
643
497k
    break;
644
237k
  case CURLINFO_DOUBLE:
645
237k
    param_doublep = va_arg(arg, double *);
646
237k
    if(param_doublep)
647
237k
      result = getinfo_double(data, info, param_doublep);
648
237k
    break;
649
496k
  case CURLINFO_OFF_T:
650
496k
    param_offt = va_arg(arg, curl_off_t *);
651
496k
    if(param_offt)
652
496k
      result = getinfo_offt(data, info, param_offt);
653
496k
    break;
654
756k
  case CURLINFO_SLIST:
655
756k
    param_slistp = va_arg(arg, struct curl_slist **);
656
756k
    if(param_slistp)
657
756k
      result = getinfo_slist(data, info, param_slistp);
658
756k
    break;
659
236k
  case CURLINFO_SOCKET:
660
236k
    param_socketp = va_arg(arg, curl_socket_t *);
661
236k
    if(param_socketp)
662
236k
      result = getinfo_socket(data, info, param_socketp);
663
236k
    break;
664
57
  default:
665
57
    result = CURLE_UNKNOWN_OPTION;
666
57
    break;
667
2.46M
  }
668
669
2.46M
  va_end(arg);
670
671
2.46M
  return result;
672
2.46M
}