From 12e62aea0d7912f545e876e2b7c9bca8acb8daef Mon Sep 17 00:00:00 2001 From: CIFuzz Date: Thu, 22 Feb 2024 00:54:57 +0000 Subject: [PATCH] Coverage upload --- coverage/latest/logs/test_libfuzzer.log | 6 +++--- .../linux/src/openiked-portable/compat/arc4random.c.html | 2 +- .../src/openiked-portable/compat/arc4random_linux.h.html | 2 +- .../src/openiked-portable/compat/arc4random_uniform.c.html | 2 +- .../src/openiked-portable/compat/chacha_private.h.html | 2 +- .../linux/src/openiked-portable/compat/freezero.c.html | 2 +- .../src/openiked-portable/compat/getdtablecount.c.html | 2 +- .../linux/src/openiked-portable/compat/getrtable.c.html | 2 +- .../linux/src/openiked-portable/compat/imsg-buffer.c.html | 2 +- .../report/linux/src/openiked-portable/compat/imsg.c.html | 2 +- .../report/linux/src/openiked-portable/compat/imsg.h.html | 2 +- .../src/openiked-portable/compat/openbsd-compat.h.html | 2 +- .../linux/src/openiked-portable/compat/recallocarray.c.html | 2 +- .../linux/src/openiked-portable/compat/setproctitle.c.html | 2 +- .../linux/src/openiked-portable/compat/strlcat.c.html | 2 +- .../linux/src/openiked-portable/compat/strlcpy.c.html | 2 +- .../linux/src/openiked-portable/compat/strtonum.c.html | 2 +- .../linux/src/openiked-portable/compat/sys/queue.h.html | 2 +- .../linux/src/openiked-portable/compat/sys/tree.h.html | 2 +- .../report/linux/src/openiked-portable/compat/vis.c.html | 2 +- .../report/linux/src/openiked-portable/compat/vis.h.html | 2 +- .../report/linux/src/openiked-portable/iked/iked.h.html | 2 +- .../report/linux/src/openiked-portable/iked/ikev2.h.html | 2 +- .../linux/src/openiked-portable/iked/ikev2_pld.c.html | 2 +- .../linux/src/openiked-portable/iked/imsg_util.c.html | 2 +- .../report/linux/src/openiked-portable/iked/log.c.html | 2 +- .../report/linux/src/openiked-portable/iked/types.h.html | 2 +- .../report/linux/src/openiked-portable/iked/util.c.html | 2 +- .../regress/parser-libfuzzer/common.c.html | 2 +- .../regress/parser-libfuzzer/test_parser_fuzz.c.html | 2 +- .../linux/src/openiked-portable/compat/arc4random.c.html | 2 +- .../src/openiked-portable/compat/arc4random_linux.h.html | 2 +- .../src/openiked-portable/compat/arc4random_uniform.c.html | 2 +- .../src/openiked-portable/compat/chacha_private.h.html | 2 +- .../linux/src/openiked-portable/compat/freezero.c.html | 2 +- .../src/openiked-portable/compat/getdtablecount.c.html | 2 +- .../linux/src/openiked-portable/compat/getrtable.c.html | 2 +- .../linux/src/openiked-portable/compat/imsg-buffer.c.html | 2 +- .../linux/src/openiked-portable/compat/imsg.c.html | 2 +- .../linux/src/openiked-portable/compat/imsg.h.html | 2 +- .../src/openiked-portable/compat/openbsd-compat.h.html | 2 +- .../linux/src/openiked-portable/compat/recallocarray.c.html | 2 +- .../linux/src/openiked-portable/compat/setproctitle.c.html | 2 +- .../linux/src/openiked-portable/compat/strlcat.c.html | 2 +- .../linux/src/openiked-portable/compat/strlcpy.c.html | 2 +- .../linux/src/openiked-portable/compat/strtonum.c.html | 2 +- .../linux/src/openiked-portable/compat/sys/queue.h.html | 2 +- .../linux/src/openiked-portable/compat/sys/tree.h.html | 2 +- .../linux/src/openiked-portable/compat/vis.c.html | 2 +- .../linux/src/openiked-portable/compat/vis.h.html | 2 +- .../linux/src/openiked-portable/iked/iked.h.html | 2 +- .../linux/src/openiked-portable/iked/ikev2.h.html | 2 +- .../linux/src/openiked-portable/iked/ikev2_pld.c.html | 2 +- .../linux/src/openiked-portable/iked/imsg_util.c.html | 2 +- .../linux/src/openiked-portable/iked/log.c.html | 2 +- .../linux/src/openiked-portable/iked/types.h.html | 2 +- .../linux/src/openiked-portable/iked/util.c.html | 2 +- .../regress/parser-libfuzzer/common.c.html | 2 +- .../regress/parser-libfuzzer/test_parser_fuzz.c.html | 2 +- 59 files changed, 61 insertions(+), 61 deletions(-) diff --git a/coverage/latest/logs/test_libfuzzer.log b/coverage/latest/logs/test_libfuzzer.log index 81a30eb18..be1a02752 100644 --- a/coverage/latest/logs/test_libfuzzer.log +++ b/coverage/latest/logs/test_libfuzzer.log @@ -1,11 +1,11 @@ INFO: Running with entropic power schedule (0xFF, 100). -INFO: Seed: 3387255153 +INFO: Seed: 3830544422 MERGE-OUTER: 15483 files, 0 in the initial corpus, 0 processed earlier MERGE-OUTER: attempt 1 INFO: Running with entropic power schedule (0xFF, 100). -INFO: Seed: 3387335462 +INFO: Seed: 3830623444 INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 1048576 bytes -MERGE-INNER: using the control file '/tmp/libFuzzerTemp.Merge116.txt' +MERGE-INNER: using the control file '/tmp/libFuzzerTemp.Merge114.txt' MERGE-INNER: 15483 total files; 0 processed earlier; will process 15483 files now #1 pulse exec/s: 0 rss: 31Mb #2 pulse exec/s: 0 rss: 31Mb diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/arc4random.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/arc4random.c.html index 12e153292..000178800 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/arc4random.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/arc4random.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/arc4random.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random.c,v 1.58 2022/07/31 13:41:45 tb Exp $  */
2
3
/*
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6
 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7
 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
/*
23
 * ChaCha based random number generator for OpenBSD.
24
 */
25
26
#include <fcntl.h>
27
#include <limits.h>
28
#include <signal.h>
29
#include <stdint.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <unistd.h>
33
#include <sys/types.h>
34
#include <sys/time.h>
35
36
#define KEYSTREAM_ONLY
37
#include "chacha_private.h"
38
39
0
#define minimum(a, b) ((a) < (b) ? (a) : (b))
40
41
#if defined(__GNUC__) || defined(_MSC_VER)
42
#define inline __inline
43
#else       /* __GNUC__ || _MSC_VER */
44
#define inline
45
#endif        /* !__GNUC__ && !_MSC_VER */
46
47
0
#define KEYSZ 32
48
0
#define IVSZ  8
49
#define BLOCKSZ 64
50
#define RSBUFSZ (16*BLOCKSZ)
51
52
0
#define REKEY_BASE  (1024*1024) /* NB. should be a power of 2 */
53
54
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
55
static struct _rs {
56
  size_t    rs_have;  /* valid bytes at end of rs_buf */
57
  size_t    rs_count; /* bytes till reseed */
58
} *rs;
59
60
/* Maybe be preserved in fork children, if _rs_allocate() decides. */
61
static struct _rsx {
62
  chacha_ctx  rs_chacha;  /* chacha context for random keystream */
63
  u_char    rs_buf[RSBUFSZ];  /* keystream blocks */
64
} *rsx;
65
66
static inline int _rs_allocate(struct _rs **, struct _rsx **);
67
static inline void _rs_forkdetect(void);
68
#include "arc4random.h"
69
70
static inline void _rs_rekey(u_char *dat, size_t datlen);
71
72
static inline void
73
_rs_init(u_char *buf, size_t n)
74
0
{
75
0
  if (n < KEYSZ + IVSZ)
76
0
    return;
77
78
0
  if (rs == NULL) {
79
0
    if (_rs_allocate(&rs, &rsx) == -1)
80
0
      _exit(1);
81
0
  }
82
83
0
  chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8);
84
0
  chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
85
0
}
86
87
static void
88
_rs_stir(void)
89
0
{
90
0
  u_char rnd[KEYSZ + IVSZ];
91
0
  uint32_t rekey_fuzz = 0;
92
93
0
  if (getentropy(rnd, sizeof rnd) == -1)
94
0
    _getentropy_fail();
95
96
0
  if (!rs)
97
0
    _rs_init(rnd, sizeof(rnd));
98
0
  else
99
0
    _rs_rekey(rnd, sizeof(rnd));
100
0
  explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
101
102
  /* invalidate rs_buf */
103
0
  rs->rs_have = 0;
104
0
  memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
105
106
  /* rekey interval should not be predictable */
107
0
  chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz,
108
0
      (uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz));
109
0
  rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE);
110
0
}
111
112
static inline void
113
_rs_stir_if_needed(size_t len)
114
0
{
115
0
  _rs_forkdetect();
116
0
  if (!rs || rs->rs_count <= len)
117
0
    _rs_stir();
118
0
  if (rs->rs_count <= len)
119
0
    rs->rs_count = 0;
120
0
  else
121
0
    rs->rs_count -= len;
122
0
}
123
124
static inline void
125
_rs_rekey(u_char *dat, size_t datlen)
126
0
{
127
#ifndef KEYSTREAM_ONLY
128
  memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
129
#endif
130
  /* fill rs_buf with the keystream */
131
0
  chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
132
0
      rsx->rs_buf, sizeof(rsx->rs_buf));
133
  /* mix in optional user provided data */
134
0
  if (dat) {
135
0
    size_t i, m;
136
137
0
    m = minimum(datlen, KEYSZ + IVSZ);
138
0
    for (i = 0; i < m; i++)
139
0
      rsx->rs_buf[i] ^= dat[i];
140
0
  }
141
  /* immediately reinit for backtracking resistance */
142
0
  _rs_init(rsx->rs_buf, KEYSZ + IVSZ);
143
0
  memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
144
0
  rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
145
0
}
146
147
static inline void
148
_rs_random_buf(void *_buf, size_t n)
149
0
{
150
0
  u_char *buf = (u_char *)_buf;
151
0
  u_char *keystream;
152
0
  size_t m;
153
154
0
  _rs_stir_if_needed(n);
155
0
  while (n > 0) {
156
0
    if (rs->rs_have > 0) {
157
0
      m = minimum(n, rs->rs_have);
158
0
      keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
159
0
          - rs->rs_have;
160
0
      memcpy(buf, keystream, m);
161
0
      memset(keystream, 0, m);
162
0
      buf += m;
163
0
      n -= m;
164
0
      rs->rs_have -= m;
165
0
    }
166
0
    if (rs->rs_have == 0)
167
0
      _rs_rekey(NULL, 0);
168
0
  }
169
0
}
170
171
static inline void
172
_rs_random_u32(uint32_t *val)
173
0
{
174
0
  u_char *keystream;
175
176
0
  _rs_stir_if_needed(sizeof(*val));
177
0
  if (rs->rs_have < sizeof(*val))
178
0
    _rs_rekey(NULL, 0);
179
0
  keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
180
0
  memcpy(val, keystream, sizeof(*val));
181
0
  memset(keystream, 0, sizeof(*val));
182
0
  rs->rs_have -= sizeof(*val);
183
0
}
184
185
uint32_t
186
arc4random(void)
187
0
{
188
0
  uint32_t val;
189
190
0
  _ARC4_LOCK();
191
0
  _rs_random_u32(&val);
192
0
  _ARC4_UNLOCK();
193
0
  return val;
194
0
}
195
196
void
197
arc4random_buf(void *buf, size_t n)
198
0
{
199
0
  _ARC4_LOCK();
200
0
  _rs_random_buf(buf, n);
201
0
  _ARC4_UNLOCK();
202
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/arc4random.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random.c,v 1.58 2022/07/31 13:41:45 tb Exp $  */
2
3
/*
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6
 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7
 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
/*
23
 * ChaCha based random number generator for OpenBSD.
24
 */
25
26
#include <fcntl.h>
27
#include <limits.h>
28
#include <signal.h>
29
#include <stdint.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <unistd.h>
33
#include <sys/types.h>
34
#include <sys/time.h>
35
36
#define KEYSTREAM_ONLY
37
#include "chacha_private.h"
38
39
0
#define minimum(a, b) ((a) < (b) ? (a) : (b))
40
41
#if defined(__GNUC__) || defined(_MSC_VER)
42
#define inline __inline
43
#else       /* __GNUC__ || _MSC_VER */
44
#define inline
45
#endif        /* !__GNUC__ && !_MSC_VER */
46
47
0
#define KEYSZ 32
48
0
#define IVSZ  8
49
#define BLOCKSZ 64
50
#define RSBUFSZ (16*BLOCKSZ)
51
52
0
#define REKEY_BASE  (1024*1024) /* NB. should be a power of 2 */
53
54
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
55
static struct _rs {
56
  size_t    rs_have;  /* valid bytes at end of rs_buf */
57
  size_t    rs_count; /* bytes till reseed */
58
} *rs;
59
60
/* Maybe be preserved in fork children, if _rs_allocate() decides. */
61
static struct _rsx {
62
  chacha_ctx  rs_chacha;  /* chacha context for random keystream */
63
  u_char    rs_buf[RSBUFSZ];  /* keystream blocks */
64
} *rsx;
65
66
static inline int _rs_allocate(struct _rs **, struct _rsx **);
67
static inline void _rs_forkdetect(void);
68
#include "arc4random.h"
69
70
static inline void _rs_rekey(u_char *dat, size_t datlen);
71
72
static inline void
73
_rs_init(u_char *buf, size_t n)
74
0
{
75
0
  if (n < KEYSZ + IVSZ)
76
0
    return;
77
78
0
  if (rs == NULL) {
79
0
    if (_rs_allocate(&rs, &rsx) == -1)
80
0
      _exit(1);
81
0
  }
82
83
0
  chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8);
84
0
  chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
85
0
}
86
87
static void
88
_rs_stir(void)
89
0
{
90
0
  u_char rnd[KEYSZ + IVSZ];
91
0
  uint32_t rekey_fuzz = 0;
92
93
0
  if (getentropy(rnd, sizeof rnd) == -1)
94
0
    _getentropy_fail();
95
96
0
  if (!rs)
97
0
    _rs_init(rnd, sizeof(rnd));
98
0
  else
99
0
    _rs_rekey(rnd, sizeof(rnd));
100
0
  explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
101
102
  /* invalidate rs_buf */
103
0
  rs->rs_have = 0;
104
0
  memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
105
106
  /* rekey interval should not be predictable */
107
0
  chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz,
108
0
      (uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz));
109
0
  rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE);
110
0
}
111
112
static inline void
113
_rs_stir_if_needed(size_t len)
114
0
{
115
0
  _rs_forkdetect();
116
0
  if (!rs || rs->rs_count <= len)
117
0
    _rs_stir();
118
0
  if (rs->rs_count <= len)
119
0
    rs->rs_count = 0;
120
0
  else
121
0
    rs->rs_count -= len;
122
0
}
123
124
static inline void
125
_rs_rekey(u_char *dat, size_t datlen)
126
0
{
127
#ifndef KEYSTREAM_ONLY
128
  memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
129
#endif
130
  /* fill rs_buf with the keystream */
131
0
  chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
132
0
      rsx->rs_buf, sizeof(rsx->rs_buf));
133
  /* mix in optional user provided data */
134
0
  if (dat) {
135
0
    size_t i, m;
136
137
0
    m = minimum(datlen, KEYSZ + IVSZ);
138
0
    for (i = 0; i < m; i++)
139
0
      rsx->rs_buf[i] ^= dat[i];
140
0
  }
141
  /* immediately reinit for backtracking resistance */
142
0
  _rs_init(rsx->rs_buf, KEYSZ + IVSZ);
143
0
  memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
144
0
  rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
145
0
}
146
147
static inline void
148
_rs_random_buf(void *_buf, size_t n)
149
0
{
150
0
  u_char *buf = (u_char *)_buf;
151
0
  u_char *keystream;
152
0
  size_t m;
153
154
0
  _rs_stir_if_needed(n);
155
0
  while (n > 0) {
156
0
    if (rs->rs_have > 0) {
157
0
      m = minimum(n, rs->rs_have);
158
0
      keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
159
0
          - rs->rs_have;
160
0
      memcpy(buf, keystream, m);
161
0
      memset(keystream, 0, m);
162
0
      buf += m;
163
0
      n -= m;
164
0
      rs->rs_have -= m;
165
0
    }
166
0
    if (rs->rs_have == 0)
167
0
      _rs_rekey(NULL, 0);
168
0
  }
169
0
}
170
171
static inline void
172
_rs_random_u32(uint32_t *val)
173
0
{
174
0
  u_char *keystream;
175
176
0
  _rs_stir_if_needed(sizeof(*val));
177
0
  if (rs->rs_have < sizeof(*val))
178
0
    _rs_rekey(NULL, 0);
179
0
  keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
180
0
  memcpy(val, keystream, sizeof(*val));
181
0
  memset(keystream, 0, sizeof(*val));
182
0
  rs->rs_have -= sizeof(*val);
183
0
}
184
185
uint32_t
186
arc4random(void)
187
0
{
188
0
  uint32_t val;
189
190
0
  _ARC4_LOCK();
191
0
  _rs_random_u32(&val);
192
0
  _ARC4_UNLOCK();
193
0
  return val;
194
0
}
195
196
void
197
arc4random_buf(void *buf, size_t n)
198
0
{
199
0
  _ARC4_LOCK();
200
0
  _rs_random_buf(buf, n);
201
0
  _ARC4_UNLOCK();
202
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/arc4random_linux.h.html b/coverage/latest/report/linux/src/openiked-portable/compat/arc4random_linux.h.html index d89659768..7b79195bc 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/arc4random_linux.h.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/arc4random_linux.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/arc4random_linux.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random_linux.h,v 1.12 2019/07/11 10:37:28 inoguchi Exp $  */
2
3
/*
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6
 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7
 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
/*
23
 * Stub functions for portability.
24
 */
25
26
#include <sys/mman.h>
27
28
#include <pthread.h>
29
#include <signal.h>
30
31
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
32
0
#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
33
0
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
34
35
#if defined(__GLIBC__) && !(defined(__UCLIBC__) && !defined(__ARCH_USE_MMU__))
36
extern void *__dso_handle;
37
extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
38
0
#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
39
#else
40
#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
41
#endif
42
43
static inline void
44
_getentropy_fail(void)
45
0
{
46
0
  raise(SIGKILL);
47
0
}
48
49
static volatile sig_atomic_t _rs_forked;
50
51
static inline void
52
_rs_forkhandler(void)
53
0
{
54
0
  _rs_forked = 1;
55
0
}
56
57
static inline void
58
_rs_forkdetect(void)
59
0
{
60
0
  static pid_t _rs_pid = 0;
61
0
  pid_t pid = getpid();
62
63
        /* XXX unusual calls to clone() can bypass checks */
64
0
  if (_rs_pid == 0 || _rs_pid == 1 || _rs_pid != pid || _rs_forked) {
65
0
    _rs_pid = pid;
66
0
    _rs_forked = 0;
67
0
    if (rs)
68
0
      memset(rs, 0, sizeof(*rs));
69
0
  }
70
0
}
71
72
static inline int
73
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
74
0
{
75
0
  if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
76
0
      MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
77
0
    return (-1);
78
79
0
  if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
80
0
      MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
81
0
    munmap(*rsp, sizeof(**rsp));
82
0
    *rsp = NULL;
83
0
    return (-1);
84
0
  }
85
86
0
  _ARC4_ATFORK(_rs_forkhandler);
87
0
  return (0);
88
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/arc4random_linux.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random_linux.h,v 1.12 2019/07/11 10:37:28 inoguchi Exp $  */
2
3
/*
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6
 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7
 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
/*
23
 * Stub functions for portability.
24
 */
25
26
#include <sys/mman.h>
27
28
#include <pthread.h>
29
#include <signal.h>
30
31
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
32
0
#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
33
0
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
34
35
#if defined(__GLIBC__) && !(defined(__UCLIBC__) && !defined(__ARCH_USE_MMU__))
36
extern void *__dso_handle;
37
extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
38
0
#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
39
#else
40
#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
41
#endif
42
43
static inline void
44
_getentropy_fail(void)
45
0
{
46
0
  raise(SIGKILL);
47
0
}
48
49
static volatile sig_atomic_t _rs_forked;
50
51
static inline void
52
_rs_forkhandler(void)
53
0
{
54
0
  _rs_forked = 1;
55
0
}
56
57
static inline void
58
_rs_forkdetect(void)
59
0
{
60
0
  static pid_t _rs_pid = 0;
61
0
  pid_t pid = getpid();
62
63
        /* XXX unusual calls to clone() can bypass checks */
64
0
  if (_rs_pid == 0 || _rs_pid == 1 || _rs_pid != pid || _rs_forked) {
65
0
    _rs_pid = pid;
66
0
    _rs_forked = 0;
67
0
    if (rs)
68
0
      memset(rs, 0, sizeof(*rs));
69
0
  }
70
0
}
71
72
static inline int
73
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
74
0
{
75
0
  if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
76
0
      MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
77
0
    return (-1);
78
79
0
  if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
80
0
      MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
81
0
    munmap(*rsp, sizeof(**rsp));
82
0
    *rsp = NULL;
83
0
    return (-1);
84
0
  }
85
86
0
  _ARC4_ATFORK(_rs_forkhandler);
87
0
  return (0);
88
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/arc4random_uniform.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/arc4random_uniform.c.html index bfe36d3ef..b80f0d07f 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/arc4random_uniform.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/arc4random_uniform.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/arc4random_uniform.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random_uniform.c,v 1.3 2019/01/20 02:59:07 bcook Exp $  */
2
3
/*
4
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <stdint.h>
20
#include <stdlib.h>
21
22
/*
23
 * Calculate a uniformly distributed random number less than upper_bound
24
 * avoiding "modulo bias".
25
 *
26
 * Uniformity is achieved by generating new random numbers until the one
27
 * returned is outside the range [0, 2**32 % upper_bound).  This
28
 * guarantees the selected random number will be inside
29
 * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
30
 * after reduction modulo upper_bound.
31
 */
32
uint32_t
33
arc4random_uniform(uint32_t upper_bound)
34
0
{
35
0
  uint32_t r, min;
36
37
0
  if (upper_bound < 2)
38
0
    return 0;
39
40
  /* 2**32 % x == (2**32 - x) % x */
41
0
  min = -upper_bound % upper_bound;
42
43
  /*
44
   * This could theoretically loop forever but each retry has
45
   * p > 0.5 (worst case, usually far better) of selecting a
46
   * number inside the range we need, so it should rarely need
47
   * to re-roll.
48
   */
49
0
  for (;;) {
50
0
    r = arc4random();
51
0
    if (r >= min)
52
0
      break;
53
0
  }
54
55
0
  return r % upper_bound;
56
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/arc4random_uniform.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random_uniform.c,v 1.3 2019/01/20 02:59:07 bcook Exp $  */
2
3
/*
4
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <stdint.h>
20
#include <stdlib.h>
21
22
/*
23
 * Calculate a uniformly distributed random number less than upper_bound
24
 * avoiding "modulo bias".
25
 *
26
 * Uniformity is achieved by generating new random numbers until the one
27
 * returned is outside the range [0, 2**32 % upper_bound).  This
28
 * guarantees the selected random number will be inside
29
 * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
30
 * after reduction modulo upper_bound.
31
 */
32
uint32_t
33
arc4random_uniform(uint32_t upper_bound)
34
0
{
35
0
  uint32_t r, min;
36
37
0
  if (upper_bound < 2)
38
0
    return 0;
39
40
  /* 2**32 % x == (2**32 - x) % x */
41
0
  min = -upper_bound % upper_bound;
42
43
  /*
44
   * This could theoretically loop forever but each retry has
45
   * p > 0.5 (worst case, usually far better) of selecting a
46
   * number inside the range we need, so it should rarely need
47
   * to re-roll.
48
   */
49
0
  for (;;) {
50
0
    r = arc4random();
51
0
    if (r >= min)
52
0
      break;
53
0
  }
54
55
0
  return r % upper_bound;
56
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/chacha_private.h.html b/coverage/latest/report/linux/src/openiked-portable/compat/chacha_private.h.html index 6787f5543..3ee8489c4 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/chacha_private.h.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/chacha_private.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/chacha_private.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
chacha-merged.c version 20080118
3
D. J. Bernstein
4
Public domain.
5
*/
6
7
/* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */
8
9
typedef unsigned char u8;
10
typedef unsigned int u32;
11
12
typedef struct
13
{
14
  u32 input[16]; /* could be compressed */
15
} chacha_ctx;
16
17
0
#define U8C(v) (v##U)
18
0
#define U32C(v) (v##U)
19
20
0
#define U8V(v) ((u8)(v) & U8C(0xFF))
21
0
#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
22
23
#define ROTL32(v, n) \
24
0
  (U32V((v) << (n)) | ((v) >> (32 - (n))))
25
26
#define U8TO32_LITTLE(p) \
27
0
  (((u32)((p)[0])      ) | \
28
0
   ((u32)((p)[1]) <<  8) | \
29
0
   ((u32)((p)[2]) << 16) | \
30
0
   ((u32)((p)[3]) << 24))
31
32
#define U32TO8_LITTLE(p, v) \
33
0
  do { \
34
0
    (p)[0] = U8V((v)      ); \
35
0
    (p)[1] = U8V((v) >>  8); \
36
0
    (p)[2] = U8V((v) >> 16); \
37
0
    (p)[3] = U8V((v) >> 24); \
38
0
  } while (0)
39
40
0
#define ROTATE(v,c) (ROTL32(v,c))
41
#define XOR(v,w) ((v) ^ (w))
42
0
#define PLUS(v,w) (U32V((v) + (w)))
43
0
#define PLUSONE(v) (PLUS((v),1))
44
45
#define QUARTERROUND(a,b,c,d) \
46
0
  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
47
0
  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
48
0
  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
49
0
  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
50
51
static const char sigma[16] = "expand 32-byte k";
52
static const char tau[16] = "expand 16-byte k";
53
54
static void
55
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
56
0
{
57
0
  const char *constants;
58
59
0
  x->input[4] = U8TO32_LITTLE(k + 0);
60
0
  x->input[5] = U8TO32_LITTLE(k + 4);
61
0
  x->input[6] = U8TO32_LITTLE(k + 8);
62
0
  x->input[7] = U8TO32_LITTLE(k + 12);
63
0
  if (kbits == 256) { /* recommended */
64
0
    k += 16;
65
0
    constants = sigma;
66
0
  } else { /* kbits == 128 */
67
0
    constants = tau;
68
0
  }
69
0
  x->input[8] = U8TO32_LITTLE(k + 0);
70
0
  x->input[9] = U8TO32_LITTLE(k + 4);
71
0
  x->input[10] = U8TO32_LITTLE(k + 8);
72
0
  x->input[11] = U8TO32_LITTLE(k + 12);
73
0
  x->input[0] = U8TO32_LITTLE(constants + 0);
74
0
  x->input[1] = U8TO32_LITTLE(constants + 4);
75
0
  x->input[2] = U8TO32_LITTLE(constants + 8);
76
0
  x->input[3] = U8TO32_LITTLE(constants + 12);
77
0
}
78
79
static void
80
chacha_ivsetup(chacha_ctx *x,const u8 *iv)
81
0
{
82
0
  x->input[12] = 0;
83
0
  x->input[13] = 0;
84
0
  x->input[14] = U8TO32_LITTLE(iv + 0);
85
0
  x->input[15] = U8TO32_LITTLE(iv + 4);
86
0
}
87
88
static void
89
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
90
0
{
91
0
  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
92
0
  u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
93
0
  u8 *ctarget = NULL;
94
0
  u8 tmp[64];
95
0
  u_int i;
96
97
0
  if (!bytes) return;
98
99
0
  j0 = x->input[0];
100
0
  j1 = x->input[1];
101
0
  j2 = x->input[2];
102
0
  j3 = x->input[3];
103
0
  j4 = x->input[4];
104
0
  j5 = x->input[5];
105
0
  j6 = x->input[6];
106
0
  j7 = x->input[7];
107
0
  j8 = x->input[8];
108
0
  j9 = x->input[9];
109
0
  j10 = x->input[10];
110
0
  j11 = x->input[11];
111
0
  j12 = x->input[12];
112
0
  j13 = x->input[13];
113
0
  j14 = x->input[14];
114
0
  j15 = x->input[15];
115
116
0
  for (;;) {
117
0
    if (bytes < 64) {
118
0
      for (i = 0;i < bytes;++i) tmp[i] = m[i];
119
0
      m = tmp;
120
0
      ctarget = c;
121
0
      c = tmp;
122
0
    }
123
0
    x0 = j0;
124
0
    x1 = j1;
125
0
    x2 = j2;
126
0
    x3 = j3;
127
0
    x4 = j4;
128
0
    x5 = j5;
129
0
    x6 = j6;
130
0
    x7 = j7;
131
0
    x8 = j8;
132
0
    x9 = j9;
133
0
    x10 = j10;
134
0
    x11 = j11;
135
0
    x12 = j12;
136
0
    x13 = j13;
137
0
    x14 = j14;
138
0
    x15 = j15;
139
0
    for (i = 20;i > 0;i -= 2) {
140
0
      QUARTERROUND( x0, x4, x8,x12)
141
0
      QUARTERROUND( x1, x5, x9,x13)
142
0
      QUARTERROUND( x2, x6,x10,x14)
143
0
      QUARTERROUND( x3, x7,x11,x15)
144
0
      QUARTERROUND( x0, x5,x10,x15)
145
0
      QUARTERROUND( x1, x6,x11,x12)
146
0
      QUARTERROUND( x2, x7, x8,x13)
147
0
      QUARTERROUND( x3, x4, x9,x14)
148
0
    }
149
0
    x0 = PLUS(x0,j0);
150
0
    x1 = PLUS(x1,j1);
151
0
    x2 = PLUS(x2,j2);
152
0
    x3 = PLUS(x3,j3);
153
0
    x4 = PLUS(x4,j4);
154
0
    x5 = PLUS(x5,j5);
155
0
    x6 = PLUS(x6,j6);
156
0
    x7 = PLUS(x7,j7);
157
0
    x8 = PLUS(x8,j8);
158
0
    x9 = PLUS(x9,j9);
159
0
    x10 = PLUS(x10,j10);
160
0
    x11 = PLUS(x11,j11);
161
0
    x12 = PLUS(x12,j12);
162
0
    x13 = PLUS(x13,j13);
163
0
    x14 = PLUS(x14,j14);
164
0
    x15 = PLUS(x15,j15);
165
166
#ifndef KEYSTREAM_ONLY
167
    x0 = XOR(x0,U8TO32_LITTLE(m + 0));
168
    x1 = XOR(x1,U8TO32_LITTLE(m + 4));
169
    x2 = XOR(x2,U8TO32_LITTLE(m + 8));
170
    x3 = XOR(x3,U8TO32_LITTLE(m + 12));
171
    x4 = XOR(x4,U8TO32_LITTLE(m + 16));
172
    x5 = XOR(x5,U8TO32_LITTLE(m + 20));
173
    x6 = XOR(x6,U8TO32_LITTLE(m + 24));
174
    x7 = XOR(x7,U8TO32_LITTLE(m + 28));
175
    x8 = XOR(x8,U8TO32_LITTLE(m + 32));
176
    x9 = XOR(x9,U8TO32_LITTLE(m + 36));
177
    x10 = XOR(x10,U8TO32_LITTLE(m + 40));
178
    x11 = XOR(x11,U8TO32_LITTLE(m + 44));
179
    x12 = XOR(x12,U8TO32_LITTLE(m + 48));
180
    x13 = XOR(x13,U8TO32_LITTLE(m + 52));
181
    x14 = XOR(x14,U8TO32_LITTLE(m + 56));
182
    x15 = XOR(x15,U8TO32_LITTLE(m + 60));
183
#endif
184
185
0
    j12 = PLUSONE(j12);
186
0
    if (!j12) {
187
0
      j13 = PLUSONE(j13);
188
      /* stopping at 2^70 bytes per nonce is user's responsibility */
189
0
    }
190
191
0
    U32TO8_LITTLE(c + 0,x0);
192
0
    U32TO8_LITTLE(c + 4,x1);
193
0
    U32TO8_LITTLE(c + 8,x2);
194
0
    U32TO8_LITTLE(c + 12,x3);
195
0
    U32TO8_LITTLE(c + 16,x4);
196
0
    U32TO8_LITTLE(c + 20,x5);
197
0
    U32TO8_LITTLE(c + 24,x6);
198
0
    U32TO8_LITTLE(c + 28,x7);
199
0
    U32TO8_LITTLE(c + 32,x8);
200
0
    U32TO8_LITTLE(c + 36,x9);
201
0
    U32TO8_LITTLE(c + 40,x10);
202
0
    U32TO8_LITTLE(c + 44,x11);
203
0
    U32TO8_LITTLE(c + 48,x12);
204
0
    U32TO8_LITTLE(c + 52,x13);
205
0
    U32TO8_LITTLE(c + 56,x14);
206
0
    U32TO8_LITTLE(c + 60,x15);
207
208
0
    if (bytes <= 64) {
209
0
      if (bytes < 64) {
210
0
        for (i = 0;i < bytes;++i) ctarget[i] = c[i];
211
0
      }
212
0
      x->input[12] = j12;
213
0
      x->input[13] = j13;
214
0
      return;
215
0
    }
216
0
    bytes -= 64;
217
0
    c += 64;
218
#ifndef KEYSTREAM_ONLY
219
    m += 64;
220
#endif
221
0
  }
222
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/chacha_private.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
chacha-merged.c version 20080118
3
D. J. Bernstein
4
Public domain.
5
*/
6
7
/* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */
8
9
typedef unsigned char u8;
10
typedef unsigned int u32;
11
12
typedef struct
13
{
14
  u32 input[16]; /* could be compressed */
15
} chacha_ctx;
16
17
0
#define U8C(v) (v##U)
18
0
#define U32C(v) (v##U)
19
20
0
#define U8V(v) ((u8)(v) & U8C(0xFF))
21
0
#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
22
23
#define ROTL32(v, n) \
24
0
  (U32V((v) << (n)) | ((v) >> (32 - (n))))
25
26
#define U8TO32_LITTLE(p) \
27
0
  (((u32)((p)[0])      ) | \
28
0
   ((u32)((p)[1]) <<  8) | \
29
0
   ((u32)((p)[2]) << 16) | \
30
0
   ((u32)((p)[3]) << 24))
31
32
#define U32TO8_LITTLE(p, v) \
33
0
  do { \
34
0
    (p)[0] = U8V((v)      ); \
35
0
    (p)[1] = U8V((v) >>  8); \
36
0
    (p)[2] = U8V((v) >> 16); \
37
0
    (p)[3] = U8V((v) >> 24); \
38
0
  } while (0)
39
40
0
#define ROTATE(v,c) (ROTL32(v,c))
41
#define XOR(v,w) ((v) ^ (w))
42
0
#define PLUS(v,w) (U32V((v) + (w)))
43
0
#define PLUSONE(v) (PLUS((v),1))
44
45
#define QUARTERROUND(a,b,c,d) \
46
0
  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
47
0
  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
48
0
  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
49
0
  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
50
51
static const char sigma[16] = "expand 32-byte k";
52
static const char tau[16] = "expand 16-byte k";
53
54
static void
55
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
56
0
{
57
0
  const char *constants;
58
59
0
  x->input[4] = U8TO32_LITTLE(k + 0);
60
0
  x->input[5] = U8TO32_LITTLE(k + 4);
61
0
  x->input[6] = U8TO32_LITTLE(k + 8);
62
0
  x->input[7] = U8TO32_LITTLE(k + 12);
63
0
  if (kbits == 256) { /* recommended */
64
0
    k += 16;
65
0
    constants = sigma;
66
0
  } else { /* kbits == 128 */
67
0
    constants = tau;
68
0
  }
69
0
  x->input[8] = U8TO32_LITTLE(k + 0);
70
0
  x->input[9] = U8TO32_LITTLE(k + 4);
71
0
  x->input[10] = U8TO32_LITTLE(k + 8);
72
0
  x->input[11] = U8TO32_LITTLE(k + 12);
73
0
  x->input[0] = U8TO32_LITTLE(constants + 0);
74
0
  x->input[1] = U8TO32_LITTLE(constants + 4);
75
0
  x->input[2] = U8TO32_LITTLE(constants + 8);
76
0
  x->input[3] = U8TO32_LITTLE(constants + 12);
77
0
}
78
79
static void
80
chacha_ivsetup(chacha_ctx *x,const u8 *iv)
81
0
{
82
0
  x->input[12] = 0;
83
0
  x->input[13] = 0;
84
0
  x->input[14] = U8TO32_LITTLE(iv + 0);
85
0
  x->input[15] = U8TO32_LITTLE(iv + 4);
86
0
}
87
88
static void
89
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
90
0
{
91
0
  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
92
0
  u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
93
0
  u8 *ctarget = NULL;
94
0
  u8 tmp[64];
95
0
  u_int i;
96
97
0
  if (!bytes) return;
98
99
0
  j0 = x->input[0];
100
0
  j1 = x->input[1];
101
0
  j2 = x->input[2];
102
0
  j3 = x->input[3];
103
0
  j4 = x->input[4];
104
0
  j5 = x->input[5];
105
0
  j6 = x->input[6];
106
0
  j7 = x->input[7];
107
0
  j8 = x->input[8];
108
0
  j9 = x->input[9];
109
0
  j10 = x->input[10];
110
0
  j11 = x->input[11];
111
0
  j12 = x->input[12];
112
0
  j13 = x->input[13];
113
0
  j14 = x->input[14];
114
0
  j15 = x->input[15];
115
116
0
  for (;;) {
117
0
    if (bytes < 64) {
118
0
      for (i = 0;i < bytes;++i) tmp[i] = m[i];
119
0
      m = tmp;
120
0
      ctarget = c;
121
0
      c = tmp;
122
0
    }
123
0
    x0 = j0;
124
0
    x1 = j1;
125
0
    x2 = j2;
126
0
    x3 = j3;
127
0
    x4 = j4;
128
0
    x5 = j5;
129
0
    x6 = j6;
130
0
    x7 = j7;
131
0
    x8 = j8;
132
0
    x9 = j9;
133
0
    x10 = j10;
134
0
    x11 = j11;
135
0
    x12 = j12;
136
0
    x13 = j13;
137
0
    x14 = j14;
138
0
    x15 = j15;
139
0
    for (i = 20;i > 0;i -= 2) {
140
0
      QUARTERROUND( x0, x4, x8,x12)
141
0
      QUARTERROUND( x1, x5, x9,x13)
142
0
      QUARTERROUND( x2, x6,x10,x14)
143
0
      QUARTERROUND( x3, x7,x11,x15)
144
0
      QUARTERROUND( x0, x5,x10,x15)
145
0
      QUARTERROUND( x1, x6,x11,x12)
146
0
      QUARTERROUND( x2, x7, x8,x13)
147
0
      QUARTERROUND( x3, x4, x9,x14)
148
0
    }
149
0
    x0 = PLUS(x0,j0);
150
0
    x1 = PLUS(x1,j1);
151
0
    x2 = PLUS(x2,j2);
152
0
    x3 = PLUS(x3,j3);
153
0
    x4 = PLUS(x4,j4);
154
0
    x5 = PLUS(x5,j5);
155
0
    x6 = PLUS(x6,j6);
156
0
    x7 = PLUS(x7,j7);
157
0
    x8 = PLUS(x8,j8);
158
0
    x9 = PLUS(x9,j9);
159
0
    x10 = PLUS(x10,j10);
160
0
    x11 = PLUS(x11,j11);
161
0
    x12 = PLUS(x12,j12);
162
0
    x13 = PLUS(x13,j13);
163
0
    x14 = PLUS(x14,j14);
164
0
    x15 = PLUS(x15,j15);
165
166
#ifndef KEYSTREAM_ONLY
167
    x0 = XOR(x0,U8TO32_LITTLE(m + 0));
168
    x1 = XOR(x1,U8TO32_LITTLE(m + 4));
169
    x2 = XOR(x2,U8TO32_LITTLE(m + 8));
170
    x3 = XOR(x3,U8TO32_LITTLE(m + 12));
171
    x4 = XOR(x4,U8TO32_LITTLE(m + 16));
172
    x5 = XOR(x5,U8TO32_LITTLE(m + 20));
173
    x6 = XOR(x6,U8TO32_LITTLE(m + 24));
174
    x7 = XOR(x7,U8TO32_LITTLE(m + 28));
175
    x8 = XOR(x8,U8TO32_LITTLE(m + 32));
176
    x9 = XOR(x9,U8TO32_LITTLE(m + 36));
177
    x10 = XOR(x10,U8TO32_LITTLE(m + 40));
178
    x11 = XOR(x11,U8TO32_LITTLE(m + 44));
179
    x12 = XOR(x12,U8TO32_LITTLE(m + 48));
180
    x13 = XOR(x13,U8TO32_LITTLE(m + 52));
181
    x14 = XOR(x14,U8TO32_LITTLE(m + 56));
182
    x15 = XOR(x15,U8TO32_LITTLE(m + 60));
183
#endif
184
185
0
    j12 = PLUSONE(j12);
186
0
    if (!j12) {
187
0
      j13 = PLUSONE(j13);
188
      /* stopping at 2^70 bytes per nonce is user's responsibility */
189
0
    }
190
191
0
    U32TO8_LITTLE(c + 0,x0);
192
0
    U32TO8_LITTLE(c + 4,x1);
193
0
    U32TO8_LITTLE(c + 8,x2);
194
0
    U32TO8_LITTLE(c + 12,x3);
195
0
    U32TO8_LITTLE(c + 16,x4);
196
0
    U32TO8_LITTLE(c + 20,x5);
197
0
    U32TO8_LITTLE(c + 24,x6);
198
0
    U32TO8_LITTLE(c + 28,x7);
199
0
    U32TO8_LITTLE(c + 32,x8);
200
0
    U32TO8_LITTLE(c + 36,x9);
201
0
    U32TO8_LITTLE(c + 40,x10);
202
0
    U32TO8_LITTLE(c + 44,x11);
203
0
    U32TO8_LITTLE(c + 48,x12);
204
0
    U32TO8_LITTLE(c + 52,x13);
205
0
    U32TO8_LITTLE(c + 56,x14);
206
0
    U32TO8_LITTLE(c + 60,x15);
207
208
0
    if (bytes <= 64) {
209
0
      if (bytes < 64) {
210
0
        for (i = 0;i < bytes;++i) ctarget[i] = c[i];
211
0
      }
212
0
      x->input[12] = j12;
213
0
      x->input[13] = j13;
214
0
      return;
215
0
    }
216
0
    bytes -= 64;
217
0
    c += 64;
218
#ifndef KEYSTREAM_ONLY
219
    m += 64;
220
#endif
221
0
  }
222
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/freezero.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/freezero.c.html index 9b3eaa0e6..c34235f02 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/freezero.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/freezero.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/freezero.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
3
 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
4
 * Copyright (c) 2008 Damien Miller <djm@openbsd.org>
5
 * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <string.h>
21
#include <stdlib.h>
22
23
void
24
freezero(void *ptr, size_t sz)
25
25.5k
{
26
  /* This is legal. */
27
25.5k
  if (ptr == NULL)
28
1.74k
    return;
29
30
23.8k
  explicit_bzero(ptr, sz);
31
23.8k
  free(ptr);
32
23.8k
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/freezero.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
3
 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
4
 * Copyright (c) 2008 Damien Miller <djm@openbsd.org>
5
 * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <string.h>
21
#include <stdlib.h>
22
23
void
24
freezero(void *ptr, size_t sz)
25
25.5k
{
26
  /* This is legal. */
27
25.5k
  if (ptr == NULL)
28
1.74k
    return;
29
30
23.8k
  explicit_bzero(ptr, sz);
31
23.8k
  free(ptr);
32
23.8k
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/getdtablecount.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/getdtablecount.c.html index 656d3dac5..cf61b3bdb 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/getdtablecount.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/getdtablecount.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/getdtablecount.c
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#include "openbsd-compat.h"
4
5
#if !defined(HAVE_GETDTABLECOUNT)
6
int
7
getdtablecount(void)
8
0
{
9
0
  return (0);
10
0
}
11
#endif
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/getdtablecount.c
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#include "openbsd-compat.h"
4
5
#if !defined(HAVE_GETDTABLECOUNT)
6
int
7
getdtablecount(void)
8
0
{
9
0
  return (0);
10
0
}
11
#endif
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/getrtable.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/getrtable.c.html index a364421aa..3ef62f948 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/getrtable.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/getrtable.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/getrtable.c
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#include "openbsd-compat.h"
4
5
#if !defined(HAVE_GETRTABLE)
6
int
7
getrtable(void)
8
0
{
9
0
  return (0);
10
0
}
11
#endif
12
13
#if !defined(HAVE_SETRTABLE)
14
int
15
setrtable(int rtableid)
16
0
{
17
0
  if (rtableid == 0)
18
0
    return (0);
19
0
  return (-1);
20
0
}
21
#endif
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/getrtable.c
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#include "openbsd-compat.h"
4
5
#if !defined(HAVE_GETRTABLE)
6
int
7
getrtable(void)
8
0
{
9
0
  return (0);
10
0
}
11
#endif
12
13
#if !defined(HAVE_SETRTABLE)
14
int
15
setrtable(int rtableid)
16
0
{
17
0
  if (rtableid == 0)
18
0
    return (0);
19
0
  return (-1);
20
0
}
21
#endif
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/imsg-buffer.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/imsg-buffer.c.html index 61a47b5d2..7f6f577ff 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/imsg-buffer.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/imsg-buffer.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/imsg-buffer.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg-buffer.c,v 1.16 2023/06/19 17:19:50 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/socket.h>
22
#include <sys/uio.h>
23
24
#include <limits.h>
25
#include <errno.h>
26
#include <endian.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <unistd.h>
30
31
#include "openbsd-compat.h"
32
#include "imsg.h"
33
34
static int  ibuf_realloc(struct ibuf *, size_t);
35
static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
36
static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
37
static void msgbuf_drain(struct msgbuf *, size_t);
38
39
struct ibuf *
40
ibuf_open(size_t len)
41
0
{
42
0
  struct ibuf *buf;
43
44
0
  if (len == 0) {
45
0
    errno = EINVAL;
46
0
    return (NULL);
47
0
  }
48
0
  if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
49
0
    return (NULL);
50
0
  if ((buf->buf = calloc(len, 1)) == NULL) {
51
0
    free(buf);
52
0
    return (NULL);
53
0
  }
54
0
  buf->size = buf->max = len;
55
0
  buf->fd = -1;
56
57
0
  return (buf);
58
0
}
59
60
struct ibuf *
61
ibuf_dynamic(size_t len, size_t max)
62
25.5k
{
63
25.5k
  struct ibuf *buf;
64
65
25.5k
  if (max < len) {
66
0
    errno = EINVAL;
67
0
    return (NULL);
68
0
  }
69
70
25.5k
  if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
71
0
    return (NULL);
72
25.5k
  if (len > 0) {
73
23.8k
    if ((buf->buf = calloc(len, 1)) == NULL) {
74
0
      free(buf);
75
0
      return (NULL);
76
0
    }
77
23.8k
  }
78
25.5k
  buf->size = len;
79
25.5k
  buf->max = max;
80
25.5k
  buf->fd = -1;
81
82
25.5k
  return (buf);
83
25.5k
}
84
85
static int
86
ibuf_realloc(struct ibuf *buf, size_t len)
87
0
{
88
0
  unsigned char *b;
89
90
  /* on static buffers max is eq size and so the following fails */
91
0
  if (len > SIZE_MAX - buf->wpos || buf->wpos + len > buf->max) {
92
0
    errno = ERANGE;
93
0
    return (-1);
94
0
  }
95
96
0
  b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
97
0
  if (b == NULL)
98
0
    return (-1);
99
0
  buf->buf = b;
100
0
  buf->size = buf->wpos + len;
101
102
0
  return (0);
103
0
}
104
105
void *
106
ibuf_reserve(struct ibuf *buf, size_t len)
107
23.8k
{
108
23.8k
  void  *b;
109
110
23.8k
  if (len > SIZE_MAX - buf->wpos) {
111
0
    errno = ERANGE;
112
0
    return (NULL);
113
0
  }
114
115
23.8k
  if (buf->wpos + len > buf->size)
116
0
    if (ibuf_realloc(buf, len) == -1)
117
0
      return (NULL);
118
119
23.8k
  b = buf->buf + buf->wpos;
120
23.8k
  buf->wpos += len;
121
23.8k
  memset(b, 0, len);
122
23.8k
  return (b);
123
23.8k
}
124
125
int
126
ibuf_add(struct ibuf *buf, const void *data, size_t len)
127
23.8k
{
128
23.8k
  void *b;
129
130
23.8k
  if ((b = ibuf_reserve(buf, len)) == NULL)
131
0
    return (-1);
132
133
23.8k
  memcpy(b, data, len);
134
23.8k
  return (0);
135
23.8k
}
136
137
138
int
139
ibuf_add_buf(struct ibuf *buf, const struct ibuf *from)
140
0
{
141
0
  return ibuf_add(buf, from->buf, from->wpos);
142
0
}
143
144
int
145
ibuf_add_n8(struct ibuf *buf, uint64_t value)
146
0
{
147
0
  uint8_t v;
148
149
0
  if (value > UINT8_MAX) {
150
0
    errno = EINVAL;
151
0
    return (-1);
152
0
  }
153
0
  v = value;
154
0
  return ibuf_add(buf, &v, sizeof(v));
155
0
}
156
157
int
158
ibuf_add_n16(struct ibuf *buf, uint64_t value)
159
0
{
160
0
  uint16_t v;
161
162
0
  if (value > UINT16_MAX) {
163
0
    errno = EINVAL;
164
0
    return (-1);
165
0
  }
166
0
  v = htobe16(value);
167
0
  return ibuf_add(buf, &v, sizeof(v));
168
0
}
169
170
int
171
ibuf_add_n32(struct ibuf *buf, uint64_t value)
172
0
{
173
0
  uint32_t v;
174
175
0
  if (value > UINT32_MAX) {
176
0
    errno = EINVAL;
177
0
    return (-1);
178
0
  }
179
0
  v = htobe32(value);
180
0
  return ibuf_add(buf, &v, sizeof(v));
181
0
}
182
183
int
184
ibuf_add_n64(struct ibuf *buf, uint64_t value)
185
0
{
186
0
  value = htobe64(value);
187
0
  return ibuf_add(buf, &value, sizeof(value));
188
0
}
189
190
int
191
ibuf_add_zero(struct ibuf *buf, size_t len)
192
0
{
193
0
  void *b;
194
195
0
  if ((b = ibuf_reserve(buf, len)) == NULL)
196
0
    return (-1);
197
0
  return (0);
198
0
}
199
200
void *
201
ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
202
284k
{
203
  /* only allowed to seek in already written parts */
204
284k
  if (len > SIZE_MAX - pos || pos + len > buf->wpos) {
205
4.20k
    errno = ERANGE;
206
4.20k
    return (NULL);
207
4.20k
  }
208
209
280k
  return (buf->buf + pos);
210
284k
}
211
212
int
213
ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len)
214
0
{
215
0
  void *b;
216
217
0
  if ((b = ibuf_seek(buf, pos, len)) == NULL)
218
0
    return (-1);
219
220
0
  memcpy(b, data, len);
221
0
  return (0);
222
0
}
223
224
int
225
ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value)
226
0
{
227
0
  uint8_t v;
228
229
0
  if (value > UINT8_MAX) {
230
0
    errno = EINVAL;
231
0
    return (-1);
232
0
  }
233
0
  v = value;
234
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
235
0
}
236
237
int
238
ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value)
239
0
{
240
0
  uint16_t v;
241
242
0
  if (value > UINT16_MAX) {
243
0
    errno = EINVAL;
244
0
    return (-1);
245
0
  }
246
0
  v = htobe16(value);
247
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
248
0
}
249
250
int
251
ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value)
252
0
{
253
0
  uint32_t v;
254
255
0
  if (value > UINT32_MAX) {
256
0
    errno = EINVAL;
257
0
    return (-1);
258
0
  }
259
0
  v = htobe32(value);
260
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
261
0
}
262
263
int
264
ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value)
265
0
{
266
0
  value = htobe64(value);
267
0
  return (ibuf_set(buf, pos, &value, sizeof(value)));
268
0
}
269
270
void *
271
ibuf_data(struct ibuf *buf)
272
908k
{
273
908k
  return (buf->buf);
274
908k
}
275
276
size_t
277
ibuf_size(struct ibuf *buf)
278
15.4k
{
279
15.4k
  return (buf->wpos);
280
15.4k
}
281
282
size_t
283
ibuf_left(struct ibuf *buf)
284
0
{
285
0
  return (buf->max - buf->wpos);
286
0
}
287
288
void
289
ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
290
0
{
291
0
  ibuf_enqueue(msgbuf, buf);
292
0
}
293
294
void
295
ibuf_free(struct ibuf *buf)
296
210k
{
297
210k
  if (buf == NULL)
298
184k
    return;
299
#ifdef NOTYET
300
  if (buf->fd != -1)
301
    close(buf->fd);
302
#endif
303
25.5k
  freezero(buf->buf, buf->size);
304
25.5k
  free(buf);
305
25.5k
}
306
307
int
308
ibuf_fd_avail(struct ibuf *buf)
309
0
{
310
0
  return (buf->fd != -1);
311
0
}
312
313
int
314
ibuf_fd_get(struct ibuf *buf)
315
0
{
316
0
  int fd;
317
318
0
  fd = buf->fd;
319
#ifdef NOTYET
320
  buf->fd = -1;
321
#endif
322
0
  return (fd);
323
0
}
324
325
void
326
ibuf_fd_set(struct ibuf *buf, int fd)
327
0
{
328
0
  if (buf->fd != -1)
329
0
    close(buf->fd);
330
0
  buf->fd = fd;
331
0
}
332
333
#ifdef _WIN32
334
#define IBUF_WSABUF_WRITE_MAX 16
335
int
336
ibuf_write(struct msgbuf *msgbuf)
337
{
338
  DWORD    bytesSent;
339
  WSABUF     iov[IBUF_WSABUF_WRITE_MAX];
340
  struct ibuf *buf;
341
  unsigned int   i = 0;
342
  ssize_t n;
343
344
  memset(&iov, 0, sizeof(iov));
345
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
346
    if (i >= IBUF_WSABUF_WRITE_MAX)
347
      break;
348
    iov[i].buf = buf->buf + buf->rpos;
349
    iov[i].len = buf->wpos - buf->rpos;
350
    i++;
351
  }
352
353
  if (WSASend(msgbuf->fd, iov, i, &bytesSent, 0, NULL, NULL))
354
    return (-1);
355
  n = bytesSent;
356
357
  if (n == 0) {     /* connection closed */
358
    errno = 0;
359
    return (0);
360
  }
361
362
  msgbuf_drain(msgbuf, n);
363
364
  return (1);
365
}
366
#else
367
int
368
ibuf_write(struct msgbuf *msgbuf)
369
0
{
370
0
  struct iovec   iov[IOV_MAX];
371
0
  struct ibuf *buf;
372
0
  unsigned int   i = 0;
373
0
  ssize_t n;
374
375
0
  memset(&iov, 0, sizeof(iov));
376
0
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
377
0
    if (i >= IOV_MAX)
378
0
      break;
379
0
    iov[i].iov_base = buf->buf + buf->rpos;
380
0
    iov[i].iov_len = buf->wpos - buf->rpos;
381
0
    i++;
382
0
  }
383
384
0
again:
385
0
  if ((n = writev(msgbuf->fd, iov, i)) == -1) {
386
0
    if (errno == EINTR)
387
0
      goto again;
388
0
    if (errno == ENOBUFS)
389
0
      errno = EAGAIN;
390
0
    return (-1);
391
0
  }
392
393
0
  if (n == 0) {     /* connection closed */
394
0
    errno = 0;
395
0
    return (0);
396
0
  }
397
398
0
  msgbuf_drain(msgbuf, n);
399
400
0
  return (1);
401
0
}
402
#endif /* !_WIN32 */
403
404
void
405
msgbuf_init(struct msgbuf *msgbuf)
406
0
{
407
0
  msgbuf->queued = 0;
408
0
  msgbuf->fd = -1;
409
0
  TAILQ_INIT(&msgbuf->bufs);
410
0
}
411
412
static void
413
msgbuf_drain(struct msgbuf *msgbuf, size_t n)
414
0
{
415
0
  struct ibuf *buf, *next;
416
417
0
  for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
418
0
      buf = next) {
419
0
    next = TAILQ_NEXT(buf, entry);
420
0
    if (n >= buf->wpos - buf->rpos) {
421
0
      n -= buf->wpos - buf->rpos;
422
0
      ibuf_dequeue(msgbuf, buf);
423
0
    } else {
424
0
      buf->rpos += n;
425
0
      n = 0;
426
0
    }
427
0
  }
428
0
}
429
430
void
431
msgbuf_clear(struct msgbuf *msgbuf)
432
0
{
433
0
  struct ibuf *buf;
434
435
0
  while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
436
0
    ibuf_dequeue(msgbuf, buf);
437
0
}
438
439
#ifdef _WIN32
440
int
441
msgbuf_write(struct msgbuf *msgbuf)
442
{
443
  struct ibuf *buf;
444
445
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry)
446
    if (buf->fd != -1)
447
      return (-1);
448
  return ibuf_write(msgbuf);
449
}
450
#else
451
int
452
msgbuf_write(struct msgbuf *msgbuf)
453
0
{
454
0
  struct iovec   iov[IOV_MAX];
455
0
  struct ibuf *buf, *buf0 = NULL;
456
0
  unsigned int   i = 0;
457
0
  ssize_t    n;
458
0
  struct msghdr  msg;
459
0
  struct cmsghdr  *cmsg;
460
0
  union {
461
0
    struct cmsghdr  hdr;
462
0
    char    buf[CMSG_SPACE(sizeof(int))];
463
0
  } cmsgbuf;
464
465
0
  memset(&iov, 0, sizeof(iov));
466
0
  memset(&msg, 0, sizeof(msg));
467
0
  memset(&cmsgbuf, 0, sizeof(cmsgbuf));
468
0
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
469
0
    if (i >= IOV_MAX)
470
0
      break;
471
0
    if (i > 0 && buf->fd != -1)
472
0
      break;
473
0
    iov[i].iov_base = buf->buf + buf->rpos;
474
0
    iov[i].iov_len = buf->wpos - buf->rpos;
475
0
    i++;
476
0
    if (buf->fd != -1)
477
0
      buf0 = buf;
478
0
  }
479
480
0
  msg.msg_iov = iov;
481
0
  msg.msg_iovlen = i;
482
483
0
  if (buf0 != NULL) {
484
0
    msg.msg_control = (caddr_t)&cmsgbuf.buf;
485
0
    msg.msg_controllen = sizeof(cmsgbuf.buf);
486
0
    cmsg = CMSG_FIRSTHDR(&msg);
487
0
    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
488
0
    cmsg->cmsg_level = SOL_SOCKET;
489
0
    cmsg->cmsg_type = SCM_RIGHTS;
490
0
    *(int *)CMSG_DATA(cmsg) = buf0->fd;
491
0
  }
492
493
0
again:
494
0
  if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
495
0
    if (errno == EINTR)
496
0
      goto again;
497
0
    if (errno == ENOBUFS)
498
0
      errno = EAGAIN;
499
0
    return (-1);
500
0
  }
501
502
0
  if (n == 0) {     /* connection closed */
503
0
    errno = 0;
504
0
    return (0);
505
0
  }
506
507
  /*
508
   * assumption: fd got sent if sendmsg sent anything
509
   * this works because fds are passed one at a time
510
   */
511
0
  if (buf0 != NULL) {
512
0
    close(buf0->fd);
513
0
    buf0->fd = -1;
514
0
  }
515
516
0
  msgbuf_drain(msgbuf, n);
517
518
0
  return (1);
519
0
}
520
#endif /* !_WIN32 */
521
522
static void
523
ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
524
0
{
525
0
  TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
526
0
  msgbuf->queued++;
527
0
}
528
529
static void
530
ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
531
0
{
532
0
  TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
533
534
0
  if (buf->fd != -1) {
535
0
    close(buf->fd);
536
0
    buf->fd = -1;
537
0
  }
538
539
0
  msgbuf->queued--;
540
0
  ibuf_free(buf);
541
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/imsg-buffer.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg-buffer.c,v 1.16 2023/06/19 17:19:50 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/socket.h>
22
#include <sys/uio.h>
23
24
#include <limits.h>
25
#include <errno.h>
26
#include <endian.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <unistd.h>
30
31
#include "openbsd-compat.h"
32
#include "imsg.h"
33
34
static int  ibuf_realloc(struct ibuf *, size_t);
35
static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
36
static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
37
static void msgbuf_drain(struct msgbuf *, size_t);
38
39
struct ibuf *
40
ibuf_open(size_t len)
41
0
{
42
0
  struct ibuf *buf;
43
44
0
  if (len == 0) {
45
0
    errno = EINVAL;
46
0
    return (NULL);
47
0
  }
48
0
  if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
49
0
    return (NULL);
50
0
  if ((buf->buf = calloc(len, 1)) == NULL) {
51
0
    free(buf);
52
0
    return (NULL);
53
0
  }
54
0
  buf->size = buf->max = len;
55
0
  buf->fd = -1;
56
57
0
  return (buf);
58
0
}
59
60
struct ibuf *
61
ibuf_dynamic(size_t len, size_t max)
62
25.5k
{
63
25.5k
  struct ibuf *buf;
64
65
25.5k
  if (max < len) {
66
0
    errno = EINVAL;
67
0
    return (NULL);
68
0
  }
69
70
25.5k
  if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
71
0
    return (NULL);
72
25.5k
  if (len > 0) {
73
23.8k
    if ((buf->buf = calloc(len, 1)) == NULL) {
74
0
      free(buf);
75
0
      return (NULL);
76
0
    }
77
23.8k
  }
78
25.5k
  buf->size = len;
79
25.5k
  buf->max = max;
80
25.5k
  buf->fd = -1;
81
82
25.5k
  return (buf);
83
25.5k
}
84
85
static int
86
ibuf_realloc(struct ibuf *buf, size_t len)
87
0
{
88
0
  unsigned char *b;
89
90
  /* on static buffers max is eq size and so the following fails */
91
0
  if (len > SIZE_MAX - buf->wpos || buf->wpos + len > buf->max) {
92
0
    errno = ERANGE;
93
0
    return (-1);
94
0
  }
95
96
0
  b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
97
0
  if (b == NULL)
98
0
    return (-1);
99
0
  buf->buf = b;
100
0
  buf->size = buf->wpos + len;
101
102
0
  return (0);
103
0
}
104
105
void *
106
ibuf_reserve(struct ibuf *buf, size_t len)
107
23.8k
{
108
23.8k
  void  *b;
109
110
23.8k
  if (len > SIZE_MAX - buf->wpos) {
111
0
    errno = ERANGE;
112
0
    return (NULL);
113
0
  }
114
115
23.8k
  if (buf->wpos + len > buf->size)
116
0
    if (ibuf_realloc(buf, len) == -1)
117
0
      return (NULL);
118
119
23.8k
  b = buf->buf + buf->wpos;
120
23.8k
  buf->wpos += len;
121
23.8k
  memset(b, 0, len);
122
23.8k
  return (b);
123
23.8k
}
124
125
int
126
ibuf_add(struct ibuf *buf, const void *data, size_t len)
127
23.8k
{
128
23.8k
  void *b;
129
130
23.8k
  if ((b = ibuf_reserve(buf, len)) == NULL)
131
0
    return (-1);
132
133
23.8k
  memcpy(b, data, len);
134
23.8k
  return (0);
135
23.8k
}
136
137
138
int
139
ibuf_add_buf(struct ibuf *buf, const struct ibuf *from)
140
0
{
141
0
  return ibuf_add(buf, from->buf, from->wpos);
142
0
}
143
144
int
145
ibuf_add_n8(struct ibuf *buf, uint64_t value)
146
0
{
147
0
  uint8_t v;
148
149
0
  if (value > UINT8_MAX) {
150
0
    errno = EINVAL;
151
0
    return (-1);
152
0
  }
153
0
  v = value;
154
0
  return ibuf_add(buf, &v, sizeof(v));
155
0
}
156
157
int
158
ibuf_add_n16(struct ibuf *buf, uint64_t value)
159
0
{
160
0
  uint16_t v;
161
162
0
  if (value > UINT16_MAX) {
163
0
    errno = EINVAL;
164
0
    return (-1);
165
0
  }
166
0
  v = htobe16(value);
167
0
  return ibuf_add(buf, &v, sizeof(v));
168
0
}
169
170
int
171
ibuf_add_n32(struct ibuf *buf, uint64_t value)
172
0
{
173
0
  uint32_t v;
174
175
0
  if (value > UINT32_MAX) {
176
0
    errno = EINVAL;
177
0
    return (-1);
178
0
  }
179
0
  v = htobe32(value);
180
0
  return ibuf_add(buf, &v, sizeof(v));
181
0
}
182
183
int
184
ibuf_add_n64(struct ibuf *buf, uint64_t value)
185
0
{
186
0
  value = htobe64(value);
187
0
  return ibuf_add(buf, &value, sizeof(value));
188
0
}
189
190
int
191
ibuf_add_zero(struct ibuf *buf, size_t len)
192
0
{
193
0
  void *b;
194
195
0
  if ((b = ibuf_reserve(buf, len)) == NULL)
196
0
    return (-1);
197
0
  return (0);
198
0
}
199
200
void *
201
ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
202
284k
{
203
  /* only allowed to seek in already written parts */
204
284k
  if (len > SIZE_MAX - pos || pos + len > buf->wpos) {
205
4.20k
    errno = ERANGE;
206
4.20k
    return (NULL);
207
4.20k
  }
208
209
280k
  return (buf->buf + pos);
210
284k
}
211
212
int
213
ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len)
214
0
{
215
0
  void *b;
216
217
0
  if ((b = ibuf_seek(buf, pos, len)) == NULL)
218
0
    return (-1);
219
220
0
  memcpy(b, data, len);
221
0
  return (0);
222
0
}
223
224
int
225
ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value)
226
0
{
227
0
  uint8_t v;
228
229
0
  if (value > UINT8_MAX) {
230
0
    errno = EINVAL;
231
0
    return (-1);
232
0
  }
233
0
  v = value;
234
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
235
0
}
236
237
int
238
ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value)
239
0
{
240
0
  uint16_t v;
241
242
0
  if (value > UINT16_MAX) {
243
0
    errno = EINVAL;
244
0
    return (-1);
245
0
  }
246
0
  v = htobe16(value);
247
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
248
0
}
249
250
int
251
ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value)
252
0
{
253
0
  uint32_t v;
254
255
0
  if (value > UINT32_MAX) {
256
0
    errno = EINVAL;
257
0
    return (-1);
258
0
  }
259
0
  v = htobe32(value);
260
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
261
0
}
262
263
int
264
ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value)
265
0
{
266
0
  value = htobe64(value);
267
0
  return (ibuf_set(buf, pos, &value, sizeof(value)));
268
0
}
269
270
void *
271
ibuf_data(struct ibuf *buf)
272
908k
{
273
908k
  return (buf->buf);
274
908k
}
275
276
size_t
277
ibuf_size(struct ibuf *buf)
278
15.4k
{
279
15.4k
  return (buf->wpos);
280
15.4k
}
281
282
size_t
283
ibuf_left(struct ibuf *buf)
284
0
{
285
0
  return (buf->max - buf->wpos);
286
0
}
287
288
void
289
ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
290
0
{
291
0
  ibuf_enqueue(msgbuf, buf);
292
0
}
293
294
void
295
ibuf_free(struct ibuf *buf)
296
210k
{
297
210k
  if (buf == NULL)
298
184k
    return;
299
#ifdef NOTYET
300
  if (buf->fd != -1)
301
    close(buf->fd);
302
#endif
303
25.5k
  freezero(buf->buf, buf->size);
304
25.5k
  free(buf);
305
25.5k
}
306
307
int
308
ibuf_fd_avail(struct ibuf *buf)
309
0
{
310
0
  return (buf->fd != -1);
311
0
}
312
313
int
314
ibuf_fd_get(struct ibuf *buf)
315
0
{
316
0
  int fd;
317
318
0
  fd = buf->fd;
319
#ifdef NOTYET
320
  buf->fd = -1;
321
#endif
322
0
  return (fd);
323
0
}
324
325
void
326
ibuf_fd_set(struct ibuf *buf, int fd)
327
0
{
328
0
  if (buf->fd != -1)
329
0
    close(buf->fd);
330
0
  buf->fd = fd;
331
0
}
332
333
#ifdef _WIN32
334
#define IBUF_WSABUF_WRITE_MAX 16
335
int
336
ibuf_write(struct msgbuf *msgbuf)
337
{
338
  DWORD    bytesSent;
339
  WSABUF     iov[IBUF_WSABUF_WRITE_MAX];
340
  struct ibuf *buf;
341
  unsigned int   i = 0;
342
  ssize_t n;
343
344
  memset(&iov, 0, sizeof(iov));
345
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
346
    if (i >= IBUF_WSABUF_WRITE_MAX)
347
      break;
348
    iov[i].buf = buf->buf + buf->rpos;
349
    iov[i].len = buf->wpos - buf->rpos;
350
    i++;
351
  }
352
353
  if (WSASend(msgbuf->fd, iov, i, &bytesSent, 0, NULL, NULL))
354
    return (-1);
355
  n = bytesSent;
356
357
  if (n == 0) {     /* connection closed */
358
    errno = 0;
359
    return (0);
360
  }
361
362
  msgbuf_drain(msgbuf, n);
363
364
  return (1);
365
}
366
#else
367
int
368
ibuf_write(struct msgbuf *msgbuf)
369
0
{
370
0
  struct iovec   iov[IOV_MAX];
371
0
  struct ibuf *buf;
372
0
  unsigned int   i = 0;
373
0
  ssize_t n;
374
375
0
  memset(&iov, 0, sizeof(iov));
376
0
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
377
0
    if (i >= IOV_MAX)
378
0
      break;
379
0
    iov[i].iov_base = buf->buf + buf->rpos;
380
0
    iov[i].iov_len = buf->wpos - buf->rpos;
381
0
    i++;
382
0
  }
383
384
0
again:
385
0
  if ((n = writev(msgbuf->fd, iov, i)) == -1) {
386
0
    if (errno == EINTR)
387
0
      goto again;
388
0
    if (errno == ENOBUFS)
389
0
      errno = EAGAIN;
390
0
    return (-1);
391
0
  }
392
393
0
  if (n == 0) {     /* connection closed */
394
0
    errno = 0;
395
0
    return (0);
396
0
  }
397
398
0
  msgbuf_drain(msgbuf, n);
399
400
0
  return (1);
401
0
}
402
#endif /* !_WIN32 */
403
404
void
405
msgbuf_init(struct msgbuf *msgbuf)
406
0
{
407
0
  msgbuf->queued = 0;
408
0
  msgbuf->fd = -1;
409
0
  TAILQ_INIT(&msgbuf->bufs);
410
0
}
411
412
static void
413
msgbuf_drain(struct msgbuf *msgbuf, size_t n)
414
0
{
415
0
  struct ibuf *buf, *next;
416
417
0
  for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
418
0
      buf = next) {
419
0
    next = TAILQ_NEXT(buf, entry);
420
0
    if (n >= buf->wpos - buf->rpos) {
421
0
      n -= buf->wpos - buf->rpos;
422
0
      ibuf_dequeue(msgbuf, buf);
423
0
    } else {
424
0
      buf->rpos += n;
425
0
      n = 0;
426
0
    }
427
0
  }
428
0
}
429
430
void
431
msgbuf_clear(struct msgbuf *msgbuf)
432
0
{
433
0
  struct ibuf *buf;
434
435
0
  while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
436
0
    ibuf_dequeue(msgbuf, buf);
437
0
}
438
439
#ifdef _WIN32
440
int
441
msgbuf_write(struct msgbuf *msgbuf)
442
{
443
  struct ibuf *buf;
444
445
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry)
446
    if (buf->fd != -1)
447
      return (-1);
448
  return ibuf_write(msgbuf);
449
}
450
#else
451
int
452
msgbuf_write(struct msgbuf *msgbuf)
453
0
{
454
0
  struct iovec   iov[IOV_MAX];
455
0
  struct ibuf *buf, *buf0 = NULL;
456
0
  unsigned int   i = 0;
457
0
  ssize_t    n;
458
0
  struct msghdr  msg;
459
0
  struct cmsghdr  *cmsg;
460
0
  union {
461
0
    struct cmsghdr  hdr;
462
0
    char    buf[CMSG_SPACE(sizeof(int))];
463
0
  } cmsgbuf;
464
465
0
  memset(&iov, 0, sizeof(iov));
466
0
  memset(&msg, 0, sizeof(msg));
467
0
  memset(&cmsgbuf, 0, sizeof(cmsgbuf));
468
0
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
469
0
    if (i >= IOV_MAX)
470
0
      break;
471
0
    if (i > 0 && buf->fd != -1)
472
0
      break;
473
0
    iov[i].iov_base = buf->buf + buf->rpos;
474
0
    iov[i].iov_len = buf->wpos - buf->rpos;
475
0
    i++;
476
0
    if (buf->fd != -1)
477
0
      buf0 = buf;
478
0
  }
479
480
0
  msg.msg_iov = iov;
481
0
  msg.msg_iovlen = i;
482
483
0
  if (buf0 != NULL) {
484
0
    msg.msg_control = (caddr_t)&cmsgbuf.buf;
485
0
    msg.msg_controllen = sizeof(cmsgbuf.buf);
486
0
    cmsg = CMSG_FIRSTHDR(&msg);
487
0
    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
488
0
    cmsg->cmsg_level = SOL_SOCKET;
489
0
    cmsg->cmsg_type = SCM_RIGHTS;
490
0
    *(int *)CMSG_DATA(cmsg) = buf0->fd;
491
0
  }
492
493
0
again:
494
0
  if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
495
0
    if (errno == EINTR)
496
0
      goto again;
497
0
    if (errno == ENOBUFS)
498
0
      errno = EAGAIN;
499
0
    return (-1);
500
0
  }
501
502
0
  if (n == 0) {     /* connection closed */
503
0
    errno = 0;
504
0
    return (0);
505
0
  }
506
507
  /*
508
   * assumption: fd got sent if sendmsg sent anything
509
   * this works because fds are passed one at a time
510
   */
511
0
  if (buf0 != NULL) {
512
0
    close(buf0->fd);
513
0
    buf0->fd = -1;
514
0
  }
515
516
0
  msgbuf_drain(msgbuf, n);
517
518
0
  return (1);
519
0
}
520
#endif /* !_WIN32 */
521
522
static void
523
ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
524
0
{
525
0
  TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
526
0
  msgbuf->queued++;
527
0
}
528
529
static void
530
ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
531
0
{
532
0
  TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
533
534
0
  if (buf->fd != -1) {
535
0
    close(buf->fd);
536
0
    buf->fd = -1;
537
0
  }
538
539
0
  msgbuf->queued--;
540
0
  ibuf_free(buf);
541
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/imsg.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/imsg.c.html index 211a4750a..3466a7497 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/imsg.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/imsg.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/imsg.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg.c,v 1.19 2023/06/19 17:19:50 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/socket.h>
22
#include <sys/uio.h>
23
24
#include <errno.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <unistd.h>
28
29
#include "openbsd-compat.h"
30
#include "imsg.h"
31
32
int  imsg_fd_overhead = 0;
33
34
static int   imsg_get_fd(struct imsgbuf *);
35
36
void
37
imsg_init(struct imsgbuf *ibuf, int fd)
38
0
{
39
0
  msgbuf_init(&ibuf->w);
40
0
  memset(&ibuf->r, 0, sizeof(ibuf->r));
41
0
  ibuf->fd = fd;
42
0
  ibuf->w.fd = fd;
43
0
  ibuf->pid = getpid();
44
0
  TAILQ_INIT(&ibuf->fds);
45
0
}
46
47
#ifdef _WIN32
48
ssize_t
49
imsg_read(struct imsgbuf *ibuf)
50
{
51
  ssize_t      n;
52
  uint8_t     *base;
53
  size_t       len;
54
55
  base = ibuf->r.buf + ibuf->r.wpos;
56
  len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
57
58
  while ((n = recv(ibuf->fd, base, len, 0)) == -1) {
59
    if (errno != EINTR)
60
      return (-1);
61
  }
62
  ibuf->r.wpos += n;
63
  return (n);
64
}
65
#else
66
ssize_t
67
imsg_read(struct imsgbuf *ibuf)
68
0
{
69
0
  struct msghdr    msg;
70
0
  struct cmsghdr    *cmsg;
71
0
  union {
72
0
    struct cmsghdr hdr;
73
0
    char  buf[CMSG_SPACE(sizeof(int) * 1)];
74
0
  } cmsgbuf;
75
0
  struct iovec     iov;
76
0
  ssize_t      n = -1;
77
0
  int      fd;
78
0
  struct imsg_fd    *ifd;
79
80
0
  memset(&msg, 0, sizeof(msg));
81
0
  memset(&cmsgbuf, 0, sizeof(cmsgbuf));
82
83
0
  iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
84
0
  iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
85
0
  msg.msg_iov = &iov;
86
0
  msg.msg_iovlen = 1;
87
0
  msg.msg_control = &cmsgbuf.buf;
88
0
  msg.msg_controllen = sizeof(cmsgbuf.buf);
89
90
0
  if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
91
0
    return (-1);
92
93
0
again:
94
0
  if (getdtablecount() + imsg_fd_overhead +
95
0
      (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
96
0
      >= getdtablesize()) {
97
0
    errno = EAGAIN;
98
0
    free(ifd);
99
0
    return (-1);
100
0
  }
101
102
0
  if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
103
0
    if (errno == EINTR)
104
0
      goto again;
105
0
    goto fail;
106
0
  }
107
108
0
  ibuf->r.wpos += n;
109
110
0
  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
111
0
      cmsg = CMSG_NXTHDR(&msg, cmsg)) {
112
0
    if (cmsg->cmsg_level == SOL_SOCKET &&
113
0
        cmsg->cmsg_type == SCM_RIGHTS) {
114
0
      int i;
115
0
      int j;
116
117
      /*
118
       * We only accept one file descriptor.  Due to C
119
       * padding rules, our control buffer might contain
120
       * more than one fd, and we must close them.
121
       */
122
0
      j = ((char *)cmsg + cmsg->cmsg_len -
123
0
          (char *)CMSG_DATA(cmsg)) / sizeof(int);
124
0
      for (i = 0; i < j; i++) {
125
0
        fd = ((int *)CMSG_DATA(cmsg))[i];
126
0
        if (ifd != NULL) {
127
0
          ifd->fd = fd;
128
0
          TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
129
0
              entry);
130
0
          ifd = NULL;
131
0
        } else
132
0
          close(fd);
133
0
      }
134
0
    }
135
    /* we do not handle other ctl data level */
136
0
  }
137
138
0
fail:
139
0
  free(ifd);
140
0
  return (n);
141
0
}
142
#endif
143
144
ssize_t
145
imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
146
0
{
147
0
  size_t       av, left, datalen;
148
149
0
  av = ibuf->r.wpos;
150
151
0
  if (IMSG_HEADER_SIZE > av)
152
0
    return (0);
153
154
0
  memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
155
0
  if (imsg->hdr.len < IMSG_HEADER_SIZE ||
156
0
      imsg->hdr.len > MAX_IMSGSIZE) {
157
0
    errno = ERANGE;
158
0
    return (-1);
159
0
  }
160
0
  if (imsg->hdr.len > av)
161
0
    return (0);
162
0
  datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
163
0
  ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
164
0
  if (datalen == 0)
165
0
    imsg->data = NULL;
166
0
  else if ((imsg->data = malloc(datalen)) == NULL)
167
0
    return (-1);
168
169
0
  if (imsg->hdr.flags & IMSGF_HASFD)
170
0
    imsg->fd = imsg_get_fd(ibuf);
171
0
  else
172
0
    imsg->fd = -1;
173
174
0
  if (datalen != 0)
175
0
    memcpy(imsg->data, ibuf->r.rptr, datalen);
176
177
0
  if (imsg->hdr.len < av) {
178
0
    left = av - imsg->hdr.len;
179
0
    memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
180
0
    ibuf->r.wpos = left;
181
0
  } else
182
0
    ibuf->r.wpos = 0;
183
184
0
  return (datalen + IMSG_HEADER_SIZE);
185
0
}
186
187
int
188
imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
189
    int fd, const void *data, uint16_t datalen)
190
0
{
191
0
  struct ibuf *wbuf;
192
193
0
  if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
194
0
    return (-1);
195
196
0
  if (imsg_add(wbuf, data, datalen) == -1)
197
0
    return (-1);
198
199
0
  ibuf_fd_set(wbuf, fd);
200
201
0
  imsg_close(ibuf, wbuf);
202
203
0
  return (1);
204
0
}
205
206
int
207
imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
208
    int fd, const struct iovec *iov, int iovcnt)
209
0
{
210
0
  struct ibuf *wbuf;
211
0
  int    i, datalen = 0;
212
213
0
  for (i = 0; i < iovcnt; i++)
214
0
    datalen += iov[i].iov_len;
215
216
0
  if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
217
0
    return (-1);
218
219
0
  for (i = 0; i < iovcnt; i++)
220
0
    if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
221
0
      return (-1);
222
223
0
  ibuf_fd_set(wbuf, fd);
224
225
0
  imsg_close(ibuf, wbuf);
226
227
0
  return (1);
228
0
}
229
230
int
231
imsg_compose_ibuf(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid,
232
    pid_t pid, struct ibuf *buf)
233
0
{
234
0
  struct ibuf *wbuf = NULL;
235
0
  struct imsg_hdr  hdr;
236
0
  int save_errno;
237
238
0
  if (ibuf_size(buf) + IMSG_HEADER_SIZE > MAX_IMSGSIZE) {
239
0
    errno = ERANGE;
240
0
    goto fail;
241
0
  }
242
243
0
  hdr.type = type;
244
0
  hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE;
245
0
  hdr.flags = 0;
246
0
  hdr.peerid = peerid;
247
0
  if ((hdr.pid = pid) == 0)
248
0
    hdr.pid = ibuf->pid;
249
250
0
  if ((wbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
251
0
    goto fail;
252
0
  if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
253
0
    goto fail;
254
255
0
  ibuf_close(&ibuf->w, wbuf);
256
0
  ibuf_close(&ibuf->w, buf);
257
0
  return (1);
258
259
0
 fail:
260
0
  save_errno = errno;
261
0
  ibuf_free(buf);
262
0
  ibuf_free(wbuf);
263
0
  errno = save_errno;
264
0
  return (-1);
265
0
}
266
267
struct ibuf *
268
imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
269
    uint16_t datalen)
270
0
{
271
0
  struct ibuf *wbuf;
272
0
  struct imsg_hdr  hdr;
273
274
0
  datalen += IMSG_HEADER_SIZE;
275
0
  if (datalen > MAX_IMSGSIZE) {
276
0
    errno = ERANGE;
277
0
    return (NULL);
278
0
  }
279
280
0
  hdr.type = type;
281
0
  hdr.flags = 0;
282
0
  hdr.peerid = peerid;
283
0
  if ((hdr.pid = pid) == 0)
284
0
    hdr.pid = ibuf->pid;
285
0
  if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
286
0
    return (NULL);
287
0
  }
288
0
  if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
289
0
    return (NULL);
290
291
0
  return (wbuf);
292
0
}
293
294
int
295
imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
296
0
{
297
0
  if (datalen)
298
0
    if (ibuf_add(msg, data, datalen) == -1) {
299
0
      ibuf_free(msg);
300
0
      return (-1);
301
0
    }
302
0
  return (datalen);
303
0
}
304
305
void
306
imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
307
0
{
308
0
  struct imsg_hdr *hdr;
309
310
0
  hdr = (struct imsg_hdr *)msg->buf;
311
312
0
  hdr->flags &= ~IMSGF_HASFD;
313
0
  if (ibuf_fd_avail(msg))
314
0
    hdr->flags |= IMSGF_HASFD;
315
0
  hdr->len = ibuf_size(msg);
316
317
0
  ibuf_close(&ibuf->w, msg);
318
0
}
319
320
void
321
imsg_free(struct imsg *imsg)
322
0
{
323
0
  freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
324
0
}
325
326
static int
327
imsg_get_fd(struct imsgbuf *ibuf)
328
0
{
329
0
  int    fd;
330
0
  struct imsg_fd  *ifd;
331
332
0
  if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
333
0
    return (-1);
334
335
0
  fd = ifd->fd;
336
0
  TAILQ_REMOVE(&ibuf->fds, ifd, entry);
337
0
  free(ifd);
338
339
0
  return (fd);
340
0
}
341
342
int
343
imsg_flush(struct imsgbuf *ibuf)
344
0
{
345
0
  while (ibuf->w.queued)
346
0
    if (msgbuf_write(&ibuf->w) <= 0)
347
0
      return (-1);
348
0
  return (0);
349
0
}
350
351
void
352
imsg_clear(struct imsgbuf *ibuf)
353
0
{
354
0
  int fd;
355
356
0
  msgbuf_clear(&ibuf->w);
357
0
  while ((fd = imsg_get_fd(ibuf)) != -1)
358
0
    close(fd);
359
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/imsg.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg.c,v 1.19 2023/06/19 17:19:50 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/socket.h>
22
#include <sys/uio.h>
23
24
#include <errno.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <unistd.h>
28
29
#include "openbsd-compat.h"
30
#include "imsg.h"
31
32
int  imsg_fd_overhead = 0;
33
34
static int   imsg_get_fd(struct imsgbuf *);
35
36
void
37
imsg_init(struct imsgbuf *ibuf, int fd)
38
0
{
39
0
  msgbuf_init(&ibuf->w);
40
0
  memset(&ibuf->r, 0, sizeof(ibuf->r));
41
0
  ibuf->fd = fd;
42
0
  ibuf->w.fd = fd;
43
0
  ibuf->pid = getpid();
44
0
  TAILQ_INIT(&ibuf->fds);
45
0
}
46
47
#ifdef _WIN32
48
ssize_t
49
imsg_read(struct imsgbuf *ibuf)
50
{
51
  ssize_t      n;
52
  uint8_t     *base;
53
  size_t       len;
54
55
  base = ibuf->r.buf + ibuf->r.wpos;
56
  len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
57
58
  while ((n = recv(ibuf->fd, base, len, 0)) == -1) {
59
    if (errno != EINTR)
60
      return (-1);
61
  }
62
  ibuf->r.wpos += n;
63
  return (n);
64
}
65
#else
66
ssize_t
67
imsg_read(struct imsgbuf *ibuf)
68
0
{
69
0
  struct msghdr    msg;
70
0
  struct cmsghdr    *cmsg;
71
0
  union {
72
0
    struct cmsghdr hdr;
73
0
    char  buf[CMSG_SPACE(sizeof(int) * 1)];
74
0
  } cmsgbuf;
75
0
  struct iovec     iov;
76
0
  ssize_t      n = -1;
77
0
  int      fd;
78
0
  struct imsg_fd    *ifd;
79
80
0
  memset(&msg, 0, sizeof(msg));
81
0
  memset(&cmsgbuf, 0, sizeof(cmsgbuf));
82
83
0
  iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
84
0
  iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
85
0
  msg.msg_iov = &iov;
86
0
  msg.msg_iovlen = 1;
87
0
  msg.msg_control = &cmsgbuf.buf;
88
0
  msg.msg_controllen = sizeof(cmsgbuf.buf);
89
90
0
  if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
91
0
    return (-1);
92
93
0
again:
94
0
  if (getdtablecount() + imsg_fd_overhead +
95
0
      (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
96
0
      >= getdtablesize()) {
97
0
    errno = EAGAIN;
98
0
    free(ifd);
99
0
    return (-1);
100
0
  }
101
102
0
  if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
103
0
    if (errno == EINTR)
104
0
      goto again;
105
0
    goto fail;
106
0
  }
107
108
0
  ibuf->r.wpos += n;
109
110
0
  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
111
0
      cmsg = CMSG_NXTHDR(&msg, cmsg)) {
112
0
    if (cmsg->cmsg_level == SOL_SOCKET &&
113
0
        cmsg->cmsg_type == SCM_RIGHTS) {
114
0
      int i;
115
0
      int j;
116
117
      /*
118
       * We only accept one file descriptor.  Due to C
119
       * padding rules, our control buffer might contain
120
       * more than one fd, and we must close them.
121
       */
122
0
      j = ((char *)cmsg + cmsg->cmsg_len -
123
0
          (char *)CMSG_DATA(cmsg)) / sizeof(int);
124
0
      for (i = 0; i < j; i++) {
125
0
        fd = ((int *)CMSG_DATA(cmsg))[i];
126
0
        if (ifd != NULL) {
127
0
          ifd->fd = fd;
128
0
          TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
129
0
              entry);
130
0
          ifd = NULL;
131
0
        } else
132
0
          close(fd);
133
0
      }
134
0
    }
135
    /* we do not handle other ctl data level */
136
0
  }
137
138
0
fail:
139
0
  free(ifd);
140
0
  return (n);
141
0
}
142
#endif
143
144
ssize_t
145
imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
146
0
{
147
0
  size_t       av, left, datalen;
148
149
0
  av = ibuf->r.wpos;
150
151
0
  if (IMSG_HEADER_SIZE > av)
152
0
    return (0);
153
154
0
  memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
155
0
  if (imsg->hdr.len < IMSG_HEADER_SIZE ||
156
0
      imsg->hdr.len > MAX_IMSGSIZE) {
157
0
    errno = ERANGE;
158
0
    return (-1);
159
0
  }
160
0
  if (imsg->hdr.len > av)
161
0
    return (0);
162
0
  datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
163
0
  ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
164
0
  if (datalen == 0)
165
0
    imsg->data = NULL;
166
0
  else if ((imsg->data = malloc(datalen)) == NULL)
167
0
    return (-1);
168
169
0
  if (imsg->hdr.flags & IMSGF_HASFD)
170
0
    imsg->fd = imsg_get_fd(ibuf);
171
0
  else
172
0
    imsg->fd = -1;
173
174
0
  if (datalen != 0)
175
0
    memcpy(imsg->data, ibuf->r.rptr, datalen);
176
177
0
  if (imsg->hdr.len < av) {
178
0
    left = av - imsg->hdr.len;
179
0
    memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
180
0
    ibuf->r.wpos = left;
181
0
  } else
182
0
    ibuf->r.wpos = 0;
183
184
0
  return (datalen + IMSG_HEADER_SIZE);
185
0
}
186
187
int
188
imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
189
    int fd, const void *data, uint16_t datalen)
190
0
{
191
0
  struct ibuf *wbuf;
192
193
0
  if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
194
0
    return (-1);
195
196
0
  if (imsg_add(wbuf, data, datalen) == -1)
197
0
    return (-1);
198
199
0
  ibuf_fd_set(wbuf, fd);
200
201
0
  imsg_close(ibuf, wbuf);
202
203
0
  return (1);
204
0
}
205
206
int
207
imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
208
    int fd, const struct iovec *iov, int iovcnt)
209
0
{
210
0
  struct ibuf *wbuf;
211
0
  int    i, datalen = 0;
212
213
0
  for (i = 0; i < iovcnt; i++)
214
0
    datalen += iov[i].iov_len;
215
216
0
  if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
217
0
    return (-1);
218
219
0
  for (i = 0; i < iovcnt; i++)
220
0
    if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
221
0
      return (-1);
222
223
0
  ibuf_fd_set(wbuf, fd);
224
225
0
  imsg_close(ibuf, wbuf);
226
227
0
  return (1);
228
0
}
229
230
int
231
imsg_compose_ibuf(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid,
232
    pid_t pid, struct ibuf *buf)
233
0
{
234
0
  struct ibuf *wbuf = NULL;
235
0
  struct imsg_hdr  hdr;
236
0
  int save_errno;
237
238
0
  if (ibuf_size(buf) + IMSG_HEADER_SIZE > MAX_IMSGSIZE) {
239
0
    errno = ERANGE;
240
0
    goto fail;
241
0
  }
242
243
0
  hdr.type = type;
244
0
  hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE;
245
0
  hdr.flags = 0;
246
0
  hdr.peerid = peerid;
247
0
  if ((hdr.pid = pid) == 0)
248
0
    hdr.pid = ibuf->pid;
249
250
0
  if ((wbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
251
0
    goto fail;
252
0
  if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
253
0
    goto fail;
254
255
0
  ibuf_close(&ibuf->w, wbuf);
256
0
  ibuf_close(&ibuf->w, buf);
257
0
  return (1);
258
259
0
 fail:
260
0
  save_errno = errno;
261
0
  ibuf_free(buf);
262
0
  ibuf_free(wbuf);
263
0
  errno = save_errno;
264
0
  return (-1);
265
0
}
266
267
struct ibuf *
268
imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
269
    uint16_t datalen)
270
0
{
271
0
  struct ibuf *wbuf;
272
0
  struct imsg_hdr  hdr;
273
274
0
  datalen += IMSG_HEADER_SIZE;
275
0
  if (datalen > MAX_IMSGSIZE) {
276
0
    errno = ERANGE;
277
0
    return (NULL);
278
0
  }
279
280
0
  hdr.type = type;
281
0
  hdr.flags = 0;
282
0
  hdr.peerid = peerid;
283
0
  if ((hdr.pid = pid) == 0)
284
0
    hdr.pid = ibuf->pid;
285
0
  if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
286
0
    return (NULL);
287
0
  }
288
0
  if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
289
0
    return (NULL);
290
291
0
  return (wbuf);
292
0
}
293
294
int
295
imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
296
0
{
297
0
  if (datalen)
298
0
    if (ibuf_add(msg, data, datalen) == -1) {
299
0
      ibuf_free(msg);
300
0
      return (-1);
301
0
    }
302
0
  return (datalen);
303
0
}
304
305
void
306
imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
307
0
{
308
0
  struct imsg_hdr *hdr;
309
310
0
  hdr = (struct imsg_hdr *)msg->buf;
311
312
0
  hdr->flags &= ~IMSGF_HASFD;
313
0
  if (ibuf_fd_avail(msg))
314
0
    hdr->flags |= IMSGF_HASFD;
315
0
  hdr->len = ibuf_size(msg);
316
317
0
  ibuf_close(&ibuf->w, msg);
318
0
}
319
320
void
321
imsg_free(struct imsg *imsg)
322
0
{
323
0
  freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
324
0
}
325
326
static int
327
imsg_get_fd(struct imsgbuf *ibuf)
328
0
{
329
0
  int    fd;
330
0
  struct imsg_fd  *ifd;
331
332
0
  if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
333
0
    return (-1);
334
335
0
  fd = ifd->fd;
336
0
  TAILQ_REMOVE(&ibuf->fds, ifd, entry);
337
0
  free(ifd);
338
339
0
  return (fd);
340
0
}
341
342
int
343
imsg_flush(struct imsgbuf *ibuf)
344
0
{
345
0
  while (ibuf->w.queued)
346
0
    if (msgbuf_write(&ibuf->w) <= 0)
347
0
      return (-1);
348
0
  return (0);
349
0
}
350
351
void
352
imsg_clear(struct imsgbuf *ibuf)
353
0
{
354
0
  int fd;
355
356
0
  msgbuf_clear(&ibuf->w);
357
0
  while ((fd = imsg_get_fd(ibuf)) != -1)
358
0
    close(fd);
359
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/imsg.h.html b/coverage/latest/report/linux/src/openiked-portable/compat/imsg.h.html index e79c4f111..dd8462226 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/imsg.h.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/imsg.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/imsg.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg.h,v 1.7 2023/06/19 17:19:50 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
5
 * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
6
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#ifndef _IMSG_H_
22
#define _IMSG_H_
23
24
#include <stdint.h>
25
26
#define IBUF_READ_SIZE    65535
27
0
#define IMSG_HEADER_SIZE  sizeof(struct imsg_hdr)
28
0
#define MAX_IMSGSIZE    16384
29
30
struct ibuf {
31
  TAILQ_ENTRY(ibuf)  entry;
32
  unsigned char   *buf;
33
  size_t       size;
34
  size_t       max;
35
  size_t       wpos;
36
  size_t       rpos;
37
  int      fd;
38
};
39
40
struct msgbuf {
41
  TAILQ_HEAD(, ibuf)   bufs;
42
  uint32_t     queued;
43
  int      fd;
44
};
45
46
struct ibuf_read {
47
  unsigned char    buf[IBUF_READ_SIZE];
48
  unsigned char   *rptr;
49
  size_t       wpos;
50
};
51
52
struct imsg_fd {
53
  TAILQ_ENTRY(imsg_fd)  entry;
54
  int     fd;
55
};
56
57
struct imsgbuf {
58
  TAILQ_HEAD(, imsg_fd)  fds;
59
  struct ibuf_read   r;
60
  struct msgbuf    w;
61
  int      fd;
62
  pid_t      pid;
63
};
64
65
0
#define IMSGF_HASFD 1
66
67
struct imsg_hdr {
68
  uint32_t   type;
69
  uint16_t   len;
70
  uint16_t   flags;
71
  uint32_t   peerid;
72
  uint32_t   pid;
73
};
74
75
struct imsg {
76
  struct imsg_hdr  hdr;
77
  int    fd;
78
  void    *data;
79
};
80
81
struct iovec;
82
83
/* imsg-buffer.c */
84
struct ibuf *ibuf_open(size_t);
85
struct ibuf *ibuf_dynamic(size_t, size_t);
86
int    ibuf_add(struct ibuf *, const void *, size_t);
87
int    ibuf_add_buf(struct ibuf *, const struct ibuf *);
88
int    ibuf_add_zero(struct ibuf *, size_t);
89
int    ibuf_add_n8(struct ibuf *, uint64_t);
90
int    ibuf_add_n16(struct ibuf *, uint64_t);
91
int    ibuf_add_n32(struct ibuf *, uint64_t);
92
int    ibuf_add_n64(struct ibuf *, uint64_t);
93
void    *ibuf_reserve(struct ibuf *, size_t);
94
void    *ibuf_seek(struct ibuf *, size_t, size_t);
95
int    ibuf_set(struct ibuf *, size_t, const void *, size_t);
96
int    ibuf_set_n8(struct ibuf *, size_t, uint64_t);
97
int    ibuf_set_n16(struct ibuf *, size_t, uint64_t);
98
int    ibuf_set_n32(struct ibuf *, size_t, uint64_t);
99
int    ibuf_set_n64(struct ibuf *, size_t, uint64_t);
100
void    *ibuf_data(struct ibuf *);
101
size_t     ibuf_size(struct ibuf *);
102
size_t     ibuf_left(struct ibuf *);
103
void     ibuf_close(struct msgbuf *, struct ibuf *);
104
void     ibuf_free(struct ibuf *);
105
int    ibuf_fd_avail(struct ibuf *);
106
int    ibuf_fd_get(struct ibuf *);
107
void     ibuf_fd_set(struct ibuf *, int);
108
int    ibuf_write(struct msgbuf *);
109
void     msgbuf_init(struct msgbuf *);
110
void     msgbuf_clear(struct msgbuf *);
111
int    msgbuf_write(struct msgbuf *);
112
113
/* imsg.c */
114
void   imsg_init(struct imsgbuf *, int);
115
ssize_t  imsg_read(struct imsgbuf *);
116
ssize_t  imsg_get(struct imsgbuf *, struct imsg *);
117
int  imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
118
      const void *, uint16_t);
119
int  imsg_composev(struct imsgbuf *, uint32_t, uint32_t,  pid_t, int,
120
      const struct iovec *, int);
121
int  imsg_compose_ibuf(struct imsgbuf *, uint32_t, uint32_t, pid_t,
122
      struct ibuf *);
123
struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t);
124
int  imsg_add(struct ibuf *, const void *, uint16_t);
125
void   imsg_close(struct imsgbuf *, struct ibuf *);
126
void   imsg_free(struct imsg *);
127
int  imsg_flush(struct imsgbuf *);
128
void   imsg_clear(struct imsgbuf *);
129
130
#endif
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/imsg.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg.h,v 1.7 2023/06/19 17:19:50 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
5
 * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
6
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#ifndef _IMSG_H_
22
#define _IMSG_H_
23
24
#include <stdint.h>
25
26
#define IBUF_READ_SIZE    65535
27
0
#define IMSG_HEADER_SIZE  sizeof(struct imsg_hdr)
28
0
#define MAX_IMSGSIZE    16384
29
30
struct ibuf {
31
  TAILQ_ENTRY(ibuf)  entry;
32
  unsigned char   *buf;
33
  size_t       size;
34
  size_t       max;
35
  size_t       wpos;
36
  size_t       rpos;
37
  int      fd;
38
};
39
40
struct msgbuf {
41
  TAILQ_HEAD(, ibuf)   bufs;
42
  uint32_t     queued;
43
  int      fd;
44
};
45
46
struct ibuf_read {
47
  unsigned char    buf[IBUF_READ_SIZE];
48
  unsigned char   *rptr;
49
  size_t       wpos;
50
};
51
52
struct imsg_fd {
53
  TAILQ_ENTRY(imsg_fd)  entry;
54
  int     fd;
55
};
56
57
struct imsgbuf {
58
  TAILQ_HEAD(, imsg_fd)  fds;
59
  struct ibuf_read   r;
60
  struct msgbuf    w;
61
  int      fd;
62
  pid_t      pid;
63
};
64
65
0
#define IMSGF_HASFD 1
66
67
struct imsg_hdr {
68
  uint32_t   type;
69
  uint16_t   len;
70
  uint16_t   flags;
71
  uint32_t   peerid;
72
  uint32_t   pid;
73
};
74
75
struct imsg {
76
  struct imsg_hdr  hdr;
77
  int    fd;
78
  void    *data;
79
};
80
81
struct iovec;
82
83
/* imsg-buffer.c */
84
struct ibuf *ibuf_open(size_t);
85
struct ibuf *ibuf_dynamic(size_t, size_t);
86
int    ibuf_add(struct ibuf *, const void *, size_t);
87
int    ibuf_add_buf(struct ibuf *, const struct ibuf *);
88
int    ibuf_add_zero(struct ibuf *, size_t);
89
int    ibuf_add_n8(struct ibuf *, uint64_t);
90
int    ibuf_add_n16(struct ibuf *, uint64_t);
91
int    ibuf_add_n32(struct ibuf *, uint64_t);
92
int    ibuf_add_n64(struct ibuf *, uint64_t);
93
void    *ibuf_reserve(struct ibuf *, size_t);
94
void    *ibuf_seek(struct ibuf *, size_t, size_t);
95
int    ibuf_set(struct ibuf *, size_t, const void *, size_t);
96
int    ibuf_set_n8(struct ibuf *, size_t, uint64_t);
97
int    ibuf_set_n16(struct ibuf *, size_t, uint64_t);
98
int    ibuf_set_n32(struct ibuf *, size_t, uint64_t);
99
int    ibuf_set_n64(struct ibuf *, size_t, uint64_t);
100
void    *ibuf_data(struct ibuf *);
101
size_t     ibuf_size(struct ibuf *);
102
size_t     ibuf_left(struct ibuf *);
103
void     ibuf_close(struct msgbuf *, struct ibuf *);
104
void     ibuf_free(struct ibuf *);
105
int    ibuf_fd_avail(struct ibuf *);
106
int    ibuf_fd_get(struct ibuf *);
107
void     ibuf_fd_set(struct ibuf *, int);
108
int    ibuf_write(struct msgbuf *);
109
void     msgbuf_init(struct msgbuf *);
110
void     msgbuf_clear(struct msgbuf *);
111
int    msgbuf_write(struct msgbuf *);
112
113
/* imsg.c */
114
void   imsg_init(struct imsgbuf *, int);
115
ssize_t  imsg_read(struct imsgbuf *);
116
ssize_t  imsg_get(struct imsgbuf *, struct imsg *);
117
int  imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
118
      const void *, uint16_t);
119
int  imsg_composev(struct imsgbuf *, uint32_t, uint32_t,  pid_t, int,
120
      const struct iovec *, int);
121
int  imsg_compose_ibuf(struct imsgbuf *, uint32_t, uint32_t, pid_t,
122
      struct ibuf *);
123
struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t);
124
int  imsg_add(struct ibuf *, const void *, uint16_t);
125
void   imsg_close(struct imsgbuf *, struct ibuf *);
126
void   imsg_free(struct imsg *);
127
int  imsg_flush(struct imsgbuf *);
128
void   imsg_clear(struct imsgbuf *);
129
130
#endif
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/openbsd-compat.h.html b/coverage/latest/report/linux/src/openiked-portable/compat/openbsd-compat.h.html index dc92ef62a..89f8dc6ba 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/openbsd-compat.h.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/openbsd-compat.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/openbsd-compat.h
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#ifndef _OPENBSD_COMPAT_H
4
#define _OPENBSD_COMPAT_H
5
6
#define YYSTYPE_IS_DECLARED 1 /* for bison */
7
8
#ifndef LOGIN_NAME_MAX
9
# define LOGIN_NAME_MAX 9
10
#endif
11
12
#include <stdlib.h>
13
14
#if !defined(HAVE_STRLCAT)
15
size_t strlcat(char *, const char *, size_t);
16
#endif
17
18
#if !defined(HAVE_STRLCPY)
19
size_t strlcpy(char *, const char *, size_t);
20
#endif
21
22
#if !defined(HAVE_REALLOCARRAY)
23
void *reallocarray(void *, size_t, size_t);
24
#endif
25
26
#if !defined(HAVE_RECALLOCARRAY)
27
void *recallocarray(void *, size_t, size_t, size_t);
28
#endif
29
30
#if !defined(HAVE_EXPLICIT_BZERO)
31
void explicit_bzero(void *, size_t);
32
#endif
33
34
#if !defined(HAVE_GETPAGESIZE)
35
int getpagesize(void);
36
#endif
37
38
#if !defined(HAVE_TIMINGSAFE_BCMP)
39
int timingsafe_bcmp(const void *, const void *, size_t);
40
#endif
41
42
#if !defined(HAVE_ACCEPT4)
43
#include <sys/socket.h>
44
#define accept4 bsd_accept4
45
int bsd_accept4(int, struct sockaddr *, socklen_t *, int flags);
46
#endif
47
48
#if !defined(HAVE_SOCK_NONBLOCK)
49
#define SOCK_NONBLOCK 0x4000  /* Set O_NONBLOCK */
50
#define SOCK_CLOEXEC  0x8000  /* Set FD_CLOEXEC */
51
#define SOCK_SETFLAGS 0xf000  /* Set flags as checked above */
52
#define socket bsd_socket
53
int bsd_socket(int domain, int type, int protocol);
54
#endif
55
56
#if !defined(HAVE_SETPROCTITLE)
57
void compat_init_setproctitle(int argc, char *argv[]);
58
void setproctitle(const char *fmt, ...);
59
#endif
60
61
#if !defined(HAVE_SETRESGID)
62
int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
63
#endif
64
65
#if !defined(HAVE_SETRESUID)
66
int setresuid(uid_t ruid, uid_t euid, uid_t suid);
67
#endif
68
69
#ifdef _WIN32
70
#include <direct.h>
71
uid_t geteuid(void);
72
#endif
73
74
#if !defined(HAVE_GETRTABLE)
75
int getrtable(void);
76
#endif
77
78
#if !defined(HAVE_SETRTABLE)
79
int setrtable(int rtableid);
80
#endif
81
82
#if !defined(HAVE_STRTONUM)
83
long long
84
strtonum(const char *nptr, long long minval, long long maxval,
85
    const char **errstr);
86
#endif
87
88
#if !defined(HAVE_FREEZERO)
89
void freezero(void *ptr, size_t size);
90
#endif
91
92
#if !defined(HAVE_GETDTABLECOUNT)
93
int getdtablecount(void);
94
#endif
95
96
#if !defined(HAVE_GETOPT)
97
#include "getopt.h"
98
#endif
99
100
#if !defined(HAVE_USLEEP)
101
int usleep(unsigned int x);
102
#endif
103
104
#ifdef HAVE_SOCKADDR_SA_LEN
105
#ifndef SA_LEN
106
#define SA_LEN(sa)      (sa)->sa_len
107
#endif
108
#ifndef SS_LEN
109
#define SS_LEN(ss)      (ss).ss_len
110
#endif
111
#else
112
#define SA_LEN(sa)                  \
113
19.8k
  ((sa->sa_family == AF_INET)  ? sizeof(struct sockaddr_in) :  \
114
19.8k
  (sa->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) :  \
115
2.63k
  sizeof(struct sockaddr))
116
#define SS_LEN(ss)              \
117
  ((ss.ss_family == AF_INET)  ? sizeof(struct sockaddr_in) :  \
118
  (ss.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) :  \
119
  sizeof(struct sockaddr_storage))
120
#endif
121
122
#ifndef HAVE_FFS
123
int ffs(int);
124
#endif
125
126
#ifdef __OpenBSD__
127
typedef int evutil_socket_t;
128
#endif
129
130
#ifndef _PASSWORD_LEN
131
#define _PASSWORD_LEN 120
132
#endif
133
134
#ifdef HAVE_DIRENT_H
135
# include <dirent.h>
136
# define NAMLEN(dirent) strlen((dirent)->d_name)
137
#else
138
# define dirent direct
139
# define NAMLEN(dirent) (dirent)->d_namlen
140
# ifdef HAVE_SYS_NDIR_H
141
#  include <sys/ndir.h>
142
# endif
143
# ifdef HAVE_SYS_DIR_H
144
#  include <sys/dir.h>
145
# endif
146
# ifdef HAVE_NDIR_H
147
#  include <ndir.h>
148
# endif
149
#endif
150
151
#if !defined(AF_LINK) && defined(AF_PACKET)
152
#define AF_LINK AF_PACKET /* XXX workaround on Linux */
153
#endif
154
155
#ifndef HOST_NAME_MAX
156
# include "netdb.h" /* for MAXHOSTNAMELEN */
157
# if defined(_POSIX_HOST_NAME_MAX)
158
#  define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
159
# elif defined(MAXHOSTNAMELEN)
160
#  define HOST_NAME_MAX MAXHOSTNAMELEN
161
# else
162
#  define HOST_NAME_MAX 255
163
# endif
164
#endif /* HOST_NAME_MAX */
165
166
/* FreeBSD */
167
#ifndef CPI_PRIVATE_MIN
168
#define CPI_PRIVATE_MIN   61440
169
#endif
170
#ifndef CPI_PRIVATE_MAX
171
#define CPI_PRIVATE_MAX   65535
172
#endif
173
174
#if !defined(SADB_X_ADDFLOW) && defined(SADB_X_SPDUPDATE)
175
#define SADB_X_ADDFLOW  SADB_X_SPDUPDATE
176
#endif
177
#if !defined(SADB_X_DELFLOW) && defined(SADB_X_SPDDELETE)
178
#define SADB_X_DELFLOW  SADB_X_SPDDELETE
179
#endif
180
#if !defined(SADB_X_FLOW_TYPE_DENY)
181
#define SADB_X_FLOW_TYPE_DENY 1
182
#endif
183
184
#if defined(HAVE_LINUX_PFKEY_H)
185
/* Encryption Algorithms */
186
#define SADB_X_EALG_AES   SADB_X_EALG_AESCBC
187
#define SADB_X_EALG_AESGCM16  SADB_X_EALG_AES_GCM_ICV16
188
#define SADB_X_EALG_AESGMAC SADB_X_EALG_NULL_AES_GMAC
189
190
/* Authentication Algorithms */
191
#define SADB_X_AALG_SHA2_256  SADB_X_AALG_SHA2_256HMAC
192
#define SADB_X_AALG_SHA2_384  SADB_X_AALG_SHA2_384HMAC
193
#define SADB_X_AALG_SHA2_512  SADB_X_AALG_SHA2_512HMAC
194
#endif
195
196
#if !defined(__packed)
197
#define __packed  __attribute__((__packed__))
198
#endif
199
200
#if defined(HAVE_APPLE_NATT) && !defined(SADB_X_EXT_NATT)
201
/*
202
 * These are hidden in Apple XNU's private pfkeyv2.h header
203
 */
204
#define SADB_X_EXT_NATT     0x0002  /* Enable UDP encapsulation */
205
#define SADB_X_EXT_NATT_KEEPALIVE 0x0004  /* Send NAT-T keepalives */
206
#define SADB_X_EXT_NATT_MULTIPLEUSERS 0x0008  /* Use for VPN gateways */
207
#define SADB_X_EXT_NATT_DETECTED_PEER 0x1000  /* Opposite of KEEPALIVE */
208
209
struct sadb_sa_natt {
210
  uint16_t   sadb_sa_natt_port;
211
  union {
212
    uint16_t   sadb_reserved0;
213
    uint16_t   sadb_sa_natt_interval;
214
  };
215
  uint16_t   sadb_sa_natt_offload_interval;
216
  uint16_t   sadb_sa_natt_src_port;
217
};
218
#endif
219
220
#endif /* !_OPENBSD_COMPAT_H */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/openbsd-compat.h
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#ifndef _OPENBSD_COMPAT_H
4
#define _OPENBSD_COMPAT_H
5
6
#define YYSTYPE_IS_DECLARED 1 /* for bison */
7
8
#ifndef LOGIN_NAME_MAX
9
# define LOGIN_NAME_MAX 9
10
#endif
11
12
#include <stdlib.h>
13
14
#if !defined(HAVE_STRLCAT)
15
size_t strlcat(char *, const char *, size_t);
16
#endif
17
18
#if !defined(HAVE_STRLCPY)
19
size_t strlcpy(char *, const char *, size_t);
20
#endif
21
22
#if !defined(HAVE_REALLOCARRAY)
23
void *reallocarray(void *, size_t, size_t);
24
#endif
25
26
#if !defined(HAVE_RECALLOCARRAY)
27
void *recallocarray(void *, size_t, size_t, size_t);
28
#endif
29
30
#if !defined(HAVE_EXPLICIT_BZERO)
31
void explicit_bzero(void *, size_t);
32
#endif
33
34
#if !defined(HAVE_GETPAGESIZE)
35
int getpagesize(void);
36
#endif
37
38
#if !defined(HAVE_TIMINGSAFE_BCMP)
39
int timingsafe_bcmp(const void *, const void *, size_t);
40
#endif
41
42
#if !defined(HAVE_ACCEPT4)
43
#include <sys/socket.h>
44
#define accept4 bsd_accept4
45
int bsd_accept4(int, struct sockaddr *, socklen_t *, int flags);
46
#endif
47
48
#if !defined(HAVE_SOCK_NONBLOCK)
49
#define SOCK_NONBLOCK 0x4000  /* Set O_NONBLOCK */
50
#define SOCK_CLOEXEC  0x8000  /* Set FD_CLOEXEC */
51
#define SOCK_SETFLAGS 0xf000  /* Set flags as checked above */
52
#define socket bsd_socket
53
int bsd_socket(int domain, int type, int protocol);
54
#endif
55
56
#if !defined(HAVE_SETPROCTITLE)
57
void compat_init_setproctitle(int argc, char *argv[]);
58
void setproctitle(const char *fmt, ...);
59
#endif
60
61
#if !defined(HAVE_SETRESGID)
62
int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
63
#endif
64
65
#if !defined(HAVE_SETRESUID)
66
int setresuid(uid_t ruid, uid_t euid, uid_t suid);
67
#endif
68
69
#ifdef _WIN32
70
#include <direct.h>
71
uid_t geteuid(void);
72
#endif
73
74
#if !defined(HAVE_GETRTABLE)
75
int getrtable(void);
76
#endif
77
78
#if !defined(HAVE_SETRTABLE)
79
int setrtable(int rtableid);
80
#endif
81
82
#if !defined(HAVE_STRTONUM)
83
long long
84
strtonum(const char *nptr, long long minval, long long maxval,
85
    const char **errstr);
86
#endif
87
88
#if !defined(HAVE_FREEZERO)
89
void freezero(void *ptr, size_t size);
90
#endif
91
92
#if !defined(HAVE_GETDTABLECOUNT)
93
int getdtablecount(void);
94
#endif
95
96
#if !defined(HAVE_GETOPT)
97
#include "getopt.h"
98
#endif
99
100
#if !defined(HAVE_USLEEP)
101
int usleep(unsigned int x);
102
#endif
103
104
#ifdef HAVE_SOCKADDR_SA_LEN
105
#ifndef SA_LEN
106
#define SA_LEN(sa)      (sa)->sa_len
107
#endif
108
#ifndef SS_LEN
109
#define SS_LEN(ss)      (ss).ss_len
110
#endif
111
#else
112
#define SA_LEN(sa)                  \
113
19.8k
  ((sa->sa_family == AF_INET)  ? sizeof(struct sockaddr_in) :  \
114
19.8k
  (sa->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) :  \
115
2.63k
  sizeof(struct sockaddr))
116
#define SS_LEN(ss)              \
117
  ((ss.ss_family == AF_INET)  ? sizeof(struct sockaddr_in) :  \
118
  (ss.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) :  \
119
  sizeof(struct sockaddr_storage))
120
#endif
121
122
#ifndef HAVE_FFS
123
int ffs(int);
124
#endif
125
126
#ifdef __OpenBSD__
127
typedef int evutil_socket_t;
128
#endif
129
130
#ifndef _PASSWORD_LEN
131
#define _PASSWORD_LEN 120
132
#endif
133
134
#ifdef HAVE_DIRENT_H
135
# include <dirent.h>
136
# define NAMLEN(dirent) strlen((dirent)->d_name)
137
#else
138
# define dirent direct
139
# define NAMLEN(dirent) (dirent)->d_namlen
140
# ifdef HAVE_SYS_NDIR_H
141
#  include <sys/ndir.h>
142
# endif
143
# ifdef HAVE_SYS_DIR_H
144
#  include <sys/dir.h>
145
# endif
146
# ifdef HAVE_NDIR_H
147
#  include <ndir.h>
148
# endif
149
#endif
150
151
#if !defined(AF_LINK) && defined(AF_PACKET)
152
#define AF_LINK AF_PACKET /* XXX workaround on Linux */
153
#endif
154
155
#ifndef HOST_NAME_MAX
156
# include "netdb.h" /* for MAXHOSTNAMELEN */
157
# if defined(_POSIX_HOST_NAME_MAX)
158
#  define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
159
# elif defined(MAXHOSTNAMELEN)
160
#  define HOST_NAME_MAX MAXHOSTNAMELEN
161
# else
162
#  define HOST_NAME_MAX 255
163
# endif
164
#endif /* HOST_NAME_MAX */
165
166
/* FreeBSD */
167
#ifndef CPI_PRIVATE_MIN
168
#define CPI_PRIVATE_MIN   61440
169
#endif
170
#ifndef CPI_PRIVATE_MAX
171
#define CPI_PRIVATE_MAX   65535
172
#endif
173
174
#if !defined(SADB_X_ADDFLOW) && defined(SADB_X_SPDUPDATE)
175
#define SADB_X_ADDFLOW  SADB_X_SPDUPDATE
176
#endif
177
#if !defined(SADB_X_DELFLOW) && defined(SADB_X_SPDDELETE)
178
#define SADB_X_DELFLOW  SADB_X_SPDDELETE
179
#endif
180
#if !defined(SADB_X_FLOW_TYPE_DENY)
181
#define SADB_X_FLOW_TYPE_DENY 1
182
#endif
183
184
#if defined(HAVE_LINUX_PFKEY_H)
185
/* Encryption Algorithms */
186
#define SADB_X_EALG_AES   SADB_X_EALG_AESCBC
187
#define SADB_X_EALG_AESGCM16  SADB_X_EALG_AES_GCM_ICV16
188
#define SADB_X_EALG_AESGMAC SADB_X_EALG_NULL_AES_GMAC
189
190
/* Authentication Algorithms */
191
#define SADB_X_AALG_SHA2_256  SADB_X_AALG_SHA2_256HMAC
192
#define SADB_X_AALG_SHA2_384  SADB_X_AALG_SHA2_384HMAC
193
#define SADB_X_AALG_SHA2_512  SADB_X_AALG_SHA2_512HMAC
194
#endif
195
196
#if !defined(__packed)
197
#define __packed  __attribute__((__packed__))
198
#endif
199
200
#if defined(HAVE_APPLE_NATT) && !defined(SADB_X_EXT_NATT)
201
/*
202
 * These are hidden in Apple XNU's private pfkeyv2.h header
203
 */
204
#define SADB_X_EXT_NATT     0x0002  /* Enable UDP encapsulation */
205
#define SADB_X_EXT_NATT_KEEPALIVE 0x0004  /* Send NAT-T keepalives */
206
#define SADB_X_EXT_NATT_MULTIPLEUSERS 0x0008  /* Use for VPN gateways */
207
#define SADB_X_EXT_NATT_DETECTED_PEER 0x1000  /* Opposite of KEEPALIVE */
208
209
struct sadb_sa_natt {
210
  uint16_t   sadb_sa_natt_port;
211
  union {
212
    uint16_t   sadb_reserved0;
213
    uint16_t   sadb_sa_natt_interval;
214
  };
215
  uint16_t   sadb_sa_natt_offload_interval;
216
  uint16_t   sadb_sa_natt_src_port;
217
};
218
#endif
219
220
#endif /* !_OPENBSD_COMPAT_H */
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/recallocarray.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/recallocarray.c.html index b6081c675..c6d552364 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/recallocarray.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/recallocarray.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/recallocarray.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: recallocarray.c,v 1.2 2021/03/18 11:16:58 claudio Exp $ */
2
/*
3
 * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
4
 *
5
 * Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <errno.h>
19
#include <stdlib.h>
20
#include <stdint.h>
21
#include <string.h>
22
#include <unistd.h>
23
24
/*
25
 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
26
 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
27
 */
28
0
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
29
30
void *
31
recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
32
0
{
33
0
  size_t oldsize, newsize;
34
0
  void *newptr;
35
36
0
  if (ptr == NULL)
37
0
    return calloc(newnmemb, size);
38
39
0
  if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
40
0
      newnmemb > 0 && SIZE_MAX / newnmemb < size) {
41
0
    errno = ENOMEM;
42
0
    return NULL;
43
0
  }
44
0
  newsize = newnmemb * size;
45
46
0
  if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
47
0
      oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
48
0
    errno = EINVAL;
49
0
    return NULL;
50
0
  }
51
0
  oldsize = oldnmemb * size;
52
  
53
  /*
54
   * Don't bother too much if we're shrinking just a bit,
55
   * we do not shrink for series of small steps, oh well.
56
   */
57
0
  if (newsize <= oldsize) {
58
0
    size_t d = oldsize - newsize;
59
60
0
    if (d < oldsize / 2 && d < (size_t)getpagesize()) {
61
0
      memset((char *)ptr + newsize, 0, d);
62
0
      return ptr;
63
0
    }
64
0
  }
65
66
0
  newptr = malloc(newsize);
67
0
  if (newptr == NULL)
68
0
    return NULL;
69
70
0
  if (newsize > oldsize) {
71
0
    memcpy(newptr, ptr, oldsize);
72
0
    memset((char *)newptr + oldsize, 0, newsize - oldsize);
73
0
  } else
74
0
    memcpy(newptr, ptr, newsize);
75
76
0
  explicit_bzero(ptr, oldsize);
77
0
  free(ptr);
78
79
0
  return newptr;
80
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/recallocarray.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: recallocarray.c,v 1.2 2021/03/18 11:16:58 claudio Exp $ */
2
/*
3
 * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
4
 *
5
 * Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <errno.h>
19
#include <stdlib.h>
20
#include <stdint.h>
21
#include <string.h>
22
#include <unistd.h>
23
24
/*
25
 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
26
 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
27
 */
28
0
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
29
30
void *
31
recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
32
0
{
33
0
  size_t oldsize, newsize;
34
0
  void *newptr;
35
36
0
  if (ptr == NULL)
37
0
    return calloc(newnmemb, size);
38
39
0
  if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
40
0
      newnmemb > 0 && SIZE_MAX / newnmemb < size) {
41
0
    errno = ENOMEM;
42
0
    return NULL;
43
0
  }
44
0
  newsize = newnmemb * size;
45
46
0
  if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
47
0
      oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
48
0
    errno = EINVAL;
49
0
    return NULL;
50
0
  }
51
0
  oldsize = oldnmemb * size;
52
  
53
  /*
54
   * Don't bother too much if we're shrinking just a bit,
55
   * we do not shrink for series of small steps, oh well.
56
   */
57
0
  if (newsize <= oldsize) {
58
0
    size_t d = oldsize - newsize;
59
60
0
    if (d < oldsize / 2 && d < (size_t)getpagesize()) {
61
0
      memset((char *)ptr + newsize, 0, d);
62
0
      return ptr;
63
0
    }
64
0
  }
65
66
0
  newptr = malloc(newsize);
67
0
  if (newptr == NULL)
68
0
    return NULL;
69
70
0
  if (newsize > oldsize) {
71
0
    memcpy(newptr, ptr, oldsize);
72
0
    memset((char *)newptr + oldsize, 0, newsize - oldsize);
73
0
  } else
74
0
    memcpy(newptr, ptr, newsize);
75
76
0
  explicit_bzero(ptr, oldsize);
77
0
  free(ptr);
78
79
0
  return newptr;
80
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/setproctitle.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/setproctitle.c.html index 4ba88c549..4ffa27345 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/setproctitle.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/setproctitle.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/setproctitle.c
Line
Count
Source (jump to first uncovered line)
1
/* Based on conf.c from UCB sendmail 8.8.8 */
2
3
/*
4
 * Copyright 2003 Damien Miller
5
 * Copyright (c) 1983, 1995-1997 Eric P. Allman
6
 * Copyright (c) 1988, 1993
7
 *  The Regents of the University of California.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 * 3. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 */
33
34
#include "openbsd-compat.h"
35
36
#ifndef HAVE_SETPROCTITLE
37
38
#include <stdarg.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <unistd.h>
42
#ifdef HAVE_SYS_PSTAT_H
43
#include <sys/pstat.h>
44
#endif
45
#include <string.h>
46
47
#include <vis.h>
48
49
#define SPT_NONE  0 /* don't use it at all */
50
#define SPT_PSTAT 1 /* use pstat(PSTAT_SETCMD, ...) */
51
#define SPT_REUSEARGV 2 /* cover argv with title information */
52
53
#ifndef SPT_TYPE
54
# define SPT_TYPE SPT_NONE
55
#endif
56
57
#ifndef SPT_PADCHAR
58
0
# define SPT_PADCHAR  '\0'
59
#endif
60
61
#if SPT_TYPE == SPT_REUSEARGV
62
static char *argv_start = NULL;
63
static size_t argv_env_len = 0;
64
#endif
65
66
#endif /* HAVE_SETPROCTITLE */
67
68
void
69
compat_init_setproctitle(int argc, char *argv[])
70
0
{
71
0
#if !defined(HAVE_SETPROCTITLE) && \
72
0
    defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV
73
0
  extern char **environ;
74
0
  char *lastargv = NULL;
75
0
  char **envp = environ;
76
0
  int i;
77
78
  /*
79
   * NB: This assumes that argv has already been copied out of the
80
   * way. This is true for sshd, but may not be true for other
81
   * programs. Beware.
82
   */
83
84
0
  if (argc == 0 || argv[0] == NULL)
85
0
    return;
86
87
  /* Fail if we can't allocate room for the new environment */
88
0
  for (i = 0; envp[i] != NULL; i++)
89
0
    ;
90
0
  if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) {
91
0
    environ = envp; /* put it back */
92
0
    return;
93
0
  }
94
95
  /*
96
   * Find the last argv string or environment variable within
97
   * our process memory area.
98
   */
99
0
  for (i = 0; i < argc; i++) {
100
0
    if (lastargv == NULL || lastargv + 1 == argv[i])
101
0
      lastargv = argv[i] + strlen(argv[i]);
102
0
  }
103
0
  for (i = 0; envp[i] != NULL; i++) {
104
0
    if (lastargv + 1 == envp[i])
105
0
      lastargv = envp[i] + strlen(envp[i]);
106
0
  }
107
108
0
  argv[1] = NULL;
109
0
  argv_start = argv[0];
110
0
  argv_env_len = lastargv - argv[0] - 1;
111
112
  /*
113
   * Copy environment
114
   * XXX - will truncate env on strdup fail
115
   */
116
0
  for (i = 0; envp[i] != NULL; i++)
117
0
    environ[i] = strdup(envp[i]);
118
0
  environ[i] = NULL;
119
0
#endif /* SPT_REUSEARGV */
120
0
}
121
122
#ifndef HAVE_SETPROCTITLE
123
void
124
setproctitle(const char *fmt, ...)
125
0
{
126
0
#if SPT_TYPE != SPT_NONE
127
0
  va_list ap;
128
0
  char buf[1024], ptitle[1024];
129
0
  size_t len = 0;
130
0
  int r;
131
0
  extern char *__progname;
132
#if SPT_TYPE == SPT_PSTAT
133
  union pstun pst;
134
#endif
135
136
0
#if SPT_TYPE == SPT_REUSEARGV
137
0
  if (argv_env_len <= 0)
138
0
    return;
139
0
#endif
140
141
0
  strlcpy(buf, __progname, sizeof(buf));
142
143
0
  r = -1;
144
0
  va_start(ap, fmt);
145
0
  if (fmt != NULL) {
146
0
    len = strlcat(buf, ": ", sizeof(buf));
147
0
    if (len < sizeof(buf))
148
0
      r = vsnprintf(buf + len, sizeof(buf) - len , fmt, ap);
149
0
  }
150
0
  va_end(ap);
151
0
  if (r == -1 || (size_t)r >= sizeof(buf) - len)
152
0
    return;
153
0
  strnvis(ptitle, buf, sizeof(ptitle),
154
0
      VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL);
155
156
#if SPT_TYPE == SPT_PSTAT
157
  pst.pst_command = ptitle;
158
  pstat(PSTAT_SETCMD, pst, strlen(ptitle), 0, 0);
159
#elif SPT_TYPE == SPT_REUSEARGV
160
/*  debug("setproctitle: copy \"%s\" into len %d",
161
      buf, argv_env_len); */
162
0
  len = strlcpy(argv_start, ptitle, argv_env_len);
163
0
  for(; len < argv_env_len; len++)
164
0
    argv_start[len] = SPT_PADCHAR;
165
0
#endif
166
167
0
#endif /* SPT_NONE */
168
0
}
169
170
#endif /* HAVE_SETPROCTITLE */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/setproctitle.c
Line
Count
Source (jump to first uncovered line)
1
/* Based on conf.c from UCB sendmail 8.8.8 */
2
3
/*
4
 * Copyright 2003 Damien Miller
5
 * Copyright (c) 1983, 1995-1997 Eric P. Allman
6
 * Copyright (c) 1988, 1993
7
 *  The Regents of the University of California.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 * 3. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 */
33
34
#include "openbsd-compat.h"
35
36
#ifndef HAVE_SETPROCTITLE
37
38
#include <stdarg.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <unistd.h>
42
#ifdef HAVE_SYS_PSTAT_H
43
#include <sys/pstat.h>
44
#endif
45
#include <string.h>
46
47
#include <vis.h>
48
49
#define SPT_NONE  0 /* don't use it at all */
50
#define SPT_PSTAT 1 /* use pstat(PSTAT_SETCMD, ...) */
51
#define SPT_REUSEARGV 2 /* cover argv with title information */
52
53
#ifndef SPT_TYPE
54
# define SPT_TYPE SPT_NONE
55
#endif
56
57
#ifndef SPT_PADCHAR
58
0
# define SPT_PADCHAR  '\0'
59
#endif
60
61
#if SPT_TYPE == SPT_REUSEARGV
62
static char *argv_start = NULL;
63
static size_t argv_env_len = 0;
64
#endif
65
66
#endif /* HAVE_SETPROCTITLE */
67
68
void
69
compat_init_setproctitle(int argc, char *argv[])
70
0
{
71
0
#if !defined(HAVE_SETPROCTITLE) && \
72
0
    defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV
73
0
  extern char **environ;
74
0
  char *lastargv = NULL;
75
0
  char **envp = environ;
76
0
  int i;
77
78
  /*
79
   * NB: This assumes that argv has already been copied out of the
80
   * way. This is true for sshd, but may not be true for other
81
   * programs. Beware.
82
   */
83
84
0
  if (argc == 0 || argv[0] == NULL)
85
0
    return;
86
87
  /* Fail if we can't allocate room for the new environment */
88
0
  for (i = 0; envp[i] != NULL; i++)
89
0
    ;
90
0
  if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) {
91
0
    environ = envp; /* put it back */
92
0
    return;
93
0
  }
94
95
  /*
96
   * Find the last argv string or environment variable within
97
   * our process memory area.
98
   */
99
0
  for (i = 0; i < argc; i++) {
100
0
    if (lastargv == NULL || lastargv + 1 == argv[i])
101
0
      lastargv = argv[i] + strlen(argv[i]);
102
0
  }
103
0
  for (i = 0; envp[i] != NULL; i++) {
104
0
    if (lastargv + 1 == envp[i])
105
0
      lastargv = envp[i] + strlen(envp[i]);
106
0
  }
107
108
0
  argv[1] = NULL;
109
0
  argv_start = argv[0];
110
0
  argv_env_len = lastargv - argv[0] - 1;
111
112
  /*
113
   * Copy environment
114
   * XXX - will truncate env on strdup fail
115
   */
116
0
  for (i = 0; envp[i] != NULL; i++)
117
0
    environ[i] = strdup(envp[i]);
118
0
  environ[i] = NULL;
119
0
#endif /* SPT_REUSEARGV */
120
0
}
121
122
#ifndef HAVE_SETPROCTITLE
123
void
124
setproctitle(const char *fmt, ...)
125
0
{
126
0
#if SPT_TYPE != SPT_NONE
127
0
  va_list ap;
128
0
  char buf[1024], ptitle[1024];
129
0
  size_t len = 0;
130
0
  int r;
131
0
  extern char *__progname;
132
#if SPT_TYPE == SPT_PSTAT
133
  union pstun pst;
134
#endif
135
136
0
#if SPT_TYPE == SPT_REUSEARGV
137
0
  if (argv_env_len <= 0)
138
0
    return;
139
0
#endif
140
141
0
  strlcpy(buf, __progname, sizeof(buf));
142
143
0
  r = -1;
144
0
  va_start(ap, fmt);
145
0
  if (fmt != NULL) {
146
0
    len = strlcat(buf, ": ", sizeof(buf));
147
0
    if (len < sizeof(buf))
148
0
      r = vsnprintf(buf + len, sizeof(buf) - len , fmt, ap);
149
0
  }
150
0
  va_end(ap);
151
0
  if (r == -1 || (size_t)r >= sizeof(buf) - len)
152
0
    return;
153
0
  strnvis(ptitle, buf, sizeof(ptitle),
154
0
      VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL);
155
156
#if SPT_TYPE == SPT_PSTAT
157
  pst.pst_command = ptitle;
158
  pstat(PSTAT_SETCMD, pst, strlen(ptitle), 0, 0);
159
#elif SPT_TYPE == SPT_REUSEARGV
160
/*  debug("setproctitle: copy \"%s\" into len %d",
161
      buf, argv_env_len); */
162
0
  len = strlcpy(argv_start, ptitle, argv_env_len);
163
0
  for(; len < argv_env_len; len++)
164
0
    argv_start[len] = SPT_PADCHAR;
165
0
#endif
166
167
0
#endif /* SPT_NONE */
168
0
}
169
170
#endif /* HAVE_SETPROCTITLE */
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/strlcat.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/strlcat.c.html index 2061b76be..f1bf3a133 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/strlcat.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/strlcat.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/strlcat.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $  */
2
3
/*
4
 * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
/* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */
20
21
#include "openbsd-compat.h"
22
23
#if !defined(HAVE_STRLCAT)
24
25
#include <sys/types.h>
26
#include <string.h>
27
28
/*
29
 * Appends src to string dst of size dsize (unlike strncat, dsize is the
30
 * full size of dst, not space left).  At most dsize-1 characters
31
 * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
32
 * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
33
 * If retval >= dsize, truncation occurred.
34
 */
35
size_t
36
strlcat(char *dst, const char *src, size_t dsize)
37
0
{
38
0
  const char *odst = dst;
39
0
  const char *osrc = src;
40
0
  size_t n = dsize;
41
0
  size_t dlen;
42
43
  /* Find the end of dst and adjust bytes left but don't go past end. */
44
0
  while (n-- != 0 && *dst != '\0')
45
0
    dst++;
46
0
  dlen = dst - odst;
47
0
  n = dsize - dlen;
48
49
0
  if (n-- == 0)
50
0
    return(dlen + strlen(src));
51
0
  while (*src != '\0') {
52
0
    if (n != 0) {
53
0
      *dst++ = *src;
54
0
      n--;
55
0
    }
56
0
    src++;
57
0
  }
58
0
  *dst = '\0';
59
60
0
  return(dlen + (src - osrc));  /* count does not include NUL */
61
0
}
62
63
#endif /* !defined(HAVE_STRLCAT) */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/strlcat.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $  */
2
3
/*
4
 * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
/* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */
20
21
#include "openbsd-compat.h"
22
23
#if !defined(HAVE_STRLCAT)
24
25
#include <sys/types.h>
26
#include <string.h>
27
28
/*
29
 * Appends src to string dst of size dsize (unlike strncat, dsize is the
30
 * full size of dst, not space left).  At most dsize-1 characters
31
 * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
32
 * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
33
 * If retval >= dsize, truncation occurred.
34
 */
35
size_t
36
strlcat(char *dst, const char *src, size_t dsize)
37
0
{
38
0
  const char *odst = dst;
39
0
  const char *osrc = src;
40
0
  size_t n = dsize;
41
0
  size_t dlen;
42
43
  /* Find the end of dst and adjust bytes left but don't go past end. */
44
0
  while (n-- != 0 && *dst != '\0')
45
0
    dst++;
46
0
  dlen = dst - odst;
47
0
  n = dsize - dlen;
48
49
0
  if (n-- == 0)
50
0
    return(dlen + strlen(src));
51
0
  while (*src != '\0') {
52
0
    if (n != 0) {
53
0
      *dst++ = *src;
54
0
      n--;
55
0
    }
56
0
    src++;
57
0
  }
58
0
  *dst = '\0';
59
60
0
  return(dlen + (src - osrc));  /* count does not include NUL */
61
0
}
62
63
#endif /* !defined(HAVE_STRLCAT) */
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/strlcpy.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/strlcpy.c.html index 00cf1d42d..3d13d855a 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/strlcpy.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/strlcpy.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/strlcpy.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $  */
2
3
/*
4
 * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <string.h>
21
22
/*
23
 * Copy string src to buffer dst of size dsize.  At most dsize-1
24
 * chars will be copied.  Always NUL terminates (unless dsize == 0).
25
 * Returns strlen(src); if retval >= dsize, truncation occurred.
26
 */
27
size_t
28
strlcpy(char *dst, const char *src, size_t dsize)
29
577k
{
30
577k
  const char *osrc = src;
31
577k
  size_t nleft = dsize;
32
33
  /* Copy as many bytes as will fit. */
34
577k
  if (nleft != 0) {
35
4.46M
    while (--nleft != 0) {
36
4.45M
      if ((*dst++ = *src++) == '\0')
37
576k
        break;
38
4.45M
    }
39
577k
  }
40
41
  /* Not enough room in dst, add NUL and traverse rest of src. */
42
577k
  if (nleft == 0) {
43
1.45k
    if (dsize != 0)
44
1.45k
      *dst = '\0';   /* NUL-terminate dst */
45
1.45k
    while (*src++)
46
0
      ;
47
1.45k
  }
48
49
577k
  return(src - osrc - 1); /* count does not include NUL */
50
577k
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/strlcpy.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $  */
2
3
/*
4
 * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <string.h>
21
22
/*
23
 * Copy string src to buffer dst of size dsize.  At most dsize-1
24
 * chars will be copied.  Always NUL terminates (unless dsize == 0).
25
 * Returns strlen(src); if retval >= dsize, truncation occurred.
26
 */
27
size_t
28
strlcpy(char *dst, const char *src, size_t dsize)
29
577k
{
30
577k
  const char *osrc = src;
31
577k
  size_t nleft = dsize;
32
33
  /* Copy as many bytes as will fit. */
34
577k
  if (nleft != 0) {
35
4.46M
    while (--nleft != 0) {
36
4.45M
      if ((*dst++ = *src++) == '\0')
37
576k
        break;
38
4.45M
    }
39
577k
  }
40
41
  /* Not enough room in dst, add NUL and traverse rest of src. */
42
577k
  if (nleft == 0) {
43
1.45k
    if (dsize != 0)
44
1.45k
      *dst = '\0';   /* NUL-terminate dst */
45
1.45k
    while (*src++)
46
0
      ;
47
1.45k
  }
48
49
577k
  return(src - osrc - 1); /* count does not include NUL */
50
577k
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/strtonum.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/strtonum.c.html index b7be42a38..ef4d69f03 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/strtonum.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/strtonum.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/strtonum.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther Exp $ */
2
3
/*
4
 * Copyright (c) 2004 Ted Unangst and Todd Miller
5
 * All rights reserved.
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <errno.h>
21
#include <limits.h>
22
#include <stdlib.h>
23
24
0
#define INVALID   1
25
0
#define TOOSMALL  2
26
0
#define TOOLARGE  3
27
28
long long
29
strtonum(const char *numstr, long long minval, long long maxval,
30
    const char **errstrp)
31
0
{
32
0
  long long ll = 0;
33
0
  int error = 0;
34
0
  char *ep;
35
0
  struct errval {
36
0
    const char *errstr;
37
0
    int err;
38
0
  } ev[4] = {
39
0
    { NULL,   0 },
40
0
    { "invalid",  EINVAL },
41
0
    { "too small",  ERANGE },
42
0
    { "too large",  ERANGE },
43
0
  };
44
45
0
  ev[0].err = errno;
46
0
  errno = 0;
47
0
  if (minval > maxval) {
48
0
    error = INVALID;
49
0
  } else {
50
0
    ll = strtoll(numstr, &ep, 10);
51
0
    if (numstr == ep || *ep != '\0')
52
0
      error = INVALID;
53
0
    else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
54
0
      error = TOOSMALL;
55
0
    else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
56
0
      error = TOOLARGE;
57
0
  }
58
0
  if (errstrp != NULL)
59
0
    *errstrp = ev[error].errstr;
60
0
  errno = ev[error].err;
61
0
  if (error)
62
0
    ll = 0;
63
64
0
  return (ll);
65
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/strtonum.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther Exp $ */
2
3
/*
4
 * Copyright (c) 2004 Ted Unangst and Todd Miller
5
 * All rights reserved.
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <errno.h>
21
#include <limits.h>
22
#include <stdlib.h>
23
24
0
#define INVALID   1
25
0
#define TOOSMALL  2
26
0
#define TOOLARGE  3
27
28
long long
29
strtonum(const char *numstr, long long minval, long long maxval,
30
    const char **errstrp)
31
0
{
32
0
  long long ll = 0;
33
0
  int error = 0;
34
0
  char *ep;
35
0
  struct errval {
36
0
    const char *errstr;
37
0
    int err;
38
0
  } ev[4] = {
39
0
    { NULL,   0 },
40
0
    { "invalid",  EINVAL },
41
0
    { "too small",  ERANGE },
42
0
    { "too large",  ERANGE },
43
0
  };
44
45
0
  ev[0].err = errno;
46
0
  errno = 0;
47
0
  if (minval > maxval) {
48
0
    error = INVALID;
49
0
  } else {
50
0
    ll = strtoll(numstr, &ep, 10);
51
0
    if (numstr == ep || *ep != '\0')
52
0
      error = INVALID;
53
0
    else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
54
0
      error = TOOSMALL;
55
0
    else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
56
0
      error = TOOLARGE;
57
0
  }
58
0
  if (errstrp != NULL)
59
0
    *errstrp = ev[error].errstr;
60
0
  errno = ev[error].err;
61
0
  if (error)
62
0
    ll = 0;
63
64
0
  return (ll);
65
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/sys/queue.h.html b/coverage/latest/report/linux/src/openiked-portable/compat/sys/queue.h.html index 7ec06dfbe..f25f3070e 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/sys/queue.h.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/sys/queue.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/sys/queue.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: queue.h,v 1.46 2020/12/30 13:33:12 millert Exp $  */
2
/*  $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
3
4
/*
5
 * Copyright (c) 1991, 1993
6
 *  The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 *
32
 *  @(#)queue.h 8.5 (Berkeley) 8/20/94
33
 */
34
35
#ifndef _SYS_QUEUE_H_
36
#define _SYS_QUEUE_H_
37
38
#include <sys/_null.h>
39
40
/*
41
 * This file defines five types of data structures: singly-linked lists,
42
 * lists, simple queues, tail queues and XOR simple queues.
43
 *
44
 *
45
 * A singly-linked list is headed by a single forward pointer. The elements
46
 * are singly linked for minimum space and pointer manipulation overhead at
47
 * the expense of O(n) removal for arbitrary elements. New elements can be
48
 * added to the list after an existing element or at the head of the list.
49
 * Elements being removed from the head of the list should use the explicit
50
 * macro for this purpose for optimum efficiency. A singly-linked list may
51
 * only be traversed in the forward direction.  Singly-linked lists are ideal
52
 * for applications with large datasets and few or no removals or for
53
 * implementing a LIFO queue.
54
 *
55
 * A list is headed by a single forward pointer (or an array of forward
56
 * pointers for a hash table header). The elements are doubly linked
57
 * so that an arbitrary element can be removed without a need to
58
 * traverse the list. New elements can be added to the list before
59
 * or after an existing element or at the head of the list. A list
60
 * may only be traversed in the forward direction.
61
 *
62
 * A simple queue is headed by a pair of pointers, one to the head of the
63
 * list and the other to the tail of the list. The elements are singly
64
 * linked to save space, so elements can only be removed from the
65
 * head of the list. New elements can be added to the list before or after
66
 * an existing element, at the head of the list, or at the end of the
67
 * list. A simple queue may only be traversed in the forward direction.
68
 *
69
 * A tail queue is headed by a pair of pointers, one to the head of the
70
 * list and the other to the tail of the list. The elements are doubly
71
 * linked so that an arbitrary element can be removed without a need to
72
 * traverse the list. New elements can be added to the list before or
73
 * after an existing element, at the head of the list, or at the end of
74
 * the list. A tail queue may be traversed in either direction.
75
 *
76
 * An XOR simple queue is used in the same way as a regular simple queue.
77
 * The difference is that the head structure also includes a "cookie" that
78
 * is XOR'd with the queue pointer (first, last or next) to generate the
79
 * real pointer value.
80
 *
81
 * For details on the use of these macros, see the queue(3) manual page.
82
 */
83
84
#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
85
#define _Q_INVALID ((void *)-1)
86
#define _Q_INVALIDATE(a) (a) = _Q_INVALID
87
#else
88
#define _Q_INVALIDATE(a)
89
#endif
90
91
/*
92
 * Singly-linked List definitions.
93
 */
94
#define SLIST_HEAD(name, type)            \
95
struct name {               \
96
  struct type *slh_first; /* first element */     \
97
}
98
99
#define SLIST_HEAD_INITIALIZER(head)          \
100
  { NULL }
101
102
#define SLIST_ENTRY(type)           \
103
struct {                \
104
  struct type *sle_next;  /* next element */      \
105
}
106
107
/*
108
 * Singly-linked List access methods.
109
 */
110
#define SLIST_FIRST(head) ((head)->slh_first)
111
#define SLIST_END(head)   NULL
112
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
113
#define SLIST_NEXT(elm, field)  ((elm)->field.sle_next)
114
115
#define SLIST_FOREACH(var, head, field)         \
116
  for((var) = SLIST_FIRST(head);          \
117
      (var) != SLIST_END(head);         \
118
      (var) = SLIST_NEXT(var, field))
119
120
#define SLIST_FOREACH_SAFE(var, head, field, tvar)      \
121
  for ((var) = SLIST_FIRST(head);       \
122
      (var) && ((tvar) = SLIST_NEXT(var, field), 1);    \
123
      (var) = (tvar))
124
125
/*
126
 * Singly-linked List functions.
127
 */
128
#define SLIST_INIT(head) {            \
129
  SLIST_FIRST(head) = SLIST_END(head);        \
130
}
131
132
#define SLIST_INSERT_AFTER(slistelm, elm, field) do {     \
133
  (elm)->field.sle_next = (slistelm)->field.sle_next;   \
134
  (slistelm)->field.sle_next = (elm);       \
135
} while (0)
136
137
#define SLIST_INSERT_HEAD(head, elm, field) do {      \
138
  (elm)->field.sle_next = (head)->slh_first;      \
139
  (head)->slh_first = (elm);          \
140
} while (0)
141
142
#define SLIST_REMOVE_AFTER(elm, field) do {       \
143
  (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
144
} while (0)
145
146
#define SLIST_REMOVE_HEAD(head, field) do {       \
147
  (head)->slh_first = (head)->slh_first->field.sle_next;    \
148
} while (0)
149
150
#define SLIST_REMOVE(head, elm, type, field) do {     \
151
  if ((head)->slh_first == (elm)) {       \
152
    SLIST_REMOVE_HEAD((head), field);     \
153
  } else {              \
154
    struct type *curelm = (head)->slh_first;    \
155
                  \
156
    while (curelm->field.sle_next != (elm))     \
157
      curelm = curelm->field.sle_next;    \
158
    curelm->field.sle_next =        \
159
        curelm->field.sle_next->field.sle_next;   \
160
  }               \
161
  _Q_INVALIDATE((elm)->field.sle_next);       \
162
} while (0)
163
164
/*
165
 * List definitions.
166
 */
167
#define LIST_HEAD(name, type)           \
168
struct name {               \
169
  struct type *lh_first;  /* first element */     \
170
}
171
172
#define LIST_HEAD_INITIALIZER(head)         \
173
  { NULL }
174
175
#define LIST_ENTRY(type)            \
176
struct {                \
177
  struct type *le_next; /* next element */      \
178
  struct type **le_prev;  /* address of previous next element */  \
179
}
180
181
/*
182
 * List access methods.
183
 */
184
#define LIST_FIRST(head)    ((head)->lh_first)
185
#define LIST_END(head)      NULL
186
#define LIST_EMPTY(head)    (LIST_FIRST(head) == LIST_END(head))
187
#define LIST_NEXT(elm, field)   ((elm)->field.le_next)
188
189
#define LIST_FOREACH(var, head, field)          \
190
  for((var) = LIST_FIRST(head);         \
191
      (var)!= LIST_END(head);         \
192
      (var) = LIST_NEXT(var, field))
193
194
#define LIST_FOREACH_SAFE(var, head, field, tvar)     \
195
  for ((var) = LIST_FIRST(head);        \
196
      (var) && ((tvar) = LIST_NEXT(var, field), 1);   \
197
      (var) = (tvar))
198
199
/*
200
 * List functions.
201
 */
202
#define LIST_INIT(head) do {            \
203
  LIST_FIRST(head) = LIST_END(head);        \
204
} while (0)
205
206
#define LIST_INSERT_AFTER(listelm, elm, field) do {     \
207
  if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
208
    (listelm)->field.le_next->field.le_prev =   \
209
        &(elm)->field.le_next;        \
210
  (listelm)->field.le_next = (elm);       \
211
  (elm)->field.le_prev = &(listelm)->field.le_next;   \
212
} while (0)
213
214
#define LIST_INSERT_BEFORE(listelm, elm, field) do {      \
215
  (elm)->field.le_prev = (listelm)->field.le_prev;    \
216
  (elm)->field.le_next = (listelm);       \
217
  *(listelm)->field.le_prev = (elm);        \
218
  (listelm)->field.le_prev = &(elm)->field.le_next;   \
219
} while (0)
220
221
#define LIST_INSERT_HEAD(head, elm, field) do {       \
222
  if (((elm)->field.le_next = (head)->lh_first) != NULL)    \
223
    (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
224
  (head)->lh_first = (elm);         \
225
  (elm)->field.le_prev = &(head)->lh_first;     \
226
} while (0)
227
228
#define LIST_REMOVE(elm, field) do {          \
229
  if ((elm)->field.le_next != NULL)       \
230
    (elm)->field.le_next->field.le_prev =     \
231
        (elm)->field.le_prev;       \
232
  *(elm)->field.le_prev = (elm)->field.le_next;     \
233
  _Q_INVALIDATE((elm)->field.le_prev);        \
234
  _Q_INVALIDATE((elm)->field.le_next);        \
235
} while (0)
236
237
#define LIST_REPLACE(elm, elm2, field) do {       \
238
  if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
239
    (elm2)->field.le_next->field.le_prev =      \
240
        &(elm2)->field.le_next;       \
241
  (elm2)->field.le_prev = (elm)->field.le_prev;     \
242
  *(elm2)->field.le_prev = (elm2);        \
243
  _Q_INVALIDATE((elm)->field.le_prev);        \
244
  _Q_INVALIDATE((elm)->field.le_next);        \
245
} while (0)
246
247
/*
248
 * Simple queue definitions.
249
 */
250
#define SIMPLEQ_HEAD(name, type)          \
251
struct name {               \
252
  struct type *sqh_first; /* first element */     \
253
  struct type **sqh_last; /* addr of last next element */   \
254
}
255
256
#define SIMPLEQ_HEAD_INITIALIZER(head)          \
257
  { NULL, &(head).sqh_first }
258
259
#define SIMPLEQ_ENTRY(type)           \
260
struct {                \
261
  struct type *sqe_next;  /* next element */      \
262
}
263
264
/*
265
 * Simple queue access methods.
266
 */
267
16.5k
#define SIMPLEQ_FIRST(head)     ((head)->sqh_first)
268
#define SIMPLEQ_END(head)     NULL
269
#define SIMPLEQ_EMPTY(head)     (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
270
#define SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
271
272
#define SIMPLEQ_FOREACH(var, head, field)       \
273
  for((var) = SIMPLEQ_FIRST(head);        \
274
      (var) != SIMPLEQ_END(head);         \
275
      (var) = SIMPLEQ_NEXT(var, field))
276
277
#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar)      \
278
  for ((var) = SIMPLEQ_FIRST(head);       \
279
      (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1);    \
280
      (var) = (tvar))
281
282
/*
283
 * Simple queue functions.
284
 */
285
15.4k
#define SIMPLEQ_INIT(head) do {           \
286
15.4k
  (head)->sqh_first = NULL;         \
287
15.4k
  (head)->sqh_last = &(head)->sqh_first;        \
288
15.4k
} while (0)
289
290
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do {      \
291
  if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)  \
292
    (head)->sqh_last = &(elm)->field.sqe_next;    \
293
  (head)->sqh_first = (elm);          \
294
} while (0)
295
296
1.04k
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do {     \
297
1.04k
  (elm)->field.sqe_next = NULL;         \
298
1.04k
  *(head)->sqh_last = (elm);          \
299
1.04k
  (head)->sqh_last = &(elm)->field.sqe_next;      \
300
1.04k
} while (0)
301
302
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {    \
303
  if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
304
    (head)->sqh_last = &(elm)->field.sqe_next;    \
305
  (listelm)->field.sqe_next = (elm);        \
306
} while (0)
307
308
1.04k
#define SIMPLEQ_REMOVE_HEAD(head, field) do {     \
309
1.04k
  if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
310
1.04k
    (head)->sqh_last = &(head)->sqh_first;     \
311
1.04k
} while (0)
312
313
#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do {     \
314
  if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
315
      == NULL)              \
316
    (head)->sqh_last = &(elm)->field.sqe_next;    \
317
} while (0)
318
319
#define SIMPLEQ_CONCAT(head1, head2) do {       \
320
  if (!SIMPLEQ_EMPTY((head2))) {          \
321
    *(head1)->sqh_last = (head2)->sqh_first;    \
322
    (head1)->sqh_last = (head2)->sqh_last;      \
323
    SIMPLEQ_INIT((head2));          \
324
  }               \
325
} while (0)
326
327
/*
328
 * XOR Simple queue definitions.
329
 */
330
#define XSIMPLEQ_HEAD(name, type)         \
331
struct name {               \
332
  struct type *sqx_first; /* first element */     \
333
  struct type **sqx_last; /* addr of last next element */   \
334
  unsigned long sqx_cookie;         \
335
}
336
337
#define XSIMPLEQ_ENTRY(type)            \
338
struct {                \
339
  struct type *sqx_next;  /* next element */      \
340
}
341
342
/*
343
 * XOR Simple queue access methods.
344
 */
345
#define XSIMPLEQ_XOR(head, ptr)     ((__typeof(ptr))((head)->sqx_cookie ^ \
346
          (unsigned long)(ptr)))
347
#define XSIMPLEQ_FIRST(head)      XSIMPLEQ_XOR(head, ((head)->sqx_first))
348
#define XSIMPLEQ_END(head)      NULL
349
#define XSIMPLEQ_EMPTY(head)      (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
350
#define XSIMPLEQ_NEXT(head, elm, field)    XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
351
352
353
#define XSIMPLEQ_FOREACH(var, head, field)        \
354
  for ((var) = XSIMPLEQ_FIRST(head);        \
355
      (var) != XSIMPLEQ_END(head);        \
356
      (var) = XSIMPLEQ_NEXT(head, var, field))
357
358
#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar)     \
359
  for ((var) = XSIMPLEQ_FIRST(head);        \
360
      (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
361
      (var) = (tvar))
362
363
/*
364
 * XOR Simple queue functions.
365
 */
366
#define XSIMPLEQ_INIT(head) do {          \
367
  arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
368
  (head)->sqx_first = XSIMPLEQ_XOR(head, NULL);     \
369
  (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first);  \
370
} while (0)
371
372
#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do {     \
373
  if (((elm)->field.sqx_next = (head)->sqx_first) ==    \
374
      XSIMPLEQ_XOR(head, NULL))         \
375
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
376
  (head)->sqx_first = XSIMPLEQ_XOR(head, (elm));      \
377
} while (0)
378
379
#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do {     \
380
  (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL);   \
381
  *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
382
  (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next);  \
383
} while (0)
384
385
#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {   \
386
  if (((elm)->field.sqx_next = (listelm)->field.sqx_next) ==  \
387
      XSIMPLEQ_XOR(head, NULL))         \
388
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
389
  (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm));    \
390
} while (0)
391
392
#define XSIMPLEQ_REMOVE_HEAD(head, field) do {        \
393
  if (((head)->sqx_first = XSIMPLEQ_XOR(head,     \
394
      (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
395
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
396
} while (0)
397
398
#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do {      \
399
  if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head,     \
400
      (elm)->field.sqx_next)->field.sqx_next)     \
401
      == XSIMPLEQ_XOR(head, NULL))        \
402
    (head)->sqx_last =          \
403
        XSIMPLEQ_XOR(head, &(elm)->field.sqx_next);   \
404
} while (0)
405
406
407
/*
408
 * Tail queue definitions.
409
 */
410
#define TAILQ_HEAD(name, type)            \
411
struct name {               \
412
  struct type *tqh_first; /* first element */     \
413
  struct type **tqh_last; /* addr of last next element */   \
414
}
415
416
#define TAILQ_HEAD_INITIALIZER(head)          \
417
  { NULL, &(head).tqh_first }
418
419
#define TAILQ_ENTRY(type)           \
420
struct {                \
421
  struct type *tqe_next;  /* next element */      \
422
  struct type **tqe_prev; /* address of previous next element */  \
423
}
424
425
/*
426
 * Tail queue access methods.
427
 */
428
15.4k
#define TAILQ_FIRST(head)   ((head)->tqh_first)
429
30.9k
#define TAILQ_END(head)     NULL
430
0
#define TAILQ_NEXT(elm, field)    ((elm)->field.tqe_next)
431
#define TAILQ_LAST(head, headname)          \
432
  (*(((struct headname *)((head)->tqh_last))->tqh_last))
433
/* XXX */
434
#define TAILQ_PREV(elm, headname, field)        \
435
  (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
436
#define TAILQ_EMPTY(head)           \
437
  (TAILQ_FIRST(head) == TAILQ_END(head))
438
439
#define TAILQ_FOREACH(var, head, field)         \
440
0
  for((var) = TAILQ_FIRST(head);         \
441
0
      (var) != TAILQ_END(head);         \
442
0
      (var) = TAILQ_NEXT(var, field))
443
444
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)      \
445
15.4k
  for ((var) = TAILQ_FIRST(head);         \
446
15.4k
      (var) != TAILQ_END(head) &&         \
447
15.4k
      ((tvar) = TAILQ_NEXT(var, field), 1);     \
448
15.4k
      (var) = (tvar))
449
450
451
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)   \
452
  for((var) = TAILQ_LAST(head, headname);       \
453
      (var) != TAILQ_END(head);         \
454
      (var) = TAILQ_PREV(var, headname, field))
455
456
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)  \
457
  for ((var) = TAILQ_LAST(head, headname);      \
458
      (var) != TAILQ_END(head) &&         \
459
      ((tvar) = TAILQ_PREV(var, headname, field), 1);   \
460
      (var) = (tvar))
461
462
/*
463
 * Tail queue functions.
464
 */
465
15.4k
#define TAILQ_INIT(head) do {           \
466
15.4k
  (head)->tqh_first = NULL;         \
467
15.4k
  (head)->tqh_last = &(head)->tqh_first;        \
468
15.4k
} while (0)
469
470
#define TAILQ_INSERT_HEAD(head, elm, field) do {      \
471
  if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)  \
472
    (head)->tqh_first->field.tqe_prev =     \
473
        &(elm)->field.tqe_next;       \
474
  else                \
475
    (head)->tqh_last = &(elm)->field.tqe_next;    \
476
  (head)->tqh_first = (elm);          \
477
  (elm)->field.tqe_prev = &(head)->tqh_first;     \
478
} while (0)
479
480
0
#define TAILQ_INSERT_TAIL(head, elm, field) do {     \
481
0
  (elm)->field.tqe_next = NULL;         \
482
0
  (elm)->field.tqe_prev = (head)->tqh_last;     \
483
0
  *(head)->tqh_last = (elm);          \
484
0
  (head)->tqh_last = &(elm)->field.tqe_next;      \
485
0
} while (0)
486
487
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {    \
488
  if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
489
    (elm)->field.tqe_next->field.tqe_prev =     \
490
        &(elm)->field.tqe_next;       \
491
  else                \
492
    (head)->tqh_last = &(elm)->field.tqe_next;    \
493
  (listelm)->field.tqe_next = (elm);        \
494
  (elm)->field.tqe_prev = &(listelm)->field.tqe_next;   \
495
} while (0)
496
497
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {     \
498
  (elm)->field.tqe_prev = (listelm)->field.tqe_prev;    \
499
  (elm)->field.tqe_next = (listelm);        \
500
  *(listelm)->field.tqe_prev = (elm);       \
501
  (listelm)->field.tqe_prev = &(elm)->field.tqe_next;   \
502
} while (0)
503
504
0
#define TAILQ_REMOVE(head, elm, field) do {       \
505
0
  if (((elm)->field.tqe_next) != NULL)       \
506
0
    (elm)->field.tqe_next->field.tqe_prev =     \
507
0
        (elm)->field.tqe_prev;       \
508
0
  else                \
509
0
    (head)->tqh_last = (elm)->field.tqe_prev;   \
510
0
  *(elm)->field.tqe_prev = (elm)->field.tqe_next;     \
511
0
  _Q_INVALIDATE((elm)->field.tqe_prev);       \
512
0
  _Q_INVALIDATE((elm)->field.tqe_next);       \
513
0
} while (0)
514
515
#define TAILQ_REPLACE(head, elm, elm2, field) do {      \
516
  if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
517
    (elm2)->field.tqe_next->field.tqe_prev =    \
518
        &(elm2)->field.tqe_next;        \
519
  else                \
520
    (head)->tqh_last = &(elm2)->field.tqe_next;   \
521
  (elm2)->field.tqe_prev = (elm)->field.tqe_prev;     \
522
  *(elm2)->field.tqe_prev = (elm2);       \
523
  _Q_INVALIDATE((elm)->field.tqe_prev);       \
524
  _Q_INVALIDATE((elm)->field.tqe_next);       \
525
} while (0)
526
527
#define TAILQ_CONCAT(head1, head2, field) do {        \
528
  if (!TAILQ_EMPTY(head2)) {          \
529
    *(head1)->tqh_last = (head2)->tqh_first;    \
530
    (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
531
    (head1)->tqh_last = (head2)->tqh_last;      \
532
    TAILQ_INIT((head2));          \
533
  }               \
534
} while (0)
535
536
/*
537
 * Singly-linked Tail queue declarations.
538
 */
539
#define STAILQ_HEAD(name, type)           \
540
struct name {               \
541
  struct type *stqh_first;  /* first element */   \
542
  struct type **stqh_last;  /* addr of last next element */ \
543
}
544
545
#define STAILQ_HEAD_INITIALIZER(head)         \
546
  { NULL, &(head).stqh_first }
547
548
#define STAILQ_ENTRY(type)            \
549
struct {                \
550
  struct type *stqe_next; /* next element */      \
551
}
552
553
/*
554
 * Singly-linked Tail queue access methods.
555
 */
556
#define STAILQ_FIRST(head)  ((head)->stqh_first)
557
#define STAILQ_END(head)  NULL
558
#define STAILQ_EMPTY(head)  (STAILQ_FIRST(head) == STAILQ_END(head))
559
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
560
561
#define STAILQ_FOREACH(var, head, field)        \
562
  for ((var) = STAILQ_FIRST(head);        \
563
      (var) != STAILQ_END(head);          \
564
      (var) = STAILQ_NEXT(var, field))
565
566
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)     \
567
  for ((var) = STAILQ_FIRST(head);        \
568
      (var) && ((tvar) = STAILQ_NEXT(var, field), 1);   \
569
      (var) = (tvar))
570
571
/*
572
 * Singly-linked Tail queue functions.
573
 */
574
#define STAILQ_INIT(head) do {            \
575
  STAILQ_FIRST((head)) = NULL;          \
576
  (head)->stqh_last = &STAILQ_FIRST((head));      \
577
} while (0)
578
579
#define STAILQ_INSERT_HEAD(head, elm, field) do {     \
580
  if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
581
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
582
  STAILQ_FIRST((head)) = (elm);         \
583
} while (0)
584
585
#define STAILQ_INSERT_TAIL(head, elm, field) do {     \
586
  STAILQ_NEXT((elm), field) = NULL;       \
587
  *(head)->stqh_last = (elm);         \
588
  (head)->stqh_last = &STAILQ_NEXT((elm), field);     \
589
} while (0)
590
591
#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do {   \
592
  if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((elm), field)) == NULL)\
593
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
594
  STAILQ_NEXT((elm), field) = (elm);        \
595
} while (0)
596
597
#define STAILQ_REMOVE_HEAD(head, field) do {                            \
598
  if ((STAILQ_FIRST((head)) =         \
599
      STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)    \
600
    (head)->stqh_last = &STAILQ_FIRST((head));    \
601
} while (0)
602
603
#define STAILQ_REMOVE_AFTER(head, elm, field) do {                      \
604
  if ((STAILQ_NEXT(elm, field) =          \
605
      STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
606
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
607
} while (0)
608
609
#define STAILQ_REMOVE(head, elm, type, field) do {      \
610
  if (STAILQ_FIRST((head)) == (elm)) {        \
611
    STAILQ_REMOVE_HEAD((head), field);      \
612
  } else {              \
613
    struct type *curelm = (head)->stqh_first;   \
614
    while (STAILQ_NEXT(curelm, field) != (elm))   \
615
      curelm = STAILQ_NEXT(curelm, field);    \
616
    STAILQ_REMOVE_AFTER(head, curelm, field);   \
617
  }               \
618
} while (0)
619
620
#define STAILQ_CONCAT(head1, head2) do {        \
621
  if (!STAILQ_EMPTY((head2))) {         \
622
    *(head1)->stqh_last = (head2)->stqh_first;    \
623
    (head1)->stqh_last = (head2)->stqh_last;    \
624
    STAILQ_INIT((head2));         \
625
  }               \
626
} while (0)
627
628
#define STAILQ_LAST(head, type, field)          \
629
  (STAILQ_EMPTY((head)) ? NULL :          \
630
          ((struct type *)(void *)        \
631
    ((char *)((head)->stqh_last) - offsetof(struct type, field))))
632
633
#endif  /* !_SYS_QUEUE_H_ */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/sys/queue.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: queue.h,v 1.46 2020/12/30 13:33:12 millert Exp $  */
2
/*  $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
3
4
/*
5
 * Copyright (c) 1991, 1993
6
 *  The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 *
32
 *  @(#)queue.h 8.5 (Berkeley) 8/20/94
33
 */
34
35
#ifndef _SYS_QUEUE_H_
36
#define _SYS_QUEUE_H_
37
38
#include <sys/_null.h>
39
40
/*
41
 * This file defines five types of data structures: singly-linked lists,
42
 * lists, simple queues, tail queues and XOR simple queues.
43
 *
44
 *
45
 * A singly-linked list is headed by a single forward pointer. The elements
46
 * are singly linked for minimum space and pointer manipulation overhead at
47
 * the expense of O(n) removal for arbitrary elements. New elements can be
48
 * added to the list after an existing element or at the head of the list.
49
 * Elements being removed from the head of the list should use the explicit
50
 * macro for this purpose for optimum efficiency. A singly-linked list may
51
 * only be traversed in the forward direction.  Singly-linked lists are ideal
52
 * for applications with large datasets and few or no removals or for
53
 * implementing a LIFO queue.
54
 *
55
 * A list is headed by a single forward pointer (or an array of forward
56
 * pointers for a hash table header). The elements are doubly linked
57
 * so that an arbitrary element can be removed without a need to
58
 * traverse the list. New elements can be added to the list before
59
 * or after an existing element or at the head of the list. A list
60
 * may only be traversed in the forward direction.
61
 *
62
 * A simple queue is headed by a pair of pointers, one to the head of the
63
 * list and the other to the tail of the list. The elements are singly
64
 * linked to save space, so elements can only be removed from the
65
 * head of the list. New elements can be added to the list before or after
66
 * an existing element, at the head of the list, or at the end of the
67
 * list. A simple queue may only be traversed in the forward direction.
68
 *
69
 * A tail queue is headed by a pair of pointers, one to the head of the
70
 * list and the other to the tail of the list. The elements are doubly
71
 * linked so that an arbitrary element can be removed without a need to
72
 * traverse the list. New elements can be added to the list before or
73
 * after an existing element, at the head of the list, or at the end of
74
 * the list. A tail queue may be traversed in either direction.
75
 *
76
 * An XOR simple queue is used in the same way as a regular simple queue.
77
 * The difference is that the head structure also includes a "cookie" that
78
 * is XOR'd with the queue pointer (first, last or next) to generate the
79
 * real pointer value.
80
 *
81
 * For details on the use of these macros, see the queue(3) manual page.
82
 */
83
84
#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
85
#define _Q_INVALID ((void *)-1)
86
#define _Q_INVALIDATE(a) (a) = _Q_INVALID
87
#else
88
#define _Q_INVALIDATE(a)
89
#endif
90
91
/*
92
 * Singly-linked List definitions.
93
 */
94
#define SLIST_HEAD(name, type)            \
95
struct name {               \
96
  struct type *slh_first; /* first element */     \
97
}
98
99
#define SLIST_HEAD_INITIALIZER(head)          \
100
  { NULL }
101
102
#define SLIST_ENTRY(type)           \
103
struct {                \
104
  struct type *sle_next;  /* next element */      \
105
}
106
107
/*
108
 * Singly-linked List access methods.
109
 */
110
#define SLIST_FIRST(head) ((head)->slh_first)
111
#define SLIST_END(head)   NULL
112
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
113
#define SLIST_NEXT(elm, field)  ((elm)->field.sle_next)
114
115
#define SLIST_FOREACH(var, head, field)         \
116
  for((var) = SLIST_FIRST(head);          \
117
      (var) != SLIST_END(head);         \
118
      (var) = SLIST_NEXT(var, field))
119
120
#define SLIST_FOREACH_SAFE(var, head, field, tvar)      \
121
  for ((var) = SLIST_FIRST(head);       \
122
      (var) && ((tvar) = SLIST_NEXT(var, field), 1);    \
123
      (var) = (tvar))
124
125
/*
126
 * Singly-linked List functions.
127
 */
128
#define SLIST_INIT(head) {            \
129
  SLIST_FIRST(head) = SLIST_END(head);        \
130
}
131
132
#define SLIST_INSERT_AFTER(slistelm, elm, field) do {     \
133
  (elm)->field.sle_next = (slistelm)->field.sle_next;   \
134
  (slistelm)->field.sle_next = (elm);       \
135
} while (0)
136
137
#define SLIST_INSERT_HEAD(head, elm, field) do {      \
138
  (elm)->field.sle_next = (head)->slh_first;      \
139
  (head)->slh_first = (elm);          \
140
} while (0)
141
142
#define SLIST_REMOVE_AFTER(elm, field) do {       \
143
  (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
144
} while (0)
145
146
#define SLIST_REMOVE_HEAD(head, field) do {       \
147
  (head)->slh_first = (head)->slh_first->field.sle_next;    \
148
} while (0)
149
150
#define SLIST_REMOVE(head, elm, type, field) do {     \
151
  if ((head)->slh_first == (elm)) {       \
152
    SLIST_REMOVE_HEAD((head), field);     \
153
  } else {              \
154
    struct type *curelm = (head)->slh_first;    \
155
                  \
156
    while (curelm->field.sle_next != (elm))     \
157
      curelm = curelm->field.sle_next;    \
158
    curelm->field.sle_next =        \
159
        curelm->field.sle_next->field.sle_next;   \
160
  }               \
161
  _Q_INVALIDATE((elm)->field.sle_next);       \
162
} while (0)
163
164
/*
165
 * List definitions.
166
 */
167
#define LIST_HEAD(name, type)           \
168
struct name {               \
169
  struct type *lh_first;  /* first element */     \
170
}
171
172
#define LIST_HEAD_INITIALIZER(head)         \
173
  { NULL }
174
175
#define LIST_ENTRY(type)            \
176
struct {                \
177
  struct type *le_next; /* next element */      \
178
  struct type **le_prev;  /* address of previous next element */  \
179
}
180
181
/*
182
 * List access methods.
183
 */
184
#define LIST_FIRST(head)    ((head)->lh_first)
185
#define LIST_END(head)      NULL
186
#define LIST_EMPTY(head)    (LIST_FIRST(head) == LIST_END(head))
187
#define LIST_NEXT(elm, field)   ((elm)->field.le_next)
188
189
#define LIST_FOREACH(var, head, field)          \
190
  for((var) = LIST_FIRST(head);         \
191
      (var)!= LIST_END(head);         \
192
      (var) = LIST_NEXT(var, field))
193
194
#define LIST_FOREACH_SAFE(var, head, field, tvar)     \
195
  for ((var) = LIST_FIRST(head);        \
196
      (var) && ((tvar) = LIST_NEXT(var, field), 1);   \
197
      (var) = (tvar))
198
199
/*
200
 * List functions.
201
 */
202
#define LIST_INIT(head) do {            \
203
  LIST_FIRST(head) = LIST_END(head);        \
204
} while (0)
205
206
#define LIST_INSERT_AFTER(listelm, elm, field) do {     \
207
  if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
208
    (listelm)->field.le_next->field.le_prev =   \
209
        &(elm)->field.le_next;        \
210
  (listelm)->field.le_next = (elm);       \
211
  (elm)->field.le_prev = &(listelm)->field.le_next;   \
212
} while (0)
213
214
#define LIST_INSERT_BEFORE(listelm, elm, field) do {      \
215
  (elm)->field.le_prev = (listelm)->field.le_prev;    \
216
  (elm)->field.le_next = (listelm);       \
217
  *(listelm)->field.le_prev = (elm);        \
218
  (listelm)->field.le_prev = &(elm)->field.le_next;   \
219
} while (0)
220
221
#define LIST_INSERT_HEAD(head, elm, field) do {       \
222
  if (((elm)->field.le_next = (head)->lh_first) != NULL)    \
223
    (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
224
  (head)->lh_first = (elm);         \
225
  (elm)->field.le_prev = &(head)->lh_first;     \
226
} while (0)
227
228
#define LIST_REMOVE(elm, field) do {          \
229
  if ((elm)->field.le_next != NULL)       \
230
    (elm)->field.le_next->field.le_prev =     \
231
        (elm)->field.le_prev;       \
232
  *(elm)->field.le_prev = (elm)->field.le_next;     \
233
  _Q_INVALIDATE((elm)->field.le_prev);        \
234
  _Q_INVALIDATE((elm)->field.le_next);        \
235
} while (0)
236
237
#define LIST_REPLACE(elm, elm2, field) do {       \
238
  if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
239
    (elm2)->field.le_next->field.le_prev =      \
240
        &(elm2)->field.le_next;       \
241
  (elm2)->field.le_prev = (elm)->field.le_prev;     \
242
  *(elm2)->field.le_prev = (elm2);        \
243
  _Q_INVALIDATE((elm)->field.le_prev);        \
244
  _Q_INVALIDATE((elm)->field.le_next);        \
245
} while (0)
246
247
/*
248
 * Simple queue definitions.
249
 */
250
#define SIMPLEQ_HEAD(name, type)          \
251
struct name {               \
252
  struct type *sqh_first; /* first element */     \
253
  struct type **sqh_last; /* addr of last next element */   \
254
}
255
256
#define SIMPLEQ_HEAD_INITIALIZER(head)          \
257
  { NULL, &(head).sqh_first }
258
259
#define SIMPLEQ_ENTRY(type)           \
260
struct {                \
261
  struct type *sqe_next;  /* next element */      \
262
}
263
264
/*
265
 * Simple queue access methods.
266
 */
267
16.5k
#define SIMPLEQ_FIRST(head)     ((head)->sqh_first)
268
#define SIMPLEQ_END(head)     NULL
269
#define SIMPLEQ_EMPTY(head)     (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
270
#define SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
271
272
#define SIMPLEQ_FOREACH(var, head, field)       \
273
  for((var) = SIMPLEQ_FIRST(head);        \
274
      (var) != SIMPLEQ_END(head);         \
275
      (var) = SIMPLEQ_NEXT(var, field))
276
277
#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar)      \
278
  for ((var) = SIMPLEQ_FIRST(head);       \
279
      (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1);    \
280
      (var) = (tvar))
281
282
/*
283
 * Simple queue functions.
284
 */
285
15.4k
#define SIMPLEQ_INIT(head) do {           \
286
15.4k
  (head)->sqh_first = NULL;         \
287
15.4k
  (head)->sqh_last = &(head)->sqh_first;        \
288
15.4k
} while (0)
289
290
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do {      \
291
  if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)  \
292
    (head)->sqh_last = &(elm)->field.sqe_next;    \
293
  (head)->sqh_first = (elm);          \
294
} while (0)
295
296
1.04k
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do {     \
297
1.04k
  (elm)->field.sqe_next = NULL;         \
298
1.04k
  *(head)->sqh_last = (elm);          \
299
1.04k
  (head)->sqh_last = &(elm)->field.sqe_next;      \
300
1.04k
} while (0)
301
302
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {    \
303
  if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
304
    (head)->sqh_last = &(elm)->field.sqe_next;    \
305
  (listelm)->field.sqe_next = (elm);        \
306
} while (0)
307
308
1.04k
#define SIMPLEQ_REMOVE_HEAD(head, field) do {     \
309
1.04k
  if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
310
1.04k
    (head)->sqh_last = &(head)->sqh_first;     \
311
1.04k
} while (0)
312
313
#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do {     \
314
  if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
315
      == NULL)              \
316
    (head)->sqh_last = &(elm)->field.sqe_next;    \
317
} while (0)
318
319
#define SIMPLEQ_CONCAT(head1, head2) do {       \
320
  if (!SIMPLEQ_EMPTY((head2))) {          \
321
    *(head1)->sqh_last = (head2)->sqh_first;    \
322
    (head1)->sqh_last = (head2)->sqh_last;      \
323
    SIMPLEQ_INIT((head2));          \
324
  }               \
325
} while (0)
326
327
/*
328
 * XOR Simple queue definitions.
329
 */
330
#define XSIMPLEQ_HEAD(name, type)         \
331
struct name {               \
332
  struct type *sqx_first; /* first element */     \
333
  struct type **sqx_last; /* addr of last next element */   \
334
  unsigned long sqx_cookie;         \
335
}
336
337
#define XSIMPLEQ_ENTRY(type)            \
338
struct {                \
339
  struct type *sqx_next;  /* next element */      \
340
}
341
342
/*
343
 * XOR Simple queue access methods.
344
 */
345
#define XSIMPLEQ_XOR(head, ptr)     ((__typeof(ptr))((head)->sqx_cookie ^ \
346
          (unsigned long)(ptr)))
347
#define XSIMPLEQ_FIRST(head)      XSIMPLEQ_XOR(head, ((head)->sqx_first))
348
#define XSIMPLEQ_END(head)      NULL
349
#define XSIMPLEQ_EMPTY(head)      (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
350
#define XSIMPLEQ_NEXT(head, elm, field)    XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
351
352
353
#define XSIMPLEQ_FOREACH(var, head, field)        \
354
  for ((var) = XSIMPLEQ_FIRST(head);        \
355
      (var) != XSIMPLEQ_END(head);        \
356
      (var) = XSIMPLEQ_NEXT(head, var, field))
357
358
#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar)     \
359
  for ((var) = XSIMPLEQ_FIRST(head);        \
360
      (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
361
      (var) = (tvar))
362
363
/*
364
 * XOR Simple queue functions.
365
 */
366
#define XSIMPLEQ_INIT(head) do {          \
367
  arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
368
  (head)->sqx_first = XSIMPLEQ_XOR(head, NULL);     \
369
  (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first);  \
370
} while (0)
371
372
#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do {     \
373
  if (((elm)->field.sqx_next = (head)->sqx_first) ==    \
374
      XSIMPLEQ_XOR(head, NULL))         \
375
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
376
  (head)->sqx_first = XSIMPLEQ_XOR(head, (elm));      \
377
} while (0)
378
379
#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do {     \
380
  (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL);   \
381
  *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
382
  (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next);  \
383
} while (0)
384
385
#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {   \
386
  if (((elm)->field.sqx_next = (listelm)->field.sqx_next) ==  \
387
      XSIMPLEQ_XOR(head, NULL))         \
388
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
389
  (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm));    \
390
} while (0)
391
392
#define XSIMPLEQ_REMOVE_HEAD(head, field) do {        \
393
  if (((head)->sqx_first = XSIMPLEQ_XOR(head,     \
394
      (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
395
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
396
} while (0)
397
398
#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do {      \
399
  if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head,     \
400
      (elm)->field.sqx_next)->field.sqx_next)     \
401
      == XSIMPLEQ_XOR(head, NULL))        \
402
    (head)->sqx_last =          \
403
        XSIMPLEQ_XOR(head, &(elm)->field.sqx_next);   \
404
} while (0)
405
406
407
/*
408
 * Tail queue definitions.
409
 */
410
#define TAILQ_HEAD(name, type)            \
411
struct name {               \
412
  struct type *tqh_first; /* first element */     \
413
  struct type **tqh_last; /* addr of last next element */   \
414
}
415
416
#define TAILQ_HEAD_INITIALIZER(head)          \
417
  { NULL, &(head).tqh_first }
418
419
#define TAILQ_ENTRY(type)           \
420
struct {                \
421
  struct type *tqe_next;  /* next element */      \
422
  struct type **tqe_prev; /* address of previous next element */  \
423
}
424
425
/*
426
 * Tail queue access methods.
427
 */
428
15.4k
#define TAILQ_FIRST(head)   ((head)->tqh_first)
429
30.9k
#define TAILQ_END(head)     NULL
430
0
#define TAILQ_NEXT(elm, field)    ((elm)->field.tqe_next)
431
#define TAILQ_LAST(head, headname)          \
432
  (*(((struct headname *)((head)->tqh_last))->tqh_last))
433
/* XXX */
434
#define TAILQ_PREV(elm, headname, field)        \
435
  (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
436
#define TAILQ_EMPTY(head)           \
437
  (TAILQ_FIRST(head) == TAILQ_END(head))
438
439
#define TAILQ_FOREACH(var, head, field)         \
440
0
  for((var) = TAILQ_FIRST(head);         \
441
0
      (var) != TAILQ_END(head);         \
442
0
      (var) = TAILQ_NEXT(var, field))
443
444
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)      \
445
15.4k
  for ((var) = TAILQ_FIRST(head);         \
446
15.4k
      (var) != TAILQ_END(head) &&         \
447
15.4k
      ((tvar) = TAILQ_NEXT(var, field), 1);     \
448
15.4k
      (var) = (tvar))
449
450
451
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)   \
452
  for((var) = TAILQ_LAST(head, headname);       \
453
      (var) != TAILQ_END(head);         \
454
      (var) = TAILQ_PREV(var, headname, field))
455
456
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)  \
457
  for ((var) = TAILQ_LAST(head, headname);      \
458
      (var) != TAILQ_END(head) &&         \
459
      ((tvar) = TAILQ_PREV(var, headname, field), 1);   \
460
      (var) = (tvar))
461
462
/*
463
 * Tail queue functions.
464
 */
465
15.4k
#define TAILQ_INIT(head) do {           \
466
15.4k
  (head)->tqh_first = NULL;         \
467
15.4k
  (head)->tqh_last = &(head)->tqh_first;        \
468
15.4k
} while (0)
469
470
#define TAILQ_INSERT_HEAD(head, elm, field) do {      \
471
  if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)  \
472
    (head)->tqh_first->field.tqe_prev =     \
473
        &(elm)->field.tqe_next;       \
474
  else                \
475
    (head)->tqh_last = &(elm)->field.tqe_next;    \
476
  (head)->tqh_first = (elm);          \
477
  (elm)->field.tqe_prev = &(head)->tqh_first;     \
478
} while (0)
479
480
0
#define TAILQ_INSERT_TAIL(head, elm, field) do {     \
481
0
  (elm)->field.tqe_next = NULL;         \
482
0
  (elm)->field.tqe_prev = (head)->tqh_last;     \
483
0
  *(head)->tqh_last = (elm);          \
484
0
  (head)->tqh_last = &(elm)->field.tqe_next;      \
485
0
} while (0)
486
487
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {    \
488
  if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
489
    (elm)->field.tqe_next->field.tqe_prev =     \
490
        &(elm)->field.tqe_next;       \
491
  else                \
492
    (head)->tqh_last = &(elm)->field.tqe_next;    \
493
  (listelm)->field.tqe_next = (elm);        \
494
  (elm)->field.tqe_prev = &(listelm)->field.tqe_next;   \
495
} while (0)
496
497
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {     \
498
  (elm)->field.tqe_prev = (listelm)->field.tqe_prev;    \
499
  (elm)->field.tqe_next = (listelm);        \
500
  *(listelm)->field.tqe_prev = (elm);       \
501
  (listelm)->field.tqe_prev = &(elm)->field.tqe_next;   \
502
} while (0)
503
504
0
#define TAILQ_REMOVE(head, elm, field) do {       \
505
0
  if (((elm)->field.tqe_next) != NULL)       \
506
0
    (elm)->field.tqe_next->field.tqe_prev =     \
507
0
        (elm)->field.tqe_prev;       \
508
0
  else                \
509
0
    (head)->tqh_last = (elm)->field.tqe_prev;   \
510
0
  *(elm)->field.tqe_prev = (elm)->field.tqe_next;     \
511
0
  _Q_INVALIDATE((elm)->field.tqe_prev);       \
512
0
  _Q_INVALIDATE((elm)->field.tqe_next);       \
513
0
} while (0)
514
515
#define TAILQ_REPLACE(head, elm, elm2, field) do {      \
516
  if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
517
    (elm2)->field.tqe_next->field.tqe_prev =    \
518
        &(elm2)->field.tqe_next;        \
519
  else                \
520
    (head)->tqh_last = &(elm2)->field.tqe_next;   \
521
  (elm2)->field.tqe_prev = (elm)->field.tqe_prev;     \
522
  *(elm2)->field.tqe_prev = (elm2);       \
523
  _Q_INVALIDATE((elm)->field.tqe_prev);       \
524
  _Q_INVALIDATE((elm)->field.tqe_next);       \
525
} while (0)
526
527
#define TAILQ_CONCAT(head1, head2, field) do {        \
528
  if (!TAILQ_EMPTY(head2)) {          \
529
    *(head1)->tqh_last = (head2)->tqh_first;    \
530
    (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
531
    (head1)->tqh_last = (head2)->tqh_last;      \
532
    TAILQ_INIT((head2));          \
533
  }               \
534
} while (0)
535
536
/*
537
 * Singly-linked Tail queue declarations.
538
 */
539
#define STAILQ_HEAD(name, type)           \
540
struct name {               \
541
  struct type *stqh_first;  /* first element */   \
542
  struct type **stqh_last;  /* addr of last next element */ \
543
}
544
545
#define STAILQ_HEAD_INITIALIZER(head)         \
546
  { NULL, &(head).stqh_first }
547
548
#define STAILQ_ENTRY(type)            \
549
struct {                \
550
  struct type *stqe_next; /* next element */      \
551
}
552
553
/*
554
 * Singly-linked Tail queue access methods.
555
 */
556
#define STAILQ_FIRST(head)  ((head)->stqh_first)
557
#define STAILQ_END(head)  NULL
558
#define STAILQ_EMPTY(head)  (STAILQ_FIRST(head) == STAILQ_END(head))
559
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
560
561
#define STAILQ_FOREACH(var, head, field)        \
562
  for ((var) = STAILQ_FIRST(head);        \
563
      (var) != STAILQ_END(head);          \
564
      (var) = STAILQ_NEXT(var, field))
565
566
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)     \
567
  for ((var) = STAILQ_FIRST(head);        \
568
      (var) && ((tvar) = STAILQ_NEXT(var, field), 1);   \
569
      (var) = (tvar))
570
571
/*
572
 * Singly-linked Tail queue functions.
573
 */
574
#define STAILQ_INIT(head) do {            \
575
  STAILQ_FIRST((head)) = NULL;          \
576
  (head)->stqh_last = &STAILQ_FIRST((head));      \
577
} while (0)
578
579
#define STAILQ_INSERT_HEAD(head, elm, field) do {     \
580
  if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
581
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
582
  STAILQ_FIRST((head)) = (elm);         \
583
} while (0)
584
585
#define STAILQ_INSERT_TAIL(head, elm, field) do {     \
586
  STAILQ_NEXT((elm), field) = NULL;       \
587
  *(head)->stqh_last = (elm);         \
588
  (head)->stqh_last = &STAILQ_NEXT((elm), field);     \
589
} while (0)
590
591
#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do {   \
592
  if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((elm), field)) == NULL)\
593
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
594
  STAILQ_NEXT((elm), field) = (elm);        \
595
} while (0)
596
597
#define STAILQ_REMOVE_HEAD(head, field) do {                            \
598
  if ((STAILQ_FIRST((head)) =         \
599
      STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)    \
600
    (head)->stqh_last = &STAILQ_FIRST((head));    \
601
} while (0)
602
603
#define STAILQ_REMOVE_AFTER(head, elm, field) do {                      \
604
  if ((STAILQ_NEXT(elm, field) =          \
605
      STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
606
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
607
} while (0)
608
609
#define STAILQ_REMOVE(head, elm, type, field) do {      \
610
  if (STAILQ_FIRST((head)) == (elm)) {        \
611
    STAILQ_REMOVE_HEAD((head), field);      \
612
  } else {              \
613
    struct type *curelm = (head)->stqh_first;   \
614
    while (STAILQ_NEXT(curelm, field) != (elm))   \
615
      curelm = STAILQ_NEXT(curelm, field);    \
616
    STAILQ_REMOVE_AFTER(head, curelm, field);   \
617
  }               \
618
} while (0)
619
620
#define STAILQ_CONCAT(head1, head2) do {        \
621
  if (!STAILQ_EMPTY((head2))) {         \
622
    *(head1)->stqh_last = (head2)->stqh_first;    \
623
    (head1)->stqh_last = (head2)->stqh_last;    \
624
    STAILQ_INIT((head2));         \
625
  }               \
626
} while (0)
627
628
#define STAILQ_LAST(head, type, field)          \
629
  (STAILQ_EMPTY((head)) ? NULL :          \
630
          ((struct type *)(void *)        \
631
    ((char *)((head)->stqh_last) - offsetof(struct type, field))))
632
633
#endif  /* !_SYS_QUEUE_H_ */
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/sys/tree.h.html b/coverage/latest/report/linux/src/openiked-portable/compat/sys/tree.h.html index c3bab5f3e..8c073885a 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/sys/tree.h.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/sys/tree.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/sys/tree.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: tree.h,v 1.31 2023/03/08 04:43:09 guenther Exp $  */
2
/*
3
 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#ifndef _SYS_TREE_H_
28
#define _SYS_TREE_H_
29
30
#include <sys/_null.h>
31
32
/*
33
 * This file defines data structures for different types of trees:
34
 * splay trees and red-black trees.
35
 *
36
 * A splay tree is a self-organizing data structure.  Every operation
37
 * on the tree causes a splay to happen.  The splay moves the requested
38
 * node to the root of the tree and partly rebalances it.
39
 *
40
 * This has the benefit that request locality causes faster lookups as
41
 * the requested nodes move to the top of the tree.  On the other hand,
42
 * every lookup causes memory writes.
43
 *
44
 * The Balance Theorem bounds the total access time for m operations
45
 * and n inserts on an initially empty tree as O((m + n)lg n).  The
46
 * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
47
 *
48
 * A red-black tree is a binary search tree with the node color as an
49
 * extra attribute.  It fulfills a set of conditions:
50
 *  - every search path from the root to a leaf consists of the
51
 *    same number of black nodes,
52
 *  - each red node (except for the root) has a black parent,
53
 *  - each leaf node is black.
54
 *
55
 * Every operation on a red-black tree is bounded as O(lg n).
56
 * The maximum height of a red-black tree is 2lg (n+1).
57
 */
58
59
#define SPLAY_HEAD(name, type)            \
60
struct name {               \
61
  struct type *sph_root; /* root of the tree */     \
62
}
63
64
#define SPLAY_INITIALIZER(root)           \
65
  { NULL }
66
67
#define SPLAY_INIT(root) do {           \
68
  (root)->sph_root = NULL;          \
69
} while (0)
70
71
#define SPLAY_ENTRY(type)           \
72
struct {                \
73
  struct type *spe_left; /* left element */     \
74
  struct type *spe_right; /* right element */     \
75
}
76
77
#define SPLAY_LEFT(elm, field)    (elm)->field.spe_left
78
#define SPLAY_RIGHT(elm, field)   (elm)->field.spe_right
79
#define SPLAY_ROOT(head)    (head)->sph_root
80
#define SPLAY_EMPTY(head)   (SPLAY_ROOT(head) == NULL)
81
82
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
83
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do {     \
84
  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);  \
85
  SPLAY_RIGHT(tmp, field) = (head)->sph_root;     \
86
  (head)->sph_root = tmp;           \
87
} while (0)
88
89
#define SPLAY_ROTATE_LEFT(head, tmp, field) do {      \
90
  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);  \
91
  SPLAY_LEFT(tmp, field) = (head)->sph_root;      \
92
  (head)->sph_root = tmp;           \
93
} while (0)
94
95
#define SPLAY_LINKLEFT(head, tmp, field) do {       \
96
  SPLAY_LEFT(tmp, field) = (head)->sph_root;      \
97
  tmp = (head)->sph_root;           \
98
  (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);   \
99
} while (0)
100
101
#define SPLAY_LINKRIGHT(head, tmp, field) do {        \
102
  SPLAY_RIGHT(tmp, field) = (head)->sph_root;     \
103
  tmp = (head)->sph_root;           \
104
  (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);  \
105
} while (0)
106
107
#define SPLAY_ASSEMBLE(head, node, left, right, field) do {   \
108
  SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
109
  SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
110
  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
111
  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
112
} while (0)
113
114
/* Generates prototypes and inline functions */
115
116
#define SPLAY_PROTOTYPE(name, type, field, cmp)       \
117
void name##_SPLAY(struct name *, struct type *);      \
118
void name##_SPLAY_MINMAX(struct name *, int);       \
119
struct type *name##_SPLAY_INSERT(struct name *, struct type *);   \
120
struct type *name##_SPLAY_REMOVE(struct name *, struct type *);   \
121
                  \
122
/* Finds the node with the same key as elm */       \
123
static __unused __inline struct type *          \
124
name##_SPLAY_FIND(struct name *head, struct type *elm)      \
125
{                 \
126
  if (SPLAY_EMPTY(head))            \
127
    return(NULL);           \
128
  name##_SPLAY(head, elm);          \
129
  if ((cmp)(elm, (head)->sph_root) == 0)        \
130
    return (head->sph_root);        \
131
  return (NULL);              \
132
}                 \
133
                  \
134
static __unused __inline struct type *          \
135
name##_SPLAY_NEXT(struct name *head, struct type *elm)      \
136
{                 \
137
  name##_SPLAY(head, elm);          \
138
  if (SPLAY_RIGHT(elm, field) != NULL) {        \
139
    elm = SPLAY_RIGHT(elm, field);        \
140
    while (SPLAY_LEFT(elm, field) != NULL) {    \
141
      elm = SPLAY_LEFT(elm, field);     \
142
    }             \
143
  } else                \
144
    elm = NULL;           \
145
  return (elm);             \
146
}                 \
147
                  \
148
static __unused __inline struct type *          \
149
name##_SPLAY_MIN_MAX(struct name *head, int val)      \
150
{                 \
151
  name##_SPLAY_MINMAX(head, val);         \
152
        return (SPLAY_ROOT(head));          \
153
}
154
155
/* Main splay operation.
156
 * Moves node close to the key of elm to top
157
 */
158
#define SPLAY_GENERATE(name, type, field, cmp)        \
159
struct type *               \
160
name##_SPLAY_INSERT(struct name *head, struct type *elm)    \
161
{                 \
162
    if (SPLAY_EMPTY(head)) {            \
163
      SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL;  \
164
    } else {                \
165
      int __comp;             \
166
      name##_SPLAY(head, elm);          \
167
      __comp = (cmp)(elm, (head)->sph_root);      \
168
      if(__comp < 0) {            \
169
        SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
170
        SPLAY_RIGHT(elm, field) = (head)->sph_root;   \
171
        SPLAY_LEFT((head)->sph_root, field) = NULL;   \
172
      } else if (__comp > 0) {          \
173
        SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
174
        SPLAY_LEFT(elm, field) = (head)->sph_root;    \
175
        SPLAY_RIGHT((head)->sph_root, field) = NULL;  \
176
      } else              \
177
        return ((head)->sph_root);        \
178
    }                 \
179
    (head)->sph_root = (elm);           \
180
    return (NULL);              \
181
}                 \
182
                  \
183
struct type *               \
184
name##_SPLAY_REMOVE(struct name *head, struct type *elm)    \
185
{                 \
186
  struct type *__tmp;           \
187
  if (SPLAY_EMPTY(head))            \
188
    return (NULL);            \
189
  name##_SPLAY(head, elm);          \
190
  if ((cmp)(elm, (head)->sph_root) == 0) {      \
191
    if (SPLAY_LEFT((head)->sph_root, field) == NULL) {  \
192
      (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
193
    } else {            \
194
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
195
      (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
196
      name##_SPLAY(head, elm);      \
197
      SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
198
    }             \
199
    return (elm);           \
200
  }               \
201
  return (NULL);              \
202
}                 \
203
                  \
204
void                  \
205
name##_SPLAY(struct name *head, struct type *elm)     \
206
{                 \
207
  struct type __node, *__left, *__right, *__tmp;      \
208
  int __comp;             \
209
\
210
  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
211
  __left = __right = &__node;         \
212
\
213
  while ((__comp = (cmp)(elm, (head)->sph_root))) {   \
214
    if (__comp < 0) {         \
215
      __tmp = SPLAY_LEFT((head)->sph_root, field);  \
216
      if (__tmp == NULL)        \
217
        break;          \
218
      if ((cmp)(elm, __tmp) < 0){     \
219
        SPLAY_ROTATE_RIGHT(head, __tmp, field); \
220
        if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
221
          break;        \
222
      }           \
223
      SPLAY_LINKLEFT(head, __right, field);   \
224
    } else if (__comp > 0) {        \
225
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
226
      if (__tmp == NULL)        \
227
        break;          \
228
      if ((cmp)(elm, __tmp) > 0){     \
229
        SPLAY_ROTATE_LEFT(head, __tmp, field);  \
230
        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
231
          break;        \
232
      }           \
233
      SPLAY_LINKRIGHT(head, __left, field);   \
234
    }             \
235
  }               \
236
  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);    \
237
}                 \
238
                  \
239
/* Splay with either the minimum or the maximum element     \
240
 * Used to find minimum or maximum element in tree.     \
241
 */                 \
242
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
243
{                 \
244
  struct type __node, *__left, *__right, *__tmp;      \
245
\
246
  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
247
  __left = __right = &__node;         \
248
\
249
  while (1) {             \
250
    if (__comp < 0) {         \
251
      __tmp = SPLAY_LEFT((head)->sph_root, field);  \
252
      if (__tmp == NULL)        \
253
        break;          \
254
      if (__comp < 0){        \
255
        SPLAY_ROTATE_RIGHT(head, __tmp, field); \
256
        if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
257
          break;        \
258
      }           \
259
      SPLAY_LINKLEFT(head, __right, field);   \
260
    } else if (__comp > 0) {        \
261
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
262
      if (__tmp == NULL)        \
263
        break;          \
264
      if (__comp > 0) {       \
265
        SPLAY_ROTATE_LEFT(head, __tmp, field);  \
266
        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
267
          break;        \
268
      }           \
269
      SPLAY_LINKRIGHT(head, __left, field);   \
270
    }             \
271
  }               \
272
  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);    \
273
}
274
275
#define SPLAY_NEGINF  -1
276
#define SPLAY_INF 1
277
278
#define SPLAY_INSERT(name, x, y)  name##_SPLAY_INSERT(x, y)
279
#define SPLAY_REMOVE(name, x, y)  name##_SPLAY_REMOVE(x, y)
280
#define SPLAY_FIND(name, x, y)    name##_SPLAY_FIND(x, y)
281
#define SPLAY_NEXT(name, x, y)    name##_SPLAY_NEXT(x, y)
282
#define SPLAY_MIN(name, x)    (SPLAY_EMPTY(x) ? NULL  \
283
          : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
284
#define SPLAY_MAX(name, x)    (SPLAY_EMPTY(x) ? NULL  \
285
          : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
286
287
#define SPLAY_FOREACH(x, name, head)          \
288
  for ((x) = SPLAY_MIN(name, head);       \
289
       (x) != NULL;           \
290
       (x) = SPLAY_NEXT(name, head, x))
291
292
/* Macros that define a red-black tree */
293
#define RB_HEAD(name, type)           \
294
struct name {               \
295
  struct type *rbh_root; /* root of the tree */     \
296
}
297
298
#define RB_INITIALIZER(root)            \
299
  { NULL }
300
301
#define RB_INIT(root) do {            \
302
  (root)->rbh_root = NULL;          \
303
} while (0)
304
305
#define RB_BLACK  0
306
#define RB_RED    1
307
#define RB_ENTRY(type)              \
308
struct {                \
309
  struct type *rbe_left;    /* left element */    \
310
  struct type *rbe_right;   /* right element */   \
311
  struct type *rbe_parent;  /* parent element */    \
312
  int rbe_color;      /* node color */    \
313
}
314
315
#define RB_LEFT(elm, field)   (elm)->field.rbe_left
316
#define RB_RIGHT(elm, field)    (elm)->field.rbe_right
317
#define RB_PARENT(elm, field)   (elm)->field.rbe_parent
318
#define RB_COLOR(elm, field)    (elm)->field.rbe_color
319
#define RB_ROOT(head)     (head)->rbh_root
320
#define RB_EMPTY(head)      (RB_ROOT(head) == NULL)
321
322
#define RB_SET(elm, parent, field) do {         \
323
  RB_PARENT(elm, field) = parent;         \
324
  RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;    \
325
  RB_COLOR(elm, field) = RB_RED;          \
326
} while (0)
327
328
#define RB_SET_BLACKRED(black, red, field) do {       \
329
  RB_COLOR(black, field) = RB_BLACK;        \
330
  RB_COLOR(red, field) = RB_RED;          \
331
} while (0)
332
333
#ifndef RB_AUGMENT
334
#define RB_AUGMENT(x) do {} while (0)
335
#endif
336
337
#define RB_ROTATE_LEFT(head, elm, tmp, field) do {      \
338
  (tmp) = RB_RIGHT(elm, field);         \
339
  if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) {   \
340
    RB_PARENT(RB_LEFT(tmp, field), field) = (elm);    \
341
  }               \
342
  RB_AUGMENT(elm);            \
343
  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {    \
344
    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
345
      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
346
    else              \
347
      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
348
  } else                \
349
    (head)->rbh_root = (tmp);       \
350
  RB_LEFT(tmp, field) = (elm);          \
351
  RB_PARENT(elm, field) = (tmp);          \
352
  RB_AUGMENT(tmp);            \
353
  if ((RB_PARENT(tmp, field)))          \
354
    RB_AUGMENT(RB_PARENT(tmp, field));      \
355
} while (0)
356
357
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do {     \
358
  (tmp) = RB_LEFT(elm, field);          \
359
  if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) {   \
360
    RB_PARENT(RB_RIGHT(tmp, field), field) = (elm);   \
361
  }               \
362
  RB_AUGMENT(elm);            \
363
  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {    \
364
    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
365
      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
366
    else              \
367
      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
368
  } else                \
369
    (head)->rbh_root = (tmp);       \
370
  RB_RIGHT(tmp, field) = (elm);         \
371
  RB_PARENT(elm, field) = (tmp);          \
372
  RB_AUGMENT(tmp);            \
373
  if ((RB_PARENT(tmp, field)))          \
374
    RB_AUGMENT(RB_PARENT(tmp, field));      \
375
} while (0)
376
377
/* Generates prototypes and inline functions */
378
#define RB_PROTOTYPE(name, type, field, cmp)        \
379
  RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
380
#define RB_PROTOTYPE_STATIC(name, type, field, cmp)     \
381
  RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
382
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr)   \
383
attr void name##_RB_INSERT_COLOR(struct name *, struct type *);   \
384
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
385
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
386
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
387
attr struct type *name##_RB_FIND(struct name *, struct type *);   \
388
attr struct type *name##_RB_NFIND(struct name *, struct type *);  \
389
attr struct type *name##_RB_NEXT(struct type *);      \
390
attr struct type *name##_RB_PREV(struct type *);      \
391
attr struct type *name##_RB_MINMAX(struct name *, int);     \
392
                  \
393
394
/* Main rb operation.
395
 * Moves node close to the key of elm to top
396
 */
397
#define RB_GENERATE(name, type, field, cmp)       \
398
  RB_GENERATE_INTERNAL(name, type, field, cmp,)
399
#define RB_GENERATE_STATIC(name, type, field, cmp)      \
400
  RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
401
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr)    \
402
attr void               \
403
name##_RB_INSERT_COLOR(struct name *head, struct type *elm)   \
404
{                 \
405
  struct type *parent, *gparent, *tmp;        \
406
  while ((parent = RB_PARENT(elm, field)) &&      \
407
      RB_COLOR(parent, field) == RB_RED) {      \
408
    gparent = RB_PARENT(parent, field);     \
409
    if (parent == RB_LEFT(gparent, field)) {    \
410
      tmp = RB_RIGHT(gparent, field);     \
411
      if (tmp && RB_COLOR(tmp, field) == RB_RED) {  \
412
        RB_COLOR(tmp, field) = RB_BLACK;  \
413
        RB_SET_BLACKRED(parent, gparent, field);\
414
        elm = gparent;        \
415
        continue;       \
416
      }           \
417
      if (RB_RIGHT(parent, field) == elm) {   \
418
        RB_ROTATE_LEFT(head, parent, tmp, field);\
419
        tmp = parent;       \
420
        parent = elm;       \
421
        elm = tmp;        \
422
      }           \
423
      RB_SET_BLACKRED(parent, gparent, field);  \
424
      RB_ROTATE_RIGHT(head, gparent, tmp, field); \
425
    } else {            \
426
      tmp = RB_LEFT(gparent, field);      \
427
      if (tmp && RB_COLOR(tmp, field) == RB_RED) {  \
428
        RB_COLOR(tmp, field) = RB_BLACK;  \
429
        RB_SET_BLACKRED(parent, gparent, field);\
430
        elm = gparent;        \
431
        continue;       \
432
      }           \
433
      if (RB_LEFT(parent, field) == elm) {    \
434
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
435
        tmp = parent;       \
436
        parent = elm;       \
437
        elm = tmp;        \
438
      }           \
439
      RB_SET_BLACKRED(parent, gparent, field);  \
440
      RB_ROTATE_LEFT(head, gparent, tmp, field);  \
441
    }             \
442
  }               \
443
  RB_COLOR(head->rbh_root, field) = RB_BLACK;     \
444
}                 \
445
                  \
446
attr void               \
447
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
448
{                 \
449
  struct type *tmp;           \
450
  while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
451
      elm != RB_ROOT(head)) {         \
452
    if (RB_LEFT(parent, field) == elm) {      \
453
      tmp = RB_RIGHT(parent, field);      \
454
      if (RB_COLOR(tmp, field) == RB_RED) {   \
455
        RB_SET_BLACKRED(tmp, parent, field);  \
456
        RB_ROTATE_LEFT(head, parent, tmp, field);\
457
        tmp = RB_RIGHT(parent, field);    \
458
      }           \
459
      if ((RB_LEFT(tmp, field) == NULL ||   \
460
          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
461
          (RB_RIGHT(tmp, field) == NULL ||    \
462
          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
463
        RB_COLOR(tmp, field) = RB_RED;    \
464
        elm = parent;       \
465
        parent = RB_PARENT(elm, field);   \
466
      } else {          \
467
        if (RB_RIGHT(tmp, field) == NULL || \
468
            RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
469
          struct type *oleft;   \
470
          if ((oleft = RB_LEFT(tmp, field)))\
471
            RB_COLOR(oleft, field) = RB_BLACK;\
472
          RB_COLOR(tmp, field) = RB_RED;  \
473
          RB_ROTATE_RIGHT(head, tmp, oleft, field);\
474
          tmp = RB_RIGHT(parent, field);  \
475
        }         \
476
        RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
477
        RB_COLOR(parent, field) = RB_BLACK; \
478
        if (RB_RIGHT(tmp, field))   \
479
          RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
480
        RB_ROTATE_LEFT(head, parent, tmp, field);\
481
        elm = RB_ROOT(head);      \
482
        break;          \
483
      }           \
484
    } else {            \
485
      tmp = RB_LEFT(parent, field);     \
486
      if (RB_COLOR(tmp, field) == RB_RED) {   \
487
        RB_SET_BLACKRED(tmp, parent, field);  \
488
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
489
        tmp = RB_LEFT(parent, field);   \
490
      }           \
491
      if ((RB_LEFT(tmp, field) == NULL ||   \
492
          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
493
          (RB_RIGHT(tmp, field) == NULL ||    \
494
          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
495
        RB_COLOR(tmp, field) = RB_RED;    \
496
        elm = parent;       \
497
        parent = RB_PARENT(elm, field);   \
498
      } else {          \
499
        if (RB_LEFT(tmp, field) == NULL ||  \
500
            RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
501
          struct type *oright;    \
502
          if ((oright = RB_RIGHT(tmp, field)))\
503
            RB_COLOR(oright, field) = RB_BLACK;\
504
          RB_COLOR(tmp, field) = RB_RED;  \
505
          RB_ROTATE_LEFT(head, tmp, oright, field);\
506
          tmp = RB_LEFT(parent, field); \
507
        }         \
508
        RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
509
        RB_COLOR(parent, field) = RB_BLACK; \
510
        if (RB_LEFT(tmp, field))    \
511
          RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
512
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
513
        elm = RB_ROOT(head);      \
514
        break;          \
515
      }           \
516
    }             \
517
  }               \
518
  if (elm)              \
519
    RB_COLOR(elm, field) = RB_BLACK;      \
520
}                 \
521
                  \
522
attr struct type *              \
523
name##_RB_REMOVE(struct name *head, struct type *elm)     \
524
{                 \
525
  struct type *child, *parent, *old = elm;      \
526
  int color;              \
527
  if (RB_LEFT(elm, field) == NULL)        \
528
    child = RB_RIGHT(elm, field);       \
529
  else if (RB_RIGHT(elm, field) == NULL)        \
530
    child = RB_LEFT(elm, field);        \
531
  else {                \
532
    struct type *left;          \
533
    elm = RB_RIGHT(elm, field);       \
534
    while ((left = RB_LEFT(elm, field)))      \
535
      elm = left;         \
536
    child = RB_RIGHT(elm, field);       \
537
    parent = RB_PARENT(elm, field);       \
538
    color = RB_COLOR(elm, field);       \
539
    if (child)            \
540
      RB_PARENT(child, field) = parent;   \
541
    if (parent) {           \
542
      if (RB_LEFT(parent, field) == elm)    \
543
        RB_LEFT(parent, field) = child;   \
544
      else            \
545
        RB_RIGHT(parent, field) = child;  \
546
      RB_AUGMENT(parent);       \
547
    } else              \
548
      RB_ROOT(head) = child;        \
549
    if (RB_PARENT(elm, field) == old)     \
550
      parent = elm;         \
551
    (elm)->field = (old)->field;        \
552
    if (RB_PARENT(old, field)) {        \
553
      if (RB_LEFT(RB_PARENT(old, field), field) == old)\
554
        RB_LEFT(RB_PARENT(old, field), field) = elm;\
555
      else            \
556
        RB_RIGHT(RB_PARENT(old, field), field) = elm;\
557
      RB_AUGMENT(RB_PARENT(old, field));    \
558
    } else              \
559
      RB_ROOT(head) = elm;        \
560
    RB_PARENT(RB_LEFT(old, field), field) = elm;    \
561
    if (RB_RIGHT(old, field))       \
562
      RB_PARENT(RB_RIGHT(old, field), field) = elm; \
563
    if (parent) {           \
564
      left = parent;          \
565
      do {            \
566
        RB_AUGMENT(left);     \
567
      } while ((left = RB_PARENT(left, field)));  \
568
    }             \
569
    goto color;           \
570
  }               \
571
  parent = RB_PARENT(elm, field);         \
572
  color = RB_COLOR(elm, field);         \
573
  if (child)              \
574
    RB_PARENT(child, field) = parent;     \
575
  if (parent) {             \
576
    if (RB_LEFT(parent, field) == elm)      \
577
      RB_LEFT(parent, field) = child;     \
578
    else              \
579
      RB_RIGHT(parent, field) = child;    \
580
    RB_AUGMENT(parent);         \
581
  } else                \
582
    RB_ROOT(head) = child;          \
583
color:                  \
584
  if (color == RB_BLACK)            \
585
    name##_RB_REMOVE_COLOR(head, parent, child);    \
586
  return (old);             \
587
}                 \
588
                  \
589
/* Inserts a node into the RB tree */         \
590
attr struct type *              \
591
name##_RB_INSERT(struct name *head, struct type *elm)     \
592
{                 \
593
  struct type *tmp;           \
594
  struct type *parent = NULL;         \
595
  int comp = 0;             \
596
  tmp = RB_ROOT(head);            \
597
  while (tmp) {             \
598
    parent = tmp;           \
599
    comp = (cmp)(elm, parent);        \
600
    if (comp < 0)           \
601
      tmp = RB_LEFT(tmp, field);      \
602
    else if (comp > 0)          \
603
      tmp = RB_RIGHT(tmp, field);     \
604
    else              \
605
      return (tmp);         \
606
  }               \
607
  RB_SET(elm, parent, field);         \
608
  if (parent != NULL) {           \
609
    if (comp < 0)           \
610
      RB_LEFT(parent, field) = elm;     \
611
    else              \
612
      RB_RIGHT(parent, field) = elm;      \
613
    RB_AUGMENT(parent);         \
614
  } else                \
615
    RB_ROOT(head) = elm;          \
616
  name##_RB_INSERT_COLOR(head, elm);        \
617
  return (NULL);              \
618
}                 \
619
                  \
620
/* Finds the node with the same key as elm */       \
621
attr struct type *              \
622
name##_RB_FIND(struct name *head, struct type *elm)     \
623
{                 \
624
  struct type *tmp = RB_ROOT(head);       \
625
  int comp;             \
626
  while (tmp) {             \
627
    comp = cmp(elm, tmp);         \
628
    if (comp < 0)           \
629
      tmp = RB_LEFT(tmp, field);      \
630
    else if (comp > 0)          \
631
      tmp = RB_RIGHT(tmp, field);     \
632
    else              \
633
      return (tmp);         \
634
  }               \
635
  return (NULL);              \
636
}                 \
637
                  \
638
/* Finds the first node greater than or equal to the search key */  \
639
attr struct type *              \
640
name##_RB_NFIND(struct name *head, struct type *elm)      \
641
{                 \
642
  struct type *tmp = RB_ROOT(head);       \
643
  struct type *res = NULL;          \
644
  int comp;             \
645
  while (tmp) {             \
646
    comp = cmp(elm, tmp);         \
647
    if (comp < 0) {           \
648
      res = tmp;          \
649
      tmp = RB_LEFT(tmp, field);      \
650
    }             \
651
    else if (comp > 0)          \
652
      tmp = RB_RIGHT(tmp, field);     \
653
    else              \
654
      return (tmp);         \
655
  }               \
656
  return (res);             \
657
}                 \
658
                  \
659
attr struct type *              \
660
name##_RB_NEXT(struct type *elm)          \
661
{                 \
662
  if (RB_RIGHT(elm, field)) {         \
663
    elm = RB_RIGHT(elm, field);       \
664
    while (RB_LEFT(elm, field))       \
665
      elm = RB_LEFT(elm, field);      \
666
  } else {              \
667
    if (RB_PARENT(elm, field) &&        \
668
        (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
669
      elm = RB_PARENT(elm, field);      \
670
    else {              \
671
      while (RB_PARENT(elm, field) &&     \
672
          (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
673
        elm = RB_PARENT(elm, field);    \
674
      elm = RB_PARENT(elm, field);      \
675
    }             \
676
  }               \
677
  return (elm);             \
678
}                 \
679
                  \
680
attr struct type *              \
681
name##_RB_PREV(struct type *elm)          \
682
{                 \
683
  if (RB_LEFT(elm, field)) {          \
684
    elm = RB_LEFT(elm, field);        \
685
    while (RB_RIGHT(elm, field))        \
686
      elm = RB_RIGHT(elm, field);     \
687
  } else {              \
688
    if (RB_PARENT(elm, field) &&        \
689
        (elm == RB_RIGHT(RB_PARENT(elm, field), field)))  \
690
      elm = RB_PARENT(elm, field);      \
691
    else {              \
692
      while (RB_PARENT(elm, field) &&     \
693
          (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
694
        elm = RB_PARENT(elm, field);    \
695
      elm = RB_PARENT(elm, field);      \
696
    }             \
697
  }               \
698
  return (elm);             \
699
}                 \
700
                  \
701
attr struct type *              \
702
name##_RB_MINMAX(struct name *head, int val)        \
703
{                 \
704
  struct type *tmp = RB_ROOT(head);       \
705
  struct type *parent = NULL;         \
706
  while (tmp) {             \
707
    parent = tmp;           \
708
    if (val < 0)            \
709
      tmp = RB_LEFT(tmp, field);      \
710
    else              \
711
      tmp = RB_RIGHT(tmp, field);     \
712
  }               \
713
  return (parent);            \
714
}
715
716
#define RB_NEGINF -1
717
#define RB_INF  1
718
719
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
720
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
721
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
722
#define RB_NFIND(name, x, y)  name##_RB_NFIND(x, y)
723
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
724
#define RB_PREV(name, x, y) name##_RB_PREV(y)
725
#define RB_MIN(name, x)   name##_RB_MINMAX(x, RB_NEGINF)
726
#define RB_MAX(name, x)   name##_RB_MINMAX(x, RB_INF)
727
728
#define RB_FOREACH(x, name, head)         \
729
  for ((x) = RB_MIN(name, head);          \
730
       (x) != NULL;           \
731
       (x) = name##_RB_NEXT(x))
732
733
#define RB_FOREACH_SAFE(x, name, head, y)       \
734
  for ((x) = RB_MIN(name, head);          \
735
      ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1);    \
736
       (x) = (y))
737
738
#define RB_FOREACH_REVERSE(x, name, head)       \
739
  for ((x) = RB_MAX(name, head);          \
740
       (x) != NULL;           \
741
       (x) = name##_RB_PREV(x))
742
743
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y)     \
744
  for ((x) = RB_MAX(name, head);          \
745
      ((x) != NULL) && ((y) = name##_RB_PREV(x), 1);    \
746
       (x) = (y))
747
748
749
/*
750
 * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
751
 *
752
 * Permission to use, copy, modify, and distribute this software for any
753
 * purpose with or without fee is hereby granted, provided that the above
754
 * copyright notice and this permission notice appear in all copies.
755
 *
756
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
757
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
758
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
759
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
760
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
761
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
762
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
763
 */
764
765
struct rb_type {
766
  int   (*t_compare)(const void *, const void *);
767
  void    (*t_augment)(void *);
768
  unsigned int    t_offset; /* offset of rb_entry in type */
769
};
770
771
struct rb_tree {
772
  struct rb_entry *rbt_root;
773
};
774
775
struct rb_entry {
776
  struct rb_entry  *rbt_parent;
777
  struct rb_entry  *rbt_left;
778
  struct rb_entry  *rbt_right;
779
  unsigned int    rbt_color;
780
};
781
782
#define RBT_HEAD(_name, _type)            \
783
struct _name {                \
784
  struct rb_tree rbh_root;          \
785
}
786
787
#define RBT_ENTRY(_type)  struct rb_entry
788
789
static inline void
790
_rb_init(struct rb_tree *rbt)
791
0
{
792
0
  rbt->rbt_root = NULL;
793
0
}
Unexecuted instantiation: common.c:_rb_init
Unexecuted instantiation: test_parser_fuzz.c:_rb_init
Unexecuted instantiation: ikev2_pld.c:_rb_init
Unexecuted instantiation: imsg_util.c:_rb_init
Unexecuted instantiation: util.c:_rb_init
794
795
static inline int
796
_rb_empty(struct rb_tree *rbt)
797
0
{
798
0
  return (rbt->rbt_root == NULL);
799
0
}
Unexecuted instantiation: common.c:_rb_empty
Unexecuted instantiation: test_parser_fuzz.c:_rb_empty
Unexecuted instantiation: ikev2_pld.c:_rb_empty
Unexecuted instantiation: imsg_util.c:_rb_empty
Unexecuted instantiation: util.c:_rb_empty
800
801
void  *_rb_insert(const struct rb_type *, struct rb_tree *, void *);
802
void  *_rb_remove(const struct rb_type *, struct rb_tree *, void *);
803
void  *_rb_find(const struct rb_type *, struct rb_tree *, const void *);
804
void  *_rb_nfind(const struct rb_type *, struct rb_tree *, const void *);
805
void  *_rb_root(const struct rb_type *, struct rb_tree *);
806
void  *_rb_min(const struct rb_type *, struct rb_tree *);
807
void  *_rb_max(const struct rb_type *, struct rb_tree *);
808
void  *_rb_next(const struct rb_type *, void *);
809
void  *_rb_prev(const struct rb_type *, void *);
810
void  *_rb_left(const struct rb_type *, void *);
811
void  *_rb_right(const struct rb_type *, void *);
812
void  *_rb_parent(const struct rb_type *, void *);
813
void   _rb_set_left(const struct rb_type *, void *, void *);
814
void   _rb_set_right(const struct rb_type *, void *, void *);
815
void   _rb_set_parent(const struct rb_type *, void *, void *);
816
void   _rb_poison(const struct rb_type *, void *, unsigned long);
817
int  _rb_check(const struct rb_type *, void *, unsigned long);
818
819
#define RBT_INITIALIZER(_head)  { { NULL } }
820
821
#define RBT_PROTOTYPE(_name, _type, _field, _cmp)     \
822
extern const struct rb_type *const _name##_RBT_TYPE;      \
823
                  \
824
__unused static inline void           \
825
_name##_RBT_INIT(struct _name *head)          \
826
{                 \
827
  _rb_init(&head->rbh_root);          \
828
}                 \
829
                  \
830
__unused static inline struct _type *         \
831
_name##_RBT_INSERT(struct _name *head, struct _type *elm)   \
832
{                 \
833
  return _rb_insert(_name##_RBT_TYPE, &head->rbh_root, elm);  \
834
}                 \
835
                  \
836
__unused static inline struct _type *         \
837
_name##_RBT_REMOVE(struct _name *head, struct _type *elm)   \
838
{                 \
839
  return _rb_remove(_name##_RBT_TYPE, &head->rbh_root, elm);  \
840
}                 \
841
                  \
842
__unused static inline struct _type *         \
843
_name##_RBT_FIND(struct _name *head, const struct _type *key)   \
844
{                 \
845
  return _rb_find(_name##_RBT_TYPE, &head->rbh_root, key);  \
846
}                 \
847
                  \
848
__unused static inline struct _type *         \
849
_name##_RBT_NFIND(struct _name *head, const struct _type *key)    \
850
{                 \
851
  return _rb_nfind(_name##_RBT_TYPE, &head->rbh_root, key); \
852
}                 \
853
                  \
854
__unused static inline struct _type *         \
855
_name##_RBT_ROOT(struct _name *head)          \
856
{                 \
857
  return _rb_root(_name##_RBT_TYPE, &head->rbh_root);   \
858
}                 \
859
                  \
860
__unused static inline int            \
861
_name##_RBT_EMPTY(struct _name *head)         \
862
{                 \
863
  return _rb_empty(&head->rbh_root);        \
864
}                 \
865
                  \
866
__unused static inline struct _type *         \
867
_name##_RBT_MIN(struct _name *head)         \
868
{                 \
869
  return _rb_min(_name##_RBT_TYPE, &head->rbh_root);    \
870
}                 \
871
                  \
872
__unused static inline struct _type *         \
873
_name##_RBT_MAX(struct _name *head)         \
874
{                 \
875
  return _rb_max(_name##_RBT_TYPE, &head->rbh_root);    \
876
}                 \
877
                  \
878
__unused static inline struct _type *         \
879
_name##_RBT_NEXT(struct _type *elm)         \
880
{                 \
881
  return _rb_next(_name##_RBT_TYPE, elm);       \
882
}                 \
883
                  \
884
__unused static inline struct _type *         \
885
_name##_RBT_PREV(struct _type *elm)         \
886
{                 \
887
  return _rb_prev(_name##_RBT_TYPE, elm);       \
888
}                 \
889
                  \
890
__unused static inline struct _type *         \
891
_name##_RBT_LEFT(struct _type *elm)         \
892
{                 \
893
  return _rb_left(_name##_RBT_TYPE, elm);       \
894
}                 \
895
                  \
896
__unused static inline struct _type *         \
897
_name##_RBT_RIGHT(struct _type *elm)          \
898
{                 \
899
  return _rb_right(_name##_RBT_TYPE, elm);      \
900
}                 \
901
                  \
902
__unused static inline struct _type *         \
903
_name##_RBT_PARENT(struct _type *elm)         \
904
{                 \
905
  return _rb_parent(_name##_RBT_TYPE, elm);     \
906
}                 \
907
                  \
908
__unused static inline void           \
909
_name##_RBT_SET_LEFT(struct _type *elm, struct _type *left)   \
910
{                 \
911
  _rb_set_left(_name##_RBT_TYPE, elm, left);      \
912
}                 \
913
                  \
914
__unused static inline void           \
915
_name##_RBT_SET_RIGHT(struct _type *elm, struct _type *right)   \
916
{                 \
917
  _rb_set_right(_name##_RBT_TYPE, elm, right);      \
918
}                 \
919
                  \
920
__unused static inline void           \
921
_name##_RBT_SET_PARENT(struct _type *elm, struct _type *parent)   \
922
{                 \
923
  _rb_set_parent(_name##_RBT_TYPE, elm, parent);      \
924
}                 \
925
                  \
926
__unused static inline void           \
927
_name##_RBT_POISON(struct _type *elm, unsigned long poison)   \
928
{                 \
929
  _rb_poison(_name##_RBT_TYPE, elm, poison);      \
930
}                 \
931
                  \
932
__unused static inline int            \
933
_name##_RBT_CHECK(struct _type *elm, unsigned long poison)    \
934
{                 \
935
  return _rb_check(_name##_RBT_TYPE, elm, poison);    \
936
}
937
938
#define RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug)   \
939
static int                \
940
_name##_RBT_COMPARE(const void *lptr, const void *rptr)     \
941
{                 \
942
  const struct _type *l = lptr, *r = rptr;      \
943
  return _cmp(l, r);            \
944
}                 \
945
static const struct rb_type _name##_RBT_INFO = {      \
946
  _name##_RBT_COMPARE,            \
947
  _aug,               \
948
  offsetof(struct _type, _field),         \
949
};                  \
950
const struct rb_type *const _name##_RBT_TYPE = &_name##_RBT_INFO
951
952
#define RBT_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug)    \
953
static void               \
954
_name##_RBT_AUGMENT(void *ptr)            \
955
{                 \
956
  struct _type *p = ptr;            \
957
  return _aug(p);             \
958
}                 \
959
RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RBT_AUGMENT)
960
961
#define RBT_GENERATE(_name, _type, _field, _cmp)      \
962
    RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL)
963
964
#define RBT_INIT(_name, _head)    _name##_RBT_INIT(_head)
965
#define RBT_INSERT(_name, _head, _elm)  _name##_RBT_INSERT(_head, _elm)
966
#define RBT_REMOVE(_name, _head, _elm)  _name##_RBT_REMOVE(_head, _elm)
967
#define RBT_FIND(_name, _head, _key)  _name##_RBT_FIND(_head, _key)
968
#define RBT_NFIND(_name, _head, _key) _name##_RBT_NFIND(_head, _key)
969
#define RBT_ROOT(_name, _head)    _name##_RBT_ROOT(_head)
970
#define RBT_EMPTY(_name, _head)   _name##_RBT_EMPTY(_head)
971
#define RBT_MIN(_name, _head)   _name##_RBT_MIN(_head)
972
#define RBT_MAX(_name, _head)   _name##_RBT_MAX(_head)
973
#define RBT_NEXT(_name, _elm)   _name##_RBT_NEXT(_elm)
974
#define RBT_PREV(_name, _elm)   _name##_RBT_PREV(_elm)
975
#define RBT_LEFT(_name, _elm)   _name##_RBT_LEFT(_elm)
976
#define RBT_RIGHT(_name, _elm)    _name##_RBT_RIGHT(_elm)
977
#define RBT_PARENT(_name, _elm)   _name##_RBT_PARENT(_elm)
978
#define RBT_SET_LEFT(_name, _elm, _l) _name##_RBT_SET_LEFT(_elm, _l)
979
#define RBT_SET_RIGHT(_name, _elm, _r)  _name##_RBT_SET_RIGHT(_elm, _r)
980
#define RBT_SET_PARENT(_name, _elm, _p) _name##_RBT_SET_PARENT(_elm, _p)
981
#define RBT_POISON(_name, _elm, _p) _name##_RBT_POISON(_elm, _p)
982
#define RBT_CHECK(_name, _elm, _p)  _name##_RBT_CHECK(_elm, _p)
983
984
#define RBT_FOREACH(_e, _name, _head)         \
985
  for ((_e) = RBT_MIN(_name, (_head));        \
986
       (_e) != NULL;            \
987
       (_e) = RBT_NEXT(_name, (_e)))
988
989
#define RBT_FOREACH_SAFE(_e, _name, _head, _n)        \
990
  for ((_e) = RBT_MIN(_name, (_head));        \
991
       (_e) != NULL && ((_n) = RBT_NEXT(_name, (_e)), 1); \
992
       (_e) = (_n))
993
994
#define RBT_FOREACH_REVERSE(_e, _name, _head)       \
995
  for ((_e) = RBT_MAX(_name, (_head));        \
996
       (_e) != NULL;            \
997
       (_e) = RBT_PREV(_name, (_e)))
998
999
#define RBT_FOREACH_REVERSE_SAFE(_e, _name, _head, _n)      \
1000
  for ((_e) = RBT_MAX(_name, (_head));        \
1001
       (_e) != NULL && ((_n) = RBT_PREV(_name, (_e)), 1); \
1002
       (_e) = (_n))
1003
1004
#endif  /* _SYS_TREE_H_ */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/sys/tree.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: tree.h,v 1.31 2023/03/08 04:43:09 guenther Exp $  */
2
/*
3
 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#ifndef _SYS_TREE_H_
28
#define _SYS_TREE_H_
29
30
#include <sys/_null.h>
31
32
/*
33
 * This file defines data structures for different types of trees:
34
 * splay trees and red-black trees.
35
 *
36
 * A splay tree is a self-organizing data structure.  Every operation
37
 * on the tree causes a splay to happen.  The splay moves the requested
38
 * node to the root of the tree and partly rebalances it.
39
 *
40
 * This has the benefit that request locality causes faster lookups as
41
 * the requested nodes move to the top of the tree.  On the other hand,
42
 * every lookup causes memory writes.
43
 *
44
 * The Balance Theorem bounds the total access time for m operations
45
 * and n inserts on an initially empty tree as O((m + n)lg n).  The
46
 * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
47
 *
48
 * A red-black tree is a binary search tree with the node color as an
49
 * extra attribute.  It fulfills a set of conditions:
50
 *  - every search path from the root to a leaf consists of the
51
 *    same number of black nodes,
52
 *  - each red node (except for the root) has a black parent,
53
 *  - each leaf node is black.
54
 *
55
 * Every operation on a red-black tree is bounded as O(lg n).
56
 * The maximum height of a red-black tree is 2lg (n+1).
57
 */
58
59
#define SPLAY_HEAD(name, type)            \
60
struct name {               \
61
  struct type *sph_root; /* root of the tree */     \
62
}
63
64
#define SPLAY_INITIALIZER(root)           \
65
  { NULL }
66
67
#define SPLAY_INIT(root) do {           \
68
  (root)->sph_root = NULL;          \
69
} while (0)
70
71
#define SPLAY_ENTRY(type)           \
72
struct {                \
73
  struct type *spe_left; /* left element */     \
74
  struct type *spe_right; /* right element */     \
75
}
76
77
#define SPLAY_LEFT(elm, field)    (elm)->field.spe_left
78
#define SPLAY_RIGHT(elm, field)   (elm)->field.spe_right
79
#define SPLAY_ROOT(head)    (head)->sph_root
80
#define SPLAY_EMPTY(head)   (SPLAY_ROOT(head) == NULL)
81
82
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
83
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do {     \
84
  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);  \
85
  SPLAY_RIGHT(tmp, field) = (head)->sph_root;     \
86
  (head)->sph_root = tmp;           \
87
} while (0)
88
89
#define SPLAY_ROTATE_LEFT(head, tmp, field) do {      \
90
  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);  \
91
  SPLAY_LEFT(tmp, field) = (head)->sph_root;      \
92
  (head)->sph_root = tmp;           \
93
} while (0)
94
95
#define SPLAY_LINKLEFT(head, tmp, field) do {       \
96
  SPLAY_LEFT(tmp, field) = (head)->sph_root;      \
97
  tmp = (head)->sph_root;           \
98
  (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);   \
99
} while (0)
100
101
#define SPLAY_LINKRIGHT(head, tmp, field) do {        \
102
  SPLAY_RIGHT(tmp, field) = (head)->sph_root;     \
103
  tmp = (head)->sph_root;           \
104
  (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);  \
105
} while (0)
106
107
#define SPLAY_ASSEMBLE(head, node, left, right, field) do {   \
108
  SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
109
  SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
110
  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
111
  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
112
} while (0)
113
114
/* Generates prototypes and inline functions */
115
116
#define SPLAY_PROTOTYPE(name, type, field, cmp)       \
117
void name##_SPLAY(struct name *, struct type *);      \
118
void name##_SPLAY_MINMAX(struct name *, int);       \
119
struct type *name##_SPLAY_INSERT(struct name *, struct type *);   \
120
struct type *name##_SPLAY_REMOVE(struct name *, struct type *);   \
121
                  \
122
/* Finds the node with the same key as elm */       \
123
static __unused __inline struct type *          \
124
name##_SPLAY_FIND(struct name *head, struct type *elm)      \
125
{                 \
126
  if (SPLAY_EMPTY(head))            \
127
    return(NULL);           \
128
  name##_SPLAY(head, elm);          \
129
  if ((cmp)(elm, (head)->sph_root) == 0)        \
130
    return (head->sph_root);        \
131
  return (NULL);              \
132
}                 \
133
                  \
134
static __unused __inline struct type *          \
135
name##_SPLAY_NEXT(struct name *head, struct type *elm)      \
136
{                 \
137
  name##_SPLAY(head, elm);          \
138
  if (SPLAY_RIGHT(elm, field) != NULL) {        \
139
    elm = SPLAY_RIGHT(elm, field);        \
140
    while (SPLAY_LEFT(elm, field) != NULL) {    \
141
      elm = SPLAY_LEFT(elm, field);     \
142
    }             \
143
  } else                \
144
    elm = NULL;           \
145
  return (elm);             \
146
}                 \
147
                  \
148
static __unused __inline struct type *          \
149
name##_SPLAY_MIN_MAX(struct name *head, int val)      \
150
{                 \
151
  name##_SPLAY_MINMAX(head, val);         \
152
        return (SPLAY_ROOT(head));          \
153
}
154
155
/* Main splay operation.
156
 * Moves node close to the key of elm to top
157
 */
158
#define SPLAY_GENERATE(name, type, field, cmp)        \
159
struct type *               \
160
name##_SPLAY_INSERT(struct name *head, struct type *elm)    \
161
{                 \
162
    if (SPLAY_EMPTY(head)) {            \
163
      SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL;  \
164
    } else {                \
165
      int __comp;             \
166
      name##_SPLAY(head, elm);          \
167
      __comp = (cmp)(elm, (head)->sph_root);      \
168
      if(__comp < 0) {            \
169
        SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
170
        SPLAY_RIGHT(elm, field) = (head)->sph_root;   \
171
        SPLAY_LEFT((head)->sph_root, field) = NULL;   \
172
      } else if (__comp > 0) {          \
173
        SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
174
        SPLAY_LEFT(elm, field) = (head)->sph_root;    \
175
        SPLAY_RIGHT((head)->sph_root, field) = NULL;  \
176
      } else              \
177
        return ((head)->sph_root);        \
178
    }                 \
179
    (head)->sph_root = (elm);           \
180
    return (NULL);              \
181
}                 \
182
                  \
183
struct type *               \
184
name##_SPLAY_REMOVE(struct name *head, struct type *elm)    \
185
{                 \
186
  struct type *__tmp;           \
187
  if (SPLAY_EMPTY(head))            \
188
    return (NULL);            \
189
  name##_SPLAY(head, elm);          \
190
  if ((cmp)(elm, (head)->sph_root) == 0) {      \
191
    if (SPLAY_LEFT((head)->sph_root, field) == NULL) {  \
192
      (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
193
    } else {            \
194
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
195
      (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
196
      name##_SPLAY(head, elm);      \
197
      SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
198
    }             \
199
    return (elm);           \
200
  }               \
201
  return (NULL);              \
202
}                 \
203
                  \
204
void                  \
205
name##_SPLAY(struct name *head, struct type *elm)     \
206
{                 \
207
  struct type __node, *__left, *__right, *__tmp;      \
208
  int __comp;             \
209
\
210
  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
211
  __left = __right = &__node;         \
212
\
213
  while ((__comp = (cmp)(elm, (head)->sph_root))) {   \
214
    if (__comp < 0) {         \
215
      __tmp = SPLAY_LEFT((head)->sph_root, field);  \
216
      if (__tmp == NULL)        \
217
        break;          \
218
      if ((cmp)(elm, __tmp) < 0){     \
219
        SPLAY_ROTATE_RIGHT(head, __tmp, field); \
220
        if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
221
          break;        \
222
      }           \
223
      SPLAY_LINKLEFT(head, __right, field);   \
224
    } else if (__comp > 0) {        \
225
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
226
      if (__tmp == NULL)        \
227
        break;          \
228
      if ((cmp)(elm, __tmp) > 0){     \
229
        SPLAY_ROTATE_LEFT(head, __tmp, field);  \
230
        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
231
          break;        \
232
      }           \
233
      SPLAY_LINKRIGHT(head, __left, field);   \
234
    }             \
235
  }               \
236
  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);    \
237
}                 \
238
                  \
239
/* Splay with either the minimum or the maximum element     \
240
 * Used to find minimum or maximum element in tree.     \
241
 */                 \
242
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
243
{                 \
244
  struct type __node, *__left, *__right, *__tmp;      \
245
\
246
  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
247
  __left = __right = &__node;         \
248
\
249
  while (1) {             \
250
    if (__comp < 0) {         \
251
      __tmp = SPLAY_LEFT((head)->sph_root, field);  \
252
      if (__tmp == NULL)        \
253
        break;          \
254
      if (__comp < 0){        \
255
        SPLAY_ROTATE_RIGHT(head, __tmp, field); \
256
        if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
257
          break;        \
258
      }           \
259
      SPLAY_LINKLEFT(head, __right, field);   \
260
    } else if (__comp > 0) {        \
261
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
262
      if (__tmp == NULL)        \
263
        break;          \
264
      if (__comp > 0) {       \
265
        SPLAY_ROTATE_LEFT(head, __tmp, field);  \
266
        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
267
          break;        \
268
      }           \
269
      SPLAY_LINKRIGHT(head, __left, field);   \
270
    }             \
271
  }               \
272
  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);    \
273
}
274
275
#define SPLAY_NEGINF  -1
276
#define SPLAY_INF 1
277
278
#define SPLAY_INSERT(name, x, y)  name##_SPLAY_INSERT(x, y)
279
#define SPLAY_REMOVE(name, x, y)  name##_SPLAY_REMOVE(x, y)
280
#define SPLAY_FIND(name, x, y)    name##_SPLAY_FIND(x, y)
281
#define SPLAY_NEXT(name, x, y)    name##_SPLAY_NEXT(x, y)
282
#define SPLAY_MIN(name, x)    (SPLAY_EMPTY(x) ? NULL  \
283
          : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
284
#define SPLAY_MAX(name, x)    (SPLAY_EMPTY(x) ? NULL  \
285
          : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
286
287
#define SPLAY_FOREACH(x, name, head)          \
288
  for ((x) = SPLAY_MIN(name, head);       \
289
       (x) != NULL;           \
290
       (x) = SPLAY_NEXT(name, head, x))
291
292
/* Macros that define a red-black tree */
293
#define RB_HEAD(name, type)           \
294
struct name {               \
295
  struct type *rbh_root; /* root of the tree */     \
296
}
297
298
#define RB_INITIALIZER(root)            \
299
  { NULL }
300
301
#define RB_INIT(root) do {            \
302
  (root)->rbh_root = NULL;          \
303
} while (0)
304
305
#define RB_BLACK  0
306
#define RB_RED    1
307
#define RB_ENTRY(type)              \
308
struct {                \
309
  struct type *rbe_left;    /* left element */    \
310
  struct type *rbe_right;   /* right element */   \
311
  struct type *rbe_parent;  /* parent element */    \
312
  int rbe_color;      /* node color */    \
313
}
314
315
#define RB_LEFT(elm, field)   (elm)->field.rbe_left
316
#define RB_RIGHT(elm, field)    (elm)->field.rbe_right
317
#define RB_PARENT(elm, field)   (elm)->field.rbe_parent
318
#define RB_COLOR(elm, field)    (elm)->field.rbe_color
319
#define RB_ROOT(head)     (head)->rbh_root
320
#define RB_EMPTY(head)      (RB_ROOT(head) == NULL)
321
322
#define RB_SET(elm, parent, field) do {         \
323
  RB_PARENT(elm, field) = parent;         \
324
  RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;    \
325
  RB_COLOR(elm, field) = RB_RED;          \
326
} while (0)
327
328
#define RB_SET_BLACKRED(black, red, field) do {       \
329
  RB_COLOR(black, field) = RB_BLACK;        \
330
  RB_COLOR(red, field) = RB_RED;          \
331
} while (0)
332
333
#ifndef RB_AUGMENT
334
#define RB_AUGMENT(x) do {} while (0)
335
#endif
336
337
#define RB_ROTATE_LEFT(head, elm, tmp, field) do {      \
338
  (tmp) = RB_RIGHT(elm, field);         \
339
  if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) {   \
340
    RB_PARENT(RB_LEFT(tmp, field), field) = (elm);    \
341
  }               \
342
  RB_AUGMENT(elm);            \
343
  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {    \
344
    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
345
      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
346
    else              \
347
      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
348
  } else                \
349
    (head)->rbh_root = (tmp);       \
350
  RB_LEFT(tmp, field) = (elm);          \
351
  RB_PARENT(elm, field) = (tmp);          \
352
  RB_AUGMENT(tmp);            \
353
  if ((RB_PARENT(tmp, field)))          \
354
    RB_AUGMENT(RB_PARENT(tmp, field));      \
355
} while (0)
356
357
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do {     \
358
  (tmp) = RB_LEFT(elm, field);          \
359
  if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) {   \
360
    RB_PARENT(RB_RIGHT(tmp, field), field) = (elm);   \
361
  }               \
362
  RB_AUGMENT(elm);            \
363
  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {    \
364
    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
365
      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
366
    else              \
367
      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
368
  } else                \
369
    (head)->rbh_root = (tmp);       \
370
  RB_RIGHT(tmp, field) = (elm);         \
371
  RB_PARENT(elm, field) = (tmp);          \
372
  RB_AUGMENT(tmp);            \
373
  if ((RB_PARENT(tmp, field)))          \
374
    RB_AUGMENT(RB_PARENT(tmp, field));      \
375
} while (0)
376
377
/* Generates prototypes and inline functions */
378
#define RB_PROTOTYPE(name, type, field, cmp)        \
379
  RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
380
#define RB_PROTOTYPE_STATIC(name, type, field, cmp)     \
381
  RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
382
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr)   \
383
attr void name##_RB_INSERT_COLOR(struct name *, struct type *);   \
384
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
385
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
386
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
387
attr struct type *name##_RB_FIND(struct name *, struct type *);   \
388
attr struct type *name##_RB_NFIND(struct name *, struct type *);  \
389
attr struct type *name##_RB_NEXT(struct type *);      \
390
attr struct type *name##_RB_PREV(struct type *);      \
391
attr struct type *name##_RB_MINMAX(struct name *, int);     \
392
                  \
393
394
/* Main rb operation.
395
 * Moves node close to the key of elm to top
396
 */
397
#define RB_GENERATE(name, type, field, cmp)       \
398
  RB_GENERATE_INTERNAL(name, type, field, cmp,)
399
#define RB_GENERATE_STATIC(name, type, field, cmp)      \
400
  RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
401
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr)    \
402
attr void               \
403
name##_RB_INSERT_COLOR(struct name *head, struct type *elm)   \
404
{                 \
405
  struct type *parent, *gparent, *tmp;        \
406
  while ((parent = RB_PARENT(elm, field)) &&      \
407
      RB_COLOR(parent, field) == RB_RED) {      \
408
    gparent = RB_PARENT(parent, field);     \
409
    if (parent == RB_LEFT(gparent, field)) {    \
410
      tmp = RB_RIGHT(gparent, field);     \
411
      if (tmp && RB_COLOR(tmp, field) == RB_RED) {  \
412
        RB_COLOR(tmp, field) = RB_BLACK;  \
413
        RB_SET_BLACKRED(parent, gparent, field);\
414
        elm = gparent;        \
415
        continue;       \
416
      }           \
417
      if (RB_RIGHT(parent, field) == elm) {   \
418
        RB_ROTATE_LEFT(head, parent, tmp, field);\
419
        tmp = parent;       \
420
        parent = elm;       \
421
        elm = tmp;        \
422
      }           \
423
      RB_SET_BLACKRED(parent, gparent, field);  \
424
      RB_ROTATE_RIGHT(head, gparent, tmp, field); \
425
    } else {            \
426
      tmp = RB_LEFT(gparent, field);      \
427
      if (tmp && RB_COLOR(tmp, field) == RB_RED) {  \
428
        RB_COLOR(tmp, field) = RB_BLACK;  \
429
        RB_SET_BLACKRED(parent, gparent, field);\
430
        elm = gparent;        \
431
        continue;       \
432
      }           \
433
      if (RB_LEFT(parent, field) == elm) {    \
434
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
435
        tmp = parent;       \
436
        parent = elm;       \
437
        elm = tmp;        \
438
      }           \
439
      RB_SET_BLACKRED(parent, gparent, field);  \
440
      RB_ROTATE_LEFT(head, gparent, tmp, field);  \
441
    }             \
442
  }               \
443
  RB_COLOR(head->rbh_root, field) = RB_BLACK;     \
444
}                 \
445
                  \
446
attr void               \
447
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
448
{                 \
449
  struct type *tmp;           \
450
  while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
451
      elm != RB_ROOT(head)) {         \
452
    if (RB_LEFT(parent, field) == elm) {      \
453
      tmp = RB_RIGHT(parent, field);      \
454
      if (RB_COLOR(tmp, field) == RB_RED) {   \
455
        RB_SET_BLACKRED(tmp, parent, field);  \
456
        RB_ROTATE_LEFT(head, parent, tmp, field);\
457
        tmp = RB_RIGHT(parent, field);    \
458
      }           \
459
      if ((RB_LEFT(tmp, field) == NULL ||   \
460
          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
461
          (RB_RIGHT(tmp, field) == NULL ||    \
462
          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
463
        RB_COLOR(tmp, field) = RB_RED;    \
464
        elm = parent;       \
465
        parent = RB_PARENT(elm, field);   \
466
      } else {          \
467
        if (RB_RIGHT(tmp, field) == NULL || \
468
            RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
469
          struct type *oleft;   \
470
          if ((oleft = RB_LEFT(tmp, field)))\
471
            RB_COLOR(oleft, field) = RB_BLACK;\
472
          RB_COLOR(tmp, field) = RB_RED;  \
473
          RB_ROTATE_RIGHT(head, tmp, oleft, field);\
474
          tmp = RB_RIGHT(parent, field);  \
475
        }         \
476
        RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
477
        RB_COLOR(parent, field) = RB_BLACK; \
478
        if (RB_RIGHT(tmp, field))   \
479
          RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
480
        RB_ROTATE_LEFT(head, parent, tmp, field);\
481
        elm = RB_ROOT(head);      \
482
        break;          \
483
      }           \
484
    } else {            \
485
      tmp = RB_LEFT(parent, field);     \
486
      if (RB_COLOR(tmp, field) == RB_RED) {   \
487
        RB_SET_BLACKRED(tmp, parent, field);  \
488
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
489
        tmp = RB_LEFT(parent, field);   \
490
      }           \
491
      if ((RB_LEFT(tmp, field) == NULL ||   \
492
          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
493
          (RB_RIGHT(tmp, field) == NULL ||    \
494
          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
495
        RB_COLOR(tmp, field) = RB_RED;    \
496
        elm = parent;       \
497
        parent = RB_PARENT(elm, field);   \
498
      } else {          \
499
        if (RB_LEFT(tmp, field) == NULL ||  \
500
            RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
501
          struct type *oright;    \
502
          if ((oright = RB_RIGHT(tmp, field)))\
503
            RB_COLOR(oright, field) = RB_BLACK;\
504
          RB_COLOR(tmp, field) = RB_RED;  \
505
          RB_ROTATE_LEFT(head, tmp, oright, field);\
506
          tmp = RB_LEFT(parent, field); \
507
        }         \
508
        RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
509
        RB_COLOR(parent, field) = RB_BLACK; \
510
        if (RB_LEFT(tmp, field))    \
511
          RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
512
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
513
        elm = RB_ROOT(head);      \
514
        break;          \
515
      }           \
516
    }             \
517
  }               \
518
  if (elm)              \
519
    RB_COLOR(elm, field) = RB_BLACK;      \
520
}                 \
521
                  \
522
attr struct type *              \
523
name##_RB_REMOVE(struct name *head, struct type *elm)     \
524
{                 \
525
  struct type *child, *parent, *old = elm;      \
526
  int color;              \
527
  if (RB_LEFT(elm, field) == NULL)        \
528
    child = RB_RIGHT(elm, field);       \
529
  else if (RB_RIGHT(elm, field) == NULL)        \
530
    child = RB_LEFT(elm, field);        \
531
  else {                \
532
    struct type *left;          \
533
    elm = RB_RIGHT(elm, field);       \
534
    while ((left = RB_LEFT(elm, field)))      \
535
      elm = left;         \
536
    child = RB_RIGHT(elm, field);       \
537
    parent = RB_PARENT(elm, field);       \
538
    color = RB_COLOR(elm, field);       \
539
    if (child)            \
540
      RB_PARENT(child, field) = parent;   \
541
    if (parent) {           \
542
      if (RB_LEFT(parent, field) == elm)    \
543
        RB_LEFT(parent, field) = child;   \
544
      else            \
545
        RB_RIGHT(parent, field) = child;  \
546
      RB_AUGMENT(parent);       \
547
    } else              \
548
      RB_ROOT(head) = child;        \
549
    if (RB_PARENT(elm, field) == old)     \
550
      parent = elm;         \
551
    (elm)->field = (old)->field;        \
552
    if (RB_PARENT(old, field)) {        \
553
      if (RB_LEFT(RB_PARENT(old, field), field) == old)\
554
        RB_LEFT(RB_PARENT(old, field), field) = elm;\
555
      else            \
556
        RB_RIGHT(RB_PARENT(old, field), field) = elm;\
557
      RB_AUGMENT(RB_PARENT(old, field));    \
558
    } else              \
559
      RB_ROOT(head) = elm;        \
560
    RB_PARENT(RB_LEFT(old, field), field) = elm;    \
561
    if (RB_RIGHT(old, field))       \
562
      RB_PARENT(RB_RIGHT(old, field), field) = elm; \
563
    if (parent) {           \
564
      left = parent;          \
565
      do {            \
566
        RB_AUGMENT(left);     \
567
      } while ((left = RB_PARENT(left, field)));  \
568
    }             \
569
    goto color;           \
570
  }               \
571
  parent = RB_PARENT(elm, field);         \
572
  color = RB_COLOR(elm, field);         \
573
  if (child)              \
574
    RB_PARENT(child, field) = parent;     \
575
  if (parent) {             \
576
    if (RB_LEFT(parent, field) == elm)      \
577
      RB_LEFT(parent, field) = child;     \
578
    else              \
579
      RB_RIGHT(parent, field) = child;    \
580
    RB_AUGMENT(parent);         \
581
  } else                \
582
    RB_ROOT(head) = child;          \
583
color:                  \
584
  if (color == RB_BLACK)            \
585
    name##_RB_REMOVE_COLOR(head, parent, child);    \
586
  return (old);             \
587
}                 \
588
                  \
589
/* Inserts a node into the RB tree */         \
590
attr struct type *              \
591
name##_RB_INSERT(struct name *head, struct type *elm)     \
592
{                 \
593
  struct type *tmp;           \
594
  struct type *parent = NULL;         \
595
  int comp = 0;             \
596
  tmp = RB_ROOT(head);            \
597
  while (tmp) {             \
598
    parent = tmp;           \
599
    comp = (cmp)(elm, parent);        \
600
    if (comp < 0)           \
601
      tmp = RB_LEFT(tmp, field);      \
602
    else if (comp > 0)          \
603
      tmp = RB_RIGHT(tmp, field);     \
604
    else              \
605
      return (tmp);         \
606
  }               \
607
  RB_SET(elm, parent, field);         \
608
  if (parent != NULL) {           \
609
    if (comp < 0)           \
610
      RB_LEFT(parent, field) = elm;     \
611
    else              \
612
      RB_RIGHT(parent, field) = elm;      \
613
    RB_AUGMENT(parent);         \
614
  } else                \
615
    RB_ROOT(head) = elm;          \
616
  name##_RB_INSERT_COLOR(head, elm);        \
617
  return (NULL);              \
618
}                 \
619
                  \
620
/* Finds the node with the same key as elm */       \
621
attr struct type *              \
622
name##_RB_FIND(struct name *head, struct type *elm)     \
623
{                 \
624
  struct type *tmp = RB_ROOT(head);       \
625
  int comp;             \
626
  while (tmp) {             \
627
    comp = cmp(elm, tmp);         \
628
    if (comp < 0)           \
629
      tmp = RB_LEFT(tmp, field);      \
630
    else if (comp > 0)          \
631
      tmp = RB_RIGHT(tmp, field);     \
632
    else              \
633
      return (tmp);         \
634
  }               \
635
  return (NULL);              \
636
}                 \
637
                  \
638
/* Finds the first node greater than or equal to the search key */  \
639
attr struct type *              \
640
name##_RB_NFIND(struct name *head, struct type *elm)      \
641
{                 \
642
  struct type *tmp = RB_ROOT(head);       \
643
  struct type *res = NULL;          \
644
  int comp;             \
645
  while (tmp) {             \
646
    comp = cmp(elm, tmp);         \
647
    if (comp < 0) {           \
648
      res = tmp;          \
649
      tmp = RB_LEFT(tmp, field);      \
650
    }             \
651
    else if (comp > 0)          \
652
      tmp = RB_RIGHT(tmp, field);     \
653
    else              \
654
      return (tmp);         \
655
  }               \
656
  return (res);             \
657
}                 \
658
                  \
659
attr struct type *              \
660
name##_RB_NEXT(struct type *elm)          \
661
{                 \
662
  if (RB_RIGHT(elm, field)) {         \
663
    elm = RB_RIGHT(elm, field);       \
664
    while (RB_LEFT(elm, field))       \
665
      elm = RB_LEFT(elm, field);      \
666
  } else {              \
667
    if (RB_PARENT(elm, field) &&        \
668
        (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
669
      elm = RB_PARENT(elm, field);      \
670
    else {              \
671
      while (RB_PARENT(elm, field) &&     \
672
          (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
673
        elm = RB_PARENT(elm, field);    \
674
      elm = RB_PARENT(elm, field);      \
675
    }             \
676
  }               \
677
  return (elm);             \
678
}                 \
679
                  \
680
attr struct type *              \
681
name##_RB_PREV(struct type *elm)          \
682
{                 \
683
  if (RB_LEFT(elm, field)) {          \
684
    elm = RB_LEFT(elm, field);        \
685
    while (RB_RIGHT(elm, field))        \
686
      elm = RB_RIGHT(elm, field);     \
687
  } else {              \
688
    if (RB_PARENT(elm, field) &&        \
689
        (elm == RB_RIGHT(RB_PARENT(elm, field), field)))  \
690
      elm = RB_PARENT(elm, field);      \
691
    else {              \
692
      while (RB_PARENT(elm, field) &&     \
693
          (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
694
        elm = RB_PARENT(elm, field);    \
695
      elm = RB_PARENT(elm, field);      \
696
    }             \
697
  }               \
698
  return (elm);             \
699
}                 \
700
                  \
701
attr struct type *              \
702
name##_RB_MINMAX(struct name *head, int val)        \
703
{                 \
704
  struct type *tmp = RB_ROOT(head);       \
705
  struct type *parent = NULL;         \
706
  while (tmp) {             \
707
    parent = tmp;           \
708
    if (val < 0)            \
709
      tmp = RB_LEFT(tmp, field);      \
710
    else              \
711
      tmp = RB_RIGHT(tmp, field);     \
712
  }               \
713
  return (parent);            \
714
}
715
716
#define RB_NEGINF -1
717
#define RB_INF  1
718
719
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
720
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
721
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
722
#define RB_NFIND(name, x, y)  name##_RB_NFIND(x, y)
723
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
724
#define RB_PREV(name, x, y) name##_RB_PREV(y)
725
#define RB_MIN(name, x)   name##_RB_MINMAX(x, RB_NEGINF)
726
#define RB_MAX(name, x)   name##_RB_MINMAX(x, RB_INF)
727
728
#define RB_FOREACH(x, name, head)         \
729
  for ((x) = RB_MIN(name, head);          \
730
       (x) != NULL;           \
731
       (x) = name##_RB_NEXT(x))
732
733
#define RB_FOREACH_SAFE(x, name, head, y)       \
734
  for ((x) = RB_MIN(name, head);          \
735
      ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1);    \
736
       (x) = (y))
737
738
#define RB_FOREACH_REVERSE(x, name, head)       \
739
  for ((x) = RB_MAX(name, head);          \
740
       (x) != NULL;           \
741
       (x) = name##_RB_PREV(x))
742
743
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y)     \
744
  for ((x) = RB_MAX(name, head);          \
745
      ((x) != NULL) && ((y) = name##_RB_PREV(x), 1);    \
746
       (x) = (y))
747
748
749
/*
750
 * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
751
 *
752
 * Permission to use, copy, modify, and distribute this software for any
753
 * purpose with or without fee is hereby granted, provided that the above
754
 * copyright notice and this permission notice appear in all copies.
755
 *
756
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
757
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
758
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
759
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
760
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
761
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
762
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
763
 */
764
765
struct rb_type {
766
  int   (*t_compare)(const void *, const void *);
767
  void    (*t_augment)(void *);
768
  unsigned int    t_offset; /* offset of rb_entry in type */
769
};
770
771
struct rb_tree {
772
  struct rb_entry *rbt_root;
773
};
774
775
struct rb_entry {
776
  struct rb_entry  *rbt_parent;
777
  struct rb_entry  *rbt_left;
778
  struct rb_entry  *rbt_right;
779
  unsigned int    rbt_color;
780
};
781
782
#define RBT_HEAD(_name, _type)            \
783
struct _name {                \
784
  struct rb_tree rbh_root;          \
785
}
786
787
#define RBT_ENTRY(_type)  struct rb_entry
788
789
static inline void
790
_rb_init(struct rb_tree *rbt)
791
0
{
792
0
  rbt->rbt_root = NULL;
793
0
}
Unexecuted instantiation: common.c:_rb_init
Unexecuted instantiation: test_parser_fuzz.c:_rb_init
Unexecuted instantiation: ikev2_pld.c:_rb_init
Unexecuted instantiation: imsg_util.c:_rb_init
Unexecuted instantiation: util.c:_rb_init
794
795
static inline int
796
_rb_empty(struct rb_tree *rbt)
797
0
{
798
0
  return (rbt->rbt_root == NULL);
799
0
}
Unexecuted instantiation: common.c:_rb_empty
Unexecuted instantiation: test_parser_fuzz.c:_rb_empty
Unexecuted instantiation: ikev2_pld.c:_rb_empty
Unexecuted instantiation: imsg_util.c:_rb_empty
Unexecuted instantiation: util.c:_rb_empty
800
801
void  *_rb_insert(const struct rb_type *, struct rb_tree *, void *);
802
void  *_rb_remove(const struct rb_type *, struct rb_tree *, void *);
803
void  *_rb_find(const struct rb_type *, struct rb_tree *, const void *);
804
void  *_rb_nfind(const struct rb_type *, struct rb_tree *, const void *);
805
void  *_rb_root(const struct rb_type *, struct rb_tree *);
806
void  *_rb_min(const struct rb_type *, struct rb_tree *);
807
void  *_rb_max(const struct rb_type *, struct rb_tree *);
808
void  *_rb_next(const struct rb_type *, void *);
809
void  *_rb_prev(const struct rb_type *, void *);
810
void  *_rb_left(const struct rb_type *, void *);
811
void  *_rb_right(const struct rb_type *, void *);
812
void  *_rb_parent(const struct rb_type *, void *);
813
void   _rb_set_left(const struct rb_type *, void *, void *);
814
void   _rb_set_right(const struct rb_type *, void *, void *);
815
void   _rb_set_parent(const struct rb_type *, void *, void *);
816
void   _rb_poison(const struct rb_type *, void *, unsigned long);
817
int  _rb_check(const struct rb_type *, void *, unsigned long);
818
819
#define RBT_INITIALIZER(_head)  { { NULL } }
820
821
#define RBT_PROTOTYPE(_name, _type, _field, _cmp)     \
822
extern const struct rb_type *const _name##_RBT_TYPE;      \
823
                  \
824
__unused static inline void           \
825
_name##_RBT_INIT(struct _name *head)          \
826
{                 \
827
  _rb_init(&head->rbh_root);          \
828
}                 \
829
                  \
830
__unused static inline struct _type *         \
831
_name##_RBT_INSERT(struct _name *head, struct _type *elm)   \
832
{                 \
833
  return _rb_insert(_name##_RBT_TYPE, &head->rbh_root, elm);  \
834
}                 \
835
                  \
836
__unused static inline struct _type *         \
837
_name##_RBT_REMOVE(struct _name *head, struct _type *elm)   \
838
{                 \
839
  return _rb_remove(_name##_RBT_TYPE, &head->rbh_root, elm);  \
840
}                 \
841
                  \
842
__unused static inline struct _type *         \
843
_name##_RBT_FIND(struct _name *head, const struct _type *key)   \
844
{                 \
845
  return _rb_find(_name##_RBT_TYPE, &head->rbh_root, key);  \
846
}                 \
847
                  \
848
__unused static inline struct _type *         \
849
_name##_RBT_NFIND(struct _name *head, const struct _type *key)    \
850
{                 \
851
  return _rb_nfind(_name##_RBT_TYPE, &head->rbh_root, key); \
852
}                 \
853
                  \
854
__unused static inline struct _type *         \
855
_name##_RBT_ROOT(struct _name *head)          \
856
{                 \
857
  return _rb_root(_name##_RBT_TYPE, &head->rbh_root);   \
858
}                 \
859
                  \
860
__unused static inline int            \
861
_name##_RBT_EMPTY(struct _name *head)         \
862
{                 \
863
  return _rb_empty(&head->rbh_root);        \
864
}                 \
865
                  \
866
__unused static inline struct _type *         \
867
_name##_RBT_MIN(struct _name *head)         \
868
{                 \
869
  return _rb_min(_name##_RBT_TYPE, &head->rbh_root);    \
870
}                 \
871
                  \
872
__unused static inline struct _type *         \
873
_name##_RBT_MAX(struct _name *head)         \
874
{                 \
875
  return _rb_max(_name##_RBT_TYPE, &head->rbh_root);    \
876
}                 \
877
                  \
878
__unused static inline struct _type *         \
879
_name##_RBT_NEXT(struct _type *elm)         \
880
{                 \
881
  return _rb_next(_name##_RBT_TYPE, elm);       \
882
}                 \
883
                  \
884
__unused static inline struct _type *         \
885
_name##_RBT_PREV(struct _type *elm)         \
886
{                 \
887
  return _rb_prev(_name##_RBT_TYPE, elm);       \
888
}                 \
889
                  \
890
__unused static inline struct _type *         \
891
_name##_RBT_LEFT(struct _type *elm)         \
892
{                 \
893
  return _rb_left(_name##_RBT_TYPE, elm);       \
894
}                 \
895
                  \
896
__unused static inline struct _type *         \
897
_name##_RBT_RIGHT(struct _type *elm)          \
898
{                 \
899
  return _rb_right(_name##_RBT_TYPE, elm);      \
900
}                 \
901
                  \
902
__unused static inline struct _type *         \
903
_name##_RBT_PARENT(struct _type *elm)         \
904
{                 \
905
  return _rb_parent(_name##_RBT_TYPE, elm);     \
906
}                 \
907
                  \
908
__unused static inline void           \
909
_name##_RBT_SET_LEFT(struct _type *elm, struct _type *left)   \
910
{                 \
911
  _rb_set_left(_name##_RBT_TYPE, elm, left);      \
912
}                 \
913
                  \
914
__unused static inline void           \
915
_name##_RBT_SET_RIGHT(struct _type *elm, struct _type *right)   \
916
{                 \
917
  _rb_set_right(_name##_RBT_TYPE, elm, right);      \
918
}                 \
919
                  \
920
__unused static inline void           \
921
_name##_RBT_SET_PARENT(struct _type *elm, struct _type *parent)   \
922
{                 \
923
  _rb_set_parent(_name##_RBT_TYPE, elm, parent);      \
924
}                 \
925
                  \
926
__unused static inline void           \
927
_name##_RBT_POISON(struct _type *elm, unsigned long poison)   \
928
{                 \
929
  _rb_poison(_name##_RBT_TYPE, elm, poison);      \
930
}                 \
931
                  \
932
__unused static inline int            \
933
_name##_RBT_CHECK(struct _type *elm, unsigned long poison)    \
934
{                 \
935
  return _rb_check(_name##_RBT_TYPE, elm, poison);    \
936
}
937
938
#define RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug)   \
939
static int                \
940
_name##_RBT_COMPARE(const void *lptr, const void *rptr)     \
941
{                 \
942
  const struct _type *l = lptr, *r = rptr;      \
943
  return _cmp(l, r);            \
944
}                 \
945
static const struct rb_type _name##_RBT_INFO = {      \
946
  _name##_RBT_COMPARE,            \
947
  _aug,               \
948
  offsetof(struct _type, _field),         \
949
};                  \
950
const struct rb_type *const _name##_RBT_TYPE = &_name##_RBT_INFO
951
952
#define RBT_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug)    \
953
static void               \
954
_name##_RBT_AUGMENT(void *ptr)            \
955
{                 \
956
  struct _type *p = ptr;            \
957
  return _aug(p);             \
958
}                 \
959
RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RBT_AUGMENT)
960
961
#define RBT_GENERATE(_name, _type, _field, _cmp)      \
962
    RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL)
963
964
#define RBT_INIT(_name, _head)    _name##_RBT_INIT(_head)
965
#define RBT_INSERT(_name, _head, _elm)  _name##_RBT_INSERT(_head, _elm)
966
#define RBT_REMOVE(_name, _head, _elm)  _name##_RBT_REMOVE(_head, _elm)
967
#define RBT_FIND(_name, _head, _key)  _name##_RBT_FIND(_head, _key)
968
#define RBT_NFIND(_name, _head, _key) _name##_RBT_NFIND(_head, _key)
969
#define RBT_ROOT(_name, _head)    _name##_RBT_ROOT(_head)
970
#define RBT_EMPTY(_name, _head)   _name##_RBT_EMPTY(_head)
971
#define RBT_MIN(_name, _head)   _name##_RBT_MIN(_head)
972
#define RBT_MAX(_name, _head)   _name##_RBT_MAX(_head)
973
#define RBT_NEXT(_name, _elm)   _name##_RBT_NEXT(_elm)
974
#define RBT_PREV(_name, _elm)   _name##_RBT_PREV(_elm)
975
#define RBT_LEFT(_name, _elm)   _name##_RBT_LEFT(_elm)
976
#define RBT_RIGHT(_name, _elm)    _name##_RBT_RIGHT(_elm)
977
#define RBT_PARENT(_name, _elm)   _name##_RBT_PARENT(_elm)
978
#define RBT_SET_LEFT(_name, _elm, _l) _name##_RBT_SET_LEFT(_elm, _l)
979
#define RBT_SET_RIGHT(_name, _elm, _r)  _name##_RBT_SET_RIGHT(_elm, _r)
980
#define RBT_SET_PARENT(_name, _elm, _p) _name##_RBT_SET_PARENT(_elm, _p)
981
#define RBT_POISON(_name, _elm, _p) _name##_RBT_POISON(_elm, _p)
982
#define RBT_CHECK(_name, _elm, _p)  _name##_RBT_CHECK(_elm, _p)
983
984
#define RBT_FOREACH(_e, _name, _head)         \
985
  for ((_e) = RBT_MIN(_name, (_head));        \
986
       (_e) != NULL;            \
987
       (_e) = RBT_NEXT(_name, (_e)))
988
989
#define RBT_FOREACH_SAFE(_e, _name, _head, _n)        \
990
  for ((_e) = RBT_MIN(_name, (_head));        \
991
       (_e) != NULL && ((_n) = RBT_NEXT(_name, (_e)), 1); \
992
       (_e) = (_n))
993
994
#define RBT_FOREACH_REVERSE(_e, _name, _head)       \
995
  for ((_e) = RBT_MAX(_name, (_head));        \
996
       (_e) != NULL;            \
997
       (_e) = RBT_PREV(_name, (_e)))
998
999
#define RBT_FOREACH_REVERSE_SAFE(_e, _name, _head, _n)      \
1000
  for ((_e) = RBT_MAX(_name, (_head));        \
1001
       (_e) != NULL && ((_n) = RBT_PREV(_name, (_e)), 1); \
1002
       (_e) = (_n))
1003
1004
#endif  /* _SYS_TREE_H_ */
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/vis.c.html b/coverage/latest/report/linux/src/openiked-portable/compat/vis.c.html index 2390311e2..89b461bcf 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/vis.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/vis.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/vis.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: vis.c,v 1.26 2022/05/04 18:57:50 deraadt Exp $ */
2
/*-
3
 * Copyright (c) 1989, 1993
4
 *  The Regents of the University of California.  All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 3. Neither the name of the University nor the names of its contributors
15
 *    may be used to endorse or promote products derived from this software
16
 *    without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
/* OPENBSD ORIGINAL: lib/libc/gen/vis.c */
32
33
#if !defined(HAVE_STRNVIS)
34
35
#include <sys/types.h>
36
#include <errno.h>
37
#include <ctype.h>
38
#include <limits.h>
39
#include <string.h>
40
#include <stdlib.h>
41
#include <vis.h>
42
43
static int
44
isoctal(int c)
45
0
{
46
0
  u_char uc = c;
47
48
0
  return uc >= '0' && uc <= '7';
49
0
}
50
51
static int
52
isvisible(int c, int flag)
53
0
{
54
0
  int vis_sp = flag & VIS_SP;
55
0
  int vis_tab = flag & VIS_TAB;
56
0
  int vis_nl = flag & VIS_NL;
57
0
  int vis_safe = flag & VIS_SAFE;
58
0
  int vis_glob = flag & VIS_GLOB;
59
0
  int vis_all = flag & VIS_ALL;
60
0
  u_char uc = c;
61
62
0
  if (c == '\\' || !vis_all) {
63
0
    if ((u_int)c <= UCHAR_MAX && isascii(uc) &&
64
0
        ((c != '*' && c != '?' && c != '[' && c != '#') || !vis_glob) &&
65
0
        isgraph(uc))
66
0
      return 1;
67
0
    if (!vis_sp && c == ' ')
68
0
      return 1;
69
0
    if (!vis_tab && c == '\t')
70
0
      return 1;
71
0
    if (!vis_nl && c == '\n')
72
0
      return 1;
73
0
    if (vis_safe && (c == '\b' || c == '\007' || c == '\r' || isgraph(uc)))
74
0
      return 1;
75
0
  }
76
0
  return 0;
77
0
}
78
79
/*
80
 * vis - visually encode characters
81
 */
82
char *
83
vis(char *dst, int c, int flag, int nextc)
84
0
{
85
0
  int vis_dq = flag & VIS_DQ;
86
0
  int vis_noslash = flag & VIS_NOSLASH;
87
0
  int vis_cstyle = flag & VIS_CSTYLE;
88
0
  int vis_octal = flag & VIS_OCTAL;
89
0
  int vis_glob = flag & VIS_GLOB;
90
91
0
  if (isvisible(c, flag)) {
92
0
    if ((c == '"' && vis_dq) ||
93
0
        (c == '\\' && !vis_noslash))
94
0
      *dst++ = '\\';
95
0
    *dst++ = c;
96
0
    *dst = '\0';
97
0
    return (dst);
98
0
  }
99
100
0
  if (vis_cstyle) {
101
0
    switch (c) {
102
0
    case '\n':
103
0
      *dst++ = '\\';
104
0
      *dst++ = 'n';
105
0
      goto done;
106
0
    case '\r':
107
0
      *dst++ = '\\';
108
0
      *dst++ = 'r';
109
0
      goto done;
110
0
    case '\b':
111
0
      *dst++ = '\\';
112
0
      *dst++ = 'b';
113
0
      goto done;
114
0
    case '\a':
115
0
      *dst++ = '\\';
116
0
      *dst++ = 'a';
117
0
      goto done;
118
0
    case '\v':
119
0
      *dst++ = '\\';
120
0
      *dst++ = 'v';
121
0
      goto done;
122
0
    case '\t':
123
0
      *dst++ = '\\';
124
0
      *dst++ = 't';
125
0
      goto done;
126
0
    case '\f':
127
0
      *dst++ = '\\';
128
0
      *dst++ = 'f';
129
0
      goto done;
130
0
    case ' ':
131
0
      *dst++ = '\\';
132
0
      *dst++ = 's';
133
0
      goto done;
134
0
    case '\0':
135
0
      *dst++ = '\\';
136
0
      *dst++ = '0';
137
0
      if (isoctal(nextc)) {
138
0
        *dst++ = '0';
139
0
        *dst++ = '0';
140
0
      }
141
0
      goto done;
142
0
    }
143
0
  }
144
0
  if (((c & 0177) == ' ') || vis_octal ||
145
0
      (vis_glob && (c == '*' || c == '?' || c == '[' || c == '#'))) {
146
0
    *dst++ = '\\';
147
0
    *dst++ = ((u_char)c >> 6 & 07) + '0';
148
0
    *dst++ = ((u_char)c >> 3 & 07) + '0';
149
0
    *dst++ = ((u_char)c & 07) + '0';
150
0
    goto done;
151
0
  }
152
0
  if (!vis_noslash)
153
0
    *dst++ = '\\';
154
0
  if (c & 0200) {
155
0
    c &= 0177;
156
0
    *dst++ = 'M';
157
0
  }
158
0
  if (iscntrl((u_char)c)) {
159
0
    *dst++ = '^';
160
0
    if (c == 0177)
161
0
      *dst++ = '?';
162
0
    else
163
0
      *dst++ = c + '@';
164
0
  } else {
165
0
    *dst++ = '-';
166
0
    *dst++ = c;
167
0
  }
168
0
done:
169
0
  *dst = '\0';
170
0
  return (dst);
171
0
}
172
173
/*
174
 * strvis, strnvis, strvisx - visually encode characters from src into dst
175
 *  
176
 *  Dst must be 4 times the size of src to account for possible
177
 *  expansion.  The length of dst, not including the trailing NULL,
178
 *  is returned. 
179
 *
180
 *  Strnvis will write no more than siz-1 bytes (and will NULL terminate).
181
 *  The number of bytes needed to fully encode the string is returned.
182
 *
183
 *  Strvisx encodes exactly len bytes from src into dst.
184
 *  This is useful for encoding a block of data.
185
 */
186
int
187
strvis(char *dst, const char *src, int flag)
188
0
{
189
0
  char c;
190
0
  char *start;
191
192
0
  for (start = dst; (c = *src);)
193
0
    dst = vis(dst, c, flag, *++src);
194
0
  *dst = '\0';
195
0
  return (dst - start);
196
0
}
197
198
int
199
strnvis(char *dst, const char *src, size_t siz, int flag)
200
0
{
201
0
  int vis_dq = flag & VIS_DQ;
202
0
  int vis_noslash = flag & VIS_NOSLASH;
203
0
  char *start, *end;
204
0
  char tbuf[5];
205
0
  int c, i;
206
207
0
  i = 0;
208
0
  for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
209
0
    if (isvisible(c, flag)) {
210
0
      if ((c == '"' && vis_dq) ||
211
0
          (c == '\\' && !vis_noslash)) {
212
        /* need space for the extra '\\' */
213
0
        if (dst + 1 >= end) {
214
0
          i = 2;
215
0
          break;
216
0
        }
217
0
        *dst++ = '\\';
218
0
      }
219
0
      i = 1;
220
0
      *dst++ = c;
221
0
      src++;
222
0
    } else {
223
0
      i = vis(tbuf, c, flag, *++src) - tbuf;
224
0
      if (dst + i <= end) {
225
0
        memcpy(dst, tbuf, i);
226
0
        dst += i;
227
0
      } else {
228
0
        src--;
229
0
        break;
230
0
      }
231
0
    }
232
0
  }
233
0
  if (siz > 0)
234
0
    *dst = '\0';
235
0
  if (dst + i > end) {
236
    /* adjust return value for truncation */
237
0
    while ((c = *src))
238
0
      dst += vis(tbuf, c, flag, *++src) - tbuf;
239
0
  }
240
0
  return (dst - start);
241
0
}
242
243
int
244
stravis(char **outp, const char *src, int flag)
245
0
{
246
0
  char *buf;
247
0
  int len, serrno;
248
249
0
  buf = reallocarray(NULL, 4, strlen(src) + 1);
250
0
  if (buf == NULL)
251
0
    return -1;
252
0
  len = strvis(buf, src, flag);
253
0
  serrno = errno;
254
0
  *outp = realloc(buf, len + 1);
255
0
  if (*outp == NULL) {
256
0
    *outp = buf;
257
0
    errno = serrno;
258
0
  }
259
0
  return (len);
260
0
}
261
262
int
263
strvisx(char *dst, const char *src, size_t len, int flag)
264
0
{
265
0
  char c;
266
0
  char *start;
267
268
0
  for (start = dst; len > 1; len--) {
269
0
    c = *src;
270
0
    dst = vis(dst, c, flag, *++src);
271
0
  }
272
0
  if (len)
273
0
    dst = vis(dst, *src, flag, '\0');
274
0
  *dst = '\0';
275
0
  return (dst - start);
276
0
}
277
278
#endif
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/vis.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: vis.c,v 1.26 2022/05/04 18:57:50 deraadt Exp $ */
2
/*-
3
 * Copyright (c) 1989, 1993
4
 *  The Regents of the University of California.  All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 3. Neither the name of the University nor the names of its contributors
15
 *    may be used to endorse or promote products derived from this software
16
 *    without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
/* OPENBSD ORIGINAL: lib/libc/gen/vis.c */
32
33
#if !defined(HAVE_STRNVIS)
34
35
#include <sys/types.h>
36
#include <errno.h>
37
#include <ctype.h>
38
#include <limits.h>
39
#include <string.h>
40
#include <stdlib.h>
41
#include <vis.h>
42
43
static int
44
isoctal(int c)
45
0
{
46
0
  u_char uc = c;
47
48
0
  return uc >= '0' && uc <= '7';
49
0
}
50
51
static int
52
isvisible(int c, int flag)
53
0
{
54
0
  int vis_sp = flag & VIS_SP;
55
0
  int vis_tab = flag & VIS_TAB;
56
0
  int vis_nl = flag & VIS_NL;
57
0
  int vis_safe = flag & VIS_SAFE;
58
0
  int vis_glob = flag & VIS_GLOB;
59
0
  int vis_all = flag & VIS_ALL;
60
0
  u_char uc = c;
61
62
0
  if (c == '\\' || !vis_all) {
63
0
    if ((u_int)c <= UCHAR_MAX && isascii(uc) &&
64
0
        ((c != '*' && c != '?' && c != '[' && c != '#') || !vis_glob) &&
65
0
        isgraph(uc))
66
0
      return 1;
67
0
    if (!vis_sp && c == ' ')
68
0
      return 1;
69
0
    if (!vis_tab && c == '\t')
70
0
      return 1;
71
0
    if (!vis_nl && c == '\n')
72
0
      return 1;
73
0
    if (vis_safe && (c == '\b' || c == '\007' || c == '\r' || isgraph(uc)))
74
0
      return 1;
75
0
  }
76
0
  return 0;
77
0
}
78
79
/*
80
 * vis - visually encode characters
81
 */
82
char *
83
vis(char *dst, int c, int flag, int nextc)
84
0
{
85
0
  int vis_dq = flag & VIS_DQ;
86
0
  int vis_noslash = flag & VIS_NOSLASH;
87
0
  int vis_cstyle = flag & VIS_CSTYLE;
88
0
  int vis_octal = flag & VIS_OCTAL;
89
0
  int vis_glob = flag & VIS_GLOB;
90
91
0
  if (isvisible(c, flag)) {
92
0
    if ((c == '"' && vis_dq) ||
93
0
        (c == '\\' && !vis_noslash))
94
0
      *dst++ = '\\';
95
0
    *dst++ = c;
96
0
    *dst = '\0';
97
0
    return (dst);
98
0
  }
99
100
0
  if (vis_cstyle) {
101
0
    switch (c) {
102
0
    case '\n':
103
0
      *dst++ = '\\';
104
0
      *dst++ = 'n';
105
0
      goto done;
106
0
    case '\r':
107
0
      *dst++ = '\\';
108
0
      *dst++ = 'r';
109
0
      goto done;
110
0
    case '\b':
111
0
      *dst++ = '\\';
112
0
      *dst++ = 'b';
113
0
      goto done;
114
0
    case '\a':
115
0
      *dst++ = '\\';
116
0
      *dst++ = 'a';
117
0
      goto done;
118
0
    case '\v':
119
0
      *dst++ = '\\';
120
0
      *dst++ = 'v';
121
0
      goto done;
122
0
    case '\t':
123
0
      *dst++ = '\\';
124
0
      *dst++ = 't';
125
0
      goto done;
126
0
    case '\f':
127
0
      *dst++ = '\\';
128
0
      *dst++ = 'f';
129
0
      goto done;
130
0
    case ' ':
131
0
      *dst++ = '\\';
132
0
      *dst++ = 's';
133
0
      goto done;
134
0
    case '\0':
135
0
      *dst++ = '\\';
136
0
      *dst++ = '0';
137
0
      if (isoctal(nextc)) {
138
0
        *dst++ = '0';
139
0
        *dst++ = '0';
140
0
      }
141
0
      goto done;
142
0
    }
143
0
  }
144
0
  if (((c & 0177) == ' ') || vis_octal ||
145
0
      (vis_glob && (c == '*' || c == '?' || c == '[' || c == '#'))) {
146
0
    *dst++ = '\\';
147
0
    *dst++ = ((u_char)c >> 6 & 07) + '0';
148
0
    *dst++ = ((u_char)c >> 3 & 07) + '0';
149
0
    *dst++ = ((u_char)c & 07) + '0';
150
0
    goto done;
151
0
  }
152
0
  if (!vis_noslash)
153
0
    *dst++ = '\\';
154
0
  if (c & 0200) {
155
0
    c &= 0177;
156
0
    *dst++ = 'M';
157
0
  }
158
0
  if (iscntrl((u_char)c)) {
159
0
    *dst++ = '^';
160
0
    if (c == 0177)
161
0
      *dst++ = '?';
162
0
    else
163
0
      *dst++ = c + '@';
164
0
  } else {
165
0
    *dst++ = '-';
166
0
    *dst++ = c;
167
0
  }
168
0
done:
169
0
  *dst = '\0';
170
0
  return (dst);
171
0
}
172
173
/*
174
 * strvis, strnvis, strvisx - visually encode characters from src into dst
175
 *  
176
 *  Dst must be 4 times the size of src to account for possible
177
 *  expansion.  The length of dst, not including the trailing NULL,
178
 *  is returned. 
179
 *
180
 *  Strnvis will write no more than siz-1 bytes (and will NULL terminate).
181
 *  The number of bytes needed to fully encode the string is returned.
182
 *
183
 *  Strvisx encodes exactly len bytes from src into dst.
184
 *  This is useful for encoding a block of data.
185
 */
186
int
187
strvis(char *dst, const char *src, int flag)
188
0
{
189
0
  char c;
190
0
  char *start;
191
192
0
  for (start = dst; (c = *src);)
193
0
    dst = vis(dst, c, flag, *++src);
194
0
  *dst = '\0';
195
0
  return (dst - start);
196
0
}
197
198
int
199
strnvis(char *dst, const char *src, size_t siz, int flag)
200
0
{
201
0
  int vis_dq = flag & VIS_DQ;
202
0
  int vis_noslash = flag & VIS_NOSLASH;
203
0
  char *start, *end;
204
0
  char tbuf[5];
205
0
  int c, i;
206
207
0
  i = 0;
208
0
  for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
209
0
    if (isvisible(c, flag)) {
210
0
      if ((c == '"' && vis_dq) ||
211
0
          (c == '\\' && !vis_noslash)) {
212
        /* need space for the extra '\\' */
213
0
        if (dst + 1 >= end) {
214
0
          i = 2;
215
0
          break;
216
0
        }
217
0
        *dst++ = '\\';
218
0
      }
219
0
      i = 1;
220
0
      *dst++ = c;
221
0
      src++;
222
0
    } else {
223
0
      i = vis(tbuf, c, flag, *++src) - tbuf;
224
0
      if (dst + i <= end) {
225
0
        memcpy(dst, tbuf, i);
226
0
        dst += i;
227
0
      } else {
228
0
        src--;
229
0
        break;
230
0
      }
231
0
    }
232
0
  }
233
0
  if (siz > 0)
234
0
    *dst = '\0';
235
0
  if (dst + i > end) {
236
    /* adjust return value for truncation */
237
0
    while ((c = *src))
238
0
      dst += vis(tbuf, c, flag, *++src) - tbuf;
239
0
  }
240
0
  return (dst - start);
241
0
}
242
243
int
244
stravis(char **outp, const char *src, int flag)
245
0
{
246
0
  char *buf;
247
0
  int len, serrno;
248
249
0
  buf = reallocarray(NULL, 4, strlen(src) + 1);
250
0
  if (buf == NULL)
251
0
    return -1;
252
0
  len = strvis(buf, src, flag);
253
0
  serrno = errno;
254
0
  *outp = realloc(buf, len + 1);
255
0
  if (*outp == NULL) {
256
0
    *outp = buf;
257
0
    errno = serrno;
258
0
  }
259
0
  return (len);
260
0
}
261
262
int
263
strvisx(char *dst, const char *src, size_t len, int flag)
264
0
{
265
0
  char c;
266
0
  char *start;
267
268
0
  for (start = dst; len > 1; len--) {
269
0
    c = *src;
270
0
    dst = vis(dst, c, flag, *++src);
271
0
  }
272
0
  if (len)
273
0
    dst = vis(dst, *src, flag, '\0');
274
0
  *dst = '\0';
275
0
  return (dst - start);
276
0
}
277
278
#endif
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/compat/vis.h.html b/coverage/latest/report/linux/src/openiked-portable/compat/vis.h.html index 670be8253..6a69d007d 100644 --- a/coverage/latest/report/linux/src/openiked-portable/compat/vis.h.html +++ b/coverage/latest/report/linux/src/openiked-portable/compat/vis.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/vis.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: vis.h,v 1.15 2015/07/20 01:52:27 millert Exp $  */
2
/*  $NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $  */
3
4
/*-
5
 * Copyright (c) 1990 The Regents of the University of California.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 *
32
 *  @(#)vis.h 5.9 (Berkeley) 4/3/91
33
 */
34
35
/* OPENBSD ORIGINAL: include/vis.h */
36
37
#ifdef HAVE_CONFIG_H
38
#include "includes.h"
39
#endif
40
41
#ifndef _VIS_H_
42
#define _VIS_H_
43
44
#include <sys/types.h>
45
#include <limits.h>
46
47
/*
48
 * to select alternate encoding format
49
 */
50
0
#define VIS_OCTAL 0x01  /* use octal \ddd format */
51
0
#define VIS_CSTYLE  0x02  /* use \[nrft0..] where appropriate */
52
53
/*
54
 * to alter set of characters encoded (default is to encode all
55
 * non-graphic except space, tab, and newline).
56
 */
57
0
#define VIS_SP    0x04  /* also encode space */
58
0
#define VIS_TAB   0x08  /* also encode tab */
59
0
#define VIS_NL    0x10  /* also encode newline */
60
#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
61
0
#define VIS_SAFE  0x20  /* only encode "unsafe" characters */
62
0
#define VIS_DQ    0x200  /* backslash-escape double quotes */
63
0
#define VIS_ALL   0x400  /* encode all characters */
64
65
/*
66
 * other
67
 */
68
0
#define VIS_NOSLASH 0x40  /* inhibit printing '\' */
69
0
#define VIS_GLOB  0x100  /* encode glob(3) magics and '#' */
70
71
/*
72
 * unvis return codes
73
 */
74
#define UNVIS_VALID  1  /* character valid */
75
#define UNVIS_VALIDPUSH  2  /* character valid, push back passed char */
76
#define UNVIS_NOCHAR   3  /* valid sequence, no character produced */
77
#define UNVIS_SYNBAD  -1  /* unrecognized escape sequence */
78
#define UNVIS_ERROR -2  /* decoder in unknown state (unrecoverable) */
79
80
/*
81
 * unvis flags
82
 */
83
#define UNVIS_END 1 /* no more characters */
84
85
char  *vis(char *, int, int, int);
86
int strvis(char *, const char *, int);
87
int stravis(char **, const char *, int);
88
int strnvis(char *, const char *, size_t, int)
89
    __attribute__ ((__bounded__(__string__,1,3)));
90
int strvisx(char *, const char *, size_t, int)
91
    __attribute__ ((__bounded__(__string__,1,3)));
92
int strunvis(char *, const char *);
93
int unvis(char *, char, int *, int);
94
ssize_t strnunvis(char *, const char *, size_t)
95
    __attribute__ ((__bounded__(__string__,1,3)));
96
97
#endif /* !_VIS_H_ */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/vis.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: vis.h,v 1.15 2015/07/20 01:52:27 millert Exp $  */
2
/*  $NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $  */
3
4
/*-
5
 * Copyright (c) 1990 The Regents of the University of California.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 *
32
 *  @(#)vis.h 5.9 (Berkeley) 4/3/91
33
 */
34
35
/* OPENBSD ORIGINAL: include/vis.h */
36
37
#ifdef HAVE_CONFIG_H
38
#include "includes.h"
39
#endif
40
41
#ifndef _VIS_H_
42
#define _VIS_H_
43
44
#include <sys/types.h>
45
#include <limits.h>
46
47
/*
48
 * to select alternate encoding format
49
 */
50
0
#define VIS_OCTAL 0x01  /* use octal \ddd format */
51
0
#define VIS_CSTYLE  0x02  /* use \[nrft0..] where appropriate */
52
53
/*
54
 * to alter set of characters encoded (default is to encode all
55
 * non-graphic except space, tab, and newline).
56
 */
57
0
#define VIS_SP    0x04  /* also encode space */
58
0
#define VIS_TAB   0x08  /* also encode tab */
59
0
#define VIS_NL    0x10  /* also encode newline */
60
#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
61
0
#define VIS_SAFE  0x20  /* only encode "unsafe" characters */
62
0
#define VIS_DQ    0x200  /* backslash-escape double quotes */
63
0
#define VIS_ALL   0x400  /* encode all characters */
64
65
/*
66
 * other
67
 */
68
0
#define VIS_NOSLASH 0x40  /* inhibit printing '\' */
69
0
#define VIS_GLOB  0x100  /* encode glob(3) magics and '#' */
70
71
/*
72
 * unvis return codes
73
 */
74
#define UNVIS_VALID  1  /* character valid */
75
#define UNVIS_VALIDPUSH  2  /* character valid, push back passed char */
76
#define UNVIS_NOCHAR   3  /* valid sequence, no character produced */
77
#define UNVIS_SYNBAD  -1  /* unrecognized escape sequence */
78
#define UNVIS_ERROR -2  /* decoder in unknown state (unrecoverable) */
79
80
/*
81
 * unvis flags
82
 */
83
#define UNVIS_END 1 /* no more characters */
84
85
char  *vis(char *, int, int, int);
86
int strvis(char *, const char *, int);
87
int stravis(char **, const char *, int);
88
int strnvis(char *, const char *, size_t, int)
89
    __attribute__ ((__bounded__(__string__,1,3)));
90
int strvisx(char *, const char *, size_t, int)
91
    __attribute__ ((__bounded__(__string__,1,3)));
92
int strunvis(char *, const char *);
93
int unvis(char *, char, int *, int);
94
ssize_t strnunvis(char *, const char *, size_t)
95
    __attribute__ ((__bounded__(__string__,1,3)));
96
97
#endif /* !_VIS_H_ */
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/iked/iked.h.html b/coverage/latest/report/linux/src/openiked-portable/iked/iked.h.html index 7f5db007b..d28a3fc8c 100644 --- a/coverage/latest/report/linux/src/openiked-portable/iked/iked.h.html +++ b/coverage/latest/report/linux/src/openiked-portable/iked/iked.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/iked.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: iked.h,v 1.224 2023/08/11 11:24:55 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019-2021 Tobias Heider <tobhe@openbsd.org>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/tree.h>
22
#include <sys/queue.h>
23
#include <arpa/inet.h>
24
#include <limits.h>
25
#include <imsg.h>
26
27
#include <openssl/evp.h>
28
29
#include "openbsd-compat.h"
30
31
#include "types.h"
32
#include "dh.h"
33
34
#define MAXIMUM(a,b) (((a)>(b))?(a):(b))
35
#define MINIMUM(a,b) (((a)<(b))?(a):(b))
36
#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
37
38
#ifndef IKED_H
39
#define IKED_H
40
41
/*
42
 * Common IKEv1/IKEv2 header
43
 */
44
45
struct ike_header {
46
  uint64_t   ike_ispi;    /* Initiator cookie */
47
  uint64_t   ike_rspi;    /* Responder cookie */
48
  uint8_t    ike_nextpayload; /* Next payload type */
49
  uint8_t    ike_version;   /* Major/Minor version number */
50
  uint8_t    ike_exchange;    /* Exchange type */
51
  uint8_t    ike_flags;   /* Message options */
52
  uint32_t   ike_msgid;   /* Message identifier */
53
  uint32_t   ike_length;    /* Total message length */
54
} __packed;
55
56
/*
57
 * Common daemon infrastructure, local imsg etc.
58
 */
59
60
struct imsgev {
61
  struct imsgbuf     ibuf;
62
  void      (*handler)(int, short, void *);
63
  struct event     ev;
64
  struct privsep_proc *proc;
65
  void      *data;
66
  short      events;
67
  const char    *name;
68
};
69
70
#define IMSG_SIZE_CHECK(imsg, p) do {       \
71
  if (IMSG_DATA_SIZE(imsg) < sizeof(*p))      \
72
    fatalx("bad length imsg received");   \
73
} while (0)
74
#define IMSG_DATA_SIZE(imsg)  ((imsg)->hdr.len - IMSG_HEADER_SIZE)
75
76
#define IKED_ADDR_EQ(_a, _b)            \
77
  ((_a)->addr_mask == (_b)->addr_mask &&        \
78
  sockaddr_cmp((struct sockaddr *)&(_a)->addr,      \
79
  (struct sockaddr *)&(_b)->addr, (_a)->addr_mask) == 0)
80
81
#define IKED_ADDR_NEQ(_a, _b)           \
82
  ((_a)->addr_mask != (_b)->addr_mask ||        \
83
  sockaddr_cmp((struct sockaddr *)&(_a)->addr,      \
84
  (struct sockaddr *)&(_b)->addr, (_a)->addr_mask) != 0)
85
86
/* initially control.h */
87
struct control_sock {
88
  const char  *cs_name;
89
  struct event   cs_ev;
90
  struct event   cs_evt;
91
  int    cs_fd;
92
  int    cs_restricted;
93
  void    *cs_env;
94
95
  TAILQ_ENTRY(control_sock) cs_entry;
96
};
97
TAILQ_HEAD(control_socks, control_sock);
98
99
struct ctl_conn {
100
  TAILQ_ENTRY(ctl_conn)  entry;
101
  uint8_t      flags;
102
#define CTL_CONN_NOTIFY    0x01
103
  struct imsgev    iev;
104
};
105
TAILQ_HEAD(ctl_connlist, ctl_conn);
106
107
extern enum privsep_procid privsep_process;
108
109
/*
110
 * Runtime structures
111
 */
112
113
struct iked_timer {
114
  struct event   tmr_ev;
115
  struct iked *tmr_env;
116
  void    (*tmr_cb)(struct iked *, void *);
117
  void    *tmr_cbarg;
118
};
119
120
struct iked_spi {
121
  uint64_t   spi;
122
  uint8_t    spi_size;
123
  uint8_t    spi_protoid;
124
};
125
126
struct iked_proposal {
127
  uint8_t        prop_id;
128
  uint8_t        prop_protoid;
129
130
  struct iked_spi      prop_localspi;
131
  struct iked_spi      prop_peerspi;
132
133
  struct iked_transform   *prop_xforms;
134
  unsigned int       prop_nxforms;
135
136
  TAILQ_ENTRY(iked_proposal)   prop_entry;
137
};
138
TAILQ_HEAD(iked_proposals, iked_proposal);
139
140
struct iked_addr {
141
  int        addr_af;
142
  struct sockaddr_storage    addr;
143
  uint8_t        addr_mask;
144
  int        addr_net;
145
  in_port_t      addr_port;
146
};
147
148
struct iked_ts {
149
  struct iked_addr     ts_addr;
150
  uint8_t        ts_ipproto;
151
  TAILQ_ENTRY(iked_ts)     ts_entry;
152
};
153
TAILQ_HEAD(iked_tss, iked_ts);
154
155
struct iked_flow {
156
  struct iked_addr     flow_src;
157
  struct iked_addr     flow_dst;
158
  unsigned int       flow_dir;  /* in/out */
159
  int        flow_rdomain;
160
  struct iked_addr     flow_prenat;
161
  int        flow_fixed;
162
163
  unsigned int       flow_loaded; /* pfkey done */
164
165
  uint8_t        flow_saproto;
166
  uint8_t        flow_ipproto;
167
168
  struct iked_addr    *flow_local;  /* outer source */
169
  struct iked_addr    *flow_peer; /* outer dest */
170
  struct iked_sa      *flow_ikesa;  /* parent SA */
171
172
  int        flow_transport;
173
174
  RB_ENTRY(iked_flow)    flow_node;
175
  TAILQ_ENTRY(iked_flow)     flow_entry;
176
};
177
RB_HEAD(iked_flows, iked_flow);
178
TAILQ_HEAD(iked_saflows, iked_flow);
179
180
struct iked_childsa {
181
  uint8_t        csa_saproto; /* IPsec protocol */
182
  unsigned int       csa_dir; /* in/out */
183
184
  uint64_t       csa_peerspi; /* peer relation */
185
  uint8_t        csa_loaded;  /* pfkey done */
186
  uint8_t        csa_rekey; /* will be deleted */
187
  uint8_t        csa_allocated; /* from the kernel */
188
  uint8_t        csa_persistent;/* do not rekey */
189
  uint8_t        csa_esn; /* use ESN */
190
  uint8_t        csa_transport; /* transport mode */
191
192
  struct iked_spi      csa_spi;
193
194
  struct ibuf     *csa_encrkey; /* encryption key */
195
  uint16_t       csa_encrid;  /* encryption xform id */
196
197
  struct ibuf     *csa_integrkey; /* auth key */
198
  uint16_t       csa_integrid;  /* auth xform id */
199
200
  struct iked_addr    *csa_local; /* outer source */
201
  struct iked_addr    *csa_peer;  /* outer dest */
202
  struct iked_sa      *csa_ikesa; /* parent SA */
203
204
  struct iked_childsa   *csa_peersa;  /* peer */
205
206
  struct iked_childsa   *csa_bundled; /* IPCOMP */
207
208
  uint16_t       csa_pfsgrpid;  /* pfs group id */
209
210
  RB_ENTRY(iked_childsa)     csa_node;
211
  TAILQ_ENTRY(iked_childsa)  csa_entry;
212
};
213
RB_HEAD(iked_activesas, iked_childsa);
214
TAILQ_HEAD(iked_childsas, iked_childsa);
215
216
217
struct iked_static_id {
218
  uint8_t   id_type;
219
  uint8_t   id_length;
220
  uint8_t   id_offset;
221
  uint8_t   id_data[IKED_ID_SIZE];
222
};
223
224
struct iked_auth {
225
  uint8_t   auth_method;
226
  uint8_t   auth_eap;     /* optional EAP */
227
  uint8_t   auth_length;      /* zero if EAP */
228
  uint8_t   auth_data[IKED_PSK_SIZE];
229
};
230
231
struct iked_cfg {
232
  uint8_t        cfg_action;
233
  uint16_t       cfg_type;
234
  union {
235
    struct iked_addr   address;
236
  } cfg;
237
};
238
239
TAILQ_HEAD(iked_sapeers, iked_sa);
240
241
struct iked_lifetime {
242
  uint64_t       lt_bytes;
243
  uint64_t       lt_seconds;
244
};
245
246
struct iked_policy {
247
  unsigned int       pol_id;
248
  char         pol_name[IKED_ID_SIZE];
249
  unsigned int       pol_iface;
250
251
#define IKED_SKIP_FLAGS      0
252
#define IKED_SKIP_AF       1
253
#define IKED_SKIP_SRC_ADDR     2
254
#define IKED_SKIP_DST_ADDR     3
255
#define IKED_SKIP_COUNT      4
256
  struct iked_policy    *pol_skip[IKED_SKIP_COUNT];
257
258
  uint8_t        pol_flags;
259
#define IKED_POLICY_PASSIVE    0x00
260
#define IKED_POLICY_DEFAULT    0x01
261
#define IKED_POLICY_ACTIVE     0x02
262
#define IKED_POLICY_REFCNT     0x04
263
#define IKED_POLICY_QUICK    0x08
264
#define IKED_POLICY_SKIP     0x10
265
#define IKED_POLICY_IPCOMP     0x20
266
0
#define IKED_POLICY_TRANSPORT    0x40
267
#define IKED_POLICY_ROUTING    0x80
268
269
  int        pol_refcnt;
270
271
  uint8_t        pol_certreqtype;
272
273
  int        pol_af;
274
  int        pol_rdomain;
275
  uint8_t        pol_saproto;
276
  unsigned int       pol_ipproto[IKED_IPPROTO_MAX];
277
  unsigned int       pol_nipproto;
278
279
  struct iked_addr     pol_peer;
280
  struct iked_static_id    pol_peerid;
281
  uint32_t       pol_peerdh;
282
283
  struct iked_addr     pol_local;
284
  struct iked_static_id    pol_localid;
285
286
  struct iked_auth     pol_auth;
287
288
  char         pol_tag[IKED_TAG_SIZE];
289
  unsigned int       pol_tap;
290
291
  struct iked_proposals    pol_proposals;
292
  size_t         pol_nproposals;
293
294
  struct iked_flows    pol_flows;
295
  size_t         pol_nflows;
296
  struct iked_tss      pol_tssrc; /* Traffic Selectors Initiator*/
297
  size_t         pol_tssrc_count;
298
  struct iked_tss      pol_tsdst; /* Traffic Selectors Responder*/
299
  size_t         pol_tsdst_count;
300
301
  struct iked_cfg      pol_cfg[IKED_CFG_MAX];
302
  unsigned int       pol_ncfg;
303
304
  uint32_t       pol_rekey; /* ike SA lifetime */
305
  struct iked_lifetime     pol_lifetime;  /* child SA lifetime */
306
307
  struct iked_sapeers    pol_sapeers;
308
309
  TAILQ_ENTRY(iked_policy)   pol_entry;
310
};
311
TAILQ_HEAD(iked_policies, iked_policy);
312
313
struct iked_hash {
314
  uint8_t    hash_type; /* PRF or INTEGR */
315
  uint16_t   hash_id; /* IKE PRF/INTEGR hash id */
316
  const void  *hash_priv; /* Identifying the hash alg */
317
  void    *hash_ctx;  /* Context of the current invocation */
318
  int    hash_fixedkey; /* Requires fixed key length */
319
  struct ibuf *hash_key;  /* MAC key derived from key seed */
320
  size_t     hash_length; /* Output length */
321
  size_t     hash_trunc;  /* Truncate the output length */
322
  struct iked_hash *hash_prf; /* PRF pointer */
323
  int    hash_isaead;
324
};
325
326
struct iked_cipher {
327
  uint8_t    encr_type; /* ENCR */
328
  uint16_t   encr_id; /* IKE ENCR hash id */
329
  const void  *encr_priv; /* Identifying the hash alg */
330
  void    *encr_ctx;  /* Context of the current invocation */
331
  int    encr_fixedkey; /* Requires fixed key length */
332
  struct ibuf *encr_key;  /* MAC key derived from key seed */
333
  struct ibuf *encr_iv; /* Initialization Vector */
334
  uint64_t   encr_civ;  /* Counter IV for GCM */
335
  size_t     encr_ivlength; /* IV length */
336
  size_t     encr_length; /* Block length */
337
  size_t     encr_saltlength; /* IV salt length */
338
  uint16_t   encr_authid; /* ID of associated authentication */
339
};
340
341
struct iked_dsa {
342
  uint8_t    dsa_method;  /* AUTH method */
343
  const void  *dsa_priv;  /* PRF or signature hash function */
344
  void    *dsa_ctx; /* PRF or signature hash ctx */
345
  struct ibuf *dsa_keydata; /* public, private or shared key */
346
  void    *dsa_key; /* parsed public or private key */
347
  int    dsa_hmac;  /* HMAC or public/private key */
348
  int    dsa_sign;  /* Sign or verify operation */
349
  uint32_t   dsa_flags; /* State flags */
350
};
351
352
struct iked_id {
353
  uint8_t    id_type;
354
  uint8_t    id_offset;
355
  struct ibuf *id_buf;
356
};
357
358
#define IKED_REQ_CERT   0x0001  /* get local certificate (if required) */
359
#define IKED_REQ_CERTVALID  0x0002  /* validated the peer cert */
360
#define IKED_REQ_CERTREQ  0x0004  /* CERTREQ has been received */
361
#define IKED_REQ_AUTH   0x0008  /* AUTH payload */
362
#define IKED_REQ_AUTHVALID  0x0010  /* AUTH payload has been verified */
363
#define IKED_REQ_SA   0x0020  /* SA available */
364
#define IKED_REQ_EAPVALID 0x0040  /* EAP payload has been verified */
365
#define IKED_REQ_CHILDSA  0x0080  /* Child SA initiated */
366
#define IKED_REQ_INF    0x0100  /* Informational exchange initiated */
367
368
#define IKED_REQ_BITS \
369
    "\20\01CERT\02CERTVALID\03CERTREQ\04AUTH\05AUTHVALID\06SA\07EAPVALID" \
370
    "\10CHILDSA\11INF"
371
372
TAILQ_HEAD(iked_msgqueue, iked_msg_retransmit);
373
TAILQ_HEAD(iked_msg_fragqueue, iked_message);
374
375
struct iked_sahdr {
376
  uint64_t       sh_ispi; /* Initiator SPI */
377
  uint64_t       sh_rspi; /* Responder SPI */
378
  unsigned int       sh_initiator;  /* Is initiator? */
379
} __packed;
380
381
struct iked_kex {
382
  struct ibuf     *kex_inonce;  /* Ni */
383
  struct ibuf     *kex_rnonce;  /* Nr */
384
385
  struct dh_group     *kex_dhgroup; /* DH group */
386
  struct ibuf     *kex_dhiexchange;
387
  struct ibuf     *kex_dhrexchange;
388
  struct ibuf     *kex_dhpeer;  /* pointer to i or r */
389
};
390
391
struct iked_frag_entry {
392
  uint8_t *frag_data;
393
  size_t   frag_size;
394
};
395
396
struct iked_frag {
397
  struct iked_frag_entry  **frag_arr; /* list of fragment buffers */
398
  size_t        frag_count; /* number of fragments received */
399
0
#define IKED_FRAG_TOTAL_MAX   111    /* upper limit (64kB / 576B) */
400
  size_t        frag_total; /* total numbe of fragments */
401
  size_t        frag_total_size;
402
  uint8_t       frag_nextpayload;
403
404
};
405
406
struct iked_ipcomp {
407
  uint16_t       ic_cpi_out;  /* outgoing CPI */
408
  uint16_t       ic_cpi_in; /* incoming CPI */
409
  uint8_t        ic_transform;  /* transform */
410
};
411
412
struct iked_sa {
413
  struct iked_sahdr    sa_hdr;
414
  uint32_t       sa_msgid;  /* Last request rcvd */
415
  int        sa_msgid_set;  /* msgid initialized */
416
  uint32_t       sa_msgid_current;  /* Current requested rcvd */
417
  uint32_t       sa_reqid;  /* Next request sent */
418
419
  int        sa_type;
420
#define IKED_SATYPE_LOOKUP     0    /* Used for lookup */
421
#define IKED_SATYPE_LOCAL    1    /* Local SA */
422
423
  struct iked_addr     sa_peer;
424
  struct iked_addr     sa_peer_loaded;/* MOBIKE */
425
  struct iked_addr     sa_local;
426
  int        sa_fd;
427
428
  struct iked_frag     sa_fragments;
429
430
  int        sa_natt; /* for IKE messages */
431
  int        sa_udpencap; /* for pfkey */
432
  int        sa_usekeepalive;/* NAT-T keepalive */
433
434
  int        sa_state;
435
  unsigned int       sa_stateflags;
436
  unsigned int       sa_stateinit;  /* SA_INIT */
437
  unsigned int       sa_statevalid; /* IKE_AUTH */
438
439
  int        sa_cp;   /* XXX */
440
  struct iked_addr    *sa_cp_addr;  /* requested address */
441
  struct iked_addr    *sa_cp_addr6; /* requested address */
442
  struct iked_addr    *sa_cp_dns; /* requested dns */
443
444
  struct iked_policy    *sa_policy;
445
  struct timeval       sa_timecreated;
446
  struct timeval       sa_timeused;
447
448
  char        *sa_tag;
449
  const char      *sa_reason; /* reason for close */
450
451
  struct iked_kex      sa_kex;
452
/* XXX compat defines until everything is converted */
453
#define sa_inonce   sa_kex.kex_inonce
454
#define sa_rnonce   sa_kex.kex_rnonce
455
#define sa_dhgroup    sa_kex.kex_dhgroup
456
#define sa_dhiexchange    sa_kex.kex_dhiexchange
457
#define sa_dhrexchange    sa_kex.kex_dhrexchange
458
#define sa_dhpeer   sa_kex.kex_dhpeer
459
460
  struct iked_hash    *sa_prf;  /* PRF alg */
461
  struct iked_hash    *sa_integr; /* integrity alg */
462
  struct iked_cipher    *sa_encr; /* encryption alg */
463
464
  struct ibuf     *sa_key_d;  /* SK_d */
465
  struct ibuf     *sa_key_iauth;  /* SK_ai */
466
  struct ibuf     *sa_key_rauth;  /* SK_ar */
467
  struct ibuf     *sa_key_iencr;  /* SK_ei */
468
  struct ibuf     *sa_key_rencr;  /* SK_er */
469
  struct ibuf     *sa_key_iprf; /* SK_pi */
470
  struct ibuf     *sa_key_rprf; /* SK_pr */
471
472
  struct ibuf     *sa_1stmsg; /* for initiator AUTH */
473
  struct ibuf     *sa_2ndmsg; /* for responder AUTH */
474
  struct iked_id       sa_localauth;  /* local AUTH message */
475
  struct iked_id       sa_peerauth; /* peer AUTH message */
476
  int        sa_sigsha2;  /* use SHA2 for signatures */
477
130k
#define IKED_SCERT_MAX  3 /* max # of supplemental cert payloads */
478
479
  struct iked_id       sa_iid;  /* initiator id */
480
  struct iked_id       sa_rid;  /* responder id */
481
  struct iked_id       sa_icert;  /* initiator cert */
482
  struct iked_id       sa_rcert;  /* responder cert */
483
  struct iked_id       sa_scert[IKED_SCERT_MAX]; /* supplemental certs */
484
#define IKESA_SRCID(x) ((x)->sa_hdr.sh_initiator ? &(x)->sa_iid : &(x)->sa_rid)
485
#define IKESA_DSTID(x) ((x)->sa_hdr.sh_initiator ? &(x)->sa_rid : &(x)->sa_iid)
486
487
  char        *sa_eapid;  /* EAP identity */
488
  struct iked_id       sa_eap;  /* EAP challenge */
489
  struct ibuf     *sa_eapmsk; /* EAK session key */
490
491
  struct iked_proposals    sa_proposals;  /* SA proposals */
492
  struct iked_childsas     sa_childsas; /* IPsec Child SAs */
493
  struct iked_saflows    sa_flows;  /* IPsec flows */
494
495
  struct iked_sa      *sa_nexti;  /* initiated IKE SA */
496
  struct iked_sa      *sa_previ;  /* matching back pointer */
497
  struct iked_sa      *sa_nextr;  /* simultaneous rekey */
498
  struct iked_sa      *sa_prevr;  /* matching back pointer */
499
  uint64_t       sa_rekeyspi; /* peerspi CSA rekey */
500
  struct ibuf     *sa_simult; /* simultaneous rekey */
501
502
  struct iked_ipcomp     sa_ipcompi;  /* IPcomp initator */
503
  struct iked_ipcomp     sa_ipcompr;  /* IPcomp responder */
504
505
  int        sa_mobike; /* MOBIKE */
506
  int        sa_frag; /* fragmentation */
507
508
  int        sa_use_transport_mode; /* peer requested */
509
  int        sa_used_transport_mode; /* we enabled */
510
511
  struct iked_timer    sa_timer;  /* SA timeouts */
512
#define IKED_IKE_SA_EXCHANGE_TIMEOUT   300    /* 5 minutes */
513
#define IKED_IKE_SA_REKEY_TIMEOUT  120    /* 2 minutes */
514
#define IKED_IKE_SA_DELETE_TIMEOUT   120    /* 2 minutes */
515
#define IKED_IKE_SA_ALIVE_TIMEOUT  60   /* 1 minute */
516
517
  struct iked_timer    sa_keepalive;  /* keepalive timer */
518
#define IKED_IKE_SA_KEEPALIVE_TIMEOUT  20
519
520
  struct iked_timer    sa_rekey;  /* rekey timeout */
521
  int        sa_tmpfail;
522
523
  struct iked_msgqueue     sa_requests; /* request queue */
524
#define IKED_RETRANSMIT_TIMEOUT    2    /* 2 seconds */
525
526
  struct iked_msgqueue     sa_responses;  /* response queue */
527
#define IKED_RESPONSE_TIMEOUT    120    /* 2 minutes */
528
529
  TAILQ_ENTRY(iked_sa)     sa_peer_entry;
530
  RB_ENTRY(iked_sa)    sa_entry;  /* all SAs */
531
532
  RB_ENTRY(iked_sa)    sa_dstid_entry;  /* SAs by DSTID */
533
  int        sa_dstid_entry_valid;    /* sa_dstid_entry valid */
534
535
  struct iked_addr    *sa_addrpool; /* address from pool */
536
  RB_ENTRY(iked_sa)    sa_addrpool_entry; /* pool entries */
537
538
  struct iked_addr    *sa_addrpool6;  /* address from pool */
539
  RB_ENTRY(iked_sa)    sa_addrpool6_entry;  /* pool entries */
540
  time_t         sa_last_recvd;
541
#define IKED_IKE_SA_LAST_RECVD_TIMEOUT   300    /* 5 minutes */
542
};
543
RB_HEAD(iked_sas, iked_sa);
544
RB_HEAD(iked_dstid_sas, iked_sa);
545
RB_HEAD(iked_addrpool, iked_sa);
546
RB_HEAD(iked_addrpool6, iked_sa);
547
548
/* stats */
549
550
struct iked_stats {
551
  uint64_t  ikes_sa_created;
552
  uint64_t  ikes_sa_established_total;
553
  uint64_t  ikes_sa_established_current;  /* gauge */
554
  uint64_t  ikes_sa_established_failures;
555
  uint64_t  ikes_sa_proposals_negotiate_failures;
556
  uint64_t  ikes_sa_rekeyed;
557
  uint64_t  ikes_sa_removed;
558
  uint64_t  ikes_csa_created;
559
  uint64_t  ikes_csa_removed;
560
  uint64_t  ikes_msg_sent;
561
  uint64_t  ikes_msg_send_failures;
562
  uint64_t  ikes_msg_rcvd;
563
  uint64_t  ikes_msg_rcvd_busy;
564
  uint64_t  ikes_msg_rcvd_dropped;
565
  uint64_t  ikes_retransmit_request;
566
  uint64_t  ikes_retransmit_response;
567
  uint64_t  ikes_retransmit_limit;
568
  uint64_t  ikes_frag_sent;
569
  uint64_t  ikes_frag_send_failures;
570
  uint64_t  ikes_frag_rcvd;
571
  uint64_t  ikes_frag_rcvd_drop;
572
  uint64_t  ikes_frag_reass_ok;
573
  uint64_t  ikes_frag_reass_drop;
574
  uint64_t  ikes_update_addresses_sent;
575
  uint64_t  ikes_dpd_sent;
576
  uint64_t  ikes_keepalive_sent;
577
};
578
579
0
#define ikestat_add(env, c, n)  do { env->sc_stats.c += (n); } while(0)
580
0
#define ikestat_inc(env, c) ikestat_add(env, c, 1)
581
#define ikestat_dec(env, c) ikestat_add(env, c, -1)
582
583
struct iked_certreq {
584
  struct ibuf     *cr_data;
585
  uint8_t        cr_type;
586
  SIMPLEQ_ENTRY(iked_certreq)  cr_entry;
587
};
588
SIMPLEQ_HEAD(iked_certreqs, iked_certreq);
589
590
#define EAP_STATE_IDENTITY    (1)
591
#define EAP_STATE_MSCHAPV2_CHALLENGE  (2)
592
#define EAP_STATE_MSCHAPV2_SUCCESS  (3)
593
#define EAP_STATE_SUCCESS   (4)
594
595
struct eap_msg {
596
  char    *eam_identity;
597
  char    *eam_user;
598
  int    eam_type;
599
  uint8_t    eam_id;
600
  uint8_t    eam_msrid;
601
  int    eam_success;
602
  int    eam_found;
603
  int    eam_response;
604
  uint8_t    eam_challenge[16];
605
  uint8_t    eam_ntresponse[24];
606
  uint32_t   eam_state;
607
};
608
609
struct iked_message {
610
  struct ibuf   *msg_data;
611
  size_t       msg_offset;
612
613
  struct sockaddr_storage  msg_local;
614
  socklen_t    msg_locallen;
615
616
  struct sockaddr_storage  msg_peer;
617
  socklen_t    msg_peerlen;
618
619
  struct iked_socket  *msg_sock;
620
621
  int      msg_fd;
622
  int      msg_response;
623
  int      msg_responded;
624
  int      msg_valid;
625
  int      msg_natt;
626
  int      msg_natt_rcvd;
627
  int      msg_nat_detected;
628
  int      msg_error;
629
  int      msg_e;
630
  struct iked_message *msg_parent;
631
632
  /* Associated policy and SA */
633
  struct iked_policy  *msg_policy;
634
  struct iked_sa    *msg_sa;
635
636
  uint32_t     msg_msgid;
637
  uint8_t      msg_exchange;
638
639
  /* Parsed information */
640
  struct iked_proposals  msg_proposals;
641
  struct iked_certreqs   msg_certreqs;
642
  struct iked_spi    msg_rekey;
643
  struct ibuf   *msg_nonce; /* dh NONCE */
644
  uint16_t     msg_dhgroup; /* dh group */
645
  struct ibuf   *msg_ke;  /* dh key exchange */
646
  struct iked_id     msg_auth;  /* AUTH payload */
647
  struct iked_id     msg_peerid;
648
  struct iked_id     msg_localid;
649
  struct iked_id     msg_cert;
650
  struct iked_id     msg_scert[IKED_SCERT_MAX]; /* supplemental certs */
651
  struct ibuf   *msg_cookie;
652
  uint16_t     msg_group;
653
  uint16_t     msg_cpi;
654
  uint8_t      msg_transform;
655
  uint16_t     msg_flags;
656
  struct eap_msg     msg_eap;
657
  size_t       msg_del_spisize;
658
  size_t       msg_del_cnt;
659
  struct ibuf   *msg_del_buf;
660
  int      msg_del_protoid;
661
  int      msg_cp;
662
  struct iked_addr  *msg_cp_addr; /* requested address */
663
  struct iked_addr  *msg_cp_addr6;  /* requested address */
664
  struct iked_addr  *msg_cp_dns;  /* requested dns */
665
666
  /* MOBIKE */
667
  int      msg_update_sa_addresses;
668
  struct ibuf   *msg_cookie2;
669
670
  /* Parse stack */
671
  struct iked_proposal  *msg_prop;
672
  uint16_t     msg_attrlength;
673
674
  /* Retransmit queue */
675
  TAILQ_ENTRY(iked_message)
676
         msg_entry;
677
};
678
679
struct iked_msg_retransmit {
680
  struct iked_msg_fragqueue       mrt_frags;
681
  TAILQ_ENTRY(iked_msg_retransmit)      mrt_entry;
682
  struct iked_timer         mrt_timer;
683
  int             mrt_tries;
684
#define IKED_RETRANSMIT_TRIES  5    /* try 5 times */
685
};
686
687
3.34k
#define IKED_MSG_NAT_SRC_IP       0x01
688
22.4k
#define IKED_MSG_NAT_DST_IP       0x02
689
690
0
#define IKED_MSG_FLAGS_FRAGMENTATION      0x0001
691
159
#define IKED_MSG_FLAGS_MOBIKE       0x0002
692
0
#define IKED_MSG_FLAGS_SIGSHA2        0x0004
693
73
#define IKED_MSG_FLAGS_CHILD_SA_NOT_FOUND   0x0008
694
273
#define IKED_MSG_FLAGS_NO_ADDITIONAL_SAS    0x0010
695
0
#define IKED_MSG_FLAGS_AUTHENTICATION_FAILED    0x0020
696
139
#define IKED_MSG_FLAGS_INVALID_KE     0x0040
697
128
#define IKED_MSG_FLAGS_IPCOMP_SUPPORTED     0x0080
698
279
#define IKED_MSG_FLAGS_USE_TRANSPORT      0x0100
699
354
#define IKED_MSG_FLAGS_TEMPORARY_FAILURE    0x0200
700
36
#define IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN   0x0400
701
702
703
struct iked_user {
704
  char       usr_name[LOGIN_NAME_MAX];
705
  char       usr_pass[IKED_PASSWORD_SIZE];
706
  RB_ENTRY(iked_user)  usr_entry;
707
};
708
RB_HEAD(iked_users, iked_user);
709
710
struct privsep_pipes {
711
  int       *pp_pipes[PROC_MAX];
712
};
713
714
struct privsep {
715
  struct privsep_pipes    *ps_pipes[PROC_MAX];
716
  struct privsep_pipes    *ps_pp;
717
718
  struct imsgev     *ps_ievs[PROC_MAX];
719
  const char      *ps_title[PROC_MAX];
720
  pid_t        ps_pid[PROC_MAX];
721
  struct passwd     *ps_pw;
722
  int        ps_noaction;
723
724
  struct control_sock    ps_csock;
725
  struct control_socks     ps_rcsocks;
726
727
  unsigned int       ps_instances[PROC_MAX];
728
  unsigned int       ps_ninstances;
729
  unsigned int       ps_instance;
730
731
  /* Event and signal handlers */
732
  struct event       ps_evsigint;
733
  struct event       ps_evsigterm;
734
  struct event       ps_evsigchld;
735
  struct event       ps_evsighup;
736
  struct event       ps_evsigpipe;
737
  struct event       ps_evsigusr1;
738
739
  struct iked     *ps_env;
740
};
741
742
struct privsep_proc {
743
  const char    *p_title;
744
  enum privsep_procid  p_id;
745
  int     (*p_cb)(int, struct privsep_proc *,
746
            struct imsg *);
747
  void      (*p_init)(struct privsep *,
748
            struct privsep_proc *);
749
  const char    *p_chroot;
750
  struct passwd   *p_pw;
751
  struct privsep    *p_ps;
752
  void      (*p_shutdown)(void);
753
};
754
755
struct privsep_fd {
756
  enum privsep_procid    pf_procid;
757
  unsigned int       pf_instance;
758
};
759
760
#define PROC_PARENT_SOCK_FILENO 3
761
#define PROC_MAX_INSTANCES      32
762
763
struct iked_ocsp_entry {
764
  TAILQ_ENTRY(iked_ocsp_entry) ioe_entry; /* next request */
765
  void      *ioe_ocsp;  /* private ocsp request data */
766
};
767
TAILQ_HEAD(iked_ocsp_requests, iked_ocsp_entry);
768
769
/*
770
 * Daemon configuration
771
 */
772
773
enum natt_mode {
774
  NATT_DEFAULT, /* send/recv with both :500 and NAT-T port */
775
  NATT_DISABLE, /* send/recv with only :500 */
776
  NATT_FORCE, /* send/recv with only NAT-T port */
777
};
778
779
struct iked_static {
780
  uint64_t     st_alive_timeout;
781
  int      st_enforcesingleikesa;
782
  uint8_t      st_frag; /* fragmentation */
783
  uint8_t      st_mobike; /* MOBIKE */
784
  in_port_t    st_nattport;
785
  int      st_stickyaddress; /* addr per DSTID  */
786
  int      st_vendorid;
787
};
788
789
struct iked {
790
  char         sc_conffile[PATH_MAX];
791
792
  uint32_t       sc_opts;
793
  enum natt_mode       sc_nattmode;
794
  uint8_t        sc_passive;
795
  uint8_t        sc_decoupled;
796
797
  struct iked_static     sc_static;
798
799
#define sc_alive_timeout  sc_static.st_alive_timeout
800
#define sc_enforcesingleikesa sc_static.st_enforcesingleikesa
801
#define sc_frag     sc_static.st_frag
802
#define sc_mobike   sc_static.st_mobike
803
#define sc_nattport   sc_static.st_nattport
804
#define sc_stickyaddress  sc_static.st_stickyaddress
805
#define sc_vendorid   sc_static.st_vendorid
806
807
  struct iked_policies     sc_policies;
808
  struct iked_policy    *sc_defaultcon;
809
810
  struct iked_sas      sc_sas;
811
  struct iked_dstid_sas    sc_dstid_sas;
812
  struct iked_activesas    sc_activesas;
813
  struct iked_flows    sc_activeflows;
814
  struct iked_users    sc_users;
815
816
  struct iked_stats    sc_stats;
817
818
  void        *sc_priv; /* per-process */
819
820
  int        sc_pfkey;  /* ike process */
821
  struct event       sc_pfkeyev;
822
  struct event       sc_routeev;
823
  uint8_t        sc_certreqtype;
824
  struct ibuf     *sc_certreq;
825
  void        *sc_vroute;
826
827
  struct iked_socket    *sc_sock4[2];
828
  struct iked_socket    *sc_sock6[2];
829
830
  struct iked_timer    sc_inittmr;
831
#define IKED_INITIATOR_INITIAL     2
832
#define IKED_INITIATOR_INTERVAL    60
833
834
  struct privsep       sc_ps;
835
836
  struct iked_ocsp_requests  sc_ocsp;
837
  char        *sc_ocsp_url;
838
  long         sc_ocsp_tolerate;
839
  long         sc_ocsp_maxage;
840
841
  struct iked_addrpool     sc_addrpool;
842
  struct iked_addrpool6    sc_addrpool6;
843
844
  int        sc_cert_partial_chain;
845
#ifdef WITH_APPARMOR
846
  int        sc_apparmor;
847
#endif
848
};
849
850
struct iked_socket {
851
  int      sock_fd;
852
  struct event     sock_ev;
853
  struct iked   *sock_env;
854
  struct sockaddr_storage  sock_addr;
855
};
856
857
struct ipsec_xf {
858
  const char  *name;
859
  unsigned int   id;
860
  unsigned int   length;
861
  unsigned int   keylength;
862
  unsigned int   nonce;
863
  unsigned int   noauth;
864
};
865
866
struct ipsec_transforms {
867
  const struct ipsec_xf **authxf;
868
  unsigned int      nauthxf;
869
  const struct ipsec_xf **prfxf;
870
  unsigned int      nprfxf;
871
  const struct ipsec_xf **encxf;
872
  unsigned int      nencxf;
873
  const struct ipsec_xf **groupxf;
874
  unsigned int      ngroupxf;
875
  const struct ipsec_xf **esnxf;
876
  unsigned int      nesnxf;
877
};
878
879
struct ipsec_mode {
880
  struct ipsec_transforms **xfs;
881
  unsigned int      nxfs;
882
};
883
884
/* iked.c */
885
void   parent_reload(struct iked *, int, const char *);
886
887
extern struct iked  *iked_env;
888
889
/* control.c */
890
void   control(struct privsep *, struct privsep_proc *);
891
int  control_init(struct privsep *, struct control_sock *);
892
int  control_listen(struct control_sock *);
893
894
/* config.c */
895
struct iked_policy *
896
   config_new_policy(struct iked *);
897
void   config_free_kex(struct iked_kex *);
898
void   config_free_fragments(struct iked_frag *);
899
void   config_free_sa(struct iked *, struct iked_sa *);
900
struct iked_sa *
901
   config_new_sa(struct iked *, int);
902
struct iked_user *
903
   config_new_user(struct iked *, struct iked_user *);
904
uint64_t
905
   config_getspi(void);
906
struct iked_transform *
907
   config_findtransform(struct iked_proposals *, uint8_t, unsigned int);
908
struct iked_transform *
909
   config_findtransform_ext(struct iked_proposals *, uint8_t,int, unsigned int);
910
void   config_free_policy(struct iked *, struct iked_policy *);
911
struct iked_proposal *
912
   config_add_proposal(struct iked_proposals *, unsigned int,
913
      unsigned int);
914
void   config_free_proposal(struct iked_proposals *, struct iked_proposal *);
915
void   config_free_proposals(struct iked_proposals *, unsigned int);
916
void   config_free_flows(struct iked *, struct iked_flows *);
917
void   config_free_childsas(struct iked *, struct iked_childsas *,
918
      struct iked_spi *, struct iked_spi *);
919
int  config_add_transform(struct iked_proposal *,
920
      unsigned int, unsigned int, unsigned int, unsigned int);
921
int  config_setcoupled(struct iked *, unsigned int);
922
int  config_getcoupled(struct iked *, unsigned int);
923
int  config_setmode(struct iked *, unsigned int);
924
int  config_getmode(struct iked *, unsigned int);
925
int  config_setreset(struct iked *, unsigned int, enum privsep_procid);
926
int  config_getreset(struct iked *, struct imsg *);
927
int  config_doreset(struct iked *, unsigned int);
928
int  config_setpolicy(struct iked *, struct iked_policy *,
929
      enum privsep_procid);
930
int  config_getpolicy(struct iked *, struct imsg *);
931
int  config_setflow(struct iked *, struct iked_policy *,
932
      enum privsep_procid);
933
int  config_getflow(struct iked *, struct imsg *);
934
int  config_setsocket(struct iked *, struct sockaddr_storage *, in_port_t,
935
      enum privsep_procid, int);
936
int  config_getsocket(struct iked *env, struct imsg *,
937
      void (*cb)(int, short, void *));
938
int  config_setpfkey(struct iked *);
939
int  config_getpfkey(struct iked *, struct imsg *);
940
int  config_setuser(struct iked *, struct iked_user *, enum privsep_procid);
941
int  config_getuser(struct iked *, struct imsg *);
942
int  config_setcompile(struct iked *, enum privsep_procid);
943
int  config_getcompile(struct iked *);
944
int  config_setocsp(struct iked *);
945
int  config_getocsp(struct iked *, struct imsg *);
946
int  config_setkeys(struct iked *);
947
int  config_getkey(struct iked *, struct imsg *);
948
int  config_setstatic(struct iked *);
949
int  config_getstatic(struct iked *, struct imsg *);
950
int  config_setcertpartialchain(struct iked *);
951
int  config_getcertpartialchain(struct iked *, struct imsg *);
952
953
/* policy.c */
954
void   policy_init(struct iked *);
955
int  policy_lookup(struct iked *, struct iked_message *,
956
      struct iked_proposals *, struct iked_flows *, int);
957
int  policy_lookup_sa(struct iked *, struct iked_sa *);
958
struct iked_policy *
959
   policy_test(struct iked *, struct iked_policy *);
960
int  policy_generate_ts(struct iked_policy *);
961
void   policy_calc_skip_steps(struct iked_policies *);
962
void   policy_ref(struct iked *, struct iked_policy *);
963
void   policy_unref(struct iked *, struct iked_policy *);
964
void   sa_state(struct iked *, struct iked_sa *, int);
965
void   sa_stateflags(struct iked_sa *, unsigned int);
966
int  sa_stateok(const struct iked_sa *, int);
967
struct iked_sa *
968
   sa_new(struct iked *, uint64_t, uint64_t, unsigned int,
969
      struct iked_policy *);
970
void   sa_free(struct iked *, struct iked_sa *);
971
void   sa_free_flows(struct iked *, struct iked_saflows *);
972
int  sa_configure_iface(struct iked *, struct iked_sa *, int);
973
int  sa_address(struct iked_sa *, struct iked_addr *, struct sockaddr *);
974
void   childsa_free(struct iked_childsa *);
975
struct iked_childsa *
976
   childsa_lookup(struct iked_sa *, uint64_t, uint8_t);
977
void   flow_free(struct iked_flow *);
978
int  flow_equal(struct iked_flow *, struct iked_flow *);
979
struct iked_sa *
980
   sa_lookup(struct iked *, uint64_t, uint64_t, unsigned int);
981
struct iked_user *
982
   user_lookup(struct iked *, const char *);
983
struct iked_sa *
984
   sa_dstid_lookup(struct iked *, struct iked_sa *);
985
struct iked_sa *
986
   sa_dstid_insert(struct iked *, struct iked_sa *);
987
void   sa_dstid_remove(struct iked *, struct iked_sa *);
988
int  proposals_negotiate(struct iked_proposals *, struct iked_proposals *,
989
      struct iked_proposals *, int, int);
990
RB_PROTOTYPE(iked_sas, iked_sa, sa_entry, sa_cmp);
991
RB_PROTOTYPE(iked_dstid_sas, iked_sa, sa_dstid_entry, sa_dstid_cmp);
992
RB_PROTOTYPE(iked_addrpool, iked_sa, sa_addrpool_entry, sa_addrpool_cmp);
993
RB_PROTOTYPE(iked_addrpool6, iked_sa, sa_addrpool6_entry, sa_addrpool6_cmp);
994
RB_PROTOTYPE(iked_users, iked_user, user_entry, user_cmp);
995
RB_PROTOTYPE(iked_activesas, iked_childsa, csa_node, childsa_cmp);
996
RB_PROTOTYPE(iked_flows, iked_flow, flow_node, flow_cmp);
997
998
/* crypto.c */
999
struct iked_hash *
1000
   hash_new(uint8_t, uint16_t);
1001
struct ibuf *
1002
   hash_setkey(struct iked_hash *, void *, size_t);
1003
void   hash_free(struct iked_hash *);
1004
void   hash_init(struct iked_hash *);
1005
void   hash_update(struct iked_hash *, void *, size_t);
1006
void   hash_final(struct iked_hash *, void *, size_t *);
1007
size_t   hash_keylength(struct iked_hash *);
1008
size_t   hash_length(struct iked_hash *);
1009
1010
struct iked_cipher *
1011
   cipher_new(uint8_t, uint16_t, uint16_t);
1012
struct ibuf *
1013
   cipher_setkey(struct iked_cipher *, const void *, size_t);
1014
struct ibuf *
1015
   cipher_setiv(struct iked_cipher *, const void *, size_t);
1016
int  cipher_settag(struct iked_cipher *, uint8_t *, size_t);
1017
int  cipher_gettag(struct iked_cipher *, uint8_t *, size_t);
1018
void   cipher_free(struct iked_cipher *);
1019
int  cipher_init(struct iked_cipher *, int);
1020
int  cipher_init_encrypt(struct iked_cipher *);
1021
int  cipher_init_decrypt(struct iked_cipher *);
1022
void   cipher_aad(struct iked_cipher *, const void *, size_t, size_t *);
1023
int  cipher_update(struct iked_cipher *, const void *, size_t, void *, size_t *);
1024
int  cipher_final(struct iked_cipher *);
1025
size_t   cipher_length(struct iked_cipher *);
1026
size_t   cipher_keylength(struct iked_cipher *);
1027
size_t   cipher_ivlength(struct iked_cipher *);
1028
size_t   cipher_outlength(struct iked_cipher *, size_t);
1029
1030
struct iked_dsa *
1031
   dsa_new(uint8_t, struct iked_hash *, int);
1032
struct iked_dsa *
1033
   dsa_sign_new(uint8_t, struct iked_hash *);
1034
struct iked_dsa *
1035
   dsa_verify_new(uint8_t, struct iked_hash *);
1036
struct ibuf *
1037
   dsa_setkey(struct iked_dsa *, void *, size_t, uint8_t);
1038
void   dsa_free(struct iked_dsa *);
1039
int  dsa_init(struct iked_dsa *, const void *, size_t);
1040
size_t   dsa_prefix(struct iked_dsa *);
1041
size_t   dsa_length(struct iked_dsa *);
1042
int  dsa_update(struct iked_dsa *, const void *, size_t);
1043
ssize_t  dsa_sign_final(struct iked_dsa *, void *, size_t);
1044
ssize_t  dsa_verify_final(struct iked_dsa *, void *, size_t);
1045
1046
/* vroute.c */
1047
void vroute_init(struct iked *);
1048
int vroute_setaddr(struct iked *, int, struct sockaddr *, int, unsigned int);
1049
void vroute_cleanup(struct iked *);
1050
int vroute_getaddr(struct iked *, struct imsg *);
1051
int vroute_setdns(struct iked *, int, struct sockaddr *, unsigned int);
1052
int vroute_getdns(struct iked *, struct imsg *);
1053
int vroute_setaddroute(struct iked *, uint8_t, struct sockaddr *,
1054
    uint8_t, struct sockaddr *);
1055
int vroute_setcloneroute(struct iked *, uint8_t, struct sockaddr *,
1056
    uint8_t, struct sockaddr *);
1057
int vroute_setdelroute(struct iked *, uint8_t, struct sockaddr *,
1058
    uint8_t, struct sockaddr *);
1059
int vroute_getroute(struct iked *, struct imsg *);
1060
int vroute_getcloneroute(struct iked *, struct imsg *);
1061
1062
/* ikev2.c */
1063
void   ikev2(struct privsep *, struct privsep_proc *);
1064
void   ikev2_recv(struct iked *, struct iked_message *);
1065
void   ikev2_init_ike_sa(struct iked *, void *);
1066
int  ikev2_policy2id(struct iked_static_id *, struct iked_id *, int);
1067
int  ikev2_childsa_enable(struct iked *, struct iked_sa *);
1068
int  ikev2_childsa_delete(struct iked *, struct iked_sa *,
1069
      uint8_t, uint64_t, uint64_t *, int);
1070
void   ikev2_ikesa_recv_delete(struct iked *, struct iked_sa *);
1071
void   ikev2_ike_sa_timeout(struct iked *env, void *);
1072
void   ikev2_ike_sa_setreason(struct iked_sa *, char *);
1073
void   ikev2_reset_alive_timer(struct iked *);
1074
int  ikev2_ike_sa_delete(struct iked *, struct iked_sa *);
1075
1076
struct ibuf *
1077
   ikev2_prfplus(struct iked_hash *, struct ibuf *, struct ibuf *,
1078
      size_t);
1079
ssize_t  ikev2_psk(struct iked_sa *, uint8_t *, size_t, uint8_t **);
1080
ssize_t  ikev2_nat_detection(struct iked *, struct iked_message *,
1081
      void *, size_t, unsigned int, int);
1082
void   ikev2_enable_natt(struct iked *, struct iked_sa *,
1083
      struct iked_message *, int);
1084
int  ikev2_send_informational(struct iked *, struct iked_message *);
1085
int  ikev2_send_ike_e(struct iked *, struct iked_sa *, struct ibuf *,
1086
      uint8_t, uint8_t, int);
1087
struct ike_header *
1088
   ikev2_add_header(struct ibuf *, struct iked_sa *,
1089
      uint32_t, uint8_t, uint8_t, uint8_t);
1090
int  ikev2_set_header(struct ike_header *, size_t);
1091
struct ikev2_payload *
1092
   ikev2_add_payload(struct ibuf *);
1093
int  ikev2_next_payload(struct ikev2_payload *, size_t,
1094
      uint8_t);
1095
int  ikev2_child_sa_acquire(struct iked *, struct iked_flow *);
1096
int  ikev2_child_sa_drop(struct iked *, struct iked_spi *);
1097
int  ikev2_child_sa_rekey(struct iked *, struct iked_spi *);
1098
void   ikev2_disable_rekeying(struct iked *, struct iked_sa *);
1099
int  ikev2_print_id(struct iked_id *, char *, size_t);
1100
int  ikev2_print_static_id(struct iked_static_id *, char *, size_t);
1101
1102
const char  *ikev2_ikesa_info(uint64_t, const char *msg);
1103
#define SPI_IH(hdr)      ikev2_ikesa_info(betoh64((hdr)->ike_ispi), NULL)
1104
9.39k
#define SPI_SH(sh, f)    ikev2_ikesa_info((sh)->sh_ispi, (f))
1105
9.39k
#define SPI_SA(sa, f)    SPI_SH(&(sa)->sa_hdr, (f))
1106
1107
/* ikev2_msg.c */
1108
void   ikev2_msg_cb(int, short, void *);
1109
struct ibuf *
1110
   ikev2_msg_init(struct iked *, struct iked_message *,
1111
      struct sockaddr_storage *, socklen_t,
1112
      struct sockaddr_storage *, socklen_t, int);
1113
struct iked_message *
1114
   ikev2_msg_copy(struct iked *, struct iked_message *);
1115
void   ikev2_msg_cleanup(struct iked *, struct iked_message *);
1116
uint32_t
1117
   ikev2_msg_id(struct iked *, struct iked_sa *);
1118
struct ibuf
1119
  *ikev2_msg_auth(struct iked *, struct iked_sa *, int);
1120
int  ikev2_msg_authsign(struct iked *, struct iked_sa *,
1121
      struct iked_auth *, struct ibuf *);
1122
int  ikev2_msg_authverify(struct iked *, struct iked_sa *,
1123
      struct iked_auth *, uint8_t *, size_t, struct ibuf *);
1124
int  ikev2_msg_valid_ike_sa(struct iked *, struct ike_header *,
1125
      struct iked_message *);
1126
int  ikev2_msg_send(struct iked *, struct iked_message *);
1127
int  ikev2_msg_send_encrypt(struct iked *, struct iked_sa *,
1128
      struct ibuf **, uint8_t, uint8_t, int);
1129
struct ibuf
1130
  *ikev2_msg_encrypt(struct iked *, struct iked_sa *, struct ibuf *,
1131
      struct ibuf *);
1132
struct ibuf *
1133
   ikev2_msg_decrypt(struct iked *, struct iked_sa *,
1134
      struct ibuf *, struct ibuf *);
1135
int  ikev2_msg_integr(struct iked *, struct iked_sa *, struct ibuf *);
1136
int  ikev2_msg_frompeer(struct iked_message *);
1137
struct iked_socket *
1138
   ikev2_msg_getsocket(struct iked *, int, int);
1139
int  ikev2_msg_enqueue(struct iked *, struct iked_msgqueue *,
1140
      struct iked_message *, int);
1141
int  ikev2_msg_retransmit_response(struct iked *, struct iked_sa *,
1142
      struct iked_message *, uint8_t);
1143
void   ikev2_msg_prevail(struct iked *, struct iked_msgqueue *,
1144
      struct iked_message *);
1145
void   ikev2_msg_dispose(struct iked *, struct iked_msgqueue *,
1146
      struct iked_msg_retransmit *);
1147
void   ikev2_msg_flushqueue(struct iked *, struct iked_msgqueue *);
1148
struct iked_msg_retransmit *
1149
   ikev2_msg_lookup(struct iked *, struct iked_msgqueue *,
1150
      struct iked_message *, uint8_t);
1151
1152
/* ikev2_pld.c */
1153
int  ikev2_pld_parse(struct iked *, struct ike_header *,
1154
      struct iked_message *, size_t);
1155
1156
/* eap.c */
1157
int  eap_parse(struct iked *, const struct iked_sa *, struct iked_message*,
1158
      void *, int);
1159
int  eap_success(struct iked *, struct iked_sa *, int);
1160
int  eap_identity_request(struct iked *, struct iked_sa *);
1161
int  eap_mschap_challenge(struct iked *, struct iked_sa *, int, int,
1162
      uint8_t *, size_t);
1163
int  eap_mschap_success(struct iked *, struct iked_sa *, int);
1164
int  eap_challenge_request(struct iked *, struct iked_sa *, int);
1165
1166
/* pfkey.c */
1167
int  pfkey_couple(struct iked *, struct iked_sas *, int);
1168
int  pfkey_flow_add(struct iked *, struct iked_flow *);
1169
int  pfkey_flow_delete(struct iked *, struct iked_flow *);
1170
int  pfkey_sa_init(struct iked *, struct iked_childsa *, uint32_t *);
1171
int  pfkey_sa_add(struct iked *, struct iked_childsa *, struct iked_childsa *);
1172
int  pfkey_sa_update_addresses(struct iked *, struct iked_childsa *);
1173
int  pfkey_sa_delete(struct iked *, struct iked_childsa *);
1174
int  pfkey_sa_last_used(struct iked *, struct iked_childsa *, uint64_t *);
1175
int  pfkey_flush(struct iked *);
1176
int  pfkey_socket(struct iked *);
1177
void   pfkey_init(struct iked *, int fd);
1178
1179
/* ipsec.c */
1180
int  ipsec_couple(struct iked *, struct iked_sas *, int);
1181
int  ipsec_flow_add(struct iked *, struct iked_flow *);
1182
int  ipsec_flow_delete(struct iked *, struct iked_flow *);
1183
int  ipsec_sa_init(struct iked *, struct iked_childsa *, uint32_t *);
1184
int  ipsec_sa_add(struct iked *, struct iked_childsa *, struct iked_childsa *);
1185
int  ipsec_sa_update_addresses(struct iked *, struct iked_childsa *);
1186
int  ipsec_sa_delete(struct iked *, struct iked_childsa *);
1187
int  ipsec_sa_last_used(struct iked *, struct iked_childsa *, uint64_t *);
1188
int  ipsec_sa_rpl(struct iked *, struct iked_childsa *, uint32_t *);
1189
int  ipsec_sa_lifetimes(struct iked *, struct iked_childsa *, struct iked_lifetime *,
1190
       struct iked_lifetime *, struct iked_lifetime *);
1191
int  ipsec_flush(struct iked *);
1192
int  ipsec_socket(struct iked *);
1193
void   ipsec_init(struct iked *, int fd);
1194
1195
/* ca.c */
1196
void   caproc(struct privsep *, struct privsep_proc *);
1197
int  ca_setreq(struct iked *, struct iked_sa *, struct iked_static_id *,
1198
      uint8_t, uint8_t, uint8_t *, size_t, enum privsep_procid);
1199
int  ca_setcert(struct iked *, struct iked_sahdr *, struct iked_id *,
1200
      uint8_t, uint8_t *, size_t, enum privsep_procid);
1201
int  ca_setauth(struct iked *, struct iked_sa *,
1202
      struct ibuf *, enum privsep_procid);
1203
void   ca_getkey(struct privsep *, struct iked_id *, enum imsg_type);
1204
int  ca_certbundle_add(struct ibuf *, struct iked_id *);
1205
int  ca_privkey_serialize(EVP_PKEY *, struct iked_id *);
1206
int  ca_pubkey_serialize(EVP_PKEY *, struct iked_id *);
1207
void   ca_sslinit(void);
1208
void   ca_sslerror(const char *);
1209
char  *ca_asn1_name(uint8_t *, size_t);
1210
void  *ca_x509_name_parse(char *);
1211
void   ca_cert_info(const char *, X509 *);
1212
1213
/* timer.c */
1214
void   timer_set(struct iked *, struct iked_timer *,
1215
      void (*)(struct iked *, void *), void *);
1216
void   timer_add(struct iked *, struct iked_timer *, int);
1217
void   timer_del(struct iked *, struct iked_timer *);
1218
1219
/* proc.c */
1220
void   proc_init(struct privsep *, struct privsep_proc *, unsigned int, int,
1221
      int, char **, enum privsep_procid);
1222
void   proc_kill(struct privsep *);
1223
void   proc_connect(struct privsep *);
1224
void   proc_dispatch(int, short event, void *);
1225
void   proc_run(struct privsep *, struct privsep_proc *,
1226
      struct privsep_proc *, unsigned int,
1227
      void (*)(struct privsep *, struct privsep_proc *, void *), void *);
1228
void   imsg_event_add(struct imsgev *);
1229
int  imsg_compose_event(struct imsgev *, uint16_t, uint32_t,
1230
      pid_t, int, void *, uint16_t);
1231
int  imsg_composev_event(struct imsgev *, uint16_t, uint32_t,
1232
      pid_t, int, const struct iovec *, int);
1233
int  proc_compose_imsg(struct privsep *, enum privsep_procid, int,
1234
      uint16_t, uint32_t, int, void *, uint16_t);
1235
int  proc_compose(struct privsep *, enum privsep_procid,
1236
      uint16_t, void *, uint16_t);
1237
int  proc_composev_imsg(struct privsep *, enum privsep_procid, int,
1238
      uint16_t, uint32_t, int, const struct iovec *, int);
1239
int  proc_composev(struct privsep *, enum privsep_procid,
1240
      uint16_t, const struct iovec *, int);
1241
int  proc_forward_imsg(struct privsep *, struct imsg *,
1242
      enum privsep_procid, int);
1243
struct imsgbuf *
1244
   proc_ibuf(struct privsep *, enum privsep_procid, int);
1245
struct imsgev *
1246
   proc_iev(struct privsep *, enum privsep_procid, int);
1247
enum privsep_procid
1248
   proc_getid(struct privsep_proc *, unsigned int, const char *);
1249
int  proc_flush_imsg(struct privsep *, enum privsep_procid, int);
1250
1251
/* util.c */
1252
int  socket_af(struct sockaddr *, in_port_t);
1253
in_port_t
1254
   socket_getport(struct sockaddr *);
1255
int  socket_setport(struct sockaddr *, in_port_t);
1256
int  socket_getaddr(int, struct sockaddr_storage *);
1257
int  socket_bypass(int, struct sockaddr *);
1258
int  udp_bind(struct sockaddr *, in_port_t);
1259
ssize_t  sendtofrom(int, void *, size_t, int, struct sockaddr *,
1260
      socklen_t, struct sockaddr *, socklen_t);
1261
ssize_t  recvfromto(int, void *, size_t, int, struct sockaddr *,
1262
      socklen_t *, struct sockaddr *, socklen_t *);
1263
const char *
1264
   print_spi(uint64_t, int);
1265
const char *
1266
   print_map(unsigned int, struct iked_constmap *);
1267
void   lc_idtype(char *);
1268
void   print_hex(const uint8_t *, off_t, size_t);
1269
void   print_hexval(const uint8_t *, off_t, size_t);
1270
void   print_hexbuf(struct ibuf *);
1271
const char *
1272
   print_bits(unsigned short, unsigned char *);
1273
int  sockaddr_cmp(struct sockaddr *, struct sockaddr *, int);
1274
uint8_t mask2prefixlen(struct sockaddr *);
1275
uint8_t mask2prefixlen6(struct sockaddr *);
1276
struct in6_addr *
1277
   prefixlen2mask6(uint8_t, uint32_t *);
1278
uint32_t
1279
   prefixlen2mask(uint8_t);
1280
const char *
1281
   print_addr(void *);
1282
char  *get_string(uint8_t *, size_t);
1283
const char *
1284
   print_proto(uint8_t);
1285
int  expand_string(char *, size_t, const char *, const char *);
1286
uint8_t *string2unicode(const char *, size_t *);
1287
void   print_debug(const char *, ...)
1288
      __attribute__((format(printf, 1, 2)));
1289
void   print_verbose(const char *, ...)
1290
      __attribute__((format(printf, 1, 2)));
1291
1292
/* imsg_util.c */
1293
struct ibuf *
1294
   ibuf_new(const void *, size_t);
1295
struct ibuf *
1296
   ibuf_static(void);
1297
size_t   ibuf_length(struct ibuf *);
1298
int  ibuf_setsize(struct ibuf *, size_t);
1299
struct ibuf *
1300
   ibuf_getdata(struct ibuf *, size_t);
1301
struct ibuf *
1302
   ibuf_dup(struct ibuf *);
1303
struct ibuf *
1304
   ibuf_random(size_t);
1305
1306
/* log.c */
1307
void  log_init(int, int);
1308
void  log_procinit(const char *);
1309
void  log_setverbose(int);
1310
int log_getverbose(void);
1311
void  log_warn(const char *, ...)
1312
      __attribute__((__format__ (printf, 1, 2)));
1313
void  log_warnx(const char *, ...)
1314
      __attribute__((__format__ (printf, 1, 2)));
1315
void  log_info(const char *, ...)
1316
      __attribute__((__format__ (printf, 1, 2)));
1317
void  log_debug(const char *, ...)
1318
      __attribute__((__format__ (printf, 1, 2)));
1319
void  logit(int, const char *, ...)
1320
      __attribute__((__format__ (printf, 2, 3)));
1321
void  vlog(int, const char *, va_list)
1322
      __attribute__((__format__ (printf, 2, 0)));
1323
__dead void fatal(const char *, ...)
1324
      __attribute__((__format__ (printf, 1, 2)));
1325
__dead void fatalx(const char *, ...)
1326
      __attribute__((__format__ (printf, 1, 2)));
1327
1328
/* ocsp.c */
1329
int  ocsp_connect(struct iked *, struct imsg *);
1330
int  ocsp_receive_fd(struct iked *, struct imsg *);
1331
int  ocsp_validate_cert(struct iked *, void *, size_t, struct iked_sahdr,
1332
    uint8_t, X509 *);
1333
1334
/* parse.y */
1335
int  parse_config(const char *, struct iked *);
1336
int  cmdline_symset(char *);
1337
extern const struct ipsec_xf authxfs[];
1338
extern const struct ipsec_xf prfxfs[];
1339
extern const struct ipsec_xf *encxfs;
1340
extern const struct ipsec_xf ikeencxfs[];
1341
extern const struct ipsec_xf ipsecencxfs[];
1342
extern const struct ipsec_xf groupxfs[];
1343
extern const struct ipsec_xf esnxfs[];
1344
extern const struct ipsec_xf methodxfs[];
1345
extern const struct ipsec_xf saxfs[];
1346
extern const struct ipsec_xf cpxfs[];
1347
size_t   keylength_xf(unsigned int, unsigned int, unsigned int);
1348
size_t   noncelength_xf(unsigned int, unsigned int);
1349
int  encxf_noauth(unsigned int);
1350
1351
/* print.c */
1352
void   print_user(struct iked_user *);
1353
void   print_policy(struct iked_policy *);
1354
const char *print_xf(unsigned int, unsigned int, const struct ipsec_xf *);
1355
1356
#endif /* IKED_H */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/iked.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: iked.h,v 1.224 2023/08/11 11:24:55 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019-2021 Tobias Heider <tobhe@openbsd.org>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/tree.h>
22
#include <sys/queue.h>
23
#include <arpa/inet.h>
24
#include <limits.h>
25
#include <imsg.h>
26
27
#include <openssl/evp.h>
28
29
#include "openbsd-compat.h"
30
31
#include "types.h"
32
#include "dh.h"
33
34
#define MAXIMUM(a,b) (((a)>(b))?(a):(b))
35
#define MINIMUM(a,b) (((a)<(b))?(a):(b))
36
#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
37
38
#ifndef IKED_H
39
#define IKED_H
40
41
/*
42
 * Common IKEv1/IKEv2 header
43
 */
44
45
struct ike_header {
46
  uint64_t   ike_ispi;    /* Initiator cookie */
47
  uint64_t   ike_rspi;    /* Responder cookie */
48
  uint8_t    ike_nextpayload; /* Next payload type */
49
  uint8_t    ike_version;   /* Major/Minor version number */
50
  uint8_t    ike_exchange;    /* Exchange type */
51
  uint8_t    ike_flags;   /* Message options */
52
  uint32_t   ike_msgid;   /* Message identifier */
53
  uint32_t   ike_length;    /* Total message length */
54
} __packed;
55
56
/*
57
 * Common daemon infrastructure, local imsg etc.
58
 */
59
60
struct imsgev {
61
  struct imsgbuf     ibuf;
62
  void      (*handler)(int, short, void *);
63
  struct event     ev;
64
  struct privsep_proc *proc;
65
  void      *data;
66
  short      events;
67
  const char    *name;
68
};
69
70
#define IMSG_SIZE_CHECK(imsg, p) do {       \
71
  if (IMSG_DATA_SIZE(imsg) < sizeof(*p))      \
72
    fatalx("bad length imsg received");   \
73
} while (0)
74
#define IMSG_DATA_SIZE(imsg)  ((imsg)->hdr.len - IMSG_HEADER_SIZE)
75
76
#define IKED_ADDR_EQ(_a, _b)            \
77
  ((_a)->addr_mask == (_b)->addr_mask &&        \
78
  sockaddr_cmp((struct sockaddr *)&(_a)->addr,      \
79
  (struct sockaddr *)&(_b)->addr, (_a)->addr_mask) == 0)
80
81
#define IKED_ADDR_NEQ(_a, _b)           \
82
  ((_a)->addr_mask != (_b)->addr_mask ||        \
83
  sockaddr_cmp((struct sockaddr *)&(_a)->addr,      \
84
  (struct sockaddr *)&(_b)->addr, (_a)->addr_mask) != 0)
85
86
/* initially control.h */
87
struct control_sock {
88
  const char  *cs_name;
89
  struct event   cs_ev;
90
  struct event   cs_evt;
91
  int    cs_fd;
92
  int    cs_restricted;
93
  void    *cs_env;
94
95
  TAILQ_ENTRY(control_sock) cs_entry;
96
};
97
TAILQ_HEAD(control_socks, control_sock);
98
99
struct ctl_conn {
100
  TAILQ_ENTRY(ctl_conn)  entry;
101
  uint8_t      flags;
102
#define CTL_CONN_NOTIFY    0x01
103
  struct imsgev    iev;
104
};
105
TAILQ_HEAD(ctl_connlist, ctl_conn);
106
107
extern enum privsep_procid privsep_process;
108
109
/*
110
 * Runtime structures
111
 */
112
113
struct iked_timer {
114
  struct event   tmr_ev;
115
  struct iked *tmr_env;
116
  void    (*tmr_cb)(struct iked *, void *);
117
  void    *tmr_cbarg;
118
};
119
120
struct iked_spi {
121
  uint64_t   spi;
122
  uint8_t    spi_size;
123
  uint8_t    spi_protoid;
124
};
125
126
struct iked_proposal {
127
  uint8_t        prop_id;
128
  uint8_t        prop_protoid;
129
130
  struct iked_spi      prop_localspi;
131
  struct iked_spi      prop_peerspi;
132
133
  struct iked_transform   *prop_xforms;
134
  unsigned int       prop_nxforms;
135
136
  TAILQ_ENTRY(iked_proposal)   prop_entry;
137
};
138
TAILQ_HEAD(iked_proposals, iked_proposal);
139
140
struct iked_addr {
141
  int        addr_af;
142
  struct sockaddr_storage    addr;
143
  uint8_t        addr_mask;
144
  int        addr_net;
145
  in_port_t      addr_port;
146
};
147
148
struct iked_ts {
149
  struct iked_addr     ts_addr;
150
  uint8_t        ts_ipproto;
151
  TAILQ_ENTRY(iked_ts)     ts_entry;
152
};
153
TAILQ_HEAD(iked_tss, iked_ts);
154
155
struct iked_flow {
156
  struct iked_addr     flow_src;
157
  struct iked_addr     flow_dst;
158
  unsigned int       flow_dir;  /* in/out */
159
  int        flow_rdomain;
160
  struct iked_addr     flow_prenat;
161
  int        flow_fixed;
162
163
  unsigned int       flow_loaded; /* pfkey done */
164
165
  uint8_t        flow_saproto;
166
  uint8_t        flow_ipproto;
167
168
  struct iked_addr    *flow_local;  /* outer source */
169
  struct iked_addr    *flow_peer; /* outer dest */
170
  struct iked_sa      *flow_ikesa;  /* parent SA */
171
172
  int        flow_transport;
173
174
  RB_ENTRY(iked_flow)    flow_node;
175
  TAILQ_ENTRY(iked_flow)     flow_entry;
176
};
177
RB_HEAD(iked_flows, iked_flow);
178
TAILQ_HEAD(iked_saflows, iked_flow);
179
180
struct iked_childsa {
181
  uint8_t        csa_saproto; /* IPsec protocol */
182
  unsigned int       csa_dir; /* in/out */
183
184
  uint64_t       csa_peerspi; /* peer relation */
185
  uint8_t        csa_loaded;  /* pfkey done */
186
  uint8_t        csa_rekey; /* will be deleted */
187
  uint8_t        csa_allocated; /* from the kernel */
188
  uint8_t        csa_persistent;/* do not rekey */
189
  uint8_t        csa_esn; /* use ESN */
190
  uint8_t        csa_transport; /* transport mode */
191
192
  struct iked_spi      csa_spi;
193
194
  struct ibuf     *csa_encrkey; /* encryption key */
195
  uint16_t       csa_encrid;  /* encryption xform id */
196
197
  struct ibuf     *csa_integrkey; /* auth key */
198
  uint16_t       csa_integrid;  /* auth xform id */
199
200
  struct iked_addr    *csa_local; /* outer source */
201
  struct iked_addr    *csa_peer;  /* outer dest */
202
  struct iked_sa      *csa_ikesa; /* parent SA */
203
204
  struct iked_childsa   *csa_peersa;  /* peer */
205
206
  struct iked_childsa   *csa_bundled; /* IPCOMP */
207
208
  uint16_t       csa_pfsgrpid;  /* pfs group id */
209
210
  RB_ENTRY(iked_childsa)     csa_node;
211
  TAILQ_ENTRY(iked_childsa)  csa_entry;
212
};
213
RB_HEAD(iked_activesas, iked_childsa);
214
TAILQ_HEAD(iked_childsas, iked_childsa);
215
216
217
struct iked_static_id {
218
  uint8_t   id_type;
219
  uint8_t   id_length;
220
  uint8_t   id_offset;
221
  uint8_t   id_data[IKED_ID_SIZE];
222
};
223
224
struct iked_auth {
225
  uint8_t   auth_method;
226
  uint8_t   auth_eap;     /* optional EAP */
227
  uint8_t   auth_length;      /* zero if EAP */
228
  uint8_t   auth_data[IKED_PSK_SIZE];
229
};
230
231
struct iked_cfg {
232
  uint8_t        cfg_action;
233
  uint16_t       cfg_type;
234
  union {
235
    struct iked_addr   address;
236
  } cfg;
237
};
238
239
TAILQ_HEAD(iked_sapeers, iked_sa);
240
241
struct iked_lifetime {
242
  uint64_t       lt_bytes;
243
  uint64_t       lt_seconds;
244
};
245
246
struct iked_policy {
247
  unsigned int       pol_id;
248
  char         pol_name[IKED_ID_SIZE];
249
  unsigned int       pol_iface;
250
251
#define IKED_SKIP_FLAGS      0
252
#define IKED_SKIP_AF       1
253
#define IKED_SKIP_SRC_ADDR     2
254
#define IKED_SKIP_DST_ADDR     3
255
#define IKED_SKIP_COUNT      4
256
  struct iked_policy    *pol_skip[IKED_SKIP_COUNT];
257
258
  uint8_t        pol_flags;
259
#define IKED_POLICY_PASSIVE    0x00
260
#define IKED_POLICY_DEFAULT    0x01
261
#define IKED_POLICY_ACTIVE     0x02
262
#define IKED_POLICY_REFCNT     0x04
263
#define IKED_POLICY_QUICK    0x08
264
#define IKED_POLICY_SKIP     0x10
265
#define IKED_POLICY_IPCOMP     0x20
266
0
#define IKED_POLICY_TRANSPORT    0x40
267
#define IKED_POLICY_ROUTING    0x80
268
269
  int        pol_refcnt;
270
271
  uint8_t        pol_certreqtype;
272
273
  int        pol_af;
274
  int        pol_rdomain;
275
  uint8_t        pol_saproto;
276
  unsigned int       pol_ipproto[IKED_IPPROTO_MAX];
277
  unsigned int       pol_nipproto;
278
279
  struct iked_addr     pol_peer;
280
  struct iked_static_id    pol_peerid;
281
  uint32_t       pol_peerdh;
282
283
  struct iked_addr     pol_local;
284
  struct iked_static_id    pol_localid;
285
286
  struct iked_auth     pol_auth;
287
288
  char         pol_tag[IKED_TAG_SIZE];
289
  unsigned int       pol_tap;
290
291
  struct iked_proposals    pol_proposals;
292
  size_t         pol_nproposals;
293
294
  struct iked_flows    pol_flows;
295
  size_t         pol_nflows;
296
  struct iked_tss      pol_tssrc; /* Traffic Selectors Initiator*/
297
  size_t         pol_tssrc_count;
298
  struct iked_tss      pol_tsdst; /* Traffic Selectors Responder*/
299
  size_t         pol_tsdst_count;
300
301
  struct iked_cfg      pol_cfg[IKED_CFG_MAX];
302
  unsigned int       pol_ncfg;
303
304
  uint32_t       pol_rekey; /* ike SA lifetime */
305
  struct iked_lifetime     pol_lifetime;  /* child SA lifetime */
306
307
  struct iked_sapeers    pol_sapeers;
308
309
  TAILQ_ENTRY(iked_policy)   pol_entry;
310
};
311
TAILQ_HEAD(iked_policies, iked_policy);
312
313
struct iked_hash {
314
  uint8_t    hash_type; /* PRF or INTEGR */
315
  uint16_t   hash_id; /* IKE PRF/INTEGR hash id */
316
  const void  *hash_priv; /* Identifying the hash alg */
317
  void    *hash_ctx;  /* Context of the current invocation */
318
  int    hash_fixedkey; /* Requires fixed key length */
319
  struct ibuf *hash_key;  /* MAC key derived from key seed */
320
  size_t     hash_length; /* Output length */
321
  size_t     hash_trunc;  /* Truncate the output length */
322
  struct iked_hash *hash_prf; /* PRF pointer */
323
  int    hash_isaead;
324
};
325
326
struct iked_cipher {
327
  uint8_t    encr_type; /* ENCR */
328
  uint16_t   encr_id; /* IKE ENCR hash id */
329
  const void  *encr_priv; /* Identifying the hash alg */
330
  void    *encr_ctx;  /* Context of the current invocation */
331
  int    encr_fixedkey; /* Requires fixed key length */
332
  struct ibuf *encr_key;  /* MAC key derived from key seed */
333
  struct ibuf *encr_iv; /* Initialization Vector */
334
  uint64_t   encr_civ;  /* Counter IV for GCM */
335
  size_t     encr_ivlength; /* IV length */
336
  size_t     encr_length; /* Block length */
337
  size_t     encr_saltlength; /* IV salt length */
338
  uint16_t   encr_authid; /* ID of associated authentication */
339
};
340
341
struct iked_dsa {
342
  uint8_t    dsa_method;  /* AUTH method */
343
  const void  *dsa_priv;  /* PRF or signature hash function */
344
  void    *dsa_ctx; /* PRF or signature hash ctx */
345
  struct ibuf *dsa_keydata; /* public, private or shared key */
346
  void    *dsa_key; /* parsed public or private key */
347
  int    dsa_hmac;  /* HMAC or public/private key */
348
  int    dsa_sign;  /* Sign or verify operation */
349
  uint32_t   dsa_flags; /* State flags */
350
};
351
352
struct iked_id {
353
  uint8_t    id_type;
354
  uint8_t    id_offset;
355
  struct ibuf *id_buf;
356
};
357
358
#define IKED_REQ_CERT   0x0001  /* get local certificate (if required) */
359
#define IKED_REQ_CERTVALID  0x0002  /* validated the peer cert */
360
#define IKED_REQ_CERTREQ  0x0004  /* CERTREQ has been received */
361
#define IKED_REQ_AUTH   0x0008  /* AUTH payload */
362
#define IKED_REQ_AUTHVALID  0x0010  /* AUTH payload has been verified */
363
#define IKED_REQ_SA   0x0020  /* SA available */
364
#define IKED_REQ_EAPVALID 0x0040  /* EAP payload has been verified */
365
#define IKED_REQ_CHILDSA  0x0080  /* Child SA initiated */
366
#define IKED_REQ_INF    0x0100  /* Informational exchange initiated */
367
368
#define IKED_REQ_BITS \
369
    "\20\01CERT\02CERTVALID\03CERTREQ\04AUTH\05AUTHVALID\06SA\07EAPVALID" \
370
    "\10CHILDSA\11INF"
371
372
TAILQ_HEAD(iked_msgqueue, iked_msg_retransmit);
373
TAILQ_HEAD(iked_msg_fragqueue, iked_message);
374
375
struct iked_sahdr {
376
  uint64_t       sh_ispi; /* Initiator SPI */
377
  uint64_t       sh_rspi; /* Responder SPI */
378
  unsigned int       sh_initiator;  /* Is initiator? */
379
} __packed;
380
381
struct iked_kex {
382
  struct ibuf     *kex_inonce;  /* Ni */
383
  struct ibuf     *kex_rnonce;  /* Nr */
384
385
  struct dh_group     *kex_dhgroup; /* DH group */
386
  struct ibuf     *kex_dhiexchange;
387
  struct ibuf     *kex_dhrexchange;
388
  struct ibuf     *kex_dhpeer;  /* pointer to i or r */
389
};
390
391
struct iked_frag_entry {
392
  uint8_t *frag_data;
393
  size_t   frag_size;
394
};
395
396
struct iked_frag {
397
  struct iked_frag_entry  **frag_arr; /* list of fragment buffers */
398
  size_t        frag_count; /* number of fragments received */
399
0
#define IKED_FRAG_TOTAL_MAX   111    /* upper limit (64kB / 576B) */
400
  size_t        frag_total; /* total numbe of fragments */
401
  size_t        frag_total_size;
402
  uint8_t       frag_nextpayload;
403
404
};
405
406
struct iked_ipcomp {
407
  uint16_t       ic_cpi_out;  /* outgoing CPI */
408
  uint16_t       ic_cpi_in; /* incoming CPI */
409
  uint8_t        ic_transform;  /* transform */
410
};
411
412
struct iked_sa {
413
  struct iked_sahdr    sa_hdr;
414
  uint32_t       sa_msgid;  /* Last request rcvd */
415
  int        sa_msgid_set;  /* msgid initialized */
416
  uint32_t       sa_msgid_current;  /* Current requested rcvd */
417
  uint32_t       sa_reqid;  /* Next request sent */
418
419
  int        sa_type;
420
#define IKED_SATYPE_LOOKUP     0    /* Used for lookup */
421
#define IKED_SATYPE_LOCAL    1    /* Local SA */
422
423
  struct iked_addr     sa_peer;
424
  struct iked_addr     sa_peer_loaded;/* MOBIKE */
425
  struct iked_addr     sa_local;
426
  int        sa_fd;
427
428
  struct iked_frag     sa_fragments;
429
430
  int        sa_natt; /* for IKE messages */
431
  int        sa_udpencap; /* for pfkey */
432
  int        sa_usekeepalive;/* NAT-T keepalive */
433
434
  int        sa_state;
435
  unsigned int       sa_stateflags;
436
  unsigned int       sa_stateinit;  /* SA_INIT */
437
  unsigned int       sa_statevalid; /* IKE_AUTH */
438
439
  int        sa_cp;   /* XXX */
440
  struct iked_addr    *sa_cp_addr;  /* requested address */
441
  struct iked_addr    *sa_cp_addr6; /* requested address */
442
  struct iked_addr    *sa_cp_dns; /* requested dns */
443
444
  struct iked_policy    *sa_policy;
445
  struct timeval       sa_timecreated;
446
  struct timeval       sa_timeused;
447
448
  char        *sa_tag;
449
  const char      *sa_reason; /* reason for close */
450
451
  struct iked_kex      sa_kex;
452
/* XXX compat defines until everything is converted */
453
#define sa_inonce   sa_kex.kex_inonce
454
#define sa_rnonce   sa_kex.kex_rnonce
455
#define sa_dhgroup    sa_kex.kex_dhgroup
456
#define sa_dhiexchange    sa_kex.kex_dhiexchange
457
#define sa_dhrexchange    sa_kex.kex_dhrexchange
458
#define sa_dhpeer   sa_kex.kex_dhpeer
459
460
  struct iked_hash    *sa_prf;  /* PRF alg */
461
  struct iked_hash    *sa_integr; /* integrity alg */
462
  struct iked_cipher    *sa_encr; /* encryption alg */
463
464
  struct ibuf     *sa_key_d;  /* SK_d */
465
  struct ibuf     *sa_key_iauth;  /* SK_ai */
466
  struct ibuf     *sa_key_rauth;  /* SK_ar */
467
  struct ibuf     *sa_key_iencr;  /* SK_ei */
468
  struct ibuf     *sa_key_rencr;  /* SK_er */
469
  struct ibuf     *sa_key_iprf; /* SK_pi */
470
  struct ibuf     *sa_key_rprf; /* SK_pr */
471
472
  struct ibuf     *sa_1stmsg; /* for initiator AUTH */
473
  struct ibuf     *sa_2ndmsg; /* for responder AUTH */
474
  struct iked_id       sa_localauth;  /* local AUTH message */
475
  struct iked_id       sa_peerauth; /* peer AUTH message */
476
  int        sa_sigsha2;  /* use SHA2 for signatures */
477
130k
#define IKED_SCERT_MAX  3 /* max # of supplemental cert payloads */
478
479
  struct iked_id       sa_iid;  /* initiator id */
480
  struct iked_id       sa_rid;  /* responder id */
481
  struct iked_id       sa_icert;  /* initiator cert */
482
  struct iked_id       sa_rcert;  /* responder cert */
483
  struct iked_id       sa_scert[IKED_SCERT_MAX]; /* supplemental certs */
484
#define IKESA_SRCID(x) ((x)->sa_hdr.sh_initiator ? &(x)->sa_iid : &(x)->sa_rid)
485
#define IKESA_DSTID(x) ((x)->sa_hdr.sh_initiator ? &(x)->sa_rid : &(x)->sa_iid)
486
487
  char        *sa_eapid;  /* EAP identity */
488
  struct iked_id       sa_eap;  /* EAP challenge */
489
  struct ibuf     *sa_eapmsk; /* EAK session key */
490
491
  struct iked_proposals    sa_proposals;  /* SA proposals */
492
  struct iked_childsas     sa_childsas; /* IPsec Child SAs */
493
  struct iked_saflows    sa_flows;  /* IPsec flows */
494
495
  struct iked_sa      *sa_nexti;  /* initiated IKE SA */
496
  struct iked_sa      *sa_previ;  /* matching back pointer */
497
  struct iked_sa      *sa_nextr;  /* simultaneous rekey */
498
  struct iked_sa      *sa_prevr;  /* matching back pointer */
499
  uint64_t       sa_rekeyspi; /* peerspi CSA rekey */
500
  struct ibuf     *sa_simult; /* simultaneous rekey */
501
502
  struct iked_ipcomp     sa_ipcompi;  /* IPcomp initator */
503
  struct iked_ipcomp     sa_ipcompr;  /* IPcomp responder */
504
505
  int        sa_mobike; /* MOBIKE */
506
  int        sa_frag; /* fragmentation */
507
508
  int        sa_use_transport_mode; /* peer requested */
509
  int        sa_used_transport_mode; /* we enabled */
510
511
  struct iked_timer    sa_timer;  /* SA timeouts */
512
#define IKED_IKE_SA_EXCHANGE_TIMEOUT   300    /* 5 minutes */
513
#define IKED_IKE_SA_REKEY_TIMEOUT  120    /* 2 minutes */
514
#define IKED_IKE_SA_DELETE_TIMEOUT   120    /* 2 minutes */
515
#define IKED_IKE_SA_ALIVE_TIMEOUT  60   /* 1 minute */
516
517
  struct iked_timer    sa_keepalive;  /* keepalive timer */
518
#define IKED_IKE_SA_KEEPALIVE_TIMEOUT  20
519
520
  struct iked_timer    sa_rekey;  /* rekey timeout */
521
  int        sa_tmpfail;
522
523
  struct iked_msgqueue     sa_requests; /* request queue */
524
#define IKED_RETRANSMIT_TIMEOUT    2    /* 2 seconds */
525
526
  struct iked_msgqueue     sa_responses;  /* response queue */
527
#define IKED_RESPONSE_TIMEOUT    120    /* 2 minutes */
528
529
  TAILQ_ENTRY(iked_sa)     sa_peer_entry;
530
  RB_ENTRY(iked_sa)    sa_entry;  /* all SAs */
531
532
  RB_ENTRY(iked_sa)    sa_dstid_entry;  /* SAs by DSTID */
533
  int        sa_dstid_entry_valid;    /* sa_dstid_entry valid */
534
535
  struct iked_addr    *sa_addrpool; /* address from pool */
536
  RB_ENTRY(iked_sa)    sa_addrpool_entry; /* pool entries */
537
538
  struct iked_addr    *sa_addrpool6;  /* address from pool */
539
  RB_ENTRY(iked_sa)    sa_addrpool6_entry;  /* pool entries */
540
  time_t         sa_last_recvd;
541
#define IKED_IKE_SA_LAST_RECVD_TIMEOUT   300    /* 5 minutes */
542
};
543
RB_HEAD(iked_sas, iked_sa);
544
RB_HEAD(iked_dstid_sas, iked_sa);
545
RB_HEAD(iked_addrpool, iked_sa);
546
RB_HEAD(iked_addrpool6, iked_sa);
547
548
/* stats */
549
550
struct iked_stats {
551
  uint64_t  ikes_sa_created;
552
  uint64_t  ikes_sa_established_total;
553
  uint64_t  ikes_sa_established_current;  /* gauge */
554
  uint64_t  ikes_sa_established_failures;
555
  uint64_t  ikes_sa_proposals_negotiate_failures;
556
  uint64_t  ikes_sa_rekeyed;
557
  uint64_t  ikes_sa_removed;
558
  uint64_t  ikes_csa_created;
559
  uint64_t  ikes_csa_removed;
560
  uint64_t  ikes_msg_sent;
561
  uint64_t  ikes_msg_send_failures;
562
  uint64_t  ikes_msg_rcvd;
563
  uint64_t  ikes_msg_rcvd_busy;
564
  uint64_t  ikes_msg_rcvd_dropped;
565
  uint64_t  ikes_retransmit_request;
566
  uint64_t  ikes_retransmit_response;
567
  uint64_t  ikes_retransmit_limit;
568
  uint64_t  ikes_frag_sent;
569
  uint64_t  ikes_frag_send_failures;
570
  uint64_t  ikes_frag_rcvd;
571
  uint64_t  ikes_frag_rcvd_drop;
572
  uint64_t  ikes_frag_reass_ok;
573
  uint64_t  ikes_frag_reass_drop;
574
  uint64_t  ikes_update_addresses_sent;
575
  uint64_t  ikes_dpd_sent;
576
  uint64_t  ikes_keepalive_sent;
577
};
578
579
0
#define ikestat_add(env, c, n)  do { env->sc_stats.c += (n); } while(0)
580
0
#define ikestat_inc(env, c) ikestat_add(env, c, 1)
581
#define ikestat_dec(env, c) ikestat_add(env, c, -1)
582
583
struct iked_certreq {
584
  struct ibuf     *cr_data;
585
  uint8_t        cr_type;
586
  SIMPLEQ_ENTRY(iked_certreq)  cr_entry;
587
};
588
SIMPLEQ_HEAD(iked_certreqs, iked_certreq);
589
590
#define EAP_STATE_IDENTITY    (1)
591
#define EAP_STATE_MSCHAPV2_CHALLENGE  (2)
592
#define EAP_STATE_MSCHAPV2_SUCCESS  (3)
593
#define EAP_STATE_SUCCESS   (4)
594
595
struct eap_msg {
596
  char    *eam_identity;
597
  char    *eam_user;
598
  int    eam_type;
599
  uint8_t    eam_id;
600
  uint8_t    eam_msrid;
601
  int    eam_success;
602
  int    eam_found;
603
  int    eam_response;
604
  uint8_t    eam_challenge[16];
605
  uint8_t    eam_ntresponse[24];
606
  uint32_t   eam_state;
607
};
608
609
struct iked_message {
610
  struct ibuf   *msg_data;
611
  size_t       msg_offset;
612
613
  struct sockaddr_storage  msg_local;
614
  socklen_t    msg_locallen;
615
616
  struct sockaddr_storage  msg_peer;
617
  socklen_t    msg_peerlen;
618
619
  struct iked_socket  *msg_sock;
620
621
  int      msg_fd;
622
  int      msg_response;
623
  int      msg_responded;
624
  int      msg_valid;
625
  int      msg_natt;
626
  int      msg_natt_rcvd;
627
  int      msg_nat_detected;
628
  int      msg_error;
629
  int      msg_e;
630
  struct iked_message *msg_parent;
631
632
  /* Associated policy and SA */
633
  struct iked_policy  *msg_policy;
634
  struct iked_sa    *msg_sa;
635
636
  uint32_t     msg_msgid;
637
  uint8_t      msg_exchange;
638
639
  /* Parsed information */
640
  struct iked_proposals  msg_proposals;
641
  struct iked_certreqs   msg_certreqs;
642
  struct iked_spi    msg_rekey;
643
  struct ibuf   *msg_nonce; /* dh NONCE */
644
  uint16_t     msg_dhgroup; /* dh group */
645
  struct ibuf   *msg_ke;  /* dh key exchange */
646
  struct iked_id     msg_auth;  /* AUTH payload */
647
  struct iked_id     msg_peerid;
648
  struct iked_id     msg_localid;
649
  struct iked_id     msg_cert;
650
  struct iked_id     msg_scert[IKED_SCERT_MAX]; /* supplemental certs */
651
  struct ibuf   *msg_cookie;
652
  uint16_t     msg_group;
653
  uint16_t     msg_cpi;
654
  uint8_t      msg_transform;
655
  uint16_t     msg_flags;
656
  struct eap_msg     msg_eap;
657
  size_t       msg_del_spisize;
658
  size_t       msg_del_cnt;
659
  struct ibuf   *msg_del_buf;
660
  int      msg_del_protoid;
661
  int      msg_cp;
662
  struct iked_addr  *msg_cp_addr; /* requested address */
663
  struct iked_addr  *msg_cp_addr6;  /* requested address */
664
  struct iked_addr  *msg_cp_dns;  /* requested dns */
665
666
  /* MOBIKE */
667
  int      msg_update_sa_addresses;
668
  struct ibuf   *msg_cookie2;
669
670
  /* Parse stack */
671
  struct iked_proposal  *msg_prop;
672
  uint16_t     msg_attrlength;
673
674
  /* Retransmit queue */
675
  TAILQ_ENTRY(iked_message)
676
         msg_entry;
677
};
678
679
struct iked_msg_retransmit {
680
  struct iked_msg_fragqueue       mrt_frags;
681
  TAILQ_ENTRY(iked_msg_retransmit)      mrt_entry;
682
  struct iked_timer         mrt_timer;
683
  int             mrt_tries;
684
#define IKED_RETRANSMIT_TRIES  5    /* try 5 times */
685
};
686
687
3.34k
#define IKED_MSG_NAT_SRC_IP       0x01
688
22.4k
#define IKED_MSG_NAT_DST_IP       0x02
689
690
0
#define IKED_MSG_FLAGS_FRAGMENTATION      0x0001
691
159
#define IKED_MSG_FLAGS_MOBIKE       0x0002
692
0
#define IKED_MSG_FLAGS_SIGSHA2        0x0004
693
73
#define IKED_MSG_FLAGS_CHILD_SA_NOT_FOUND   0x0008
694
273
#define IKED_MSG_FLAGS_NO_ADDITIONAL_SAS    0x0010
695
0
#define IKED_MSG_FLAGS_AUTHENTICATION_FAILED    0x0020
696
139
#define IKED_MSG_FLAGS_INVALID_KE     0x0040
697
128
#define IKED_MSG_FLAGS_IPCOMP_SUPPORTED     0x0080
698
279
#define IKED_MSG_FLAGS_USE_TRANSPORT      0x0100
699
354
#define IKED_MSG_FLAGS_TEMPORARY_FAILURE    0x0200
700
36
#define IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN   0x0400
701
702
703
struct iked_user {
704
  char       usr_name[LOGIN_NAME_MAX];
705
  char       usr_pass[IKED_PASSWORD_SIZE];
706
  RB_ENTRY(iked_user)  usr_entry;
707
};
708
RB_HEAD(iked_users, iked_user);
709
710
struct privsep_pipes {
711
  int       *pp_pipes[PROC_MAX];
712
};
713
714
struct privsep {
715
  struct privsep_pipes    *ps_pipes[PROC_MAX];
716
  struct privsep_pipes    *ps_pp;
717
718
  struct imsgev     *ps_ievs[PROC_MAX];
719
  const char      *ps_title[PROC_MAX];
720
  pid_t        ps_pid[PROC_MAX];
721
  struct passwd     *ps_pw;
722
  int        ps_noaction;
723
724
  struct control_sock    ps_csock;
725
  struct control_socks     ps_rcsocks;
726
727
  unsigned int       ps_instances[PROC_MAX];
728
  unsigned int       ps_ninstances;
729
  unsigned int       ps_instance;
730
731
  /* Event and signal handlers */
732
  struct event       ps_evsigint;
733
  struct event       ps_evsigterm;
734
  struct event       ps_evsigchld;
735
  struct event       ps_evsighup;
736
  struct event       ps_evsigpipe;
737
  struct event       ps_evsigusr1;
738
739
  struct iked     *ps_env;
740
};
741
742
struct privsep_proc {
743
  const char    *p_title;
744
  enum privsep_procid  p_id;
745
  int     (*p_cb)(int, struct privsep_proc *,
746
            struct imsg *);
747
  void      (*p_init)(struct privsep *,
748
            struct privsep_proc *);
749
  const char    *p_chroot;
750
  struct passwd   *p_pw;
751
  struct privsep    *p_ps;
752
  void      (*p_shutdown)(void);
753
};
754
755
struct privsep_fd {
756
  enum privsep_procid    pf_procid;
757
  unsigned int       pf_instance;
758
};
759
760
#define PROC_PARENT_SOCK_FILENO 3
761
#define PROC_MAX_INSTANCES      32
762
763
struct iked_ocsp_entry {
764
  TAILQ_ENTRY(iked_ocsp_entry) ioe_entry; /* next request */
765
  void      *ioe_ocsp;  /* private ocsp request data */
766
};
767
TAILQ_HEAD(iked_ocsp_requests, iked_ocsp_entry);
768
769
/*
770
 * Daemon configuration
771
 */
772
773
enum natt_mode {
774
  NATT_DEFAULT, /* send/recv with both :500 and NAT-T port */
775
  NATT_DISABLE, /* send/recv with only :500 */
776
  NATT_FORCE, /* send/recv with only NAT-T port */
777
};
778
779
struct iked_static {
780
  uint64_t     st_alive_timeout;
781
  int      st_enforcesingleikesa;
782
  uint8_t      st_frag; /* fragmentation */
783
  uint8_t      st_mobike; /* MOBIKE */
784
  in_port_t    st_nattport;
785
  int      st_stickyaddress; /* addr per DSTID  */
786
  int      st_vendorid;
787
};
788
789
struct iked {
790
  char         sc_conffile[PATH_MAX];
791
792
  uint32_t       sc_opts;
793
  enum natt_mode       sc_nattmode;
794
  uint8_t        sc_passive;
795
  uint8_t        sc_decoupled;
796
797
  struct iked_static     sc_static;
798
799
#define sc_alive_timeout  sc_static.st_alive_timeout
800
#define sc_enforcesingleikesa sc_static.st_enforcesingleikesa
801
#define sc_frag     sc_static.st_frag
802
#define sc_mobike   sc_static.st_mobike
803
#define sc_nattport   sc_static.st_nattport
804
#define sc_stickyaddress  sc_static.st_stickyaddress
805
#define sc_vendorid   sc_static.st_vendorid
806
807
  struct iked_policies     sc_policies;
808
  struct iked_policy    *sc_defaultcon;
809
810
  struct iked_sas      sc_sas;
811
  struct iked_dstid_sas    sc_dstid_sas;
812
  struct iked_activesas    sc_activesas;
813
  struct iked_flows    sc_activeflows;
814
  struct iked_users    sc_users;
815
816
  struct iked_stats    sc_stats;
817
818
  void        *sc_priv; /* per-process */
819
820
  int        sc_pfkey;  /* ike process */
821
  struct event       sc_pfkeyev;
822
  struct event       sc_routeev;
823
  uint8_t        sc_certreqtype;
824
  struct ibuf     *sc_certreq;
825
  void        *sc_vroute;
826
827
  struct iked_socket    *sc_sock4[2];
828
  struct iked_socket    *sc_sock6[2];
829
830
  struct iked_timer    sc_inittmr;
831
#define IKED_INITIATOR_INITIAL     2
832
#define IKED_INITIATOR_INTERVAL    60
833
834
  struct privsep       sc_ps;
835
836
  struct iked_ocsp_requests  sc_ocsp;
837
  char        *sc_ocsp_url;
838
  long         sc_ocsp_tolerate;
839
  long         sc_ocsp_maxage;
840
841
  struct iked_addrpool     sc_addrpool;
842
  struct iked_addrpool6    sc_addrpool6;
843
844
  int        sc_cert_partial_chain;
845
#ifdef WITH_APPARMOR
846
  int        sc_apparmor;
847
#endif
848
};
849
850
struct iked_socket {
851
  int      sock_fd;
852
  struct event     sock_ev;
853
  struct iked   *sock_env;
854
  struct sockaddr_storage  sock_addr;
855
};
856
857
struct ipsec_xf {
858
  const char  *name;
859
  unsigned int   id;
860
  unsigned int   length;
861
  unsigned int   keylength;
862
  unsigned int   nonce;
863
  unsigned int   noauth;
864
};
865
866
struct ipsec_transforms {
867
  const struct ipsec_xf **authxf;
868
  unsigned int      nauthxf;
869
  const struct ipsec_xf **prfxf;
870
  unsigned int      nprfxf;
871
  const struct ipsec_xf **encxf;
872
  unsigned int      nencxf;
873
  const struct ipsec_xf **groupxf;
874
  unsigned int      ngroupxf;
875
  const struct ipsec_xf **esnxf;
876
  unsigned int      nesnxf;
877
};
878
879
struct ipsec_mode {
880
  struct ipsec_transforms **xfs;
881
  unsigned int      nxfs;
882
};
883
884
/* iked.c */
885
void   parent_reload(struct iked *, int, const char *);
886
887
extern struct iked  *iked_env;
888
889
/* control.c */
890
void   control(struct privsep *, struct privsep_proc *);
891
int  control_init(struct privsep *, struct control_sock *);
892
int  control_listen(struct control_sock *);
893
894
/* config.c */
895
struct iked_policy *
896
   config_new_policy(struct iked *);
897
void   config_free_kex(struct iked_kex *);
898
void   config_free_fragments(struct iked_frag *);
899
void   config_free_sa(struct iked *, struct iked_sa *);
900
struct iked_sa *
901
   config_new_sa(struct iked *, int);
902
struct iked_user *
903
   config_new_user(struct iked *, struct iked_user *);
904
uint64_t
905
   config_getspi(void);
906
struct iked_transform *
907
   config_findtransform(struct iked_proposals *, uint8_t, unsigned int);
908
struct iked_transform *
909
   config_findtransform_ext(struct iked_proposals *, uint8_t,int, unsigned int);
910
void   config_free_policy(struct iked *, struct iked_policy *);
911
struct iked_proposal *
912
   config_add_proposal(struct iked_proposals *, unsigned int,
913
      unsigned int);
914
void   config_free_proposal(struct iked_proposals *, struct iked_proposal *);
915
void   config_free_proposals(struct iked_proposals *, unsigned int);
916
void   config_free_flows(struct iked *, struct iked_flows *);
917
void   config_free_childsas(struct iked *, struct iked_childsas *,
918
      struct iked_spi *, struct iked_spi *);
919
int  config_add_transform(struct iked_proposal *,
920
      unsigned int, unsigned int, unsigned int, unsigned int);
921
int  config_setcoupled(struct iked *, unsigned int);
922
int  config_getcoupled(struct iked *, unsigned int);
923
int  config_setmode(struct iked *, unsigned int);
924
int  config_getmode(struct iked *, unsigned int);
925
int  config_setreset(struct iked *, unsigned int, enum privsep_procid);
926
int  config_getreset(struct iked *, struct imsg *);
927
int  config_doreset(struct iked *, unsigned int);
928
int  config_setpolicy(struct iked *, struct iked_policy *,
929
      enum privsep_procid);
930
int  config_getpolicy(struct iked *, struct imsg *);
931
int  config_setflow(struct iked *, struct iked_policy *,
932
      enum privsep_procid);
933
int  config_getflow(struct iked *, struct imsg *);
934
int  config_setsocket(struct iked *, struct sockaddr_storage *, in_port_t,
935
      enum privsep_procid, int);
936
int  config_getsocket(struct iked *env, struct imsg *,
937
      void (*cb)(int, short, void *));
938
int  config_setpfkey(struct iked *);
939
int  config_getpfkey(struct iked *, struct imsg *);
940
int  config_setuser(struct iked *, struct iked_user *, enum privsep_procid);
941
int  config_getuser(struct iked *, struct imsg *);
942
int  config_setcompile(struct iked *, enum privsep_procid);
943
int  config_getcompile(struct iked *);
944
int  config_setocsp(struct iked *);
945
int  config_getocsp(struct iked *, struct imsg *);
946
int  config_setkeys(struct iked *);
947
int  config_getkey(struct iked *, struct imsg *);
948
int  config_setstatic(struct iked *);
949
int  config_getstatic(struct iked *, struct imsg *);
950
int  config_setcertpartialchain(struct iked *);
951
int  config_getcertpartialchain(struct iked *, struct imsg *);
952
953
/* policy.c */
954
void   policy_init(struct iked *);
955
int  policy_lookup(struct iked *, struct iked_message *,
956
      struct iked_proposals *, struct iked_flows *, int);
957
int  policy_lookup_sa(struct iked *, struct iked_sa *);
958
struct iked_policy *
959
   policy_test(struct iked *, struct iked_policy *);
960
int  policy_generate_ts(struct iked_policy *);
961
void   policy_calc_skip_steps(struct iked_policies *);
962
void   policy_ref(struct iked *, struct iked_policy *);
963
void   policy_unref(struct iked *, struct iked_policy *);
964
void   sa_state(struct iked *, struct iked_sa *, int);
965
void   sa_stateflags(struct iked_sa *, unsigned int);
966
int  sa_stateok(const struct iked_sa *, int);
967
struct iked_sa *
968
   sa_new(struct iked *, uint64_t, uint64_t, unsigned int,
969
      struct iked_policy *);
970
void   sa_free(struct iked *, struct iked_sa *);
971
void   sa_free_flows(struct iked *, struct iked_saflows *);
972
int  sa_configure_iface(struct iked *, struct iked_sa *, int);
973
int  sa_address(struct iked_sa *, struct iked_addr *, struct sockaddr *);
974
void   childsa_free(struct iked_childsa *);
975
struct iked_childsa *
976
   childsa_lookup(struct iked_sa *, uint64_t, uint8_t);
977
void   flow_free(struct iked_flow *);
978
int  flow_equal(struct iked_flow *, struct iked_flow *);
979
struct iked_sa *
980
   sa_lookup(struct iked *, uint64_t, uint64_t, unsigned int);
981
struct iked_user *
982
   user_lookup(struct iked *, const char *);
983
struct iked_sa *
984
   sa_dstid_lookup(struct iked *, struct iked_sa *);
985
struct iked_sa *
986
   sa_dstid_insert(struct iked *, struct iked_sa *);
987
void   sa_dstid_remove(struct iked *, struct iked_sa *);
988
int  proposals_negotiate(struct iked_proposals *, struct iked_proposals *,
989
      struct iked_proposals *, int, int);
990
RB_PROTOTYPE(iked_sas, iked_sa, sa_entry, sa_cmp);
991
RB_PROTOTYPE(iked_dstid_sas, iked_sa, sa_dstid_entry, sa_dstid_cmp);
992
RB_PROTOTYPE(iked_addrpool, iked_sa, sa_addrpool_entry, sa_addrpool_cmp);
993
RB_PROTOTYPE(iked_addrpool6, iked_sa, sa_addrpool6_entry, sa_addrpool6_cmp);
994
RB_PROTOTYPE(iked_users, iked_user, user_entry, user_cmp);
995
RB_PROTOTYPE(iked_activesas, iked_childsa, csa_node, childsa_cmp);
996
RB_PROTOTYPE(iked_flows, iked_flow, flow_node, flow_cmp);
997
998
/* crypto.c */
999
struct iked_hash *
1000
   hash_new(uint8_t, uint16_t);
1001
struct ibuf *
1002
   hash_setkey(struct iked_hash *, void *, size_t);
1003
void   hash_free(struct iked_hash *);
1004
void   hash_init(struct iked_hash *);
1005
void   hash_update(struct iked_hash *, void *, size_t);
1006
void   hash_final(struct iked_hash *, void *, size_t *);
1007
size_t   hash_keylength(struct iked_hash *);
1008
size_t   hash_length(struct iked_hash *);
1009
1010
struct iked_cipher *
1011
   cipher_new(uint8_t, uint16_t, uint16_t);
1012
struct ibuf *
1013
   cipher_setkey(struct iked_cipher *, const void *, size_t);
1014
struct ibuf *
1015
   cipher_setiv(struct iked_cipher *, const void *, size_t);
1016
int  cipher_settag(struct iked_cipher *, uint8_t *, size_t);
1017
int  cipher_gettag(struct iked_cipher *, uint8_t *, size_t);
1018
void   cipher_free(struct iked_cipher *);
1019
int  cipher_init(struct iked_cipher *, int);
1020
int  cipher_init_encrypt(struct iked_cipher *);
1021
int  cipher_init_decrypt(struct iked_cipher *);
1022
void   cipher_aad(struct iked_cipher *, const void *, size_t, size_t *);
1023
int  cipher_update(struct iked_cipher *, const void *, size_t, void *, size_t *);
1024
int  cipher_final(struct iked_cipher *);
1025
size_t   cipher_length(struct iked_cipher *);
1026
size_t   cipher_keylength(struct iked_cipher *);
1027
size_t   cipher_ivlength(struct iked_cipher *);
1028
size_t   cipher_outlength(struct iked_cipher *, size_t);
1029
1030
struct iked_dsa *
1031
   dsa_new(uint8_t, struct iked_hash *, int);
1032
struct iked_dsa *
1033
   dsa_sign_new(uint8_t, struct iked_hash *);
1034
struct iked_dsa *
1035
   dsa_verify_new(uint8_t, struct iked_hash *);
1036
struct ibuf *
1037
   dsa_setkey(struct iked_dsa *, void *, size_t, uint8_t);
1038
void   dsa_free(struct iked_dsa *);
1039
int  dsa_init(struct iked_dsa *, const void *, size_t);
1040
size_t   dsa_prefix(struct iked_dsa *);
1041
size_t   dsa_length(struct iked_dsa *);
1042
int  dsa_update(struct iked_dsa *, const void *, size_t);
1043
ssize_t  dsa_sign_final(struct iked_dsa *, void *, size_t);
1044
ssize_t  dsa_verify_final(struct iked_dsa *, void *, size_t);
1045
1046
/* vroute.c */
1047
void vroute_init(struct iked *);
1048
int vroute_setaddr(struct iked *, int, struct sockaddr *, int, unsigned int);
1049
void vroute_cleanup(struct iked *);
1050
int vroute_getaddr(struct iked *, struct imsg *);
1051
int vroute_setdns(struct iked *, int, struct sockaddr *, unsigned int);
1052
int vroute_getdns(struct iked *, struct imsg *);
1053
int vroute_setaddroute(struct iked *, uint8_t, struct sockaddr *,
1054
    uint8_t, struct sockaddr *);
1055
int vroute_setcloneroute(struct iked *, uint8_t, struct sockaddr *,
1056
    uint8_t, struct sockaddr *);
1057
int vroute_setdelroute(struct iked *, uint8_t, struct sockaddr *,
1058
    uint8_t, struct sockaddr *);
1059
int vroute_getroute(struct iked *, struct imsg *);
1060
int vroute_getcloneroute(struct iked *, struct imsg *);
1061
1062
/* ikev2.c */
1063
void   ikev2(struct privsep *, struct privsep_proc *);
1064
void   ikev2_recv(struct iked *, struct iked_message *);
1065
void   ikev2_init_ike_sa(struct iked *, void *);
1066
int  ikev2_policy2id(struct iked_static_id *, struct iked_id *, int);
1067
int  ikev2_childsa_enable(struct iked *, struct iked_sa *);
1068
int  ikev2_childsa_delete(struct iked *, struct iked_sa *,
1069
      uint8_t, uint64_t, uint64_t *, int);
1070
void   ikev2_ikesa_recv_delete(struct iked *, struct iked_sa *);
1071
void   ikev2_ike_sa_timeout(struct iked *env, void *);
1072
void   ikev2_ike_sa_setreason(struct iked_sa *, char *);
1073
void   ikev2_reset_alive_timer(struct iked *);
1074
int  ikev2_ike_sa_delete(struct iked *, struct iked_sa *);
1075
1076
struct ibuf *
1077
   ikev2_prfplus(struct iked_hash *, struct ibuf *, struct ibuf *,
1078
      size_t);
1079
ssize_t  ikev2_psk(struct iked_sa *, uint8_t *, size_t, uint8_t **);
1080
ssize_t  ikev2_nat_detection(struct iked *, struct iked_message *,
1081
      void *, size_t, unsigned int, int);
1082
void   ikev2_enable_natt(struct iked *, struct iked_sa *,
1083
      struct iked_message *, int);
1084
int  ikev2_send_informational(struct iked *, struct iked_message *);
1085
int  ikev2_send_ike_e(struct iked *, struct iked_sa *, struct ibuf *,
1086
      uint8_t, uint8_t, int);
1087
struct ike_header *
1088
   ikev2_add_header(struct ibuf *, struct iked_sa *,
1089
      uint32_t, uint8_t, uint8_t, uint8_t);
1090
int  ikev2_set_header(struct ike_header *, size_t);
1091
struct ikev2_payload *
1092
   ikev2_add_payload(struct ibuf *);
1093
int  ikev2_next_payload(struct ikev2_payload *, size_t,
1094
      uint8_t);
1095
int  ikev2_child_sa_acquire(struct iked *, struct iked_flow *);
1096
int  ikev2_child_sa_drop(struct iked *, struct iked_spi *);
1097
int  ikev2_child_sa_rekey(struct iked *, struct iked_spi *);
1098
void   ikev2_disable_rekeying(struct iked *, struct iked_sa *);
1099
int  ikev2_print_id(struct iked_id *, char *, size_t);
1100
int  ikev2_print_static_id(struct iked_static_id *, char *, size_t);
1101
1102
const char  *ikev2_ikesa_info(uint64_t, const char *msg);
1103
#define SPI_IH(hdr)      ikev2_ikesa_info(betoh64((hdr)->ike_ispi), NULL)
1104
9.39k
#define SPI_SH(sh, f)    ikev2_ikesa_info((sh)->sh_ispi, (f))
1105
9.39k
#define SPI_SA(sa, f)    SPI_SH(&(sa)->sa_hdr, (f))
1106
1107
/* ikev2_msg.c */
1108
void   ikev2_msg_cb(int, short, void *);
1109
struct ibuf *
1110
   ikev2_msg_init(struct iked *, struct iked_message *,
1111
      struct sockaddr_storage *, socklen_t,
1112
      struct sockaddr_storage *, socklen_t, int);
1113
struct iked_message *
1114
   ikev2_msg_copy(struct iked *, struct iked_message *);
1115
void   ikev2_msg_cleanup(struct iked *, struct iked_message *);
1116
uint32_t
1117
   ikev2_msg_id(struct iked *, struct iked_sa *);
1118
struct ibuf
1119
  *ikev2_msg_auth(struct iked *, struct iked_sa *, int);
1120
int  ikev2_msg_authsign(struct iked *, struct iked_sa *,
1121
      struct iked_auth *, struct ibuf *);
1122
int  ikev2_msg_authverify(struct iked *, struct iked_sa *,
1123
      struct iked_auth *, uint8_t *, size_t, struct ibuf *);
1124
int  ikev2_msg_valid_ike_sa(struct iked *, struct ike_header *,
1125
      struct iked_message *);
1126
int  ikev2_msg_send(struct iked *, struct iked_message *);
1127
int  ikev2_msg_send_encrypt(struct iked *, struct iked_sa *,
1128
      struct ibuf **, uint8_t, uint8_t, int);
1129
struct ibuf
1130
  *ikev2_msg_encrypt(struct iked *, struct iked_sa *, struct ibuf *,
1131
      struct ibuf *);
1132
struct ibuf *
1133
   ikev2_msg_decrypt(struct iked *, struct iked_sa *,
1134
      struct ibuf *, struct ibuf *);
1135
int  ikev2_msg_integr(struct iked *, struct iked_sa *, struct ibuf *);
1136
int  ikev2_msg_frompeer(struct iked_message *);
1137
struct iked_socket *
1138
   ikev2_msg_getsocket(struct iked *, int, int);
1139
int  ikev2_msg_enqueue(struct iked *, struct iked_msgqueue *,
1140
      struct iked_message *, int);
1141
int  ikev2_msg_retransmit_response(struct iked *, struct iked_sa *,
1142
      struct iked_message *, uint8_t);
1143
void   ikev2_msg_prevail(struct iked *, struct iked_msgqueue *,
1144
      struct iked_message *);
1145
void   ikev2_msg_dispose(struct iked *, struct iked_msgqueue *,
1146
      struct iked_msg_retransmit *);
1147
void   ikev2_msg_flushqueue(struct iked *, struct iked_msgqueue *);
1148
struct iked_msg_retransmit *
1149
   ikev2_msg_lookup(struct iked *, struct iked_msgqueue *,
1150
      struct iked_message *, uint8_t);
1151
1152
/* ikev2_pld.c */
1153
int  ikev2_pld_parse(struct iked *, struct ike_header *,
1154
      struct iked_message *, size_t);
1155
1156
/* eap.c */
1157
int  eap_parse(struct iked *, const struct iked_sa *, struct iked_message*,
1158
      void *, int);
1159
int  eap_success(struct iked *, struct iked_sa *, int);
1160
int  eap_identity_request(struct iked *, struct iked_sa *);
1161
int  eap_mschap_challenge(struct iked *, struct iked_sa *, int, int,
1162
      uint8_t *, size_t);
1163
int  eap_mschap_success(struct iked *, struct iked_sa *, int);
1164
int  eap_challenge_request(struct iked *, struct iked_sa *, int);
1165
1166
/* pfkey.c */
1167
int  pfkey_couple(struct iked *, struct iked_sas *, int);
1168
int  pfkey_flow_add(struct iked *, struct iked_flow *);
1169
int  pfkey_flow_delete(struct iked *, struct iked_flow *);
1170
int  pfkey_sa_init(struct iked *, struct iked_childsa *, uint32_t *);
1171
int  pfkey_sa_add(struct iked *, struct iked_childsa *, struct iked_childsa *);
1172
int  pfkey_sa_update_addresses(struct iked *, struct iked_childsa *);
1173
int  pfkey_sa_delete(struct iked *, struct iked_childsa *);
1174
int  pfkey_sa_last_used(struct iked *, struct iked_childsa *, uint64_t *);
1175
int  pfkey_flush(struct iked *);
1176
int  pfkey_socket(struct iked *);
1177
void   pfkey_init(struct iked *, int fd);
1178
1179
/* ipsec.c */
1180
int  ipsec_couple(struct iked *, struct iked_sas *, int);
1181
int  ipsec_flow_add(struct iked *, struct iked_flow *);
1182
int  ipsec_flow_delete(struct iked *, struct iked_flow *);
1183
int  ipsec_sa_init(struct iked *, struct iked_childsa *, uint32_t *);
1184
int  ipsec_sa_add(struct iked *, struct iked_childsa *, struct iked_childsa *);
1185
int  ipsec_sa_update_addresses(struct iked *, struct iked_childsa *);
1186
int  ipsec_sa_delete(struct iked *, struct iked_childsa *);
1187
int  ipsec_sa_last_used(struct iked *, struct iked_childsa *, uint64_t *);
1188
int  ipsec_sa_rpl(struct iked *, struct iked_childsa *, uint32_t *);
1189
int  ipsec_sa_lifetimes(struct iked *, struct iked_childsa *, struct iked_lifetime *,
1190
       struct iked_lifetime *, struct iked_lifetime *);
1191
int  ipsec_flush(struct iked *);
1192
int  ipsec_socket(struct iked *);
1193
void   ipsec_init(struct iked *, int fd);
1194
1195
/* ca.c */
1196
void   caproc(struct privsep *, struct privsep_proc *);
1197
int  ca_setreq(struct iked *, struct iked_sa *, struct iked_static_id *,
1198
      uint8_t, uint8_t, uint8_t *, size_t, enum privsep_procid);
1199
int  ca_setcert(struct iked *, struct iked_sahdr *, struct iked_id *,
1200
      uint8_t, uint8_t *, size_t, enum privsep_procid);
1201
int  ca_setauth(struct iked *, struct iked_sa *,
1202
      struct ibuf *, enum privsep_procid);
1203
void   ca_getkey(struct privsep *, struct iked_id *, enum imsg_type);
1204
int  ca_certbundle_add(struct ibuf *, struct iked_id *);
1205
int  ca_privkey_serialize(EVP_PKEY *, struct iked_id *);
1206
int  ca_pubkey_serialize(EVP_PKEY *, struct iked_id *);
1207
void   ca_sslinit(void);
1208
void   ca_sslerror(const char *);
1209
char  *ca_asn1_name(uint8_t *, size_t);
1210
void  *ca_x509_name_parse(char *);
1211
void   ca_cert_info(const char *, X509 *);
1212
1213
/* timer.c */
1214
void   timer_set(struct iked *, struct iked_timer *,
1215
      void (*)(struct iked *, void *), void *);
1216
void   timer_add(struct iked *, struct iked_timer *, int);
1217
void   timer_del(struct iked *, struct iked_timer *);
1218
1219
/* proc.c */
1220
void   proc_init(struct privsep *, struct privsep_proc *, unsigned int, int,
1221
      int, char **, enum privsep_procid);
1222
void   proc_kill(struct privsep *);
1223
void   proc_connect(struct privsep *);
1224
void   proc_dispatch(int, short event, void *);
1225
void   proc_run(struct privsep *, struct privsep_proc *,
1226
      struct privsep_proc *, unsigned int,
1227
      void (*)(struct privsep *, struct privsep_proc *, void *), void *);
1228
void   imsg_event_add(struct imsgev *);
1229
int  imsg_compose_event(struct imsgev *, uint16_t, uint32_t,
1230
      pid_t, int, void *, uint16_t);
1231
int  imsg_composev_event(struct imsgev *, uint16_t, uint32_t,
1232
      pid_t, int, const struct iovec *, int);
1233
int  proc_compose_imsg(struct privsep *, enum privsep_procid, int,
1234
      uint16_t, uint32_t, int, void *, uint16_t);
1235
int  proc_compose(struct privsep *, enum privsep_procid,
1236
      uint16_t, void *, uint16_t);
1237
int  proc_composev_imsg(struct privsep *, enum privsep_procid, int,
1238
      uint16_t, uint32_t, int, const struct iovec *, int);
1239
int  proc_composev(struct privsep *, enum privsep_procid,
1240
      uint16_t, const struct iovec *, int);
1241
int  proc_forward_imsg(struct privsep *, struct imsg *,
1242
      enum privsep_procid, int);
1243
struct imsgbuf *
1244
   proc_ibuf(struct privsep *, enum privsep_procid, int);
1245
struct imsgev *
1246
   proc_iev(struct privsep *, enum privsep_procid, int);
1247
enum privsep_procid
1248
   proc_getid(struct privsep_proc *, unsigned int, const char *);
1249
int  proc_flush_imsg(struct privsep *, enum privsep_procid, int);
1250
1251
/* util.c */
1252
int  socket_af(struct sockaddr *, in_port_t);
1253
in_port_t
1254
   socket_getport(struct sockaddr *);
1255
int  socket_setport(struct sockaddr *, in_port_t);
1256
int  socket_getaddr(int, struct sockaddr_storage *);
1257
int  socket_bypass(int, struct sockaddr *);
1258
int  udp_bind(struct sockaddr *, in_port_t);
1259
ssize_t  sendtofrom(int, void *, size_t, int, struct sockaddr *,
1260
      socklen_t, struct sockaddr *, socklen_t);
1261
ssize_t  recvfromto(int, void *, size_t, int, struct sockaddr *,
1262
      socklen_t *, struct sockaddr *, socklen_t *);
1263
const char *
1264
   print_spi(uint64_t, int);
1265
const char *
1266
   print_map(unsigned int, struct iked_constmap *);
1267
void   lc_idtype(char *);
1268
void   print_hex(const uint8_t *, off_t, size_t);
1269
void   print_hexval(const uint8_t *, off_t, size_t);
1270
void   print_hexbuf(struct ibuf *);
1271
const char *
1272
   print_bits(unsigned short, unsigned char *);
1273
int  sockaddr_cmp(struct sockaddr *, struct sockaddr *, int);
1274
uint8_t mask2prefixlen(struct sockaddr *);
1275
uint8_t mask2prefixlen6(struct sockaddr *);
1276
struct in6_addr *
1277
   prefixlen2mask6(uint8_t, uint32_t *);
1278
uint32_t
1279
   prefixlen2mask(uint8_t);
1280
const char *
1281
   print_addr(void *);
1282
char  *get_string(uint8_t *, size_t);
1283
const char *
1284
   print_proto(uint8_t);
1285
int  expand_string(char *, size_t, const char *, const char *);
1286
uint8_t *string2unicode(const char *, size_t *);
1287
void   print_debug(const char *, ...)
1288
      __attribute__((format(printf, 1, 2)));
1289
void   print_verbose(const char *, ...)
1290
      __attribute__((format(printf, 1, 2)));
1291
1292
/* imsg_util.c */
1293
struct ibuf *
1294
   ibuf_new(const void *, size_t);
1295
struct ibuf *
1296
   ibuf_static(void);
1297
size_t   ibuf_length(struct ibuf *);
1298
int  ibuf_setsize(struct ibuf *, size_t);
1299
struct ibuf *
1300
   ibuf_getdata(struct ibuf *, size_t);
1301
struct ibuf *
1302
   ibuf_dup(struct ibuf *);
1303
struct ibuf *
1304
   ibuf_random(size_t);
1305
1306
/* log.c */
1307
void  log_init(int, int);
1308
void  log_procinit(const char *);
1309
void  log_setverbose(int);
1310
int log_getverbose(void);
1311
void  log_warn(const char *, ...)
1312
      __attribute__((__format__ (printf, 1, 2)));
1313
void  log_warnx(const char *, ...)
1314
      __attribute__((__format__ (printf, 1, 2)));
1315
void  log_info(const char *, ...)
1316
      __attribute__((__format__ (printf, 1, 2)));
1317
void  log_debug(const char *, ...)
1318
      __attribute__((__format__ (printf, 1, 2)));
1319
void  logit(int, const char *, ...)
1320
      __attribute__((__format__ (printf, 2, 3)));
1321
void  vlog(int, const char *, va_list)
1322
      __attribute__((__format__ (printf, 2, 0)));
1323
__dead void fatal(const char *, ...)
1324
      __attribute__((__format__ (printf, 1, 2)));
1325
__dead void fatalx(const char *, ...)
1326
      __attribute__((__format__ (printf, 1, 2)));
1327
1328
/* ocsp.c */
1329
int  ocsp_connect(struct iked *, struct imsg *);
1330
int  ocsp_receive_fd(struct iked *, struct imsg *);
1331
int  ocsp_validate_cert(struct iked *, void *, size_t, struct iked_sahdr,
1332
    uint8_t, X509 *);
1333
1334
/* parse.y */
1335
int  parse_config(const char *, struct iked *);
1336
int  cmdline_symset(char *);
1337
extern const struct ipsec_xf authxfs[];
1338
extern const struct ipsec_xf prfxfs[];
1339
extern const struct ipsec_xf *encxfs;
1340
extern const struct ipsec_xf ikeencxfs[];
1341
extern const struct ipsec_xf ipsecencxfs[];
1342
extern const struct ipsec_xf groupxfs[];
1343
extern const struct ipsec_xf esnxfs[];
1344
extern const struct ipsec_xf methodxfs[];
1345
extern const struct ipsec_xf saxfs[];
1346
extern const struct ipsec_xf cpxfs[];
1347
size_t   keylength_xf(unsigned int, unsigned int, unsigned int);
1348
size_t   noncelength_xf(unsigned int, unsigned int);
1349
int  encxf_noauth(unsigned int);
1350
1351
/* print.c */
1352
void   print_user(struct iked_user *);
1353
void   print_policy(struct iked_policy *);
1354
const char *print_xf(unsigned int, unsigned int, const struct ipsec_xf *);
1355
1356
#endif /* IKED_H */
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/iked/ikev2.h.html b/coverage/latest/report/linux/src/openiked-portable/iked/ikev2.h.html index 8a80e5c77..ab96c128e 100644 --- a/coverage/latest/report/linux/src/openiked-portable/iked/ikev2.h.html +++ b/coverage/latest/report/linux/src/openiked-portable/iked/ikev2.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/ikev2.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: ikev2.h,v 1.35 2023/06/28 14:10:24 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#ifndef IKED_IKEV2_H
21
#define IKED_IKEV2_H
22
23
#include "openbsd-compat.h"
24
25
#define IKEV2_VERSION   0x20  /* IKE version 2.0 */
26
#define IKEV1_VERSION   0x10  /* IKE version 1.0 */
27
28
#define IKEV2_KEYPAD    "Key Pad for IKEv2" /* don't change! */
29
30
/*
31
 * IKEv2 pseudo states
32
 */
33
34
#define IKEV2_STATE_INIT    0 /* new IKE SA */
35
#define IKEV2_STATE_COOKIE    1 /* cookie requested */
36
#define IKEV2_STATE_SA_INIT   2 /* init IKE SA */
37
#define IKEV2_STATE_EAP     3 /* EAP requested */
38
#define IKEV2_STATE_EAP_SUCCESS   4 /* EAP succeeded */
39
#define IKEV2_STATE_AUTH_REQUEST  5 /* auth received */
40
#define IKEV2_STATE_AUTH_SUCCESS  6 /* authenticated */
41
149
#define IKEV2_STATE_VALID   7  /* authenticated AND validated certs */
42
#define IKEV2_STATE_EAP_VALID   8 /* EAP validated */
43
#define IKEV2_STATE_ESTABLISHED   9 /* active IKE SA */
44
#define IKEV2_STATE_CLOSING   10  /* expect delete for this SA */
45
#define IKEV2_STATE_CLOSED    11  /* delete this SA */
46
47
extern struct iked_constmap ikev2_state_map[];
48
49
/*
50
 * "IKEv2 Parameters" based on the official RFC-based assignments by IANA
51
 * (http://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.txt)
52
 */
53
54
/*
55
 * IKEv2 definitions of the IKE header
56
 */
57
58
/* IKEv2 exchange types */
59
#define IKEV2_EXCHANGE_IKE_SA_INIT    34  /* Initial Exchange */
60
#define IKEV2_EXCHANGE_IKE_AUTH     35  /* Authentication */
61
#define IKEV2_EXCHANGE_CREATE_CHILD_SA    36  /* Create Child SA */
62
#define IKEV2_EXCHANGE_INFORMATIONAL    37  /* Informational */
63
#define IKEV2_EXCHANGE_IKE_SESSION_RESUME 38  /* RFC5723 */
64
65
extern struct iked_constmap ikev2_exchange_map[];
66
67
/* IKEv2 message flags */
68
#define IKEV2_FLAG_INITIATOR    0x08  /* Sent by the initiator */
69
#define IKEV2_FLAG_OLDVERSION   0x10  /* Supports a higher IKE version */
70
#define IKEV2_FLAG_RESPONSE   0x20  /* Message is a response */
71
72
extern struct iked_constmap ikev2_flag_map[];
73
74
/*
75
 * IKEv2 payloads
76
 */
77
78
struct ikev2_payload {
79
  uint8_t    pld_nextpayload; /* Next payload type */
80
  uint8_t    pld_reserved;    /* Contains the critical bit */
81
  uint16_t   pld_length;    /* Payload length with header */
82
} __packed;
83
84
struct ikev2_frag_payload {
85
  uint16_t   frag_num;    /* current fragment message number */
86
  uint16_t   frag_total;    /* total number of fragment messages */
87
} __packed;
88
89
279k
#define IKEV2_CRITICAL_PAYLOAD  0x01  /* First bit in the reserved field */
90
91
/* IKEv2 payload types */
92
#define IKEV2_PAYLOAD_NONE  0 /* No payload */
93
32.7k
#define IKEV2_PAYLOAD_SA  33  /* Security Association */
94
10.9k
#define IKEV2_PAYLOAD_KE  34  /* Key Exchange */
95
14.1k
#define IKEV2_PAYLOAD_IDi 35  /* Identification - Initiator */
96
23.8k
#define IKEV2_PAYLOAD_IDr 36  /* Identification - Responder */
97
6.90k
#define IKEV2_PAYLOAD_CERT  37  /* Certificate */
98
15.4k
#define IKEV2_PAYLOAD_CERTREQ 38  /* Certificate Request */
99
10.5k
#define IKEV2_PAYLOAD_AUTH  39  /* Authentication */
100
3.51k
#define IKEV2_PAYLOAD_NONCE 40  /* Nonce */
101
39.8k
#define IKEV2_PAYLOAD_NOTIFY  41  /* Notify */
102
7.54k
#define IKEV2_PAYLOAD_DELETE  42  /* Delete */
103
#define IKEV2_PAYLOAD_VENDOR  43  /* Vendor ID */
104
5.65k
#define IKEV2_PAYLOAD_TSi 44  /* Traffic Selector - Initiator */
105
23.0k
#define IKEV2_PAYLOAD_TSr 45  /* Traffic Selector - Responder */
106
278k
#define IKEV2_PAYLOAD_SK  46  /* Encrypted */
107
11.6k
#define IKEV2_PAYLOAD_CP  47  /* Configuration Payload */
108
21.2k
#define IKEV2_PAYLOAD_EAP 48  /* Extensible Authentication */
109
#define IKEV2_PAYLOAD_GSPM  49  /* RFC6467 Generic Secure Password */
110
278k
#define IKEV2_PAYLOAD_SKF 53  /* RFC7383 Encrypted Fragment Payload */
111
112
extern struct iked_constmap ikev2_payload_map[];
113
114
/*
115
 * SA payload
116
 */
117
118
struct ikev2_sa_proposal {
119
  uint8_t    sap_more;    /* Last proposal or more */
120
  uint8_t    sap_reserved;    /* Must be set to zero */
121
  uint16_t   sap_length;    /* Proposal length */
122
  uint8_t    sap_proposalnr;  /* Proposal number */
123
  uint8_t    sap_protoid;   /* Protocol Id */
124
  uint8_t    sap_spisize;   /* SPI size */
125
  uint8_t    sap_transforms;  /* Number of transforms */
126
  /* Followed by variable-length SPI */
127
  /* Followed by variable-length transforms */
128
} __packed;
129
130
#define IKEV2_SAP_LAST  0
131
#define IKEV2_SAP_MORE  2
132
133
#define IKEV2_SAPROTO_NONE    0 /* None */
134
#define IKEV2_SAPROTO_IKE   1 /* IKEv2 */
135
#define IKEV2_SAPROTO_AH    2 /* AH */
136
#define IKEV2_SAPROTO_ESP   3 /* ESP */
137
#define IKEV2_SAPROTO_FC_ESP_HEADER 4 /* RFC4595 */
138
#define IKEV2_SAPROTO_FC_CT_AUTH  5 /* RFC4595 */
139
#define IKEV2_SAPROTO_IPCOMP    204 /* private, should be 4 */
140
141
extern struct iked_constmap ikev2_saproto_map[];
142
143
struct ikev2_transform {
144
  uint8_t   xfrm_more;    /* Last transform or more */
145
  uint8_t   xfrm_reserved;    /* Must be set to zero */
146
  uint16_t  xfrm_length;    /* Transform length */
147
  uint8_t   xfrm_type;    /* Transform type */
148
  uint8_t   xfrm_reserved1;   /* Must be set to zero */
149
  uint16_t  xfrm_id;    /* Transform Id */
150
  /* Followed by variable-length transform attributes */
151
} __packed;
152
153
#define IKEV2_XFORM_LAST    0
154
3.63k
#define IKEV2_XFORM_MORE    3
155
156
1.27k
#define IKEV2_XFORMTYPE_ENCR    1  /* Encryption */
157
789
#define IKEV2_XFORMTYPE_PRF   2  /* Pseudo-Random Function */
158
174
#define IKEV2_XFORMTYPE_INTEGR    3  /* Integrity Algorithm */
159
861
#define IKEV2_XFORMTYPE_DH    4  /* Diffie-Hellman Group */
160
1.01k
#define IKEV2_XFORMTYPE_ESN   5  /* Extended Sequence Numbers */
161
#define IKEV2_XFORMTYPE_MAX   6
162
163
extern struct iked_constmap ikev2_xformtype_map[];
164
165
#define IKEV2_XFORMENCR_NONE    0 /* None */
166
#define IKEV2_XFORMENCR_DES_IV64  1 /* RFC1827 */
167
#define IKEV2_XFORMENCR_DES   2 /* RFC2405 */
168
#define IKEV2_XFORMENCR_3DES    3 /* RFC2451 */
169
#define IKEV2_XFORMENCR_RC5   4 /* RFC2451 */
170
#define IKEV2_XFORMENCR_IDEA    5 /* RFC2451 */
171
#define IKEV2_XFORMENCR_CAST    6 /* RFC2451 */
172
#define IKEV2_XFORMENCR_BLOWFISH  7 /* RFC2451 */
173
#define IKEV2_XFORMENCR_3IDEA   8 /* RFC2451 */
174
#define IKEV2_XFORMENCR_DES_IV32  9 /* DESIV32 */
175
#define IKEV2_XFORMENCR_RC4   10  /* RFC2451 */
176
#define IKEV2_XFORMENCR_NULL    11  /* RFC2410 */
177
#define IKEV2_XFORMENCR_AES_CBC   12  /* RFC3602 */
178
#define IKEV2_XFORMENCR_AES_CTR   13  /* RFC3664 */
179
#define IKEV2_XFORMENCR_AES_CCM_8 14  /* RFC5282 */
180
#define IKEV2_XFORMENCR_AES_CCM_12  15  /* RFC5282 */
181
#define IKEV2_XFORMENCR_AES_CCM_16  16  /* RFC5282 */
182
#define IKEV2_XFORMENCR_AES_GCM_8 18  /* RFC5282 */
183
#define IKEV2_XFORMENCR_AES_GCM_12  19  /* RFC5282 */
184
#define IKEV2_XFORMENCR_AES_GCM_16  20  /* RFC5282 */
185
#define IKEV2_XFORMENCR_NULL_AES_GMAC 21  /* RFC4543 */
186
#define IKEV2_XFORMENCR_XTS_AES   22  /* IEEE P1619 */
187
#define IKEV2_XFORMENCR_CAMELLIA_CBC  23  /* RFC5529 */
188
#define IKEV2_XFORMENCR_CAMELLIA_CTR  24  /* RFC5529 */
189
#define IKEV2_XFORMENCR_CAMELLIA_CCM_8  25  /* RFC5529 */
190
#define IKEV2_XFORMENCR_CAMELLIA_CCM_12 26  /* RFC5529 */
191
#define IKEV2_XFORMENCR_CAMELLIA_CCM_16 27  /* RFC5529 */
192
#define IKEV2_XFORMENCR_CHACHA20_POLY1305 28  /* RFC7634 */
193
194
extern struct iked_constmap ikev2_xformencr_map[];
195
196
#define IKEV2_IPCOMP_OUI    1 /* UNSPECIFIED */
197
#define IKEV2_IPCOMP_DEFLATE    2 /* RFC2394 */
198
#define IKEV2_IPCOMP_LZS    3 /* RFC2395 */
199
#define IKEV2_IPCOMP_LZJH   4 /* RFC3051 */
200
201
extern struct iked_constmap ikev2_ipcomp_map[];
202
203
#define IKEV2_XFORMPRF_HMAC_MD5   1 /* RFC2104 */
204
#define IKEV2_XFORMPRF_HMAC_SHA1  2 /* RFC2104 */
205
#define IKEV2_XFORMPRF_HMAC_TIGER 3 /* RFC2104 */
206
#define IKEV2_XFORMPRF_AES128_XCBC  4 /* RFC3664 */
207
#define IKEV2_XFORMPRF_HMAC_SHA2_256  5 /* RFC4868 */
208
#define IKEV2_XFORMPRF_HMAC_SHA2_384  6 /* RFC4868 */
209
#define IKEV2_XFORMPRF_HMAC_SHA2_512  7 /* RFC4868 */
210
#define IKEV2_XFORMPRF_AES128_CMAC  8 /* RFC4615 */
211
212
extern struct iked_constmap ikev2_xformprf_map[];
213
214
#define IKEV2_XFORMAUTH_NONE    0 /* No Authentication */
215
#define IKEV2_XFORMAUTH_HMAC_MD5_96 1 /* RFC2403 */
216
#define IKEV2_XFORMAUTH_HMAC_SHA1_96  2 /* RFC2404 */
217
#define IKEV2_XFORMAUTH_DES_MAC   3 /* DES-MAC */
218
#define IKEV2_XFORMAUTH_KPDK_MD5  4 /* RFC1826 */
219
#define IKEV2_XFORMAUTH_AES_XCBC_96 5 /* RFC3566 */
220
#define IKEV2_XFORMAUTH_HMAC_MD5_128  6 /* RFC4595 */
221
#define IKEV2_XFORMAUTH_HMAC_SHA1_160 7 /* RFC4595 */
222
#define IKEV2_XFORMAUTH_AES_CMAC_96 8 /* RFC4494 */
223
#define IKEV2_XFORMAUTH_AES_128_GMAC  9 /* RFC4543 */
224
#define IKEV2_XFORMAUTH_AES_192_GMAC  10  /* RFC4543 */
225
#define IKEV2_XFORMAUTH_AES_256_GMAC  11  /* RFC4543 */
226
#define IKEV2_XFORMAUTH_HMAC_SHA2_256_128 12  /* RFC4868 */
227
#define IKEV2_XFORMAUTH_HMAC_SHA2_384_192 13  /* RFC4868 */
228
#define IKEV2_XFORMAUTH_HMAC_SHA2_512_256 14  /* RFC4868 */
229
230
/* Placeholders for AEAD ciphers (only used internally) */
231
#define IKEV2_XFORMAUTH_AES_GCM_8 2018  /* internal */
232
#define IKEV2_XFORMAUTH_AES_GCM_12  2019  /* internal */
233
#define IKEV2_XFORMAUTH_AES_GCM_16  2020  /* internal */
234
235
extern struct iked_constmap ikev2_xformauth_map[];
236
237
#define IKEV2_XFORMDH_NONE    0 /* No DH */
238
#define IKEV2_XFORMDH_MODP_768    1 /* DH Group 1 */
239
#define IKEV2_XFORMDH_MODP_1024   2 /* DH Group 2 */
240
#define IKEV2_XFORMDH_MODP_1536   5 /* DH Group 5 */
241
#define IKEV2_XFORMDH_MODP_2048   14  /* DH Group 14 */
242
#define IKEV2_XFORMDH_MODP_3072   15  /* DH Group 15 */
243
#define IKEV2_XFORMDH_MODP_4096   16  /* DH Group 16 */
244
#define IKEV2_XFORMDH_MODP_6144   17  /* DH Group 17 */
245
#define IKEV2_XFORMDH_MODP_8192   18  /* DH Group 18 */
246
#define IKEV2_XFORMDH_ECP_256   19  /* RFC5114 */
247
#define IKEV2_XFORMDH_ECP_384   20  /* RFC5114 */
248
#define IKEV2_XFORMDH_ECP_521   21  /* RFC5114 */
249
#define IKEV2_XFORMDH_ECP_192   25  /* RFC5114 */
250
#define IKEV2_XFORMDH_ECP_224   26  /* RFC5114 */
251
#define IKEV2_XFORMDH_BRAINPOOL_P224R1  27  /* RFC6954 */
252
#define IKEV2_XFORMDH_BRAINPOOL_P256R1  28  /* RFC6954 */
253
#define IKEV2_XFORMDH_BRAINPOOL_P384R1  29  /* RFC6954 */
254
#define IKEV2_XFORMDH_BRAINPOOL_P512R1  30  /* RFC6954 */
255
#define IKEV2_XFORMDH_CURVE25519  31  /* RFC8031 */
256
#define IKEV2_XFORMDH_X_SNTRUP761X25519 1035  /* private */
257
258
extern struct iked_constmap ikev2_xformdh_map[];
259
260
#define IKEV2_IPV4_OVERHEAD   (20 + 8 + 28) /* IPv4 + UDP + IKE_HDR*/
261
#define IKEV2_MAXLEN_IPV4_FRAG    (576 - IKEV2_IPV4_OVERHEAD)
262
#define IKEV2_IPV6_OVERHEAD   (40 + 8 + 28) /* IPv6 + UDP + IKE_HDR*/
263
#define IKEV2_MAXLEN_IPV6_FRAG    (1280 - IKEV2_IPV6_OVERHEAD)
264
265
#define IKEV2_MAXNUM_TSS    255 /* 8 bit Number of TSs field */
266
267
#define IKEV2_XFORMESN_NONE   0 /* No ESN */
268
#define IKEV2_XFORMESN_ESN    1 /* ESN */
269
270
extern struct iked_constmap ikev2_xformesn_map[];
271
272
struct ikev2_attribute {
273
  uint16_t  attr_type;  /* Attribute type */
274
  uint16_t  attr_length;  /* Attribute length or value */
275
  /* Followed by variable length (TLV) */
276
} __packed;
277
278
#define IKEV2_ATTRAF_TLV    0x0000  /* Type-Length-Value format */
279
105k
#define IKEV2_ATTRAF_TV     0x8000  /* Type-Value format */
280
281
41.9k
#define IKEV2_ATTRTYPE_KEY_LENGTH 14  /* Key length */
282
283
extern struct iked_constmap ikev2_attrtype_map[];
284
285
/*
286
 * KE Payload
287
 */
288
289
struct ikev2_keyexchange {
290
  uint16_t   kex_dhgroup;   /* DH Group # */
291
  uint16_t   kex_reserved;    /* Reserved */
292
} __packed;
293
294
/*
295
 * N payload
296
 */
297
298
struct ikev2_notify {
299
  uint8_t    n_protoid;   /* Protocol Id */
300
  uint8_t    n_spisize;   /* SPI size */
301
  uint16_t   n_type;    /* Notify message type */
302
  /* Followed by variable length SPI */
303
  /* Followed by variable length notification data */
304
} __packed;
305
306
#define IKEV2_N_UNSUPPORTED_CRITICAL_PAYLOAD  1 /* RFC7296 */
307
#define IKEV2_N_INVALID_IKE_SPI     4 /* RFC7296 */
308
#define IKEV2_N_INVALID_MAJOR_VERSION   5 /* RFC7296 */
309
#define IKEV2_N_INVALID_SYNTAX      7 /* RFC7296 */
310
#define IKEV2_N_INVALID_MESSAGE_ID    9 /* RFC7296 */
311
#define IKEV2_N_INVALID_SPI     11  /* RFC7296 */
312
36
#define IKEV2_N_NO_PROPOSAL_CHOSEN    14  /* RFC7296 */
313
143
#define IKEV2_N_INVALID_KE_PAYLOAD    17  /* RFC7296 */
314
6
#define IKEV2_N_AUTHENTICATION_FAILED   24  /* RFC7296 */
315
#define IKEV2_N_SINGLE_PAIR_REQUIRED    34  /* RFC7296 */
316
273
#define IKEV2_N_NO_ADDITIONAL_SAS   35  /* RFC7296 */
317
#define IKEV2_N_INTERNAL_ADDRESS_FAILURE  36  /* RFC7296 */
318
#define IKEV2_N_FAILED_CP_REQUIRED    37  /* RFC7296 */
319
#define IKEV2_N_TS_UNACCEPTABLE     38  /* RFC7296 */
320
#define IKEV2_N_INVALID_SELECTORS   39  /* RFC7296 */
321
#define IKEV2_N_UNACCEPTABLE_ADDRESSES    40  /* RFC4555 */
322
#define IKEV2_N_UNEXPECTED_NAT_DETECTED   41  /* RFC4555 */
323
#define IKEV2_N_USE_ASSIGNED_HoA    42  /* RFC5026 */
324
354
#define IKEV2_N_TEMPORARY_FAILURE   43  /* RFC7296 */
325
73
#define IKEV2_N_CHILD_SA_NOT_FOUND    44  /* RFC7296 */
326
#define IKEV2_N_INITIAL_CONTACT     16384 /* RFC7296 */
327
#define IKEV2_N_SET_WINDOW_SIZE     16385 /* RFC7296 */
328
#define IKEV2_N_ADDITIONAL_TS_POSSIBLE    16386 /* RFC7296 */
329
255
#define IKEV2_N_IPCOMP_SUPPORTED    16387  /* RFC7296 */
330
29.1k
#define IKEV2_N_NAT_DETECTION_SOURCE_IP   16388  /* RFC7296 */
331
26.0k
#define IKEV2_N_NAT_DETECTION_DESTINATION_IP  16389  /* RFC7296 */
332
2
#define IKEV2_N_COOKIE        16390  /* RFC7296 */
333
356
#define IKEV2_N_USE_TRANSPORT_MODE    16391  /* RFC7296 */
334
#define IKEV2_N_HTTP_CERT_LOOKUP_SUPPORTED  16392 /* RFC7296 */
335
82
#define IKEV2_N_REKEY_SA      16393  /* RFC7296 */
336
#define IKEV2_N_ESP_TFC_PADDING_NOT_SUPPORTED 16394 /* RFC7296 */
337
#define IKEV2_N_NON_FIRST_FRAGMENTS_ALSO  16395 /* RFC7296 */
338
1.81k
#define IKEV2_N_MOBIKE_SUPPORTED    16396  /* RFC4555 */
339
#define IKEV2_N_ADDITIONAL_IP4_ADDRESS    16397 /* RFC4555 */
340
#define IKEV2_N_ADDITIONAL_IP6_ADDRESS    16398 /* RFC4555 */
341
#define IKEV2_N_NO_ADDITIONAL_ADDRESSES   16399 /* RFC4555 */
342
388
#define IKEV2_N_UPDATE_SA_ADDRESSES   16400  /* RFC4555 */
343
242
#define IKEV2_N_COOKIE2       16401  /* RFC4555 */
344
#define IKEV2_N_NO_NATS_ALLOWED     16402 /* RFC4555 */
345
#define IKEV2_N_AUTH_LIFETIME     16403 /* RFC4478 */
346
#define IKEV2_N_MULTIPLE_AUTH_SUPPORTED   16404 /* RFC4739 */
347
#define IKEV2_N_ANOTHER_AUTH_FOLLOWS    16405 /* RFC4739 */
348
#define IKEV2_N_REDIRECT_SUPPORTED    16406 /* RFC5685 */
349
#define IKEV2_N_REDIRECT      16407 /* RFC5685 */
350
#define IKEV2_N_REDIRECTED_FROM     16408 /* RFC5685 */
351
#define IKEV2_N_TICKET_LT_OPAQUE    16409 /* RFC5723 */
352
#define IKEV2_N_TICKET_REQUEST      16410 /* RFC5723 */
353
#define IKEV2_N_TICKET_ACK      16411 /* RFC5723 */
354
#define IKEV2_N_TICKET_NACK     16412 /* RFC5723 */
355
#define IKEV2_N_TICKET_OPAQUE     16413 /* RFC5723 */
356
#define IKEV2_N_LINK_ID       16414 /* RFC5739 */
357
#define IKEV2_N_USE_WESP_MODE     16415 /* RFC5415 */
358
#define IKEV2_N_ROHC_SUPPORTED      16416 /* RFC5857 */
359
#define IKEV2_N_EAP_ONLY_AUTHENTICATION   16417 /* RFC5998 */
360
#define IKEV2_N_CHILDLESS_IKEV2_SUPPORTED 16418 /* RFC6023 */
361
#define IKEV2_N_QUICK_CRASH_DETECTION   16419 /* RFC6290 */
362
#define IKEV2_N_IKEV2_MESSAGE_ID_SYNC_SUPPORTED 16420 /* RFC6311 */
363
#define IKEV2_N_IPSEC_REPLAY_CTR_SYNC_SUPPORTED 16421 /* RFC6311 */
364
#define IKEV2_N_IKEV2_MESSAGE_ID_SYNC   16422 /* RFC6311 */
365
#define IKEV2_N_IPSEC_REPLAY_CTR_SYNC   16423 /* RFC6311 */
366
#define IKEV2_N_SECURE_PASSWORD_METHODS   16424 /* RFC6467 */
367
#define IKEV2_N_PSK_PERSIST     16425 /* RFC6631 */
368
#define IKEV2_N_PSK_CONFIRM     16426 /* RFC6631 */
369
#define IKEV2_N_ERX_SUPPORTED     16427 /* RFC6867 */
370
#define IKEV2_N_IFOM_CAPABILITY     16428 /* OA3GPP */
371
14
#define IKEV2_N_FRAGMENTATION_SUPPORTED   16430  /* RFC7383 */
372
7
#define IKEV2_N_SIGNATURE_HASH_ALGORITHMS 16431  /* RFC7427 */
373
374
extern struct iked_constmap ikev2_n_map[];
375
376
/*
377
 * DELETE payload
378
 */
379
380
struct ikev2_delete {
381
  uint8_t    del_protoid;   /* Protocol Id */
382
  uint8_t    del_spisize;   /* SPI size */
383
  uint16_t   del_nspi;    /* Number of SPIs */
384
  /* Followed by variable length SPIs */
385
} __packed;
386
387
/*
388
 * ID payload
389
 */
390
391
struct ikev2_id {
392
  uint8_t    id_type;   /* Id type */
393
  uint8_t    id_reserved[3];  /* Reserved */
394
  /* Followed by the identification data */
395
} __packed;
396
397
14.3k
#define IKEV2_ID_NONE   0  /* No ID */
398
#define IKEV2_ID_IPV4   1 /* RFC7296 (ID_IPV4_ADDR) */
399
#define IKEV2_ID_FQDN   2 /* RFC7296 */
400
#define IKEV2_ID_UFQDN    3 /* RFC7296 (ID_RFC822_ADDR) */
401
#define IKEV2_ID_IPV6   5 /* RFC7296 (ID_IPV6_ADDR) */
402
#define IKEV2_ID_ASN1_DN  9 /* RFC7296 */
403
#define IKEV2_ID_ASN1_GN  10  /* RFC7296 */
404
#define IKEV2_ID_KEY_ID   11  /* RFC7296 */
405
#define IKEV2_ID_FC_NAME  12  /* RFC4595 */
406
407
extern struct iked_constmap ikev2_id_map[];
408
409
/*
410
 * CERT/CERTREQ payloads
411
 */
412
413
struct ikev2_cert {
414
  uint8_t   cert_type;  /* Encoding */
415
  /* Followed by the certificate data */
416
} __packed;
417
418
5.37k
#define IKEV2_CERT_NONE     0  /* None */
419
#define IKEV2_CERT_X509_PKCS7   1 /* UNSPECIFIED */
420
#define IKEV2_CERT_PGP      2 /* UNSPECIFIED */
421
#define IKEV2_CERT_DNS_SIGNED_KEY 3 /* UNSPECIFIED */
422
1.34k
#define IKEV2_CERT_X509_CERT    4  /* RFC7296 */
423
#define IKEV2_CERT_KERBEROS_TOKEN 6 /* UNSPECIFIED */
424
#define IKEV2_CERT_CRL      7 /* RFC7296 */
425
#define IKEV2_CERT_ARL      8 /* UNSPECIFIED */
426
#define IKEV2_CERT_SPKI     9 /* UNSPECIFIED */
427
#define IKEV2_CERT_X509_ATTR    10  /* UNSPECIFIED */
428
#define IKEV2_CERT_RSA_KEY    11  /* RFC7296 */
429
#define IKEV2_CERT_HASHURL_X509   12  /* RFC7296 */
430
#define IKEV2_CERT_HASHURL_X509_BUNDLE  13  /* RFC7296 */
431
#define IKEV2_CERT_OCSP     14  /* RFC4806 */
432
/*
433
 * As of November 2014, work was still in progress to add a more generic
434
 * format for raw public keys (RFC7296), so we use a number in IANA's private
435
 * use range (201-255, same RFC) for ECDSA.
436
 */
437
#define IKEV2_CERT_ECDSA    201 /* Private */
438
2.78k
#define IKEV2_CERT_BUNDLE   254  /* Private */
439
440
extern struct iked_constmap ikev2_cert_map[];
441
442
/*
443
 * TSi/TSr payloads
444
 */
445
446
struct ikev2_tsp {
447
  uint8_t   tsp_count;    /* Number of TSs */
448
  uint8_t   tsp_reserved[3];  /* Reserved */
449
  /* Followed by the traffic selectors */
450
} __packed;
451
452
struct ikev2_ts {
453
  uint8_t   ts_type;    /* TS type */
454
  uint8_t   ts_protoid;   /* Protocol Id */
455
  uint16_t  ts_length;    /* Length */
456
  uint16_t  ts_startport;   /* Start port */
457
  uint16_t  ts_endport;   /* End port */
458
} __packed;
459
460
9.66k
#define IKEV2_TS_IPV4_ADDR_RANGE  7  /* RFC7296 */
461
1.54k
#define IKEV2_TS_IPV6_ADDR_RANGE  8  /* RFC7296 */
462
#define IKEV2_TS_FC_ADDR_RANGE    9 /* RFC4595 */
463
464
extern struct iked_constmap ikev2_ts_map[];
465
466
/*
467
 * AUTH payload
468
 */
469
470
struct ikev2_auth {
471
  uint8_t   auth_method;    /* Signature type */
472
  uint8_t   auth_reserved[3]; /* Reserved */
473
  /* Followed by the signature */
474
} __packed;
475
476
#define IKEV2_AUTH_NONE     0 /* None */
477
#define IKEV2_AUTH_RSA_SIG    1 /* RFC7296 */
478
#define IKEV2_AUTH_SHARED_KEY_MIC 2 /* RFC7296 */
479
#define IKEV2_AUTH_DSS_SIG    3 /* RFC7296 */
480
#define IKEV2_AUTH_ECDSA_256    9 /* RFC4754 */
481
#define IKEV2_AUTH_ECDSA_384    10  /* RFC4754 */
482
#define IKEV2_AUTH_ECDSA_521    11  /* RFC4754 */
483
#define IKEV2_AUTH_GSPM     12  /* RFC6467 */
484
#define IKEV2_AUTH_NULL     13  /* RFC7619 */
485
#define IKEV2_AUTH_SIG      14  /* RFC7427 */
486
#define IKEV2_AUTH_SIG_ANY    255 /* Internal (any signature) */
487
/*
488
 * AUTH_SIG also serves as an indication that a given policy has
489
 * been configured to accept RSA or ECDSA payloads, as long as it
490
 * successfully authenticates against a configured CA.
491
 */
492
493
extern struct iked_constmap ikev2_auth_map[];
494
495
/* Notifications used together with IKEV2_AUTH_SIG */
496
497
#define IKEV2_SIGHASH_RESERVED    0 /* RFC7427 */
498
#define IKEV2_SIGHASH_SHA1    1 /* RFC7427 */
499
0
#define IKEV2_SIGHASH_SHA2_256    2  /* RFC7427 */
500
#define IKEV2_SIGHASH_SHA2_384    3 /* RFC7427 */
501
#define IKEV2_SIGHASH_SHA2_512    4 /* RFC7427 */
502
503
extern struct iked_constmap ikev2_sighash_map[];
504
505
/*
506
 * CP payload
507
 */
508
509
struct ikev2_cp {
510
  uint8_t   cp_type;
511
  uint8_t   cp_reserved[3];
512
  /* Followed by the attributes */
513
} __packed;
514
515
#define IKEV2_CP_REQUEST  1 /* CFG-Request */
516
#define IKEV2_CP_REPLY    2 /* CFG-Reply */
517
#define IKEV2_CP_SET    3 /* CFG-SET */
518
#define IKEV2_CP_ACK    4 /* CFG-ACK */
519
520
extern struct iked_constmap ikev2_cp_map[];
521
522
struct ikev2_cfg {
523
  uint16_t  cfg_type; /* first bit must be set to zero */
524
  uint16_t  cfg_length;
525
  /* Followed by variable-length data */
526
} __packed;
527
528
1.32k
#define IKEV2_CFG_INTERNAL_IP4_ADDRESS    1  /* RFC7296 */
529
#define IKEV2_CFG_INTERNAL_IP4_NETMASK    2 /* RFC7296 */
530
1.67k
#define IKEV2_CFG_INTERNAL_IP4_DNS    3  /* RFC7296 */
531
#define IKEV2_CFG_INTERNAL_IP4_NBNS   4 /* RFC7296 */
532
#define IKEV2_CFG_INTERNAL_ADDRESS_EXPIRY 5 /* RFC4306 */
533
#define IKEV2_CFG_INTERNAL_IP4_DHCP   6 /* RFC7296 */
534
#define IKEV2_CFG_APPLICATION_VERSION   7 /* RFC7296 */
535
2.41k
#define IKEV2_CFG_INTERNAL_IP6_ADDRESS    8  /* RFC7296 */
536
3.18k
#define IKEV2_CFG_INTERNAL_IP6_DNS    10  /* RFC7296 */
537
#define IKEV2_CFG_INTERNAL_IP6_NBNS   11  /* RFC4306 */
538
#define IKEV2_CFG_INTERNAL_IP6_DHCP   12  /* RFC7296 */
539
#define IKEV2_CFG_INTERNAL_IP4_SUBNET   13  /* RFC7296 */
540
#define IKEV2_CFG_SUPPORTED_ATTRIBUTES    14  /* RFC7296 */
541
#define IKEV2_CFG_INTERNAL_IP6_SUBNET   15  /* RFC7296 */
542
#define IKEV2_CFG_MIP6_HOME_PREFIX    16  /* RFC5026 */
543
#define IKEV2_CFG_INTERNAL_IP6_LINK   17  /* RFC5739 */
544
#define IKEV2_CFG_INTERNAL_IP6_PREFIX   18  /* RFC5739 */
545
#define IKEV2_CFG_HOME_AGENT_ADDRESS    19  /* http://www.3gpp.org/ftp/Specs/html-info/24302.htm */
546
#define IKEV2_CFG_INTERNAL_IP4_SERVER   23456 /* MS-IKEE */
547
#define IKEV2_CFG_INTERNAL_IP6_SERVER   23457 /* MS-IKEE */
548
549
extern struct iked_constmap ikev2_cfg_map[];
550
551
/* IKEv1 payload types */
552
#define IKEV1_PAYLOAD_NONE  0 /* No payload */
553
#define IKEV1_PAYLOAD_PROPOSAL  2 /* Proposal */
554
555
#endif /* IKED_IKEV2_H */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/ikev2.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: ikev2.h,v 1.35 2023/06/28 14:10:24 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#ifndef IKED_IKEV2_H
21
#define IKED_IKEV2_H
22
23
#include "openbsd-compat.h"
24
25
#define IKEV2_VERSION   0x20  /* IKE version 2.0 */
26
#define IKEV1_VERSION   0x10  /* IKE version 1.0 */
27
28
#define IKEV2_KEYPAD    "Key Pad for IKEv2" /* don't change! */
29
30
/*
31
 * IKEv2 pseudo states
32
 */
33
34
#define IKEV2_STATE_INIT    0 /* new IKE SA */
35
#define IKEV2_STATE_COOKIE    1 /* cookie requested */
36
#define IKEV2_STATE_SA_INIT   2 /* init IKE SA */
37
#define IKEV2_STATE_EAP     3 /* EAP requested */
38
#define IKEV2_STATE_EAP_SUCCESS   4 /* EAP succeeded */
39
#define IKEV2_STATE_AUTH_REQUEST  5 /* auth received */
40
#define IKEV2_STATE_AUTH_SUCCESS  6 /* authenticated */
41
149
#define IKEV2_STATE_VALID   7  /* authenticated AND validated certs */
42
#define IKEV2_STATE_EAP_VALID   8 /* EAP validated */
43
#define IKEV2_STATE_ESTABLISHED   9 /* active IKE SA */
44
#define IKEV2_STATE_CLOSING   10  /* expect delete for this SA */
45
#define IKEV2_STATE_CLOSED    11  /* delete this SA */
46
47
extern struct iked_constmap ikev2_state_map[];
48
49
/*
50
 * "IKEv2 Parameters" based on the official RFC-based assignments by IANA
51
 * (http://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.txt)
52
 */
53
54
/*
55
 * IKEv2 definitions of the IKE header
56
 */
57
58
/* IKEv2 exchange types */
59
#define IKEV2_EXCHANGE_IKE_SA_INIT    34  /* Initial Exchange */
60
#define IKEV2_EXCHANGE_IKE_AUTH     35  /* Authentication */
61
#define IKEV2_EXCHANGE_CREATE_CHILD_SA    36  /* Create Child SA */
62
#define IKEV2_EXCHANGE_INFORMATIONAL    37  /* Informational */
63
#define IKEV2_EXCHANGE_IKE_SESSION_RESUME 38  /* RFC5723 */
64
65
extern struct iked_constmap ikev2_exchange_map[];
66
67
/* IKEv2 message flags */
68
#define IKEV2_FLAG_INITIATOR    0x08  /* Sent by the initiator */
69
#define IKEV2_FLAG_OLDVERSION   0x10  /* Supports a higher IKE version */
70
#define IKEV2_FLAG_RESPONSE   0x20  /* Message is a response */
71
72
extern struct iked_constmap ikev2_flag_map[];
73
74
/*
75
 * IKEv2 payloads
76
 */
77
78
struct ikev2_payload {
79
  uint8_t    pld_nextpayload; /* Next payload type */
80
  uint8_t    pld_reserved;    /* Contains the critical bit */
81
  uint16_t   pld_length;    /* Payload length with header */
82
} __packed;
83
84
struct ikev2_frag_payload {
85
  uint16_t   frag_num;    /* current fragment message number */
86
  uint16_t   frag_total;    /* total number of fragment messages */
87
} __packed;
88
89
279k
#define IKEV2_CRITICAL_PAYLOAD  0x01  /* First bit in the reserved field */
90
91
/* IKEv2 payload types */
92
#define IKEV2_PAYLOAD_NONE  0 /* No payload */
93
32.7k
#define IKEV2_PAYLOAD_SA  33  /* Security Association */
94
10.9k
#define IKEV2_PAYLOAD_KE  34  /* Key Exchange */
95
14.1k
#define IKEV2_PAYLOAD_IDi 35  /* Identification - Initiator */
96
23.8k
#define IKEV2_PAYLOAD_IDr 36  /* Identification - Responder */
97
6.90k
#define IKEV2_PAYLOAD_CERT  37  /* Certificate */
98
15.4k
#define IKEV2_PAYLOAD_CERTREQ 38  /* Certificate Request */
99
10.5k
#define IKEV2_PAYLOAD_AUTH  39  /* Authentication */
100
3.51k
#define IKEV2_PAYLOAD_NONCE 40  /* Nonce */
101
39.8k
#define IKEV2_PAYLOAD_NOTIFY  41  /* Notify */
102
7.54k
#define IKEV2_PAYLOAD_DELETE  42  /* Delete */
103
#define IKEV2_PAYLOAD_VENDOR  43  /* Vendor ID */
104
5.65k
#define IKEV2_PAYLOAD_TSi 44  /* Traffic Selector - Initiator */
105
23.0k
#define IKEV2_PAYLOAD_TSr 45  /* Traffic Selector - Responder */
106
278k
#define IKEV2_PAYLOAD_SK  46  /* Encrypted */
107
11.6k
#define IKEV2_PAYLOAD_CP  47  /* Configuration Payload */
108
21.2k
#define IKEV2_PAYLOAD_EAP 48  /* Extensible Authentication */
109
#define IKEV2_PAYLOAD_GSPM  49  /* RFC6467 Generic Secure Password */
110
278k
#define IKEV2_PAYLOAD_SKF 53  /* RFC7383 Encrypted Fragment Payload */
111
112
extern struct iked_constmap ikev2_payload_map[];
113
114
/*
115
 * SA payload
116
 */
117
118
struct ikev2_sa_proposal {
119
  uint8_t    sap_more;    /* Last proposal or more */
120
  uint8_t    sap_reserved;    /* Must be set to zero */
121
  uint16_t   sap_length;    /* Proposal length */
122
  uint8_t    sap_proposalnr;  /* Proposal number */
123
  uint8_t    sap_protoid;   /* Protocol Id */
124
  uint8_t    sap_spisize;   /* SPI size */
125
  uint8_t    sap_transforms;  /* Number of transforms */
126
  /* Followed by variable-length SPI */
127
  /* Followed by variable-length transforms */
128
} __packed;
129
130
#define IKEV2_SAP_LAST  0
131
#define IKEV2_SAP_MORE  2
132
133
#define IKEV2_SAPROTO_NONE    0 /* None */
134
#define IKEV2_SAPROTO_IKE   1 /* IKEv2 */
135
#define IKEV2_SAPROTO_AH    2 /* AH */
136
#define IKEV2_SAPROTO_ESP   3 /* ESP */
137
#define IKEV2_SAPROTO_FC_ESP_HEADER 4 /* RFC4595 */
138
#define IKEV2_SAPROTO_FC_CT_AUTH  5 /* RFC4595 */
139
#define IKEV2_SAPROTO_IPCOMP    204 /* private, should be 4 */
140
141
extern struct iked_constmap ikev2_saproto_map[];
142
143
struct ikev2_transform {
144
  uint8_t   xfrm_more;    /* Last transform or more */
145
  uint8_t   xfrm_reserved;    /* Must be set to zero */
146
  uint16_t  xfrm_length;    /* Transform length */
147
  uint8_t   xfrm_type;    /* Transform type */
148
  uint8_t   xfrm_reserved1;   /* Must be set to zero */
149
  uint16_t  xfrm_id;    /* Transform Id */
150
  /* Followed by variable-length transform attributes */
151
} __packed;
152
153
#define IKEV2_XFORM_LAST    0
154
3.63k
#define IKEV2_XFORM_MORE    3
155
156
1.27k
#define IKEV2_XFORMTYPE_ENCR    1  /* Encryption */
157
789
#define IKEV2_XFORMTYPE_PRF   2  /* Pseudo-Random Function */
158
174
#define IKEV2_XFORMTYPE_INTEGR    3  /* Integrity Algorithm */
159
861
#define IKEV2_XFORMTYPE_DH    4  /* Diffie-Hellman Group */
160
1.01k
#define IKEV2_XFORMTYPE_ESN   5  /* Extended Sequence Numbers */
161
#define IKEV2_XFORMTYPE_MAX   6
162
163
extern struct iked_constmap ikev2_xformtype_map[];
164
165
#define IKEV2_XFORMENCR_NONE    0 /* None */
166
#define IKEV2_XFORMENCR_DES_IV64  1 /* RFC1827 */
167
#define IKEV2_XFORMENCR_DES   2 /* RFC2405 */
168
#define IKEV2_XFORMENCR_3DES    3 /* RFC2451 */
169
#define IKEV2_XFORMENCR_RC5   4 /* RFC2451 */
170
#define IKEV2_XFORMENCR_IDEA    5 /* RFC2451 */
171
#define IKEV2_XFORMENCR_CAST    6 /* RFC2451 */
172
#define IKEV2_XFORMENCR_BLOWFISH  7 /* RFC2451 */
173
#define IKEV2_XFORMENCR_3IDEA   8 /* RFC2451 */
174
#define IKEV2_XFORMENCR_DES_IV32  9 /* DESIV32 */
175
#define IKEV2_XFORMENCR_RC4   10  /* RFC2451 */
176
#define IKEV2_XFORMENCR_NULL    11  /* RFC2410 */
177
#define IKEV2_XFORMENCR_AES_CBC   12  /* RFC3602 */
178
#define IKEV2_XFORMENCR_AES_CTR   13  /* RFC3664 */
179
#define IKEV2_XFORMENCR_AES_CCM_8 14  /* RFC5282 */
180
#define IKEV2_XFORMENCR_AES_CCM_12  15  /* RFC5282 */
181
#define IKEV2_XFORMENCR_AES_CCM_16  16  /* RFC5282 */
182
#define IKEV2_XFORMENCR_AES_GCM_8 18  /* RFC5282 */
183
#define IKEV2_XFORMENCR_AES_GCM_12  19  /* RFC5282 */
184
#define IKEV2_XFORMENCR_AES_GCM_16  20  /* RFC5282 */
185
#define IKEV2_XFORMENCR_NULL_AES_GMAC 21  /* RFC4543 */
186
#define IKEV2_XFORMENCR_XTS_AES   22  /* IEEE P1619 */
187
#define IKEV2_XFORMENCR_CAMELLIA_CBC  23  /* RFC5529 */
188
#define IKEV2_XFORMENCR_CAMELLIA_CTR  24  /* RFC5529 */
189
#define IKEV2_XFORMENCR_CAMELLIA_CCM_8  25  /* RFC5529 */
190
#define IKEV2_XFORMENCR_CAMELLIA_CCM_12 26  /* RFC5529 */
191
#define IKEV2_XFORMENCR_CAMELLIA_CCM_16 27  /* RFC5529 */
192
#define IKEV2_XFORMENCR_CHACHA20_POLY1305 28  /* RFC7634 */
193
194
extern struct iked_constmap ikev2_xformencr_map[];
195
196
#define IKEV2_IPCOMP_OUI    1 /* UNSPECIFIED */
197
#define IKEV2_IPCOMP_DEFLATE    2 /* RFC2394 */
198
#define IKEV2_IPCOMP_LZS    3 /* RFC2395 */
199
#define IKEV2_IPCOMP_LZJH   4 /* RFC3051 */
200
201
extern struct iked_constmap ikev2_ipcomp_map[];
202
203
#define IKEV2_XFORMPRF_HMAC_MD5   1 /* RFC2104 */
204
#define IKEV2_XFORMPRF_HMAC_SHA1  2 /* RFC2104 */
205
#define IKEV2_XFORMPRF_HMAC_TIGER 3 /* RFC2104 */
206
#define IKEV2_XFORMPRF_AES128_XCBC  4 /* RFC3664 */
207
#define IKEV2_XFORMPRF_HMAC_SHA2_256  5 /* RFC4868 */
208
#define IKEV2_XFORMPRF_HMAC_SHA2_384  6 /* RFC4868 */
209
#define IKEV2_XFORMPRF_HMAC_SHA2_512  7 /* RFC4868 */
210
#define IKEV2_XFORMPRF_AES128_CMAC  8 /* RFC4615 */
211
212
extern struct iked_constmap ikev2_xformprf_map[];
213
214
#define IKEV2_XFORMAUTH_NONE    0 /* No Authentication */
215
#define IKEV2_XFORMAUTH_HMAC_MD5_96 1 /* RFC2403 */
216
#define IKEV2_XFORMAUTH_HMAC_SHA1_96  2 /* RFC2404 */
217
#define IKEV2_XFORMAUTH_DES_MAC   3 /* DES-MAC */
218
#define IKEV2_XFORMAUTH_KPDK_MD5  4 /* RFC1826 */
219
#define IKEV2_XFORMAUTH_AES_XCBC_96 5 /* RFC3566 */
220
#define IKEV2_XFORMAUTH_HMAC_MD5_128  6 /* RFC4595 */
221
#define IKEV2_XFORMAUTH_HMAC_SHA1_160 7 /* RFC4595 */
222
#define IKEV2_XFORMAUTH_AES_CMAC_96 8 /* RFC4494 */
223
#define IKEV2_XFORMAUTH_AES_128_GMAC  9 /* RFC4543 */
224
#define IKEV2_XFORMAUTH_AES_192_GMAC  10  /* RFC4543 */
225
#define IKEV2_XFORMAUTH_AES_256_GMAC  11  /* RFC4543 */
226
#define IKEV2_XFORMAUTH_HMAC_SHA2_256_128 12  /* RFC4868 */
227
#define IKEV2_XFORMAUTH_HMAC_SHA2_384_192 13  /* RFC4868 */
228
#define IKEV2_XFORMAUTH_HMAC_SHA2_512_256 14  /* RFC4868 */
229
230
/* Placeholders for AEAD ciphers (only used internally) */
231
#define IKEV2_XFORMAUTH_AES_GCM_8 2018  /* internal */
232
#define IKEV2_XFORMAUTH_AES_GCM_12  2019  /* internal */
233
#define IKEV2_XFORMAUTH_AES_GCM_16  2020  /* internal */
234
235
extern struct iked_constmap ikev2_xformauth_map[];
236
237
#define IKEV2_XFORMDH_NONE    0 /* No DH */
238
#define IKEV2_XFORMDH_MODP_768    1 /* DH Group 1 */
239
#define IKEV2_XFORMDH_MODP_1024   2 /* DH Group 2 */
240
#define IKEV2_XFORMDH_MODP_1536   5 /* DH Group 5 */
241
#define IKEV2_XFORMDH_MODP_2048   14  /* DH Group 14 */
242
#define IKEV2_XFORMDH_MODP_3072   15  /* DH Group 15 */
243
#define IKEV2_XFORMDH_MODP_4096   16  /* DH Group 16 */
244
#define IKEV2_XFORMDH_MODP_6144   17  /* DH Group 17 */
245
#define IKEV2_XFORMDH_MODP_8192   18  /* DH Group 18 */
246
#define IKEV2_XFORMDH_ECP_256   19  /* RFC5114 */
247
#define IKEV2_XFORMDH_ECP_384   20  /* RFC5114 */
248
#define IKEV2_XFORMDH_ECP_521   21  /* RFC5114 */
249
#define IKEV2_XFORMDH_ECP_192   25  /* RFC5114 */
250
#define IKEV2_XFORMDH_ECP_224   26  /* RFC5114 */
251
#define IKEV2_XFORMDH_BRAINPOOL_P224R1  27  /* RFC6954 */
252
#define IKEV2_XFORMDH_BRAINPOOL_P256R1  28  /* RFC6954 */
253
#define IKEV2_XFORMDH_BRAINPOOL_P384R1  29  /* RFC6954 */
254
#define IKEV2_XFORMDH_BRAINPOOL_P512R1  30  /* RFC6954 */
255
#define IKEV2_XFORMDH_CURVE25519  31  /* RFC8031 */
256
#define IKEV2_XFORMDH_X_SNTRUP761X25519 1035  /* private */
257
258
extern struct iked_constmap ikev2_xformdh_map[];
259
260
#define IKEV2_IPV4_OVERHEAD   (20 + 8 + 28) /* IPv4 + UDP + IKE_HDR*/
261
#define IKEV2_MAXLEN_IPV4_FRAG    (576 - IKEV2_IPV4_OVERHEAD)
262
#define IKEV2_IPV6_OVERHEAD   (40 + 8 + 28) /* IPv6 + UDP + IKE_HDR*/
263
#define IKEV2_MAXLEN_IPV6_FRAG    (1280 - IKEV2_IPV6_OVERHEAD)
264
265
#define IKEV2_MAXNUM_TSS    255 /* 8 bit Number of TSs field */
266
267
#define IKEV2_XFORMESN_NONE   0 /* No ESN */
268
#define IKEV2_XFORMESN_ESN    1 /* ESN */
269
270
extern struct iked_constmap ikev2_xformesn_map[];
271
272
struct ikev2_attribute {
273
  uint16_t  attr_type;  /* Attribute type */
274
  uint16_t  attr_length;  /* Attribute length or value */
275
  /* Followed by variable length (TLV) */
276
} __packed;
277
278
#define IKEV2_ATTRAF_TLV    0x0000  /* Type-Length-Value format */
279
105k
#define IKEV2_ATTRAF_TV     0x8000  /* Type-Value format */
280
281
41.9k
#define IKEV2_ATTRTYPE_KEY_LENGTH 14  /* Key length */
282
283
extern struct iked_constmap ikev2_attrtype_map[];
284
285
/*
286
 * KE Payload
287
 */
288
289
struct ikev2_keyexchange {
290
  uint16_t   kex_dhgroup;   /* DH Group # */
291
  uint16_t   kex_reserved;    /* Reserved */
292
} __packed;
293
294
/*
295
 * N payload
296
 */
297
298
struct ikev2_notify {
299
  uint8_t    n_protoid;   /* Protocol Id */
300
  uint8_t    n_spisize;   /* SPI size */
301
  uint16_t   n_type;    /* Notify message type */
302
  /* Followed by variable length SPI */
303
  /* Followed by variable length notification data */
304
} __packed;
305
306
#define IKEV2_N_UNSUPPORTED_CRITICAL_PAYLOAD  1 /* RFC7296 */
307
#define IKEV2_N_INVALID_IKE_SPI     4 /* RFC7296 */
308
#define IKEV2_N_INVALID_MAJOR_VERSION   5 /* RFC7296 */
309
#define IKEV2_N_INVALID_SYNTAX      7 /* RFC7296 */
310
#define IKEV2_N_INVALID_MESSAGE_ID    9 /* RFC7296 */
311
#define IKEV2_N_INVALID_SPI     11  /* RFC7296 */
312
36
#define IKEV2_N_NO_PROPOSAL_CHOSEN    14  /* RFC7296 */
313
143
#define IKEV2_N_INVALID_KE_PAYLOAD    17  /* RFC7296 */
314
6
#define IKEV2_N_AUTHENTICATION_FAILED   24  /* RFC7296 */
315
#define IKEV2_N_SINGLE_PAIR_REQUIRED    34  /* RFC7296 */
316
273
#define IKEV2_N_NO_ADDITIONAL_SAS   35  /* RFC7296 */
317
#define IKEV2_N_INTERNAL_ADDRESS_FAILURE  36  /* RFC7296 */
318
#define IKEV2_N_FAILED_CP_REQUIRED    37  /* RFC7296 */
319
#define IKEV2_N_TS_UNACCEPTABLE     38  /* RFC7296 */
320
#define IKEV2_N_INVALID_SELECTORS   39  /* RFC7296 */
321
#define IKEV2_N_UNACCEPTABLE_ADDRESSES    40  /* RFC4555 */
322
#define IKEV2_N_UNEXPECTED_NAT_DETECTED   41  /* RFC4555 */
323
#define IKEV2_N_USE_ASSIGNED_HoA    42  /* RFC5026 */
324
354
#define IKEV2_N_TEMPORARY_FAILURE   43  /* RFC7296 */
325
73
#define IKEV2_N_CHILD_SA_NOT_FOUND    44  /* RFC7296 */
326
#define IKEV2_N_INITIAL_CONTACT     16384 /* RFC7296 */
327
#define IKEV2_N_SET_WINDOW_SIZE     16385 /* RFC7296 */
328
#define IKEV2_N_ADDITIONAL_TS_POSSIBLE    16386 /* RFC7296 */
329
255
#define IKEV2_N_IPCOMP_SUPPORTED    16387  /* RFC7296 */
330
29.1k
#define IKEV2_N_NAT_DETECTION_SOURCE_IP   16388  /* RFC7296 */
331
26.0k
#define IKEV2_N_NAT_DETECTION_DESTINATION_IP  16389  /* RFC7296 */
332
2
#define IKEV2_N_COOKIE        16390  /* RFC7296 */
333
356
#define IKEV2_N_USE_TRANSPORT_MODE    16391  /* RFC7296 */
334
#define IKEV2_N_HTTP_CERT_LOOKUP_SUPPORTED  16392 /* RFC7296 */
335
82
#define IKEV2_N_REKEY_SA      16393  /* RFC7296 */
336
#define IKEV2_N_ESP_TFC_PADDING_NOT_SUPPORTED 16394 /* RFC7296 */
337
#define IKEV2_N_NON_FIRST_FRAGMENTS_ALSO  16395 /* RFC7296 */
338
1.81k
#define IKEV2_N_MOBIKE_SUPPORTED    16396  /* RFC4555 */
339
#define IKEV2_N_ADDITIONAL_IP4_ADDRESS    16397 /* RFC4555 */
340
#define IKEV2_N_ADDITIONAL_IP6_ADDRESS    16398 /* RFC4555 */
341
#define IKEV2_N_NO_ADDITIONAL_ADDRESSES   16399 /* RFC4555 */
342
388
#define IKEV2_N_UPDATE_SA_ADDRESSES   16400  /* RFC4555 */
343
242
#define IKEV2_N_COOKIE2       16401  /* RFC4555 */
344
#define IKEV2_N_NO_NATS_ALLOWED     16402 /* RFC4555 */
345
#define IKEV2_N_AUTH_LIFETIME     16403 /* RFC4478 */
346
#define IKEV2_N_MULTIPLE_AUTH_SUPPORTED   16404 /* RFC4739 */
347
#define IKEV2_N_ANOTHER_AUTH_FOLLOWS    16405 /* RFC4739 */
348
#define IKEV2_N_REDIRECT_SUPPORTED    16406 /* RFC5685 */
349
#define IKEV2_N_REDIRECT      16407 /* RFC5685 */
350
#define IKEV2_N_REDIRECTED_FROM     16408 /* RFC5685 */
351
#define IKEV2_N_TICKET_LT_OPAQUE    16409 /* RFC5723 */
352
#define IKEV2_N_TICKET_REQUEST      16410 /* RFC5723 */
353
#define IKEV2_N_TICKET_ACK      16411 /* RFC5723 */
354
#define IKEV2_N_TICKET_NACK     16412 /* RFC5723 */
355
#define IKEV2_N_TICKET_OPAQUE     16413 /* RFC5723 */
356
#define IKEV2_N_LINK_ID       16414 /* RFC5739 */
357
#define IKEV2_N_USE_WESP_MODE     16415 /* RFC5415 */
358
#define IKEV2_N_ROHC_SUPPORTED      16416 /* RFC5857 */
359
#define IKEV2_N_EAP_ONLY_AUTHENTICATION   16417 /* RFC5998 */
360
#define IKEV2_N_CHILDLESS_IKEV2_SUPPORTED 16418 /* RFC6023 */
361
#define IKEV2_N_QUICK_CRASH_DETECTION   16419 /* RFC6290 */
362
#define IKEV2_N_IKEV2_MESSAGE_ID_SYNC_SUPPORTED 16420 /* RFC6311 */
363
#define IKEV2_N_IPSEC_REPLAY_CTR_SYNC_SUPPORTED 16421 /* RFC6311 */
364
#define IKEV2_N_IKEV2_MESSAGE_ID_SYNC   16422 /* RFC6311 */
365
#define IKEV2_N_IPSEC_REPLAY_CTR_SYNC   16423 /* RFC6311 */
366
#define IKEV2_N_SECURE_PASSWORD_METHODS   16424 /* RFC6467 */
367
#define IKEV2_N_PSK_PERSIST     16425 /* RFC6631 */
368
#define IKEV2_N_PSK_CONFIRM     16426 /* RFC6631 */
369
#define IKEV2_N_ERX_SUPPORTED     16427 /* RFC6867 */
370
#define IKEV2_N_IFOM_CAPABILITY     16428 /* OA3GPP */
371
14
#define IKEV2_N_FRAGMENTATION_SUPPORTED   16430  /* RFC7383 */
372
7
#define IKEV2_N_SIGNATURE_HASH_ALGORITHMS 16431  /* RFC7427 */
373
374
extern struct iked_constmap ikev2_n_map[];
375
376
/*
377
 * DELETE payload
378
 */
379
380
struct ikev2_delete {
381
  uint8_t    del_protoid;   /* Protocol Id */
382
  uint8_t    del_spisize;   /* SPI size */
383
  uint16_t   del_nspi;    /* Number of SPIs */
384
  /* Followed by variable length SPIs */
385
} __packed;
386
387
/*
388
 * ID payload
389
 */
390
391
struct ikev2_id {
392
  uint8_t    id_type;   /* Id type */
393
  uint8_t    id_reserved[3];  /* Reserved */
394
  /* Followed by the identification data */
395
} __packed;
396
397
14.3k
#define IKEV2_ID_NONE   0  /* No ID */
398
#define IKEV2_ID_IPV4   1 /* RFC7296 (ID_IPV4_ADDR) */
399
#define IKEV2_ID_FQDN   2 /* RFC7296 */
400
#define IKEV2_ID_UFQDN    3 /* RFC7296 (ID_RFC822_ADDR) */
401
#define IKEV2_ID_IPV6   5 /* RFC7296 (ID_IPV6_ADDR) */
402
#define IKEV2_ID_ASN1_DN  9 /* RFC7296 */
403
#define IKEV2_ID_ASN1_GN  10  /* RFC7296 */
404
#define IKEV2_ID_KEY_ID   11  /* RFC7296 */
405
#define IKEV2_ID_FC_NAME  12  /* RFC4595 */
406
407
extern struct iked_constmap ikev2_id_map[];
408
409
/*
410
 * CERT/CERTREQ payloads
411
 */
412
413
struct ikev2_cert {
414
  uint8_t   cert_type;  /* Encoding */
415
  /* Followed by the certificate data */
416
} __packed;
417
418
5.37k
#define IKEV2_CERT_NONE     0  /* None */
419
#define IKEV2_CERT_X509_PKCS7   1 /* UNSPECIFIED */
420
#define IKEV2_CERT_PGP      2 /* UNSPECIFIED */
421
#define IKEV2_CERT_DNS_SIGNED_KEY 3 /* UNSPECIFIED */
422
1.34k
#define IKEV2_CERT_X509_CERT    4  /* RFC7296 */
423
#define IKEV2_CERT_KERBEROS_TOKEN 6 /* UNSPECIFIED */
424
#define IKEV2_CERT_CRL      7 /* RFC7296 */
425
#define IKEV2_CERT_ARL      8 /* UNSPECIFIED */
426
#define IKEV2_CERT_SPKI     9 /* UNSPECIFIED */
427
#define IKEV2_CERT_X509_ATTR    10  /* UNSPECIFIED */
428
#define IKEV2_CERT_RSA_KEY    11  /* RFC7296 */
429
#define IKEV2_CERT_HASHURL_X509   12  /* RFC7296 */
430
#define IKEV2_CERT_HASHURL_X509_BUNDLE  13  /* RFC7296 */
431
#define IKEV2_CERT_OCSP     14  /* RFC4806 */
432
/*
433
 * As of November 2014, work was still in progress to add a more generic
434
 * format for raw public keys (RFC7296), so we use a number in IANA's private
435
 * use range (201-255, same RFC) for ECDSA.
436
 */
437
#define IKEV2_CERT_ECDSA    201 /* Private */
438
2.78k
#define IKEV2_CERT_BUNDLE   254  /* Private */
439
440
extern struct iked_constmap ikev2_cert_map[];
441
442
/*
443
 * TSi/TSr payloads
444
 */
445
446
struct ikev2_tsp {
447
  uint8_t   tsp_count;    /* Number of TSs */
448
  uint8_t   tsp_reserved[3];  /* Reserved */
449
  /* Followed by the traffic selectors */
450
} __packed;
451
452
struct ikev2_ts {
453
  uint8_t   ts_type;    /* TS type */
454
  uint8_t   ts_protoid;   /* Protocol Id */
455
  uint16_t  ts_length;    /* Length */
456
  uint16_t  ts_startport;   /* Start port */
457
  uint16_t  ts_endport;   /* End port */
458
} __packed;
459
460
9.66k
#define IKEV2_TS_IPV4_ADDR_RANGE  7  /* RFC7296 */
461
1.54k
#define IKEV2_TS_IPV6_ADDR_RANGE  8  /* RFC7296 */
462
#define IKEV2_TS_FC_ADDR_RANGE    9 /* RFC4595 */
463
464
extern struct iked_constmap ikev2_ts_map[];
465
466
/*
467
 * AUTH payload
468
 */
469
470
struct ikev2_auth {
471
  uint8_t   auth_method;    /* Signature type */
472
  uint8_t   auth_reserved[3]; /* Reserved */
473
  /* Followed by the signature */
474
} __packed;
475
476
#define IKEV2_AUTH_NONE     0 /* None */
477
#define IKEV2_AUTH_RSA_SIG    1 /* RFC7296 */
478
#define IKEV2_AUTH_SHARED_KEY_MIC 2 /* RFC7296 */
479
#define IKEV2_AUTH_DSS_SIG    3 /* RFC7296 */
480
#define IKEV2_AUTH_ECDSA_256    9 /* RFC4754 */
481
#define IKEV2_AUTH_ECDSA_384    10  /* RFC4754 */
482
#define IKEV2_AUTH_ECDSA_521    11  /* RFC4754 */
483
#define IKEV2_AUTH_GSPM     12  /* RFC6467 */
484
#define IKEV2_AUTH_NULL     13  /* RFC7619 */
485
#define IKEV2_AUTH_SIG      14  /* RFC7427 */
486
#define IKEV2_AUTH_SIG_ANY    255 /* Internal (any signature) */
487
/*
488
 * AUTH_SIG also serves as an indication that a given policy has
489
 * been configured to accept RSA or ECDSA payloads, as long as it
490
 * successfully authenticates against a configured CA.
491
 */
492
493
extern struct iked_constmap ikev2_auth_map[];
494
495
/* Notifications used together with IKEV2_AUTH_SIG */
496
497
#define IKEV2_SIGHASH_RESERVED    0 /* RFC7427 */
498
#define IKEV2_SIGHASH_SHA1    1 /* RFC7427 */
499
0
#define IKEV2_SIGHASH_SHA2_256    2  /* RFC7427 */
500
#define IKEV2_SIGHASH_SHA2_384    3 /* RFC7427 */
501
#define IKEV2_SIGHASH_SHA2_512    4 /* RFC7427 */
502
503
extern struct iked_constmap ikev2_sighash_map[];
504
505
/*
506
 * CP payload
507
 */
508
509
struct ikev2_cp {
510
  uint8_t   cp_type;
511
  uint8_t   cp_reserved[3];
512
  /* Followed by the attributes */
513
} __packed;
514
515
#define IKEV2_CP_REQUEST  1 /* CFG-Request */
516
#define IKEV2_CP_REPLY    2 /* CFG-Reply */
517
#define IKEV2_CP_SET    3 /* CFG-SET */
518
#define IKEV2_CP_ACK    4 /* CFG-ACK */
519
520
extern struct iked_constmap ikev2_cp_map[];
521
522
struct ikev2_cfg {
523
  uint16_t  cfg_type; /* first bit must be set to zero */
524
  uint16_t  cfg_length;
525
  /* Followed by variable-length data */
526
} __packed;
527
528
1.32k
#define IKEV2_CFG_INTERNAL_IP4_ADDRESS    1  /* RFC7296 */
529
#define IKEV2_CFG_INTERNAL_IP4_NETMASK    2 /* RFC7296 */
530
1.67k
#define IKEV2_CFG_INTERNAL_IP4_DNS    3  /* RFC7296 */
531
#define IKEV2_CFG_INTERNAL_IP4_NBNS   4 /* RFC7296 */
532
#define IKEV2_CFG_INTERNAL_ADDRESS_EXPIRY 5 /* RFC4306 */
533
#define IKEV2_CFG_INTERNAL_IP4_DHCP   6 /* RFC7296 */
534
#define IKEV2_CFG_APPLICATION_VERSION   7 /* RFC7296 */
535
2.41k
#define IKEV2_CFG_INTERNAL_IP6_ADDRESS    8  /* RFC7296 */
536
3.18k
#define IKEV2_CFG_INTERNAL_IP6_DNS    10  /* RFC7296 */
537
#define IKEV2_CFG_INTERNAL_IP6_NBNS   11  /* RFC4306 */
538
#define IKEV2_CFG_INTERNAL_IP6_DHCP   12  /* RFC7296 */
539
#define IKEV2_CFG_INTERNAL_IP4_SUBNET   13  /* RFC7296 */
540
#define IKEV2_CFG_SUPPORTED_ATTRIBUTES    14  /* RFC7296 */
541
#define IKEV2_CFG_INTERNAL_IP6_SUBNET   15  /* RFC7296 */
542
#define IKEV2_CFG_MIP6_HOME_PREFIX    16  /* RFC5026 */
543
#define IKEV2_CFG_INTERNAL_IP6_LINK   17  /* RFC5739 */
544
#define IKEV2_CFG_INTERNAL_IP6_PREFIX   18  /* RFC5739 */
545
#define IKEV2_CFG_HOME_AGENT_ADDRESS    19  /* http://www.3gpp.org/ftp/Specs/html-info/24302.htm */
546
#define IKEV2_CFG_INTERNAL_IP4_SERVER   23456 /* MS-IKEE */
547
#define IKEV2_CFG_INTERNAL_IP6_SERVER   23457 /* MS-IKEE */
548
549
extern struct iked_constmap ikev2_cfg_map[];
550
551
/* IKEv1 payload types */
552
#define IKEV1_PAYLOAD_NONE  0 /* No payload */
553
#define IKEV1_PAYLOAD_PROPOSAL  2 /* Proposal */
554
555
#endif /* IKED_IKEV2_H */
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/iked/ikev2_pld.c.html b/coverage/latest/report/linux/src/openiked-portable/iked/ikev2_pld.c.html index ba36ae8e0..9562d48ea 100644 --- a/coverage/latest/report/linux/src/openiked-portable/iked/ikev2_pld.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/iked/ikev2_pld.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/ikev2_pld.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: ikev2_pld.c,v 1.133 2023/09/02 18:36:30 tobhe Exp $ */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 * Copyright (c) 2014 Hans-Joerg Hoexer
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#include <sys/queue.h>
22
#include <sys/socket.h>
23
#include <sys/uio.h>
24
25
#include <netinet/in.h>
26
#include <arpa/inet.h>
27
28
#include <stdlib.h>
29
#include <stdio.h>
30
#include <unistd.h>
31
#include <string.h>
32
#include <signal.h>
33
#include <endian.h>
34
#include <errno.h>
35
#include <err.h>
36
#include <event.h>
37
38
#include <openssl/sha.h>
39
#include <openssl/evp.h>
40
41
#include "iked.h"
42
#include "ikev2.h"
43
#include "eap.h"
44
#include "dh.h"
45
46
int  ikev2_validate_pld(struct iked_message *, size_t, size_t,
47
      struct ikev2_payload *);
48
int  ikev2_pld_payloads(struct iked *, struct iked_message *,
49
      size_t, size_t, unsigned int);
50
int  ikev2_validate_sa(struct iked_message *, size_t, size_t,
51
      struct ikev2_sa_proposal *);
52
int  ikev2_pld_sa(struct iked *, struct ikev2_payload *,
53
      struct iked_message *, size_t, size_t);
54
int  ikev2_validate_xform(struct iked_message *, size_t, size_t,
55
      struct ikev2_transform *);
56
int  ikev2_pld_xform(struct iked *, struct iked_message *,
57
      size_t, size_t);
58
int  ikev2_validate_attr(struct iked_message *, size_t, size_t,
59
      struct ikev2_attribute *);
60
int  ikev2_pld_attr(struct iked *, struct ikev2_transform *,
61
      struct iked_message *, size_t, size_t);
62
int  ikev2_validate_ke(struct iked_message *, size_t, size_t,
63
      struct ikev2_keyexchange *);
64
int  ikev2_pld_ke(struct iked *, struct ikev2_payload *,
65
      struct iked_message *, size_t, size_t);
66
int  ikev2_validate_id(struct iked_message *, size_t, size_t,
67
      struct ikev2_id *);
68
int  ikev2_pld_id(struct iked *, struct ikev2_payload *,
69
      struct iked_message *, size_t, size_t, unsigned int);
70
int  ikev2_validate_cert(struct iked_message *, size_t, size_t,
71
      struct ikev2_cert *);
72
int  ikev2_pld_cert(struct iked *, struct ikev2_payload *,
73
      struct iked_message *, size_t, size_t);
74
int  ikev2_validate_certreq(struct iked_message *, size_t, size_t,
75
      struct ikev2_cert *);
76
int  ikev2_pld_certreq(struct iked *, struct ikev2_payload *,
77
      struct iked_message *, size_t, size_t);
78
int  ikev2_pld_nonce(struct iked *, struct ikev2_payload *,
79
      struct iked_message *, size_t, size_t);
80
int  ikev2_validate_notify(struct iked_message *, size_t, size_t,
81
      struct ikev2_notify *);
82
int  ikev2_pld_notify(struct iked *, struct ikev2_payload *,
83
      struct iked_message *, size_t, size_t);
84
int  ikev2_validate_delete(struct iked_message *, size_t, size_t,
85
      struct ikev2_delete *);
86
int  ikev2_pld_delete(struct iked *, struct ikev2_payload *,
87
      struct iked_message *, size_t, size_t);
88
int  ikev2_validate_tss(struct iked_message *, size_t, size_t,
89
      struct ikev2_tsp *);
90
int  ikev2_pld_tss(struct iked *, struct ikev2_payload *,
91
      struct iked_message *, size_t, size_t);
92
int  ikev2_validate_ts(struct iked_message *, size_t, size_t,
93
      struct ikev2_ts *);
94
int  ikev2_pld_ts(struct iked *, struct ikev2_payload *,
95
      struct iked_message *, size_t, size_t, unsigned int);
96
int  ikev2_validate_auth(struct iked_message *, size_t, size_t,
97
      struct ikev2_auth *);
98
int  ikev2_pld_auth(struct iked *, struct ikev2_payload *,
99
      struct iked_message *, size_t, size_t);
100
int  ikev2_pld_e(struct iked *, struct ikev2_payload *,
101
      struct iked_message *, size_t, size_t);
102
int  ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
103
      struct iked_message *msg, size_t offset, size_t left);
104
int  ikev2_frags_reassemble(struct iked *env,
105
      struct ikev2_payload *pld, struct iked_message *msg);
106
int  ikev2_validate_cp(struct iked_message *, size_t, size_t,
107
      struct ikev2_cp *);
108
int  ikev2_pld_cp(struct iked *, struct ikev2_payload *,
109
      struct iked_message *, size_t, size_t);
110
int  ikev2_validate_eap(struct iked_message *, size_t, size_t,
111
      struct eap_header *);
112
int  ikev2_pld_eap(struct iked *, struct ikev2_payload *,
113
      struct iked_message *, size_t, size_t);
114
115
int
116
ikev2_pld_parse(struct iked *env, struct ike_header *hdr,
117
    struct iked_message *msg, size_t offset)
118
15.4k
{
119
15.4k
  log_debug("%s: header ispi %s rspi %s"
120
15.4k
      " nextpayload %s version 0x%02x exchange %s flags 0x%02x"
121
15.4k
      " msgid %d length %u response %d", __func__,
122
15.4k
      print_spi(betoh64(hdr->ike_ispi), 8),
123
15.4k
      print_spi(betoh64(hdr->ike_rspi), 8),
124
15.4k
      print_map(hdr->ike_nextpayload, ikev2_payload_map),
125
15.4k
      hdr->ike_version,
126
15.4k
      print_map(hdr->ike_exchange, ikev2_exchange_map),
127
15.4k
      hdr->ike_flags,
128
15.4k
      betoh32(hdr->ike_msgid),
129
15.4k
      betoh32(hdr->ike_length),
130
15.4k
      msg->msg_response);
131
132
15.4k
  if (ibuf_size(msg->msg_data) < betoh32(hdr->ike_length)) {
133
6
    log_debug("%s: short message", __func__);
134
6
    return (-1);
135
6
  }
136
137
15.4k
  offset += sizeof(*hdr);
138
139
15.4k
  return (ikev2_pld_payloads(env, msg, offset,
140
15.4k
      betoh32(hdr->ike_length), hdr->ike_nextpayload));
141
15.4k
}
142
143
int
144
ikev2_validate_pld(struct iked_message *msg, size_t offset, size_t left,
145
    struct ikev2_payload *pld)
146
291k
{
147
291k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
148
291k
  size_t     pld_length;
149
150
  /* We need at least the generic header. */
151
291k
  if (left < sizeof(*pld)) {
152
2.01k
    log_debug("%s: malformed payload: too short for generic "
153
2.01k
        "header (%zu < %zu)", __func__, left, sizeof(*pld));
154
2.01k
    return (-1);
155
2.01k
  }
156
289k
  memcpy(pld, msgbuf + offset, sizeof(*pld));
157
158
  /*
159
   * We need at least the specified number of bytes.
160
   * pld_length is the full size of the payload including
161
   * the generic payload header.
162
   */
163
289k
  pld_length = betoh16(pld->pld_length);
164
289k
  if (left < pld_length) {
165
6.81k
    log_debug("%s: malformed payload: shorter than specified "
166
6.81k
        "(%zu < %zu)", __func__, left, pld_length);
167
6.81k
    return (-1);
168
6.81k
  }
169
  /*
170
   * Sanity check the specified payload size, it must
171
   * be at least the size of the generic payload header.
172
   */
173
282k
  if (pld_length < sizeof(*pld)) {
174
2.83k
    log_debug("%s: malformed payload: shorter than minimum "
175
2.83k
        "header size (%zu < %zu)", __func__, pld_length,
176
2.83k
        sizeof(*pld));
177
2.83k
    return (-1);
178
2.83k
  }
179
180
279k
  return (0);
181
282k
}
182
183
int
184
ikev2_pld_payloads(struct iked *env, struct iked_message *msg,
185
    size_t offset, size_t length, unsigned int payload)
186
15.4k
{
187
15.4k
  struct ikev2_payload   pld;
188
15.4k
  unsigned int     e;
189
15.4k
  int      ret;
190
15.4k
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
191
15.4k
  size_t       total, left;
192
193
  /* Check if message was decrypted in an E payload */
194
15.4k
  e = msg->msg_e ? IKED_E : 0;
195
196
  /* Bytes left in datagram. */
197
15.4k
  total = length - offset;
198
199
294k
  while (payload != 0 && offset < length) {
200
291k
    if (ikev2_validate_pld(msg, offset, total, &pld))
201
11.6k
      return (-1);
202
203
279k
    log_debug("%s: %spayload %s"
204
279k
        " nextpayload %s critical 0x%02x length %d",
205
279k
        __func__, e ? "decrypted " : "",
206
279k
        print_map(payload, ikev2_payload_map),
207
279k
        print_map(pld.pld_nextpayload, ikev2_payload_map),
208
279k
        pld.pld_reserved & IKEV2_CRITICAL_PAYLOAD,
209
279k
        betoh16(pld.pld_length));
210
211
    /* Skip over generic payload header. */
212
279k
    offset += sizeof(pld);
213
279k
    total -= sizeof(pld);
214
279k
    left = betoh16(pld.pld_length) - sizeof(pld);
215
279k
    ret = 0;
216
217
279k
    switch (payload | e) {
218
0
    case IKEV2_PAYLOAD_SA:
219
32.7k
    case IKEV2_PAYLOAD_SA | IKED_E:
220
32.7k
      ret = ikev2_pld_sa(env, &pld, msg, offset, left);
221
32.7k
      break;
222
0
    case IKEV2_PAYLOAD_KE:
223
10.9k
    case IKEV2_PAYLOAD_KE | IKED_E:
224
10.9k
      ret = ikev2_pld_ke(env, &pld, msg, offset, left);
225
10.9k
      break;
226
13.9k
    case IKEV2_PAYLOAD_IDi | IKED_E:
227
23.7k
    case IKEV2_PAYLOAD_IDr | IKED_E:
228
23.7k
      ret = ikev2_pld_id(env, &pld, msg, offset, left,
229
23.7k
          payload);
230
23.7k
      break;
231
6.90k
    case IKEV2_PAYLOAD_CERT | IKED_E:
232
6.90k
      ret = ikev2_pld_cert(env, &pld, msg, offset, left);
233
6.90k
      break;
234
0
    case IKEV2_PAYLOAD_CERTREQ:
235
15.4k
    case IKEV2_PAYLOAD_CERTREQ | IKED_E:
236
15.4k
      ret = ikev2_pld_certreq(env, &pld, msg, offset, left);
237
15.4k
      break;
238
10.5k
    case IKEV2_PAYLOAD_AUTH | IKED_E:
239
10.5k
      ret = ikev2_pld_auth(env, &pld, msg, offset, left);
240
10.5k
      break;
241
0
    case IKEV2_PAYLOAD_NONCE:
242
3.51k
    case IKEV2_PAYLOAD_NONCE | IKED_E:
243
3.51k
      ret = ikev2_pld_nonce(env, &pld, msg, offset, left);
244
3.51k
      break;
245
0
    case IKEV2_PAYLOAD_NOTIFY:
246
39.8k
    case IKEV2_PAYLOAD_NOTIFY | IKED_E:
247
39.8k
      ret = ikev2_pld_notify(env, &pld, msg, offset, left);
248
39.8k
      break;
249
7.54k
    case IKEV2_PAYLOAD_DELETE | IKED_E:
250
7.54k
      ret = ikev2_pld_delete(env, &pld, msg, offset, left);
251
7.54k
      break;
252
5.65k
    case IKEV2_PAYLOAD_TSi | IKED_E:
253
23.0k
    case IKEV2_PAYLOAD_TSr | IKED_E:
254
23.0k
      ret = ikev2_pld_tss(env, &pld, msg, offset, left);
255
23.0k
      break;
256
0
    case IKEV2_PAYLOAD_SK:
257
0
      ret = ikev2_pld_e(env, &pld, msg, offset, left);
258
0
      break;
259
0
    case IKEV2_PAYLOAD_SKF:
260
0
      ret = ikev2_pld_ef(env, &pld, msg, offset, left);
261
0
      break;
262
11.6k
    case IKEV2_PAYLOAD_CP | IKED_E:
263
11.6k
      ret = ikev2_pld_cp(env, &pld, msg, offset, left);
264
11.6k
      break;
265
21.2k
    case IKEV2_PAYLOAD_EAP | IKED_E:
266
21.2k
      ret = ikev2_pld_eap(env, &pld, msg, offset, left);
267
21.2k
      break;
268
72.4k
    default:
269
72.4k
      print_hex(msgbuf, offset,
270
72.4k
          betoh16(pld.pld_length) - sizeof(pld));
271
72.4k
      break;
272
279k
    }
273
274
279k
    if (ret != 0 && ikev2_msg_frompeer(msg)) {
275
748
      (void)ikev2_send_informational(env, msg);
276
748
      return (-1);
277
748
    }
278
279
    /* Encrypted payloads must appear last */
280
278k
    if ((payload == IKEV2_PAYLOAD_SK) ||
281
278k
        (payload == IKEV2_PAYLOAD_SKF))
282
4
      return (0);
283
284
278k
    payload = pld.pld_nextpayload;
285
278k
    offset += left;
286
278k
    total -= left;
287
278k
  }
288
289
3.06k
  return (0);
290
15.4k
}
291
292
int
293
ikev2_validate_sa(struct iked_message *msg, size_t offset, size_t left,
294
    struct ikev2_sa_proposal *sap)
295
37.6k
{
296
37.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
297
37.6k
  size_t     sap_length;
298
299
37.6k
  if (left < sizeof(*sap)) {
300
15.9k
    log_debug("%s: malformed payload: too short for header "
301
15.9k
        "(%zu < %zu)", __func__, left, sizeof(*sap));
302
15.9k
    return (-1);
303
15.9k
  }
304
21.6k
  memcpy(sap, msgbuf + offset, sizeof(*sap));
305
306
21.6k
  sap_length = betoh16(sap->sap_length);
307
21.6k
  if (sap_length < sizeof(*sap)) {
308
5.62k
    log_debug("%s: malformed payload: shorter than minimum header "
309
5.62k
        "size (%zu < %zu)", __func__, sap_length, sizeof(*sap));
310
5.62k
    return (-1);
311
5.62k
  }
312
16.0k
  if (left < sap_length) {
313
3.10k
    log_debug("%s: malformed payload: too long for actual payload "
314
3.10k
        "size (%zu < %zu)", __func__, left, sap_length);
315
3.10k
    return (-1);
316
3.10k
  }
317
  /*
318
   * If there is only one proposal, sap_length must be the
319
   * total payload size.
320
   */
321
12.9k
  if (!sap->sap_more && left != sap_length) {
322
30
    log_debug("%s: malformed payload: SA payload length mismatches "
323
30
        "single proposal substructure length (%zu != %zu)",
324
30
        __func__, left, sap_length);
325
30
    return (-1);
326
30
  }
327
  /*
328
   * If there are more than one proposal, there must be bytes
329
   * left in the payload.
330
   */
331
12.9k
  if (sap->sap_more && left <= sap_length) {
332
1.00k
    log_debug("%s: malformed payload: SA payload too small for "
333
1.00k
        "further proposals (%zu <= %zu)", __func__,
334
1.00k
        left, sap_length);
335
1.00k
    return (-1);
336
1.00k
  }
337
11.9k
  return (0);
338
12.9k
}
339
340
int
341
ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld,
342
    struct iked_message *msg, size_t offset, size_t left)
343
32.7k
{
344
32.7k
  struct ikev2_sa_proposal   sap;
345
32.7k
  struct iked_proposal    *prop = NULL;
346
32.7k
  uint32_t       spi32;
347
32.7k
  uint64_t       spi = 0, spi64;
348
32.7k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
349
32.7k
  int        r;
350
32.7k
  struct iked_proposals   *props;
351
32.7k
  size_t         total;
352
353
37.6k
  do {
354
37.6k
    if (ikev2_validate_sa(msg, offset, left, &sap))
355
25.6k
      return (-1);
356
357
    /* Assumed size of the first proposals, including SPI if present. */
358
11.9k
    total = (betoh16(sap.sap_length) - sizeof(sap));
359
360
11.9k
    props = &msg->msg_parent->msg_proposals;
361
362
11.9k
    offset += sizeof(sap);
363
11.9k
    left -= sizeof(sap);
364
365
11.9k
    if (sap.sap_spisize) {
366
1.66k
      if (left < sap.sap_spisize) {
367
758
        log_debug("%s: malformed payload: SPI larger than "
368
758
            "actual payload (%zu < %d)", __func__, left,
369
758
            sap.sap_spisize);
370
758
        return (-1);
371
758
      }
372
905
      if (total < sap.sap_spisize) {
373
183
        log_debug("%s: malformed payload: SPI larger than "
374
183
            "proposal (%zu < %d)", __func__, total,
375
183
            sap.sap_spisize);
376
183
        return (-1);
377
183
      }
378
722
      switch (sap.sap_spisize) {
379
356
      case 4:
380
356
        memcpy(&spi32, msgbuf + offset, 4);
381
356
        spi = betoh32(spi32);
382
356
        break;
383
236
      case 8:
384
236
        memcpy(&spi64, msgbuf + offset, 8);
385
236
        spi = betoh64(spi64);
386
236
        break;
387
130
      default:
388
130
        log_debug("%s: unsupported SPI size %d",
389
130
            __func__, sap.sap_spisize);
390
130
        return (-1);
391
722
      }
392
393
592
      offset += sap.sap_spisize;
394
592
      left -= sap.sap_spisize;
395
396
      /* Assumed size of the proposal, now without SPI. */
397
592
      total -= sap.sap_spisize;
398
592
    }
399
400
    /*
401
     * As we verified sanity of packet headers, this check will
402
     * be always false, but just to be sure we keep it.
403
     */
404
10.8k
    if (left < total) {
405
0
      log_debug("%s: malformed payload: too long for payload "
406
0
          "(%zu < %zu)", __func__, left, total);
407
0
      return (-1);
408
0
    }
409
410
10.8k
    log_debug("%s: more %d reserved %d length %d"
411
10.8k
        " proposal #%d protoid %s spisize %d xforms %d spi %s",
412
10.8k
        __func__, sap.sap_more, sap.sap_reserved,
413
10.8k
        betoh16(sap.sap_length), sap.sap_proposalnr,
414
10.8k
        print_map(sap.sap_protoid, ikev2_saproto_map), sap.sap_spisize,
415
10.8k
        sap.sap_transforms, print_spi(spi, sap.sap_spisize));
416
417
10.8k
    if (ikev2_msg_frompeer(msg)) {
418
69
      if ((msg->msg_parent->msg_prop = config_add_proposal(props,
419
69
          sap.sap_proposalnr, sap.sap_protoid)) == NULL) {
420
69
        log_debug("%s: invalid proposal", __func__);
421
69
        return (-1);
422
69
      }
423
0
      prop = msg->msg_parent->msg_prop;
424
0
      prop->prop_peerspi.spi = spi;
425
0
      prop->prop_peerspi.spi_protoid = sap.sap_protoid;
426
0
      prop->prop_peerspi.spi_size = sap.sap_spisize;
427
428
0
      prop->prop_localspi.spi_protoid = sap.sap_protoid;
429
0
      prop->prop_localspi.spi_size = sap.sap_spisize;
430
0
    }
431
432
    /*
433
     * Parse the attached transforms
434
     */
435
10.7k
    if (sap.sap_transforms) {
436
6.27k
      r = ikev2_pld_xform(env, msg, offset, total);
437
6.27k
      if ((r == -2) && ikev2_msg_frompeer(msg)) {
438
0
        log_debug("%s: invalid proposal transform",
439
0
            __func__);
440
441
        /* cleanup and ignore proposal */
442
0
        config_free_proposal(props, prop);
443
0
        prop = msg->msg_parent->msg_prop = NULL;
444
6.27k
      } else if (r != 0) {
445
5.04k
        log_debug("%s: invalid proposal transforms",
446
5.04k
            __func__);
447
5.04k
        return (-1);
448
5.04k
      }
449
6.27k
    }
450
451
5.74k
    offset += total;
452
5.74k
    left -= total;
453
5.74k
  } while (sap.sap_more);
454
455
846
  return (0);
456
32.7k
}
457
458
int
459
ikev2_validate_xform(struct iked_message *msg, size_t offset, size_t total,
460
    struct ikev2_transform *xfrm)
461
8.43k
{
462
8.43k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
463
8.43k
  size_t     xfrm_length;
464
465
8.43k
  if (total < sizeof(*xfrm)) {
466
772
    log_debug("%s: malformed payload: too short for header "
467
772
        "(%zu < %zu)", __func__, total, sizeof(*xfrm));
468
772
    return (-1);
469
772
  }
470
7.66k
  memcpy(xfrm, msgbuf + offset, sizeof(*xfrm));
471
472
7.66k
  xfrm_length = betoh16(xfrm->xfrm_length);
473
7.66k
  if (xfrm_length < sizeof(*xfrm)) {
474
1.14k
    log_debug("%s: malformed payload: shorter than minimum header "
475
1.14k
        "size (%zu < %zu)", __func__, xfrm_length, sizeof(*xfrm));
476
1.14k
    return (-1);
477
1.14k
  }
478
6.51k
  if (total < xfrm_length) {
479
706
    log_debug("%s: malformed payload: too long for payload size "
480
706
        "(%zu < %zu)", __func__, total, xfrm_length);
481
706
    return (-1);
482
706
  }
483
484
5.81k
  return (0);
485
6.51k
}
486
487
int
488
ikev2_pld_xform(struct iked *env, struct iked_message *msg,
489
    size_t offset, size_t total)
490
8.43k
{
491
8.43k
  struct ikev2_transform     xfrm;
492
8.43k
  char         id[BUFSIZ];
493
8.43k
  int        ret = 0;
494
8.43k
  int        r;
495
8.43k
  size_t         xfrm_length;
496
497
8.43k
  if (ikev2_validate_xform(msg, offset, total, &xfrm))
498
2.62k
    return (-1);
499
500
5.81k
  xfrm_length = betoh16(xfrm.xfrm_length);
501
502
5.81k
  switch (xfrm.xfrm_type) {
503
1.27k
  case IKEV2_XFORMTYPE_ENCR:
504
1.27k
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
505
1.27k
        ikev2_xformencr_map), sizeof(id));
506
1.27k
    break;
507
789
  case IKEV2_XFORMTYPE_PRF:
508
789
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
509
789
        ikev2_xformprf_map), sizeof(id));
510
789
    break;
511
174
  case IKEV2_XFORMTYPE_INTEGR:
512
174
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
513
174
        ikev2_xformauth_map), sizeof(id));
514
174
    break;
515
861
  case IKEV2_XFORMTYPE_DH:
516
861
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
517
861
        ikev2_xformdh_map), sizeof(id));
518
861
    break;
519
1.01k
  case IKEV2_XFORMTYPE_ESN:
520
1.01k
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
521
1.01k
        ikev2_xformesn_map), sizeof(id));
522
1.01k
    break;
523
1.69k
  default:
524
1.69k
    snprintf(id, sizeof(id), "<%d>", betoh16(xfrm.xfrm_id));
525
1.69k
    break;
526
5.81k
  }
527
528
5.81k
  log_debug("%s: more %d reserved %d length %zu"
529
5.81k
      " type %s id %s",
530
5.81k
      __func__, xfrm.xfrm_more, xfrm.xfrm_reserved, xfrm_length,
531
5.81k
      print_map(xfrm.xfrm_type, ikev2_xformtype_map), id);
532
533
  /*
534
   * Parse transform attributes, if available
535
   */
536
5.81k
  msg->msg_attrlength = 0;
537
5.81k
  if (xfrm_length > sizeof(xfrm)) {
538
2.77k
    if (ikev2_pld_attr(env, &xfrm, msg, offset + sizeof(xfrm),
539
2.77k
        xfrm_length - sizeof(xfrm)) != 0) {
540
2.17k
      return (-1);
541
2.17k
    }
542
2.77k
  }
543
544
3.63k
  if (ikev2_msg_frompeer(msg)) {
545
0
    r = config_add_transform(msg->msg_parent->msg_prop,
546
0
        xfrm.xfrm_type, betoh16(xfrm.xfrm_id),
547
0
        msg->msg_attrlength, msg->msg_attrlength);
548
0
    if (r == -1) {
549
0
      log_debug("%s: failed to add transform: alloc error",
550
0
          __func__);
551
0
      return (r);
552
0
    } else if (r == -2) {
553
0
      log_debug("%s: failed to add transform: unknown type",
554
0
          __func__);
555
0
      return (r);
556
0
    }
557
0
  }
558
559
  /* Next transform */
560
3.63k
  offset += xfrm_length;
561
3.63k
  total -= xfrm_length;
562
3.63k
  if (xfrm.xfrm_more == IKEV2_XFORM_MORE)
563
2.16k
    ret = ikev2_pld_xform(env, msg, offset, total);
564
1.46k
  else if (total != 0) {
565
    /* No more transforms but still some data left. */
566
245
    log_debug("%s: less data than specified, %zu bytes left",
567
245
        __func__, total);
568
245
    ret = -1;
569
245
  }
570
571
3.63k
  return (ret);
572
3.63k
}
573
574
int
575
ikev2_validate_attr(struct iked_message *msg, size_t offset, size_t total,
576
    struct ikev2_attribute *attr)
577
53.6k
{
578
53.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
579
580
53.6k
  if (total < sizeof(*attr)) {
581
1.04k
    log_debug("%s: malformed payload: too short for header "
582
1.04k
        "(%zu < %zu)", __func__, total, sizeof(*attr));
583
1.04k
    return (-1);
584
1.04k
  }
585
52.6k
  memcpy(attr, msgbuf + offset, sizeof(*attr));
586
587
52.6k
  return (0);
588
53.6k
}
589
590
int
591
ikev2_pld_attr(struct iked *env, struct ikev2_transform *xfrm,
592
    struct iked_message *msg, size_t offset, size_t total)
593
53.6k
{
594
53.6k
  struct ikev2_attribute     attr;
595
53.6k
  unsigned int       type;
596
53.6k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
597
53.6k
  int        ret = 0;
598
53.6k
  size_t         attr_length;
599
600
53.6k
  if (ikev2_validate_attr(msg, offset, total, &attr))
601
1.04k
    return (-1);
602
603
52.6k
  type = betoh16(attr.attr_type) & ~IKEV2_ATTRAF_TV;
604
605
52.6k
  log_debug("%s: attribute type %s length %d total %zu",
606
52.6k
      __func__, print_map(type, ikev2_attrtype_map),
607
52.6k
      betoh16(attr.attr_length), total);
608
609
52.6k
  if (betoh16(attr.attr_type) & IKEV2_ATTRAF_TV) {
610
    /* Type-Value attribute */
611
41.9k
    offset += sizeof(attr);
612
41.9k
    total -= sizeof(attr);
613
614
41.9k
    if (type == IKEV2_ATTRTYPE_KEY_LENGTH)
615
48
      msg->msg_attrlength = betoh16(attr.attr_length);
616
41.9k
  } else {
617
    /* Type-Length-Value attribute */
618
10.7k
    attr_length = betoh16(attr.attr_length);
619
10.7k
    if (attr_length < sizeof(attr)) {
620
605
      log_debug("%s: malformed payload: shorter than "
621
605
          "minimum header size (%zu < %zu)", __func__,
622
605
          attr_length, sizeof(attr));
623
605
      return (-1);
624
605
    }
625
10.1k
    if (total < attr_length) {
626
529
      log_debug("%s: malformed payload: attribute larger "
627
529
          "than actual payload (%zu < %zu)", __func__,
628
529
          total, attr_length);
629
529
      return (-1);
630
529
    }
631
9.57k
    print_hex(msgbuf, offset + sizeof(attr),
632
9.57k
        attr_length - sizeof(attr));
633
9.57k
    offset += attr_length;
634
9.57k
    total -= attr_length;
635
9.57k
  }
636
637
51.4k
  if (total > 0) {
638
    /* Next attribute */
639
50.9k
    ret = ikev2_pld_attr(env, xfrm, msg, offset, total);
640
50.9k
  }
641
642
51.4k
  return (ret);
643
52.6k
}
644
645
int
646
ikev2_validate_ke(struct iked_message *msg, size_t offset, size_t left,
647
    struct ikev2_keyexchange *kex)
648
10.9k
{
649
10.9k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
650
651
10.9k
  if (left < sizeof(*kex)) {
652
6.72k
    log_debug("%s: malformed payload: too short for header "
653
6.72k
        "(%zu < %zu)", __func__, left, sizeof(*kex));
654
6.72k
    return (-1);
655
6.72k
  }
656
4.22k
  memcpy(kex, msgbuf + offset, sizeof(*kex));
657
658
4.22k
  return (0);
659
10.9k
}
660
661
int
662
ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld,
663
    struct iked_message *msg, size_t offset, size_t left)
664
10.9k
{
665
10.9k
  struct ikev2_keyexchange   kex;
666
10.9k
  uint8_t       *buf;
667
10.9k
  size_t         len;
668
10.9k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
669
670
10.9k
  if (ikev2_validate_ke(msg, offset, left, &kex))
671
6.72k
    return (-1);
672
673
4.22k
  log_debug("%s: dh group %s reserved %d", __func__,
674
4.22k
      print_map(betoh16(kex.kex_dhgroup), ikev2_xformdh_map),
675
4.22k
      betoh16(kex.kex_reserved));
676
677
4.22k
  buf = msgbuf + offset + sizeof(kex);
678
4.22k
  len = left - sizeof(kex);
679
680
4.22k
  if (len == 0) {
681
2.08k
    log_debug("%s: malformed payload: no KE data given", __func__);
682
2.08k
    return (-1);
683
2.08k
  }
684
685
2.14k
  print_hex(buf, 0, len);
686
687
2.14k
  if (ikev2_msg_frompeer(msg)) {
688
27
    if (msg->msg_parent->msg_ke != NULL) {
689
4
      log_info("%s: duplicate KE payload", __func__);
690
4
      return (-1);
691
4
    }
692
23
    if ((msg->msg_parent->msg_ke = ibuf_new(buf, len)) == NULL) {
693
0
      log_debug("%s: failed to get exchange", __func__);
694
0
      return (-1);
695
0
    }
696
23
    msg->msg_parent->msg_dhgroup = betoh16(kex.kex_dhgroup);
697
23
  }
698
699
2.13k
  return (0);
700
2.14k
}
701
702
int
703
ikev2_validate_id(struct iked_message *msg, size_t offset, size_t left,
704
    struct ikev2_id *id)
705
23.7k
{
706
23.7k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
707
708
23.7k
  if (left < sizeof(*id)) {
709
9.33k
    log_debug("%s: malformed payload: too short for header "
710
9.33k
        "(%zu < %zu)", __func__, left, sizeof(*id));
711
9.33k
    return (-1);
712
9.33k
  }
713
14.3k
  memcpy(id, msgbuf + offset, sizeof(*id));
714
715
14.3k
  if (id->id_type == IKEV2_ID_NONE) {
716
6.62k
    log_debug("%s: malformed payload: invalid ID type.",
717
6.62k
        __func__);
718
6.62k
    return (-1);
719
6.62k
  }
720
721
7.77k
  return (0);
722
14.3k
}
723
724
int
725
ikev2_pld_id(struct iked *env, struct ikev2_payload *pld,
726
    struct iked_message *msg, size_t offset, size_t left, unsigned int payload)
727
23.7k
{
728
23.7k
  uint8_t       *ptr;
729
23.7k
  struct ikev2_id      id;
730
23.7k
  size_t         len;
731
23.7k
  struct iked_id      *idp, idb;
732
23.7k
  const struct iked_sa    *sa = msg->msg_sa;
733
23.7k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
734
23.7k
  char         idstr[IKED_ID_SIZE];
735
736
23.7k
  if (ikev2_validate_id(msg, offset, left, &id))
737
15.9k
    return (-1);
738
739
7.77k
  bzero(&idb, sizeof(idb));
740
741
  /* Don't strip the Id payload header */
742
7.77k
  ptr = msgbuf + offset;
743
7.77k
  len = left;
744
745
7.77k
  idb.id_type = id.id_type;
746
7.77k
  idb.id_offset = sizeof(id);
747
7.77k
  if ((idb.id_buf = ibuf_new(ptr, len)) == NULL)
748
0
    return (-1);
749
750
7.77k
  if (ikev2_print_id(&idb, idstr, sizeof(idstr)) == -1) {
751
0
    ibuf_free(idb.id_buf);
752
0
    log_debug("%s: malformed id", __func__);
753
0
    return (-1);
754
0
  }
755
756
7.77k
  log_debug("%s: id %s length %zu", __func__, idstr, len);
757
758
7.77k
  if (!ikev2_msg_frompeer(msg)) {
759
7.61k
    ibuf_free(idb.id_buf);
760
7.61k
    return (0);
761
7.61k
  }
762
763
157
  if (((sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr) ||
764
157
      (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDi)))
765
77
    idp = &msg->msg_parent->msg_peerid;
766
80
  else if (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr)
767
80
    idp = &msg->msg_parent->msg_localid;
768
0
  else {
769
0
    ibuf_free(idb.id_buf);
770
0
    log_debug("%s: unexpected id payload", __func__);
771
0
    return (0);
772
0
  }
773
774
157
  if (idp->id_type) {
775
33
    ibuf_free(idb.id_buf);
776
33
    log_debug("%s: duplicate id payload", __func__);
777
33
    return (-1);
778
33
  }
779
780
124
  idp->id_buf = idb.id_buf;
781
124
  idp->id_offset = idb.id_offset;
782
124
  idp->id_type = idb.id_type;
783
784
124
  return (0);
785
157
}
786
787
int
788
ikev2_validate_cert(struct iked_message *msg, size_t offset, size_t left,
789
    struct ikev2_cert *cert)
790
6.90k
{
791
6.90k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
792
793
6.90k
  if (left < sizeof(*cert)) {
794
1.53k
    log_debug("%s: malformed payload: too short for header "
795
1.53k
        "(%zu < %zu)", __func__, left, sizeof(*cert));
796
1.53k
    return (-1);
797
1.53k
  }
798
5.37k
  memcpy(cert, msgbuf + offset, sizeof(*cert));
799
5.37k
  if (cert->cert_type == IKEV2_CERT_NONE) {
800
1.03k
    log_debug("%s: malformed payload: invalid cert type", __func__);
801
1.03k
    return (-1);
802
1.03k
  }
803
804
4.33k
  return (0);
805
5.37k
}
806
807
int
808
ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld,
809
    struct iked_message *msg, size_t offset, size_t left)
810
6.90k
{
811
6.90k
  struct ikev2_cert    cert;
812
6.90k
  uint8_t       *buf;
813
6.90k
  size_t         len;
814
6.90k
  struct iked_id      *certid;
815
6.90k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
816
6.90k
  const struct iked_sa    *sa = msg->msg_sa;
817
6.90k
  int        i;
818
819
6.90k
  if (ikev2_validate_cert(msg, offset, left, &cert))
820
2.56k
    return (-1);
821
4.33k
  offset += sizeof(cert);
822
823
4.33k
  buf = msgbuf + offset;
824
4.33k
  len = left - sizeof(cert);
825
826
4.33k
  log_debug("%s: type %s length %zu",
827
4.33k
      __func__, print_map(cert.cert_type, ikev2_cert_map), len);
828
829
4.33k
  print_hex(buf, 0, len);
830
831
4.33k
  if (!ikev2_msg_frompeer(msg))
832
1.54k
    return (0);
833
834
  /* do not accept internal encoding in the wire */
835
2.78k
  if (cert.cert_type == IKEV2_CERT_BUNDLE) {
836
290
    log_debug("%s: ignoring IKEV2_CERT_BUNDLE",
837
290
       SPI_SA(sa, __func__));
838
290
    return (0);
839
290
  }
840
841
2.49k
  certid = &msg->msg_parent->msg_cert;
842
2.49k
  if (certid->id_type) {
843
    /* try to set supplemental certs */
844
6.88k
    for (i = 0; i < IKED_SCERT_MAX; i++) {
845
5.52k
      certid = &msg->msg_parent->msg_scert[i];
846
5.52k
      if (!certid->id_type)
847
778
        break;
848
5.52k
    }
849
2.13k
    if (certid->id_type) {
850
1.35k
      log_debug("%s: too many cert payloads, ignoring",
851
1.35k
         SPI_SA(sa, __func__));
852
1.35k
      return (0);
853
1.35k
    }
854
2.13k
  }
855
856
1.14k
  if ((certid->id_buf = ibuf_new(buf, len)) == NULL) {
857
0
    log_debug("%s: failed to save cert", __func__);
858
0
    return (-1);
859
0
  }
860
1.14k
  certid->id_type = cert.cert_type;
861
1.14k
  certid->id_offset = 0;
862
863
1.14k
  return (0);
864
1.14k
}
865
866
int
867
ikev2_validate_certreq(struct iked_message *msg, size_t offset, size_t left,
868
    struct ikev2_cert *cert)
869
15.4k
{
870
15.4k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
871
872
15.4k
  if (left < sizeof(*cert)) {
873
3.58k
    log_debug("%s: malformed payload: too short for header "
874
3.58k
        "(%zu < %zu)", __func__, left, sizeof(*cert));
875
3.58k
    return (-1);
876
3.58k
  }
877
11.8k
  memcpy(cert, msgbuf + offset, sizeof(*cert));
878
879
11.8k
  return (0);
880
15.4k
}
881
882
int
883
ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld,
884
    struct iked_message *msg, size_t offset, size_t left)
885
15.4k
{
886
15.4k
  struct ikev2_cert    cert;
887
15.4k
  struct iked_certreq   *cr;
888
15.4k
  uint8_t       *buf;
889
15.4k
  ssize_t        len;
890
15.4k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
891
892
15.4k
  if (ikev2_validate_certreq(msg, offset, left, &cert))
893
3.58k
    return (-1);
894
11.8k
  offset += sizeof(cert);
895
896
11.8k
  buf = msgbuf + offset;
897
11.8k
  len = left - sizeof(cert);
898
899
11.8k
  log_debug("%s: type %s length %zd",
900
11.8k
      __func__, print_map(cert.cert_type, ikev2_cert_map), len);
901
902
11.8k
  print_hex(buf, 0, len);
903
904
11.8k
  if (!ikev2_msg_frompeer(msg))
905
10.4k
    return (0);
906
907
1.34k
  if (cert.cert_type == IKEV2_CERT_X509_CERT) {
908
330
    if (len == 0) {
909
288
      log_info("%s: invalid length 0", __func__);
910
288
      return (0);
911
288
    }
912
42
    if ((len % SHA_DIGEST_LENGTH) != 0) {
913
9
      log_info("%s: invalid certificate request",
914
9
          __func__);
915
9
      return (-1);
916
9
    }
917
42
  }
918
919
1.04k
  if ((cr = calloc(1, sizeof(struct iked_certreq))) == NULL) {
920
0
    log_info("%s: failed to allocate certreq.", __func__);
921
0
    return (-1);
922
0
  }
923
1.04k
  if ((cr->cr_data = ibuf_new(buf, len)) == NULL) {
924
0
    log_info("%s: failed to allocate buffer.", __func__);
925
0
    free(cr);
926
0
    return (-1);
927
0
  }
928
1.04k
  cr->cr_type = cert.cert_type;
929
1.04k
  SIMPLEQ_INSERT_TAIL(&msg->msg_parent->msg_certreqs, cr, cr_entry);
930
931
1.04k
  return (0);
932
1.04k
}
933
934
int
935
ikev2_validate_auth(struct iked_message *msg, size_t offset, size_t left,
936
    struct ikev2_auth *auth)
937
10.5k
{
938
10.5k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
939
940
10.5k
  if (left < sizeof(*auth)) {
941
2.04k
    log_debug("%s: malformed payload: too short for header "
942
2.04k
        "(%zu < %zu)", __func__, left, sizeof(*auth));
943
2.04k
    return (-1);
944
2.04k
  }
945
8.50k
  memcpy(auth, msgbuf + offset, sizeof(*auth));
946
947
8.50k
  if (auth->auth_method == 0) {
948
4.72k
    log_info("%s: malformed payload: invalid auth method",
949
4.72k
        __func__);
950
4.72k
    return (-1);
951
4.72k
  }
952
953
3.78k
  return (0);
954
8.50k
}
955
956
int
957
ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld,
958
    struct iked_message *msg, size_t offset, size_t left)
959
10.5k
{
960
10.5k
  struct ikev2_auth    auth;
961
10.5k
  struct iked_id      *idp;
962
10.5k
  uint8_t       *buf;
963
10.5k
  size_t         len;
964
10.5k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
965
966
10.5k
  if (ikev2_validate_auth(msg, offset, left, &auth))
967
6.76k
    return (-1);
968
3.78k
  offset += sizeof(auth);
969
970
3.78k
  buf = msgbuf + offset;
971
3.78k
  len = left - sizeof(auth);
972
973
3.78k
  log_debug("%s: method %s length %zu",
974
3.78k
      __func__, print_map(auth.auth_method, ikev2_auth_map), len);
975
976
3.78k
  print_hex(buf, 0, len);
977
978
3.78k
  if (!ikev2_msg_frompeer(msg))
979
3.74k
    return (0);
980
981
42
  idp = &msg->msg_parent->msg_auth;
982
42
  if (idp->id_type) {
983
1
    log_debug("%s: duplicate auth payload", __func__);
984
1
    return (-1);
985
1
  }
986
987
41
  ibuf_free(idp->id_buf);
988
41
  idp->id_type = auth.auth_method;
989
41
  idp->id_offset = 0;
990
41
  if ((idp->id_buf = ibuf_new(buf, len)) == NULL)
991
0
    return (-1);
992
993
41
  return (0);
994
41
}
995
996
int
997
ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld,
998
    struct iked_message *msg, size_t offset, size_t left)
999
3.51k
{
1000
3.51k
  size_t     len;
1001
3.51k
  uint8_t   *buf;
1002
3.51k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1003
1004
3.51k
  buf = msgbuf + offset;
1005
3.51k
  len = left;
1006
1007
3.51k
  if (len == 0) {
1008
3.21k
    log_debug("%s: malformed payload: no NONCE given", __func__);
1009
3.21k
    return (-1);
1010
3.21k
  }
1011
1012
298
  print_hex(buf, 0, len);
1013
1014
298
  if (ikev2_msg_frompeer(msg)) {
1015
62
    if (msg->msg_parent->msg_nonce != NULL) {
1016
19
      log_info("%s: duplicate NONCE payload", __func__);
1017
19
      return (-1);
1018
19
    }
1019
43
    if ((msg->msg_nonce = ibuf_new(buf, len)) == NULL) {
1020
0
      log_debug("%s: failed to get peer nonce", __func__);
1021
0
      return (-1);
1022
0
    }
1023
43
    msg->msg_parent->msg_nonce = msg->msg_nonce;
1024
43
  }
1025
1026
279
  return (0);
1027
298
}
1028
1029
int
1030
ikev2_validate_notify(struct iked_message *msg, size_t offset, size_t left,
1031
    struct ikev2_notify *n)
1032
39.8k
{
1033
39.8k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1034
1035
39.8k
  if (left < sizeof(*n)) {
1036
5.32k
    log_debug("%s: malformed payload: too short for header "
1037
5.32k
        "(%zu < %zu)", __func__, left, sizeof(*n));
1038
5.32k
    return (-1);
1039
5.32k
  }
1040
34.4k
  memcpy(n, msgbuf + offset, sizeof(*n));
1041
1042
34.4k
  return (0);
1043
39.8k
}
1044
1045
int
1046
ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld,
1047
    struct iked_message *msg, size_t offset, size_t left)
1048
39.8k
{
1049
39.8k
  struct ikev2_notify  n;
1050
39.8k
  const struct iked_sa  *sa = msg->msg_sa;
1051
39.8k
  uint8_t     *buf, md[SHA_DIGEST_LENGTH];
1052
39.8k
  uint32_t     spi32;
1053
39.8k
  uint64_t     spi64;
1054
39.8k
  struct iked_spi   *rekey;
1055
39.8k
  uint16_t     type;
1056
39.8k
  uint16_t     signature_hash;
1057
1058
39.8k
  if (ikev2_validate_notify(msg, offset, left, &n))
1059
5.32k
    return (-1);
1060
34.4k
  type = betoh16(n.n_type);
1061
1062
34.4k
  log_debug("%s: protoid %s spisize %d type %s",
1063
34.4k
      __func__,
1064
34.4k
      print_map(n.n_protoid, ikev2_saproto_map), n.n_spisize,
1065
34.4k
      print_map(type, ikev2_n_map));
1066
1067
34.4k
  left -= sizeof(n);
1068
34.4k
  if ((buf = ibuf_seek(msg->msg_data, offset + sizeof(n), left)) == NULL)
1069
0
    return (-1);
1070
1071
34.4k
  print_hex(buf, 0, left);
1072
1073
34.4k
  if (!ikev2_msg_frompeer(msg))
1074
2.00k
    return (0);
1075
1076
32.4k
  switch (type) {
1077
3.34k
  case IKEV2_N_NAT_DETECTION_SOURCE_IP:
1078
26.0k
  case IKEV2_N_NAT_DETECTION_DESTINATION_IP:
1079
26.0k
    if (left != sizeof(md)) {
1080
17
      log_debug("%s: malformed payload: hash size mismatch"
1081
17
          " (%zu != %zu)", __func__, left, sizeof(md));
1082
17
      return (-1);
1083
17
    }
1084
26.0k
    if (ikev2_nat_detection(env, msg, md, sizeof(md), type,
1085
26.0k
        ikev2_msg_frompeer(msg)) == -1)
1086
0
      return (-1);
1087
26.0k
    if (memcmp(buf, md, left) != 0) {
1088
25.8k
      log_debug("%s: %s detected NAT", __func__,
1089
25.8k
          print_map(type, ikev2_n_map));
1090
25.8k
      if (type == IKEV2_N_NAT_DETECTION_SOURCE_IP)
1091
3.34k
        msg->msg_parent->msg_nat_detected
1092
3.34k
            |= IKED_MSG_NAT_SRC_IP;
1093
22.4k
      else
1094
22.4k
        msg->msg_parent->msg_nat_detected
1095
22.4k
            |= IKED_MSG_NAT_DST_IP;
1096
25.8k
    }
1097
26.0k
    print_hex(md, 0, sizeof(md));
1098
    /* remember for MOBIKE */
1099
26.0k
    msg->msg_parent->msg_natt_rcvd = 1;
1100
26.0k
    break;
1101
6
  case IKEV2_N_AUTHENTICATION_FAILED:
1102
6
    if (!msg->msg_e) {
1103
0
      log_debug("%s: AUTHENTICATION_FAILED not encrypted",
1104
0
          __func__);
1105
0
      return (-1);
1106
0
    }
1107
    /*
1108
     * If we are the responder, then we only accept
1109
     * AUTHENTICATION_FAILED from authenticated peers.
1110
     * If we are the initiator, the peer cannot be authenticated.
1111
     */
1112
6
    if (!sa->sa_hdr.sh_initiator) {
1113
6
      if (!sa_stateok(sa, IKEV2_STATE_VALID)) {
1114
6
        log_debug("%s: ignoring AUTHENTICATION_FAILED"
1115
6
            " from unauthenticated initiator",
1116
6
            __func__);
1117
6
        return (-1);
1118
6
      }
1119
6
    } else {
1120
0
      if (sa_stateok(sa, IKEV2_STATE_VALID)) {
1121
0
        log_debug("%s: ignoring AUTHENTICATION_FAILED"
1122
0
            " from authenticated responder",
1123
0
            __func__);
1124
0
        return (-1);
1125
0
      }
1126
0
    }
1127
0
    msg->msg_parent->msg_flags
1128
0
        |= IKED_MSG_FLAGS_AUTHENTICATION_FAILED;
1129
0
    break;
1130
143
  case IKEV2_N_INVALID_KE_PAYLOAD:
1131
143
    if (sa_stateok(sa, IKEV2_STATE_VALID) &&
1132
143
        !msg->msg_e) {
1133
0
      log_debug("%s: INVALID_KE_PAYLOAD not encrypted",
1134
0
          __func__);
1135
0
      return (-1);
1136
0
    }
1137
143
    if (left != sizeof(msg->msg_parent->msg_group)) {
1138
4
      log_debug("%s: malformed payload: group size mismatch"
1139
4
          " (%zu != %zu)", __func__, left,
1140
4
          sizeof(msg->msg_parent->msg_group));
1141
4
      return (-1);
1142
4
    }
1143
139
    memcpy(&msg->msg_parent->msg_group, buf, left);
1144
139
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_INVALID_KE;
1145
139
    break;
1146
273
  case IKEV2_N_NO_ADDITIONAL_SAS:
1147
273
    if (!msg->msg_e) {
1148
0
      log_debug("%s: NO_ADDITIONAL_SAS not encrypted",
1149
0
          __func__);
1150
0
      return (-1);
1151
0
    }
1152
273
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_NO_ADDITIONAL_SAS;
1153
273
    break;
1154
82
  case IKEV2_N_REKEY_SA:
1155
82
    if (!msg->msg_e) {
1156
0
      log_debug("%s: N_REKEY_SA not encrypted", __func__);
1157
0
      return (-1);
1158
0
    }
1159
82
    if (left != n.n_spisize) {
1160
5
      log_debug("%s: malformed notification", __func__);
1161
5
      return (-1);
1162
5
    }
1163
77
    rekey = &msg->msg_parent->msg_rekey;
1164
77
    if (rekey->spi != 0) {
1165
5
      log_debug("%s: rekeying of multiple SAs not supported",
1166
5
          __func__);
1167
5
      return (-1);
1168
5
    }
1169
72
    switch (n.n_spisize) {
1170
65
    case 4:
1171
65
      memcpy(&spi32, buf, left);
1172
65
      rekey->spi = betoh32(spi32);
1173
65
      break;
1174
4
    case 8:
1175
4
      memcpy(&spi64, buf, left);
1176
4
      rekey->spi = betoh64(spi64);
1177
4
      break;
1178
3
    default:
1179
3
      log_debug("%s: invalid spi size %d", __func__,
1180
3
          n.n_spisize);
1181
3
      return (-1);
1182
72
    }
1183
69
    rekey->spi_size = n.n_spisize;
1184
69
    rekey->spi_protoid = n.n_protoid;
1185
1186
69
    log_debug("%s: rekey %s spi %s", __func__,
1187
69
        print_map(n.n_protoid, ikev2_saproto_map),
1188
69
        print_spi(rekey->spi, n.n_spisize));
1189
69
    break;
1190
354
  case IKEV2_N_TEMPORARY_FAILURE:
1191
354
    if (!msg->msg_e) {
1192
0
      log_debug("%s: IKEV2_N_TEMPORARY_FAILURE not encrypted",
1193
0
          __func__);
1194
0
      return (-1);
1195
0
    }
1196
354
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_TEMPORARY_FAILURE;
1197
354
    break;
1198
255
  case IKEV2_N_IPCOMP_SUPPORTED:
1199
255
    if (!msg->msg_e) {
1200
0
      log_debug("%s: N_IPCOMP_SUPPORTED not encrypted",
1201
0
          __func__);
1202
0
      return (-1);
1203
0
    }
1204
255
    if (left < sizeof(msg->msg_parent->msg_cpi) +
1205
255
        sizeof(msg->msg_parent->msg_transform)) {
1206
127
      log_debug("%s: ignoring malformed ipcomp notification",
1207
127
          __func__);
1208
127
      return (0);
1209
127
    }
1210
128
    memcpy(&msg->msg_parent->msg_cpi, buf,
1211
128
        sizeof(msg->msg_parent->msg_cpi));
1212
128
    memcpy(&msg->msg_parent->msg_transform,
1213
128
        buf + sizeof(msg->msg_parent->msg_cpi),
1214
128
        sizeof(msg->msg_parent->msg_transform));
1215
1216
128
    log_debug("%s: %s cpi 0x%x, transform %s, length %zu", __func__,
1217
128
        msg->msg_parent->msg_response ? "res" : "req",
1218
128
        betoh16(msg->msg_parent->msg_cpi),
1219
128
        print_map(msg->msg_parent->msg_transform,
1220
128
        ikev2_ipcomp_map), left);
1221
1222
128
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_IPCOMP_SUPPORTED;
1223
128
    break;
1224
73
  case IKEV2_N_CHILD_SA_NOT_FOUND:
1225
73
    if (!msg->msg_e) {
1226
0
      log_debug("%s: N_CHILD_SA_NOT_FOUND not encrypted",
1227
0
          __func__);
1228
0
      return (-1);
1229
0
    }
1230
73
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_CHILD_SA_NOT_FOUND;
1231
73
    break;
1232
36
  case IKEV2_N_NO_PROPOSAL_CHOSEN:
1233
36
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN;
1234
36
    break;
1235
1.81k
  case IKEV2_N_MOBIKE_SUPPORTED:
1236
1.81k
    if (!msg->msg_e) {
1237
0
      log_debug("%s: N_MOBIKE_SUPPORTED not encrypted",
1238
0
          __func__);
1239
0
      return (-1);
1240
0
    }
1241
1.81k
    if (left != 0) {
1242
1.65k
      log_debug("%s: ignoring malformed mobike"
1243
1.65k
          " notification: %zu", __func__, left);
1244
1.65k
      return (0);
1245
1.65k
    }
1246
159
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_MOBIKE;
1247
159
    break;
1248
356
  case IKEV2_N_USE_TRANSPORT_MODE:
1249
356
    if (!msg->msg_e) {
1250
0
      log_debug("%s: N_USE_TRANSPORT_MODE not encrypted",
1251
0
          __func__);
1252
0
      return (-1);
1253
0
    }
1254
356
    if (left != 0) {
1255
77
      log_debug("%s: ignoring malformed transport mode"
1256
77
          " notification: %zu", __func__, left);
1257
77
      return (0);
1258
77
    }
1259
279
    if (msg->msg_parent->msg_response) {
1260
0
      if (!(msg->msg_policy->pol_flags & IKED_POLICY_TRANSPORT)) {
1261
0
        log_debug("%s: ignoring transport mode"
1262
0
            " notification (policy)", __func__);
1263
0
        return (0);
1264
0
      }
1265
0
    }
1266
279
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_USE_TRANSPORT;
1267
279
    break;
1268
388
  case IKEV2_N_UPDATE_SA_ADDRESSES:
1269
388
    if (!msg->msg_e) {
1270
0
      log_debug("%s: N_UPDATE_SA_ADDRESSES not encrypted",
1271
0
          __func__);
1272
0
      return (-1);
1273
0
    }
1274
388
    if (!sa->sa_mobike) {
1275
388
      log_debug("%s: ignoring update sa addresses"
1276
388
          " notification w/o mobike: %zu", __func__, left);
1277
388
      return (0);
1278
388
    }
1279
0
    if (left != 0) {
1280
0
      log_debug("%s: ignoring malformed update sa addresses"
1281
0
          " notification: %zu", __func__, left);
1282
0
      return (0);
1283
0
    }
1284
0
    msg->msg_parent->msg_update_sa_addresses = 1;
1285
0
    break;
1286
242
  case IKEV2_N_COOKIE2:
1287
242
    if (!msg->msg_e) {
1288
0
      log_debug("%s: N_COOKIE2 not encrypted",
1289
0
          __func__);
1290
0
      return (-1);
1291
0
    }
1292
242
    if (!sa->sa_mobike) {
1293
242
      log_debug("%s: ignoring cookie2 notification"
1294
242
          " w/o mobike: %zu", __func__, left);
1295
242
      return (0);
1296
242
    }
1297
0
    if (left < IKED_COOKIE2_MIN || left > IKED_COOKIE2_MAX) {
1298
0
      log_debug("%s: ignoring malformed cookie2"
1299
0
          " notification: %zu", __func__, left);
1300
0
      return (0);
1301
0
    }
1302
0
    ibuf_free(msg->msg_cookie2);  /* should not happen */
1303
0
    if ((msg->msg_cookie2 = ibuf_new(buf, left)) == NULL) {
1304
0
      log_debug("%s: failed to get peer cookie2", __func__);
1305
0
      return (-1);
1306
0
    }
1307
0
    msg->msg_parent->msg_cookie2 = msg->msg_cookie2;
1308
0
    break;
1309
2
  case IKEV2_N_COOKIE:
1310
2
    if (msg->msg_e) {
1311
2
      log_debug("%s: N_COOKIE encrypted",
1312
2
          __func__);
1313
2
      return (-1);
1314
2
    }
1315
0
    if (left < IKED_COOKIE_MIN || left > IKED_COOKIE_MAX) {
1316
0
      log_debug("%s: ignoring malformed cookie"
1317
0
          " notification: %zu", __func__, left);
1318
0
      return (0);
1319
0
    }
1320
0
    log_debug("%s: received cookie, len %zu", __func__, left);
1321
0
    print_hex(buf, 0, left);
1322
1323
0
    ibuf_free(msg->msg_cookie);
1324
0
    if ((msg->msg_cookie = ibuf_new(buf, left)) == NULL) {
1325
0
      log_debug("%s: failed to get peer cookie", __func__);
1326
0
      return (-1);
1327
0
    }
1328
0
    msg->msg_parent->msg_cookie = msg->msg_cookie;
1329
0
    break;
1330
14
  case IKEV2_N_FRAGMENTATION_SUPPORTED:
1331
14
    if (msg->msg_e) {
1332
14
      log_debug("%s: N_FRAGMENTATION_SUPPORTED encrypted",
1333
14
          __func__);
1334
14
      return (-1);
1335
14
    }
1336
0
    if (left != 0) {
1337
0
      log_debug("%s: ignoring malformed fragmentation"
1338
0
          " notification: %zu", __func__, left);
1339
0
      return (0);
1340
0
    }
1341
0
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_FRAGMENTATION;
1342
0
    break;
1343
7
  case IKEV2_N_SIGNATURE_HASH_ALGORITHMS:
1344
7
    if (msg->msg_e) {
1345
7
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: encrypted",
1346
7
          __func__);
1347
7
      return (-1);
1348
7
    }
1349
0
    if (sa == NULL) {
1350
0
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: no SA",
1351
0
          __func__);
1352
0
      return (-1);
1353
0
    }
1354
0
    if (sa->sa_sigsha2) {
1355
0
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: "
1356
0
          "duplicate notify", __func__);
1357
0
      return (0);
1358
0
    }
1359
0
    if (left < sizeof(signature_hash) ||
1360
0
        left % sizeof(signature_hash)) {
1361
0
      log_debug("%s: malformed signature hash notification"
1362
0
          "(%zu bytes)", __func__, left);
1363
0
      return (0);
1364
0
    }
1365
0
    while (left >= sizeof(signature_hash)) {
1366
0
      memcpy(&signature_hash, buf, sizeof(signature_hash));
1367
0
      signature_hash = betoh16(signature_hash);
1368
0
      log_debug("%s: signature hash %s (%x)", __func__,
1369
0
          print_map(signature_hash, ikev2_sighash_map),
1370
0
          signature_hash);
1371
0
      left -= sizeof(signature_hash);
1372
0
      buf += sizeof(signature_hash);
1373
0
      if (signature_hash == IKEV2_SIGHASH_SHA2_256)
1374
0
        msg->msg_parent->msg_flags
1375
0
            |= IKED_MSG_FLAGS_SIGSHA2;
1376
0
    }
1377
0
    break;
1378
32.4k
  }
1379
1380
29.9k
  return (0);
1381
32.4k
}
1382
1383
int
1384
ikev2_validate_delete(struct iked_message *msg, size_t offset, size_t left,
1385
    struct ikev2_delete *del)
1386
7.54k
{
1387
7.54k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1388
1389
7.54k
  if (left < sizeof(*del)) {
1390
1.53k
    log_debug("%s: malformed payload: too short for header "
1391
1.53k
        "(%zu < %zu)", __func__, left, sizeof(*del));
1392
1.53k
    return (-1);
1393
1.53k
  }
1394
6.01k
  memcpy(del, msgbuf + offset, sizeof(*del));
1395
1396
6.01k
  if (del->del_protoid == 0) {
1397
84
    log_info("%s: malformed payload: invalid protoid", __func__);
1398
84
    return (-1);
1399
84
  }
1400
1401
5.92k
  return (0);
1402
6.01k
}
1403
1404
int
1405
ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld,
1406
    struct iked_message *msg, size_t offset, size_t left)
1407
7.54k
{
1408
7.54k
  struct ikev2_delete  del;
1409
7.54k
  uint8_t     *buf, *msgbuf = ibuf_data(msg->msg_data);
1410
7.54k
  size_t       cnt, sz, len;
1411
1412
7.54k
  if (ikev2_validate_delete(msg, offset, left, &del))
1413
1.62k
    return (-1);
1414
1415
  /* Skip if it's a response, then we don't have to deal with it */
1416
5.92k
  if (ikev2_msg_frompeer(msg) &&
1417
5.92k
      msg->msg_parent->msg_response)
1418
0
    return (0);
1419
1420
5.92k
  cnt = betoh16(del.del_nspi);
1421
5.92k
  sz = del.del_spisize;
1422
1423
5.92k
  log_debug("%s: proto %s spisize %zu nspi %zu",
1424
5.92k
      __func__, print_map(del.del_protoid, ikev2_saproto_map),
1425
5.92k
      sz, cnt);
1426
1427
5.92k
  if (msg->msg_parent->msg_del_protoid) {
1428
5.54k
    log_debug("%s: duplicate delete payload", __func__);
1429
5.54k
    return (0);
1430
5.54k
  }
1431
1432
380
  msg->msg_parent->msg_del_protoid = del.del_protoid;
1433
380
  msg->msg_parent->msg_del_cnt = cnt;
1434
380
  msg->msg_parent->msg_del_spisize = sz;
1435
1436
380
  buf = msgbuf + offset + sizeof(del);
1437
380
  len = left - sizeof(del);
1438
380
  if (len == 0 || sz == 0 || cnt == 0)
1439
357
    return (0);
1440
1441
23
  if ((len / sz) != cnt) {
1442
21
    log_debug("%s: invalid payload length %zu/%zu != %zu",
1443
21
        __func__, len, sz, cnt);
1444
21
    return (-1);
1445
21
  }
1446
1447
2
  print_hex(buf, 0, len);
1448
1449
2
  msg->msg_parent->msg_del_buf = ibuf_new(buf, len);
1450
1451
2
  return (0);
1452
23
}
1453
1454
int
1455
ikev2_validate_tss(struct iked_message *msg, size_t offset, size_t left,
1456
    struct ikev2_tsp *tsp)
1457
23.0k
{
1458
23.0k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1459
1460
23.0k
  if (left < sizeof(*tsp)) {
1461
2.69k
    log_debug("%s: malformed payload: too short for header "
1462
2.69k
        "(%zu < %zu)", __func__, left, sizeof(*tsp));
1463
2.69k
    return (-1);
1464
2.69k
  }
1465
20.4k
  memcpy(tsp, msgbuf + offset, sizeof(*tsp));
1466
1467
20.4k
  return (0);
1468
23.0k
}
1469
1470
int
1471
ikev2_pld_tss(struct iked *env, struct ikev2_payload *pld,
1472
    struct iked_message *msg, size_t offset, size_t left)
1473
23.0k
{
1474
23.0k
  struct ikev2_tsp     tsp;
1475
23.0k
  struct ikev2_ts      ts;
1476
23.0k
  size_t         ts_len, i;
1477
1478
23.0k
  if (ikev2_validate_tss(msg, offset, left, &tsp))
1479
2.69k
    return (-1);
1480
1481
20.4k
  offset += sizeof(tsp);
1482
20.4k
  left -= sizeof(tsp);
1483
1484
20.4k
  log_debug("%s: count %d length %zu", __func__,
1485
20.4k
      tsp.tsp_count, left);
1486
1487
40.3k
  for (i = 0; i < tsp.tsp_count; i++) {
1488
38.6k
    if (ikev2_validate_ts(msg, offset, left, &ts))
1489
15.9k
      return (-1);
1490
1491
22.6k
    log_debug("%s: type %s protoid %u length %d "
1492
22.6k
        "startport %u endport %u", __func__,
1493
22.6k
        print_map(ts.ts_type, ikev2_ts_map),
1494
22.6k
        ts.ts_protoid, betoh16(ts.ts_length),
1495
22.6k
        betoh16(ts.ts_startport),
1496
22.6k
        betoh16(ts.ts_endport));
1497
1498
22.6k
    offset += sizeof(ts);
1499
22.6k
    left -= sizeof(ts);
1500
1501
22.6k
    ts_len = betoh16(ts.ts_length) - sizeof(ts);
1502
22.6k
    if (ikev2_pld_ts(env, pld, msg, offset, ts_len, ts.ts_type))
1503
2.71k
      return (-1);
1504
1505
19.9k
    offset += ts_len;
1506
19.9k
    left -= ts_len;
1507
19.9k
  }
1508
1509
1.70k
  return (0);
1510
20.4k
}
1511
1512
int
1513
ikev2_validate_ts(struct iked_message *msg, size_t offset, size_t left,
1514
    struct ikev2_ts *ts)
1515
38.6k
{
1516
38.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1517
38.6k
  size_t     ts_length;
1518
1519
38.6k
  if (left < sizeof(*ts)) {
1520
14.4k
    log_debug("%s: malformed payload: too short for header "
1521
14.4k
        "(%zu < %zu)", __func__, left, sizeof(*ts));
1522
14.4k
    return (-1);
1523
14.4k
  }
1524
24.1k
  memcpy(ts, msgbuf + offset, sizeof(*ts));
1525
1526
24.1k
  ts_length = betoh16(ts->ts_length);
1527
24.1k
  if (ts_length < sizeof(*ts)) {
1528
349
    log_debug("%s: malformed payload: shorter than minimum header "
1529
349
        "size (%zu < %zu)", __func__, ts_length, sizeof(*ts));
1530
349
    return (-1);
1531
349
  }
1532
23.8k
  if (left < ts_length) {
1533
1.21k
    log_debug("%s: malformed payload: too long for payload size "
1534
1.21k
        "(%zu < %zu)", __func__, left, ts_length);
1535
1.21k
    return (-1);
1536
1.21k
  }
1537
1538
22.6k
  return (0);
1539
23.8k
}
1540
1541
int
1542
ikev2_pld_ts(struct iked *env, struct ikev2_payload *pld,
1543
    struct iked_message *msg, size_t offset, size_t left, unsigned int type)
1544
22.6k
{
1545
22.6k
  struct sockaddr_in     start4, end4;
1546
22.6k
  struct sockaddr_in6    start6, end6;
1547
22.6k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
1548
22.6k
  uint8_t       *ptr;
1549
1550
22.6k
  ptr = msgbuf + offset;
1551
1552
22.6k
  switch (type) {
1553
9.66k
  case IKEV2_TS_IPV4_ADDR_RANGE:
1554
9.66k
    if (left < 2 * 4) {
1555
1.16k
      log_debug("%s: malformed payload: too short "
1556
1.16k
          "for ipv4 addr range (%zu < %u)",
1557
1.16k
          __func__, left, 2 * 4);
1558
1.16k
      return (-1);
1559
1.16k
    }
1560
1561
8.50k
    bzero(&start4, sizeof(start4));
1562
8.50k
    start4.sin_family = AF_INET;
1563
#ifdef HAVE_SOCKADDR_SA_LEN
1564
    start4.sin_len = sizeof(start4);
1565
#endif
1566
8.50k
    memcpy(&start4.sin_addr.s_addr, ptr, 4);
1567
8.50k
    ptr += 4;
1568
8.50k
    left -= 4;
1569
1570
8.50k
    bzero(&end4, sizeof(end4));
1571
8.50k
    end4.sin_family = AF_INET;
1572
#ifdef HAVE_SOCKADDR_SA_LEN
1573
    end4.sin_len = sizeof(end4);
1574
#endif
1575
8.50k
    memcpy(&end4.sin_addr.s_addr, ptr, 4);
1576
8.50k
    left -= 4;
1577
1578
8.50k
    log_debug("%s: start %s end %s", __func__,
1579
8.50k
        print_addr(&start4), print_addr(&end4));
1580
8.50k
    break;
1581
1.54k
  case IKEV2_TS_IPV6_ADDR_RANGE:
1582
1.54k
    if (left < 2 * 16) {
1583
252
      log_debug("%s: malformed payload: too short "
1584
252
          "for ipv6 addr range (%zu < %u)",
1585
252
          __func__, left, 2 * 16);
1586
252
      return (-1);
1587
252
    }
1588
1.29k
    bzero(&start6, sizeof(start6));
1589
1.29k
    start6.sin6_family = AF_INET6;
1590
#ifdef HAVE_SOCKADDR_SA_LEN
1591
    start6.sin6_len = sizeof(start6);
1592
#endif
1593
1.29k
    memcpy(&start6.sin6_addr, ptr, 16);
1594
1.29k
    ptr += 16;
1595
1.29k
    left -= 16;
1596
1597
1.29k
    bzero(&end6, sizeof(end6));
1598
1.29k
    end6.sin6_family = AF_INET6;
1599
#ifdef HAVE_SOCKADDR_SA_LEN
1600
    end6.sin6_len = sizeof(end6);
1601
#endif
1602
1.29k
    memcpy(&end6.sin6_addr, ptr, 16);
1603
1.29k
    left -= 16;
1604
1605
1.29k
    log_debug("%s: start %s end %s", __func__,
1606
1.29k
        print_addr(&start6), print_addr(&end6));
1607
1.29k
    break;
1608
11.4k
  default:
1609
11.4k
    log_debug("%s: ignoring unknown TS type %u", __func__, type);
1610
11.4k
    return (0);
1611
22.6k
  }
1612
1613
9.79k
  if (left > 0) {
1614
1.30k
    log_debug("%s: malformed payload: left (%zu) > 0",
1615
1.30k
        __func__, left);
1616
1.30k
    return (-1);
1617
1.30k
  }
1618
1619
8.49k
  return (0);
1620
9.79k
}
1621
1622
int
1623
ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
1624
    struct iked_message *msg, size_t offset, size_t left)
1625
0
{
1626
0
  struct iked_sa      *sa = msg->msg_sa;
1627
0
  struct iked_frag    *sa_frag = &sa->sa_fragments;
1628
0
  struct iked_frag_entry    *el;
1629
0
  struct ikev2_frag_payload  frag;
1630
0
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
1631
0
  uint8_t       *buf;
1632
0
  struct ibuf     *e = NULL;
1633
0
  size_t         frag_num, frag_total;
1634
0
  size_t         len;
1635
0
  int        ret = -1;
1636
0
  int        processed = 0;
1637
0
  ssize_t        elen;
1638
1639
0
  buf = msgbuf + offset;
1640
0
  memcpy(&frag, buf, sizeof(frag));
1641
0
  frag_num = betoh16(frag.frag_num);
1642
0
  frag_total = betoh16(frag.frag_total);
1643
1644
0
  offset += sizeof(frag);
1645
0
  buf = msgbuf + offset;
1646
0
  len = left - sizeof(frag);
1647
1648
0
  ikestat_inc(env, ikes_frag_rcvd);
1649
1650
  /* Limit number of total fragments to avoid DOS */
1651
0
  if (frag_total > IKED_FRAG_TOTAL_MAX ) {
1652
0
    log_debug("%s: Total Fragments too big  %zu",
1653
0
        __func__, frag_total);
1654
0
    goto dropall;
1655
0
  }
1656
1657
  /* Check sanity of fragment header */
1658
0
  if (frag_num == 0 || frag_total == 0) {
1659
0
    log_debug("%s: Malformed fragment received: %zu of %zu",
1660
0
        __func__, frag_num, frag_total);
1661
0
    goto done;
1662
0
  }
1663
0
  log_debug("%s: Received fragment: %zu of %zu",
1664
0
      __func__, frag_num, frag_total);
1665
1666
  /* Drop fragment if frag_num and frag_total don't match */
1667
0
  if (frag_num > frag_total)
1668
0
    goto done;
1669
1670
  /* Decrypt fragment */
1671
0
  if ((e = ibuf_new(buf, len)) == NULL)
1672
0
    goto done;
1673
1674
0
  if ((e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e))
1675
0
      == NULL ) {
1676
0
    log_debug("%s: Failed to decrypt fragment: %zu of %zu",
1677
0
        __func__, frag_num, frag_total);
1678
0
    goto done;
1679
0
  }
1680
0
  elen = ibuf_size(e);
1681
1682
  /* Check new fragmented message */
1683
0
  if (sa_frag->frag_arr == NULL) {
1684
0
    sa_frag->frag_arr = recallocarray(NULL, 0, frag_total,
1685
0
        sizeof(struct iked_frag_entry*));
1686
0
    if (sa_frag->frag_arr == NULL) {
1687
0
      log_info("%s: recallocarray sa_frag->frag_arr.", __func__);
1688
0
      goto done;
1689
0
    }
1690
0
    sa_frag->frag_total = frag_total;
1691
0
  } else {
1692
    /* Drop all fragments if frag_total doesn't match previous */
1693
0
    if (frag_total != sa_frag->frag_total)
1694
0
      goto dropall;
1695
1696
    /* Silent drop if fragment already stored */
1697
0
    if (sa_frag->frag_arr[frag_num-1] != NULL)
1698
0
      goto done;
1699
0
  }
1700
1701
  /* The first fragments IKE header determines pld_nextpayload */
1702
0
  if (frag_num == 1)
1703
0
    sa_frag->frag_nextpayload = pld->pld_nextpayload;
1704
1705
  /* Insert new list element */
1706
0
  el = calloc(1, sizeof(struct iked_frag_entry));
1707
0
  if (el == NULL) {
1708
0
    log_info("%s: Failed allocating new fragment: %zu of %zu",
1709
0
        __func__, frag_num, frag_total);
1710
0
    goto done;
1711
0
  }
1712
1713
0
  sa_frag->frag_arr[frag_num-1] = el;
1714
0
  el->frag_size = elen;
1715
0
  el->frag_data = calloc(1, elen);
1716
0
  if (el->frag_data == NULL) {
1717
0
    log_debug("%s: Failed allocating new fragment data: %zu of %zu",
1718
0
        __func__, frag_num, frag_total);
1719
0
    goto done;
1720
0
  }
1721
1722
  /* Copy plaintext to fragment */
1723
0
  memcpy(el->frag_data, ibuf_seek(e, 0, 0), elen);
1724
0
  sa_frag->frag_total_size += elen;
1725
0
  sa_frag->frag_count++;
1726
1727
  /* If all frags are received start reassembly */
1728
0
  if (sa_frag->frag_count == sa_frag->frag_total) {
1729
0
    log_debug("%s: All fragments received: %zu of %zu",
1730
0
        __func__, frag_num, frag_total);
1731
0
    ret = ikev2_frags_reassemble(env, pld, msg);
1732
0
  } else {
1733
0
    ret = 0;
1734
0
  }
1735
0
  processed = 1;
1736
1737
0
done:
1738
0
  if (!processed)
1739
0
    ikestat_inc(env, ikes_frag_rcvd_drop);
1740
0
  ibuf_free(e);
1741
0
  return (ret);
1742
0
dropall:
1743
0
  ikestat_add(env, ikes_frag_rcvd_drop, sa_frag->frag_count + 1);
1744
0
  config_free_fragments(sa_frag);
1745
0
  ibuf_free(e);
1746
0
  return -1;
1747
0
}
1748
1749
int
1750
ikev2_frags_reassemble(struct iked *env, struct ikev2_payload *pld,
1751
    struct iked_message *msg)
1752
0
{
1753
0
  struct iked_frag    *sa_frag = &msg->msg_sa->sa_fragments;
1754
0
  struct ibuf     *e = NULL;
1755
0
  struct iked_frag_entry    *el;
1756
0
  uint8_t       *ptr;
1757
0
  size_t         offset;
1758
0
  size_t         i;
1759
0
  struct iked_message    emsg;
1760
0
  int        ret = -1;
1761
0
  int        processed = 0;
1762
1763
  /* Reassemble fragments to single buffer */
1764
0
  if ((e = ibuf_new(NULL, sa_frag->frag_total_size)) == NULL) {
1765
0
    log_debug("%s: Failed allocating SK buffer.", __func__);
1766
0
    goto done;
1767
0
  }
1768
1769
  /* Empty queue to new buffer */
1770
0
  offset = 0;
1771
0
  for (i = 0; i < sa_frag->frag_total; i++) {
1772
0
    if ((el = sa_frag->frag_arr[i]) == NULL)
1773
0
      fatalx("Tried to reassemble shallow frag_arr");
1774
0
    ptr = ibuf_seek(e, offset, el->frag_size);
1775
0
    if (ptr == NULL) {
1776
0
      log_info("%s: failed to reassemble fragments", __func__);
1777
0
      goto done;
1778
0
    }
1779
0
    memcpy(ptr, el->frag_data, el->frag_size);
1780
0
    offset += el->frag_size;
1781
0
  }
1782
1783
0
  log_debug("%s: Defragmented length %zd", __func__,
1784
0
      sa_frag->frag_total_size);
1785
0
  print_hex(ibuf_data(e), 0,  sa_frag->frag_total_size);
1786
1787
  /* Drop the original request's packets from the retransmit queue */
1788
0
  if (msg->msg_response)
1789
0
    ikev2_msg_dispose(env, &msg->msg_sa->sa_requests,
1790
0
        ikev2_msg_lookup(env, &msg->msg_sa->sa_requests, msg,
1791
0
        msg->msg_exchange));
1792
1793
  /*
1794
   * Parse decrypted payload
1795
   */
1796
0
  bzero(&emsg, sizeof(emsg));
1797
0
  memcpy(&emsg, msg, sizeof(*msg));
1798
0
  emsg.msg_data = e;
1799
0
  emsg.msg_e = 1;
1800
0
  emsg.msg_parent = msg;
1801
0
  TAILQ_INIT(&emsg.msg_proposals);
1802
1803
0
  ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
1804
0
      sa_frag->frag_nextpayload);
1805
0
  processed = 1;
1806
0
done:
1807
0
  if (processed)
1808
0
    ikestat_add(env, ikes_frag_reass_ok, sa_frag->frag_total);
1809
0
  else
1810
0
    ikestat_add(env, ikes_frag_reass_drop, sa_frag->frag_total);
1811
0
  config_free_fragments(sa_frag);
1812
0
  ibuf_free(e);
1813
1814
0
  return (ret);
1815
0
}
1816
1817
int
1818
ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
1819
    struct iked_message *msg, size_t offset, size_t left)
1820
0
{
1821
0
  struct iked_sa    *sa = msg->msg_sa;
1822
0
  struct ibuf   *e = NULL;
1823
0
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
1824
0
  struct iked_message  emsg;
1825
0
  uint8_t     *buf;
1826
0
  size_t       len;
1827
0
  int      ret = -1;
1828
1829
0
  if (sa->sa_fragments.frag_arr != NULL) {
1830
0
    log_warn("%s: Received SK payload when SKFs are in queue.",
1831
0
        __func__);
1832
0
    config_free_fragments(&sa->sa_fragments);
1833
0
    return (ret);
1834
0
  }
1835
1836
0
  buf = msgbuf + offset;
1837
0
  len = left;
1838
1839
0
  if ((e = ibuf_new(buf, len)) == NULL)
1840
0
    goto done;
1841
1842
0
  if (ikev2_msg_frompeer(msg)) {
1843
0
    e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
1844
0
  } else {
1845
0
    sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
1846
0
    e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
1847
0
    sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
1848
0
  }
1849
1850
0
  if (e == NULL)
1851
0
    goto done;
1852
1853
  /*
1854
   * Parse decrypted payload
1855
   */
1856
0
  bzero(&emsg, sizeof(emsg));
1857
0
  memcpy(&emsg, msg, sizeof(*msg));
1858
0
  emsg.msg_data = e;
1859
0
  emsg.msg_e = 1;
1860
0
  emsg.msg_parent = msg;
1861
0
  TAILQ_INIT(&emsg.msg_proposals);
1862
1863
0
  ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
1864
0
      pld->pld_nextpayload);
1865
1866
0
 done:
1867
0
  ibuf_free(e);
1868
1869
0
  return (ret);
1870
0
}
1871
1872
int
1873
ikev2_validate_cp(struct iked_message *msg, size_t offset, size_t left,
1874
    struct ikev2_cp *cp)
1875
11.6k
{
1876
11.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1877
1878
11.6k
  if (left < sizeof(*cp)) {
1879
3.58k
    log_debug("%s: malformed payload: too short for header "
1880
3.58k
        "(%zu < %zu)", __func__, left, sizeof(*cp));
1881
3.58k
    return (-1);
1882
3.58k
  }
1883
8.11k
  memcpy(cp, msgbuf + offset, sizeof(*cp));
1884
1885
8.11k
  return (0);
1886
11.6k
}
1887
1888
int
1889
ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld,
1890
    struct iked_message *msg, size_t offset, size_t left)
1891
11.6k
{
1892
11.6k
  struct ikev2_cp    cp;
1893
11.6k
  struct ikev2_cfg  *cfg;
1894
11.6k
  struct iked_addr  *addr;
1895
11.6k
  struct sockaddr_in  *in4;
1896
11.6k
  struct sockaddr_in6 *in6;
1897
11.6k
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
1898
11.6k
  uint8_t     *ptr;
1899
11.6k
  size_t       len;
1900
11.6k
  int      cfg_type;
1901
1902
11.6k
  if (ikev2_validate_cp(msg, offset, left, &cp))
1903
3.58k
    return (-1);
1904
1905
8.11k
  ptr = msgbuf + offset + sizeof(cp);
1906
8.11k
  len = left - sizeof(cp);
1907
1908
8.11k
  log_debug("%s: type %s length %zu",
1909
8.11k
      __func__, print_map(cp.cp_type, ikev2_cp_map), len);
1910
8.11k
  print_hex(ptr, 0, len);
1911
1912
16.4k
  while (len > 0) {
1913
10.1k
    if (len < sizeof(*cfg)) {
1914
367
      log_debug("%s: malformed payload: too short for cfg "
1915
367
          "(%zu < %zu)", __func__, len, sizeof(*cfg));
1916
367
      return (-1);
1917
367
    }
1918
9.74k
    cfg = (struct ikev2_cfg *)ptr;
1919
1920
9.74k
    log_debug("%s: %s 0x%04x length %d", __func__,
1921
9.74k
        print_map(betoh16(cfg->cfg_type), ikev2_cfg_map),
1922
9.74k
        betoh16(cfg->cfg_type),
1923
9.74k
        betoh16(cfg->cfg_length));
1924
1925
9.74k
    ptr += sizeof(*cfg);
1926
9.74k
    len -= sizeof(*cfg);
1927
1928
9.74k
    if (len < betoh16(cfg->cfg_length)) {
1929
1.42k
      log_debug("%s: malformed payload: too short for "
1930
1.42k
          "cfg_length (%zu < %u)", __func__, len,
1931
1.42k
          betoh16(cfg->cfg_length));
1932
1.42k
      return (-1);
1933
1.42k
    }
1934
1935
8.32k
    print_hex(ptr, sizeof(*cfg), betoh16(cfg->cfg_length));
1936
1937
8.32k
    cfg_type = betoh16(cfg->cfg_type);
1938
8.32k
    switch (cfg_type) {
1939
848
    case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1940
1.51k
    case IKEV2_CFG_INTERNAL_IP4_DNS:
1941
1.51k
      if (!ikev2_msg_frompeer(msg))
1942
741
        break;
1943
777
      if (betoh16(cfg->cfg_length) == 0)
1944
309
        break;
1945
      /* XXX multiple-valued */
1946
468
      if (betoh16(cfg->cfg_length) < 4) {
1947
6
        log_debug("%s: malformed payload: too short "
1948
6
            "for ipv4 addr (%u < %u)",
1949
6
            __func__, betoh16(cfg->cfg_length), 4);
1950
6
        return (-1);
1951
6
      }
1952
462
      switch(cfg_type) {
1953
359
      case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1954
359
        if (msg->msg_parent->msg_cp_addr != NULL) {
1955
240
          log_debug("%s: address already set", __func__);
1956
240
          goto skip;
1957
240
        }
1958
119
        break;
1959
119
      case IKEV2_CFG_INTERNAL_IP4_DNS:
1960
103
        if (msg->msg_parent->msg_cp_dns != NULL) {
1961
53
          log_debug("%s: dns already set", __func__);
1962
53
          goto skip;
1963
53
        }
1964
50
        break;
1965
50
      default:
1966
0
        break;
1967
462
      }
1968
169
      if ((addr = calloc(1, sizeof(*addr))) == NULL) {
1969
0
        log_debug("%s: malloc failed", __func__);
1970
0
        break;
1971
0
      }
1972
169
      addr->addr_af = AF_INET;
1973
169
      in4 = (struct sockaddr_in *)&addr->addr;
1974
169
      in4->sin_family = AF_INET;
1975
#ifdef HAVE_SOCKADDR_SA_LEN
1976
      in4->sin_len = sizeof(*in4);
1977
#endif
1978
169
      memcpy(&in4->sin_addr.s_addr, ptr, 4);
1979
169
      switch(cfg_type) {
1980
119
      case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1981
119
        msg->msg_parent->msg_cp_addr = addr;
1982
119
        log_debug("%s: IP4_ADDRESS %s", __func__,
1983
119
            print_addr(&addr->addr));
1984
119
        break;
1985
50
      case IKEV2_CFG_INTERNAL_IP4_DNS:
1986
50
        msg->msg_parent->msg_cp_dns = addr;
1987
50
        log_debug("%s: IP4_DNS %s", __func__,
1988
50
            print_addr(&addr->addr));
1989
50
        break;
1990
0
      default:
1991
0
        log_debug("%s: cfg %s", __func__,
1992
0
            print_addr(&addr->addr));
1993
0
        break;
1994
169
      }
1995
169
      break;
1996
2.28k
    case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
1997
3.13k
    case IKEV2_CFG_INTERNAL_IP6_DNS:
1998
3.13k
      if (!ikev2_msg_frompeer(msg))
1999
2.90k
        break;
2000
230
      if (betoh16(cfg->cfg_length) == 0)
2001
94
        break;
2002
      /* XXX multiple-valued */
2003
136
      if (betoh16(cfg->cfg_length) < 16) {
2004
5
        log_debug("%s: malformed payload: too short "
2005
5
            "for ipv6 addr w/prefixlen (%u < %u)",
2006
5
            __func__, betoh16(cfg->cfg_length), 16);
2007
5
        return (-1);
2008
5
      }
2009
131
      switch(cfg_type) {
2010
89
      case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
2011
89
        if (msg->msg_parent->msg_cp_addr6 != NULL) {
2012
47
          log_debug("%s: address6 already set", __func__);
2013
47
          goto skip;
2014
47
        }
2015
42
        break;
2016
42
      case IKEV2_CFG_INTERNAL_IP6_DNS:
2017
42
        if (msg->msg_parent->msg_cp_dns != NULL) {
2018
36
          log_debug("%s: dns already set", __func__);
2019
36
          goto skip;
2020
36
        }
2021
6
        break;
2022
131
      }
2023
48
      if ((addr = calloc(1, sizeof(*addr))) == NULL) {
2024
0
        log_debug("%s: malloc failed", __func__);
2025
0
        break;
2026
0
      }
2027
48
      addr->addr_af = AF_INET6;
2028
48
      in6 = (struct sockaddr_in6 *)&addr->addr;
2029
48
      in6->sin6_family = AF_INET6;
2030
#ifdef HAVE_SOCKADDR_SA_LEN
2031
      in6->sin6_len = sizeof(*in6);
2032
#endif
2033
48
      memcpy(&in6->sin6_addr, ptr, 16);
2034
48
      switch(cfg_type) {
2035
42
      case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
2036
42
        msg->msg_parent->msg_cp_addr6 = addr;
2037
42
        log_debug("%s: IP6_ADDRESS %s", __func__,
2038
42
            print_addr(&addr->addr));
2039
42
        break;
2040
6
      case IKEV2_CFG_INTERNAL_IP6_DNS:
2041
6
        msg->msg_parent->msg_cp_dns = addr;
2042
6
        log_debug("%s: IP6_DNS %s", __func__,
2043
6
            print_addr(&addr->addr));
2044
6
        break;
2045
0
      default:
2046
0
        log_debug("%s: cfg %s/%d", __func__,
2047
0
            print_addr(&addr->addr), ptr[16]);
2048
0
        break;
2049
48
      }
2050
48
      break;
2051
8.32k
    }
2052
2053
8.31k
 skip:
2054
8.31k
    ptr += betoh16(cfg->cfg_length);
2055
8.31k
    len -= betoh16(cfg->cfg_length);
2056
8.31k
  }
2057
2058
6.31k
  if (!ikev2_msg_frompeer(msg))
2059
6.10k
    return (0);
2060
2061
207
  msg->msg_parent->msg_cp = cp.cp_type;
2062
2063
207
  return (0);
2064
6.31k
}
2065
2066
int
2067
ikev2_validate_eap(struct iked_message *msg, size_t offset, size_t left,
2068
    struct eap_header *hdr)
2069
21.2k
{
2070
21.2k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
2071
2072
21.2k
  if (left < sizeof(*hdr)) {
2073
9.30k
    log_debug("%s: malformed payload: too short for header "
2074
9.30k
        "(%zu < %zu)", __func__, left, sizeof(*hdr));
2075
9.30k
    return (-1);
2076
9.30k
  }
2077
11.9k
  memcpy(hdr, msgbuf + offset, sizeof(*hdr));
2078
2079
11.9k
  return (0);
2080
21.2k
}
2081
2082
int
2083
ikev2_pld_eap(struct iked *env, struct ikev2_payload *pld,
2084
    struct iked_message *msg, size_t offset, size_t left)
2085
21.2k
{
2086
21.2k
  struct eap_header    hdr;
2087
21.2k
  struct eap_message    *eap = NULL;
2088
21.2k
  const struct iked_sa    *sa = msg->msg_sa;
2089
21.2k
  size_t         len;
2090
2091
21.2k
  if (ikev2_validate_eap(msg, offset, left, &hdr))
2092
9.30k
    return (-1);
2093
11.9k
  len = betoh16(hdr.eap_length);
2094
2095
11.9k
  if (len < sizeof(*eap)) {
2096
3.88k
    log_info("%s: %s id %d length %d", SPI_SA(sa, __func__),
2097
3.88k
        print_map(hdr.eap_code, eap_code_map),
2098
3.88k
        hdr.eap_id, betoh16(hdr.eap_length));
2099
8.07k
  } else {
2100
    /* Now try to get the indicated length */
2101
8.07k
    if ((eap = ibuf_seek(msg->msg_data, offset, len)) == NULL) {
2102
4.20k
      log_debug("%s: invalid EAP length", __func__);
2103
4.20k
      return (-1);
2104
4.20k
    }
2105
2106
3.86k
    log_info("%s: %s id %d length %d EAP-%s", SPI_SA(sa, __func__),
2107
3.86k
        print_map(eap->eap_code, eap_code_map),
2108
3.86k
        eap->eap_id, betoh16(eap->eap_length),
2109
3.86k
        print_map(eap->eap_type, eap_type_map));
2110
2111
3.86k
    if (eap_parse(env, sa, msg, eap, msg->msg_response) == -1)
2112
0
      return (-1);
2113
3.86k
    msg->msg_parent->msg_eap.eam_found = 1;
2114
3.86k
  }
2115
2116
7.75k
  return (0);
2117
11.9k
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/ikev2_pld.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: ikev2_pld.c,v 1.133 2023/09/02 18:36:30 tobhe Exp $ */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 * Copyright (c) 2014 Hans-Joerg Hoexer
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#include <sys/queue.h>
22
#include <sys/socket.h>
23
#include <sys/uio.h>
24
25
#include <netinet/in.h>
26
#include <arpa/inet.h>
27
28
#include <stdlib.h>
29
#include <stdio.h>
30
#include <unistd.h>
31
#include <string.h>
32
#include <signal.h>
33
#include <endian.h>
34
#include <errno.h>
35
#include <err.h>
36
#include <event.h>
37
38
#include <openssl/sha.h>
39
#include <openssl/evp.h>
40
41
#include "iked.h"
42
#include "ikev2.h"
43
#include "eap.h"
44
#include "dh.h"
45
46
int  ikev2_validate_pld(struct iked_message *, size_t, size_t,
47
      struct ikev2_payload *);
48
int  ikev2_pld_payloads(struct iked *, struct iked_message *,
49
      size_t, size_t, unsigned int);
50
int  ikev2_validate_sa(struct iked_message *, size_t, size_t,
51
      struct ikev2_sa_proposal *);
52
int  ikev2_pld_sa(struct iked *, struct ikev2_payload *,
53
      struct iked_message *, size_t, size_t);
54
int  ikev2_validate_xform(struct iked_message *, size_t, size_t,
55
      struct ikev2_transform *);
56
int  ikev2_pld_xform(struct iked *, struct iked_message *,
57
      size_t, size_t);
58
int  ikev2_validate_attr(struct iked_message *, size_t, size_t,
59
      struct ikev2_attribute *);
60
int  ikev2_pld_attr(struct iked *, struct ikev2_transform *,
61
      struct iked_message *, size_t, size_t);
62
int  ikev2_validate_ke(struct iked_message *, size_t, size_t,
63
      struct ikev2_keyexchange *);
64
int  ikev2_pld_ke(struct iked *, struct ikev2_payload *,
65
      struct iked_message *, size_t, size_t);
66
int  ikev2_validate_id(struct iked_message *, size_t, size_t,
67
      struct ikev2_id *);
68
int  ikev2_pld_id(struct iked *, struct ikev2_payload *,
69
      struct iked_message *, size_t, size_t, unsigned int);
70
int  ikev2_validate_cert(struct iked_message *, size_t, size_t,
71
      struct ikev2_cert *);
72
int  ikev2_pld_cert(struct iked *, struct ikev2_payload *,
73
      struct iked_message *, size_t, size_t);
74
int  ikev2_validate_certreq(struct iked_message *, size_t, size_t,
75
      struct ikev2_cert *);
76
int  ikev2_pld_certreq(struct iked *, struct ikev2_payload *,
77
      struct iked_message *, size_t, size_t);
78
int  ikev2_pld_nonce(struct iked *, struct ikev2_payload *,
79
      struct iked_message *, size_t, size_t);
80
int  ikev2_validate_notify(struct iked_message *, size_t, size_t,
81
      struct ikev2_notify *);
82
int  ikev2_pld_notify(struct iked *, struct ikev2_payload *,
83
      struct iked_message *, size_t, size_t);
84
int  ikev2_validate_delete(struct iked_message *, size_t, size_t,
85
      struct ikev2_delete *);
86
int  ikev2_pld_delete(struct iked *, struct ikev2_payload *,
87
      struct iked_message *, size_t, size_t);
88
int  ikev2_validate_tss(struct iked_message *, size_t, size_t,
89
      struct ikev2_tsp *);
90
int  ikev2_pld_tss(struct iked *, struct ikev2_payload *,
91
      struct iked_message *, size_t, size_t);
92
int  ikev2_validate_ts(struct iked_message *, size_t, size_t,
93
      struct ikev2_ts *);
94
int  ikev2_pld_ts(struct iked *, struct ikev2_payload *,
95
      struct iked_message *, size_t, size_t, unsigned int);
96
int  ikev2_validate_auth(struct iked_message *, size_t, size_t,
97
      struct ikev2_auth *);
98
int  ikev2_pld_auth(struct iked *, struct ikev2_payload *,
99
      struct iked_message *, size_t, size_t);
100
int  ikev2_pld_e(struct iked *, struct ikev2_payload *,
101
      struct iked_message *, size_t, size_t);
102
int  ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
103
      struct iked_message *msg, size_t offset, size_t left);
104
int  ikev2_frags_reassemble(struct iked *env,
105
      struct ikev2_payload *pld, struct iked_message *msg);
106
int  ikev2_validate_cp(struct iked_message *, size_t, size_t,
107
      struct ikev2_cp *);
108
int  ikev2_pld_cp(struct iked *, struct ikev2_payload *,
109
      struct iked_message *, size_t, size_t);
110
int  ikev2_validate_eap(struct iked_message *, size_t, size_t,
111
      struct eap_header *);
112
int  ikev2_pld_eap(struct iked *, struct ikev2_payload *,
113
      struct iked_message *, size_t, size_t);
114
115
int
116
ikev2_pld_parse(struct iked *env, struct ike_header *hdr,
117
    struct iked_message *msg, size_t offset)
118
15.4k
{
119
15.4k
  log_debug("%s: header ispi %s rspi %s"
120
15.4k
      " nextpayload %s version 0x%02x exchange %s flags 0x%02x"
121
15.4k
      " msgid %d length %u response %d", __func__,
122
15.4k
      print_spi(betoh64(hdr->ike_ispi), 8),
123
15.4k
      print_spi(betoh64(hdr->ike_rspi), 8),
124
15.4k
      print_map(hdr->ike_nextpayload, ikev2_payload_map),
125
15.4k
      hdr->ike_version,
126
15.4k
      print_map(hdr->ike_exchange, ikev2_exchange_map),
127
15.4k
      hdr->ike_flags,
128
15.4k
      betoh32(hdr->ike_msgid),
129
15.4k
      betoh32(hdr->ike_length),
130
15.4k
      msg->msg_response);
131
132
15.4k
  if (ibuf_size(msg->msg_data) < betoh32(hdr->ike_length)) {
133
6
    log_debug("%s: short message", __func__);
134
6
    return (-1);
135
6
  }
136
137
15.4k
  offset += sizeof(*hdr);
138
139
15.4k
  return (ikev2_pld_payloads(env, msg, offset,
140
15.4k
      betoh32(hdr->ike_length), hdr->ike_nextpayload));
141
15.4k
}
142
143
int
144
ikev2_validate_pld(struct iked_message *msg, size_t offset, size_t left,
145
    struct ikev2_payload *pld)
146
291k
{
147
291k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
148
291k
  size_t     pld_length;
149
150
  /* We need at least the generic header. */
151
291k
  if (left < sizeof(*pld)) {
152
2.01k
    log_debug("%s: malformed payload: too short for generic "
153
2.01k
        "header (%zu < %zu)", __func__, left, sizeof(*pld));
154
2.01k
    return (-1);
155
2.01k
  }
156
289k
  memcpy(pld, msgbuf + offset, sizeof(*pld));
157
158
  /*
159
   * We need at least the specified number of bytes.
160
   * pld_length is the full size of the payload including
161
   * the generic payload header.
162
   */
163
289k
  pld_length = betoh16(pld->pld_length);
164
289k
  if (left < pld_length) {
165
6.81k
    log_debug("%s: malformed payload: shorter than specified "
166
6.81k
        "(%zu < %zu)", __func__, left, pld_length);
167
6.81k
    return (-1);
168
6.81k
  }
169
  /*
170
   * Sanity check the specified payload size, it must
171
   * be at least the size of the generic payload header.
172
   */
173
282k
  if (pld_length < sizeof(*pld)) {
174
2.83k
    log_debug("%s: malformed payload: shorter than minimum "
175
2.83k
        "header size (%zu < %zu)", __func__, pld_length,
176
2.83k
        sizeof(*pld));
177
2.83k
    return (-1);
178
2.83k
  }
179
180
279k
  return (0);
181
282k
}
182
183
int
184
ikev2_pld_payloads(struct iked *env, struct iked_message *msg,
185
    size_t offset, size_t length, unsigned int payload)
186
15.4k
{
187
15.4k
  struct ikev2_payload   pld;
188
15.4k
  unsigned int     e;
189
15.4k
  int      ret;
190
15.4k
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
191
15.4k
  size_t       total, left;
192
193
  /* Check if message was decrypted in an E payload */
194
15.4k
  e = msg->msg_e ? IKED_E : 0;
195
196
  /* Bytes left in datagram. */
197
15.4k
  total = length - offset;
198
199
294k
  while (payload != 0 && offset < length) {
200
291k
    if (ikev2_validate_pld(msg, offset, total, &pld))
201
11.6k
      return (-1);
202
203
279k
    log_debug("%s: %spayload %s"
204
279k
        " nextpayload %s critical 0x%02x length %d",
205
279k
        __func__, e ? "decrypted " : "",
206
279k
        print_map(payload, ikev2_payload_map),
207
279k
        print_map(pld.pld_nextpayload, ikev2_payload_map),
208
279k
        pld.pld_reserved & IKEV2_CRITICAL_PAYLOAD,
209
279k
        betoh16(pld.pld_length));
210
211
    /* Skip over generic payload header. */
212
279k
    offset += sizeof(pld);
213
279k
    total -= sizeof(pld);
214
279k
    left = betoh16(pld.pld_length) - sizeof(pld);
215
279k
    ret = 0;
216
217
279k
    switch (payload | e) {
218
0
    case IKEV2_PAYLOAD_SA:
219
32.7k
    case IKEV2_PAYLOAD_SA | IKED_E:
220
32.7k
      ret = ikev2_pld_sa(env, &pld, msg, offset, left);
221
32.7k
      break;
222
0
    case IKEV2_PAYLOAD_KE:
223
10.9k
    case IKEV2_PAYLOAD_KE | IKED_E:
224
10.9k
      ret = ikev2_pld_ke(env, &pld, msg, offset, left);
225
10.9k
      break;
226
13.9k
    case IKEV2_PAYLOAD_IDi | IKED_E:
227
23.7k
    case IKEV2_PAYLOAD_IDr | IKED_E:
228
23.7k
      ret = ikev2_pld_id(env, &pld, msg, offset, left,
229
23.7k
          payload);
230
23.7k
      break;
231
6.90k
    case IKEV2_PAYLOAD_CERT | IKED_E:
232
6.90k
      ret = ikev2_pld_cert(env, &pld, msg, offset, left);
233
6.90k
      break;
234
0
    case IKEV2_PAYLOAD_CERTREQ:
235
15.4k
    case IKEV2_PAYLOAD_CERTREQ | IKED_E:
236
15.4k
      ret = ikev2_pld_certreq(env, &pld, msg, offset, left);
237
15.4k
      break;
238
10.5k
    case IKEV2_PAYLOAD_AUTH | IKED_E:
239
10.5k
      ret = ikev2_pld_auth(env, &pld, msg, offset, left);
240
10.5k
      break;
241
0
    case IKEV2_PAYLOAD_NONCE:
242
3.51k
    case IKEV2_PAYLOAD_NONCE | IKED_E:
243
3.51k
      ret = ikev2_pld_nonce(env, &pld, msg, offset, left);
244
3.51k
      break;
245
0
    case IKEV2_PAYLOAD_NOTIFY:
246
39.8k
    case IKEV2_PAYLOAD_NOTIFY | IKED_E:
247
39.8k
      ret = ikev2_pld_notify(env, &pld, msg, offset, left);
248
39.8k
      break;
249
7.54k
    case IKEV2_PAYLOAD_DELETE | IKED_E:
250
7.54k
      ret = ikev2_pld_delete(env, &pld, msg, offset, left);
251
7.54k
      break;
252
5.65k
    case IKEV2_PAYLOAD_TSi | IKED_E:
253
23.0k
    case IKEV2_PAYLOAD_TSr | IKED_E:
254
23.0k
      ret = ikev2_pld_tss(env, &pld, msg, offset, left);
255
23.0k
      break;
256
0
    case IKEV2_PAYLOAD_SK:
257
0
      ret = ikev2_pld_e(env, &pld, msg, offset, left);
258
0
      break;
259
0
    case IKEV2_PAYLOAD_SKF:
260
0
      ret = ikev2_pld_ef(env, &pld, msg, offset, left);
261
0
      break;
262
11.6k
    case IKEV2_PAYLOAD_CP | IKED_E:
263
11.6k
      ret = ikev2_pld_cp(env, &pld, msg, offset, left);
264
11.6k
      break;
265
21.2k
    case IKEV2_PAYLOAD_EAP | IKED_E:
266
21.2k
      ret = ikev2_pld_eap(env, &pld, msg, offset, left);
267
21.2k
      break;
268
72.4k
    default:
269
72.4k
      print_hex(msgbuf, offset,
270
72.4k
          betoh16(pld.pld_length) - sizeof(pld));
271
72.4k
      break;
272
279k
    }
273
274
279k
    if (ret != 0 && ikev2_msg_frompeer(msg)) {
275
748
      (void)ikev2_send_informational(env, msg);
276
748
      return (-1);
277
748
    }
278
279
    /* Encrypted payloads must appear last */
280
278k
    if ((payload == IKEV2_PAYLOAD_SK) ||
281
278k
        (payload == IKEV2_PAYLOAD_SKF))
282
4
      return (0);
283
284
278k
    payload = pld.pld_nextpayload;
285
278k
    offset += left;
286
278k
    total -= left;
287
278k
  }
288
289
3.06k
  return (0);
290
15.4k
}
291
292
int
293
ikev2_validate_sa(struct iked_message *msg, size_t offset, size_t left,
294
    struct ikev2_sa_proposal *sap)
295
37.6k
{
296
37.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
297
37.6k
  size_t     sap_length;
298
299
37.6k
  if (left < sizeof(*sap)) {
300
15.9k
    log_debug("%s: malformed payload: too short for header "
301
15.9k
        "(%zu < %zu)", __func__, left, sizeof(*sap));
302
15.9k
    return (-1);
303
15.9k
  }
304
21.6k
  memcpy(sap, msgbuf + offset, sizeof(*sap));
305
306
21.6k
  sap_length = betoh16(sap->sap_length);
307
21.6k
  if (sap_length < sizeof(*sap)) {
308
5.62k
    log_debug("%s: malformed payload: shorter than minimum header "
309
5.62k
        "size (%zu < %zu)", __func__, sap_length, sizeof(*sap));
310
5.62k
    return (-1);
311
5.62k
  }
312
16.0k
  if (left < sap_length) {
313
3.10k
    log_debug("%s: malformed payload: too long for actual payload "
314
3.10k
        "size (%zu < %zu)", __func__, left, sap_length);
315
3.10k
    return (-1);
316
3.10k
  }
317
  /*
318
   * If there is only one proposal, sap_length must be the
319
   * total payload size.
320
   */
321
12.9k
  if (!sap->sap_more && left != sap_length) {
322
30
    log_debug("%s: malformed payload: SA payload length mismatches "
323
30
        "single proposal substructure length (%zu != %zu)",
324
30
        __func__, left, sap_length);
325
30
    return (-1);
326
30
  }
327
  /*
328
   * If there are more than one proposal, there must be bytes
329
   * left in the payload.
330
   */
331
12.9k
  if (sap->sap_more && left <= sap_length) {
332
1.00k
    log_debug("%s: malformed payload: SA payload too small for "
333
1.00k
        "further proposals (%zu <= %zu)", __func__,
334
1.00k
        left, sap_length);
335
1.00k
    return (-1);
336
1.00k
  }
337
11.9k
  return (0);
338
12.9k
}
339
340
int
341
ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld,
342
    struct iked_message *msg, size_t offset, size_t left)
343
32.7k
{
344
32.7k
  struct ikev2_sa_proposal   sap;
345
32.7k
  struct iked_proposal    *prop = NULL;
346
32.7k
  uint32_t       spi32;
347
32.7k
  uint64_t       spi = 0, spi64;
348
32.7k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
349
32.7k
  int        r;
350
32.7k
  struct iked_proposals   *props;
351
32.7k
  size_t         total;
352
353
37.6k
  do {
354
37.6k
    if (ikev2_validate_sa(msg, offset, left, &sap))
355
25.6k
      return (-1);
356
357
    /* Assumed size of the first proposals, including SPI if present. */
358
11.9k
    total = (betoh16(sap.sap_length) - sizeof(sap));
359
360
11.9k
    props = &msg->msg_parent->msg_proposals;
361
362
11.9k
    offset += sizeof(sap);
363
11.9k
    left -= sizeof(sap);
364
365
11.9k
    if (sap.sap_spisize) {
366
1.66k
      if (left < sap.sap_spisize) {
367
758
        log_debug("%s: malformed payload: SPI larger than "
368
758
            "actual payload (%zu < %d)", __func__, left,
369
758
            sap.sap_spisize);
370
758
        return (-1);
371
758
      }
372
905
      if (total < sap.sap_spisize) {
373
183
        log_debug("%s: malformed payload: SPI larger than "
374
183
            "proposal (%zu < %d)", __func__, total,
375
183
            sap.sap_spisize);
376
183
        return (-1);
377
183
      }
378
722
      switch (sap.sap_spisize) {
379
356
      case 4:
380
356
        memcpy(&spi32, msgbuf + offset, 4);
381
356
        spi = betoh32(spi32);
382
356
        break;
383
236
      case 8:
384
236
        memcpy(&spi64, msgbuf + offset, 8);
385
236
        spi = betoh64(spi64);
386
236
        break;
387
130
      default:
388
130
        log_debug("%s: unsupported SPI size %d",
389
130
            __func__, sap.sap_spisize);
390
130
        return (-1);
391
722
      }
392
393
592
      offset += sap.sap_spisize;
394
592
      left -= sap.sap_spisize;
395
396
      /* Assumed size of the proposal, now without SPI. */
397
592
      total -= sap.sap_spisize;
398
592
    }
399
400
    /*
401
     * As we verified sanity of packet headers, this check will
402
     * be always false, but just to be sure we keep it.
403
     */
404
10.8k
    if (left < total) {
405
0
      log_debug("%s: malformed payload: too long for payload "
406
0
          "(%zu < %zu)", __func__, left, total);
407
0
      return (-1);
408
0
    }
409
410
10.8k
    log_debug("%s: more %d reserved %d length %d"
411
10.8k
        " proposal #%d protoid %s spisize %d xforms %d spi %s",
412
10.8k
        __func__, sap.sap_more, sap.sap_reserved,
413
10.8k
        betoh16(sap.sap_length), sap.sap_proposalnr,
414
10.8k
        print_map(sap.sap_protoid, ikev2_saproto_map), sap.sap_spisize,
415
10.8k
        sap.sap_transforms, print_spi(spi, sap.sap_spisize));
416
417
10.8k
    if (ikev2_msg_frompeer(msg)) {
418
69
      if ((msg->msg_parent->msg_prop = config_add_proposal(props,
419
69
          sap.sap_proposalnr, sap.sap_protoid)) == NULL) {
420
69
        log_debug("%s: invalid proposal", __func__);
421
69
        return (-1);
422
69
      }
423
0
      prop = msg->msg_parent->msg_prop;
424
0
      prop->prop_peerspi.spi = spi;
425
0
      prop->prop_peerspi.spi_protoid = sap.sap_protoid;
426
0
      prop->prop_peerspi.spi_size = sap.sap_spisize;
427
428
0
      prop->prop_localspi.spi_protoid = sap.sap_protoid;
429
0
      prop->prop_localspi.spi_size = sap.sap_spisize;
430
0
    }
431
432
    /*
433
     * Parse the attached transforms
434
     */
435
10.7k
    if (sap.sap_transforms) {
436
6.27k
      r = ikev2_pld_xform(env, msg, offset, total);
437
6.27k
      if ((r == -2) && ikev2_msg_frompeer(msg)) {
438
0
        log_debug("%s: invalid proposal transform",
439
0
            __func__);
440
441
        /* cleanup and ignore proposal */
442
0
        config_free_proposal(props, prop);
443
0
        prop = msg->msg_parent->msg_prop = NULL;
444
6.27k
      } else if (r != 0) {
445
5.04k
        log_debug("%s: invalid proposal transforms",
446
5.04k
            __func__);
447
5.04k
        return (-1);
448
5.04k
      }
449
6.27k
    }
450
451
5.74k
    offset += total;
452
5.74k
    left -= total;
453
5.74k
  } while (sap.sap_more);
454
455
846
  return (0);
456
32.7k
}
457
458
int
459
ikev2_validate_xform(struct iked_message *msg, size_t offset, size_t total,
460
    struct ikev2_transform *xfrm)
461
8.43k
{
462
8.43k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
463
8.43k
  size_t     xfrm_length;
464
465
8.43k
  if (total < sizeof(*xfrm)) {
466
772
    log_debug("%s: malformed payload: too short for header "
467
772
        "(%zu < %zu)", __func__, total, sizeof(*xfrm));
468
772
    return (-1);
469
772
  }
470
7.66k
  memcpy(xfrm, msgbuf + offset, sizeof(*xfrm));
471
472
7.66k
  xfrm_length = betoh16(xfrm->xfrm_length);
473
7.66k
  if (xfrm_length < sizeof(*xfrm)) {
474
1.14k
    log_debug("%s: malformed payload: shorter than minimum header "
475
1.14k
        "size (%zu < %zu)", __func__, xfrm_length, sizeof(*xfrm));
476
1.14k
    return (-1);
477
1.14k
  }
478
6.51k
  if (total < xfrm_length) {
479
706
    log_debug("%s: malformed payload: too long for payload size "
480
706
        "(%zu < %zu)", __func__, total, xfrm_length);
481
706
    return (-1);
482
706
  }
483
484
5.81k
  return (0);
485
6.51k
}
486
487
int
488
ikev2_pld_xform(struct iked *env, struct iked_message *msg,
489
    size_t offset, size_t total)
490
8.43k
{
491
8.43k
  struct ikev2_transform     xfrm;
492
8.43k
  char         id[BUFSIZ];
493
8.43k
  int        ret = 0;
494
8.43k
  int        r;
495
8.43k
  size_t         xfrm_length;
496
497
8.43k
  if (ikev2_validate_xform(msg, offset, total, &xfrm))
498
2.62k
    return (-1);
499
500
5.81k
  xfrm_length = betoh16(xfrm.xfrm_length);
501
502
5.81k
  switch (xfrm.xfrm_type) {
503
1.27k
  case IKEV2_XFORMTYPE_ENCR:
504
1.27k
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
505
1.27k
        ikev2_xformencr_map), sizeof(id));
506
1.27k
    break;
507
789
  case IKEV2_XFORMTYPE_PRF:
508
789
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
509
789
        ikev2_xformprf_map), sizeof(id));
510
789
    break;
511
174
  case IKEV2_XFORMTYPE_INTEGR:
512
174
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
513
174
        ikev2_xformauth_map), sizeof(id));
514
174
    break;
515
861
  case IKEV2_XFORMTYPE_DH:
516
861
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
517
861
        ikev2_xformdh_map), sizeof(id));
518
861
    break;
519
1.01k
  case IKEV2_XFORMTYPE_ESN:
520
1.01k
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
521
1.01k
        ikev2_xformesn_map), sizeof(id));
522
1.01k
    break;
523
1.69k
  default:
524
1.69k
    snprintf(id, sizeof(id), "<%d>", betoh16(xfrm.xfrm_id));
525
1.69k
    break;
526
5.81k
  }
527
528
5.81k
  log_debug("%s: more %d reserved %d length %zu"
529
5.81k
      " type %s id %s",
530
5.81k
      __func__, xfrm.xfrm_more, xfrm.xfrm_reserved, xfrm_length,
531
5.81k
      print_map(xfrm.xfrm_type, ikev2_xformtype_map), id);
532
533
  /*
534
   * Parse transform attributes, if available
535
   */
536
5.81k
  msg->msg_attrlength = 0;
537
5.81k
  if (xfrm_length > sizeof(xfrm)) {
538
2.77k
    if (ikev2_pld_attr(env, &xfrm, msg, offset + sizeof(xfrm),
539
2.77k
        xfrm_length - sizeof(xfrm)) != 0) {
540
2.17k
      return (-1);
541
2.17k
    }
542
2.77k
  }
543
544
3.63k
  if (ikev2_msg_frompeer(msg)) {
545
0
    r = config_add_transform(msg->msg_parent->msg_prop,
546
0
        xfrm.xfrm_type, betoh16(xfrm.xfrm_id),
547
0
        msg->msg_attrlength, msg->msg_attrlength);
548
0
    if (r == -1) {
549
0
      log_debug("%s: failed to add transform: alloc error",
550
0
          __func__);
551
0
      return (r);
552
0
    } else if (r == -2) {
553
0
      log_debug("%s: failed to add transform: unknown type",
554
0
          __func__);
555
0
      return (r);
556
0
    }
557
0
  }
558
559
  /* Next transform */
560
3.63k
  offset += xfrm_length;
561
3.63k
  total -= xfrm_length;
562
3.63k
  if (xfrm.xfrm_more == IKEV2_XFORM_MORE)
563
2.16k
    ret = ikev2_pld_xform(env, msg, offset, total);
564
1.46k
  else if (total != 0) {
565
    /* No more transforms but still some data left. */
566
245
    log_debug("%s: less data than specified, %zu bytes left",
567
245
        __func__, total);
568
245
    ret = -1;
569
245
  }
570
571
3.63k
  return (ret);
572
3.63k
}
573
574
int
575
ikev2_validate_attr(struct iked_message *msg, size_t offset, size_t total,
576
    struct ikev2_attribute *attr)
577
53.6k
{
578
53.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
579
580
53.6k
  if (total < sizeof(*attr)) {
581
1.04k
    log_debug("%s: malformed payload: too short for header "
582
1.04k
        "(%zu < %zu)", __func__, total, sizeof(*attr));
583
1.04k
    return (-1);
584
1.04k
  }
585
52.6k
  memcpy(attr, msgbuf + offset, sizeof(*attr));
586
587
52.6k
  return (0);
588
53.6k
}
589
590
int
591
ikev2_pld_attr(struct iked *env, struct ikev2_transform *xfrm,
592
    struct iked_message *msg, size_t offset, size_t total)
593
53.6k
{
594
53.6k
  struct ikev2_attribute     attr;
595
53.6k
  unsigned int       type;
596
53.6k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
597
53.6k
  int        ret = 0;
598
53.6k
  size_t         attr_length;
599
600
53.6k
  if (ikev2_validate_attr(msg, offset, total, &attr))
601
1.04k
    return (-1);
602
603
52.6k
  type = betoh16(attr.attr_type) & ~IKEV2_ATTRAF_TV;
604
605
52.6k
  log_debug("%s: attribute type %s length %d total %zu",
606
52.6k
      __func__, print_map(type, ikev2_attrtype_map),
607
52.6k
      betoh16(attr.attr_length), total);
608
609
52.6k
  if (betoh16(attr.attr_type) & IKEV2_ATTRAF_TV) {
610
    /* Type-Value attribute */
611
41.9k
    offset += sizeof(attr);
612
41.9k
    total -= sizeof(attr);
613
614
41.9k
    if (type == IKEV2_ATTRTYPE_KEY_LENGTH)
615
48
      msg->msg_attrlength = betoh16(attr.attr_length);
616
41.9k
  } else {
617
    /* Type-Length-Value attribute */
618
10.7k
    attr_length = betoh16(attr.attr_length);
619
10.7k
    if (attr_length < sizeof(attr)) {
620
605
      log_debug("%s: malformed payload: shorter than "
621
605
          "minimum header size (%zu < %zu)", __func__,
622
605
          attr_length, sizeof(attr));
623
605
      return (-1);
624
605
    }
625
10.1k
    if (total < attr_length) {
626
529
      log_debug("%s: malformed payload: attribute larger "
627
529
          "than actual payload (%zu < %zu)", __func__,
628
529
          total, attr_length);
629
529
      return (-1);
630
529
    }
631
9.57k
    print_hex(msgbuf, offset + sizeof(attr),
632
9.57k
        attr_length - sizeof(attr));
633
9.57k
    offset += attr_length;
634
9.57k
    total -= attr_length;
635
9.57k
  }
636
637
51.4k
  if (total > 0) {
638
    /* Next attribute */
639
50.9k
    ret = ikev2_pld_attr(env, xfrm, msg, offset, total);
640
50.9k
  }
641
642
51.4k
  return (ret);
643
52.6k
}
644
645
int
646
ikev2_validate_ke(struct iked_message *msg, size_t offset, size_t left,
647
    struct ikev2_keyexchange *kex)
648
10.9k
{
649
10.9k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
650
651
10.9k
  if (left < sizeof(*kex)) {
652
6.72k
    log_debug("%s: malformed payload: too short for header "
653
6.72k
        "(%zu < %zu)", __func__, left, sizeof(*kex));
654
6.72k
    return (-1);
655
6.72k
  }
656
4.22k
  memcpy(kex, msgbuf + offset, sizeof(*kex));
657
658
4.22k
  return (0);
659
10.9k
}
660
661
int
662
ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld,
663
    struct iked_message *msg, size_t offset, size_t left)
664
10.9k
{
665
10.9k
  struct ikev2_keyexchange   kex;
666
10.9k
  uint8_t       *buf;
667
10.9k
  size_t         len;
668
10.9k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
669
670
10.9k
  if (ikev2_validate_ke(msg, offset, left, &kex))
671
6.72k
    return (-1);
672
673
4.22k
  log_debug("%s: dh group %s reserved %d", __func__,
674
4.22k
      print_map(betoh16(kex.kex_dhgroup), ikev2_xformdh_map),
675
4.22k
      betoh16(kex.kex_reserved));
676
677
4.22k
  buf = msgbuf + offset + sizeof(kex);
678
4.22k
  len = left - sizeof(kex);
679
680
4.22k
  if (len == 0) {
681
2.08k
    log_debug("%s: malformed payload: no KE data given", __func__);
682
2.08k
    return (-1);
683
2.08k
  }
684
685
2.14k
  print_hex(buf, 0, len);
686
687
2.14k
  if (ikev2_msg_frompeer(msg)) {
688
27
    if (msg->msg_parent->msg_ke != NULL) {
689
4
      log_info("%s: duplicate KE payload", __func__);
690
4
      return (-1);
691
4
    }
692
23
    if ((msg->msg_parent->msg_ke = ibuf_new(buf, len)) == NULL) {
693
0
      log_debug("%s: failed to get exchange", __func__);
694
0
      return (-1);
695
0
    }
696
23
    msg->msg_parent->msg_dhgroup = betoh16(kex.kex_dhgroup);
697
23
  }
698
699
2.13k
  return (0);
700
2.14k
}
701
702
int
703
ikev2_validate_id(struct iked_message *msg, size_t offset, size_t left,
704
    struct ikev2_id *id)
705
23.7k
{
706
23.7k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
707
708
23.7k
  if (left < sizeof(*id)) {
709
9.33k
    log_debug("%s: malformed payload: too short for header "
710
9.33k
        "(%zu < %zu)", __func__, left, sizeof(*id));
711
9.33k
    return (-1);
712
9.33k
  }
713
14.3k
  memcpy(id, msgbuf + offset, sizeof(*id));
714
715
14.3k
  if (id->id_type == IKEV2_ID_NONE) {
716
6.62k
    log_debug("%s: malformed payload: invalid ID type.",
717
6.62k
        __func__);
718
6.62k
    return (-1);
719
6.62k
  }
720
721
7.77k
  return (0);
722
14.3k
}
723
724
int
725
ikev2_pld_id(struct iked *env, struct ikev2_payload *pld,
726
    struct iked_message *msg, size_t offset, size_t left, unsigned int payload)
727
23.7k
{
728
23.7k
  uint8_t       *ptr;
729
23.7k
  struct ikev2_id      id;
730
23.7k
  size_t         len;
731
23.7k
  struct iked_id      *idp, idb;
732
23.7k
  const struct iked_sa    *sa = msg->msg_sa;
733
23.7k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
734
23.7k
  char         idstr[IKED_ID_SIZE];
735
736
23.7k
  if (ikev2_validate_id(msg, offset, left, &id))
737
15.9k
    return (-1);
738
739
7.77k
  bzero(&idb, sizeof(idb));
740
741
  /* Don't strip the Id payload header */
742
7.77k
  ptr = msgbuf + offset;
743
7.77k
  len = left;
744
745
7.77k
  idb.id_type = id.id_type;
746
7.77k
  idb.id_offset = sizeof(id);
747
7.77k
  if ((idb.id_buf = ibuf_new(ptr, len)) == NULL)
748
0
    return (-1);
749
750
7.77k
  if (ikev2_print_id(&idb, idstr, sizeof(idstr)) == -1) {
751
0
    ibuf_free(idb.id_buf);
752
0
    log_debug("%s: malformed id", __func__);
753
0
    return (-1);
754
0
  }
755
756
7.77k
  log_debug("%s: id %s length %zu", __func__, idstr, len);
757
758
7.77k
  if (!ikev2_msg_frompeer(msg)) {
759
7.61k
    ibuf_free(idb.id_buf);
760
7.61k
    return (0);
761
7.61k
  }
762
763
157
  if (((sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr) ||
764
157
      (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDi)))
765
77
    idp = &msg->msg_parent->msg_peerid;
766
80
  else if (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr)
767
80
    idp = &msg->msg_parent->msg_localid;
768
0
  else {
769
0
    ibuf_free(idb.id_buf);
770
0
    log_debug("%s: unexpected id payload", __func__);
771
0
    return (0);
772
0
  }
773
774
157
  if (idp->id_type) {
775
33
    ibuf_free(idb.id_buf);
776
33
    log_debug("%s: duplicate id payload", __func__);
777
33
    return (-1);
778
33
  }
779
780
124
  idp->id_buf = idb.id_buf;
781
124
  idp->id_offset = idb.id_offset;
782
124
  idp->id_type = idb.id_type;
783
784
124
  return (0);
785
157
}
786
787
int
788
ikev2_validate_cert(struct iked_message *msg, size_t offset, size_t left,
789
    struct ikev2_cert *cert)
790
6.90k
{
791
6.90k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
792
793
6.90k
  if (left < sizeof(*cert)) {
794
1.53k
    log_debug("%s: malformed payload: too short for header "
795
1.53k
        "(%zu < %zu)", __func__, left, sizeof(*cert));
796
1.53k
    return (-1);
797
1.53k
  }
798
5.37k
  memcpy(cert, msgbuf + offset, sizeof(*cert));
799
5.37k
  if (cert->cert_type == IKEV2_CERT_NONE) {
800
1.03k
    log_debug("%s: malformed payload: invalid cert type", __func__);
801
1.03k
    return (-1);
802
1.03k
  }
803
804
4.33k
  return (0);
805
5.37k
}
806
807
int
808
ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld,
809
    struct iked_message *msg, size_t offset, size_t left)
810
6.90k
{
811
6.90k
  struct ikev2_cert    cert;
812
6.90k
  uint8_t       *buf;
813
6.90k
  size_t         len;
814
6.90k
  struct iked_id      *certid;
815
6.90k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
816
6.90k
  const struct iked_sa    *sa = msg->msg_sa;
817
6.90k
  int        i;
818
819
6.90k
  if (ikev2_validate_cert(msg, offset, left, &cert))
820
2.56k
    return (-1);
821
4.33k
  offset += sizeof(cert);
822
823
4.33k
  buf = msgbuf + offset;
824
4.33k
  len = left - sizeof(cert);
825
826
4.33k
  log_debug("%s: type %s length %zu",
827
4.33k
      __func__, print_map(cert.cert_type, ikev2_cert_map), len);
828
829
4.33k
  print_hex(buf, 0, len);
830
831
4.33k
  if (!ikev2_msg_frompeer(msg))
832
1.54k
    return (0);
833
834
  /* do not accept internal encoding in the wire */
835
2.78k
  if (cert.cert_type == IKEV2_CERT_BUNDLE) {
836
290
    log_debug("%s: ignoring IKEV2_CERT_BUNDLE",
837
290
       SPI_SA(sa, __func__));
838
290
    return (0);
839
290
  }
840
841
2.49k
  certid = &msg->msg_parent->msg_cert;
842
2.49k
  if (certid->id_type) {
843
    /* try to set supplemental certs */
844
6.88k
    for (i = 0; i < IKED_SCERT_MAX; i++) {
845
5.52k
      certid = &msg->msg_parent->msg_scert[i];
846
5.52k
      if (!certid->id_type)
847
778
        break;
848
5.52k
    }
849
2.13k
    if (certid->id_type) {
850
1.35k
      log_debug("%s: too many cert payloads, ignoring",
851
1.35k
         SPI_SA(sa, __func__));
852
1.35k
      return (0);
853
1.35k
    }
854
2.13k
  }
855
856
1.14k
  if ((certid->id_buf = ibuf_new(buf, len)) == NULL) {
857
0
    log_debug("%s: failed to save cert", __func__);
858
0
    return (-1);
859
0
  }
860
1.14k
  certid->id_type = cert.cert_type;
861
1.14k
  certid->id_offset = 0;
862
863
1.14k
  return (0);
864
1.14k
}
865
866
int
867
ikev2_validate_certreq(struct iked_message *msg, size_t offset, size_t left,
868
    struct ikev2_cert *cert)
869
15.4k
{
870
15.4k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
871
872
15.4k
  if (left < sizeof(*cert)) {
873
3.58k
    log_debug("%s: malformed payload: too short for header "
874
3.58k
        "(%zu < %zu)", __func__, left, sizeof(*cert));
875
3.58k
    return (-1);
876
3.58k
  }
877
11.8k
  memcpy(cert, msgbuf + offset, sizeof(*cert));
878
879
11.8k
  return (0);
880
15.4k
}
881
882
int
883
ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld,
884
    struct iked_message *msg, size_t offset, size_t left)
885
15.4k
{
886
15.4k
  struct ikev2_cert    cert;
887
15.4k
  struct iked_certreq   *cr;
888
15.4k
  uint8_t       *buf;
889
15.4k
  ssize_t        len;
890
15.4k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
891
892
15.4k
  if (ikev2_validate_certreq(msg, offset, left, &cert))
893
3.58k
    return (-1);
894
11.8k
  offset += sizeof(cert);
895
896
11.8k
  buf = msgbuf + offset;
897
11.8k
  len = left - sizeof(cert);
898
899
11.8k
  log_debug("%s: type %s length %zd",
900
11.8k
      __func__, print_map(cert.cert_type, ikev2_cert_map), len);
901
902
11.8k
  print_hex(buf, 0, len);
903
904
11.8k
  if (!ikev2_msg_frompeer(msg))
905
10.4k
    return (0);
906
907
1.34k
  if (cert.cert_type == IKEV2_CERT_X509_CERT) {
908
330
    if (len == 0) {
909
288
      log_info("%s: invalid length 0", __func__);
910
288
      return (0);
911
288
    }
912
42
    if ((len % SHA_DIGEST_LENGTH) != 0) {
913
9
      log_info("%s: invalid certificate request",
914
9
          __func__);
915
9
      return (-1);
916
9
    }
917
42
  }
918
919
1.04k
  if ((cr = calloc(1, sizeof(struct iked_certreq))) == NULL) {
920
0
    log_info("%s: failed to allocate certreq.", __func__);
921
0
    return (-1);
922
0
  }
923
1.04k
  if ((cr->cr_data = ibuf_new(buf, len)) == NULL) {
924
0
    log_info("%s: failed to allocate buffer.", __func__);
925
0
    free(cr);
926
0
    return (-1);
927
0
  }
928
1.04k
  cr->cr_type = cert.cert_type;
929
1.04k
  SIMPLEQ_INSERT_TAIL(&msg->msg_parent->msg_certreqs, cr, cr_entry);
930
931
1.04k
  return (0);
932
1.04k
}
933
934
int
935
ikev2_validate_auth(struct iked_message *msg, size_t offset, size_t left,
936
    struct ikev2_auth *auth)
937
10.5k
{
938
10.5k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
939
940
10.5k
  if (left < sizeof(*auth)) {
941
2.04k
    log_debug("%s: malformed payload: too short for header "
942
2.04k
        "(%zu < %zu)", __func__, left, sizeof(*auth));
943
2.04k
    return (-1);
944
2.04k
  }
945
8.50k
  memcpy(auth, msgbuf + offset, sizeof(*auth));
946
947
8.50k
  if (auth->auth_method == 0) {
948
4.72k
    log_info("%s: malformed payload: invalid auth method",
949
4.72k
        __func__);
950
4.72k
    return (-1);
951
4.72k
  }
952
953
3.78k
  return (0);
954
8.50k
}
955
956
int
957
ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld,
958
    struct iked_message *msg, size_t offset, size_t left)
959
10.5k
{
960
10.5k
  struct ikev2_auth    auth;
961
10.5k
  struct iked_id      *idp;
962
10.5k
  uint8_t       *buf;
963
10.5k
  size_t         len;
964
10.5k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
965
966
10.5k
  if (ikev2_validate_auth(msg, offset, left, &auth))
967
6.76k
    return (-1);
968
3.78k
  offset += sizeof(auth);
969
970
3.78k
  buf = msgbuf + offset;
971
3.78k
  len = left - sizeof(auth);
972
973
3.78k
  log_debug("%s: method %s length %zu",
974
3.78k
      __func__, print_map(auth.auth_method, ikev2_auth_map), len);
975
976
3.78k
  print_hex(buf, 0, len);
977
978
3.78k
  if (!ikev2_msg_frompeer(msg))
979
3.74k
    return (0);
980
981
42
  idp = &msg->msg_parent->msg_auth;
982
42
  if (idp->id_type) {
983
1
    log_debug("%s: duplicate auth payload", __func__);
984
1
    return (-1);
985
1
  }
986
987
41
  ibuf_free(idp->id_buf);
988
41
  idp->id_type = auth.auth_method;
989
41
  idp->id_offset = 0;
990
41
  if ((idp->id_buf = ibuf_new(buf, len)) == NULL)
991
0
    return (-1);
992
993
41
  return (0);
994
41
}
995
996
int
997
ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld,
998
    struct iked_message *msg, size_t offset, size_t left)
999
3.51k
{
1000
3.51k
  size_t     len;
1001
3.51k
  uint8_t   *buf;
1002
3.51k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1003
1004
3.51k
  buf = msgbuf + offset;
1005
3.51k
  len = left;
1006
1007
3.51k
  if (len == 0) {
1008
3.21k
    log_debug("%s: malformed payload: no NONCE given", __func__);
1009
3.21k
    return (-1);
1010
3.21k
  }
1011
1012
298
  print_hex(buf, 0, len);
1013
1014
298
  if (ikev2_msg_frompeer(msg)) {
1015
62
    if (msg->msg_parent->msg_nonce != NULL) {
1016
19
      log_info("%s: duplicate NONCE payload", __func__);
1017
19
      return (-1);
1018
19
    }
1019
43
    if ((msg->msg_nonce = ibuf_new(buf, len)) == NULL) {
1020
0
      log_debug("%s: failed to get peer nonce", __func__);
1021
0
      return (-1);
1022
0
    }
1023
43
    msg->msg_parent->msg_nonce = msg->msg_nonce;
1024
43
  }
1025
1026
279
  return (0);
1027
298
}
1028
1029
int
1030
ikev2_validate_notify(struct iked_message *msg, size_t offset, size_t left,
1031
    struct ikev2_notify *n)
1032
39.8k
{
1033
39.8k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1034
1035
39.8k
  if (left < sizeof(*n)) {
1036
5.32k
    log_debug("%s: malformed payload: too short for header "
1037
5.32k
        "(%zu < %zu)", __func__, left, sizeof(*n));
1038
5.32k
    return (-1);
1039
5.32k
  }
1040
34.4k
  memcpy(n, msgbuf + offset, sizeof(*n));
1041
1042
34.4k
  return (0);
1043
39.8k
}
1044
1045
int
1046
ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld,
1047
    struct iked_message *msg, size_t offset, size_t left)
1048
39.8k
{
1049
39.8k
  struct ikev2_notify  n;
1050
39.8k
  const struct iked_sa  *sa = msg->msg_sa;
1051
39.8k
  uint8_t     *buf, md[SHA_DIGEST_LENGTH];
1052
39.8k
  uint32_t     spi32;
1053
39.8k
  uint64_t     spi64;
1054
39.8k
  struct iked_spi   *rekey;
1055
39.8k
  uint16_t     type;
1056
39.8k
  uint16_t     signature_hash;
1057
1058
39.8k
  if (ikev2_validate_notify(msg, offset, left, &n))
1059
5.32k
    return (-1);
1060
34.4k
  type = betoh16(n.n_type);
1061
1062
34.4k
  log_debug("%s: protoid %s spisize %d type %s",
1063
34.4k
      __func__,
1064
34.4k
      print_map(n.n_protoid, ikev2_saproto_map), n.n_spisize,
1065
34.4k
      print_map(type, ikev2_n_map));
1066
1067
34.4k
  left -= sizeof(n);
1068
34.4k
  if ((buf = ibuf_seek(msg->msg_data, offset + sizeof(n), left)) == NULL)
1069
0
    return (-1);
1070
1071
34.4k
  print_hex(buf, 0, left);
1072
1073
34.4k
  if (!ikev2_msg_frompeer(msg))
1074
2.00k
    return (0);
1075
1076
32.4k
  switch (type) {
1077
3.34k
  case IKEV2_N_NAT_DETECTION_SOURCE_IP:
1078
26.0k
  case IKEV2_N_NAT_DETECTION_DESTINATION_IP:
1079
26.0k
    if (left != sizeof(md)) {
1080
17
      log_debug("%s: malformed payload: hash size mismatch"
1081
17
          " (%zu != %zu)", __func__, left, sizeof(md));
1082
17
      return (-1);
1083
17
    }
1084
26.0k
    if (ikev2_nat_detection(env, msg, md, sizeof(md), type,
1085
26.0k
        ikev2_msg_frompeer(msg)) == -1)
1086
0
      return (-1);
1087
26.0k
    if (memcmp(buf, md, left) != 0) {
1088
25.8k
      log_debug("%s: %s detected NAT", __func__,
1089
25.8k
          print_map(type, ikev2_n_map));
1090
25.8k
      if (type == IKEV2_N_NAT_DETECTION_SOURCE_IP)
1091
3.34k
        msg->msg_parent->msg_nat_detected
1092
3.34k
            |= IKED_MSG_NAT_SRC_IP;
1093
22.4k
      else
1094
22.4k
        msg->msg_parent->msg_nat_detected
1095
22.4k
            |= IKED_MSG_NAT_DST_IP;
1096
25.8k
    }
1097
26.0k
    print_hex(md, 0, sizeof(md));
1098
    /* remember for MOBIKE */
1099
26.0k
    msg->msg_parent->msg_natt_rcvd = 1;
1100
26.0k
    break;
1101
6
  case IKEV2_N_AUTHENTICATION_FAILED:
1102
6
    if (!msg->msg_e) {
1103
0
      log_debug("%s: AUTHENTICATION_FAILED not encrypted",
1104
0
          __func__);
1105
0
      return (-1);
1106
0
    }
1107
    /*
1108
     * If we are the responder, then we only accept
1109
     * AUTHENTICATION_FAILED from authenticated peers.
1110
     * If we are the initiator, the peer cannot be authenticated.
1111
     */
1112
6
    if (!sa->sa_hdr.sh_initiator) {
1113
6
      if (!sa_stateok(sa, IKEV2_STATE_VALID)) {
1114
6
        log_debug("%s: ignoring AUTHENTICATION_FAILED"
1115
6
            " from unauthenticated initiator",
1116
6
            __func__);
1117
6
        return (-1);
1118
6
      }
1119
6
    } else {
1120
0
      if (sa_stateok(sa, IKEV2_STATE_VALID)) {
1121
0
        log_debug("%s: ignoring AUTHENTICATION_FAILED"
1122
0
            " from authenticated responder",
1123
0
            __func__);
1124
0
        return (-1);
1125
0
      }
1126
0
    }
1127
0
    msg->msg_parent->msg_flags
1128
0
        |= IKED_MSG_FLAGS_AUTHENTICATION_FAILED;
1129
0
    break;
1130
143
  case IKEV2_N_INVALID_KE_PAYLOAD:
1131
143
    if (sa_stateok(sa, IKEV2_STATE_VALID) &&
1132
143
        !msg->msg_e) {
1133
0
      log_debug("%s: INVALID_KE_PAYLOAD not encrypted",
1134
0
          __func__);
1135
0
      return (-1);
1136
0
    }
1137
143
    if (left != sizeof(msg->msg_parent->msg_group)) {
1138
4
      log_debug("%s: malformed payload: group size mismatch"
1139
4
          " (%zu != %zu)", __func__, left,
1140
4
          sizeof(msg->msg_parent->msg_group));
1141
4
      return (-1);
1142
4
    }
1143
139
    memcpy(&msg->msg_parent->msg_group, buf, left);
1144
139
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_INVALID_KE;
1145
139
    break;
1146
273
  case IKEV2_N_NO_ADDITIONAL_SAS:
1147
273
    if (!msg->msg_e) {
1148
0
      log_debug("%s: NO_ADDITIONAL_SAS not encrypted",
1149
0
          __func__);
1150
0
      return (-1);
1151
0
    }
1152
273
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_NO_ADDITIONAL_SAS;
1153
273
    break;
1154
82
  case IKEV2_N_REKEY_SA:
1155
82
    if (!msg->msg_e) {
1156
0
      log_debug("%s: N_REKEY_SA not encrypted", __func__);
1157
0
      return (-1);
1158
0
    }
1159
82
    if (left != n.n_spisize) {
1160
5
      log_debug("%s: malformed notification", __func__);
1161
5
      return (-1);
1162
5
    }
1163
77
    rekey = &msg->msg_parent->msg_rekey;
1164
77
    if (rekey->spi != 0) {
1165
5
      log_debug("%s: rekeying of multiple SAs not supported",
1166
5
          __func__);
1167
5
      return (-1);
1168
5
    }
1169
72
    switch (n.n_spisize) {
1170
65
    case 4:
1171
65
      memcpy(&spi32, buf, left);
1172
65
      rekey->spi = betoh32(spi32);
1173
65
      break;
1174
4
    case 8:
1175
4
      memcpy(&spi64, buf, left);
1176
4
      rekey->spi = betoh64(spi64);
1177
4
      break;
1178
3
    default:
1179
3
      log_debug("%s: invalid spi size %d", __func__,
1180
3
          n.n_spisize);
1181
3
      return (-1);
1182
72
    }
1183
69
    rekey->spi_size = n.n_spisize;
1184
69
    rekey->spi_protoid = n.n_protoid;
1185
1186
69
    log_debug("%s: rekey %s spi %s", __func__,
1187
69
        print_map(n.n_protoid, ikev2_saproto_map),
1188
69
        print_spi(rekey->spi, n.n_spisize));
1189
69
    break;
1190
354
  case IKEV2_N_TEMPORARY_FAILURE:
1191
354
    if (!msg->msg_e) {
1192
0
      log_debug("%s: IKEV2_N_TEMPORARY_FAILURE not encrypted",
1193
0
          __func__);
1194
0
      return (-1);
1195
0
    }
1196
354
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_TEMPORARY_FAILURE;
1197
354
    break;
1198
255
  case IKEV2_N_IPCOMP_SUPPORTED:
1199
255
    if (!msg->msg_e) {
1200
0
      log_debug("%s: N_IPCOMP_SUPPORTED not encrypted",
1201
0
          __func__);
1202
0
      return (-1);
1203
0
    }
1204
255
    if (left < sizeof(msg->msg_parent->msg_cpi) +
1205
255
        sizeof(msg->msg_parent->msg_transform)) {
1206
127
      log_debug("%s: ignoring malformed ipcomp notification",
1207
127
          __func__);
1208
127
      return (0);
1209
127
    }
1210
128
    memcpy(&msg->msg_parent->msg_cpi, buf,
1211
128
        sizeof(msg->msg_parent->msg_cpi));
1212
128
    memcpy(&msg->msg_parent->msg_transform,
1213
128
        buf + sizeof(msg->msg_parent->msg_cpi),
1214
128
        sizeof(msg->msg_parent->msg_transform));
1215
1216
128
    log_debug("%s: %s cpi 0x%x, transform %s, length %zu", __func__,
1217
128
        msg->msg_parent->msg_response ? "res" : "req",
1218
128
        betoh16(msg->msg_parent->msg_cpi),
1219
128
        print_map(msg->msg_parent->msg_transform,
1220
128
        ikev2_ipcomp_map), left);
1221
1222
128
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_IPCOMP_SUPPORTED;
1223
128
    break;
1224
73
  case IKEV2_N_CHILD_SA_NOT_FOUND:
1225
73
    if (!msg->msg_e) {
1226
0
      log_debug("%s: N_CHILD_SA_NOT_FOUND not encrypted",
1227
0
          __func__);
1228
0
      return (-1);
1229
0
    }
1230
73
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_CHILD_SA_NOT_FOUND;
1231
73
    break;
1232
36
  case IKEV2_N_NO_PROPOSAL_CHOSEN:
1233
36
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN;
1234
36
    break;
1235
1.81k
  case IKEV2_N_MOBIKE_SUPPORTED:
1236
1.81k
    if (!msg->msg_e) {
1237
0
      log_debug("%s: N_MOBIKE_SUPPORTED not encrypted",
1238
0
          __func__);
1239
0
      return (-1);
1240
0
    }
1241
1.81k
    if (left != 0) {
1242
1.65k
      log_debug("%s: ignoring malformed mobike"
1243
1.65k
          " notification: %zu", __func__, left);
1244
1.65k
      return (0);
1245
1.65k
    }
1246
159
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_MOBIKE;
1247
159
    break;
1248
356
  case IKEV2_N_USE_TRANSPORT_MODE:
1249
356
    if (!msg->msg_e) {
1250
0
      log_debug("%s: N_USE_TRANSPORT_MODE not encrypted",
1251
0
          __func__);
1252
0
      return (-1);
1253
0
    }
1254
356
    if (left != 0) {
1255
77
      log_debug("%s: ignoring malformed transport mode"
1256
77
          " notification: %zu", __func__, left);
1257
77
      return (0);
1258
77
    }
1259
279
    if (msg->msg_parent->msg_response) {
1260
0
      if (!(msg->msg_policy->pol_flags & IKED_POLICY_TRANSPORT)) {
1261
0
        log_debug("%s: ignoring transport mode"
1262
0
            " notification (policy)", __func__);
1263
0
        return (0);
1264
0
      }
1265
0
    }
1266
279
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_USE_TRANSPORT;
1267
279
    break;
1268
388
  case IKEV2_N_UPDATE_SA_ADDRESSES:
1269
388
    if (!msg->msg_e) {
1270
0
      log_debug("%s: N_UPDATE_SA_ADDRESSES not encrypted",
1271
0
          __func__);
1272
0
      return (-1);
1273
0
    }
1274
388
    if (!sa->sa_mobike) {
1275
388
      log_debug("%s: ignoring update sa addresses"
1276
388
          " notification w/o mobike: %zu", __func__, left);
1277
388
      return (0);
1278
388
    }
1279
0
    if (left != 0) {
1280
0
      log_debug("%s: ignoring malformed update sa addresses"
1281
0
          " notification: %zu", __func__, left);
1282
0
      return (0);
1283
0
    }
1284
0
    msg->msg_parent->msg_update_sa_addresses = 1;
1285
0
    break;
1286
242
  case IKEV2_N_COOKIE2:
1287
242
    if (!msg->msg_e) {
1288
0
      log_debug("%s: N_COOKIE2 not encrypted",
1289
0
          __func__);
1290
0
      return (-1);
1291
0
    }
1292
242
    if (!sa->sa_mobike) {
1293
242
      log_debug("%s: ignoring cookie2 notification"
1294
242
          " w/o mobike: %zu", __func__, left);
1295
242
      return (0);
1296
242
    }
1297
0
    if (left < IKED_COOKIE2_MIN || left > IKED_COOKIE2_MAX) {
1298
0
      log_debug("%s: ignoring malformed cookie2"
1299
0
          " notification: %zu", __func__, left);
1300
0
      return (0);
1301
0
    }
1302
0
    ibuf_free(msg->msg_cookie2);  /* should not happen */
1303
0
    if ((msg->msg_cookie2 = ibuf_new(buf, left)) == NULL) {
1304
0
      log_debug("%s: failed to get peer cookie2", __func__);
1305
0
      return (-1);
1306
0
    }
1307
0
    msg->msg_parent->msg_cookie2 = msg->msg_cookie2;
1308
0
    break;
1309
2
  case IKEV2_N_COOKIE:
1310
2
    if (msg->msg_e) {
1311
2
      log_debug("%s: N_COOKIE encrypted",
1312
2
          __func__);
1313
2
      return (-1);
1314
2
    }
1315
0
    if (left < IKED_COOKIE_MIN || left > IKED_COOKIE_MAX) {
1316
0
      log_debug("%s: ignoring malformed cookie"
1317
0
          " notification: %zu", __func__, left);
1318
0
      return (0);
1319
0
    }
1320
0
    log_debug("%s: received cookie, len %zu", __func__, left);
1321
0
    print_hex(buf, 0, left);
1322
1323
0
    ibuf_free(msg->msg_cookie);
1324
0
    if ((msg->msg_cookie = ibuf_new(buf, left)) == NULL) {
1325
0
      log_debug("%s: failed to get peer cookie", __func__);
1326
0
      return (-1);
1327
0
    }
1328
0
    msg->msg_parent->msg_cookie = msg->msg_cookie;
1329
0
    break;
1330
14
  case IKEV2_N_FRAGMENTATION_SUPPORTED:
1331
14
    if (msg->msg_e) {
1332
14
      log_debug("%s: N_FRAGMENTATION_SUPPORTED encrypted",
1333
14
          __func__);
1334
14
      return (-1);
1335
14
    }
1336
0
    if (left != 0) {
1337
0
      log_debug("%s: ignoring malformed fragmentation"
1338
0
          " notification: %zu", __func__, left);
1339
0
      return (0);
1340
0
    }
1341
0
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_FRAGMENTATION;
1342
0
    break;
1343
7
  case IKEV2_N_SIGNATURE_HASH_ALGORITHMS:
1344
7
    if (msg->msg_e) {
1345
7
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: encrypted",
1346
7
          __func__);
1347
7
      return (-1);
1348
7
    }
1349
0
    if (sa == NULL) {
1350
0
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: no SA",
1351
0
          __func__);
1352
0
      return (-1);
1353
0
    }
1354
0
    if (sa->sa_sigsha2) {
1355
0
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: "
1356
0
          "duplicate notify", __func__);
1357
0
      return (0);
1358
0
    }
1359
0
    if (left < sizeof(signature_hash) ||
1360
0
        left % sizeof(signature_hash)) {
1361
0
      log_debug("%s: malformed signature hash notification"
1362
0
          "(%zu bytes)", __func__, left);
1363
0
      return (0);
1364
0
    }
1365
0
    while (left >= sizeof(signature_hash)) {
1366
0
      memcpy(&signature_hash, buf, sizeof(signature_hash));
1367
0
      signature_hash = betoh16(signature_hash);
1368
0
      log_debug("%s: signature hash %s (%x)", __func__,
1369
0
          print_map(signature_hash, ikev2_sighash_map),
1370
0
          signature_hash);
1371
0
      left -= sizeof(signature_hash);
1372
0
      buf += sizeof(signature_hash);
1373
0
      if (signature_hash == IKEV2_SIGHASH_SHA2_256)
1374
0
        msg->msg_parent->msg_flags
1375
0
            |= IKED_MSG_FLAGS_SIGSHA2;
1376
0
    }
1377
0
    break;
1378
32.4k
  }
1379
1380
29.9k
  return (0);
1381
32.4k
}
1382
1383
int
1384
ikev2_validate_delete(struct iked_message *msg, size_t offset, size_t left,
1385
    struct ikev2_delete *del)
1386
7.54k
{
1387
7.54k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1388
1389
7.54k
  if (left < sizeof(*del)) {
1390
1.53k
    log_debug("%s: malformed payload: too short for header "
1391
1.53k
        "(%zu < %zu)", __func__, left, sizeof(*del));
1392
1.53k
    return (-1);
1393
1.53k
  }
1394
6.01k
  memcpy(del, msgbuf + offset, sizeof(*del));
1395
1396
6.01k
  if (del->del_protoid == 0) {
1397
84
    log_info("%s: malformed payload: invalid protoid", __func__);
1398
84
    return (-1);
1399
84
  }
1400
1401
5.92k
  return (0);
1402
6.01k
}
1403
1404
int
1405
ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld,
1406
    struct iked_message *msg, size_t offset, size_t left)
1407
7.54k
{
1408
7.54k
  struct ikev2_delete  del;
1409
7.54k
  uint8_t     *buf, *msgbuf = ibuf_data(msg->msg_data);
1410
7.54k
  size_t       cnt, sz, len;
1411
1412
7.54k
  if (ikev2_validate_delete(msg, offset, left, &del))
1413
1.62k
    return (-1);
1414
1415
  /* Skip if it's a response, then we don't have to deal with it */
1416
5.92k
  if (ikev2_msg_frompeer(msg) &&
1417
5.92k
      msg->msg_parent->msg_response)
1418
0
    return (0);
1419
1420
5.92k
  cnt = betoh16(del.del_nspi);
1421
5.92k
  sz = del.del_spisize;
1422
1423
5.92k
  log_debug("%s: proto %s spisize %zu nspi %zu",
1424
5.92k
      __func__, print_map(del.del_protoid, ikev2_saproto_map),
1425
5.92k
      sz, cnt);
1426
1427
5.92k
  if (msg->msg_parent->msg_del_protoid) {
1428
5.54k
    log_debug("%s: duplicate delete payload", __func__);
1429
5.54k
    return (0);
1430
5.54k
  }
1431
1432
380
  msg->msg_parent->msg_del_protoid = del.del_protoid;
1433
380
  msg->msg_parent->msg_del_cnt = cnt;
1434
380
  msg->msg_parent->msg_del_spisize = sz;
1435
1436
380
  buf = msgbuf + offset + sizeof(del);
1437
380
  len = left - sizeof(del);
1438
380
  if (len == 0 || sz == 0 || cnt == 0)
1439
357
    return (0);
1440
1441
23
  if ((len / sz) != cnt) {
1442
21
    log_debug("%s: invalid payload length %zu/%zu != %zu",
1443
21
        __func__, len, sz, cnt);
1444
21
    return (-1);
1445
21
  }
1446
1447
2
  print_hex(buf, 0, len);
1448
1449
2
  msg->msg_parent->msg_del_buf = ibuf_new(buf, len);
1450
1451
2
  return (0);
1452
23
}
1453
1454
int
1455
ikev2_validate_tss(struct iked_message *msg, size_t offset, size_t left,
1456
    struct ikev2_tsp *tsp)
1457
23.0k
{
1458
23.0k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1459
1460
23.0k
  if (left < sizeof(*tsp)) {
1461
2.69k
    log_debug("%s: malformed payload: too short for header "
1462
2.69k
        "(%zu < %zu)", __func__, left, sizeof(*tsp));
1463
2.69k
    return (-1);
1464
2.69k
  }
1465
20.4k
  memcpy(tsp, msgbuf + offset, sizeof(*tsp));
1466
1467
20.4k
  return (0);
1468
23.0k
}
1469
1470
int
1471
ikev2_pld_tss(struct iked *env, struct ikev2_payload *pld,
1472
    struct iked_message *msg, size_t offset, size_t left)
1473
23.0k
{
1474
23.0k
  struct ikev2_tsp     tsp;
1475
23.0k
  struct ikev2_ts      ts;
1476
23.0k
  size_t         ts_len, i;
1477
1478
23.0k
  if (ikev2_validate_tss(msg, offset, left, &tsp))
1479
2.69k
    return (-1);
1480
1481
20.4k
  offset += sizeof(tsp);
1482
20.4k
  left -= sizeof(tsp);
1483
1484
20.4k
  log_debug("%s: count %d length %zu", __func__,
1485
20.4k
      tsp.tsp_count, left);
1486
1487
40.3k
  for (i = 0; i < tsp.tsp_count; i++) {
1488
38.6k
    if (ikev2_validate_ts(msg, offset, left, &ts))
1489
15.9k
      return (-1);
1490
1491
22.6k
    log_debug("%s: type %s protoid %u length %d "
1492
22.6k
        "startport %u endport %u", __func__,
1493
22.6k
        print_map(ts.ts_type, ikev2_ts_map),
1494
22.6k
        ts.ts_protoid, betoh16(ts.ts_length),
1495
22.6k
        betoh16(ts.ts_startport),
1496
22.6k
        betoh16(ts.ts_endport));
1497
1498
22.6k
    offset += sizeof(ts);
1499
22.6k
    left -= sizeof(ts);
1500
1501
22.6k
    ts_len = betoh16(ts.ts_length) - sizeof(ts);
1502
22.6k
    if (ikev2_pld_ts(env, pld, msg, offset, ts_len, ts.ts_type))
1503
2.71k
      return (-1);
1504
1505
19.9k
    offset += ts_len;
1506
19.9k
    left -= ts_len;
1507
19.9k
  }
1508
1509
1.70k
  return (0);
1510
20.4k
}
1511
1512
int
1513
ikev2_validate_ts(struct iked_message *msg, size_t offset, size_t left,
1514
    struct ikev2_ts *ts)
1515
38.6k
{
1516
38.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1517
38.6k
  size_t     ts_length;
1518
1519
38.6k
  if (left < sizeof(*ts)) {
1520
14.4k
    log_debug("%s: malformed payload: too short for header "
1521
14.4k
        "(%zu < %zu)", __func__, left, sizeof(*ts));
1522
14.4k
    return (-1);
1523
14.4k
  }
1524
24.1k
  memcpy(ts, msgbuf + offset, sizeof(*ts));
1525
1526
24.1k
  ts_length = betoh16(ts->ts_length);
1527
24.1k
  if (ts_length < sizeof(*ts)) {
1528
349
    log_debug("%s: malformed payload: shorter than minimum header "
1529
349
        "size (%zu < %zu)", __func__, ts_length, sizeof(*ts));
1530
349
    return (-1);
1531
349
  }
1532
23.8k
  if (left < ts_length) {
1533
1.21k
    log_debug("%s: malformed payload: too long for payload size "
1534
1.21k
        "(%zu < %zu)", __func__, left, ts_length);
1535
1.21k
    return (-1);
1536
1.21k
  }
1537
1538
22.6k
  return (0);
1539
23.8k
}
1540
1541
int
1542
ikev2_pld_ts(struct iked *env, struct ikev2_payload *pld,
1543
    struct iked_message *msg, size_t offset, size_t left, unsigned int type)
1544
22.6k
{
1545
22.6k
  struct sockaddr_in     start4, end4;
1546
22.6k
  struct sockaddr_in6    start6, end6;
1547
22.6k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
1548
22.6k
  uint8_t       *ptr;
1549
1550
22.6k
  ptr = msgbuf + offset;
1551
1552
22.6k
  switch (type) {
1553
9.66k
  case IKEV2_TS_IPV4_ADDR_RANGE:
1554
9.66k
    if (left < 2 * 4) {
1555
1.16k
      log_debug("%s: malformed payload: too short "
1556
1.16k
          "for ipv4 addr range (%zu < %u)",
1557
1.16k
          __func__, left, 2 * 4);
1558
1.16k
      return (-1);
1559
1.16k
    }
1560
1561
8.50k
    bzero(&start4, sizeof(start4));
1562
8.50k
    start4.sin_family = AF_INET;
1563
#ifdef HAVE_SOCKADDR_SA_LEN
1564
    start4.sin_len = sizeof(start4);
1565
#endif
1566
8.50k
    memcpy(&start4.sin_addr.s_addr, ptr, 4);
1567
8.50k
    ptr += 4;
1568
8.50k
    left -= 4;
1569
1570
8.50k
    bzero(&end4, sizeof(end4));
1571
8.50k
    end4.sin_family = AF_INET;
1572
#ifdef HAVE_SOCKADDR_SA_LEN
1573
    end4.sin_len = sizeof(end4);
1574
#endif
1575
8.50k
    memcpy(&end4.sin_addr.s_addr, ptr, 4);
1576
8.50k
    left -= 4;
1577
1578
8.50k
    log_debug("%s: start %s end %s", __func__,
1579
8.50k
        print_addr(&start4), print_addr(&end4));
1580
8.50k
    break;
1581
1.54k
  case IKEV2_TS_IPV6_ADDR_RANGE:
1582
1.54k
    if (left < 2 * 16) {
1583
252
      log_debug("%s: malformed payload: too short "
1584
252
          "for ipv6 addr range (%zu < %u)",
1585
252
          __func__, left, 2 * 16);
1586
252
      return (-1);
1587
252
    }
1588
1.29k
    bzero(&start6, sizeof(start6));
1589
1.29k
    start6.sin6_family = AF_INET6;
1590
#ifdef HAVE_SOCKADDR_SA_LEN
1591
    start6.sin6_len = sizeof(start6);
1592
#endif
1593
1.29k
    memcpy(&start6.sin6_addr, ptr, 16);
1594
1.29k
    ptr += 16;
1595
1.29k
    left -= 16;
1596
1597
1.29k
    bzero(&end6, sizeof(end6));
1598
1.29k
    end6.sin6_family = AF_INET6;
1599
#ifdef HAVE_SOCKADDR_SA_LEN
1600
    end6.sin6_len = sizeof(end6);
1601
#endif
1602
1.29k
    memcpy(&end6.sin6_addr, ptr, 16);
1603
1.29k
    left -= 16;
1604
1605
1.29k
    log_debug("%s: start %s end %s", __func__,
1606
1.29k
        print_addr(&start6), print_addr(&end6));
1607
1.29k
    break;
1608
11.4k
  default:
1609
11.4k
    log_debug("%s: ignoring unknown TS type %u", __func__, type);
1610
11.4k
    return (0);
1611
22.6k
  }
1612
1613
9.79k
  if (left > 0) {
1614
1.30k
    log_debug("%s: malformed payload: left (%zu) > 0",
1615
1.30k
        __func__, left);
1616
1.30k
    return (-1);
1617
1.30k
  }
1618
1619
8.49k
  return (0);
1620
9.79k
}
1621
1622
int
1623
ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
1624
    struct iked_message *msg, size_t offset, size_t left)
1625
0
{
1626
0
  struct iked_sa      *sa = msg->msg_sa;
1627
0
  struct iked_frag    *sa_frag = &sa->sa_fragments;
1628
0
  struct iked_frag_entry    *el;
1629
0
  struct ikev2_frag_payload  frag;
1630
0
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
1631
0
  uint8_t       *buf;
1632
0
  struct ibuf     *e = NULL;
1633
0
  size_t         frag_num, frag_total;
1634
0
  size_t         len;
1635
0
  int        ret = -1;
1636
0
  int        processed = 0;
1637
0
  ssize_t        elen;
1638
1639
0
  buf = msgbuf + offset;
1640
0
  memcpy(&frag, buf, sizeof(frag));
1641
0
  frag_num = betoh16(frag.frag_num);
1642
0
  frag_total = betoh16(frag.frag_total);
1643
1644
0
  offset += sizeof(frag);
1645
0
  buf = msgbuf + offset;
1646
0
  len = left - sizeof(frag);
1647
1648
0
  ikestat_inc(env, ikes_frag_rcvd);
1649
1650
  /* Limit number of total fragments to avoid DOS */
1651
0
  if (frag_total > IKED_FRAG_TOTAL_MAX ) {
1652
0
    log_debug("%s: Total Fragments too big  %zu",
1653
0
        __func__, frag_total);
1654
0
    goto dropall;
1655
0
  }
1656
1657
  /* Check sanity of fragment header */
1658
0
  if (frag_num == 0 || frag_total == 0) {
1659
0
    log_debug("%s: Malformed fragment received: %zu of %zu",
1660
0
        __func__, frag_num, frag_total);
1661
0
    goto done;
1662
0
  }
1663
0
  log_debug("%s: Received fragment: %zu of %zu",
1664
0
      __func__, frag_num, frag_total);
1665
1666
  /* Drop fragment if frag_num and frag_total don't match */
1667
0
  if (frag_num > frag_total)
1668
0
    goto done;
1669
1670
  /* Decrypt fragment */
1671
0
  if ((e = ibuf_new(buf, len)) == NULL)
1672
0
    goto done;
1673
1674
0
  if ((e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e))
1675
0
      == NULL ) {
1676
0
    log_debug("%s: Failed to decrypt fragment: %zu of %zu",
1677
0
        __func__, frag_num, frag_total);
1678
0
    goto done;
1679
0
  }
1680
0
  elen = ibuf_size(e);
1681
1682
  /* Check new fragmented message */
1683
0
  if (sa_frag->frag_arr == NULL) {
1684
0
    sa_frag->frag_arr = recallocarray(NULL, 0, frag_total,
1685
0
        sizeof(struct iked_frag_entry*));
1686
0
    if (sa_frag->frag_arr == NULL) {
1687
0
      log_info("%s: recallocarray sa_frag->frag_arr.", __func__);
1688
0
      goto done;
1689
0
    }
1690
0
    sa_frag->frag_total = frag_total;
1691
0
  } else {
1692
    /* Drop all fragments if frag_total doesn't match previous */
1693
0
    if (frag_total != sa_frag->frag_total)
1694
0
      goto dropall;
1695
1696
    /* Silent drop if fragment already stored */
1697
0
    if (sa_frag->frag_arr[frag_num-1] != NULL)
1698
0
      goto done;
1699
0
  }
1700
1701
  /* The first fragments IKE header determines pld_nextpayload */
1702
0
  if (frag_num == 1)
1703
0
    sa_frag->frag_nextpayload = pld->pld_nextpayload;
1704
1705
  /* Insert new list element */
1706
0
  el = calloc(1, sizeof(struct iked_frag_entry));
1707
0
  if (el == NULL) {
1708
0
    log_info("%s: Failed allocating new fragment: %zu of %zu",
1709
0
        __func__, frag_num, frag_total);
1710
0
    goto done;
1711
0
  }
1712
1713
0
  sa_frag->frag_arr[frag_num-1] = el;
1714
0
  el->frag_size = elen;
1715
0
  el->frag_data = calloc(1, elen);
1716
0
  if (el->frag_data == NULL) {
1717
0
    log_debug("%s: Failed allocating new fragment data: %zu of %zu",
1718
0
        __func__, frag_num, frag_total);
1719
0
    goto done;
1720
0
  }
1721
1722
  /* Copy plaintext to fragment */
1723
0
  memcpy(el->frag_data, ibuf_seek(e, 0, 0), elen);
1724
0
  sa_frag->frag_total_size += elen;
1725
0
  sa_frag->frag_count++;
1726
1727
  /* If all frags are received start reassembly */
1728
0
  if (sa_frag->frag_count == sa_frag->frag_total) {
1729
0
    log_debug("%s: All fragments received: %zu of %zu",
1730
0
        __func__, frag_num, frag_total);
1731
0
    ret = ikev2_frags_reassemble(env, pld, msg);
1732
0
  } else {
1733
0
    ret = 0;
1734
0
  }
1735
0
  processed = 1;
1736
1737
0
done:
1738
0
  if (!processed)
1739
0
    ikestat_inc(env, ikes_frag_rcvd_drop);
1740
0
  ibuf_free(e);
1741
0
  return (ret);
1742
0
dropall:
1743
0
  ikestat_add(env, ikes_frag_rcvd_drop, sa_frag->frag_count + 1);
1744
0
  config_free_fragments(sa_frag);
1745
0
  ibuf_free(e);
1746
0
  return -1;
1747
0
}
1748
1749
int
1750
ikev2_frags_reassemble(struct iked *env, struct ikev2_payload *pld,
1751
    struct iked_message *msg)
1752
0
{
1753
0
  struct iked_frag    *sa_frag = &msg->msg_sa->sa_fragments;
1754
0
  struct ibuf     *e = NULL;
1755
0
  struct iked_frag_entry    *el;
1756
0
  uint8_t       *ptr;
1757
0
  size_t         offset;
1758
0
  size_t         i;
1759
0
  struct iked_message    emsg;
1760
0
  int        ret = -1;
1761
0
  int        processed = 0;
1762
1763
  /* Reassemble fragments to single buffer */
1764
0
  if ((e = ibuf_new(NULL, sa_frag->frag_total_size)) == NULL) {
1765
0
    log_debug("%s: Failed allocating SK buffer.", __func__);
1766
0
    goto done;
1767
0
  }
1768
1769
  /* Empty queue to new buffer */
1770
0
  offset = 0;
1771
0
  for (i = 0; i < sa_frag->frag_total; i++) {
1772
0
    if ((el = sa_frag->frag_arr[i]) == NULL)
1773
0
      fatalx("Tried to reassemble shallow frag_arr");
1774
0
    ptr = ibuf_seek(e, offset, el->frag_size);
1775
0
    if (ptr == NULL) {
1776
0
      log_info("%s: failed to reassemble fragments", __func__);
1777
0
      goto done;
1778
0
    }
1779
0
    memcpy(ptr, el->frag_data, el->frag_size);
1780
0
    offset += el->frag_size;
1781
0
  }
1782
1783
0
  log_debug("%s: Defragmented length %zd", __func__,
1784
0
      sa_frag->frag_total_size);
1785
0
  print_hex(ibuf_data(e), 0,  sa_frag->frag_total_size);
1786
1787
  /* Drop the original request's packets from the retransmit queue */
1788
0
  if (msg->msg_response)
1789
0
    ikev2_msg_dispose(env, &msg->msg_sa->sa_requests,
1790
0
        ikev2_msg_lookup(env, &msg->msg_sa->sa_requests, msg,
1791
0
        msg->msg_exchange));
1792
1793
  /*
1794
   * Parse decrypted payload
1795
   */
1796
0
  bzero(&emsg, sizeof(emsg));
1797
0
  memcpy(&emsg, msg, sizeof(*msg));
1798
0
  emsg.msg_data = e;
1799
0
  emsg.msg_e = 1;
1800
0
  emsg.msg_parent = msg;
1801
0
  TAILQ_INIT(&emsg.msg_proposals);
1802
1803
0
  ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
1804
0
      sa_frag->frag_nextpayload);
1805
0
  processed = 1;
1806
0
done:
1807
0
  if (processed)
1808
0
    ikestat_add(env, ikes_frag_reass_ok, sa_frag->frag_total);
1809
0
  else
1810
0
    ikestat_add(env, ikes_frag_reass_drop, sa_frag->frag_total);
1811
0
  config_free_fragments(sa_frag);
1812
0
  ibuf_free(e);
1813
1814
0
  return (ret);
1815
0
}
1816
1817
int
1818
ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
1819
    struct iked_message *msg, size_t offset, size_t left)
1820
0
{
1821
0
  struct iked_sa    *sa = msg->msg_sa;
1822
0
  struct ibuf   *e = NULL;
1823
0
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
1824
0
  struct iked_message  emsg;
1825
0
  uint8_t     *buf;
1826
0
  size_t       len;
1827
0
  int      ret = -1;
1828
1829
0
  if (sa->sa_fragments.frag_arr != NULL) {
1830
0
    log_warn("%s: Received SK payload when SKFs are in queue.",
1831
0
        __func__);
1832
0
    config_free_fragments(&sa->sa_fragments);
1833
0
    return (ret);
1834
0
  }
1835
1836
0
  buf = msgbuf + offset;
1837
0
  len = left;
1838
1839
0
  if ((e = ibuf_new(buf, len)) == NULL)
1840
0
    goto done;
1841
1842
0
  if (ikev2_msg_frompeer(msg)) {
1843
0
    e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
1844
0
  } else {
1845
0
    sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
1846
0
    e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
1847
0
    sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
1848
0
  }
1849
1850
0
  if (e == NULL)
1851
0
    goto done;
1852
1853
  /*
1854
   * Parse decrypted payload
1855
   */
1856
0
  bzero(&emsg, sizeof(emsg));
1857
0
  memcpy(&emsg, msg, sizeof(*msg));
1858
0
  emsg.msg_data = e;
1859
0
  emsg.msg_e = 1;
1860
0
  emsg.msg_parent = msg;
1861
0
  TAILQ_INIT(&emsg.msg_proposals);
1862
1863
0
  ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
1864
0
      pld->pld_nextpayload);
1865
1866
0
 done:
1867
0
  ibuf_free(e);
1868
1869
0
  return (ret);
1870
0
}
1871
1872
int
1873
ikev2_validate_cp(struct iked_message *msg, size_t offset, size_t left,
1874
    struct ikev2_cp *cp)
1875
11.6k
{
1876
11.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1877
1878
11.6k
  if (left < sizeof(*cp)) {
1879
3.58k
    log_debug("%s: malformed payload: too short for header "
1880
3.58k
        "(%zu < %zu)", __func__, left, sizeof(*cp));
1881
3.58k
    return (-1);
1882
3.58k
  }
1883
8.11k
  memcpy(cp, msgbuf + offset, sizeof(*cp));
1884
1885
8.11k
  return (0);
1886
11.6k
}
1887
1888
int
1889
ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld,
1890
    struct iked_message *msg, size_t offset, size_t left)
1891
11.6k
{
1892
11.6k
  struct ikev2_cp    cp;
1893
11.6k
  struct ikev2_cfg  *cfg;
1894
11.6k
  struct iked_addr  *addr;
1895
11.6k
  struct sockaddr_in  *in4;
1896
11.6k
  struct sockaddr_in6 *in6;
1897
11.6k
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
1898
11.6k
  uint8_t     *ptr;
1899
11.6k
  size_t       len;
1900
11.6k
  int      cfg_type;
1901
1902
11.6k
  if (ikev2_validate_cp(msg, offset, left, &cp))
1903
3.58k
    return (-1);
1904
1905
8.11k
  ptr = msgbuf + offset + sizeof(cp);
1906
8.11k
  len = left - sizeof(cp);
1907
1908
8.11k
  log_debug("%s: type %s length %zu",
1909
8.11k
      __func__, print_map(cp.cp_type, ikev2_cp_map), len);
1910
8.11k
  print_hex(ptr, 0, len);
1911
1912
16.4k
  while (len > 0) {
1913
10.1k
    if (len < sizeof(*cfg)) {
1914
367
      log_debug("%s: malformed payload: too short for cfg "
1915
367
          "(%zu < %zu)", __func__, len, sizeof(*cfg));
1916
367
      return (-1);
1917
367
    }
1918
9.74k
    cfg = (struct ikev2_cfg *)ptr;
1919
1920
9.74k
    log_debug("%s: %s 0x%04x length %d", __func__,
1921
9.74k
        print_map(betoh16(cfg->cfg_type), ikev2_cfg_map),
1922
9.74k
        betoh16(cfg->cfg_type),
1923
9.74k
        betoh16(cfg->cfg_length));
1924
1925
9.74k
    ptr += sizeof(*cfg);
1926
9.74k
    len -= sizeof(*cfg);
1927
1928
9.74k
    if (len < betoh16(cfg->cfg_length)) {
1929
1.42k
      log_debug("%s: malformed payload: too short for "
1930
1.42k
          "cfg_length (%zu < %u)", __func__, len,
1931
1.42k
          betoh16(cfg->cfg_length));
1932
1.42k
      return (-1);
1933
1.42k
    }
1934
1935
8.32k
    print_hex(ptr, sizeof(*cfg), betoh16(cfg->cfg_length));
1936
1937
8.32k
    cfg_type = betoh16(cfg->cfg_type);
1938
8.32k
    switch (cfg_type) {
1939
848
    case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1940
1.51k
    case IKEV2_CFG_INTERNAL_IP4_DNS:
1941
1.51k
      if (!ikev2_msg_frompeer(msg))
1942
741
        break;
1943
777
      if (betoh16(cfg->cfg_length) == 0)
1944
309
        break;
1945
      /* XXX multiple-valued */
1946
468
      if (betoh16(cfg->cfg_length) < 4) {
1947
6
        log_debug("%s: malformed payload: too short "
1948
6
            "for ipv4 addr (%u < %u)",
1949
6
            __func__, betoh16(cfg->cfg_length), 4);
1950
6
        return (-1);
1951
6
      }
1952
462
      switch(cfg_type) {
1953
359
      case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1954
359
        if (msg->msg_parent->msg_cp_addr != NULL) {
1955
240
          log_debug("%s: address already set", __func__);
1956
240
          goto skip;
1957
240
        }
1958
119
        break;
1959
119
      case IKEV2_CFG_INTERNAL_IP4_DNS:
1960
103
        if (msg->msg_parent->msg_cp_dns != NULL) {
1961
53
          log_debug("%s: dns already set", __func__);
1962
53
          goto skip;
1963
53
        }
1964
50
        break;
1965
50
      default:
1966
0
        break;
1967
462
      }
1968
169
      if ((addr = calloc(1, sizeof(*addr))) == NULL) {
1969
0
        log_debug("%s: malloc failed", __func__);
1970
0
        break;
1971
0
      }
1972
169
      addr->addr_af = AF_INET;
1973
169
      in4 = (struct sockaddr_in *)&addr->addr;
1974
169
      in4->sin_family = AF_INET;
1975
#ifdef HAVE_SOCKADDR_SA_LEN
1976
      in4->sin_len = sizeof(*in4);
1977
#endif
1978
169
      memcpy(&in4->sin_addr.s_addr, ptr, 4);
1979
169
      switch(cfg_type) {
1980
119
      case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1981
119
        msg->msg_parent->msg_cp_addr = addr;
1982
119
        log_debug("%s: IP4_ADDRESS %s", __func__,
1983
119
            print_addr(&addr->addr));
1984
119
        break;
1985
50
      case IKEV2_CFG_INTERNAL_IP4_DNS:
1986
50
        msg->msg_parent->msg_cp_dns = addr;
1987
50
        log_debug("%s: IP4_DNS %s", __func__,
1988
50
            print_addr(&addr->addr));
1989
50
        break;
1990
0
      default:
1991
0
        log_debug("%s: cfg %s", __func__,
1992
0
            print_addr(&addr->addr));
1993
0
        break;
1994
169
      }
1995
169
      break;
1996
2.28k
    case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
1997
3.13k
    case IKEV2_CFG_INTERNAL_IP6_DNS:
1998
3.13k
      if (!ikev2_msg_frompeer(msg))
1999
2.90k
        break;
2000
230
      if (betoh16(cfg->cfg_length) == 0)
2001
94
        break;
2002
      /* XXX multiple-valued */
2003
136
      if (betoh16(cfg->cfg_length) < 16) {
2004
5
        log_debug("%s: malformed payload: too short "
2005
5
            "for ipv6 addr w/prefixlen (%u < %u)",
2006
5
            __func__, betoh16(cfg->cfg_length), 16);
2007
5
        return (-1);
2008
5
      }
2009
131
      switch(cfg_type) {
2010
89
      case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
2011
89
        if (msg->msg_parent->msg_cp_addr6 != NULL) {
2012
47
          log_debug("%s: address6 already set", __func__);
2013
47
          goto skip;
2014
47
        }
2015
42
        break;
2016
42
      case IKEV2_CFG_INTERNAL_IP6_DNS:
2017
42
        if (msg->msg_parent->msg_cp_dns != NULL) {
2018
36
          log_debug("%s: dns already set", __func__);
2019
36
          goto skip;
2020
36
        }
2021
6
        break;
2022
131
      }
2023
48
      if ((addr = calloc(1, sizeof(*addr))) == NULL) {
2024
0
        log_debug("%s: malloc failed", __func__);
2025
0
        break;
2026
0
      }
2027
48
      addr->addr_af = AF_INET6;
2028
48
      in6 = (struct sockaddr_in6 *)&addr->addr;
2029
48
      in6->sin6_family = AF_INET6;
2030
#ifdef HAVE_SOCKADDR_SA_LEN
2031
      in6->sin6_len = sizeof(*in6);
2032
#endif
2033
48
      memcpy(&in6->sin6_addr, ptr, 16);
2034
48
      switch(cfg_type) {
2035
42
      case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
2036
42
        msg->msg_parent->msg_cp_addr6 = addr;
2037
42
        log_debug("%s: IP6_ADDRESS %s", __func__,
2038
42
            print_addr(&addr->addr));
2039
42
        break;
2040
6
      case IKEV2_CFG_INTERNAL_IP6_DNS:
2041
6
        msg->msg_parent->msg_cp_dns = addr;
2042
6
        log_debug("%s: IP6_DNS %s", __func__,
2043
6
            print_addr(&addr->addr));
2044
6
        break;
2045
0
      default:
2046
0
        log_debug("%s: cfg %s/%d", __func__,
2047
0
            print_addr(&addr->addr), ptr[16]);
2048
0
        break;
2049
48
      }
2050
48
      break;
2051
8.32k
    }
2052
2053
8.31k
 skip:
2054
8.31k
    ptr += betoh16(cfg->cfg_length);
2055
8.31k
    len -= betoh16(cfg->cfg_length);
2056
8.31k
  }
2057
2058
6.31k
  if (!ikev2_msg_frompeer(msg))
2059
6.10k
    return (0);
2060
2061
207
  msg->msg_parent->msg_cp = cp.cp_type;
2062
2063
207
  return (0);
2064
6.31k
}
2065
2066
int
2067
ikev2_validate_eap(struct iked_message *msg, size_t offset, size_t left,
2068
    struct eap_header *hdr)
2069
21.2k
{
2070
21.2k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
2071
2072
21.2k
  if (left < sizeof(*hdr)) {
2073
9.30k
    log_debug("%s: malformed payload: too short for header "
2074
9.30k
        "(%zu < %zu)", __func__, left, sizeof(*hdr));
2075
9.30k
    return (-1);
2076
9.30k
  }
2077
11.9k
  memcpy(hdr, msgbuf + offset, sizeof(*hdr));
2078
2079
11.9k
  return (0);
2080
21.2k
}
2081
2082
int
2083
ikev2_pld_eap(struct iked *env, struct ikev2_payload *pld,
2084
    struct iked_message *msg, size_t offset, size_t left)
2085
21.2k
{
2086
21.2k
  struct eap_header    hdr;
2087
21.2k
  struct eap_message    *eap = NULL;
2088
21.2k
  const struct iked_sa    *sa = msg->msg_sa;
2089
21.2k
  size_t         len;
2090
2091
21.2k
  if (ikev2_validate_eap(msg, offset, left, &hdr))
2092
9.30k
    return (-1);
2093
11.9k
  len = betoh16(hdr.eap_length);
2094
2095
11.9k
  if (len < sizeof(*eap)) {
2096
3.88k
    log_info("%s: %s id %d length %d", SPI_SA(sa, __func__),
2097
3.88k
        print_map(hdr.eap_code, eap_code_map),
2098
3.88k
        hdr.eap_id, betoh16(hdr.eap_length));
2099
8.07k
  } else {
2100
    /* Now try to get the indicated length */
2101
8.07k
    if ((eap = ibuf_seek(msg->msg_data, offset, len)) == NULL) {
2102
4.20k
      log_debug("%s: invalid EAP length", __func__);
2103
4.20k
      return (-1);
2104
4.20k
    }
2105
2106
3.86k
    log_info("%s: %s id %d length %d EAP-%s", SPI_SA(sa, __func__),
2107
3.86k
        print_map(eap->eap_code, eap_code_map),
2108
3.86k
        eap->eap_id, betoh16(eap->eap_length),
2109
3.86k
        print_map(eap->eap_type, eap_type_map));
2110
2111
3.86k
    if (eap_parse(env, sa, msg, eap, msg->msg_response) == -1)
2112
0
      return (-1);
2113
3.86k
    msg->msg_parent->msg_eap.eam_found = 1;
2114
3.86k
  }
2115
2116
7.75k
  return (0);
2117
11.9k
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/iked/imsg_util.c.html b/coverage/latest/report/linux/src/openiked-portable/iked/imsg_util.c.html index b6f52e38e..a4a7852e7 100644 --- a/coverage/latest/report/linux/src/openiked-portable/iked/imsg_util.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/iked/imsg_util.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/imsg_util.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg_util.c,v 1.21 2023/07/18 15:07:41 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/queue.h>
20
#include <sys/socket.h>
21
#include <sys/uio.h>
22
23
#include <netdb.h>
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <unistd.h>
27
#include <string.h>
28
#include <errno.h>
29
#include <fcntl.h>
30
#include <ctype.h>
31
#include <event.h>
32
33
#include "iked.h"
34
35
/*
36
 * Extending the imsg buffer API for internal use
37
 */
38
39
struct ibuf *
40
ibuf_new(const void *data, size_t len)
41
25.5k
{
42
25.5k
  struct ibuf *buf;
43
44
25.5k
  if ((buf = ibuf_dynamic(len,
45
25.5k
      IKED_MSGBUF_MAX)) == NULL)
46
0
    return (NULL);
47
48
25.5k
  if (len == 0)
49
1.74k
    return (buf);
50
51
23.8k
  if (data == NULL) {
52
0
    if (ibuf_add_zero(buf, len) != 0) {
53
0
      ibuf_free(buf);
54
0
      return (NULL);
55
0
    }
56
23.8k
  } else {
57
23.8k
    if (ibuf_add(buf, data, len) != 0) {
58
0
      ibuf_free(buf);
59
0
      return (NULL);
60
0
    }
61
23.8k
  }
62
63
23.8k
  return (buf);
64
23.8k
}
65
66
struct ibuf *
67
ibuf_static(void)
68
0
{
69
0
  return ibuf_open(IKED_MSGBUF_MAX);
70
0
}
71
72
size_t
73
ibuf_length(struct ibuf *buf)
74
0
{
75
0
  if (buf == NULL)
76
0
    return (0);
77
0
  return (ibuf_size(buf));
78
0
}
79
80
struct ibuf *
81
ibuf_getdata(struct ibuf *buf, size_t len)
82
0
{
83
0
  void  *data;
84
85
0
  if ((data = ibuf_seek(buf, buf->rpos, len)) == NULL)
86
0
    return (NULL);
87
0
  buf->rpos += len;
88
89
0
  return (ibuf_new(data, len));
90
0
}
91
92
struct ibuf *
93
ibuf_dup(struct ibuf *buf)
94
0
{
95
0
  if (buf == NULL)
96
0
    return (NULL);
97
0
  return (ibuf_new(ibuf_data(buf), ibuf_size(buf)));
98
0
}
99
100
struct ibuf *
101
ibuf_random(size_t len)
102
0
{
103
0
  struct ibuf *buf;
104
0
  void    *ptr;
105
106
0
  if ((buf = ibuf_open(len)) == NULL)
107
0
    return (NULL);
108
0
  if ((ptr = ibuf_reserve(buf, len)) == NULL) {
109
0
    ibuf_free(buf);
110
0
    return (NULL);
111
0
  }
112
0
  arc4random_buf(ptr, len);
113
0
  return (buf);
114
0
}
115
116
int
117
ibuf_setsize(struct ibuf *buf, size_t len)
118
0
{
119
0
  if (len > buf->size)
120
0
    return (-1);
121
0
  buf->wpos = len;
122
0
  return (0);
123
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/imsg_util.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg_util.c,v 1.21 2023/07/18 15:07:41 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/queue.h>
20
#include <sys/socket.h>
21
#include <sys/uio.h>
22
23
#include <netdb.h>
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <unistd.h>
27
#include <string.h>
28
#include <errno.h>
29
#include <fcntl.h>
30
#include <ctype.h>
31
#include <event.h>
32
33
#include "iked.h"
34
35
/*
36
 * Extending the imsg buffer API for internal use
37
 */
38
39
struct ibuf *
40
ibuf_new(const void *data, size_t len)
41
25.5k
{
42
25.5k
  struct ibuf *buf;
43
44
25.5k
  if ((buf = ibuf_dynamic(len,
45
25.5k
      IKED_MSGBUF_MAX)) == NULL)
46
0
    return (NULL);
47
48
25.5k
  if (len == 0)
49
1.74k
    return (buf);
50
51
23.8k
  if (data == NULL) {
52
0
    if (ibuf_add_zero(buf, len) != 0) {
53
0
      ibuf_free(buf);
54
0
      return (NULL);
55
0
    }
56
23.8k
  } else {
57
23.8k
    if (ibuf_add(buf, data, len) != 0) {
58
0
      ibuf_free(buf);
59
0
      return (NULL);
60
0
    }
61
23.8k
  }
62
63
23.8k
  return (buf);
64
23.8k
}
65
66
struct ibuf *
67
ibuf_static(void)
68
0
{
69
0
  return ibuf_open(IKED_MSGBUF_MAX);
70
0
}
71
72
size_t
73
ibuf_length(struct ibuf *buf)
74
0
{
75
0
  if (buf == NULL)
76
0
    return (0);
77
0
  return (ibuf_size(buf));
78
0
}
79
80
struct ibuf *
81
ibuf_getdata(struct ibuf *buf, size_t len)
82
0
{
83
0
  void  *data;
84
85
0
  if ((data = ibuf_seek(buf, buf->rpos, len)) == NULL)
86
0
    return (NULL);
87
0
  buf->rpos += len;
88
89
0
  return (ibuf_new(data, len));
90
0
}
91
92
struct ibuf *
93
ibuf_dup(struct ibuf *buf)
94
0
{
95
0
  if (buf == NULL)
96
0
    return (NULL);
97
0
  return (ibuf_new(ibuf_data(buf), ibuf_size(buf)));
98
0
}
99
100
struct ibuf *
101
ibuf_random(size_t len)
102
0
{
103
0
  struct ibuf *buf;
104
0
  void    *ptr;
105
106
0
  if ((buf = ibuf_open(len)) == NULL)
107
0
    return (NULL);
108
0
  if ((ptr = ibuf_reserve(buf, len)) == NULL) {
109
0
    ibuf_free(buf);
110
0
    return (NULL);
111
0
  }
112
0
  arc4random_buf(ptr, len);
113
0
  return (buf);
114
0
}
115
116
int
117
ibuf_setsize(struct ibuf *buf, size_t len)
118
0
{
119
0
  if (len > buf->size)
120
0
    return (-1);
121
0
  buf->wpos = len;
122
0
  return (0);
123
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/iked/log.c.html b/coverage/latest/report/linux/src/openiked-portable/iked/log.c.html index 289332b21..a8f120030 100644 --- a/coverage/latest/report/linux/src/openiked-portable/iked/log.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/iked/log.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/log.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: log.c,v 1.12 2017/03/21 12:06:55 bluhm Exp $  */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <stdarg.h>
22
#include <string.h>
23
#include <syslog.h>
24
#include <errno.h>
25
#include <time.h>
26
27
static int   debug;
28
static int   verbose;
29
const char  *log_procname;
30
31
void  log_init(int, int);
32
void  log_procinit(const char *);
33
void  log_setverbose(int);
34
int log_getverbose(void);
35
void  log_warn(const char *, ...)
36
      __attribute__((__format__ (printf, 1, 2)));
37
void  log_warnx(const char *, ...)
38
      __attribute__((__format__ (printf, 1, 2)));
39
void  log_info(const char *, ...)
40
      __attribute__((__format__ (printf, 1, 2)));
41
void  log_debug(const char *, ...)
42
      __attribute__((__format__ (printf, 1, 2)));
43
void  logit(int, const char *, ...)
44
      __attribute__((__format__ (printf, 2, 3)));
45
void  vlog(int, const char *, va_list)
46
      __attribute__((__format__ (printf, 2, 0)));
47
__dead void fatal(const char *, ...)
48
      __attribute__((__format__ (printf, 1, 2)));
49
__dead void fatalx(const char *, ...)
50
      __attribute__((__format__ (printf, 1, 2)));
51
52
void
53
log_init(int n_debug, int facility)
54
0
{
55
0
  extern char *__progname;
56
57
0
  debug = n_debug;
58
0
  verbose = n_debug;
59
0
  log_procinit(__progname);
60
61
0
  if (!debug)
62
0
    openlog(__progname, LOG_PID | LOG_NDELAY, facility);
63
64
0
  tzset();
65
0
}
66
67
void
68
log_procinit(const char *procname)
69
0
{
70
0
  if (procname != NULL)
71
0
    log_procname = procname;
72
0
}
73
74
void
75
log_setverbose(int v)
76
0
{
77
0
  verbose = v;
78
0
}
79
80
int
81
log_getverbose(void)
82
181k
{
83
181k
  return (verbose);
84
181k
}
85
86
void
87
logit(int pri, const char *fmt, ...)
88
0
{
89
0
  va_list ap;
90
91
0
  va_start(ap, fmt);
92
0
  vlog(pri, fmt, ap);
93
0
  va_end(ap);
94
0
}
95
96
void
97
vlog(int pri, const char *fmt, va_list ap)
98
12.8k
{
99
12.8k
  char  *nfmt;
100
12.8k
  int  saved_errno = errno;
101
102
12.8k
  if (debug) {
103
    /* best effort in out of mem situations */
104
0
    if (asprintf(&nfmt, "%s\n", fmt) == -1) {
105
0
      vfprintf(stderr, fmt, ap);
106
0
      fprintf(stderr, "\n");
107
0
    } else {
108
0
      vfprintf(stderr, nfmt, ap);
109
0
      free(nfmt);
110
0
    }
111
0
    fflush(stderr);
112
0
  } else
113
12.8k
    vsyslog(pri, fmt, ap);
114
115
12.8k
  errno = saved_errno;
116
12.8k
}
117
118
void
119
log_warn(const char *emsg, ...)
120
0
{
121
0
  char    *nfmt;
122
0
  va_list    ap;
123
0
  int    saved_errno = errno;
124
125
  /* best effort to even work in out of memory situations */
126
0
  if (emsg == NULL)
127
0
    logit(LOG_ERR, "%s", strerror(saved_errno));
128
0
  else {
129
0
    va_start(ap, emsg);
130
131
0
    if (asprintf(&nfmt, "%s: %s", emsg,
132
0
        strerror(saved_errno)) == -1) {
133
      /* we tried it... */
134
0
      vlog(LOG_ERR, emsg, ap);
135
0
      logit(LOG_ERR, "%s", strerror(saved_errno));
136
0
    } else {
137
0
      vlog(LOG_ERR, nfmt, ap);
138
0
      free(nfmt);
139
0
    }
140
0
    va_end(ap);
141
0
  }
142
143
0
  errno = saved_errno;
144
0
}
145
146
void
147
log_warnx(const char *emsg, ...)
148
0
{
149
0
  va_list  ap;
150
151
0
  va_start(ap, emsg);
152
0
  vlog(LOG_ERR, emsg, ap);
153
0
  va_end(ap);
154
0
}
155
156
void
157
log_info(const char *emsg, ...)
158
12.8k
{
159
12.8k
  va_list  ap;
160
161
12.8k
  va_start(ap, emsg);
162
12.8k
  vlog(LOG_INFO, emsg, ap);
163
12.8k
  va_end(ap);
164
12.8k
}
165
166
void
167
log_debug(const char *emsg, ...)
168
687k
{
169
687k
  va_list  ap;
170
171
687k
  if (verbose > 1) {
172
0
    va_start(ap, emsg);
173
0
    vlog(LOG_DEBUG, emsg, ap);
174
0
    va_end(ap);
175
0
  }
176
687k
}
177
178
static void
179
vfatalc(int code, const char *emsg, va_list ap)
180
0
{
181
0
  static char s[BUFSIZ];
182
0
  const char  *sep;
183
184
0
  if (emsg != NULL) {
185
0
    (void)vsnprintf(s, sizeof(s), emsg, ap);
186
0
    sep = ": ";
187
0
  } else {
188
0
    s[0] = '\0';
189
0
    sep = "";
190
0
  }
191
0
  if (code)
192
0
    logit(LOG_CRIT, "%s: %s%s%s",
193
0
        log_procname, s, sep, strerror(code));
194
0
  else
195
0
    logit(LOG_CRIT, "%s%s%s", log_procname, sep, s);
196
0
}
197
198
void
199
fatal(const char *emsg, ...)
200
0
{
201
0
  va_list ap;
202
203
0
  va_start(ap, emsg);
204
0
  vfatalc(errno, emsg, ap);
205
0
  va_end(ap);
206
0
  exit(1);
207
0
}
208
209
void
210
fatalx(const char *emsg, ...)
211
0
{
212
0
  va_list ap;
213
214
0
  va_start(ap, emsg);
215
0
  vfatalc(0, emsg, ap);
216
0
  va_end(ap);
217
0
  exit(1);
218
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/log.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: log.c,v 1.12 2017/03/21 12:06:55 bluhm Exp $  */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <stdarg.h>
22
#include <string.h>
23
#include <syslog.h>
24
#include <errno.h>
25
#include <time.h>
26
27
static int   debug;
28
static int   verbose;
29
const char  *log_procname;
30
31
void  log_init(int, int);
32
void  log_procinit(const char *);
33
void  log_setverbose(int);
34
int log_getverbose(void);
35
void  log_warn(const char *, ...)
36
      __attribute__((__format__ (printf, 1, 2)));
37
void  log_warnx(const char *, ...)
38
      __attribute__((__format__ (printf, 1, 2)));
39
void  log_info(const char *, ...)
40
      __attribute__((__format__ (printf, 1, 2)));
41
void  log_debug(const char *, ...)
42
      __attribute__((__format__ (printf, 1, 2)));
43
void  logit(int, const char *, ...)
44
      __attribute__((__format__ (printf, 2, 3)));
45
void  vlog(int, const char *, va_list)
46
      __attribute__((__format__ (printf, 2, 0)));
47
__dead void fatal(const char *, ...)
48
      __attribute__((__format__ (printf, 1, 2)));
49
__dead void fatalx(const char *, ...)
50
      __attribute__((__format__ (printf, 1, 2)));
51
52
void
53
log_init(int n_debug, int facility)
54
0
{
55
0
  extern char *__progname;
56
57
0
  debug = n_debug;
58
0
  verbose = n_debug;
59
0
  log_procinit(__progname);
60
61
0
  if (!debug)
62
0
    openlog(__progname, LOG_PID | LOG_NDELAY, facility);
63
64
0
  tzset();
65
0
}
66
67
void
68
log_procinit(const char *procname)
69
0
{
70
0
  if (procname != NULL)
71
0
    log_procname = procname;
72
0
}
73
74
void
75
log_setverbose(int v)
76
0
{
77
0
  verbose = v;
78
0
}
79
80
int
81
log_getverbose(void)
82
181k
{
83
181k
  return (verbose);
84
181k
}
85
86
void
87
logit(int pri, const char *fmt, ...)
88
0
{
89
0
  va_list ap;
90
91
0
  va_start(ap, fmt);
92
0
  vlog(pri, fmt, ap);
93
0
  va_end(ap);
94
0
}
95
96
void
97
vlog(int pri, const char *fmt, va_list ap)
98
12.8k
{
99
12.8k
  char  *nfmt;
100
12.8k
  int  saved_errno = errno;
101
102
12.8k
  if (debug) {
103
    /* best effort in out of mem situations */
104
0
    if (asprintf(&nfmt, "%s\n", fmt) == -1) {
105
0
      vfprintf(stderr, fmt, ap);
106
0
      fprintf(stderr, "\n");
107
0
    } else {
108
0
      vfprintf(stderr, nfmt, ap);
109
0
      free(nfmt);
110
0
    }
111
0
    fflush(stderr);
112
0
  } else
113
12.8k
    vsyslog(pri, fmt, ap);
114
115
12.8k
  errno = saved_errno;
116
12.8k
}
117
118
void
119
log_warn(const char *emsg, ...)
120
0
{
121
0
  char    *nfmt;
122
0
  va_list    ap;
123
0
  int    saved_errno = errno;
124
125
  /* best effort to even work in out of memory situations */
126
0
  if (emsg == NULL)
127
0
    logit(LOG_ERR, "%s", strerror(saved_errno));
128
0
  else {
129
0
    va_start(ap, emsg);
130
131
0
    if (asprintf(&nfmt, "%s: %s", emsg,
132
0
        strerror(saved_errno)) == -1) {
133
      /* we tried it... */
134
0
      vlog(LOG_ERR, emsg, ap);
135
0
      logit(LOG_ERR, "%s", strerror(saved_errno));
136
0
    } else {
137
0
      vlog(LOG_ERR, nfmt, ap);
138
0
      free(nfmt);
139
0
    }
140
0
    va_end(ap);
141
0
  }
142
143
0
  errno = saved_errno;
144
0
}
145
146
void
147
log_warnx(const char *emsg, ...)
148
0
{
149
0
  va_list  ap;
150
151
0
  va_start(ap, emsg);
152
0
  vlog(LOG_ERR, emsg, ap);
153
0
  va_end(ap);
154
0
}
155
156
void
157
log_info(const char *emsg, ...)
158
12.8k
{
159
12.8k
  va_list  ap;
160
161
12.8k
  va_start(ap, emsg);
162
12.8k
  vlog(LOG_INFO, emsg, ap);
163
12.8k
  va_end(ap);
164
12.8k
}
165
166
void
167
log_debug(const char *emsg, ...)
168
687k
{
169
687k
  va_list  ap;
170
171
687k
  if (verbose > 1) {
172
0
    va_start(ap, emsg);
173
0
    vlog(LOG_DEBUG, emsg, ap);
174
0
    va_end(ap);
175
0
  }
176
687k
}
177
178
static void
179
vfatalc(int code, const char *emsg, va_list ap)
180
0
{
181
0
  static char s[BUFSIZ];
182
0
  const char  *sep;
183
184
0
  if (emsg != NULL) {
185
0
    (void)vsnprintf(s, sizeof(s), emsg, ap);
186
0
    sep = ": ";
187
0
  } else {
188
0
    s[0] = '\0';
189
0
    sep = "";
190
0
  }
191
0
  if (code)
192
0
    logit(LOG_CRIT, "%s: %s%s%s",
193
0
        log_procname, s, sep, strerror(code));
194
0
  else
195
0
    logit(LOG_CRIT, "%s%s%s", log_procname, sep, s);
196
0
}
197
198
void
199
fatal(const char *emsg, ...)
200
0
{
201
0
  va_list ap;
202
203
0
  va_start(ap, emsg);
204
0
  vfatalc(errno, emsg, ap);
205
0
  va_end(ap);
206
0
  exit(1);
207
0
}
208
209
void
210
fatalx(const char *emsg, ...)
211
0
{
212
0
  va_list ap;
213
214
0
  va_start(ap, emsg);
215
0
  vfatalc(0, emsg, ap);
216
0
  va_end(ap);
217
0
  exit(1);
218
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/iked/types.h.html b/coverage/latest/report/linux/src/openiked-portable/iked/types.h.html index c10cb2916..c9b88ea7d 100644 --- a/coverage/latest/report/linux/src/openiked-portable/iked/types.h.html +++ b/coverage/latest/report/linux/src/openiked-portable/iked/types.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/types.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: types.h,v 1.52 2023/03/04 22:22:51 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#ifndef IKED_TYPES_H
21
#define IKED_TYPES_H
22
23
#ifndef IKED_USER
24
#define IKED_USER   "_iked"
25
#endif
26
27
#ifndef IKED_CONFIG
28
#define IKED_CONFIG   "/etc/iked.conf"
29
#endif
30
31
#define IKED_SOCKET   "/var/run/iked.sock"
32
33
#ifndef IKED_CA
34
#define IKED_CA     "/etc/iked/"
35
#endif
36
37
#define IKED_CA_DIR   "ca/"
38
#define IKED_CRL_DIR    "crls/"
39
#define IKED_CERT_DIR   "certs/"
40
#define IKED_PUBKEY_DIR   "pubkeys/"
41
#define IKED_PRIVKEY    IKED_CA "private/local.key"
42
#define IKED_PUBKEY   "local.pub"
43
44
#define IKED_VENDOR_ID    "OpenIKED-"
45
46
#define IKED_OCSP_RESPCERT  "ocsp/responder.crt"
47
48
#define IKED_OPT_VERBOSE  0x00000001
49
#define IKED_OPT_NOACTION 0x00000002
50
#define IKED_OPT_PASSIVE  0x00000004
51
52
#define IKED_IKE_PORT   500
53
#define IKED_NATT_PORT    4500
54
55
#define IKED_NONCE_MIN    16  /* XXX 128 bits */
56
#define IKED_NONCE_SIZE   32  /* XXX 256 bits */
57
58
0
#define IKED_COOKIE_MIN   1  /* min 1 bytes */
59
0
#define IKED_COOKIE_MAX   64  /* max 64 bytes */
60
61
0
#define IKED_COOKIE2_MIN  8  /* min 8 bytes */
62
0
#define IKED_COOKIE2_MAX  64  /* max 64 bytes */
63
64
#define IKED_ID_SIZE    1024  /* XXX should be dynamic */
65
#define IKED_PSK_SIZE   1024  /* XXX should be dynamic */
66
25.5k
#define IKED_MSGBUF_MAX   8192
67
#define IKED_CFG_MAX    16  /* maximum CP attributes */
68
#define IKED_IPPROTO_MAX  16
69
#define IKED_TAG_SIZE   64
70
902k
#define IKED_CYCLE_BUFFERS  8  /* # of static buffers for mapping */
71
#define IKED_PASSWORD_SIZE  256 /* limited by most EAP types */
72
73
#define IKED_LIFETIME_BYTES 4294967296ULL /* 4 GB */
74
#define IKED_LIFETIME_SECONDS 10800     /* 3 hours */
75
76
242k
#define IKED_E      0x1000  /* Decrypted flag */
77
78
struct iked_constmap {
79
  unsigned int   cm_type;
80
  const char  *cm_name;
81
  const char  *cm_descr;
82
};
83
84
struct iked_transform {
85
  uint8_t        xform_type;
86
  uint16_t       xform_id;
87
  uint16_t       xform_length;
88
  uint16_t       xform_keylength;
89
  unsigned int       xform_score;
90
  struct iked_constmap    *xform_map;
91
};
92
93
enum imsg_type {
94
  IMSG_NONE,
95
  IMSG_CTL_OK,
96
  IMSG_CTL_FAIL,
97
  IMSG_CTL_VERBOSE,
98
  IMSG_CTL_NOTIFY,
99
  IMSG_CTL_RELOAD,
100
  IMSG_CTL_RESET,
101
  IMSG_CTL_COUPLE,
102
  IMSG_CTL_DECOUPLE,
103
  IMSG_CTL_ACTIVE,
104
  IMSG_CTL_PASSIVE,
105
  IMSG_CTL_RESET_ID,
106
  IMSG_CTL_SHOW_SA,
107
  IMSG_CTL_STATIC,
108
  IMSG_COMPILE,
109
  IMSG_UDP_SOCKET,
110
  IMSG_PFKEY_SOCKET,
111
  IMSG_IKE_MESSAGE,
112
  IMSG_CFG_POLICY,
113
  IMSG_CFG_FLOW,
114
  IMSG_CFG_USER,
115
  IMSG_CERTREQ,
116
  IMSG_CERT,
117
  IMSG_CERTVALID,
118
  IMSG_CERTINVALID,
119
  IMSG_CERT_PARTIAL_CHAIN,
120
  IMSG_SCERT,
121
  IMSG_IF_ADDADDR,
122
  IMSG_IF_DELADDR,
123
  IMSG_VROUTE_ADD,
124
  IMSG_VROUTE_DEL,
125
  IMSG_VROUTE_CLONE,
126
  IMSG_VDNS_ADD,
127
  IMSG_VDNS_DEL,
128
  IMSG_OCSP_FD,
129
  IMSG_OCSP_CFG,
130
  IMSG_AUTH,
131
  IMSG_PRIVKEY,
132
  IMSG_PUBKEY,
133
  IMSG_CTL_SHOW_CERTSTORE,
134
  IMSG_CTL_SHOW_STATS,
135
  IMSG_CTL_PROCFD,
136
};
137
138
enum privsep_procid {
139
  PROC_PARENT = 0,
140
  PROC_CONTROL,
141
  PROC_CERT,
142
  PROC_IKEV2,
143
  PROC_MAX
144
};
145
146
enum flushmode {
147
  RESET_RELOAD  = 0,
148
  RESET_ALL,
149
  RESET_CA,
150
  RESET_POLICY,
151
  RESET_SA,
152
  RESET_USER,
153
};
154
155
#ifndef nitems
156
#define nitems(_a)   (sizeof((_a)) / sizeof((_a)[0]))
157
#endif
158
159
#endif /* IKED_TYPES_H */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/types.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: types.h,v 1.52 2023/03/04 22:22:51 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#ifndef IKED_TYPES_H
21
#define IKED_TYPES_H
22
23
#ifndef IKED_USER
24
#define IKED_USER   "_iked"
25
#endif
26
27
#ifndef IKED_CONFIG
28
#define IKED_CONFIG   "/etc/iked.conf"
29
#endif
30
31
#define IKED_SOCKET   "/var/run/iked.sock"
32
33
#ifndef IKED_CA
34
#define IKED_CA     "/etc/iked/"
35
#endif
36
37
#define IKED_CA_DIR   "ca/"
38
#define IKED_CRL_DIR    "crls/"
39
#define IKED_CERT_DIR   "certs/"
40
#define IKED_PUBKEY_DIR   "pubkeys/"
41
#define IKED_PRIVKEY    IKED_CA "private/local.key"
42
#define IKED_PUBKEY   "local.pub"
43
44
#define IKED_VENDOR_ID    "OpenIKED-"
45
46
#define IKED_OCSP_RESPCERT  "ocsp/responder.crt"
47
48
#define IKED_OPT_VERBOSE  0x00000001
49
#define IKED_OPT_NOACTION 0x00000002
50
#define IKED_OPT_PASSIVE  0x00000004
51
52
#define IKED_IKE_PORT   500
53
#define IKED_NATT_PORT    4500
54
55
#define IKED_NONCE_MIN    16  /* XXX 128 bits */
56
#define IKED_NONCE_SIZE   32  /* XXX 256 bits */
57
58
0
#define IKED_COOKIE_MIN   1  /* min 1 bytes */
59
0
#define IKED_COOKIE_MAX   64  /* max 64 bytes */
60
61
0
#define IKED_COOKIE2_MIN  8  /* min 8 bytes */
62
0
#define IKED_COOKIE2_MAX  64  /* max 64 bytes */
63
64
#define IKED_ID_SIZE    1024  /* XXX should be dynamic */
65
#define IKED_PSK_SIZE   1024  /* XXX should be dynamic */
66
25.5k
#define IKED_MSGBUF_MAX   8192
67
#define IKED_CFG_MAX    16  /* maximum CP attributes */
68
#define IKED_IPPROTO_MAX  16
69
#define IKED_TAG_SIZE   64
70
902k
#define IKED_CYCLE_BUFFERS  8  /* # of static buffers for mapping */
71
#define IKED_PASSWORD_SIZE  256 /* limited by most EAP types */
72
73
#define IKED_LIFETIME_BYTES 4294967296ULL /* 4 GB */
74
#define IKED_LIFETIME_SECONDS 10800     /* 3 hours */
75
76
242k
#define IKED_E      0x1000  /* Decrypted flag */
77
78
struct iked_constmap {
79
  unsigned int   cm_type;
80
  const char  *cm_name;
81
  const char  *cm_descr;
82
};
83
84
struct iked_transform {
85
  uint8_t        xform_type;
86
  uint16_t       xform_id;
87
  uint16_t       xform_length;
88
  uint16_t       xform_keylength;
89
  unsigned int       xform_score;
90
  struct iked_constmap    *xform_map;
91
};
92
93
enum imsg_type {
94
  IMSG_NONE,
95
  IMSG_CTL_OK,
96
  IMSG_CTL_FAIL,
97
  IMSG_CTL_VERBOSE,
98
  IMSG_CTL_NOTIFY,
99
  IMSG_CTL_RELOAD,
100
  IMSG_CTL_RESET,
101
  IMSG_CTL_COUPLE,
102
  IMSG_CTL_DECOUPLE,
103
  IMSG_CTL_ACTIVE,
104
  IMSG_CTL_PASSIVE,
105
  IMSG_CTL_RESET_ID,
106
  IMSG_CTL_SHOW_SA,
107
  IMSG_CTL_STATIC,
108
  IMSG_COMPILE,
109
  IMSG_UDP_SOCKET,
110
  IMSG_PFKEY_SOCKET,
111
  IMSG_IKE_MESSAGE,
112
  IMSG_CFG_POLICY,
113
  IMSG_CFG_FLOW,
114
  IMSG_CFG_USER,
115
  IMSG_CERTREQ,
116
  IMSG_CERT,
117
  IMSG_CERTVALID,
118
  IMSG_CERTINVALID,
119
  IMSG_CERT_PARTIAL_CHAIN,
120
  IMSG_SCERT,
121
  IMSG_IF_ADDADDR,
122
  IMSG_IF_DELADDR,
123
  IMSG_VROUTE_ADD,
124
  IMSG_VROUTE_DEL,
125
  IMSG_VROUTE_CLONE,
126
  IMSG_VDNS_ADD,
127
  IMSG_VDNS_DEL,
128
  IMSG_OCSP_FD,
129
  IMSG_OCSP_CFG,
130
  IMSG_AUTH,
131
  IMSG_PRIVKEY,
132
  IMSG_PUBKEY,
133
  IMSG_CTL_SHOW_CERTSTORE,
134
  IMSG_CTL_SHOW_STATS,
135
  IMSG_CTL_PROCFD,
136
};
137
138
enum privsep_procid {
139
  PROC_PARENT = 0,
140
  PROC_CONTROL,
141
  PROC_CERT,
142
  PROC_IKEV2,
143
  PROC_MAX
144
};
145
146
enum flushmode {
147
  RESET_RELOAD  = 0,
148
  RESET_ALL,
149
  RESET_CA,
150
  RESET_POLICY,
151
  RESET_SA,
152
  RESET_USER,
153
};
154
155
#ifndef nitems
156
#define nitems(_a)   (sizeof((_a)) / sizeof((_a)[0]))
157
#endif
158
159
#endif /* IKED_TYPES_H */
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/iked/util.c.html b/coverage/latest/report/linux/src/openiked-portable/iked/util.c.html index 01423c044..f82c19f39 100644 --- a/coverage/latest/report/linux/src/openiked-portable/iked/util.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/iked/util.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/util.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: util.c,v 1.43 2023/07/28 11:23:03 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2021 Tobias Heider <tobhe@openbsd.org>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/queue.h>
22
#include <sys/socket.h>
23
#include <sys/uio.h>
24
25
#include <netinet/in.h>
26
#include <netinet/ip_ipsp.h>
27
28
#include <netdb.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <unistd.h>
32
#include <string.h>
33
#include <errno.h>
34
#include <limits.h>
35
#include <fcntl.h>
36
#include <ctype.h>
37
#include <event.h>
38
39
#include "iked.h"
40
#include "ikev2.h"
41
42
int
43
socket_af(struct sockaddr *sa, in_port_t port)
44
0
{
45
0
  errno = 0;
46
0
  switch (sa->sa_family) {
47
0
  case AF_INET:
48
0
    ((struct sockaddr_in *)sa)->sin_port = port;
49
#ifdef HAVE_SOCKADDR_SA_LEN
50
    ((struct sockaddr_in *)sa)->sin_len =
51
        sizeof(struct sockaddr_in);
52
#endif
53
0
    break;
54
0
  case AF_INET6:
55
0
    ((struct sockaddr_in6 *)sa)->sin6_port = port;
56
#ifdef HAVE_SOCKADDR_SA_LEN
57
    ((struct sockaddr_in6 *)sa)->sin6_len =
58
        sizeof(struct sockaddr_in6);
59
#endif
60
0
    break;
61
0
  default:
62
0
    errno = EPFNOSUPPORT;
63
0
    return (-1);
64
0
  }
65
66
0
  return (0);
67
0
}
68
69
in_port_t
70
socket_getport(struct sockaddr *sa)
71
19.8k
{
72
19.8k
  switch (sa->sa_family) {
73
17.1k
  case AF_INET:
74
17.1k
    return (ntohs(((struct sockaddr_in *)sa)->sin_port));
75
2.63k
  case AF_INET6:
76
2.63k
    return (ntohs(((struct sockaddr_in6 *)sa)->sin6_port));
77
0
  default:
78
0
    return (0);
79
19.8k
  }
80
81
  /* NOTREACHED */
82
0
  return (0);
83
19.8k
}
84
85
int
86
socket_setport(struct sockaddr *sa, in_port_t port)
87
0
{
88
0
  switch (sa->sa_family) {
89
0
  case AF_INET:
90
0
    ((struct sockaddr_in *)sa)->sin_port = htons(port);
91
0
    break;
92
0
  case AF_INET6:
93
0
    ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
94
0
    break;
95
0
  default:
96
0
    return (-1);
97
0
  }
98
0
  return (0);
99
0
}
100
101
int
102
socket_getaddr(int s, struct sockaddr_storage *ss)
103
0
{
104
0
  socklen_t sslen = sizeof(*ss);
105
106
0
  return (getsockname(s, (struct sockaddr *)ss, &sslen));
107
0
}
108
109
int
110
socket_bypass(int s, struct sockaddr *sa)
111
0
{
112
#if defined(__OpenBSD__)
113
  int  v, *a;
114
  int  a4[] = {
115
        IPPROTO_IP,
116
        IP_AUTH_LEVEL,
117
        IP_ESP_TRANS_LEVEL,
118
        IP_ESP_NETWORK_LEVEL,
119
#ifdef IPV6_IPCOMP_LEVEL
120
        IP_IPCOMP_LEVEL
121
#endif
122
  };
123
  int  a6[] = {
124
        IPPROTO_IPV6,
125
        IPV6_AUTH_LEVEL,
126
        IPV6_ESP_TRANS_LEVEL,
127
        IPV6_ESP_NETWORK_LEVEL,
128
#ifdef IPV6_IPCOMP_LEVEL
129
        IPV6_IPCOMP_LEVEL
130
#endif
131
  };
132
133
  switch (sa->sa_family) {
134
  case AF_INET:
135
    a = a4;
136
    break;
137
  case AF_INET6:
138
    a = a6;
139
    break;
140
  default:
141
    log_warn("%s: invalid address family", __func__);
142
    return (-1);
143
  }
144
145
  v = IPSEC_LEVEL_BYPASS;
146
  if (setsockopt(s, a[0], a[1], &v, sizeof(v)) == -1) {
147
    log_warn("%s: AUTH_LEVEL", __func__);
148
    return (-1);
149
  }
150
  if (setsockopt(s, a[0], a[2], &v, sizeof(v)) == -1) {
151
    log_warn("%s: ESP_TRANS_LEVEL", __func__);
152
    return (-1);
153
  }
154
  if (setsockopt(s, a[0], a[3], &v, sizeof(v)) == -1) {
155
    log_warn("%s: ESP_NETWORK_LEVEL", __func__);
156
    return (-1);
157
  }
158
#ifdef IP_IPCOMP_LEVEL
159
  if (setsockopt(s, a[0], a[4], &v, sizeof(v)) == -1) {
160
    log_warn("%s: IPCOMP_LEVEL", __func__);
161
    return (-1);
162
  }
163
#endif
164
#else /* __OpenBSD__ */
165
0
  int *a;
166
0
  int  a4[] = {
167
0
        IPPROTO_IP,
168
0
        IP_IPSEC_POLICY
169
0
  };
170
0
  int  a6[] = {
171
0
        IPPROTO_IPV6,
172
0
        IPV6_IPSEC_POLICY,
173
0
  };
174
0
  struct sadb_x_policy pol = {
175
0
        SADB_UPDATE,
176
0
        SADB_EXT_SENSITIVITY,
177
0
        IPSEC_POLICY_BYPASS,
178
0
        0, 0, 0, 0
179
0
  };
180
181
0
  switch (sa->sa_family) {
182
0
  case AF_INET:
183
0
    a = a4;
184
0
    break;
185
0
  case AF_INET6:
186
0
    a = a6;
187
0
    break;
188
0
  default:
189
0
    log_warn("%s: invalid address family", __func__);
190
0
    return (-1);
191
0
  }
192
193
0
  pol.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
194
0
  if (setsockopt(s, a[0], a[1], &pol, sizeof(pol)) == -1) {
195
0
    log_warn("%s: IPSEC_DIR_INBOUND", __func__);
196
0
    return (-1);
197
0
  }
198
0
  pol.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
199
0
  if (setsockopt(s, a[0], a[1], &pol, sizeof(pol)) == -1) {
200
0
    log_warn("%s: IPSEC_DIR_OUTBOUND", __func__);
201
0
    return (-1);
202
0
  }
203
0
#endif /* !__OpenBSD__ */
204
205
0
  return (0);
206
0
}
207
208
int
209
udp_bind(struct sockaddr *sa, in_port_t port)
210
0
{
211
0
  int  s, val;
212
213
0
  if (socket_af(sa, port) == -1) {
214
0
    log_warn("%s: failed to set UDP port", __func__);
215
0
    return (-1);
216
0
  }
217
218
0
  if ((s = socket(sa->sa_family,
219
0
      SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP)) == -1) {
220
0
    log_warn("%s: failed to get UDP socket", __func__);
221
0
    return (-1);
222
0
  }
223
224
  /* Skip IPsec processing (don't encrypt) for IKE messages */
225
0
  if (socket_bypass(s, sa) == -1) {
226
0
    log_warn("%s: failed to bypass IPsec on IKE socket",
227
0
        __func__);
228
0
    goto bad;
229
0
  }
230
231
0
  val = 1;
232
0
  if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(int)) == -1) {
233
0
    log_warn("%s: failed to set reuseport", __func__);
234
0
    goto bad;
235
0
  }
236
0
  val = 1;
237
0
  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int)) == -1) {
238
0
    log_warn("%s: failed to set reuseaddr", __func__);
239
0
    goto bad;
240
0
  }
241
242
0
  if (sa->sa_family == AF_INET) {
243
0
#if defined(IP_RECVORIGDSTADDR)
244
0
    val = 1;
245
0
    if (setsockopt(s, IPPROTO_IP, IP_RECVORIGDSTADDR,
246
0
        &val, sizeof(int)) == -1) {
247
0
      log_warn("%s: failed to set IPv4 packet info",
248
0
          __func__);
249
0
      goto bad;
250
0
    }
251
#elif defined(IP_RECVDSTADDR)
252
    val = 1;
253
    if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
254
        &val, sizeof(int)) == -1) {
255
      log_warn("%s: failed to set IPv4 packet info",
256
          __func__);
257
      goto bad;
258
    }
259
#endif
260
0
  } else {
261
0
#ifdef IPV6_RECVPKTINFO
262
0
    val = 1;
263
0
    if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
264
0
        &val, sizeof(int)) == -1) {
265
0
      log_warn("%s: failed to set IPv6 packet info",
266
0
          __func__);
267
0
      goto bad;
268
0
    }
269
0
#endif
270
0
  }
271
272
0
  if (bind(s, sa, SA_LEN(sa)) == -1) {
273
0
    log_warn("%s: failed to bind UDP socket", __func__);
274
0
    goto bad;
275
0
  }
276
277
0
  return (s);
278
0
 bad:
279
0
  close(s);
280
0
  return (-1);
281
0
}
282
283
int
284
sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen)
285
0
{
286
0
  struct sockaddr_in  *a4, *b4;
287
0
  struct sockaddr_in6 *a6, *b6;
288
0
  uint32_t     av[4], bv[4], mv[4];
289
290
0
  if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC)
291
0
    return (0);
292
0
  else if (a->sa_family > b->sa_family)
293
0
    return (1);
294
0
  else if (a->sa_family < b->sa_family)
295
0
    return (-1);
296
297
0
  if (prefixlen == -1)
298
0
    memset(&mv, 0xff, sizeof(mv));
299
300
0
  switch (a->sa_family) {
301
0
  case AF_INET:
302
0
    a4 = (struct sockaddr_in *)a;
303
0
    b4 = (struct sockaddr_in *)b;
304
305
0
    av[0] = a4->sin_addr.s_addr;
306
0
    bv[0] = b4->sin_addr.s_addr;
307
0
    if (prefixlen != -1)
308
0
      mv[0] = prefixlen2mask(prefixlen);
309
310
0
    if ((av[0] & mv[0]) > (bv[0] & mv[0]))
311
0
      return (1);
312
0
    if ((av[0] & mv[0]) < (bv[0] & mv[0]))
313
0
      return (-1);
314
0
    break;
315
0
  case AF_INET6:
316
0
    a6 = (struct sockaddr_in6 *)a;
317
0
    b6 = (struct sockaddr_in6 *)b;
318
319
0
    memcpy(&av, &a6->sin6_addr.s6_addr, 16);
320
0
    memcpy(&bv, &b6->sin6_addr.s6_addr, 16);
321
0
    if (prefixlen != -1)
322
0
      prefixlen2mask6(prefixlen, mv);
323
324
0
    if ((av[3] & mv[3]) > (bv[3] & mv[3]))
325
0
      return (1);
326
0
    if ((av[3] & mv[3]) < (bv[3] & mv[3]))
327
0
      return (-1);
328
0
    if ((av[2] & mv[2]) > (bv[2] & mv[2]))
329
0
      return (1);
330
0
    if ((av[2] & mv[2]) < (bv[2] & mv[2]))
331
0
      return (-1);
332
0
    if ((av[1] & mv[1]) > (bv[1] & mv[1]))
333
0
      return (1);
334
0
    if ((av[1] & mv[1]) < (bv[1] & mv[1]))
335
0
      return (-1);
336
0
    if ((av[0] & mv[0]) > (bv[0] & mv[0]))
337
0
      return (1);
338
0
    if ((av[0] & mv[0]) < (bv[0] & mv[0]))
339
0
      return (-1);
340
0
    break;
341
0
  }
342
343
0
  return (0);
344
0
}
345
346
ssize_t
347
sendtofrom(int s, void *buf, size_t len, int flags, struct sockaddr *to,
348
    socklen_t tolen, struct sockaddr *from, socklen_t fromlen)
349
0
{
350
0
  struct iovec     iov;
351
0
  struct msghdr    msg;
352
0
  struct cmsghdr    *cmsg;
353
#ifdef IP_SENDSRCADDR
354
  struct sockaddr_in  *in;
355
#endif
356
0
#ifdef IPV6_PKTINFO
357
0
  struct in6_pktinfo  *pkt6;
358
0
  struct sockaddr_in6 *in6;
359
0
#endif
360
0
  union {
361
0
    struct cmsghdr  hdr;
362
0
    char    inbuf[CMSG_SPACE(sizeof(struct in_addr))];
363
0
    char    in6buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
364
0
  } cmsgbuf;
365
366
0
  bzero(&msg, sizeof(msg));
367
0
  bzero(&cmsgbuf, sizeof(cmsgbuf));
368
369
0
  iov.iov_base = buf;
370
0
  iov.iov_len = len;
371
0
  msg.msg_iov = &iov;
372
0
  msg.msg_iovlen = 1;
373
0
  msg.msg_name = to;
374
0
  msg.msg_namelen = tolen;
375
0
  msg.msg_controllen = 0;
376
377
0
  switch (to->sa_family) {
378
0
  case AF_INET:
379
#ifdef IP_SENDSRCADDR
380
    in = (struct sockaddr_in *)from;
381
    if (in->sin_addr.s_addr == INADDR_ANY)
382
      break;
383
    msg.msg_control = &cmsgbuf;
384
    msg.msg_controllen += sizeof(cmsgbuf.inbuf);
385
    cmsg = CMSG_FIRSTHDR(&msg);
386
    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
387
    cmsg->cmsg_level = IPPROTO_IP;
388
    cmsg->cmsg_type = IP_SENDSRCADDR;
389
    memcpy(CMSG_DATA(cmsg), &in->sin_addr, sizeof(struct in_addr));
390
#endif
391
0
    break;
392
0
  case AF_INET6:
393
0
#ifdef IPV6_PKTINFO
394
0
    msg.msg_control = &cmsgbuf;
395
0
    msg.msg_controllen += sizeof(cmsgbuf.in6buf);
396
0
    cmsg = CMSG_FIRSTHDR(&msg);
397
0
    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
398
0
    cmsg->cmsg_level = IPPROTO_IPV6;
399
0
    cmsg->cmsg_type = IPV6_PKTINFO;
400
0
    in6 = (struct sockaddr_in6 *)from;
401
0
    pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
402
0
    pkt6->ipi6_addr = in6->sin6_addr;
403
0
#endif
404
0
    break;
405
0
  }
406
407
0
  return sendmsg(s, &msg, flags);
408
0
}
409
410
ssize_t
411
recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from,
412
    socklen_t *fromlen, struct sockaddr *to, socklen_t *tolen)
413
0
{
414
0
  struct iovec     iov;
415
0
  struct msghdr    msg;
416
0
  struct cmsghdr    *cmsg;
417
#if !defined(IP_RECVORIGDSTADDR) && defined(IP_RECVDSTADDR)
418
  struct sockaddr_in  *in;
419
#endif
420
0
#ifdef IPV6_PKTINFO
421
0
  struct in6_pktinfo  *pkt6;
422
0
  struct sockaddr_in6 *in6;
423
0
#endif
424
0
  ssize_t      ret;
425
0
  union {
426
0
    struct cmsghdr hdr;
427
0
    char  buf[CMSG_SPACE(sizeof(struct sockaddr_storage))];
428
0
  } cmsgbuf;
429
430
0
  bzero(&msg, sizeof(msg));
431
0
  bzero(&cmsgbuf.buf, sizeof(cmsgbuf.buf));
432
433
0
  iov.iov_base = buf;
434
0
  iov.iov_len = len;
435
0
  msg.msg_iov = &iov;
436
0
  msg.msg_iovlen = 1;
437
0
  msg.msg_name = from;
438
0
  msg.msg_namelen = *fromlen;
439
0
  msg.msg_control = &cmsgbuf.buf;
440
0
  msg.msg_controllen = sizeof(cmsgbuf.buf);
441
442
0
  if ((ret = recvmsg(s, &msg, flags)) == -1)
443
0
    return (-1);
444
445
0
  *fromlen = SA_LEN(from);
446
447
0
  if (getsockname(s, to, tolen) != 0)
448
0
    *tolen = 0;
449
450
0
  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
451
0
      cmsg = CMSG_NXTHDR(&msg, cmsg)) {
452
0
    switch (from->sa_family) {
453
0
    case AF_INET:
454
0
#if defined(IP_RECVORIGDSTADDR)
455
0
      if (cmsg->cmsg_level == IPPROTO_IP &&
456
0
          cmsg->cmsg_type == IP_RECVORIGDSTADDR) {
457
0
        memcpy(to, CMSG_DATA(cmsg),
458
0
            sizeof(struct sockaddr_in));
459
0
      }
460
#elif defined(IP_RECVDSTADDR)
461
      if (cmsg->cmsg_level == IPPROTO_IP &&
462
          cmsg->cmsg_type == IP_RECVDSTADDR) {
463
        in = (struct sockaddr_in *)to;
464
        in->sin_family = AF_INET;
465
#ifdef HAVE_SOCKADDR_SA_LEN
466
        in->sin_len = *tolen = sizeof(*in);
467
#endif
468
        memcpy(&in->sin_addr, CMSG_DATA(cmsg),
469
            sizeof(struct in_addr));
470
      }
471
#endif /* defined(IP_RECVDSTADDR) */
472
0
      break;
473
0
    case AF_INET6:
474
0
#ifdef IPV6_PKTINFO
475
0
      if (cmsg->cmsg_level == IPPROTO_IPV6 &&
476
0
          cmsg->cmsg_type == IPV6_PKTINFO) {
477
0
        in6 = (struct sockaddr_in6 *)to;
478
0
        in6->sin6_family = AF_INET6;
479
#ifdef HAVE_SOCKADDR_SA_LEN
480
        in6->sin6_len = *tolen = sizeof(*in6);
481
#endif
482
0
        pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
483
0
        memcpy(&in6->sin6_addr, &pkt6->ipi6_addr,
484
0
            sizeof(struct in6_addr));
485
0
        if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
486
0
          in6->sin6_scope_id =
487
0
              pkt6->ipi6_ifindex;
488
0
      }
489
0
#endif
490
0
      break;
491
0
    }
492
0
  }
493
494
0
  return (ret);
495
0
}
496
497
const char *
498
print_spi(uint64_t spi, int size)
499
41.9k
{
500
41.9k
  static char    buf[IKED_CYCLE_BUFFERS][32];
501
41.9k
  static int     i = 0;
502
41.9k
  char      *ptr;
503
504
41.9k
  ptr = buf[i];
505
506
41.9k
  switch (size) {
507
0
  case 2:
508
0
    snprintf(ptr, 32, "0x%04x", (uint16_t)spi);
509
0
    break;
510
421
  case 4:
511
421
    snprintf(ptr, 32, "0x%08x", (uint32_t)spi);
512
421
    break;
513
31.2k
  case 8:
514
31.2k
    snprintf(ptr, 32, "0x%016llx", (long long unsigned)spi);
515
31.2k
    break;
516
10.2k
  default:
517
10.2k
    snprintf(ptr, 32, "%llu", (long long unsigned)spi);
518
10.2k
    break;
519
41.9k
  }
520
521
41.9k
  if (++i >= IKED_CYCLE_BUFFERS)
522
5.23k
    i = 0;
523
524
41.9k
  return (ptr);
525
41.9k
}
526
527
const char *
528
print_map(unsigned int type, struct iked_constmap *map)
529
840k
{
530
840k
  unsigned int     i;
531
840k
  static char    buf[IKED_CYCLE_BUFFERS][32];
532
840k
  static int     idx = 0;
533
840k
  const char    *name = NULL;
534
535
840k
  if (idx >= IKED_CYCLE_BUFFERS)
536
105k
    idx = 0;
537
840k
  bzero(buf[idx], sizeof(buf[idx]));
538
539
17.2M
  for (i = 0; map[i].cm_name != NULL; i++) {
540
16.4M
    if (map[i].cm_type == type)
541
573k
      name = map[i].cm_name;
542
16.4M
  }
543
544
840k
  if (name == NULL)
545
267k
    snprintf(buf[idx], sizeof(buf[idx]), "<UNKNOWN:%u>", type);
546
573k
  else
547
573k
    strlcpy(buf[idx], name, sizeof(buf[idx]));
548
549
840k
  return (buf[idx++]);
550
840k
}
551
552
void
553
lc_idtype(char *str)
554
0
{
555
0
  for (; *str != '\0' && *str != '/'; str++)
556
0
    *str = tolower((unsigned char)*str);
557
0
}
558
559
void
560
print_hex(const uint8_t *buf, off_t offset, size_t length)
561
181k
{
562
181k
  unsigned int   i;
563
564
181k
  if (log_getverbose() < 3 || !length)
565
181k
    return;
566
567
0
  for (i = 0; i < length; i++) {
568
0
    if (i && (i % 4) == 0) {
569
0
      if ((i % 32) == 0)
570
0
        print_debug("\n");
571
0
      else
572
0
        print_debug(" ");
573
0
    }
574
0
    print_debug("%02x", buf[offset + i]);
575
0
  }
576
0
  print_debug("\n");
577
0
}
578
579
void
580
print_hexval(const uint8_t *buf, off_t offset, size_t length)
581
0
{
582
0
  unsigned int   i;
583
584
0
  if (log_getverbose() < 2 || !length)
585
0
    return;
586
587
0
  print_debug("0x");
588
0
  for (i = 0; i < length; i++)
589
0
    print_debug("%02x", buf[offset + i]);
590
0
  print_debug("\n");
591
0
}
592
593
void
594
print_hexbuf(struct ibuf *ibuf)
595
0
{
596
0
  print_hex(ibuf_data(ibuf), 0, ibuf_size(ibuf));
597
0
}
598
599
const char *
600
print_bits(unsigned short v, unsigned char *bits)
601
0
{
602
0
  static char  buf[IKED_CYCLE_BUFFERS][BUFSIZ];
603
0
  static int   idx = 0;
604
0
  unsigned int   i, any = 0, j = 0;
605
0
  unsigned char  c;
606
607
0
  if (!bits)
608
0
    return ("");
609
610
0
  if (++idx >= IKED_CYCLE_BUFFERS)
611
0
    idx = 0;
612
613
0
  bzero(buf[idx], sizeof(buf[idx]));
614
615
0
  bits++;
616
0
  while ((i = *bits++)) {
617
0
    if (v & (1 << (i-1))) {
618
0
      if (any) {
619
0
        buf[idx][j++] = ',';
620
0
        if (j >= sizeof(buf[idx]))
621
0
          return (buf[idx]);
622
0
      }
623
0
      any = 1;
624
0
      for (; (c = *bits) > 32; bits++) {
625
0
        buf[idx][j++] = tolower((unsigned char)c);
626
0
        if (j >= sizeof(buf[idx]))
627
0
          return (buf[idx]);
628
0
      }
629
0
    } else
630
0
      for (; *bits > 32; bits++)
631
0
        ;
632
0
  }
633
634
0
  return (buf[idx]);
635
0
}
636
637
uint8_t
638
mask2prefixlen(struct sockaddr *sa)
639
0
{
640
0
  struct sockaddr_in  *sa_in = (struct sockaddr_in *)sa;
641
0
  in_addr_t    ina = sa_in->sin_addr.s_addr;
642
643
0
  if (ina == 0)
644
0
    return (0);
645
0
  else
646
0
    return (33 - ffs(ntohl(ina)));
647
0
}
648
649
uint8_t
650
mask2prefixlen6(struct sockaddr *sa)
651
0
{
652
0
  struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa;
653
0
  uint8_t     *ap, *ep;
654
0
  unsigned int     l = 0;
655
656
  /*
657
   * sin6_len is the size of the sockaddr so substract the offset of
658
   * the possibly truncated sin6_addr struct.
659
   */
660
0
  ap = (uint8_t *)&sa_in6->sin6_addr;
661
0
  ep = (uint8_t *)sa_in6 + SA_LEN(sa);
662
0
  for (; ap < ep; ap++) {
663
    /* this "beauty" is adopted from sbin/route/show.c ... */
664
0
    switch (*ap) {
665
0
    case 0xff:
666
0
      l += 8;
667
0
      break;
668
0
    case 0xfe:
669
0
      l += 7;
670
0
      goto done;
671
0
    case 0xfc:
672
0
      l += 6;
673
0
      goto done;
674
0
    case 0xf8:
675
0
      l += 5;
676
0
      goto done;
677
0
    case 0xf0:
678
0
      l += 4;
679
0
      goto done;
680
0
    case 0xe0:
681
0
      l += 3;
682
0
      goto done;
683
0
    case 0xc0:
684
0
      l += 2;
685
0
      goto done;
686
0
    case 0x80:
687
0
      l += 1;
688
0
      goto done;
689
0
    case 0x00:
690
0
      goto done;
691
0
    default:
692
0
      fatalx("non contiguous inet6 netmask");
693
0
    }
694
0
  }
695
696
0
done:
697
0
  if (l > sizeof(struct in6_addr) * 8)
698
0
    fatalx("%s: prefixlen %d out of bound", __func__, l);
699
0
  return (l);
700
0
}
701
702
uint32_t
703
prefixlen2mask(uint8_t prefixlen)
704
0
{
705
0
  if (prefixlen == 0)
706
0
    return (0);
707
708
0
  if (prefixlen > 32)
709
0
    prefixlen = 32;
710
711
0
  return (htonl(0xffffffff << (32 - prefixlen)));
712
0
}
713
714
struct in6_addr *
715
prefixlen2mask6(uint8_t prefixlen, uint32_t *mask)
716
0
{
717
0
  static struct in6_addr  s6;
718
0
  int     i;
719
720
0
  if (prefixlen > 128)
721
0
    prefixlen = 128;
722
723
0
  bzero(&s6, sizeof(s6));
724
0
  for (i = 0; i < prefixlen / 8; i++)
725
0
    s6.s6_addr[i] = 0xff;
726
0
  i = prefixlen % 8;
727
0
  if (i)
728
0
    s6.s6_addr[prefixlen / 8] = 0xff00 >> i;
729
730
0
  memcpy(mask, &s6, sizeof(s6));
731
732
0
  return (&s6);
733
0
}
734
735
const char *
736
print_addr(void *addr)
737
19.8k
{
738
19.8k
  static char  sbuf[IKED_CYCLE_BUFFERS][NI_MAXHOST + 7];
739
19.8k
  static int   idx;
740
19.8k
  struct sockaddr *sa = addr;
741
19.8k
  char    *buf;
742
19.8k
  size_t     len;
743
19.8k
  char     pbuf[7];
744
19.8k
  in_port_t  port;
745
746
19.8k
  buf = sbuf[idx];
747
19.8k
  len = sizeof(sbuf[idx]);
748
19.8k
  if (++idx >= IKED_CYCLE_BUFFERS)
749
2.47k
    idx = 0;
750
751
19.8k
  if (sa->sa_family == AF_UNSPEC) {
752
0
    strlcpy(buf, "any", len);
753
0
    return (buf);
754
0
  }
755
756
19.8k
  if (getnameinfo(sa, SA_LEN(sa),
757
19.8k
      buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
758
0
    strlcpy(buf, "unknown", len);
759
0
    return (buf);
760
0
  }
761
762
19.8k
  if ((port = socket_getport(sa)) != 0) {
763
0
    snprintf(pbuf, sizeof(pbuf), ":%d", port);
764
0
    (void)strlcat(buf, pbuf, len);
765
0
  }
766
767
19.8k
  return (buf);
768
19.8k
}
769
770
char *
771
get_string(uint8_t *ptr, size_t len)
772
0
{
773
0
  size_t   i;
774
775
0
  for (i = 0; i < len; i++)
776
0
    if (!isprint(ptr[i]))
777
0
      break;
778
779
0
  return strndup(ptr, i);
780
0
}
781
782
const char *
783
print_proto(uint8_t proto)
784
0
{
785
0
  struct protoent *p;
786
0
  static char  buf[IKED_CYCLE_BUFFERS][BUFSIZ];
787
0
  static int   idx = 0;
788
789
0
  if (idx >= IKED_CYCLE_BUFFERS)
790
0
    idx = 0;
791
792
0
  if ((p = getprotobynumber(proto)) != NULL)
793
0
    strlcpy(buf[idx], p->p_name, sizeof(buf[idx]));
794
0
  else
795
0
    snprintf(buf[idx], sizeof(buf), "%u", proto);
796
797
798
0
  return (buf[idx++]);
799
0
}
800
801
int
802
expand_string(char *label, size_t len, const char *srch, const char *repl)
803
0
{
804
0
  char *tmp;
805
0
  char *p, *q;
806
807
0
  if ((tmp = calloc(1, len)) == NULL) {
808
0
    log_debug("%s: calloc", __func__);
809
0
    return (-1);
810
0
  }
811
0
  p = label;
812
0
  while ((q = strstr(p, srch)) != NULL) {
813
0
    *q = '\0';
814
0
    if ((strlcat(tmp, p, len) >= len) ||
815
0
        (strlcat(tmp, repl, len) >= len)) {
816
0
      log_debug("%s: string too long", __func__);
817
0
      free(tmp);
818
0
      return (-1);
819
0
    }
820
0
    q += strlen(srch);
821
0
    p = q;
822
0
  }
823
0
  if (strlcat(tmp, p, len) >= len) {
824
0
    log_debug("%s: string too long", __func__);
825
0
    free(tmp);
826
0
    return (-1);
827
0
  }
828
0
  strlcpy(label, tmp, len); /* always fits */
829
0
  free(tmp);
830
831
0
  return (0);
832
0
}
833
834
uint8_t *
835
string2unicode(const char *ascii, size_t *outlen)
836
0
{
837
0
  uint8_t   *uc = NULL;
838
0
  size_t     i, len = strlen(ascii);
839
840
0
  if ((uc = calloc(1, (len * 2) + 2)) == NULL)
841
0
    return (NULL);
842
843
0
  for (i = 0; i < len; i++) {
844
    /* XXX what about the byte order? */
845
0
    uc[i * 2] = ascii[i];
846
0
  }
847
0
  *outlen = len * 2;
848
849
0
  return (uc);
850
0
}
851
852
void
853
print_debug(const char *emsg, ...)
854
0
{
855
0
  va_list  ap;
856
857
0
  if (log_getverbose() > 2) {
858
0
    va_start(ap, emsg);
859
0
    vfprintf(stderr, emsg, ap);
860
0
    va_end(ap);
861
0
  }
862
0
}
863
864
void
865
print_verbose(const char *emsg, ...)
866
0
{
867
0
  va_list  ap;
868
869
0
  if (log_getverbose()) {
870
0
    va_start(ap, emsg);
871
0
    vfprintf(stderr, emsg, ap);
872
0
    va_end(ap);
873
0
  }
874
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/util.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: util.c,v 1.43 2023/07/28 11:23:03 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2021 Tobias Heider <tobhe@openbsd.org>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/queue.h>
22
#include <sys/socket.h>
23
#include <sys/uio.h>
24
25
#include <netinet/in.h>
26
#include <netinet/ip_ipsp.h>
27
28
#include <netdb.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <unistd.h>
32
#include <string.h>
33
#include <errno.h>
34
#include <limits.h>
35
#include <fcntl.h>
36
#include <ctype.h>
37
#include <event.h>
38
39
#include "iked.h"
40
#include "ikev2.h"
41
42
int
43
socket_af(struct sockaddr *sa, in_port_t port)
44
0
{
45
0
  errno = 0;
46
0
  switch (sa->sa_family) {
47
0
  case AF_INET:
48
0
    ((struct sockaddr_in *)sa)->sin_port = port;
49
#ifdef HAVE_SOCKADDR_SA_LEN
50
    ((struct sockaddr_in *)sa)->sin_len =
51
        sizeof(struct sockaddr_in);
52
#endif
53
0
    break;
54
0
  case AF_INET6:
55
0
    ((struct sockaddr_in6 *)sa)->sin6_port = port;
56
#ifdef HAVE_SOCKADDR_SA_LEN
57
    ((struct sockaddr_in6 *)sa)->sin6_len =
58
        sizeof(struct sockaddr_in6);
59
#endif
60
0
    break;
61
0
  default:
62
0
    errno = EPFNOSUPPORT;
63
0
    return (-1);
64
0
  }
65
66
0
  return (0);
67
0
}
68
69
in_port_t
70
socket_getport(struct sockaddr *sa)
71
19.8k
{
72
19.8k
  switch (sa->sa_family) {
73
17.1k
  case AF_INET:
74
17.1k
    return (ntohs(((struct sockaddr_in *)sa)->sin_port));
75
2.63k
  case AF_INET6:
76
2.63k
    return (ntohs(((struct sockaddr_in6 *)sa)->sin6_port));
77
0
  default:
78
0
    return (0);
79
19.8k
  }
80
81
  /* NOTREACHED */
82
0
  return (0);
83
19.8k
}
84
85
int
86
socket_setport(struct sockaddr *sa, in_port_t port)
87
0
{
88
0
  switch (sa->sa_family) {
89
0
  case AF_INET:
90
0
    ((struct sockaddr_in *)sa)->sin_port = htons(port);
91
0
    break;
92
0
  case AF_INET6:
93
0
    ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
94
0
    break;
95
0
  default:
96
0
    return (-1);
97
0
  }
98
0
  return (0);
99
0
}
100
101
int
102
socket_getaddr(int s, struct sockaddr_storage *ss)
103
0
{
104
0
  socklen_t sslen = sizeof(*ss);
105
106
0
  return (getsockname(s, (struct sockaddr *)ss, &sslen));
107
0
}
108
109
int
110
socket_bypass(int s, struct sockaddr *sa)
111
0
{
112
#if defined(__OpenBSD__)
113
  int  v, *a;
114
  int  a4[] = {
115
        IPPROTO_IP,
116
        IP_AUTH_LEVEL,
117
        IP_ESP_TRANS_LEVEL,
118
        IP_ESP_NETWORK_LEVEL,
119
#ifdef IPV6_IPCOMP_LEVEL
120
        IP_IPCOMP_LEVEL
121
#endif
122
  };
123
  int  a6[] = {
124
        IPPROTO_IPV6,
125
        IPV6_AUTH_LEVEL,
126
        IPV6_ESP_TRANS_LEVEL,
127
        IPV6_ESP_NETWORK_LEVEL,
128
#ifdef IPV6_IPCOMP_LEVEL
129
        IPV6_IPCOMP_LEVEL
130
#endif
131
  };
132
133
  switch (sa->sa_family) {
134
  case AF_INET:
135
    a = a4;
136
    break;
137
  case AF_INET6:
138
    a = a6;
139
    break;
140
  default:
141
    log_warn("%s: invalid address family", __func__);
142
    return (-1);
143
  }
144
145
  v = IPSEC_LEVEL_BYPASS;
146
  if (setsockopt(s, a[0], a[1], &v, sizeof(v)) == -1) {
147
    log_warn("%s: AUTH_LEVEL", __func__);
148
    return (-1);
149
  }
150
  if (setsockopt(s, a[0], a[2], &v, sizeof(v)) == -1) {
151
    log_warn("%s: ESP_TRANS_LEVEL", __func__);
152
    return (-1);
153
  }
154
  if (setsockopt(s, a[0], a[3], &v, sizeof(v)) == -1) {
155
    log_warn("%s: ESP_NETWORK_LEVEL", __func__);
156
    return (-1);
157
  }
158
#ifdef IP_IPCOMP_LEVEL
159
  if (setsockopt(s, a[0], a[4], &v, sizeof(v)) == -1) {
160
    log_warn("%s: IPCOMP_LEVEL", __func__);
161
    return (-1);
162
  }
163
#endif
164
#else /* __OpenBSD__ */
165
0
  int *a;
166
0
  int  a4[] = {
167
0
        IPPROTO_IP,
168
0
        IP_IPSEC_POLICY
169
0
  };
170
0
  int  a6[] = {
171
0
        IPPROTO_IPV6,
172
0
        IPV6_IPSEC_POLICY,
173
0
  };
174
0
  struct sadb_x_policy pol = {
175
0
        SADB_UPDATE,
176
0
        SADB_EXT_SENSITIVITY,
177
0
        IPSEC_POLICY_BYPASS,
178
0
        0, 0, 0, 0
179
0
  };
180
181
0
  switch (sa->sa_family) {
182
0
  case AF_INET:
183
0
    a = a4;
184
0
    break;
185
0
  case AF_INET6:
186
0
    a = a6;
187
0
    break;
188
0
  default:
189
0
    log_warn("%s: invalid address family", __func__);
190
0
    return (-1);
191
0
  }
192
193
0
  pol.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
194
0
  if (setsockopt(s, a[0], a[1], &pol, sizeof(pol)) == -1) {
195
0
    log_warn("%s: IPSEC_DIR_INBOUND", __func__);
196
0
    return (-1);
197
0
  }
198
0
  pol.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
199
0
  if (setsockopt(s, a[0], a[1], &pol, sizeof(pol)) == -1) {
200
0
    log_warn("%s: IPSEC_DIR_OUTBOUND", __func__);
201
0
    return (-1);
202
0
  }
203
0
#endif /* !__OpenBSD__ */
204
205
0
  return (0);
206
0
}
207
208
int
209
udp_bind(struct sockaddr *sa, in_port_t port)
210
0
{
211
0
  int  s, val;
212
213
0
  if (socket_af(sa, port) == -1) {
214
0
    log_warn("%s: failed to set UDP port", __func__);
215
0
    return (-1);
216
0
  }
217
218
0
  if ((s = socket(sa->sa_family,
219
0
      SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP)) == -1) {
220
0
    log_warn("%s: failed to get UDP socket", __func__);
221
0
    return (-1);
222
0
  }
223
224
  /* Skip IPsec processing (don't encrypt) for IKE messages */
225
0
  if (socket_bypass(s, sa) == -1) {
226
0
    log_warn("%s: failed to bypass IPsec on IKE socket",
227
0
        __func__);
228
0
    goto bad;
229
0
  }
230
231
0
  val = 1;
232
0
  if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(int)) == -1) {
233
0
    log_warn("%s: failed to set reuseport", __func__);
234
0
    goto bad;
235
0
  }
236
0
  val = 1;
237
0
  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int)) == -1) {
238
0
    log_warn("%s: failed to set reuseaddr", __func__);
239
0
    goto bad;
240
0
  }
241
242
0
  if (sa->sa_family == AF_INET) {
243
0
#if defined(IP_RECVORIGDSTADDR)
244
0
    val = 1;
245
0
    if (setsockopt(s, IPPROTO_IP, IP_RECVORIGDSTADDR,
246
0
        &val, sizeof(int)) == -1) {
247
0
      log_warn("%s: failed to set IPv4 packet info",
248
0
          __func__);
249
0
      goto bad;
250
0
    }
251
#elif defined(IP_RECVDSTADDR)
252
    val = 1;
253
    if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
254
        &val, sizeof(int)) == -1) {
255
      log_warn("%s: failed to set IPv4 packet info",
256
          __func__);
257
      goto bad;
258
    }
259
#endif
260
0
  } else {
261
0
#ifdef IPV6_RECVPKTINFO
262
0
    val = 1;
263
0
    if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
264
0
        &val, sizeof(int)) == -1) {
265
0
      log_warn("%s: failed to set IPv6 packet info",
266
0
          __func__);
267
0
      goto bad;
268
0
    }
269
0
#endif
270
0
  }
271
272
0
  if (bind(s, sa, SA_LEN(sa)) == -1) {
273
0
    log_warn("%s: failed to bind UDP socket", __func__);
274
0
    goto bad;
275
0
  }
276
277
0
  return (s);
278
0
 bad:
279
0
  close(s);
280
0
  return (-1);
281
0
}
282
283
int
284
sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen)
285
0
{
286
0
  struct sockaddr_in  *a4, *b4;
287
0
  struct sockaddr_in6 *a6, *b6;
288
0
  uint32_t     av[4], bv[4], mv[4];
289
290
0
  if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC)
291
0
    return (0);
292
0
  else if (a->sa_family > b->sa_family)
293
0
    return (1);
294
0
  else if (a->sa_family < b->sa_family)
295
0
    return (-1);
296
297
0
  if (prefixlen == -1)
298
0
    memset(&mv, 0xff, sizeof(mv));
299
300
0
  switch (a->sa_family) {
301
0
  case AF_INET:
302
0
    a4 = (struct sockaddr_in *)a;
303
0
    b4 = (struct sockaddr_in *)b;
304
305
0
    av[0] = a4->sin_addr.s_addr;
306
0
    bv[0] = b4->sin_addr.s_addr;
307
0
    if (prefixlen != -1)
308
0
      mv[0] = prefixlen2mask(prefixlen);
309
310
0
    if ((av[0] & mv[0]) > (bv[0] & mv[0]))
311
0
      return (1);
312
0
    if ((av[0] & mv[0]) < (bv[0] & mv[0]))
313
0
      return (-1);
314
0
    break;
315
0
  case AF_INET6:
316
0
    a6 = (struct sockaddr_in6 *)a;
317
0
    b6 = (struct sockaddr_in6 *)b;
318
319
0
    memcpy(&av, &a6->sin6_addr.s6_addr, 16);
320
0
    memcpy(&bv, &b6->sin6_addr.s6_addr, 16);
321
0
    if (prefixlen != -1)
322
0
      prefixlen2mask6(prefixlen, mv);
323
324
0
    if ((av[3] & mv[3]) > (bv[3] & mv[3]))
325
0
      return (1);
326
0
    if ((av[3] & mv[3]) < (bv[3] & mv[3]))
327
0
      return (-1);
328
0
    if ((av[2] & mv[2]) > (bv[2] & mv[2]))
329
0
      return (1);
330
0
    if ((av[2] & mv[2]) < (bv[2] & mv[2]))
331
0
      return (-1);
332
0
    if ((av[1] & mv[1]) > (bv[1] & mv[1]))
333
0
      return (1);
334
0
    if ((av[1] & mv[1]) < (bv[1] & mv[1]))
335
0
      return (-1);
336
0
    if ((av[0] & mv[0]) > (bv[0] & mv[0]))
337
0
      return (1);
338
0
    if ((av[0] & mv[0]) < (bv[0] & mv[0]))
339
0
      return (-1);
340
0
    break;
341
0
  }
342
343
0
  return (0);
344
0
}
345
346
ssize_t
347
sendtofrom(int s, void *buf, size_t len, int flags, struct sockaddr *to,
348
    socklen_t tolen, struct sockaddr *from, socklen_t fromlen)
349
0
{
350
0
  struct iovec     iov;
351
0
  struct msghdr    msg;
352
0
  struct cmsghdr    *cmsg;
353
#ifdef IP_SENDSRCADDR
354
  struct sockaddr_in  *in;
355
#endif
356
0
#ifdef IPV6_PKTINFO
357
0
  struct in6_pktinfo  *pkt6;
358
0
  struct sockaddr_in6 *in6;
359
0
#endif
360
0
  union {
361
0
    struct cmsghdr  hdr;
362
0
    char    inbuf[CMSG_SPACE(sizeof(struct in_addr))];
363
0
    char    in6buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
364
0
  } cmsgbuf;
365
366
0
  bzero(&msg, sizeof(msg));
367
0
  bzero(&cmsgbuf, sizeof(cmsgbuf));
368
369
0
  iov.iov_base = buf;
370
0
  iov.iov_len = len;
371
0
  msg.msg_iov = &iov;
372
0
  msg.msg_iovlen = 1;
373
0
  msg.msg_name = to;
374
0
  msg.msg_namelen = tolen;
375
0
  msg.msg_controllen = 0;
376
377
0
  switch (to->sa_family) {
378
0
  case AF_INET:
379
#ifdef IP_SENDSRCADDR
380
    in = (struct sockaddr_in *)from;
381
    if (in->sin_addr.s_addr == INADDR_ANY)
382
      break;
383
    msg.msg_control = &cmsgbuf;
384
    msg.msg_controllen += sizeof(cmsgbuf.inbuf);
385
    cmsg = CMSG_FIRSTHDR(&msg);
386
    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
387
    cmsg->cmsg_level = IPPROTO_IP;
388
    cmsg->cmsg_type = IP_SENDSRCADDR;
389
    memcpy(CMSG_DATA(cmsg), &in->sin_addr, sizeof(struct in_addr));
390
#endif
391
0
    break;
392
0
  case AF_INET6:
393
0
#ifdef IPV6_PKTINFO
394
0
    msg.msg_control = &cmsgbuf;
395
0
    msg.msg_controllen += sizeof(cmsgbuf.in6buf);
396
0
    cmsg = CMSG_FIRSTHDR(&msg);
397
0
    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
398
0
    cmsg->cmsg_level = IPPROTO_IPV6;
399
0
    cmsg->cmsg_type = IPV6_PKTINFO;
400
0
    in6 = (struct sockaddr_in6 *)from;
401
0
    pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
402
0
    pkt6->ipi6_addr = in6->sin6_addr;
403
0
#endif
404
0
    break;
405
0
  }
406
407
0
  return sendmsg(s, &msg, flags);
408
0
}
409
410
ssize_t
411
recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from,
412
    socklen_t *fromlen, struct sockaddr *to, socklen_t *tolen)
413
0
{
414
0
  struct iovec     iov;
415
0
  struct msghdr    msg;
416
0
  struct cmsghdr    *cmsg;
417
#if !defined(IP_RECVORIGDSTADDR) && defined(IP_RECVDSTADDR)
418
  struct sockaddr_in  *in;
419
#endif
420
0
#ifdef IPV6_PKTINFO
421
0
  struct in6_pktinfo  *pkt6;
422
0
  struct sockaddr_in6 *in6;
423
0
#endif
424
0
  ssize_t      ret;
425
0
  union {
426
0
    struct cmsghdr hdr;
427
0
    char  buf[CMSG_SPACE(sizeof(struct sockaddr_storage))];
428
0
  } cmsgbuf;
429
430
0
  bzero(&msg, sizeof(msg));
431
0
  bzero(&cmsgbuf.buf, sizeof(cmsgbuf.buf));
432
433
0
  iov.iov_base = buf;
434
0
  iov.iov_len = len;
435
0
  msg.msg_iov = &iov;
436
0
  msg.msg_iovlen = 1;
437
0
  msg.msg_name = from;
438
0
  msg.msg_namelen = *fromlen;
439
0
  msg.msg_control = &cmsgbuf.buf;
440
0
  msg.msg_controllen = sizeof(cmsgbuf.buf);
441
442
0
  if ((ret = recvmsg(s, &msg, flags)) == -1)
443
0
    return (-1);
444
445
0
  *fromlen = SA_LEN(from);
446
447
0
  if (getsockname(s, to, tolen) != 0)
448
0
    *tolen = 0;
449
450
0
  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
451
0
      cmsg = CMSG_NXTHDR(&msg, cmsg)) {
452
0
    switch (from->sa_family) {
453
0
    case AF_INET:
454
0
#if defined(IP_RECVORIGDSTADDR)
455
0
      if (cmsg->cmsg_level == IPPROTO_IP &&
456
0
          cmsg->cmsg_type == IP_RECVORIGDSTADDR) {
457
0
        memcpy(to, CMSG_DATA(cmsg),
458
0
            sizeof(struct sockaddr_in));
459
0
      }
460
#elif defined(IP_RECVDSTADDR)
461
      if (cmsg->cmsg_level == IPPROTO_IP &&
462
          cmsg->cmsg_type == IP_RECVDSTADDR) {
463
        in = (struct sockaddr_in *)to;
464
        in->sin_family = AF_INET;
465
#ifdef HAVE_SOCKADDR_SA_LEN
466
        in->sin_len = *tolen = sizeof(*in);
467
#endif
468
        memcpy(&in->sin_addr, CMSG_DATA(cmsg),
469
            sizeof(struct in_addr));
470
      }
471
#endif /* defined(IP_RECVDSTADDR) */
472
0
      break;
473
0
    case AF_INET6:
474
0
#ifdef IPV6_PKTINFO
475
0
      if (cmsg->cmsg_level == IPPROTO_IPV6 &&
476
0
          cmsg->cmsg_type == IPV6_PKTINFO) {
477
0
        in6 = (struct sockaddr_in6 *)to;
478
0
        in6->sin6_family = AF_INET6;
479
#ifdef HAVE_SOCKADDR_SA_LEN
480
        in6->sin6_len = *tolen = sizeof(*in6);
481
#endif
482
0
        pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
483
0
        memcpy(&in6->sin6_addr, &pkt6->ipi6_addr,
484
0
            sizeof(struct in6_addr));
485
0
        if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
486
0
          in6->sin6_scope_id =
487
0
              pkt6->ipi6_ifindex;
488
0
      }
489
0
#endif
490
0
      break;
491
0
    }
492
0
  }
493
494
0
  return (ret);
495
0
}
496
497
const char *
498
print_spi(uint64_t spi, int size)
499
41.9k
{
500
41.9k
  static char    buf[IKED_CYCLE_BUFFERS][32];
501
41.9k
  static int     i = 0;
502
41.9k
  char      *ptr;
503
504
41.9k
  ptr = buf[i];
505
506
41.9k
  switch (size) {
507
0
  case 2:
508
0
    snprintf(ptr, 32, "0x%04x", (uint16_t)spi);
509
0
    break;
510
421
  case 4:
511
421
    snprintf(ptr, 32, "0x%08x", (uint32_t)spi);
512
421
    break;
513
31.2k
  case 8:
514
31.2k
    snprintf(ptr, 32, "0x%016llx", (long long unsigned)spi);
515
31.2k
    break;
516
10.2k
  default:
517
10.2k
    snprintf(ptr, 32, "%llu", (long long unsigned)spi);
518
10.2k
    break;
519
41.9k
  }
520
521
41.9k
  if (++i >= IKED_CYCLE_BUFFERS)
522
5.23k
    i = 0;
523
524
41.9k
  return (ptr);
525
41.9k
}
526
527
const char *
528
print_map(unsigned int type, struct iked_constmap *map)
529
840k
{
530
840k
  unsigned int     i;
531
840k
  static char    buf[IKED_CYCLE_BUFFERS][32];
532
840k
  static int     idx = 0;
533
840k
  const char    *name = NULL;
534
535
840k
  if (idx >= IKED_CYCLE_BUFFERS)
536
105k
    idx = 0;
537
840k
  bzero(buf[idx], sizeof(buf[idx]));
538
539
17.2M
  for (i = 0; map[i].cm_name != NULL; i++) {
540
16.4M
    if (map[i].cm_type == type)
541
573k
      name = map[i].cm_name;
542
16.4M
  }
543
544
840k
  if (name == NULL)
545
267k
    snprintf(buf[idx], sizeof(buf[idx]), "<UNKNOWN:%u>", type);
546
573k
  else
547
573k
    strlcpy(buf[idx], name, sizeof(buf[idx]));
548
549
840k
  return (buf[idx++]);
550
840k
}
551
552
void
553
lc_idtype(char *str)
554
0
{
555
0
  for (; *str != '\0' && *str != '/'; str++)
556
0
    *str = tolower((unsigned char)*str);
557
0
}
558
559
void
560
print_hex(const uint8_t *buf, off_t offset, size_t length)
561
181k
{
562
181k
  unsigned int   i;
563
564
181k
  if (log_getverbose() < 3 || !length)
565
181k
    return;
566
567
0
  for (i = 0; i < length; i++) {
568
0
    if (i && (i % 4) == 0) {
569
0
      if ((i % 32) == 0)
570
0
        print_debug("\n");
571
0
      else
572
0
        print_debug(" ");
573
0
    }
574
0
    print_debug("%02x", buf[offset + i]);
575
0
  }
576
0
  print_debug("\n");
577
0
}
578
579
void
580
print_hexval(const uint8_t *buf, off_t offset, size_t length)
581
0
{
582
0
  unsigned int   i;
583
584
0
  if (log_getverbose() < 2 || !length)
585
0
    return;
586
587
0
  print_debug("0x");
588
0
  for (i = 0; i < length; i++)
589
0
    print_debug("%02x", buf[offset + i]);
590
0
  print_debug("\n");
591
0
}
592
593
void
594
print_hexbuf(struct ibuf *ibuf)
595
0
{
596
0
  print_hex(ibuf_data(ibuf), 0, ibuf_size(ibuf));
597
0
}
598
599
const char *
600
print_bits(unsigned short v, unsigned char *bits)
601
0
{
602
0
  static char  buf[IKED_CYCLE_BUFFERS][BUFSIZ];
603
0
  static int   idx = 0;
604
0
  unsigned int   i, any = 0, j = 0;
605
0
  unsigned char  c;
606
607
0
  if (!bits)
608
0
    return ("");
609
610
0
  if (++idx >= IKED_CYCLE_BUFFERS)
611
0
    idx = 0;
612
613
0
  bzero(buf[idx], sizeof(buf[idx]));
614
615
0
  bits++;
616
0
  while ((i = *bits++)) {
617
0
    if (v & (1 << (i-1))) {
618
0
      if (any) {
619
0
        buf[idx][j++] = ',';
620
0
        if (j >= sizeof(buf[idx]))
621
0
          return (buf[idx]);
622
0
      }
623
0
      any = 1;
624
0
      for (; (c = *bits) > 32; bits++) {
625
0
        buf[idx][j++] = tolower((unsigned char)c);
626
0
        if (j >= sizeof(buf[idx]))
627
0
          return (buf[idx]);
628
0
      }
629
0
    } else
630
0
      for (; *bits > 32; bits++)
631
0
        ;
632
0
  }
633
634
0
  return (buf[idx]);
635
0
}
636
637
uint8_t
638
mask2prefixlen(struct sockaddr *sa)
639
0
{
640
0
  struct sockaddr_in  *sa_in = (struct sockaddr_in *)sa;
641
0
  in_addr_t    ina = sa_in->sin_addr.s_addr;
642
643
0
  if (ina == 0)
644
0
    return (0);
645
0
  else
646
0
    return (33 - ffs(ntohl(ina)));
647
0
}
648
649
uint8_t
650
mask2prefixlen6(struct sockaddr *sa)
651
0
{
652
0
  struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa;
653
0
  uint8_t     *ap, *ep;
654
0
  unsigned int     l = 0;
655
656
  /*
657
   * sin6_len is the size of the sockaddr so substract the offset of
658
   * the possibly truncated sin6_addr struct.
659
   */
660
0
  ap = (uint8_t *)&sa_in6->sin6_addr;
661
0
  ep = (uint8_t *)sa_in6 + SA_LEN(sa);
662
0
  for (; ap < ep; ap++) {
663
    /* this "beauty" is adopted from sbin/route/show.c ... */
664
0
    switch (*ap) {
665
0
    case 0xff:
666
0
      l += 8;
667
0
      break;
668
0
    case 0xfe:
669
0
      l += 7;
670
0
      goto done;
671
0
    case 0xfc:
672
0
      l += 6;
673
0
      goto done;
674
0
    case 0xf8:
675
0
      l += 5;
676
0
      goto done;
677
0
    case 0xf0:
678
0
      l += 4;
679
0
      goto done;
680
0
    case 0xe0:
681
0
      l += 3;
682
0
      goto done;
683
0
    case 0xc0:
684
0
      l += 2;
685
0
      goto done;
686
0
    case 0x80:
687
0
      l += 1;
688
0
      goto done;
689
0
    case 0x00:
690
0
      goto done;
691
0
    default:
692
0
      fatalx("non contiguous inet6 netmask");
693
0
    }
694
0
  }
695
696
0
done:
697
0
  if (l > sizeof(struct in6_addr) * 8)
698
0
    fatalx("%s: prefixlen %d out of bound", __func__, l);
699
0
  return (l);
700
0
}
701
702
uint32_t
703
prefixlen2mask(uint8_t prefixlen)
704
0
{
705
0
  if (prefixlen == 0)
706
0
    return (0);
707
708
0
  if (prefixlen > 32)
709
0
    prefixlen = 32;
710
711
0
  return (htonl(0xffffffff << (32 - prefixlen)));
712
0
}
713
714
struct in6_addr *
715
prefixlen2mask6(uint8_t prefixlen, uint32_t *mask)
716
0
{
717
0
  static struct in6_addr  s6;
718
0
  int     i;
719
720
0
  if (prefixlen > 128)
721
0
    prefixlen = 128;
722
723
0
  bzero(&s6, sizeof(s6));
724
0
  for (i = 0; i < prefixlen / 8; i++)
725
0
    s6.s6_addr[i] = 0xff;
726
0
  i = prefixlen % 8;
727
0
  if (i)
728
0
    s6.s6_addr[prefixlen / 8] = 0xff00 >> i;
729
730
0
  memcpy(mask, &s6, sizeof(s6));
731
732
0
  return (&s6);
733
0
}
734
735
const char *
736
print_addr(void *addr)
737
19.8k
{
738
19.8k
  static char  sbuf[IKED_CYCLE_BUFFERS][NI_MAXHOST + 7];
739
19.8k
  static int   idx;
740
19.8k
  struct sockaddr *sa = addr;
741
19.8k
  char    *buf;
742
19.8k
  size_t     len;
743
19.8k
  char     pbuf[7];
744
19.8k
  in_port_t  port;
745
746
19.8k
  buf = sbuf[idx];
747
19.8k
  len = sizeof(sbuf[idx]);
748
19.8k
  if (++idx >= IKED_CYCLE_BUFFERS)
749
2.47k
    idx = 0;
750
751
19.8k
  if (sa->sa_family == AF_UNSPEC) {
752
0
    strlcpy(buf, "any", len);
753
0
    return (buf);
754
0
  }
755
756
19.8k
  if (getnameinfo(sa, SA_LEN(sa),
757
19.8k
      buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
758
0
    strlcpy(buf, "unknown", len);
759
0
    return (buf);
760
0
  }
761
762
19.8k
  if ((port = socket_getport(sa)) != 0) {
763
0
    snprintf(pbuf, sizeof(pbuf), ":%d", port);
764
0
    (void)strlcat(buf, pbuf, len);
765
0
  }
766
767
19.8k
  return (buf);
768
19.8k
}
769
770
char *
771
get_string(uint8_t *ptr, size_t len)
772
0
{
773
0
  size_t   i;
774
775
0
  for (i = 0; i < len; i++)
776
0
    if (!isprint(ptr[i]))
777
0
      break;
778
779
0
  return strndup(ptr, i);
780
0
}
781
782
const char *
783
print_proto(uint8_t proto)
784
0
{
785
0
  struct protoent *p;
786
0
  static char  buf[IKED_CYCLE_BUFFERS][BUFSIZ];
787
0
  static int   idx = 0;
788
789
0
  if (idx >= IKED_CYCLE_BUFFERS)
790
0
    idx = 0;
791
792
0
  if ((p = getprotobynumber(proto)) != NULL)
793
0
    strlcpy(buf[idx], p->p_name, sizeof(buf[idx]));
794
0
  else
795
0
    snprintf(buf[idx], sizeof(buf), "%u", proto);
796
797
798
0
  return (buf[idx++]);
799
0
}
800
801
int
802
expand_string(char *label, size_t len, const char *srch, const char *repl)
803
0
{
804
0
  char *tmp;
805
0
  char *p, *q;
806
807
0
  if ((tmp = calloc(1, len)) == NULL) {
808
0
    log_debug("%s: calloc", __func__);
809
0
    return (-1);
810
0
  }
811
0
  p = label;
812
0
  while ((q = strstr(p, srch)) != NULL) {
813
0
    *q = '\0';
814
0
    if ((strlcat(tmp, p, len) >= len) ||
815
0
        (strlcat(tmp, repl, len) >= len)) {
816
0
      log_debug("%s: string too long", __func__);
817
0
      free(tmp);
818
0
      return (-1);
819
0
    }
820
0
    q += strlen(srch);
821
0
    p = q;
822
0
  }
823
0
  if (strlcat(tmp, p, len) >= len) {
824
0
    log_debug("%s: string too long", __func__);
825
0
    free(tmp);
826
0
    return (-1);
827
0
  }
828
0
  strlcpy(label, tmp, len); /* always fits */
829
0
  free(tmp);
830
831
0
  return (0);
832
0
}
833
834
uint8_t *
835
string2unicode(const char *ascii, size_t *outlen)
836
0
{
837
0
  uint8_t   *uc = NULL;
838
0
  size_t     i, len = strlen(ascii);
839
840
0
  if ((uc = calloc(1, (len * 2) + 2)) == NULL)
841
0
    return (NULL);
842
843
0
  for (i = 0; i < len; i++) {
844
    /* XXX what about the byte order? */
845
0
    uc[i * 2] = ascii[i];
846
0
  }
847
0
  *outlen = len * 2;
848
849
0
  return (uc);
850
0
}
851
852
void
853
print_debug(const char *emsg, ...)
854
0
{
855
0
  va_list  ap;
856
857
0
  if (log_getverbose() > 2) {
858
0
    va_start(ap, emsg);
859
0
    vfprintf(stderr, emsg, ap);
860
0
    va_end(ap);
861
0
  }
862
0
}
863
864
void
865
print_verbose(const char *emsg, ...)
866
0
{
867
0
  va_list  ap;
868
869
0
  if (log_getverbose()) {
870
0
    va_start(ap, emsg);
871
0
    vfprintf(stderr, emsg, ap);
872
0
    va_end(ap);
873
0
  }
874
0
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/regress/parser-libfuzzer/common.c.html b/coverage/latest/report/linux/src/openiked-portable/regress/parser-libfuzzer/common.c.html index e02411af6..c32f8b438 100644 --- a/coverage/latest/report/linux/src/openiked-portable/regress/parser-libfuzzer/common.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/regress/parser-libfuzzer/common.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/regress/parser-libfuzzer/common.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: common.c,v 1.9 2020/11/26 22:29:32 tobhe Exp $ */
2
/*
3
 * A bunch of stub functions so we can compile and link ikev2_pld.c
4
 * in a standalone program for testing purposes.
5
 *
6
 * Placed in the public domain
7
 */
8
9
#include <sys/socket.h>
10
#include <sys/time.h>
11
#include <sys/uio.h>
12
13
#include <event.h>
14
#include <limits.h>
15
#include <string.h>
16
17
#include "iked.h"
18
#include "types.h"
19
20
242k
#define IKEV2_FLAG_INITIATOR            0x08    /* Sent by the initiator */
21
22
int  eap_parse(struct iked *, const struct iked_sa *,
23
      struct iked_message *, void *, int);
24
int  ikev2_msg_frompeer(struct iked_message *);
25
int  ikev2_send_ike_e(struct iked *, struct iked_sa *, struct ibuf *,
26
      u_int8_t, u_int8_t, int);
27
void   ikev2_ikesa_recv_delete(struct iked *, struct iked_sa *);
28
struct iked_childsa *
29
   childsa_lookup(struct iked_sa *, u_int64_t, u_int8_t);
30
int   ikev2_childsa_delete(struct iked *, struct iked_sa *,
31
      u_int8_t, u_int64_t, u_int64_t *, int);
32
int  sa_stateok(const struct iked_sa *, int);
33
void   sa_state(struct iked *, struct iked_sa *, int);
34
void   ikev2_disable_rekeying(struct iked *, struct iked_sa *);
35
void   ikev2_init_ike_sa(struct iked *, void *);
36
struct dh_group *
37
   group_get(u_int32_t);
38
void   timer_set(struct iked *, struct iked_timer *,
39
       void (*)(struct iked *, void *), void *);
40
void   timer_add(struct iked *, struct iked_timer *, int);
41
void   timer_del(struct iked *, struct iked_timer *);
42
ssize_t  ikev2_nat_detection(struct iked *, struct iked_message *,
43
       void *, size_t, u_int, int);
44
int  ca_setreq(struct iked *, struct iked_sa *, struct iked_static_id *,
45
       u_int8_t, u_int8_t, u_int8_t *, size_t, enum privsep_procid);
46
int  ikev2_print_id(struct iked_id *, char *, size_t);
47
int  config_add_transform(struct iked_proposal *, u_int, u_int, u_int,
48
       u_int);
49
struct iked_proposal *
50
   config_add_proposal(struct iked_proposals *, u_int, u_int);
51
void   config_free_proposal(struct iked_proposals *, struct iked_proposal *);
52
int  ikev2_send_informational(struct iked *, struct iked_message *);
53
struct ibuf *
54
   ikev2_msg_decrypt(struct iked *, struct iked_sa *, struct ibuf *,
55
       struct ibuf *);
56
void ikev2_msg_cleanup(struct iked *, struct iked_message *);
57
58
int
59
eap_parse(struct iked *env, const struct iked_sa *sa, struct iked_message *msg,
60
    void *data, int response)
61
3.86k
{
62
3.86k
  return (0);
63
3.86k
}
64
65
/* Copied from ikev2_msg.c for better coverage */
66
int
67
ikev2_msg_frompeer(struct iked_message *msg)
68
242k
{
69
242k
  struct iked_sa    *sa = msg->msg_sa;
70
242k
  struct ike_header *hdr;
71
72
242k
  msg = msg->msg_parent;
73
74
242k
  if (sa == NULL ||
75
242k
      (hdr = ibuf_seek(msg->msg_data, 0, sizeof(*hdr))) == NULL)
76
0
    return (0);
77
78
242k
  if (!sa->sa_hdr.sh_initiator &&
79
242k
      (hdr->ike_flags & IKEV2_FLAG_INITIATOR))
80
65.1k
    return (1);
81
177k
  else if (sa->sa_hdr.sh_initiator &&
82
177k
      (hdr->ike_flags & IKEV2_FLAG_INITIATOR) == 0)
83
0
    return (1);
84
85
177k
  return (0);
86
242k
}
87
88
int
89
ikev2_send_ike_e(struct iked *env, struct iked_sa *sa, struct ibuf *buf,
90
    u_int8_t firstpayload, u_int8_t exchange, int response)
91
0
{
92
0
  return (0);
93
0
}
94
95
void
96
ikev2_ikesa_recv_delete(struct iked *env, struct iked_sa *sa)
97
0
{
98
0
}
99
100
const char *
101
ikev2_ikesa_info(uint64_t spi, const char *msg)
102
9.39k
{
103
9.39k
  return "";
104
9.39k
}
105
106
struct iked_childsa *
107
childsa_lookup(struct iked_sa *a, u_int64_t b, u_int8_t c)
108
0
{
109
0
  return (NULL);
110
0
}
111
112
int
113
ikev2_childsa_delete(struct iked *a, struct iked_sa *b, u_int8_t c,
114
    u_int64_t d, u_int64_t *e , int f)
115
0
{
116
0
  return (0);
117
0
}
118
119
int
120
sa_stateok(const struct iked_sa *a, int b)
121
149
{
122
149
  return (0);
123
149
}
124
125
void
126
sa_state(struct iked * a, struct iked_sa *b, int c)
127
0
{
128
0
}
129
130
void
131
ikev2_disable_rekeying(struct iked *a, struct iked_sa *b)
132
0
{
133
0
}
134
135
void
136
ikev2_init_ike_sa(struct iked *a, void *b)
137
0
{
138
0
}
139
140
const struct group_id *
141
group_getid(u_int32_t id)
142
0
{
143
0
  return (NULL);
144
0
}
145
146
void
147
timer_set(struct iked *env, struct iked_timer *tmr,
148
    void (*cb)(struct iked *, void *), void *arg)
149
0
{
150
0
}
151
152
void
153
timer_add(struct iked *env, struct iked_timer *tmr, int timeout)
154
0
{
155
0
}
156
157
void
158
timer_del(struct iked *env, struct iked_timer *tmr)
159
0
{
160
0
}
161
162
ssize_t
163
ikev2_nat_detection(struct iked *env, struct iked_message *msg,
164
    void *ptr, size_t len, u_int type, int frompeer)
165
26.0k
{
166
26.0k
  bzero(ptr, len);
167
26.0k
  return (0);
168
26.0k
}
169
170
int
171
ca_setreq(struct iked *env, struct iked_sa *sh, struct iked_static_id *localid,
172
    u_int8_t type, u_int8_t more, u_int8_t *data, size_t len,
173
    enum privsep_procid procid)
174
0
{
175
0
  return (0);
176
0
}
177
178
int
179
ikev2_print_id(struct iked_id *id, char *idstr, size_t idstrlen)
180
7.77k
{
181
7.77k
  return (0);
182
7.77k
}
183
184
int
185
config_add_transform(struct iked_proposal *prop, u_int type,
186
    u_int id, u_int length, u_int keylength)
187
0
{
188
0
  return (0);
189
0
}
190
191
struct iked_proposal *
192
config_add_proposal(struct iked_proposals *head, u_int id, u_int proto)
193
69
{
194
69
  return (NULL);
195
69
}
196
197
void
198
config_free_proposal(struct iked_proposals *head, struct iked_proposal *prop)
199
0
{
200
0
  return;
201
0
}
202
203
void config_free_fragments(struct iked_frag *frag)
204
0
{
205
0
  return;
206
0
}
207
208
int
209
ikev2_send_informational(struct iked *env, struct iked_message *msg)
210
748
{
211
748
  return (0);
212
748
}
213
214
struct ibuf *
215
ikev2_msg_decrypt(struct iked *env, struct iked_sa *sa,
216
    struct ibuf *msg, struct ibuf *src)
217
0
{
218
0
  if (src == NULL){
219
0
                fprintf(stderr, "%s\n", "msg_decrypt: src == NULL!");
220
0
                exit(-1);
221
0
        }
222
223
  /*
224
   * Free src as caller uses ikev2_msg_decrypt() like this:
225
   * src = ikev2_msg_decrypt(..., src);
226
   */
227
0
  ibuf_free(src); 
228
0
  return (NULL);
229
0
}
230
231
void
232
ikev2_ike_sa_setreason(struct iked_sa *sa, char *r)
233
0
{
234
0
}
235
236
void
237
ikev2_msg_dispose(struct iked *env, struct iked_msgqueue *queue,
238
    struct iked_msg_retransmit *mr)
239
0
{
240
0
}
241
242
struct iked_msg_retransmit *
243
ikev2_msg_lookup(struct iked *env, struct iked_msgqueue *queue,
244
    struct iked_message *msg, uint8_t exchange)
245
0
{
246
0
  return NULL;
247
0
}
248
249
/* copied from ikev2_msg.c */
250
void
251
ikev2_msg_cleanup(struct iked *env, struct iked_message *msg)
252
15.4k
{
253
15.4k
  struct iked_certreq *cr;
254
15.4k
  struct iked_proposal *prop, *proptmp;
255
15.4k
  int      i;
256
257
15.4k
  if (msg == msg->msg_parent) {
258
15.4k
    ibuf_free(msg->msg_nonce);
259
15.4k
    ibuf_free(msg->msg_ke);
260
15.4k
    ibuf_free(msg->msg_auth.id_buf);
261
15.4k
    ibuf_free(msg->msg_peerid.id_buf);
262
15.4k
    ibuf_free(msg->msg_localid.id_buf);
263
15.4k
    ibuf_free(msg->msg_cert.id_buf);
264
61.9k
    for (i = 0; i < IKED_SCERT_MAX; i++)
265
46.4k
      ibuf_free(msg->msg_scert[i].id_buf);
266
15.4k
    ibuf_free(msg->msg_cookie);
267
15.4k
    ibuf_free(msg->msg_cookie2);
268
15.4k
    ibuf_free(msg->msg_del_buf);
269
15.4k
    free(msg->msg_eap.eam_user);
270
15.4k
    free(msg->msg_cp_addr);
271
15.4k
    free(msg->msg_cp_addr6);
272
15.4k
    free(msg->msg_cp_dns);
273
274
15.4k
    TAILQ_FOREACH_SAFE(prop, &msg->msg_proposals, prop_entry,
275
15.4k
        proptmp) {
276
0
      TAILQ_REMOVE(&msg->msg_proposals, prop, prop_entry);
277
0
      if (prop->prop_nxforms)
278
0
        free(prop->prop_xforms);
279
0
      free(prop);
280
0
    }
281
282
15.4k
    msg->msg_nonce = NULL;
283
15.4k
    msg->msg_ke = NULL;
284
15.4k
    msg->msg_auth.id_buf = NULL;
285
15.4k
    msg->msg_peerid.id_buf = NULL;
286
15.4k
    msg->msg_localid.id_buf = NULL;
287
15.4k
    msg->msg_cert.id_buf = NULL;
288
61.9k
    for (i = 0; i < IKED_SCERT_MAX; i++)
289
46.4k
      msg->msg_scert[i].id_buf = NULL;
290
15.4k
    msg->msg_cookie = NULL;
291
15.4k
    msg->msg_cookie2 = NULL;
292
15.4k
    msg->msg_del_buf = NULL;
293
15.4k
    msg->msg_eap.eam_user = NULL;
294
15.4k
    msg->msg_cp_addr = NULL;
295
15.4k
    msg->msg_cp_addr6 = NULL;
296
15.4k
    msg->msg_cp_dns = NULL;
297
298
16.5k
    while ((cr = SIMPLEQ_FIRST(&msg->msg_certreqs))) {
299
1.04k
      ibuf_free(cr->cr_data);
300
1.04k
      SIMPLEQ_REMOVE_HEAD(&msg->msg_certreqs, cr_entry);
301
1.04k
      free(cr);
302
1.04k
    }
303
15.4k
  }
304
305
15.4k
  if (msg->msg_data != NULL) {
306
15.4k
    ibuf_free(msg->msg_data);
307
15.4k
    msg->msg_data = NULL;
308
15.4k
  }
309
15.4k
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/regress/parser-libfuzzer/common.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: common.c,v 1.9 2020/11/26 22:29:32 tobhe Exp $ */
2
/*
3
 * A bunch of stub functions so we can compile and link ikev2_pld.c
4
 * in a standalone program for testing purposes.
5
 *
6
 * Placed in the public domain
7
 */
8
9
#include <sys/socket.h>
10
#include <sys/time.h>
11
#include <sys/uio.h>
12
13
#include <event.h>
14
#include <limits.h>
15
#include <string.h>
16
17
#include "iked.h"
18
#include "types.h"
19
20
242k
#define IKEV2_FLAG_INITIATOR            0x08    /* Sent by the initiator */
21
22
int  eap_parse(struct iked *, const struct iked_sa *,
23
      struct iked_message *, void *, int);
24
int  ikev2_msg_frompeer(struct iked_message *);
25
int  ikev2_send_ike_e(struct iked *, struct iked_sa *, struct ibuf *,
26
      u_int8_t, u_int8_t, int);
27
void   ikev2_ikesa_recv_delete(struct iked *, struct iked_sa *);
28
struct iked_childsa *
29
   childsa_lookup(struct iked_sa *, u_int64_t, u_int8_t);
30
int   ikev2_childsa_delete(struct iked *, struct iked_sa *,
31
      u_int8_t, u_int64_t, u_int64_t *, int);
32
int  sa_stateok(const struct iked_sa *, int);
33
void   sa_state(struct iked *, struct iked_sa *, int);
34
void   ikev2_disable_rekeying(struct iked *, struct iked_sa *);
35
void   ikev2_init_ike_sa(struct iked *, void *);
36
struct dh_group *
37
   group_get(u_int32_t);
38
void   timer_set(struct iked *, struct iked_timer *,
39
       void (*)(struct iked *, void *), void *);
40
void   timer_add(struct iked *, struct iked_timer *, int);
41
void   timer_del(struct iked *, struct iked_timer *);
42
ssize_t  ikev2_nat_detection(struct iked *, struct iked_message *,
43
       void *, size_t, u_int, int);
44
int  ca_setreq(struct iked *, struct iked_sa *, struct iked_static_id *,
45
       u_int8_t, u_int8_t, u_int8_t *, size_t, enum privsep_procid);
46
int  ikev2_print_id(struct iked_id *, char *, size_t);
47
int  config_add_transform(struct iked_proposal *, u_int, u_int, u_int,
48
       u_int);
49
struct iked_proposal *
50
   config_add_proposal(struct iked_proposals *, u_int, u_int);
51
void   config_free_proposal(struct iked_proposals *, struct iked_proposal *);
52
int  ikev2_send_informational(struct iked *, struct iked_message *);
53
struct ibuf *
54
   ikev2_msg_decrypt(struct iked *, struct iked_sa *, struct ibuf *,
55
       struct ibuf *);
56
void ikev2_msg_cleanup(struct iked *, struct iked_message *);
57
58
int
59
eap_parse(struct iked *env, const struct iked_sa *sa, struct iked_message *msg,
60
    void *data, int response)
61
3.86k
{
62
3.86k
  return (0);
63
3.86k
}
64
65
/* Copied from ikev2_msg.c for better coverage */
66
int
67
ikev2_msg_frompeer(struct iked_message *msg)
68
242k
{
69
242k
  struct iked_sa    *sa = msg->msg_sa;
70
242k
  struct ike_header *hdr;
71
72
242k
  msg = msg->msg_parent;
73
74
242k
  if (sa == NULL ||
75
242k
      (hdr = ibuf_seek(msg->msg_data, 0, sizeof(*hdr))) == NULL)
76
0
    return (0);
77
78
242k
  if (!sa->sa_hdr.sh_initiator &&
79
242k
      (hdr->ike_flags & IKEV2_FLAG_INITIATOR))
80
65.1k
    return (1);
81
177k
  else if (sa->sa_hdr.sh_initiator &&
82
177k
      (hdr->ike_flags & IKEV2_FLAG_INITIATOR) == 0)
83
0
    return (1);
84
85
177k
  return (0);
86
242k
}
87
88
int
89
ikev2_send_ike_e(struct iked *env, struct iked_sa *sa, struct ibuf *buf,
90
    u_int8_t firstpayload, u_int8_t exchange, int response)
91
0
{
92
0
  return (0);
93
0
}
94
95
void
96
ikev2_ikesa_recv_delete(struct iked *env, struct iked_sa *sa)
97
0
{
98
0
}
99
100
const char *
101
ikev2_ikesa_info(uint64_t spi, const char *msg)
102
9.39k
{
103
9.39k
  return "";
104
9.39k
}
105
106
struct iked_childsa *
107
childsa_lookup(struct iked_sa *a, u_int64_t b, u_int8_t c)
108
0
{
109
0
  return (NULL);
110
0
}
111
112
int
113
ikev2_childsa_delete(struct iked *a, struct iked_sa *b, u_int8_t c,
114
    u_int64_t d, u_int64_t *e , int f)
115
0
{
116
0
  return (0);
117
0
}
118
119
int
120
sa_stateok(const struct iked_sa *a, int b)
121
149
{
122
149
  return (0);
123
149
}
124
125
void
126
sa_state(struct iked * a, struct iked_sa *b, int c)
127
0
{
128
0
}
129
130
void
131
ikev2_disable_rekeying(struct iked *a, struct iked_sa *b)
132
0
{
133
0
}
134
135
void
136
ikev2_init_ike_sa(struct iked *a, void *b)
137
0
{
138
0
}
139
140
const struct group_id *
141
group_getid(u_int32_t id)
142
0
{
143
0
  return (NULL);
144
0
}
145
146
void
147
timer_set(struct iked *env, struct iked_timer *tmr,
148
    void (*cb)(struct iked *, void *), void *arg)
149
0
{
150
0
}
151
152
void
153
timer_add(struct iked *env, struct iked_timer *tmr, int timeout)
154
0
{
155
0
}
156
157
void
158
timer_del(struct iked *env, struct iked_timer *tmr)
159
0
{
160
0
}
161
162
ssize_t
163
ikev2_nat_detection(struct iked *env, struct iked_message *msg,
164
    void *ptr, size_t len, u_int type, int frompeer)
165
26.0k
{
166
26.0k
  bzero(ptr, len);
167
26.0k
  return (0);
168
26.0k
}
169
170
int
171
ca_setreq(struct iked *env, struct iked_sa *sh, struct iked_static_id *localid,
172
    u_int8_t type, u_int8_t more, u_int8_t *data, size_t len,
173
    enum privsep_procid procid)
174
0
{
175
0
  return (0);
176
0
}
177
178
int
179
ikev2_print_id(struct iked_id *id, char *idstr, size_t idstrlen)
180
7.77k
{
181
7.77k
  return (0);
182
7.77k
}
183
184
int
185
config_add_transform(struct iked_proposal *prop, u_int type,
186
    u_int id, u_int length, u_int keylength)
187
0
{
188
0
  return (0);
189
0
}
190
191
struct iked_proposal *
192
config_add_proposal(struct iked_proposals *head, u_int id, u_int proto)
193
69
{
194
69
  return (NULL);
195
69
}
196
197
void
198
config_free_proposal(struct iked_proposals *head, struct iked_proposal *prop)
199
0
{
200
0
  return;
201
0
}
202
203
void config_free_fragments(struct iked_frag *frag)
204
0
{
205
0
  return;
206
0
}
207
208
int
209
ikev2_send_informational(struct iked *env, struct iked_message *msg)
210
748
{
211
748
  return (0);
212
748
}
213
214
struct ibuf *
215
ikev2_msg_decrypt(struct iked *env, struct iked_sa *sa,
216
    struct ibuf *msg, struct ibuf *src)
217
0
{
218
0
  if (src == NULL){
219
0
                fprintf(stderr, "%s\n", "msg_decrypt: src == NULL!");
220
0
                exit(-1);
221
0
        }
222
223
  /*
224
   * Free src as caller uses ikev2_msg_decrypt() like this:
225
   * src = ikev2_msg_decrypt(..., src);
226
   */
227
0
  ibuf_free(src); 
228
0
  return (NULL);
229
0
}
230
231
void
232
ikev2_ike_sa_setreason(struct iked_sa *sa, char *r)
233
0
{
234
0
}
235
236
void
237
ikev2_msg_dispose(struct iked *env, struct iked_msgqueue *queue,
238
    struct iked_msg_retransmit *mr)
239
0
{
240
0
}
241
242
struct iked_msg_retransmit *
243
ikev2_msg_lookup(struct iked *env, struct iked_msgqueue *queue,
244
    struct iked_message *msg, uint8_t exchange)
245
0
{
246
0
  return NULL;
247
0
}
248
249
/* copied from ikev2_msg.c */
250
void
251
ikev2_msg_cleanup(struct iked *env, struct iked_message *msg)
252
15.4k
{
253
15.4k
  struct iked_certreq *cr;
254
15.4k
  struct iked_proposal *prop, *proptmp;
255
15.4k
  int      i;
256
257
15.4k
  if (msg == msg->msg_parent) {
258
15.4k
    ibuf_free(msg->msg_nonce);
259
15.4k
    ibuf_free(msg->msg_ke);
260
15.4k
    ibuf_free(msg->msg_auth.id_buf);
261
15.4k
    ibuf_free(msg->msg_peerid.id_buf);
262
15.4k
    ibuf_free(msg->msg_localid.id_buf);
263
15.4k
    ibuf_free(msg->msg_cert.id_buf);
264
61.9k
    for (i = 0; i < IKED_SCERT_MAX; i++)
265
46.4k
      ibuf_free(msg->msg_scert[i].id_buf);
266
15.4k
    ibuf_free(msg->msg_cookie);
267
15.4k
    ibuf_free(msg->msg_cookie2);
268
15.4k
    ibuf_free(msg->msg_del_buf);
269
15.4k
    free(msg->msg_eap.eam_user);
270
15.4k
    free(msg->msg_cp_addr);
271
15.4k
    free(msg->msg_cp_addr6);
272
15.4k
    free(msg->msg_cp_dns);
273
274
15.4k
    TAILQ_FOREACH_SAFE(prop, &msg->msg_proposals, prop_entry,
275
15.4k
        proptmp) {
276
0
      TAILQ_REMOVE(&msg->msg_proposals, prop, prop_entry);
277
0
      if (prop->prop_nxforms)
278
0
        free(prop->prop_xforms);
279
0
      free(prop);
280
0
    }
281
282
15.4k
    msg->msg_nonce = NULL;
283
15.4k
    msg->msg_ke = NULL;
284
15.4k
    msg->msg_auth.id_buf = NULL;
285
15.4k
    msg->msg_peerid.id_buf = NULL;
286
15.4k
    msg->msg_localid.id_buf = NULL;
287
15.4k
    msg->msg_cert.id_buf = NULL;
288
61.9k
    for (i = 0; i < IKED_SCERT_MAX; i++)
289
46.4k
      msg->msg_scert[i].id_buf = NULL;
290
15.4k
    msg->msg_cookie = NULL;
291
15.4k
    msg->msg_cookie2 = NULL;
292
15.4k
    msg->msg_del_buf = NULL;
293
15.4k
    msg->msg_eap.eam_user = NULL;
294
15.4k
    msg->msg_cp_addr = NULL;
295
15.4k
    msg->msg_cp_addr6 = NULL;
296
15.4k
    msg->msg_cp_dns = NULL;
297
298
16.5k
    while ((cr = SIMPLEQ_FIRST(&msg->msg_certreqs))) {
299
1.04k
      ibuf_free(cr->cr_data);
300
1.04k
      SIMPLEQ_REMOVE_HEAD(&msg->msg_certreqs, cr_entry);
301
1.04k
      free(cr);
302
1.04k
    }
303
15.4k
  }
304
305
15.4k
  if (msg->msg_data != NULL) {
306
15.4k
    ibuf_free(msg->msg_data);
307
15.4k
    msg->msg_data = NULL;
308
15.4k
  }
309
15.4k
}
\ No newline at end of file diff --git a/coverage/latest/report/linux/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c.html b/coverage/latest/report/linux/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c.html index e1b06fa49..971454157 100644 --- a/coverage/latest/report/linux/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c.html +++ b/coverage/latest/report/linux/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD$ */
2
/*
3
 * Fuzz tests for payload parsing
4
 *
5
 * Placed in the public domain
6
 */
7
8
#include <sys/socket.h>
9
#include <sys/queue.h>
10
#include <sys/uio.h>
11
12
#include <event.h>
13
#include <imsg.h>
14
#include <string.h>
15
16
#include "iked.h"
17
#include "ikev2.h"
18
19
u_int8_t cookies[] = {
20
  0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x01, /* initator cookie */
21
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* responder cookie */
22
};
23
24
u_int8_t genhdr[] = {
25
  0x00, 0x20, 0x22, 0x08, /* next, major/minor, exchange type, flags */
26
  0x00, 0x00, 0x00, 0x00, /* message ID */
27
  0x00, 0x00, 0x00, 0x00  /* total length */
28
};
29
30
15.4k
#define OFFSET_ICOOKIE    0
31
15.4k
#define OFFSET_RCOOKIE    8
32
15.4k
#define OFFSET_NEXTPAYLOAD  (0 + sizeof(cookies))
33
15.4k
#define OFFSET_VERSION    (1 + sizeof(cookies))
34
15.4k
#define OFFSET_EXCHANGE   (2 + sizeof(cookies))
35
15.4k
#define OFFSET_LENGTH   (8 + sizeof(cookies))
36
37
static u_int8_t *
38
get_icookie(u_int8_t *data)
39
15.4k
{
40
15.4k
  return &data[OFFSET_ICOOKIE];
41
15.4k
}
42
43
static u_int8_t *
44
get_rcookie(u_int8_t *data)
45
15.4k
{
46
15.4k
  return &data[OFFSET_RCOOKIE];
47
15.4k
}
48
49
static u_int8_t
50
get_nextpayload(u_int8_t *data)
51
15.4k
{
52
15.4k
  return data[OFFSET_NEXTPAYLOAD];
53
15.4k
}
54
55
static u_int8_t
56
get_version(u_int8_t *data)
57
15.4k
{
58
15.4k
  return data[OFFSET_VERSION];
59
15.4k
}
60
61
static u_int8_t
62
get_exchange(u_int8_t *data)
63
15.4k
{
64
15.4k
  return data[OFFSET_EXCHANGE];
65
15.4k
}
66
67
static u_int32_t
68
get_length(u_int8_t *data)
69
15.4k
{
70
15.4k
  return *(u_int32_t *)&data[OFFSET_LENGTH];
71
15.4k
}
72
73
static void
74
prepare_header(struct ike_header *hdr, struct ibuf *data)
75
15.4k
{
76
15.4k
  bzero(hdr, sizeof(*hdr));
77
15.4k
  bcopy(get_icookie(ibuf_data(data)), &hdr->ike_ispi,
78
15.4k
      sizeof(hdr->ike_ispi));
79
15.4k
  bcopy(get_rcookie(ibuf_data(data)), &hdr->ike_rspi,
80
15.4k
      sizeof(hdr->ike_rspi));
81
15.4k
  hdr->ike_nextpayload = get_nextpayload(ibuf_data(data));
82
15.4k
  hdr->ike_version = get_version(ibuf_data(data));
83
15.4k
  hdr->ike_exchange = get_exchange(ibuf_data(data));
84
15.4k
  hdr->ike_length = get_length(ibuf_data(data));
85
15.4k
}
86
87
static void
88
prepare_message(struct iked_message *msg, struct ibuf *data)
89
15.4k
{
90
15.4k
  static struct iked_sa sa;
91
92
15.4k
  bzero(&sa, sizeof(sa));
93
15.4k
  bzero(msg, sizeof(*msg));
94
95
15.4k
  msg->msg_sa = &sa;
96
15.4k
  msg->msg_data = data;
97
15.4k
  msg->msg_e = 1;
98
15.4k
  msg->msg_parent = msg;
99
100
15.4k
  TAILQ_INIT(&msg->msg_proposals);
101
15.4k
  SIMPLEQ_INIT(&msg->msg_certreqs);
102
15.4k
}
103
104
/* Entry-Point for libFuzzer */
105
int
106
LLVMFuzzerTestOneInput(const char *data, size_t size)
107
15.4k
{
108
15.4k
  struct ibuf   *fuzzed;
109
15.4k
  struct ike_header  hdr;
110
15.4k
  struct iked_message  msg;
111
112
15.4k
  bzero(&hdr, sizeof(hdr));
113
15.4k
  bzero(&msg, sizeof(msg));
114
115
15.4k
  fuzzed = ibuf_new(data, size);
116
15.4k
  if (fuzzed == NULL){
117
0
    fprintf(stderr, "%s\n", "ERROR: fuzzed == NULL! "
118
0
        "(hint: fuzz-input too long?)");
119
0
    return -1;
120
0
  }  
121
  
122
  /* size too small? */
123
15.4k
  if (size < sizeof(cookies) + sizeof(genhdr)){
124
1
    ibuf_free(fuzzed);
125
1
    return 0;
126
1
  }         
127
128
15.4k
  prepare_header(&hdr, fuzzed);
129
15.4k
  prepare_message(&msg, fuzzed);
130
131
15.4k
  ikev2_pld_parse(NULL, &hdr, &msg, 0);
132
133
15.4k
  ikev2_msg_cleanup(NULL, &msg);
134
135
15.4k
  return 0;
136
15.4k
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD$ */
2
/*
3
 * Fuzz tests for payload parsing
4
 *
5
 * Placed in the public domain
6
 */
7
8
#include <sys/socket.h>
9
#include <sys/queue.h>
10
#include <sys/uio.h>
11
12
#include <event.h>
13
#include <imsg.h>
14
#include <string.h>
15
16
#include "iked.h"
17
#include "ikev2.h"
18
19
u_int8_t cookies[] = {
20
  0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x01, /* initator cookie */
21
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* responder cookie */
22
};
23
24
u_int8_t genhdr[] = {
25
  0x00, 0x20, 0x22, 0x08, /* next, major/minor, exchange type, flags */
26
  0x00, 0x00, 0x00, 0x00, /* message ID */
27
  0x00, 0x00, 0x00, 0x00  /* total length */
28
};
29
30
15.4k
#define OFFSET_ICOOKIE    0
31
15.4k
#define OFFSET_RCOOKIE    8
32
15.4k
#define OFFSET_NEXTPAYLOAD  (0 + sizeof(cookies))
33
15.4k
#define OFFSET_VERSION    (1 + sizeof(cookies))
34
15.4k
#define OFFSET_EXCHANGE   (2 + sizeof(cookies))
35
15.4k
#define OFFSET_LENGTH   (8 + sizeof(cookies))
36
37
static u_int8_t *
38
get_icookie(u_int8_t *data)
39
15.4k
{
40
15.4k
  return &data[OFFSET_ICOOKIE];
41
15.4k
}
42
43
static u_int8_t *
44
get_rcookie(u_int8_t *data)
45
15.4k
{
46
15.4k
  return &data[OFFSET_RCOOKIE];
47
15.4k
}
48
49
static u_int8_t
50
get_nextpayload(u_int8_t *data)
51
15.4k
{
52
15.4k
  return data[OFFSET_NEXTPAYLOAD];
53
15.4k
}
54
55
static u_int8_t
56
get_version(u_int8_t *data)
57
15.4k
{
58
15.4k
  return data[OFFSET_VERSION];
59
15.4k
}
60
61
static u_int8_t
62
get_exchange(u_int8_t *data)
63
15.4k
{
64
15.4k
  return data[OFFSET_EXCHANGE];
65
15.4k
}
66
67
static u_int32_t
68
get_length(u_int8_t *data)
69
15.4k
{
70
15.4k
  return *(u_int32_t *)&data[OFFSET_LENGTH];
71
15.4k
}
72
73
static void
74
prepare_header(struct ike_header *hdr, struct ibuf *data)
75
15.4k
{
76
15.4k
  bzero(hdr, sizeof(*hdr));
77
15.4k
  bcopy(get_icookie(ibuf_data(data)), &hdr->ike_ispi,
78
15.4k
      sizeof(hdr->ike_ispi));
79
15.4k
  bcopy(get_rcookie(ibuf_data(data)), &hdr->ike_rspi,
80
15.4k
      sizeof(hdr->ike_rspi));
81
15.4k
  hdr->ike_nextpayload = get_nextpayload(ibuf_data(data));
82
15.4k
  hdr->ike_version = get_version(ibuf_data(data));
83
15.4k
  hdr->ike_exchange = get_exchange(ibuf_data(data));
84
15.4k
  hdr->ike_length = get_length(ibuf_data(data));
85
15.4k
}
86
87
static void
88
prepare_message(struct iked_message *msg, struct ibuf *data)
89
15.4k
{
90
15.4k
  static struct iked_sa sa;
91
92
15.4k
  bzero(&sa, sizeof(sa));
93
15.4k
  bzero(msg, sizeof(*msg));
94
95
15.4k
  msg->msg_sa = &sa;
96
15.4k
  msg->msg_data = data;
97
15.4k
  msg->msg_e = 1;
98
15.4k
  msg->msg_parent = msg;
99
100
15.4k
  TAILQ_INIT(&msg->msg_proposals);
101
15.4k
  SIMPLEQ_INIT(&msg->msg_certreqs);
102
15.4k
}
103
104
/* Entry-Point for libFuzzer */
105
int
106
LLVMFuzzerTestOneInput(const char *data, size_t size)
107
15.4k
{
108
15.4k
  struct ibuf   *fuzzed;
109
15.4k
  struct ike_header  hdr;
110
15.4k
  struct iked_message  msg;
111
112
15.4k
  bzero(&hdr, sizeof(hdr));
113
15.4k
  bzero(&msg, sizeof(msg));
114
115
15.4k
  fuzzed = ibuf_new(data, size);
116
15.4k
  if (fuzzed == NULL){
117
0
    fprintf(stderr, "%s\n", "ERROR: fuzzed == NULL! "
118
0
        "(hint: fuzz-input too long?)");
119
0
    return -1;
120
0
  }  
121
  
122
  /* size too small? */
123
15.4k
  if (size < sizeof(cookies) + sizeof(genhdr)){
124
1
    ibuf_free(fuzzed);
125
1
    return 0;
126
1
  }         
127
128
15.4k
  prepare_header(&hdr, fuzzed);
129
15.4k
  prepare_message(&msg, fuzzed);
130
131
15.4k
  ikev2_pld_parse(NULL, &hdr, &msg, 0);
132
133
15.4k
  ikev2_msg_cleanup(NULL, &msg);
134
135
15.4k
  return 0;
136
15.4k
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random.c.html index 12e153292..000178800 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/arc4random.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random.c,v 1.58 2022/07/31 13:41:45 tb Exp $  */
2
3
/*
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6
 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7
 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
/*
23
 * ChaCha based random number generator for OpenBSD.
24
 */
25
26
#include <fcntl.h>
27
#include <limits.h>
28
#include <signal.h>
29
#include <stdint.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <unistd.h>
33
#include <sys/types.h>
34
#include <sys/time.h>
35
36
#define KEYSTREAM_ONLY
37
#include "chacha_private.h"
38
39
0
#define minimum(a, b) ((a) < (b) ? (a) : (b))
40
41
#if defined(__GNUC__) || defined(_MSC_VER)
42
#define inline __inline
43
#else       /* __GNUC__ || _MSC_VER */
44
#define inline
45
#endif        /* !__GNUC__ && !_MSC_VER */
46
47
0
#define KEYSZ 32
48
0
#define IVSZ  8
49
#define BLOCKSZ 64
50
#define RSBUFSZ (16*BLOCKSZ)
51
52
0
#define REKEY_BASE  (1024*1024) /* NB. should be a power of 2 */
53
54
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
55
static struct _rs {
56
  size_t    rs_have;  /* valid bytes at end of rs_buf */
57
  size_t    rs_count; /* bytes till reseed */
58
} *rs;
59
60
/* Maybe be preserved in fork children, if _rs_allocate() decides. */
61
static struct _rsx {
62
  chacha_ctx  rs_chacha;  /* chacha context for random keystream */
63
  u_char    rs_buf[RSBUFSZ];  /* keystream blocks */
64
} *rsx;
65
66
static inline int _rs_allocate(struct _rs **, struct _rsx **);
67
static inline void _rs_forkdetect(void);
68
#include "arc4random.h"
69
70
static inline void _rs_rekey(u_char *dat, size_t datlen);
71
72
static inline void
73
_rs_init(u_char *buf, size_t n)
74
0
{
75
0
  if (n < KEYSZ + IVSZ)
76
0
    return;
77
78
0
  if (rs == NULL) {
79
0
    if (_rs_allocate(&rs, &rsx) == -1)
80
0
      _exit(1);
81
0
  }
82
83
0
  chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8);
84
0
  chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
85
0
}
86
87
static void
88
_rs_stir(void)
89
0
{
90
0
  u_char rnd[KEYSZ + IVSZ];
91
0
  uint32_t rekey_fuzz = 0;
92
93
0
  if (getentropy(rnd, sizeof rnd) == -1)
94
0
    _getentropy_fail();
95
96
0
  if (!rs)
97
0
    _rs_init(rnd, sizeof(rnd));
98
0
  else
99
0
    _rs_rekey(rnd, sizeof(rnd));
100
0
  explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
101
102
  /* invalidate rs_buf */
103
0
  rs->rs_have = 0;
104
0
  memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
105
106
  /* rekey interval should not be predictable */
107
0
  chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz,
108
0
      (uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz));
109
0
  rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE);
110
0
}
111
112
static inline void
113
_rs_stir_if_needed(size_t len)
114
0
{
115
0
  _rs_forkdetect();
116
0
  if (!rs || rs->rs_count <= len)
117
0
    _rs_stir();
118
0
  if (rs->rs_count <= len)
119
0
    rs->rs_count = 0;
120
0
  else
121
0
    rs->rs_count -= len;
122
0
}
123
124
static inline void
125
_rs_rekey(u_char *dat, size_t datlen)
126
0
{
127
#ifndef KEYSTREAM_ONLY
128
  memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
129
#endif
130
  /* fill rs_buf with the keystream */
131
0
  chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
132
0
      rsx->rs_buf, sizeof(rsx->rs_buf));
133
  /* mix in optional user provided data */
134
0
  if (dat) {
135
0
    size_t i, m;
136
137
0
    m = minimum(datlen, KEYSZ + IVSZ);
138
0
    for (i = 0; i < m; i++)
139
0
      rsx->rs_buf[i] ^= dat[i];
140
0
  }
141
  /* immediately reinit for backtracking resistance */
142
0
  _rs_init(rsx->rs_buf, KEYSZ + IVSZ);
143
0
  memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
144
0
  rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
145
0
}
146
147
static inline void
148
_rs_random_buf(void *_buf, size_t n)
149
0
{
150
0
  u_char *buf = (u_char *)_buf;
151
0
  u_char *keystream;
152
0
  size_t m;
153
154
0
  _rs_stir_if_needed(n);
155
0
  while (n > 0) {
156
0
    if (rs->rs_have > 0) {
157
0
      m = minimum(n, rs->rs_have);
158
0
      keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
159
0
          - rs->rs_have;
160
0
      memcpy(buf, keystream, m);
161
0
      memset(keystream, 0, m);
162
0
      buf += m;
163
0
      n -= m;
164
0
      rs->rs_have -= m;
165
0
    }
166
0
    if (rs->rs_have == 0)
167
0
      _rs_rekey(NULL, 0);
168
0
  }
169
0
}
170
171
static inline void
172
_rs_random_u32(uint32_t *val)
173
0
{
174
0
  u_char *keystream;
175
176
0
  _rs_stir_if_needed(sizeof(*val));
177
0
  if (rs->rs_have < sizeof(*val))
178
0
    _rs_rekey(NULL, 0);
179
0
  keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
180
0
  memcpy(val, keystream, sizeof(*val));
181
0
  memset(keystream, 0, sizeof(*val));
182
0
  rs->rs_have -= sizeof(*val);
183
0
}
184
185
uint32_t
186
arc4random(void)
187
0
{
188
0
  uint32_t val;
189
190
0
  _ARC4_LOCK();
191
0
  _rs_random_u32(&val);
192
0
  _ARC4_UNLOCK();
193
0
  return val;
194
0
}
195
196
void
197
arc4random_buf(void *buf, size_t n)
198
0
{
199
0
  _ARC4_LOCK();
200
0
  _rs_random_buf(buf, n);
201
0
  _ARC4_UNLOCK();
202
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/arc4random.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random.c,v 1.58 2022/07/31 13:41:45 tb Exp $  */
2
3
/*
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6
 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7
 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
/*
23
 * ChaCha based random number generator for OpenBSD.
24
 */
25
26
#include <fcntl.h>
27
#include <limits.h>
28
#include <signal.h>
29
#include <stdint.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <unistd.h>
33
#include <sys/types.h>
34
#include <sys/time.h>
35
36
#define KEYSTREAM_ONLY
37
#include "chacha_private.h"
38
39
0
#define minimum(a, b) ((a) < (b) ? (a) : (b))
40
41
#if defined(__GNUC__) || defined(_MSC_VER)
42
#define inline __inline
43
#else       /* __GNUC__ || _MSC_VER */
44
#define inline
45
#endif        /* !__GNUC__ && !_MSC_VER */
46
47
0
#define KEYSZ 32
48
0
#define IVSZ  8
49
#define BLOCKSZ 64
50
#define RSBUFSZ (16*BLOCKSZ)
51
52
0
#define REKEY_BASE  (1024*1024) /* NB. should be a power of 2 */
53
54
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
55
static struct _rs {
56
  size_t    rs_have;  /* valid bytes at end of rs_buf */
57
  size_t    rs_count; /* bytes till reseed */
58
} *rs;
59
60
/* Maybe be preserved in fork children, if _rs_allocate() decides. */
61
static struct _rsx {
62
  chacha_ctx  rs_chacha;  /* chacha context for random keystream */
63
  u_char    rs_buf[RSBUFSZ];  /* keystream blocks */
64
} *rsx;
65
66
static inline int _rs_allocate(struct _rs **, struct _rsx **);
67
static inline void _rs_forkdetect(void);
68
#include "arc4random.h"
69
70
static inline void _rs_rekey(u_char *dat, size_t datlen);
71
72
static inline void
73
_rs_init(u_char *buf, size_t n)
74
0
{
75
0
  if (n < KEYSZ + IVSZ)
76
0
    return;
77
78
0
  if (rs == NULL) {
79
0
    if (_rs_allocate(&rs, &rsx) == -1)
80
0
      _exit(1);
81
0
  }
82
83
0
  chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8);
84
0
  chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
85
0
}
86
87
static void
88
_rs_stir(void)
89
0
{
90
0
  u_char rnd[KEYSZ + IVSZ];
91
0
  uint32_t rekey_fuzz = 0;
92
93
0
  if (getentropy(rnd, sizeof rnd) == -1)
94
0
    _getentropy_fail();
95
96
0
  if (!rs)
97
0
    _rs_init(rnd, sizeof(rnd));
98
0
  else
99
0
    _rs_rekey(rnd, sizeof(rnd));
100
0
  explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
101
102
  /* invalidate rs_buf */
103
0
  rs->rs_have = 0;
104
0
  memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
105
106
  /* rekey interval should not be predictable */
107
0
  chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz,
108
0
      (uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz));
109
0
  rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE);
110
0
}
111
112
static inline void
113
_rs_stir_if_needed(size_t len)
114
0
{
115
0
  _rs_forkdetect();
116
0
  if (!rs || rs->rs_count <= len)
117
0
    _rs_stir();
118
0
  if (rs->rs_count <= len)
119
0
    rs->rs_count = 0;
120
0
  else
121
0
    rs->rs_count -= len;
122
0
}
123
124
static inline void
125
_rs_rekey(u_char *dat, size_t datlen)
126
0
{
127
#ifndef KEYSTREAM_ONLY
128
  memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
129
#endif
130
  /* fill rs_buf with the keystream */
131
0
  chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
132
0
      rsx->rs_buf, sizeof(rsx->rs_buf));
133
  /* mix in optional user provided data */
134
0
  if (dat) {
135
0
    size_t i, m;
136
137
0
    m = minimum(datlen, KEYSZ + IVSZ);
138
0
    for (i = 0; i < m; i++)
139
0
      rsx->rs_buf[i] ^= dat[i];
140
0
  }
141
  /* immediately reinit for backtracking resistance */
142
0
  _rs_init(rsx->rs_buf, KEYSZ + IVSZ);
143
0
  memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
144
0
  rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
145
0
}
146
147
static inline void
148
_rs_random_buf(void *_buf, size_t n)
149
0
{
150
0
  u_char *buf = (u_char *)_buf;
151
0
  u_char *keystream;
152
0
  size_t m;
153
154
0
  _rs_stir_if_needed(n);
155
0
  while (n > 0) {
156
0
    if (rs->rs_have > 0) {
157
0
      m = minimum(n, rs->rs_have);
158
0
      keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
159
0
          - rs->rs_have;
160
0
      memcpy(buf, keystream, m);
161
0
      memset(keystream, 0, m);
162
0
      buf += m;
163
0
      n -= m;
164
0
      rs->rs_have -= m;
165
0
    }
166
0
    if (rs->rs_have == 0)
167
0
      _rs_rekey(NULL, 0);
168
0
  }
169
0
}
170
171
static inline void
172
_rs_random_u32(uint32_t *val)
173
0
{
174
0
  u_char *keystream;
175
176
0
  _rs_stir_if_needed(sizeof(*val));
177
0
  if (rs->rs_have < sizeof(*val))
178
0
    _rs_rekey(NULL, 0);
179
0
  keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
180
0
  memcpy(val, keystream, sizeof(*val));
181
0
  memset(keystream, 0, sizeof(*val));
182
0
  rs->rs_have -= sizeof(*val);
183
0
}
184
185
uint32_t
186
arc4random(void)
187
0
{
188
0
  uint32_t val;
189
190
0
  _ARC4_LOCK();
191
0
  _rs_random_u32(&val);
192
0
  _ARC4_UNLOCK();
193
0
  return val;
194
0
}
195
196
void
197
arc4random_buf(void *buf, size_t n)
198
0
{
199
0
  _ARC4_LOCK();
200
0
  _rs_random_buf(buf, n);
201
0
  _ARC4_UNLOCK();
202
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random_linux.h.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random_linux.h.html index d89659768..7b79195bc 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random_linux.h.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random_linux.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/arc4random_linux.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random_linux.h,v 1.12 2019/07/11 10:37:28 inoguchi Exp $  */
2
3
/*
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6
 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7
 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
/*
23
 * Stub functions for portability.
24
 */
25
26
#include <sys/mman.h>
27
28
#include <pthread.h>
29
#include <signal.h>
30
31
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
32
0
#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
33
0
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
34
35
#if defined(__GLIBC__) && !(defined(__UCLIBC__) && !defined(__ARCH_USE_MMU__))
36
extern void *__dso_handle;
37
extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
38
0
#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
39
#else
40
#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
41
#endif
42
43
static inline void
44
_getentropy_fail(void)
45
0
{
46
0
  raise(SIGKILL);
47
0
}
48
49
static volatile sig_atomic_t _rs_forked;
50
51
static inline void
52
_rs_forkhandler(void)
53
0
{
54
0
  _rs_forked = 1;
55
0
}
56
57
static inline void
58
_rs_forkdetect(void)
59
0
{
60
0
  static pid_t _rs_pid = 0;
61
0
  pid_t pid = getpid();
62
63
        /* XXX unusual calls to clone() can bypass checks */
64
0
  if (_rs_pid == 0 || _rs_pid == 1 || _rs_pid != pid || _rs_forked) {
65
0
    _rs_pid = pid;
66
0
    _rs_forked = 0;
67
0
    if (rs)
68
0
      memset(rs, 0, sizeof(*rs));
69
0
  }
70
0
}
71
72
static inline int
73
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
74
0
{
75
0
  if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
76
0
      MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
77
0
    return (-1);
78
79
0
  if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
80
0
      MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
81
0
    munmap(*rsp, sizeof(**rsp));
82
0
    *rsp = NULL;
83
0
    return (-1);
84
0
  }
85
86
0
  _ARC4_ATFORK(_rs_forkhandler);
87
0
  return (0);
88
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/arc4random_linux.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random_linux.h,v 1.12 2019/07/11 10:37:28 inoguchi Exp $  */
2
3
/*
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6
 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7
 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 */
21
22
/*
23
 * Stub functions for portability.
24
 */
25
26
#include <sys/mman.h>
27
28
#include <pthread.h>
29
#include <signal.h>
30
31
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
32
0
#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
33
0
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
34
35
#if defined(__GLIBC__) && !(defined(__UCLIBC__) && !defined(__ARCH_USE_MMU__))
36
extern void *__dso_handle;
37
extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
38
0
#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
39
#else
40
#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
41
#endif
42
43
static inline void
44
_getentropy_fail(void)
45
0
{
46
0
  raise(SIGKILL);
47
0
}
48
49
static volatile sig_atomic_t _rs_forked;
50
51
static inline void
52
_rs_forkhandler(void)
53
0
{
54
0
  _rs_forked = 1;
55
0
}
56
57
static inline void
58
_rs_forkdetect(void)
59
0
{
60
0
  static pid_t _rs_pid = 0;
61
0
  pid_t pid = getpid();
62
63
        /* XXX unusual calls to clone() can bypass checks */
64
0
  if (_rs_pid == 0 || _rs_pid == 1 || _rs_pid != pid || _rs_forked) {
65
0
    _rs_pid = pid;
66
0
    _rs_forked = 0;
67
0
    if (rs)
68
0
      memset(rs, 0, sizeof(*rs));
69
0
  }
70
0
}
71
72
static inline int
73
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
74
0
{
75
0
  if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
76
0
      MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
77
0
    return (-1);
78
79
0
  if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
80
0
      MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
81
0
    munmap(*rsp, sizeof(**rsp));
82
0
    *rsp = NULL;
83
0
    return (-1);
84
0
  }
85
86
0
  _ARC4_ATFORK(_rs_forkhandler);
87
0
  return (0);
88
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random_uniform.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random_uniform.c.html index bfe36d3ef..b80f0d07f 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random_uniform.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/arc4random_uniform.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/arc4random_uniform.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random_uniform.c,v 1.3 2019/01/20 02:59:07 bcook Exp $  */
2
3
/*
4
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <stdint.h>
20
#include <stdlib.h>
21
22
/*
23
 * Calculate a uniformly distributed random number less than upper_bound
24
 * avoiding "modulo bias".
25
 *
26
 * Uniformity is achieved by generating new random numbers until the one
27
 * returned is outside the range [0, 2**32 % upper_bound).  This
28
 * guarantees the selected random number will be inside
29
 * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
30
 * after reduction modulo upper_bound.
31
 */
32
uint32_t
33
arc4random_uniform(uint32_t upper_bound)
34
0
{
35
0
  uint32_t r, min;
36
37
0
  if (upper_bound < 2)
38
0
    return 0;
39
40
  /* 2**32 % x == (2**32 - x) % x */
41
0
  min = -upper_bound % upper_bound;
42
43
  /*
44
   * This could theoretically loop forever but each retry has
45
   * p > 0.5 (worst case, usually far better) of selecting a
46
   * number inside the range we need, so it should rarely need
47
   * to re-roll.
48
   */
49
0
  for (;;) {
50
0
    r = arc4random();
51
0
    if (r >= min)
52
0
      break;
53
0
  }
54
55
0
  return r % upper_bound;
56
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/arc4random_uniform.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: arc4random_uniform.c,v 1.3 2019/01/20 02:59:07 bcook Exp $  */
2
3
/*
4
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <stdint.h>
20
#include <stdlib.h>
21
22
/*
23
 * Calculate a uniformly distributed random number less than upper_bound
24
 * avoiding "modulo bias".
25
 *
26
 * Uniformity is achieved by generating new random numbers until the one
27
 * returned is outside the range [0, 2**32 % upper_bound).  This
28
 * guarantees the selected random number will be inside
29
 * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
30
 * after reduction modulo upper_bound.
31
 */
32
uint32_t
33
arc4random_uniform(uint32_t upper_bound)
34
0
{
35
0
  uint32_t r, min;
36
37
0
  if (upper_bound < 2)
38
0
    return 0;
39
40
  /* 2**32 % x == (2**32 - x) % x */
41
0
  min = -upper_bound % upper_bound;
42
43
  /*
44
   * This could theoretically loop forever but each retry has
45
   * p > 0.5 (worst case, usually far better) of selecting a
46
   * number inside the range we need, so it should rarely need
47
   * to re-roll.
48
   */
49
0
  for (;;) {
50
0
    r = arc4random();
51
0
    if (r >= min)
52
0
      break;
53
0
  }
54
55
0
  return r % upper_bound;
56
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/chacha_private.h.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/chacha_private.h.html index 6787f5543..3ee8489c4 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/chacha_private.h.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/chacha_private.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/chacha_private.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
chacha-merged.c version 20080118
3
D. J. Bernstein
4
Public domain.
5
*/
6
7
/* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */
8
9
typedef unsigned char u8;
10
typedef unsigned int u32;
11
12
typedef struct
13
{
14
  u32 input[16]; /* could be compressed */
15
} chacha_ctx;
16
17
0
#define U8C(v) (v##U)
18
0
#define U32C(v) (v##U)
19
20
0
#define U8V(v) ((u8)(v) & U8C(0xFF))
21
0
#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
22
23
#define ROTL32(v, n) \
24
0
  (U32V((v) << (n)) | ((v) >> (32 - (n))))
25
26
#define U8TO32_LITTLE(p) \
27
0
  (((u32)((p)[0])      ) | \
28
0
   ((u32)((p)[1]) <<  8) | \
29
0
   ((u32)((p)[2]) << 16) | \
30
0
   ((u32)((p)[3]) << 24))
31
32
#define U32TO8_LITTLE(p, v) \
33
0
  do { \
34
0
    (p)[0] = U8V((v)      ); \
35
0
    (p)[1] = U8V((v) >>  8); \
36
0
    (p)[2] = U8V((v) >> 16); \
37
0
    (p)[3] = U8V((v) >> 24); \
38
0
  } while (0)
39
40
0
#define ROTATE(v,c) (ROTL32(v,c))
41
#define XOR(v,w) ((v) ^ (w))
42
0
#define PLUS(v,w) (U32V((v) + (w)))
43
0
#define PLUSONE(v) (PLUS((v),1))
44
45
#define QUARTERROUND(a,b,c,d) \
46
0
  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
47
0
  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
48
0
  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
49
0
  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
50
51
static const char sigma[16] = "expand 32-byte k";
52
static const char tau[16] = "expand 16-byte k";
53
54
static void
55
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
56
0
{
57
0
  const char *constants;
58
59
0
  x->input[4] = U8TO32_LITTLE(k + 0);
60
0
  x->input[5] = U8TO32_LITTLE(k + 4);
61
0
  x->input[6] = U8TO32_LITTLE(k + 8);
62
0
  x->input[7] = U8TO32_LITTLE(k + 12);
63
0
  if (kbits == 256) { /* recommended */
64
0
    k += 16;
65
0
    constants = sigma;
66
0
  } else { /* kbits == 128 */
67
0
    constants = tau;
68
0
  }
69
0
  x->input[8] = U8TO32_LITTLE(k + 0);
70
0
  x->input[9] = U8TO32_LITTLE(k + 4);
71
0
  x->input[10] = U8TO32_LITTLE(k + 8);
72
0
  x->input[11] = U8TO32_LITTLE(k + 12);
73
0
  x->input[0] = U8TO32_LITTLE(constants + 0);
74
0
  x->input[1] = U8TO32_LITTLE(constants + 4);
75
0
  x->input[2] = U8TO32_LITTLE(constants + 8);
76
0
  x->input[3] = U8TO32_LITTLE(constants + 12);
77
0
}
78
79
static void
80
chacha_ivsetup(chacha_ctx *x,const u8 *iv)
81
0
{
82
0
  x->input[12] = 0;
83
0
  x->input[13] = 0;
84
0
  x->input[14] = U8TO32_LITTLE(iv + 0);
85
0
  x->input[15] = U8TO32_LITTLE(iv + 4);
86
0
}
87
88
static void
89
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
90
0
{
91
0
  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
92
0
  u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
93
0
  u8 *ctarget = NULL;
94
0
  u8 tmp[64];
95
0
  u_int i;
96
97
0
  if (!bytes) return;
98
99
0
  j0 = x->input[0];
100
0
  j1 = x->input[1];
101
0
  j2 = x->input[2];
102
0
  j3 = x->input[3];
103
0
  j4 = x->input[4];
104
0
  j5 = x->input[5];
105
0
  j6 = x->input[6];
106
0
  j7 = x->input[7];
107
0
  j8 = x->input[8];
108
0
  j9 = x->input[9];
109
0
  j10 = x->input[10];
110
0
  j11 = x->input[11];
111
0
  j12 = x->input[12];
112
0
  j13 = x->input[13];
113
0
  j14 = x->input[14];
114
0
  j15 = x->input[15];
115
116
0
  for (;;) {
117
0
    if (bytes < 64) {
118
0
      for (i = 0;i < bytes;++i) tmp[i] = m[i];
119
0
      m = tmp;
120
0
      ctarget = c;
121
0
      c = tmp;
122
0
    }
123
0
    x0 = j0;
124
0
    x1 = j1;
125
0
    x2 = j2;
126
0
    x3 = j3;
127
0
    x4 = j4;
128
0
    x5 = j5;
129
0
    x6 = j6;
130
0
    x7 = j7;
131
0
    x8 = j8;
132
0
    x9 = j9;
133
0
    x10 = j10;
134
0
    x11 = j11;
135
0
    x12 = j12;
136
0
    x13 = j13;
137
0
    x14 = j14;
138
0
    x15 = j15;
139
0
    for (i = 20;i > 0;i -= 2) {
140
0
      QUARTERROUND( x0, x4, x8,x12)
141
0
      QUARTERROUND( x1, x5, x9,x13)
142
0
      QUARTERROUND( x2, x6,x10,x14)
143
0
      QUARTERROUND( x3, x7,x11,x15)
144
0
      QUARTERROUND( x0, x5,x10,x15)
145
0
      QUARTERROUND( x1, x6,x11,x12)
146
0
      QUARTERROUND( x2, x7, x8,x13)
147
0
      QUARTERROUND( x3, x4, x9,x14)
148
0
    }
149
0
    x0 = PLUS(x0,j0);
150
0
    x1 = PLUS(x1,j1);
151
0
    x2 = PLUS(x2,j2);
152
0
    x3 = PLUS(x3,j3);
153
0
    x4 = PLUS(x4,j4);
154
0
    x5 = PLUS(x5,j5);
155
0
    x6 = PLUS(x6,j6);
156
0
    x7 = PLUS(x7,j7);
157
0
    x8 = PLUS(x8,j8);
158
0
    x9 = PLUS(x9,j9);
159
0
    x10 = PLUS(x10,j10);
160
0
    x11 = PLUS(x11,j11);
161
0
    x12 = PLUS(x12,j12);
162
0
    x13 = PLUS(x13,j13);
163
0
    x14 = PLUS(x14,j14);
164
0
    x15 = PLUS(x15,j15);
165
166
#ifndef KEYSTREAM_ONLY
167
    x0 = XOR(x0,U8TO32_LITTLE(m + 0));
168
    x1 = XOR(x1,U8TO32_LITTLE(m + 4));
169
    x2 = XOR(x2,U8TO32_LITTLE(m + 8));
170
    x3 = XOR(x3,U8TO32_LITTLE(m + 12));
171
    x4 = XOR(x4,U8TO32_LITTLE(m + 16));
172
    x5 = XOR(x5,U8TO32_LITTLE(m + 20));
173
    x6 = XOR(x6,U8TO32_LITTLE(m + 24));
174
    x7 = XOR(x7,U8TO32_LITTLE(m + 28));
175
    x8 = XOR(x8,U8TO32_LITTLE(m + 32));
176
    x9 = XOR(x9,U8TO32_LITTLE(m + 36));
177
    x10 = XOR(x10,U8TO32_LITTLE(m + 40));
178
    x11 = XOR(x11,U8TO32_LITTLE(m + 44));
179
    x12 = XOR(x12,U8TO32_LITTLE(m + 48));
180
    x13 = XOR(x13,U8TO32_LITTLE(m + 52));
181
    x14 = XOR(x14,U8TO32_LITTLE(m + 56));
182
    x15 = XOR(x15,U8TO32_LITTLE(m + 60));
183
#endif
184
185
0
    j12 = PLUSONE(j12);
186
0
    if (!j12) {
187
0
      j13 = PLUSONE(j13);
188
      /* stopping at 2^70 bytes per nonce is user's responsibility */
189
0
    }
190
191
0
    U32TO8_LITTLE(c + 0,x0);
192
0
    U32TO8_LITTLE(c + 4,x1);
193
0
    U32TO8_LITTLE(c + 8,x2);
194
0
    U32TO8_LITTLE(c + 12,x3);
195
0
    U32TO8_LITTLE(c + 16,x4);
196
0
    U32TO8_LITTLE(c + 20,x5);
197
0
    U32TO8_LITTLE(c + 24,x6);
198
0
    U32TO8_LITTLE(c + 28,x7);
199
0
    U32TO8_LITTLE(c + 32,x8);
200
0
    U32TO8_LITTLE(c + 36,x9);
201
0
    U32TO8_LITTLE(c + 40,x10);
202
0
    U32TO8_LITTLE(c + 44,x11);
203
0
    U32TO8_LITTLE(c + 48,x12);
204
0
    U32TO8_LITTLE(c + 52,x13);
205
0
    U32TO8_LITTLE(c + 56,x14);
206
0
    U32TO8_LITTLE(c + 60,x15);
207
208
0
    if (bytes <= 64) {
209
0
      if (bytes < 64) {
210
0
        for (i = 0;i < bytes;++i) ctarget[i] = c[i];
211
0
      }
212
0
      x->input[12] = j12;
213
0
      x->input[13] = j13;
214
0
      return;
215
0
    }
216
0
    bytes -= 64;
217
0
    c += 64;
218
#ifndef KEYSTREAM_ONLY
219
    m += 64;
220
#endif
221
0
  }
222
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/chacha_private.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
chacha-merged.c version 20080118
3
D. J. Bernstein
4
Public domain.
5
*/
6
7
/* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */
8
9
typedef unsigned char u8;
10
typedef unsigned int u32;
11
12
typedef struct
13
{
14
  u32 input[16]; /* could be compressed */
15
} chacha_ctx;
16
17
0
#define U8C(v) (v##U)
18
0
#define U32C(v) (v##U)
19
20
0
#define U8V(v) ((u8)(v) & U8C(0xFF))
21
0
#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
22
23
#define ROTL32(v, n) \
24
0
  (U32V((v) << (n)) | ((v) >> (32 - (n))))
25
26
#define U8TO32_LITTLE(p) \
27
0
  (((u32)((p)[0])      ) | \
28
0
   ((u32)((p)[1]) <<  8) | \
29
0
   ((u32)((p)[2]) << 16) | \
30
0
   ((u32)((p)[3]) << 24))
31
32
#define U32TO8_LITTLE(p, v) \
33
0
  do { \
34
0
    (p)[0] = U8V((v)      ); \
35
0
    (p)[1] = U8V((v) >>  8); \
36
0
    (p)[2] = U8V((v) >> 16); \
37
0
    (p)[3] = U8V((v) >> 24); \
38
0
  } while (0)
39
40
0
#define ROTATE(v,c) (ROTL32(v,c))
41
#define XOR(v,w) ((v) ^ (w))
42
0
#define PLUS(v,w) (U32V((v) + (w)))
43
0
#define PLUSONE(v) (PLUS((v),1))
44
45
#define QUARTERROUND(a,b,c,d) \
46
0
  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
47
0
  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
48
0
  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
49
0
  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
50
51
static const char sigma[16] = "expand 32-byte k";
52
static const char tau[16] = "expand 16-byte k";
53
54
static void
55
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
56
0
{
57
0
  const char *constants;
58
59
0
  x->input[4] = U8TO32_LITTLE(k + 0);
60
0
  x->input[5] = U8TO32_LITTLE(k + 4);
61
0
  x->input[6] = U8TO32_LITTLE(k + 8);
62
0
  x->input[7] = U8TO32_LITTLE(k + 12);
63
0
  if (kbits == 256) { /* recommended */
64
0
    k += 16;
65
0
    constants = sigma;
66
0
  } else { /* kbits == 128 */
67
0
    constants = tau;
68
0
  }
69
0
  x->input[8] = U8TO32_LITTLE(k + 0);
70
0
  x->input[9] = U8TO32_LITTLE(k + 4);
71
0
  x->input[10] = U8TO32_LITTLE(k + 8);
72
0
  x->input[11] = U8TO32_LITTLE(k + 12);
73
0
  x->input[0] = U8TO32_LITTLE(constants + 0);
74
0
  x->input[1] = U8TO32_LITTLE(constants + 4);
75
0
  x->input[2] = U8TO32_LITTLE(constants + 8);
76
0
  x->input[3] = U8TO32_LITTLE(constants + 12);
77
0
}
78
79
static void
80
chacha_ivsetup(chacha_ctx *x,const u8 *iv)
81
0
{
82
0
  x->input[12] = 0;
83
0
  x->input[13] = 0;
84
0
  x->input[14] = U8TO32_LITTLE(iv + 0);
85
0
  x->input[15] = U8TO32_LITTLE(iv + 4);
86
0
}
87
88
static void
89
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
90
0
{
91
0
  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
92
0
  u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
93
0
  u8 *ctarget = NULL;
94
0
  u8 tmp[64];
95
0
  u_int i;
96
97
0
  if (!bytes) return;
98
99
0
  j0 = x->input[0];
100
0
  j1 = x->input[1];
101
0
  j2 = x->input[2];
102
0
  j3 = x->input[3];
103
0
  j4 = x->input[4];
104
0
  j5 = x->input[5];
105
0
  j6 = x->input[6];
106
0
  j7 = x->input[7];
107
0
  j8 = x->input[8];
108
0
  j9 = x->input[9];
109
0
  j10 = x->input[10];
110
0
  j11 = x->input[11];
111
0
  j12 = x->input[12];
112
0
  j13 = x->input[13];
113
0
  j14 = x->input[14];
114
0
  j15 = x->input[15];
115
116
0
  for (;;) {
117
0
    if (bytes < 64) {
118
0
      for (i = 0;i < bytes;++i) tmp[i] = m[i];
119
0
      m = tmp;
120
0
      ctarget = c;
121
0
      c = tmp;
122
0
    }
123
0
    x0 = j0;
124
0
    x1 = j1;
125
0
    x2 = j2;
126
0
    x3 = j3;
127
0
    x4 = j4;
128
0
    x5 = j5;
129
0
    x6 = j6;
130
0
    x7 = j7;
131
0
    x8 = j8;
132
0
    x9 = j9;
133
0
    x10 = j10;
134
0
    x11 = j11;
135
0
    x12 = j12;
136
0
    x13 = j13;
137
0
    x14 = j14;
138
0
    x15 = j15;
139
0
    for (i = 20;i > 0;i -= 2) {
140
0
      QUARTERROUND( x0, x4, x8,x12)
141
0
      QUARTERROUND( x1, x5, x9,x13)
142
0
      QUARTERROUND( x2, x6,x10,x14)
143
0
      QUARTERROUND( x3, x7,x11,x15)
144
0
      QUARTERROUND( x0, x5,x10,x15)
145
0
      QUARTERROUND( x1, x6,x11,x12)
146
0
      QUARTERROUND( x2, x7, x8,x13)
147
0
      QUARTERROUND( x3, x4, x9,x14)
148
0
    }
149
0
    x0 = PLUS(x0,j0);
150
0
    x1 = PLUS(x1,j1);
151
0
    x2 = PLUS(x2,j2);
152
0
    x3 = PLUS(x3,j3);
153
0
    x4 = PLUS(x4,j4);
154
0
    x5 = PLUS(x5,j5);
155
0
    x6 = PLUS(x6,j6);
156
0
    x7 = PLUS(x7,j7);
157
0
    x8 = PLUS(x8,j8);
158
0
    x9 = PLUS(x9,j9);
159
0
    x10 = PLUS(x10,j10);
160
0
    x11 = PLUS(x11,j11);
161
0
    x12 = PLUS(x12,j12);
162
0
    x13 = PLUS(x13,j13);
163
0
    x14 = PLUS(x14,j14);
164
0
    x15 = PLUS(x15,j15);
165
166
#ifndef KEYSTREAM_ONLY
167
    x0 = XOR(x0,U8TO32_LITTLE(m + 0));
168
    x1 = XOR(x1,U8TO32_LITTLE(m + 4));
169
    x2 = XOR(x2,U8TO32_LITTLE(m + 8));
170
    x3 = XOR(x3,U8TO32_LITTLE(m + 12));
171
    x4 = XOR(x4,U8TO32_LITTLE(m + 16));
172
    x5 = XOR(x5,U8TO32_LITTLE(m + 20));
173
    x6 = XOR(x6,U8TO32_LITTLE(m + 24));
174
    x7 = XOR(x7,U8TO32_LITTLE(m + 28));
175
    x8 = XOR(x8,U8TO32_LITTLE(m + 32));
176
    x9 = XOR(x9,U8TO32_LITTLE(m + 36));
177
    x10 = XOR(x10,U8TO32_LITTLE(m + 40));
178
    x11 = XOR(x11,U8TO32_LITTLE(m + 44));
179
    x12 = XOR(x12,U8TO32_LITTLE(m + 48));
180
    x13 = XOR(x13,U8TO32_LITTLE(m + 52));
181
    x14 = XOR(x14,U8TO32_LITTLE(m + 56));
182
    x15 = XOR(x15,U8TO32_LITTLE(m + 60));
183
#endif
184
185
0
    j12 = PLUSONE(j12);
186
0
    if (!j12) {
187
0
      j13 = PLUSONE(j13);
188
      /* stopping at 2^70 bytes per nonce is user's responsibility */
189
0
    }
190
191
0
    U32TO8_LITTLE(c + 0,x0);
192
0
    U32TO8_LITTLE(c + 4,x1);
193
0
    U32TO8_LITTLE(c + 8,x2);
194
0
    U32TO8_LITTLE(c + 12,x3);
195
0
    U32TO8_LITTLE(c + 16,x4);
196
0
    U32TO8_LITTLE(c + 20,x5);
197
0
    U32TO8_LITTLE(c + 24,x6);
198
0
    U32TO8_LITTLE(c + 28,x7);
199
0
    U32TO8_LITTLE(c + 32,x8);
200
0
    U32TO8_LITTLE(c + 36,x9);
201
0
    U32TO8_LITTLE(c + 40,x10);
202
0
    U32TO8_LITTLE(c + 44,x11);
203
0
    U32TO8_LITTLE(c + 48,x12);
204
0
    U32TO8_LITTLE(c + 52,x13);
205
0
    U32TO8_LITTLE(c + 56,x14);
206
0
    U32TO8_LITTLE(c + 60,x15);
207
208
0
    if (bytes <= 64) {
209
0
      if (bytes < 64) {
210
0
        for (i = 0;i < bytes;++i) ctarget[i] = c[i];
211
0
      }
212
0
      x->input[12] = j12;
213
0
      x->input[13] = j13;
214
0
      return;
215
0
    }
216
0
    bytes -= 64;
217
0
    c += 64;
218
#ifndef KEYSTREAM_ONLY
219
    m += 64;
220
#endif
221
0
  }
222
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/freezero.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/freezero.c.html index 9b3eaa0e6..c34235f02 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/freezero.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/freezero.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/freezero.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
3
 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
4
 * Copyright (c) 2008 Damien Miller <djm@openbsd.org>
5
 * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <string.h>
21
#include <stdlib.h>
22
23
void
24
freezero(void *ptr, size_t sz)
25
25.5k
{
26
  /* This is legal. */
27
25.5k
  if (ptr == NULL)
28
1.74k
    return;
29
30
23.8k
  explicit_bzero(ptr, sz);
31
23.8k
  free(ptr);
32
23.8k
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/freezero.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
3
 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
4
 * Copyright (c) 2008 Damien Miller <djm@openbsd.org>
5
 * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <string.h>
21
#include <stdlib.h>
22
23
void
24
freezero(void *ptr, size_t sz)
25
25.5k
{
26
  /* This is legal. */
27
25.5k
  if (ptr == NULL)
28
1.74k
    return;
29
30
23.8k
  explicit_bzero(ptr, sz);
31
23.8k
  free(ptr);
32
23.8k
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/getdtablecount.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/getdtablecount.c.html index 656d3dac5..cf61b3bdb 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/getdtablecount.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/getdtablecount.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/getdtablecount.c
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#include "openbsd-compat.h"
4
5
#if !defined(HAVE_GETDTABLECOUNT)
6
int
7
getdtablecount(void)
8
0
{
9
0
  return (0);
10
0
}
11
#endif
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/getdtablecount.c
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#include "openbsd-compat.h"
4
5
#if !defined(HAVE_GETDTABLECOUNT)
6
int
7
getdtablecount(void)
8
0
{
9
0
  return (0);
10
0
}
11
#endif
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/getrtable.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/getrtable.c.html index a364421aa..3ef62f948 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/getrtable.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/getrtable.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/getrtable.c
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#include "openbsd-compat.h"
4
5
#if !defined(HAVE_GETRTABLE)
6
int
7
getrtable(void)
8
0
{
9
0
  return (0);
10
0
}
11
#endif
12
13
#if !defined(HAVE_SETRTABLE)
14
int
15
setrtable(int rtableid)
16
0
{
17
0
  if (rtableid == 0)
18
0
    return (0);
19
0
  return (-1);
20
0
}
21
#endif
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/getrtable.c
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#include "openbsd-compat.h"
4
5
#if !defined(HAVE_GETRTABLE)
6
int
7
getrtable(void)
8
0
{
9
0
  return (0);
10
0
}
11
#endif
12
13
#if !defined(HAVE_SETRTABLE)
14
int
15
setrtable(int rtableid)
16
0
{
17
0
  if (rtableid == 0)
18
0
    return (0);
19
0
  return (-1);
20
0
}
21
#endif
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg-buffer.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg-buffer.c.html index 61a47b5d2..7f6f577ff 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg-buffer.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg-buffer.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/imsg-buffer.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg-buffer.c,v 1.16 2023/06/19 17:19:50 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/socket.h>
22
#include <sys/uio.h>
23
24
#include <limits.h>
25
#include <errno.h>
26
#include <endian.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <unistd.h>
30
31
#include "openbsd-compat.h"
32
#include "imsg.h"
33
34
static int  ibuf_realloc(struct ibuf *, size_t);
35
static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
36
static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
37
static void msgbuf_drain(struct msgbuf *, size_t);
38
39
struct ibuf *
40
ibuf_open(size_t len)
41
0
{
42
0
  struct ibuf *buf;
43
44
0
  if (len == 0) {
45
0
    errno = EINVAL;
46
0
    return (NULL);
47
0
  }
48
0
  if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
49
0
    return (NULL);
50
0
  if ((buf->buf = calloc(len, 1)) == NULL) {
51
0
    free(buf);
52
0
    return (NULL);
53
0
  }
54
0
  buf->size = buf->max = len;
55
0
  buf->fd = -1;
56
57
0
  return (buf);
58
0
}
59
60
struct ibuf *
61
ibuf_dynamic(size_t len, size_t max)
62
25.5k
{
63
25.5k
  struct ibuf *buf;
64
65
25.5k
  if (max < len) {
66
0
    errno = EINVAL;
67
0
    return (NULL);
68
0
  }
69
70
25.5k
  if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
71
0
    return (NULL);
72
25.5k
  if (len > 0) {
73
23.8k
    if ((buf->buf = calloc(len, 1)) == NULL) {
74
0
      free(buf);
75
0
      return (NULL);
76
0
    }
77
23.8k
  }
78
25.5k
  buf->size = len;
79
25.5k
  buf->max = max;
80
25.5k
  buf->fd = -1;
81
82
25.5k
  return (buf);
83
25.5k
}
84
85
static int
86
ibuf_realloc(struct ibuf *buf, size_t len)
87
0
{
88
0
  unsigned char *b;
89
90
  /* on static buffers max is eq size and so the following fails */
91
0
  if (len > SIZE_MAX - buf->wpos || buf->wpos + len > buf->max) {
92
0
    errno = ERANGE;
93
0
    return (-1);
94
0
  }
95
96
0
  b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
97
0
  if (b == NULL)
98
0
    return (-1);
99
0
  buf->buf = b;
100
0
  buf->size = buf->wpos + len;
101
102
0
  return (0);
103
0
}
104
105
void *
106
ibuf_reserve(struct ibuf *buf, size_t len)
107
23.8k
{
108
23.8k
  void  *b;
109
110
23.8k
  if (len > SIZE_MAX - buf->wpos) {
111
0
    errno = ERANGE;
112
0
    return (NULL);
113
0
  }
114
115
23.8k
  if (buf->wpos + len > buf->size)
116
0
    if (ibuf_realloc(buf, len) == -1)
117
0
      return (NULL);
118
119
23.8k
  b = buf->buf + buf->wpos;
120
23.8k
  buf->wpos += len;
121
23.8k
  memset(b, 0, len);
122
23.8k
  return (b);
123
23.8k
}
124
125
int
126
ibuf_add(struct ibuf *buf, const void *data, size_t len)
127
23.8k
{
128
23.8k
  void *b;
129
130
23.8k
  if ((b = ibuf_reserve(buf, len)) == NULL)
131
0
    return (-1);
132
133
23.8k
  memcpy(b, data, len);
134
23.8k
  return (0);
135
23.8k
}
136
137
138
int
139
ibuf_add_buf(struct ibuf *buf, const struct ibuf *from)
140
0
{
141
0
  return ibuf_add(buf, from->buf, from->wpos);
142
0
}
143
144
int
145
ibuf_add_n8(struct ibuf *buf, uint64_t value)
146
0
{
147
0
  uint8_t v;
148
149
0
  if (value > UINT8_MAX) {
150
0
    errno = EINVAL;
151
0
    return (-1);
152
0
  }
153
0
  v = value;
154
0
  return ibuf_add(buf, &v, sizeof(v));
155
0
}
156
157
int
158
ibuf_add_n16(struct ibuf *buf, uint64_t value)
159
0
{
160
0
  uint16_t v;
161
162
0
  if (value > UINT16_MAX) {
163
0
    errno = EINVAL;
164
0
    return (-1);
165
0
  }
166
0
  v = htobe16(value);
167
0
  return ibuf_add(buf, &v, sizeof(v));
168
0
}
169
170
int
171
ibuf_add_n32(struct ibuf *buf, uint64_t value)
172
0
{
173
0
  uint32_t v;
174
175
0
  if (value > UINT32_MAX) {
176
0
    errno = EINVAL;
177
0
    return (-1);
178
0
  }
179
0
  v = htobe32(value);
180
0
  return ibuf_add(buf, &v, sizeof(v));
181
0
}
182
183
int
184
ibuf_add_n64(struct ibuf *buf, uint64_t value)
185
0
{
186
0
  value = htobe64(value);
187
0
  return ibuf_add(buf, &value, sizeof(value));
188
0
}
189
190
int
191
ibuf_add_zero(struct ibuf *buf, size_t len)
192
0
{
193
0
  void *b;
194
195
0
  if ((b = ibuf_reserve(buf, len)) == NULL)
196
0
    return (-1);
197
0
  return (0);
198
0
}
199
200
void *
201
ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
202
284k
{
203
  /* only allowed to seek in already written parts */
204
284k
  if (len > SIZE_MAX - pos || pos + len > buf->wpos) {
205
4.20k
    errno = ERANGE;
206
4.20k
    return (NULL);
207
4.20k
  }
208
209
280k
  return (buf->buf + pos);
210
284k
}
211
212
int
213
ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len)
214
0
{
215
0
  void *b;
216
217
0
  if ((b = ibuf_seek(buf, pos, len)) == NULL)
218
0
    return (-1);
219
220
0
  memcpy(b, data, len);
221
0
  return (0);
222
0
}
223
224
int
225
ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value)
226
0
{
227
0
  uint8_t v;
228
229
0
  if (value > UINT8_MAX) {
230
0
    errno = EINVAL;
231
0
    return (-1);
232
0
  }
233
0
  v = value;
234
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
235
0
}
236
237
int
238
ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value)
239
0
{
240
0
  uint16_t v;
241
242
0
  if (value > UINT16_MAX) {
243
0
    errno = EINVAL;
244
0
    return (-1);
245
0
  }
246
0
  v = htobe16(value);
247
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
248
0
}
249
250
int
251
ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value)
252
0
{
253
0
  uint32_t v;
254
255
0
  if (value > UINT32_MAX) {
256
0
    errno = EINVAL;
257
0
    return (-1);
258
0
  }
259
0
  v = htobe32(value);
260
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
261
0
}
262
263
int
264
ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value)
265
0
{
266
0
  value = htobe64(value);
267
0
  return (ibuf_set(buf, pos, &value, sizeof(value)));
268
0
}
269
270
void *
271
ibuf_data(struct ibuf *buf)
272
908k
{
273
908k
  return (buf->buf);
274
908k
}
275
276
size_t
277
ibuf_size(struct ibuf *buf)
278
15.4k
{
279
15.4k
  return (buf->wpos);
280
15.4k
}
281
282
size_t
283
ibuf_left(struct ibuf *buf)
284
0
{
285
0
  return (buf->max - buf->wpos);
286
0
}
287
288
void
289
ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
290
0
{
291
0
  ibuf_enqueue(msgbuf, buf);
292
0
}
293
294
void
295
ibuf_free(struct ibuf *buf)
296
210k
{
297
210k
  if (buf == NULL)
298
184k
    return;
299
#ifdef NOTYET
300
  if (buf->fd != -1)
301
    close(buf->fd);
302
#endif
303
25.5k
  freezero(buf->buf, buf->size);
304
25.5k
  free(buf);
305
25.5k
}
306
307
int
308
ibuf_fd_avail(struct ibuf *buf)
309
0
{
310
0
  return (buf->fd != -1);
311
0
}
312
313
int
314
ibuf_fd_get(struct ibuf *buf)
315
0
{
316
0
  int fd;
317
318
0
  fd = buf->fd;
319
#ifdef NOTYET
320
  buf->fd = -1;
321
#endif
322
0
  return (fd);
323
0
}
324
325
void
326
ibuf_fd_set(struct ibuf *buf, int fd)
327
0
{
328
0
  if (buf->fd != -1)
329
0
    close(buf->fd);
330
0
  buf->fd = fd;
331
0
}
332
333
#ifdef _WIN32
334
#define IBUF_WSABUF_WRITE_MAX 16
335
int
336
ibuf_write(struct msgbuf *msgbuf)
337
{
338
  DWORD    bytesSent;
339
  WSABUF     iov[IBUF_WSABUF_WRITE_MAX];
340
  struct ibuf *buf;
341
  unsigned int   i = 0;
342
  ssize_t n;
343
344
  memset(&iov, 0, sizeof(iov));
345
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
346
    if (i >= IBUF_WSABUF_WRITE_MAX)
347
      break;
348
    iov[i].buf = buf->buf + buf->rpos;
349
    iov[i].len = buf->wpos - buf->rpos;
350
    i++;
351
  }
352
353
  if (WSASend(msgbuf->fd, iov, i, &bytesSent, 0, NULL, NULL))
354
    return (-1);
355
  n = bytesSent;
356
357
  if (n == 0) {     /* connection closed */
358
    errno = 0;
359
    return (0);
360
  }
361
362
  msgbuf_drain(msgbuf, n);
363
364
  return (1);
365
}
366
#else
367
int
368
ibuf_write(struct msgbuf *msgbuf)
369
0
{
370
0
  struct iovec   iov[IOV_MAX];
371
0
  struct ibuf *buf;
372
0
  unsigned int   i = 0;
373
0
  ssize_t n;
374
375
0
  memset(&iov, 0, sizeof(iov));
376
0
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
377
0
    if (i >= IOV_MAX)
378
0
      break;
379
0
    iov[i].iov_base = buf->buf + buf->rpos;
380
0
    iov[i].iov_len = buf->wpos - buf->rpos;
381
0
    i++;
382
0
  }
383
384
0
again:
385
0
  if ((n = writev(msgbuf->fd, iov, i)) == -1) {
386
0
    if (errno == EINTR)
387
0
      goto again;
388
0
    if (errno == ENOBUFS)
389
0
      errno = EAGAIN;
390
0
    return (-1);
391
0
  }
392
393
0
  if (n == 0) {     /* connection closed */
394
0
    errno = 0;
395
0
    return (0);
396
0
  }
397
398
0
  msgbuf_drain(msgbuf, n);
399
400
0
  return (1);
401
0
}
402
#endif /* !_WIN32 */
403
404
void
405
msgbuf_init(struct msgbuf *msgbuf)
406
0
{
407
0
  msgbuf->queued = 0;
408
0
  msgbuf->fd = -1;
409
0
  TAILQ_INIT(&msgbuf->bufs);
410
0
}
411
412
static void
413
msgbuf_drain(struct msgbuf *msgbuf, size_t n)
414
0
{
415
0
  struct ibuf *buf, *next;
416
417
0
  for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
418
0
      buf = next) {
419
0
    next = TAILQ_NEXT(buf, entry);
420
0
    if (n >= buf->wpos - buf->rpos) {
421
0
      n -= buf->wpos - buf->rpos;
422
0
      ibuf_dequeue(msgbuf, buf);
423
0
    } else {
424
0
      buf->rpos += n;
425
0
      n = 0;
426
0
    }
427
0
  }
428
0
}
429
430
void
431
msgbuf_clear(struct msgbuf *msgbuf)
432
0
{
433
0
  struct ibuf *buf;
434
435
0
  while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
436
0
    ibuf_dequeue(msgbuf, buf);
437
0
}
438
439
#ifdef _WIN32
440
int
441
msgbuf_write(struct msgbuf *msgbuf)
442
{
443
  struct ibuf *buf;
444
445
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry)
446
    if (buf->fd != -1)
447
      return (-1);
448
  return ibuf_write(msgbuf);
449
}
450
#else
451
int
452
msgbuf_write(struct msgbuf *msgbuf)
453
0
{
454
0
  struct iovec   iov[IOV_MAX];
455
0
  struct ibuf *buf, *buf0 = NULL;
456
0
  unsigned int   i = 0;
457
0
  ssize_t    n;
458
0
  struct msghdr  msg;
459
0
  struct cmsghdr  *cmsg;
460
0
  union {
461
0
    struct cmsghdr  hdr;
462
0
    char    buf[CMSG_SPACE(sizeof(int))];
463
0
  } cmsgbuf;
464
465
0
  memset(&iov, 0, sizeof(iov));
466
0
  memset(&msg, 0, sizeof(msg));
467
0
  memset(&cmsgbuf, 0, sizeof(cmsgbuf));
468
0
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
469
0
    if (i >= IOV_MAX)
470
0
      break;
471
0
    if (i > 0 && buf->fd != -1)
472
0
      break;
473
0
    iov[i].iov_base = buf->buf + buf->rpos;
474
0
    iov[i].iov_len = buf->wpos - buf->rpos;
475
0
    i++;
476
0
    if (buf->fd != -1)
477
0
      buf0 = buf;
478
0
  }
479
480
0
  msg.msg_iov = iov;
481
0
  msg.msg_iovlen = i;
482
483
0
  if (buf0 != NULL) {
484
0
    msg.msg_control = (caddr_t)&cmsgbuf.buf;
485
0
    msg.msg_controllen = sizeof(cmsgbuf.buf);
486
0
    cmsg = CMSG_FIRSTHDR(&msg);
487
0
    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
488
0
    cmsg->cmsg_level = SOL_SOCKET;
489
0
    cmsg->cmsg_type = SCM_RIGHTS;
490
0
    *(int *)CMSG_DATA(cmsg) = buf0->fd;
491
0
  }
492
493
0
again:
494
0
  if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
495
0
    if (errno == EINTR)
496
0
      goto again;
497
0
    if (errno == ENOBUFS)
498
0
      errno = EAGAIN;
499
0
    return (-1);
500
0
  }
501
502
0
  if (n == 0) {     /* connection closed */
503
0
    errno = 0;
504
0
    return (0);
505
0
  }
506
507
  /*
508
   * assumption: fd got sent if sendmsg sent anything
509
   * this works because fds are passed one at a time
510
   */
511
0
  if (buf0 != NULL) {
512
0
    close(buf0->fd);
513
0
    buf0->fd = -1;
514
0
  }
515
516
0
  msgbuf_drain(msgbuf, n);
517
518
0
  return (1);
519
0
}
520
#endif /* !_WIN32 */
521
522
static void
523
ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
524
0
{
525
0
  TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
526
0
  msgbuf->queued++;
527
0
}
528
529
static void
530
ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
531
0
{
532
0
  TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
533
534
0
  if (buf->fd != -1) {
535
0
    close(buf->fd);
536
0
    buf->fd = -1;
537
0
  }
538
539
0
  msgbuf->queued--;
540
0
  ibuf_free(buf);
541
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/imsg-buffer.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg-buffer.c,v 1.16 2023/06/19 17:19:50 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/socket.h>
22
#include <sys/uio.h>
23
24
#include <limits.h>
25
#include <errno.h>
26
#include <endian.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <unistd.h>
30
31
#include "openbsd-compat.h"
32
#include "imsg.h"
33
34
static int  ibuf_realloc(struct ibuf *, size_t);
35
static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
36
static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
37
static void msgbuf_drain(struct msgbuf *, size_t);
38
39
struct ibuf *
40
ibuf_open(size_t len)
41
0
{
42
0
  struct ibuf *buf;
43
44
0
  if (len == 0) {
45
0
    errno = EINVAL;
46
0
    return (NULL);
47
0
  }
48
0
  if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
49
0
    return (NULL);
50
0
  if ((buf->buf = calloc(len, 1)) == NULL) {
51
0
    free(buf);
52
0
    return (NULL);
53
0
  }
54
0
  buf->size = buf->max = len;
55
0
  buf->fd = -1;
56
57
0
  return (buf);
58
0
}
59
60
struct ibuf *
61
ibuf_dynamic(size_t len, size_t max)
62
25.5k
{
63
25.5k
  struct ibuf *buf;
64
65
25.5k
  if (max < len) {
66
0
    errno = EINVAL;
67
0
    return (NULL);
68
0
  }
69
70
25.5k
  if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
71
0
    return (NULL);
72
25.5k
  if (len > 0) {
73
23.8k
    if ((buf->buf = calloc(len, 1)) == NULL) {
74
0
      free(buf);
75
0
      return (NULL);
76
0
    }
77
23.8k
  }
78
25.5k
  buf->size = len;
79
25.5k
  buf->max = max;
80
25.5k
  buf->fd = -1;
81
82
25.5k
  return (buf);
83
25.5k
}
84
85
static int
86
ibuf_realloc(struct ibuf *buf, size_t len)
87
0
{
88
0
  unsigned char *b;
89
90
  /* on static buffers max is eq size and so the following fails */
91
0
  if (len > SIZE_MAX - buf->wpos || buf->wpos + len > buf->max) {
92
0
    errno = ERANGE;
93
0
    return (-1);
94
0
  }
95
96
0
  b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
97
0
  if (b == NULL)
98
0
    return (-1);
99
0
  buf->buf = b;
100
0
  buf->size = buf->wpos + len;
101
102
0
  return (0);
103
0
}
104
105
void *
106
ibuf_reserve(struct ibuf *buf, size_t len)
107
23.8k
{
108
23.8k
  void  *b;
109
110
23.8k
  if (len > SIZE_MAX - buf->wpos) {
111
0
    errno = ERANGE;
112
0
    return (NULL);
113
0
  }
114
115
23.8k
  if (buf->wpos + len > buf->size)
116
0
    if (ibuf_realloc(buf, len) == -1)
117
0
      return (NULL);
118
119
23.8k
  b = buf->buf + buf->wpos;
120
23.8k
  buf->wpos += len;
121
23.8k
  memset(b, 0, len);
122
23.8k
  return (b);
123
23.8k
}
124
125
int
126
ibuf_add(struct ibuf *buf, const void *data, size_t len)
127
23.8k
{
128
23.8k
  void *b;
129
130
23.8k
  if ((b = ibuf_reserve(buf, len)) == NULL)
131
0
    return (-1);
132
133
23.8k
  memcpy(b, data, len);
134
23.8k
  return (0);
135
23.8k
}
136
137
138
int
139
ibuf_add_buf(struct ibuf *buf, const struct ibuf *from)
140
0
{
141
0
  return ibuf_add(buf, from->buf, from->wpos);
142
0
}
143
144
int
145
ibuf_add_n8(struct ibuf *buf, uint64_t value)
146
0
{
147
0
  uint8_t v;
148
149
0
  if (value > UINT8_MAX) {
150
0
    errno = EINVAL;
151
0
    return (-1);
152
0
  }
153
0
  v = value;
154
0
  return ibuf_add(buf, &v, sizeof(v));
155
0
}
156
157
int
158
ibuf_add_n16(struct ibuf *buf, uint64_t value)
159
0
{
160
0
  uint16_t v;
161
162
0
  if (value > UINT16_MAX) {
163
0
    errno = EINVAL;
164
0
    return (-1);
165
0
  }
166
0
  v = htobe16(value);
167
0
  return ibuf_add(buf, &v, sizeof(v));
168
0
}
169
170
int
171
ibuf_add_n32(struct ibuf *buf, uint64_t value)
172
0
{
173
0
  uint32_t v;
174
175
0
  if (value > UINT32_MAX) {
176
0
    errno = EINVAL;
177
0
    return (-1);
178
0
  }
179
0
  v = htobe32(value);
180
0
  return ibuf_add(buf, &v, sizeof(v));
181
0
}
182
183
int
184
ibuf_add_n64(struct ibuf *buf, uint64_t value)
185
0
{
186
0
  value = htobe64(value);
187
0
  return ibuf_add(buf, &value, sizeof(value));
188
0
}
189
190
int
191
ibuf_add_zero(struct ibuf *buf, size_t len)
192
0
{
193
0
  void *b;
194
195
0
  if ((b = ibuf_reserve(buf, len)) == NULL)
196
0
    return (-1);
197
0
  return (0);
198
0
}
199
200
void *
201
ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
202
284k
{
203
  /* only allowed to seek in already written parts */
204
284k
  if (len > SIZE_MAX - pos || pos + len > buf->wpos) {
205
4.20k
    errno = ERANGE;
206
4.20k
    return (NULL);
207
4.20k
  }
208
209
280k
  return (buf->buf + pos);
210
284k
}
211
212
int
213
ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len)
214
0
{
215
0
  void *b;
216
217
0
  if ((b = ibuf_seek(buf, pos, len)) == NULL)
218
0
    return (-1);
219
220
0
  memcpy(b, data, len);
221
0
  return (0);
222
0
}
223
224
int
225
ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value)
226
0
{
227
0
  uint8_t v;
228
229
0
  if (value > UINT8_MAX) {
230
0
    errno = EINVAL;
231
0
    return (-1);
232
0
  }
233
0
  v = value;
234
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
235
0
}
236
237
int
238
ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value)
239
0
{
240
0
  uint16_t v;
241
242
0
  if (value > UINT16_MAX) {
243
0
    errno = EINVAL;
244
0
    return (-1);
245
0
  }
246
0
  v = htobe16(value);
247
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
248
0
}
249
250
int
251
ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value)
252
0
{
253
0
  uint32_t v;
254
255
0
  if (value > UINT32_MAX) {
256
0
    errno = EINVAL;
257
0
    return (-1);
258
0
  }
259
0
  v = htobe32(value);
260
0
  return (ibuf_set(buf, pos, &v, sizeof(v)));
261
0
}
262
263
int
264
ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value)
265
0
{
266
0
  value = htobe64(value);
267
0
  return (ibuf_set(buf, pos, &value, sizeof(value)));
268
0
}
269
270
void *
271
ibuf_data(struct ibuf *buf)
272
908k
{
273
908k
  return (buf->buf);
274
908k
}
275
276
size_t
277
ibuf_size(struct ibuf *buf)
278
15.4k
{
279
15.4k
  return (buf->wpos);
280
15.4k
}
281
282
size_t
283
ibuf_left(struct ibuf *buf)
284
0
{
285
0
  return (buf->max - buf->wpos);
286
0
}
287
288
void
289
ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
290
0
{
291
0
  ibuf_enqueue(msgbuf, buf);
292
0
}
293
294
void
295
ibuf_free(struct ibuf *buf)
296
210k
{
297
210k
  if (buf == NULL)
298
184k
    return;
299
#ifdef NOTYET
300
  if (buf->fd != -1)
301
    close(buf->fd);
302
#endif
303
25.5k
  freezero(buf->buf, buf->size);
304
25.5k
  free(buf);
305
25.5k
}
306
307
int
308
ibuf_fd_avail(struct ibuf *buf)
309
0
{
310
0
  return (buf->fd != -1);
311
0
}
312
313
int
314
ibuf_fd_get(struct ibuf *buf)
315
0
{
316
0
  int fd;
317
318
0
  fd = buf->fd;
319
#ifdef NOTYET
320
  buf->fd = -1;
321
#endif
322
0
  return (fd);
323
0
}
324
325
void
326
ibuf_fd_set(struct ibuf *buf, int fd)
327
0
{
328
0
  if (buf->fd != -1)
329
0
    close(buf->fd);
330
0
  buf->fd = fd;
331
0
}
332
333
#ifdef _WIN32
334
#define IBUF_WSABUF_WRITE_MAX 16
335
int
336
ibuf_write(struct msgbuf *msgbuf)
337
{
338
  DWORD    bytesSent;
339
  WSABUF     iov[IBUF_WSABUF_WRITE_MAX];
340
  struct ibuf *buf;
341
  unsigned int   i = 0;
342
  ssize_t n;
343
344
  memset(&iov, 0, sizeof(iov));
345
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
346
    if (i >= IBUF_WSABUF_WRITE_MAX)
347
      break;
348
    iov[i].buf = buf->buf + buf->rpos;
349
    iov[i].len = buf->wpos - buf->rpos;
350
    i++;
351
  }
352
353
  if (WSASend(msgbuf->fd, iov, i, &bytesSent, 0, NULL, NULL))
354
    return (-1);
355
  n = bytesSent;
356
357
  if (n == 0) {     /* connection closed */
358
    errno = 0;
359
    return (0);
360
  }
361
362
  msgbuf_drain(msgbuf, n);
363
364
  return (1);
365
}
366
#else
367
int
368
ibuf_write(struct msgbuf *msgbuf)
369
0
{
370
0
  struct iovec   iov[IOV_MAX];
371
0
  struct ibuf *buf;
372
0
  unsigned int   i = 0;
373
0
  ssize_t n;
374
375
0
  memset(&iov, 0, sizeof(iov));
376
0
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
377
0
    if (i >= IOV_MAX)
378
0
      break;
379
0
    iov[i].iov_base = buf->buf + buf->rpos;
380
0
    iov[i].iov_len = buf->wpos - buf->rpos;
381
0
    i++;
382
0
  }
383
384
0
again:
385
0
  if ((n = writev(msgbuf->fd, iov, i)) == -1) {
386
0
    if (errno == EINTR)
387
0
      goto again;
388
0
    if (errno == ENOBUFS)
389
0
      errno = EAGAIN;
390
0
    return (-1);
391
0
  }
392
393
0
  if (n == 0) {     /* connection closed */
394
0
    errno = 0;
395
0
    return (0);
396
0
  }
397
398
0
  msgbuf_drain(msgbuf, n);
399
400
0
  return (1);
401
0
}
402
#endif /* !_WIN32 */
403
404
void
405
msgbuf_init(struct msgbuf *msgbuf)
406
0
{
407
0
  msgbuf->queued = 0;
408
0
  msgbuf->fd = -1;
409
0
  TAILQ_INIT(&msgbuf->bufs);
410
0
}
411
412
static void
413
msgbuf_drain(struct msgbuf *msgbuf, size_t n)
414
0
{
415
0
  struct ibuf *buf, *next;
416
417
0
  for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
418
0
      buf = next) {
419
0
    next = TAILQ_NEXT(buf, entry);
420
0
    if (n >= buf->wpos - buf->rpos) {
421
0
      n -= buf->wpos - buf->rpos;
422
0
      ibuf_dequeue(msgbuf, buf);
423
0
    } else {
424
0
      buf->rpos += n;
425
0
      n = 0;
426
0
    }
427
0
  }
428
0
}
429
430
void
431
msgbuf_clear(struct msgbuf *msgbuf)
432
0
{
433
0
  struct ibuf *buf;
434
435
0
  while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
436
0
    ibuf_dequeue(msgbuf, buf);
437
0
}
438
439
#ifdef _WIN32
440
int
441
msgbuf_write(struct msgbuf *msgbuf)
442
{
443
  struct ibuf *buf;
444
445
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry)
446
    if (buf->fd != -1)
447
      return (-1);
448
  return ibuf_write(msgbuf);
449
}
450
#else
451
int
452
msgbuf_write(struct msgbuf *msgbuf)
453
0
{
454
0
  struct iovec   iov[IOV_MAX];
455
0
  struct ibuf *buf, *buf0 = NULL;
456
0
  unsigned int   i = 0;
457
0
  ssize_t    n;
458
0
  struct msghdr  msg;
459
0
  struct cmsghdr  *cmsg;
460
0
  union {
461
0
    struct cmsghdr  hdr;
462
0
    char    buf[CMSG_SPACE(sizeof(int))];
463
0
  } cmsgbuf;
464
465
0
  memset(&iov, 0, sizeof(iov));
466
0
  memset(&msg, 0, sizeof(msg));
467
0
  memset(&cmsgbuf, 0, sizeof(cmsgbuf));
468
0
  TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
469
0
    if (i >= IOV_MAX)
470
0
      break;
471
0
    if (i > 0 && buf->fd != -1)
472
0
      break;
473
0
    iov[i].iov_base = buf->buf + buf->rpos;
474
0
    iov[i].iov_len = buf->wpos - buf->rpos;
475
0
    i++;
476
0
    if (buf->fd != -1)
477
0
      buf0 = buf;
478
0
  }
479
480
0
  msg.msg_iov = iov;
481
0
  msg.msg_iovlen = i;
482
483
0
  if (buf0 != NULL) {
484
0
    msg.msg_control = (caddr_t)&cmsgbuf.buf;
485
0
    msg.msg_controllen = sizeof(cmsgbuf.buf);
486
0
    cmsg = CMSG_FIRSTHDR(&msg);
487
0
    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
488
0
    cmsg->cmsg_level = SOL_SOCKET;
489
0
    cmsg->cmsg_type = SCM_RIGHTS;
490
0
    *(int *)CMSG_DATA(cmsg) = buf0->fd;
491
0
  }
492
493
0
again:
494
0
  if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
495
0
    if (errno == EINTR)
496
0
      goto again;
497
0
    if (errno == ENOBUFS)
498
0
      errno = EAGAIN;
499
0
    return (-1);
500
0
  }
501
502
0
  if (n == 0) {     /* connection closed */
503
0
    errno = 0;
504
0
    return (0);
505
0
  }
506
507
  /*
508
   * assumption: fd got sent if sendmsg sent anything
509
   * this works because fds are passed one at a time
510
   */
511
0
  if (buf0 != NULL) {
512
0
    close(buf0->fd);
513
0
    buf0->fd = -1;
514
0
  }
515
516
0
  msgbuf_drain(msgbuf, n);
517
518
0
  return (1);
519
0
}
520
#endif /* !_WIN32 */
521
522
static void
523
ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
524
0
{
525
0
  TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
526
0
  msgbuf->queued++;
527
0
}
528
529
static void
530
ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
531
0
{
532
0
  TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
533
534
0
  if (buf->fd != -1) {
535
0
    close(buf->fd);
536
0
    buf->fd = -1;
537
0
  }
538
539
0
  msgbuf->queued--;
540
0
  ibuf_free(buf);
541
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg.c.html index 211a4750a..3466a7497 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/imsg.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg.c,v 1.19 2023/06/19 17:19:50 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/socket.h>
22
#include <sys/uio.h>
23
24
#include <errno.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <unistd.h>
28
29
#include "openbsd-compat.h"
30
#include "imsg.h"
31
32
int  imsg_fd_overhead = 0;
33
34
static int   imsg_get_fd(struct imsgbuf *);
35
36
void
37
imsg_init(struct imsgbuf *ibuf, int fd)
38
0
{
39
0
  msgbuf_init(&ibuf->w);
40
0
  memset(&ibuf->r, 0, sizeof(ibuf->r));
41
0
  ibuf->fd = fd;
42
0
  ibuf->w.fd = fd;
43
0
  ibuf->pid = getpid();
44
0
  TAILQ_INIT(&ibuf->fds);
45
0
}
46
47
#ifdef _WIN32
48
ssize_t
49
imsg_read(struct imsgbuf *ibuf)
50
{
51
  ssize_t      n;
52
  uint8_t     *base;
53
  size_t       len;
54
55
  base = ibuf->r.buf + ibuf->r.wpos;
56
  len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
57
58
  while ((n = recv(ibuf->fd, base, len, 0)) == -1) {
59
    if (errno != EINTR)
60
      return (-1);
61
  }
62
  ibuf->r.wpos += n;
63
  return (n);
64
}
65
#else
66
ssize_t
67
imsg_read(struct imsgbuf *ibuf)
68
0
{
69
0
  struct msghdr    msg;
70
0
  struct cmsghdr    *cmsg;
71
0
  union {
72
0
    struct cmsghdr hdr;
73
0
    char  buf[CMSG_SPACE(sizeof(int) * 1)];
74
0
  } cmsgbuf;
75
0
  struct iovec     iov;
76
0
  ssize_t      n = -1;
77
0
  int      fd;
78
0
  struct imsg_fd    *ifd;
79
80
0
  memset(&msg, 0, sizeof(msg));
81
0
  memset(&cmsgbuf, 0, sizeof(cmsgbuf));
82
83
0
  iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
84
0
  iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
85
0
  msg.msg_iov = &iov;
86
0
  msg.msg_iovlen = 1;
87
0
  msg.msg_control = &cmsgbuf.buf;
88
0
  msg.msg_controllen = sizeof(cmsgbuf.buf);
89
90
0
  if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
91
0
    return (-1);
92
93
0
again:
94
0
  if (getdtablecount() + imsg_fd_overhead +
95
0
      (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
96
0
      >= getdtablesize()) {
97
0
    errno = EAGAIN;
98
0
    free(ifd);
99
0
    return (-1);
100
0
  }
101
102
0
  if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
103
0
    if (errno == EINTR)
104
0
      goto again;
105
0
    goto fail;
106
0
  }
107
108
0
  ibuf->r.wpos += n;
109
110
0
  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
111
0
      cmsg = CMSG_NXTHDR(&msg, cmsg)) {
112
0
    if (cmsg->cmsg_level == SOL_SOCKET &&
113
0
        cmsg->cmsg_type == SCM_RIGHTS) {
114
0
      int i;
115
0
      int j;
116
117
      /*
118
       * We only accept one file descriptor.  Due to C
119
       * padding rules, our control buffer might contain
120
       * more than one fd, and we must close them.
121
       */
122
0
      j = ((char *)cmsg + cmsg->cmsg_len -
123
0
          (char *)CMSG_DATA(cmsg)) / sizeof(int);
124
0
      for (i = 0; i < j; i++) {
125
0
        fd = ((int *)CMSG_DATA(cmsg))[i];
126
0
        if (ifd != NULL) {
127
0
          ifd->fd = fd;
128
0
          TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
129
0
              entry);
130
0
          ifd = NULL;
131
0
        } else
132
0
          close(fd);
133
0
      }
134
0
    }
135
    /* we do not handle other ctl data level */
136
0
  }
137
138
0
fail:
139
0
  free(ifd);
140
0
  return (n);
141
0
}
142
#endif
143
144
ssize_t
145
imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
146
0
{
147
0
  size_t       av, left, datalen;
148
149
0
  av = ibuf->r.wpos;
150
151
0
  if (IMSG_HEADER_SIZE > av)
152
0
    return (0);
153
154
0
  memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
155
0
  if (imsg->hdr.len < IMSG_HEADER_SIZE ||
156
0
      imsg->hdr.len > MAX_IMSGSIZE) {
157
0
    errno = ERANGE;
158
0
    return (-1);
159
0
  }
160
0
  if (imsg->hdr.len > av)
161
0
    return (0);
162
0
  datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
163
0
  ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
164
0
  if (datalen == 0)
165
0
    imsg->data = NULL;
166
0
  else if ((imsg->data = malloc(datalen)) == NULL)
167
0
    return (-1);
168
169
0
  if (imsg->hdr.flags & IMSGF_HASFD)
170
0
    imsg->fd = imsg_get_fd(ibuf);
171
0
  else
172
0
    imsg->fd = -1;
173
174
0
  if (datalen != 0)
175
0
    memcpy(imsg->data, ibuf->r.rptr, datalen);
176
177
0
  if (imsg->hdr.len < av) {
178
0
    left = av - imsg->hdr.len;
179
0
    memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
180
0
    ibuf->r.wpos = left;
181
0
  } else
182
0
    ibuf->r.wpos = 0;
183
184
0
  return (datalen + IMSG_HEADER_SIZE);
185
0
}
186
187
int
188
imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
189
    int fd, const void *data, uint16_t datalen)
190
0
{
191
0
  struct ibuf *wbuf;
192
193
0
  if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
194
0
    return (-1);
195
196
0
  if (imsg_add(wbuf, data, datalen) == -1)
197
0
    return (-1);
198
199
0
  ibuf_fd_set(wbuf, fd);
200
201
0
  imsg_close(ibuf, wbuf);
202
203
0
  return (1);
204
0
}
205
206
int
207
imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
208
    int fd, const struct iovec *iov, int iovcnt)
209
0
{
210
0
  struct ibuf *wbuf;
211
0
  int    i, datalen = 0;
212
213
0
  for (i = 0; i < iovcnt; i++)
214
0
    datalen += iov[i].iov_len;
215
216
0
  if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
217
0
    return (-1);
218
219
0
  for (i = 0; i < iovcnt; i++)
220
0
    if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
221
0
      return (-1);
222
223
0
  ibuf_fd_set(wbuf, fd);
224
225
0
  imsg_close(ibuf, wbuf);
226
227
0
  return (1);
228
0
}
229
230
int
231
imsg_compose_ibuf(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid,
232
    pid_t pid, struct ibuf *buf)
233
0
{
234
0
  struct ibuf *wbuf = NULL;
235
0
  struct imsg_hdr  hdr;
236
0
  int save_errno;
237
238
0
  if (ibuf_size(buf) + IMSG_HEADER_SIZE > MAX_IMSGSIZE) {
239
0
    errno = ERANGE;
240
0
    goto fail;
241
0
  }
242
243
0
  hdr.type = type;
244
0
  hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE;
245
0
  hdr.flags = 0;
246
0
  hdr.peerid = peerid;
247
0
  if ((hdr.pid = pid) == 0)
248
0
    hdr.pid = ibuf->pid;
249
250
0
  if ((wbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
251
0
    goto fail;
252
0
  if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
253
0
    goto fail;
254
255
0
  ibuf_close(&ibuf->w, wbuf);
256
0
  ibuf_close(&ibuf->w, buf);
257
0
  return (1);
258
259
0
 fail:
260
0
  save_errno = errno;
261
0
  ibuf_free(buf);
262
0
  ibuf_free(wbuf);
263
0
  errno = save_errno;
264
0
  return (-1);
265
0
}
266
267
struct ibuf *
268
imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
269
    uint16_t datalen)
270
0
{
271
0
  struct ibuf *wbuf;
272
0
  struct imsg_hdr  hdr;
273
274
0
  datalen += IMSG_HEADER_SIZE;
275
0
  if (datalen > MAX_IMSGSIZE) {
276
0
    errno = ERANGE;
277
0
    return (NULL);
278
0
  }
279
280
0
  hdr.type = type;
281
0
  hdr.flags = 0;
282
0
  hdr.peerid = peerid;
283
0
  if ((hdr.pid = pid) == 0)
284
0
    hdr.pid = ibuf->pid;
285
0
  if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
286
0
    return (NULL);
287
0
  }
288
0
  if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
289
0
    return (NULL);
290
291
0
  return (wbuf);
292
0
}
293
294
int
295
imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
296
0
{
297
0
  if (datalen)
298
0
    if (ibuf_add(msg, data, datalen) == -1) {
299
0
      ibuf_free(msg);
300
0
      return (-1);
301
0
    }
302
0
  return (datalen);
303
0
}
304
305
void
306
imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
307
0
{
308
0
  struct imsg_hdr *hdr;
309
310
0
  hdr = (struct imsg_hdr *)msg->buf;
311
312
0
  hdr->flags &= ~IMSGF_HASFD;
313
0
  if (ibuf_fd_avail(msg))
314
0
    hdr->flags |= IMSGF_HASFD;
315
0
  hdr->len = ibuf_size(msg);
316
317
0
  ibuf_close(&ibuf->w, msg);
318
0
}
319
320
void
321
imsg_free(struct imsg *imsg)
322
0
{
323
0
  freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
324
0
}
325
326
static int
327
imsg_get_fd(struct imsgbuf *ibuf)
328
0
{
329
0
  int    fd;
330
0
  struct imsg_fd  *ifd;
331
332
0
  if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
333
0
    return (-1);
334
335
0
  fd = ifd->fd;
336
0
  TAILQ_REMOVE(&ibuf->fds, ifd, entry);
337
0
  free(ifd);
338
339
0
  return (fd);
340
0
}
341
342
int
343
imsg_flush(struct imsgbuf *ibuf)
344
0
{
345
0
  while (ibuf->w.queued)
346
0
    if (msgbuf_write(&ibuf->w) <= 0)
347
0
      return (-1);
348
0
  return (0);
349
0
}
350
351
void
352
imsg_clear(struct imsgbuf *ibuf)
353
0
{
354
0
  int fd;
355
356
0
  msgbuf_clear(&ibuf->w);
357
0
  while ((fd = imsg_get_fd(ibuf)) != -1)
358
0
    close(fd);
359
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/imsg.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg.c,v 1.19 2023/06/19 17:19:50 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/socket.h>
22
#include <sys/uio.h>
23
24
#include <errno.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <unistd.h>
28
29
#include "openbsd-compat.h"
30
#include "imsg.h"
31
32
int  imsg_fd_overhead = 0;
33
34
static int   imsg_get_fd(struct imsgbuf *);
35
36
void
37
imsg_init(struct imsgbuf *ibuf, int fd)
38
0
{
39
0
  msgbuf_init(&ibuf->w);
40
0
  memset(&ibuf->r, 0, sizeof(ibuf->r));
41
0
  ibuf->fd = fd;
42
0
  ibuf->w.fd = fd;
43
0
  ibuf->pid = getpid();
44
0
  TAILQ_INIT(&ibuf->fds);
45
0
}
46
47
#ifdef _WIN32
48
ssize_t
49
imsg_read(struct imsgbuf *ibuf)
50
{
51
  ssize_t      n;
52
  uint8_t     *base;
53
  size_t       len;
54
55
  base = ibuf->r.buf + ibuf->r.wpos;
56
  len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
57
58
  while ((n = recv(ibuf->fd, base, len, 0)) == -1) {
59
    if (errno != EINTR)
60
      return (-1);
61
  }
62
  ibuf->r.wpos += n;
63
  return (n);
64
}
65
#else
66
ssize_t
67
imsg_read(struct imsgbuf *ibuf)
68
0
{
69
0
  struct msghdr    msg;
70
0
  struct cmsghdr    *cmsg;
71
0
  union {
72
0
    struct cmsghdr hdr;
73
0
    char  buf[CMSG_SPACE(sizeof(int) * 1)];
74
0
  } cmsgbuf;
75
0
  struct iovec     iov;
76
0
  ssize_t      n = -1;
77
0
  int      fd;
78
0
  struct imsg_fd    *ifd;
79
80
0
  memset(&msg, 0, sizeof(msg));
81
0
  memset(&cmsgbuf, 0, sizeof(cmsgbuf));
82
83
0
  iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
84
0
  iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
85
0
  msg.msg_iov = &iov;
86
0
  msg.msg_iovlen = 1;
87
0
  msg.msg_control = &cmsgbuf.buf;
88
0
  msg.msg_controllen = sizeof(cmsgbuf.buf);
89
90
0
  if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
91
0
    return (-1);
92
93
0
again:
94
0
  if (getdtablecount() + imsg_fd_overhead +
95
0
      (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
96
0
      >= getdtablesize()) {
97
0
    errno = EAGAIN;
98
0
    free(ifd);
99
0
    return (-1);
100
0
  }
101
102
0
  if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
103
0
    if (errno == EINTR)
104
0
      goto again;
105
0
    goto fail;
106
0
  }
107
108
0
  ibuf->r.wpos += n;
109
110
0
  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
111
0
      cmsg = CMSG_NXTHDR(&msg, cmsg)) {
112
0
    if (cmsg->cmsg_level == SOL_SOCKET &&
113
0
        cmsg->cmsg_type == SCM_RIGHTS) {
114
0
      int i;
115
0
      int j;
116
117
      /*
118
       * We only accept one file descriptor.  Due to C
119
       * padding rules, our control buffer might contain
120
       * more than one fd, and we must close them.
121
       */
122
0
      j = ((char *)cmsg + cmsg->cmsg_len -
123
0
          (char *)CMSG_DATA(cmsg)) / sizeof(int);
124
0
      for (i = 0; i < j; i++) {
125
0
        fd = ((int *)CMSG_DATA(cmsg))[i];
126
0
        if (ifd != NULL) {
127
0
          ifd->fd = fd;
128
0
          TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
129
0
              entry);
130
0
          ifd = NULL;
131
0
        } else
132
0
          close(fd);
133
0
      }
134
0
    }
135
    /* we do not handle other ctl data level */
136
0
  }
137
138
0
fail:
139
0
  free(ifd);
140
0
  return (n);
141
0
}
142
#endif
143
144
ssize_t
145
imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
146
0
{
147
0
  size_t       av, left, datalen;
148
149
0
  av = ibuf->r.wpos;
150
151
0
  if (IMSG_HEADER_SIZE > av)
152
0
    return (0);
153
154
0
  memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
155
0
  if (imsg->hdr.len < IMSG_HEADER_SIZE ||
156
0
      imsg->hdr.len > MAX_IMSGSIZE) {
157
0
    errno = ERANGE;
158
0
    return (-1);
159
0
  }
160
0
  if (imsg->hdr.len > av)
161
0
    return (0);
162
0
  datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
163
0
  ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
164
0
  if (datalen == 0)
165
0
    imsg->data = NULL;
166
0
  else if ((imsg->data = malloc(datalen)) == NULL)
167
0
    return (-1);
168
169
0
  if (imsg->hdr.flags & IMSGF_HASFD)
170
0
    imsg->fd = imsg_get_fd(ibuf);
171
0
  else
172
0
    imsg->fd = -1;
173
174
0
  if (datalen != 0)
175
0
    memcpy(imsg->data, ibuf->r.rptr, datalen);
176
177
0
  if (imsg->hdr.len < av) {
178
0
    left = av - imsg->hdr.len;
179
0
    memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
180
0
    ibuf->r.wpos = left;
181
0
  } else
182
0
    ibuf->r.wpos = 0;
183
184
0
  return (datalen + IMSG_HEADER_SIZE);
185
0
}
186
187
int
188
imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
189
    int fd, const void *data, uint16_t datalen)
190
0
{
191
0
  struct ibuf *wbuf;
192
193
0
  if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
194
0
    return (-1);
195
196
0
  if (imsg_add(wbuf, data, datalen) == -1)
197
0
    return (-1);
198
199
0
  ibuf_fd_set(wbuf, fd);
200
201
0
  imsg_close(ibuf, wbuf);
202
203
0
  return (1);
204
0
}
205
206
int
207
imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
208
    int fd, const struct iovec *iov, int iovcnt)
209
0
{
210
0
  struct ibuf *wbuf;
211
0
  int    i, datalen = 0;
212
213
0
  for (i = 0; i < iovcnt; i++)
214
0
    datalen += iov[i].iov_len;
215
216
0
  if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
217
0
    return (-1);
218
219
0
  for (i = 0; i < iovcnt; i++)
220
0
    if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
221
0
      return (-1);
222
223
0
  ibuf_fd_set(wbuf, fd);
224
225
0
  imsg_close(ibuf, wbuf);
226
227
0
  return (1);
228
0
}
229
230
int
231
imsg_compose_ibuf(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid,
232
    pid_t pid, struct ibuf *buf)
233
0
{
234
0
  struct ibuf *wbuf = NULL;
235
0
  struct imsg_hdr  hdr;
236
0
  int save_errno;
237
238
0
  if (ibuf_size(buf) + IMSG_HEADER_SIZE > MAX_IMSGSIZE) {
239
0
    errno = ERANGE;
240
0
    goto fail;
241
0
  }
242
243
0
  hdr.type = type;
244
0
  hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE;
245
0
  hdr.flags = 0;
246
0
  hdr.peerid = peerid;
247
0
  if ((hdr.pid = pid) == 0)
248
0
    hdr.pid = ibuf->pid;
249
250
0
  if ((wbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
251
0
    goto fail;
252
0
  if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
253
0
    goto fail;
254
255
0
  ibuf_close(&ibuf->w, wbuf);
256
0
  ibuf_close(&ibuf->w, buf);
257
0
  return (1);
258
259
0
 fail:
260
0
  save_errno = errno;
261
0
  ibuf_free(buf);
262
0
  ibuf_free(wbuf);
263
0
  errno = save_errno;
264
0
  return (-1);
265
0
}
266
267
struct ibuf *
268
imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
269
    uint16_t datalen)
270
0
{
271
0
  struct ibuf *wbuf;
272
0
  struct imsg_hdr  hdr;
273
274
0
  datalen += IMSG_HEADER_SIZE;
275
0
  if (datalen > MAX_IMSGSIZE) {
276
0
    errno = ERANGE;
277
0
    return (NULL);
278
0
  }
279
280
0
  hdr.type = type;
281
0
  hdr.flags = 0;
282
0
  hdr.peerid = peerid;
283
0
  if ((hdr.pid = pid) == 0)
284
0
    hdr.pid = ibuf->pid;
285
0
  if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
286
0
    return (NULL);
287
0
  }
288
0
  if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
289
0
    return (NULL);
290
291
0
  return (wbuf);
292
0
}
293
294
int
295
imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
296
0
{
297
0
  if (datalen)
298
0
    if (ibuf_add(msg, data, datalen) == -1) {
299
0
      ibuf_free(msg);
300
0
      return (-1);
301
0
    }
302
0
  return (datalen);
303
0
}
304
305
void
306
imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
307
0
{
308
0
  struct imsg_hdr *hdr;
309
310
0
  hdr = (struct imsg_hdr *)msg->buf;
311
312
0
  hdr->flags &= ~IMSGF_HASFD;
313
0
  if (ibuf_fd_avail(msg))
314
0
    hdr->flags |= IMSGF_HASFD;
315
0
  hdr->len = ibuf_size(msg);
316
317
0
  ibuf_close(&ibuf->w, msg);
318
0
}
319
320
void
321
imsg_free(struct imsg *imsg)
322
0
{
323
0
  freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
324
0
}
325
326
static int
327
imsg_get_fd(struct imsgbuf *ibuf)
328
0
{
329
0
  int    fd;
330
0
  struct imsg_fd  *ifd;
331
332
0
  if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
333
0
    return (-1);
334
335
0
  fd = ifd->fd;
336
0
  TAILQ_REMOVE(&ibuf->fds, ifd, entry);
337
0
  free(ifd);
338
339
0
  return (fd);
340
0
}
341
342
int
343
imsg_flush(struct imsgbuf *ibuf)
344
0
{
345
0
  while (ibuf->w.queued)
346
0
    if (msgbuf_write(&ibuf->w) <= 0)
347
0
      return (-1);
348
0
  return (0);
349
0
}
350
351
void
352
imsg_clear(struct imsgbuf *ibuf)
353
0
{
354
0
  int fd;
355
356
0
  msgbuf_clear(&ibuf->w);
357
0
  while ((fd = imsg_get_fd(ibuf)) != -1)
358
0
    close(fd);
359
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg.h.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg.h.html index e79c4f111..dd8462226 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg.h.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/imsg.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/imsg.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg.h,v 1.7 2023/06/19 17:19:50 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
5
 * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
6
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#ifndef _IMSG_H_
22
#define _IMSG_H_
23
24
#include <stdint.h>
25
26
#define IBUF_READ_SIZE    65535
27
0
#define IMSG_HEADER_SIZE  sizeof(struct imsg_hdr)
28
0
#define MAX_IMSGSIZE    16384
29
30
struct ibuf {
31
  TAILQ_ENTRY(ibuf)  entry;
32
  unsigned char   *buf;
33
  size_t       size;
34
  size_t       max;
35
  size_t       wpos;
36
  size_t       rpos;
37
  int      fd;
38
};
39
40
struct msgbuf {
41
  TAILQ_HEAD(, ibuf)   bufs;
42
  uint32_t     queued;
43
  int      fd;
44
};
45
46
struct ibuf_read {
47
  unsigned char    buf[IBUF_READ_SIZE];
48
  unsigned char   *rptr;
49
  size_t       wpos;
50
};
51
52
struct imsg_fd {
53
  TAILQ_ENTRY(imsg_fd)  entry;
54
  int     fd;
55
};
56
57
struct imsgbuf {
58
  TAILQ_HEAD(, imsg_fd)  fds;
59
  struct ibuf_read   r;
60
  struct msgbuf    w;
61
  int      fd;
62
  pid_t      pid;
63
};
64
65
0
#define IMSGF_HASFD 1
66
67
struct imsg_hdr {
68
  uint32_t   type;
69
  uint16_t   len;
70
  uint16_t   flags;
71
  uint32_t   peerid;
72
  uint32_t   pid;
73
};
74
75
struct imsg {
76
  struct imsg_hdr  hdr;
77
  int    fd;
78
  void    *data;
79
};
80
81
struct iovec;
82
83
/* imsg-buffer.c */
84
struct ibuf *ibuf_open(size_t);
85
struct ibuf *ibuf_dynamic(size_t, size_t);
86
int    ibuf_add(struct ibuf *, const void *, size_t);
87
int    ibuf_add_buf(struct ibuf *, const struct ibuf *);
88
int    ibuf_add_zero(struct ibuf *, size_t);
89
int    ibuf_add_n8(struct ibuf *, uint64_t);
90
int    ibuf_add_n16(struct ibuf *, uint64_t);
91
int    ibuf_add_n32(struct ibuf *, uint64_t);
92
int    ibuf_add_n64(struct ibuf *, uint64_t);
93
void    *ibuf_reserve(struct ibuf *, size_t);
94
void    *ibuf_seek(struct ibuf *, size_t, size_t);
95
int    ibuf_set(struct ibuf *, size_t, const void *, size_t);
96
int    ibuf_set_n8(struct ibuf *, size_t, uint64_t);
97
int    ibuf_set_n16(struct ibuf *, size_t, uint64_t);
98
int    ibuf_set_n32(struct ibuf *, size_t, uint64_t);
99
int    ibuf_set_n64(struct ibuf *, size_t, uint64_t);
100
void    *ibuf_data(struct ibuf *);
101
size_t     ibuf_size(struct ibuf *);
102
size_t     ibuf_left(struct ibuf *);
103
void     ibuf_close(struct msgbuf *, struct ibuf *);
104
void     ibuf_free(struct ibuf *);
105
int    ibuf_fd_avail(struct ibuf *);
106
int    ibuf_fd_get(struct ibuf *);
107
void     ibuf_fd_set(struct ibuf *, int);
108
int    ibuf_write(struct msgbuf *);
109
void     msgbuf_init(struct msgbuf *);
110
void     msgbuf_clear(struct msgbuf *);
111
int    msgbuf_write(struct msgbuf *);
112
113
/* imsg.c */
114
void   imsg_init(struct imsgbuf *, int);
115
ssize_t  imsg_read(struct imsgbuf *);
116
ssize_t  imsg_get(struct imsgbuf *, struct imsg *);
117
int  imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
118
      const void *, uint16_t);
119
int  imsg_composev(struct imsgbuf *, uint32_t, uint32_t,  pid_t, int,
120
      const struct iovec *, int);
121
int  imsg_compose_ibuf(struct imsgbuf *, uint32_t, uint32_t, pid_t,
122
      struct ibuf *);
123
struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t);
124
int  imsg_add(struct ibuf *, const void *, uint16_t);
125
void   imsg_close(struct imsgbuf *, struct ibuf *);
126
void   imsg_free(struct imsg *);
127
int  imsg_flush(struct imsgbuf *);
128
void   imsg_clear(struct imsgbuf *);
129
130
#endif
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/imsg.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg.h,v 1.7 2023/06/19 17:19:50 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
5
 * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
6
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#ifndef _IMSG_H_
22
#define _IMSG_H_
23
24
#include <stdint.h>
25
26
#define IBUF_READ_SIZE    65535
27
0
#define IMSG_HEADER_SIZE  sizeof(struct imsg_hdr)
28
0
#define MAX_IMSGSIZE    16384
29
30
struct ibuf {
31
  TAILQ_ENTRY(ibuf)  entry;
32
  unsigned char   *buf;
33
  size_t       size;
34
  size_t       max;
35
  size_t       wpos;
36
  size_t       rpos;
37
  int      fd;
38
};
39
40
struct msgbuf {
41
  TAILQ_HEAD(, ibuf)   bufs;
42
  uint32_t     queued;
43
  int      fd;
44
};
45
46
struct ibuf_read {
47
  unsigned char    buf[IBUF_READ_SIZE];
48
  unsigned char   *rptr;
49
  size_t       wpos;
50
};
51
52
struct imsg_fd {
53
  TAILQ_ENTRY(imsg_fd)  entry;
54
  int     fd;
55
};
56
57
struct imsgbuf {
58
  TAILQ_HEAD(, imsg_fd)  fds;
59
  struct ibuf_read   r;
60
  struct msgbuf    w;
61
  int      fd;
62
  pid_t      pid;
63
};
64
65
0
#define IMSGF_HASFD 1
66
67
struct imsg_hdr {
68
  uint32_t   type;
69
  uint16_t   len;
70
  uint16_t   flags;
71
  uint32_t   peerid;
72
  uint32_t   pid;
73
};
74
75
struct imsg {
76
  struct imsg_hdr  hdr;
77
  int    fd;
78
  void    *data;
79
};
80
81
struct iovec;
82
83
/* imsg-buffer.c */
84
struct ibuf *ibuf_open(size_t);
85
struct ibuf *ibuf_dynamic(size_t, size_t);
86
int    ibuf_add(struct ibuf *, const void *, size_t);
87
int    ibuf_add_buf(struct ibuf *, const struct ibuf *);
88
int    ibuf_add_zero(struct ibuf *, size_t);
89
int    ibuf_add_n8(struct ibuf *, uint64_t);
90
int    ibuf_add_n16(struct ibuf *, uint64_t);
91
int    ibuf_add_n32(struct ibuf *, uint64_t);
92
int    ibuf_add_n64(struct ibuf *, uint64_t);
93
void    *ibuf_reserve(struct ibuf *, size_t);
94
void    *ibuf_seek(struct ibuf *, size_t, size_t);
95
int    ibuf_set(struct ibuf *, size_t, const void *, size_t);
96
int    ibuf_set_n8(struct ibuf *, size_t, uint64_t);
97
int    ibuf_set_n16(struct ibuf *, size_t, uint64_t);
98
int    ibuf_set_n32(struct ibuf *, size_t, uint64_t);
99
int    ibuf_set_n64(struct ibuf *, size_t, uint64_t);
100
void    *ibuf_data(struct ibuf *);
101
size_t     ibuf_size(struct ibuf *);
102
size_t     ibuf_left(struct ibuf *);
103
void     ibuf_close(struct msgbuf *, struct ibuf *);
104
void     ibuf_free(struct ibuf *);
105
int    ibuf_fd_avail(struct ibuf *);
106
int    ibuf_fd_get(struct ibuf *);
107
void     ibuf_fd_set(struct ibuf *, int);
108
int    ibuf_write(struct msgbuf *);
109
void     msgbuf_init(struct msgbuf *);
110
void     msgbuf_clear(struct msgbuf *);
111
int    msgbuf_write(struct msgbuf *);
112
113
/* imsg.c */
114
void   imsg_init(struct imsgbuf *, int);
115
ssize_t  imsg_read(struct imsgbuf *);
116
ssize_t  imsg_get(struct imsgbuf *, struct imsg *);
117
int  imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
118
      const void *, uint16_t);
119
int  imsg_composev(struct imsgbuf *, uint32_t, uint32_t,  pid_t, int,
120
      const struct iovec *, int);
121
int  imsg_compose_ibuf(struct imsgbuf *, uint32_t, uint32_t, pid_t,
122
      struct ibuf *);
123
struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t);
124
int  imsg_add(struct ibuf *, const void *, uint16_t);
125
void   imsg_close(struct imsgbuf *, struct ibuf *);
126
void   imsg_free(struct imsg *);
127
int  imsg_flush(struct imsgbuf *);
128
void   imsg_clear(struct imsgbuf *);
129
130
#endif
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/openbsd-compat.h.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/openbsd-compat.h.html index dc92ef62a..89f8dc6ba 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/openbsd-compat.h.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/openbsd-compat.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/openbsd-compat.h
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#ifndef _OPENBSD_COMPAT_H
4
#define _OPENBSD_COMPAT_H
5
6
#define YYSTYPE_IS_DECLARED 1 /* for bison */
7
8
#ifndef LOGIN_NAME_MAX
9
# define LOGIN_NAME_MAX 9
10
#endif
11
12
#include <stdlib.h>
13
14
#if !defined(HAVE_STRLCAT)
15
size_t strlcat(char *, const char *, size_t);
16
#endif
17
18
#if !defined(HAVE_STRLCPY)
19
size_t strlcpy(char *, const char *, size_t);
20
#endif
21
22
#if !defined(HAVE_REALLOCARRAY)
23
void *reallocarray(void *, size_t, size_t);
24
#endif
25
26
#if !defined(HAVE_RECALLOCARRAY)
27
void *recallocarray(void *, size_t, size_t, size_t);
28
#endif
29
30
#if !defined(HAVE_EXPLICIT_BZERO)
31
void explicit_bzero(void *, size_t);
32
#endif
33
34
#if !defined(HAVE_GETPAGESIZE)
35
int getpagesize(void);
36
#endif
37
38
#if !defined(HAVE_TIMINGSAFE_BCMP)
39
int timingsafe_bcmp(const void *, const void *, size_t);
40
#endif
41
42
#if !defined(HAVE_ACCEPT4)
43
#include <sys/socket.h>
44
#define accept4 bsd_accept4
45
int bsd_accept4(int, struct sockaddr *, socklen_t *, int flags);
46
#endif
47
48
#if !defined(HAVE_SOCK_NONBLOCK)
49
#define SOCK_NONBLOCK 0x4000  /* Set O_NONBLOCK */
50
#define SOCK_CLOEXEC  0x8000  /* Set FD_CLOEXEC */
51
#define SOCK_SETFLAGS 0xf000  /* Set flags as checked above */
52
#define socket bsd_socket
53
int bsd_socket(int domain, int type, int protocol);
54
#endif
55
56
#if !defined(HAVE_SETPROCTITLE)
57
void compat_init_setproctitle(int argc, char *argv[]);
58
void setproctitle(const char *fmt, ...);
59
#endif
60
61
#if !defined(HAVE_SETRESGID)
62
int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
63
#endif
64
65
#if !defined(HAVE_SETRESUID)
66
int setresuid(uid_t ruid, uid_t euid, uid_t suid);
67
#endif
68
69
#ifdef _WIN32
70
#include <direct.h>
71
uid_t geteuid(void);
72
#endif
73
74
#if !defined(HAVE_GETRTABLE)
75
int getrtable(void);
76
#endif
77
78
#if !defined(HAVE_SETRTABLE)
79
int setrtable(int rtableid);
80
#endif
81
82
#if !defined(HAVE_STRTONUM)
83
long long
84
strtonum(const char *nptr, long long minval, long long maxval,
85
    const char **errstr);
86
#endif
87
88
#if !defined(HAVE_FREEZERO)
89
void freezero(void *ptr, size_t size);
90
#endif
91
92
#if !defined(HAVE_GETDTABLECOUNT)
93
int getdtablecount(void);
94
#endif
95
96
#if !defined(HAVE_GETOPT)
97
#include "getopt.h"
98
#endif
99
100
#if !defined(HAVE_USLEEP)
101
int usleep(unsigned int x);
102
#endif
103
104
#ifdef HAVE_SOCKADDR_SA_LEN
105
#ifndef SA_LEN
106
#define SA_LEN(sa)      (sa)->sa_len
107
#endif
108
#ifndef SS_LEN
109
#define SS_LEN(ss)      (ss).ss_len
110
#endif
111
#else
112
#define SA_LEN(sa)                  \
113
19.8k
  ((sa->sa_family == AF_INET)  ? sizeof(struct sockaddr_in) :  \
114
19.8k
  (sa->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) :  \
115
2.63k
  sizeof(struct sockaddr))
116
#define SS_LEN(ss)              \
117
  ((ss.ss_family == AF_INET)  ? sizeof(struct sockaddr_in) :  \
118
  (ss.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) :  \
119
  sizeof(struct sockaddr_storage))
120
#endif
121
122
#ifndef HAVE_FFS
123
int ffs(int);
124
#endif
125
126
#ifdef __OpenBSD__
127
typedef int evutil_socket_t;
128
#endif
129
130
#ifndef _PASSWORD_LEN
131
#define _PASSWORD_LEN 120
132
#endif
133
134
#ifdef HAVE_DIRENT_H
135
# include <dirent.h>
136
# define NAMLEN(dirent) strlen((dirent)->d_name)
137
#else
138
# define dirent direct
139
# define NAMLEN(dirent) (dirent)->d_namlen
140
# ifdef HAVE_SYS_NDIR_H
141
#  include <sys/ndir.h>
142
# endif
143
# ifdef HAVE_SYS_DIR_H
144
#  include <sys/dir.h>
145
# endif
146
# ifdef HAVE_NDIR_H
147
#  include <ndir.h>
148
# endif
149
#endif
150
151
#if !defined(AF_LINK) && defined(AF_PACKET)
152
#define AF_LINK AF_PACKET /* XXX workaround on Linux */
153
#endif
154
155
#ifndef HOST_NAME_MAX
156
# include "netdb.h" /* for MAXHOSTNAMELEN */
157
# if defined(_POSIX_HOST_NAME_MAX)
158
#  define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
159
# elif defined(MAXHOSTNAMELEN)
160
#  define HOST_NAME_MAX MAXHOSTNAMELEN
161
# else
162
#  define HOST_NAME_MAX 255
163
# endif
164
#endif /* HOST_NAME_MAX */
165
166
/* FreeBSD */
167
#ifndef CPI_PRIVATE_MIN
168
#define CPI_PRIVATE_MIN   61440
169
#endif
170
#ifndef CPI_PRIVATE_MAX
171
#define CPI_PRIVATE_MAX   65535
172
#endif
173
174
#if !defined(SADB_X_ADDFLOW) && defined(SADB_X_SPDUPDATE)
175
#define SADB_X_ADDFLOW  SADB_X_SPDUPDATE
176
#endif
177
#if !defined(SADB_X_DELFLOW) && defined(SADB_X_SPDDELETE)
178
#define SADB_X_DELFLOW  SADB_X_SPDDELETE
179
#endif
180
#if !defined(SADB_X_FLOW_TYPE_DENY)
181
#define SADB_X_FLOW_TYPE_DENY 1
182
#endif
183
184
#if defined(HAVE_LINUX_PFKEY_H)
185
/* Encryption Algorithms */
186
#define SADB_X_EALG_AES   SADB_X_EALG_AESCBC
187
#define SADB_X_EALG_AESGCM16  SADB_X_EALG_AES_GCM_ICV16
188
#define SADB_X_EALG_AESGMAC SADB_X_EALG_NULL_AES_GMAC
189
190
/* Authentication Algorithms */
191
#define SADB_X_AALG_SHA2_256  SADB_X_AALG_SHA2_256HMAC
192
#define SADB_X_AALG_SHA2_384  SADB_X_AALG_SHA2_384HMAC
193
#define SADB_X_AALG_SHA2_512  SADB_X_AALG_SHA2_512HMAC
194
#endif
195
196
#if !defined(__packed)
197
#define __packed  __attribute__((__packed__))
198
#endif
199
200
#if defined(HAVE_APPLE_NATT) && !defined(SADB_X_EXT_NATT)
201
/*
202
 * These are hidden in Apple XNU's private pfkeyv2.h header
203
 */
204
#define SADB_X_EXT_NATT     0x0002  /* Enable UDP encapsulation */
205
#define SADB_X_EXT_NATT_KEEPALIVE 0x0004  /* Send NAT-T keepalives */
206
#define SADB_X_EXT_NATT_MULTIPLEUSERS 0x0008  /* Use for VPN gateways */
207
#define SADB_X_EXT_NATT_DETECTED_PEER 0x1000  /* Opposite of KEEPALIVE */
208
209
struct sadb_sa_natt {
210
  uint16_t   sadb_sa_natt_port;
211
  union {
212
    uint16_t   sadb_reserved0;
213
    uint16_t   sadb_sa_natt_interval;
214
  };
215
  uint16_t   sadb_sa_natt_offload_interval;
216
  uint16_t   sadb_sa_natt_src_port;
217
};
218
#endif
219
220
#endif /* !_OPENBSD_COMPAT_H */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/openbsd-compat.h
Line
Count
Source (jump to first uncovered line)
1
/* Placed in the public domain */
2
3
#ifndef _OPENBSD_COMPAT_H
4
#define _OPENBSD_COMPAT_H
5
6
#define YYSTYPE_IS_DECLARED 1 /* for bison */
7
8
#ifndef LOGIN_NAME_MAX
9
# define LOGIN_NAME_MAX 9
10
#endif
11
12
#include <stdlib.h>
13
14
#if !defined(HAVE_STRLCAT)
15
size_t strlcat(char *, const char *, size_t);
16
#endif
17
18
#if !defined(HAVE_STRLCPY)
19
size_t strlcpy(char *, const char *, size_t);
20
#endif
21
22
#if !defined(HAVE_REALLOCARRAY)
23
void *reallocarray(void *, size_t, size_t);
24
#endif
25
26
#if !defined(HAVE_RECALLOCARRAY)
27
void *recallocarray(void *, size_t, size_t, size_t);
28
#endif
29
30
#if !defined(HAVE_EXPLICIT_BZERO)
31
void explicit_bzero(void *, size_t);
32
#endif
33
34
#if !defined(HAVE_GETPAGESIZE)
35
int getpagesize(void);
36
#endif
37
38
#if !defined(HAVE_TIMINGSAFE_BCMP)
39
int timingsafe_bcmp(const void *, const void *, size_t);
40
#endif
41
42
#if !defined(HAVE_ACCEPT4)
43
#include <sys/socket.h>
44
#define accept4 bsd_accept4
45
int bsd_accept4(int, struct sockaddr *, socklen_t *, int flags);
46
#endif
47
48
#if !defined(HAVE_SOCK_NONBLOCK)
49
#define SOCK_NONBLOCK 0x4000  /* Set O_NONBLOCK */
50
#define SOCK_CLOEXEC  0x8000  /* Set FD_CLOEXEC */
51
#define SOCK_SETFLAGS 0xf000  /* Set flags as checked above */
52
#define socket bsd_socket
53
int bsd_socket(int domain, int type, int protocol);
54
#endif
55
56
#if !defined(HAVE_SETPROCTITLE)
57
void compat_init_setproctitle(int argc, char *argv[]);
58
void setproctitle(const char *fmt, ...);
59
#endif
60
61
#if !defined(HAVE_SETRESGID)
62
int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
63
#endif
64
65
#if !defined(HAVE_SETRESUID)
66
int setresuid(uid_t ruid, uid_t euid, uid_t suid);
67
#endif
68
69
#ifdef _WIN32
70
#include <direct.h>
71
uid_t geteuid(void);
72
#endif
73
74
#if !defined(HAVE_GETRTABLE)
75
int getrtable(void);
76
#endif
77
78
#if !defined(HAVE_SETRTABLE)
79
int setrtable(int rtableid);
80
#endif
81
82
#if !defined(HAVE_STRTONUM)
83
long long
84
strtonum(const char *nptr, long long minval, long long maxval,
85
    const char **errstr);
86
#endif
87
88
#if !defined(HAVE_FREEZERO)
89
void freezero(void *ptr, size_t size);
90
#endif
91
92
#if !defined(HAVE_GETDTABLECOUNT)
93
int getdtablecount(void);
94
#endif
95
96
#if !defined(HAVE_GETOPT)
97
#include "getopt.h"
98
#endif
99
100
#if !defined(HAVE_USLEEP)
101
int usleep(unsigned int x);
102
#endif
103
104
#ifdef HAVE_SOCKADDR_SA_LEN
105
#ifndef SA_LEN
106
#define SA_LEN(sa)      (sa)->sa_len
107
#endif
108
#ifndef SS_LEN
109
#define SS_LEN(ss)      (ss).ss_len
110
#endif
111
#else
112
#define SA_LEN(sa)                  \
113
19.8k
  ((sa->sa_family == AF_INET)  ? sizeof(struct sockaddr_in) :  \
114
19.8k
  (sa->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) :  \
115
2.63k
  sizeof(struct sockaddr))
116
#define SS_LEN(ss)              \
117
  ((ss.ss_family == AF_INET)  ? sizeof(struct sockaddr_in) :  \
118
  (ss.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) :  \
119
  sizeof(struct sockaddr_storage))
120
#endif
121
122
#ifndef HAVE_FFS
123
int ffs(int);
124
#endif
125
126
#ifdef __OpenBSD__
127
typedef int evutil_socket_t;
128
#endif
129
130
#ifndef _PASSWORD_LEN
131
#define _PASSWORD_LEN 120
132
#endif
133
134
#ifdef HAVE_DIRENT_H
135
# include <dirent.h>
136
# define NAMLEN(dirent) strlen((dirent)->d_name)
137
#else
138
# define dirent direct
139
# define NAMLEN(dirent) (dirent)->d_namlen
140
# ifdef HAVE_SYS_NDIR_H
141
#  include <sys/ndir.h>
142
# endif
143
# ifdef HAVE_SYS_DIR_H
144
#  include <sys/dir.h>
145
# endif
146
# ifdef HAVE_NDIR_H
147
#  include <ndir.h>
148
# endif
149
#endif
150
151
#if !defined(AF_LINK) && defined(AF_PACKET)
152
#define AF_LINK AF_PACKET /* XXX workaround on Linux */
153
#endif
154
155
#ifndef HOST_NAME_MAX
156
# include "netdb.h" /* for MAXHOSTNAMELEN */
157
# if defined(_POSIX_HOST_NAME_MAX)
158
#  define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
159
# elif defined(MAXHOSTNAMELEN)
160
#  define HOST_NAME_MAX MAXHOSTNAMELEN
161
# else
162
#  define HOST_NAME_MAX 255
163
# endif
164
#endif /* HOST_NAME_MAX */
165
166
/* FreeBSD */
167
#ifndef CPI_PRIVATE_MIN
168
#define CPI_PRIVATE_MIN   61440
169
#endif
170
#ifndef CPI_PRIVATE_MAX
171
#define CPI_PRIVATE_MAX   65535
172
#endif
173
174
#if !defined(SADB_X_ADDFLOW) && defined(SADB_X_SPDUPDATE)
175
#define SADB_X_ADDFLOW  SADB_X_SPDUPDATE
176
#endif
177
#if !defined(SADB_X_DELFLOW) && defined(SADB_X_SPDDELETE)
178
#define SADB_X_DELFLOW  SADB_X_SPDDELETE
179
#endif
180
#if !defined(SADB_X_FLOW_TYPE_DENY)
181
#define SADB_X_FLOW_TYPE_DENY 1
182
#endif
183
184
#if defined(HAVE_LINUX_PFKEY_H)
185
/* Encryption Algorithms */
186
#define SADB_X_EALG_AES   SADB_X_EALG_AESCBC
187
#define SADB_X_EALG_AESGCM16  SADB_X_EALG_AES_GCM_ICV16
188
#define SADB_X_EALG_AESGMAC SADB_X_EALG_NULL_AES_GMAC
189
190
/* Authentication Algorithms */
191
#define SADB_X_AALG_SHA2_256  SADB_X_AALG_SHA2_256HMAC
192
#define SADB_X_AALG_SHA2_384  SADB_X_AALG_SHA2_384HMAC
193
#define SADB_X_AALG_SHA2_512  SADB_X_AALG_SHA2_512HMAC
194
#endif
195
196
#if !defined(__packed)
197
#define __packed  __attribute__((__packed__))
198
#endif
199
200
#if defined(HAVE_APPLE_NATT) && !defined(SADB_X_EXT_NATT)
201
/*
202
 * These are hidden in Apple XNU's private pfkeyv2.h header
203
 */
204
#define SADB_X_EXT_NATT     0x0002  /* Enable UDP encapsulation */
205
#define SADB_X_EXT_NATT_KEEPALIVE 0x0004  /* Send NAT-T keepalives */
206
#define SADB_X_EXT_NATT_MULTIPLEUSERS 0x0008  /* Use for VPN gateways */
207
#define SADB_X_EXT_NATT_DETECTED_PEER 0x1000  /* Opposite of KEEPALIVE */
208
209
struct sadb_sa_natt {
210
  uint16_t   sadb_sa_natt_port;
211
  union {
212
    uint16_t   sadb_reserved0;
213
    uint16_t   sadb_sa_natt_interval;
214
  };
215
  uint16_t   sadb_sa_natt_offload_interval;
216
  uint16_t   sadb_sa_natt_src_port;
217
};
218
#endif
219
220
#endif /* !_OPENBSD_COMPAT_H */
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/recallocarray.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/recallocarray.c.html index b6081c675..c6d552364 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/recallocarray.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/recallocarray.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/recallocarray.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: recallocarray.c,v 1.2 2021/03/18 11:16:58 claudio Exp $ */
2
/*
3
 * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
4
 *
5
 * Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <errno.h>
19
#include <stdlib.h>
20
#include <stdint.h>
21
#include <string.h>
22
#include <unistd.h>
23
24
/*
25
 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
26
 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
27
 */
28
0
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
29
30
void *
31
recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
32
0
{
33
0
  size_t oldsize, newsize;
34
0
  void *newptr;
35
36
0
  if (ptr == NULL)
37
0
    return calloc(newnmemb, size);
38
39
0
  if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
40
0
      newnmemb > 0 && SIZE_MAX / newnmemb < size) {
41
0
    errno = ENOMEM;
42
0
    return NULL;
43
0
  }
44
0
  newsize = newnmemb * size;
45
46
0
  if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
47
0
      oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
48
0
    errno = EINVAL;
49
0
    return NULL;
50
0
  }
51
0
  oldsize = oldnmemb * size;
52
  
53
  /*
54
   * Don't bother too much if we're shrinking just a bit,
55
   * we do not shrink for series of small steps, oh well.
56
   */
57
0
  if (newsize <= oldsize) {
58
0
    size_t d = oldsize - newsize;
59
60
0
    if (d < oldsize / 2 && d < (size_t)getpagesize()) {
61
0
      memset((char *)ptr + newsize, 0, d);
62
0
      return ptr;
63
0
    }
64
0
  }
65
66
0
  newptr = malloc(newsize);
67
0
  if (newptr == NULL)
68
0
    return NULL;
69
70
0
  if (newsize > oldsize) {
71
0
    memcpy(newptr, ptr, oldsize);
72
0
    memset((char *)newptr + oldsize, 0, newsize - oldsize);
73
0
  } else
74
0
    memcpy(newptr, ptr, newsize);
75
76
0
  explicit_bzero(ptr, oldsize);
77
0
  free(ptr);
78
79
0
  return newptr;
80
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/recallocarray.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: recallocarray.c,v 1.2 2021/03/18 11:16:58 claudio Exp $ */
2
/*
3
 * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
4
 *
5
 * Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <errno.h>
19
#include <stdlib.h>
20
#include <stdint.h>
21
#include <string.h>
22
#include <unistd.h>
23
24
/*
25
 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
26
 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
27
 */
28
0
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
29
30
void *
31
recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
32
0
{
33
0
  size_t oldsize, newsize;
34
0
  void *newptr;
35
36
0
  if (ptr == NULL)
37
0
    return calloc(newnmemb, size);
38
39
0
  if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
40
0
      newnmemb > 0 && SIZE_MAX / newnmemb < size) {
41
0
    errno = ENOMEM;
42
0
    return NULL;
43
0
  }
44
0
  newsize = newnmemb * size;
45
46
0
  if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
47
0
      oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
48
0
    errno = EINVAL;
49
0
    return NULL;
50
0
  }
51
0
  oldsize = oldnmemb * size;
52
  
53
  /*
54
   * Don't bother too much if we're shrinking just a bit,
55
   * we do not shrink for series of small steps, oh well.
56
   */
57
0
  if (newsize <= oldsize) {
58
0
    size_t d = oldsize - newsize;
59
60
0
    if (d < oldsize / 2 && d < (size_t)getpagesize()) {
61
0
      memset((char *)ptr + newsize, 0, d);
62
0
      return ptr;
63
0
    }
64
0
  }
65
66
0
  newptr = malloc(newsize);
67
0
  if (newptr == NULL)
68
0
    return NULL;
69
70
0
  if (newsize > oldsize) {
71
0
    memcpy(newptr, ptr, oldsize);
72
0
    memset((char *)newptr + oldsize, 0, newsize - oldsize);
73
0
  } else
74
0
    memcpy(newptr, ptr, newsize);
75
76
0
  explicit_bzero(ptr, oldsize);
77
0
  free(ptr);
78
79
0
  return newptr;
80
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/setproctitle.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/setproctitle.c.html index 4ba88c549..4ffa27345 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/setproctitle.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/setproctitle.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/setproctitle.c
Line
Count
Source (jump to first uncovered line)
1
/* Based on conf.c from UCB sendmail 8.8.8 */
2
3
/*
4
 * Copyright 2003 Damien Miller
5
 * Copyright (c) 1983, 1995-1997 Eric P. Allman
6
 * Copyright (c) 1988, 1993
7
 *  The Regents of the University of California.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 * 3. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 */
33
34
#include "openbsd-compat.h"
35
36
#ifndef HAVE_SETPROCTITLE
37
38
#include <stdarg.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <unistd.h>
42
#ifdef HAVE_SYS_PSTAT_H
43
#include <sys/pstat.h>
44
#endif
45
#include <string.h>
46
47
#include <vis.h>
48
49
#define SPT_NONE  0 /* don't use it at all */
50
#define SPT_PSTAT 1 /* use pstat(PSTAT_SETCMD, ...) */
51
#define SPT_REUSEARGV 2 /* cover argv with title information */
52
53
#ifndef SPT_TYPE
54
# define SPT_TYPE SPT_NONE
55
#endif
56
57
#ifndef SPT_PADCHAR
58
0
# define SPT_PADCHAR  '\0'
59
#endif
60
61
#if SPT_TYPE == SPT_REUSEARGV
62
static char *argv_start = NULL;
63
static size_t argv_env_len = 0;
64
#endif
65
66
#endif /* HAVE_SETPROCTITLE */
67
68
void
69
compat_init_setproctitle(int argc, char *argv[])
70
0
{
71
0
#if !defined(HAVE_SETPROCTITLE) && \
72
0
    defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV
73
0
  extern char **environ;
74
0
  char *lastargv = NULL;
75
0
  char **envp = environ;
76
0
  int i;
77
78
  /*
79
   * NB: This assumes that argv has already been copied out of the
80
   * way. This is true for sshd, but may not be true for other
81
   * programs. Beware.
82
   */
83
84
0
  if (argc == 0 || argv[0] == NULL)
85
0
    return;
86
87
  /* Fail if we can't allocate room for the new environment */
88
0
  for (i = 0; envp[i] != NULL; i++)
89
0
    ;
90
0
  if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) {
91
0
    environ = envp; /* put it back */
92
0
    return;
93
0
  }
94
95
  /*
96
   * Find the last argv string or environment variable within
97
   * our process memory area.
98
   */
99
0
  for (i = 0; i < argc; i++) {
100
0
    if (lastargv == NULL || lastargv + 1 == argv[i])
101
0
      lastargv = argv[i] + strlen(argv[i]);
102
0
  }
103
0
  for (i = 0; envp[i] != NULL; i++) {
104
0
    if (lastargv + 1 == envp[i])
105
0
      lastargv = envp[i] + strlen(envp[i]);
106
0
  }
107
108
0
  argv[1] = NULL;
109
0
  argv_start = argv[0];
110
0
  argv_env_len = lastargv - argv[0] - 1;
111
112
  /*
113
   * Copy environment
114
   * XXX - will truncate env on strdup fail
115
   */
116
0
  for (i = 0; envp[i] != NULL; i++)
117
0
    environ[i] = strdup(envp[i]);
118
0
  environ[i] = NULL;
119
0
#endif /* SPT_REUSEARGV */
120
0
}
121
122
#ifndef HAVE_SETPROCTITLE
123
void
124
setproctitle(const char *fmt, ...)
125
0
{
126
0
#if SPT_TYPE != SPT_NONE
127
0
  va_list ap;
128
0
  char buf[1024], ptitle[1024];
129
0
  size_t len = 0;
130
0
  int r;
131
0
  extern char *__progname;
132
#if SPT_TYPE == SPT_PSTAT
133
  union pstun pst;
134
#endif
135
136
0
#if SPT_TYPE == SPT_REUSEARGV
137
0
  if (argv_env_len <= 0)
138
0
    return;
139
0
#endif
140
141
0
  strlcpy(buf, __progname, sizeof(buf));
142
143
0
  r = -1;
144
0
  va_start(ap, fmt);
145
0
  if (fmt != NULL) {
146
0
    len = strlcat(buf, ": ", sizeof(buf));
147
0
    if (len < sizeof(buf))
148
0
      r = vsnprintf(buf + len, sizeof(buf) - len , fmt, ap);
149
0
  }
150
0
  va_end(ap);
151
0
  if (r == -1 || (size_t)r >= sizeof(buf) - len)
152
0
    return;
153
0
  strnvis(ptitle, buf, sizeof(ptitle),
154
0
      VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL);
155
156
#if SPT_TYPE == SPT_PSTAT
157
  pst.pst_command = ptitle;
158
  pstat(PSTAT_SETCMD, pst, strlen(ptitle), 0, 0);
159
#elif SPT_TYPE == SPT_REUSEARGV
160
/*  debug("setproctitle: copy \"%s\" into len %d",
161
      buf, argv_env_len); */
162
0
  len = strlcpy(argv_start, ptitle, argv_env_len);
163
0
  for(; len < argv_env_len; len++)
164
0
    argv_start[len] = SPT_PADCHAR;
165
0
#endif
166
167
0
#endif /* SPT_NONE */
168
0
}
169
170
#endif /* HAVE_SETPROCTITLE */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/setproctitle.c
Line
Count
Source (jump to first uncovered line)
1
/* Based on conf.c from UCB sendmail 8.8.8 */
2
3
/*
4
 * Copyright 2003 Damien Miller
5
 * Copyright (c) 1983, 1995-1997 Eric P. Allman
6
 * Copyright (c) 1988, 1993
7
 *  The Regents of the University of California.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 * 3. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 */
33
34
#include "openbsd-compat.h"
35
36
#ifndef HAVE_SETPROCTITLE
37
38
#include <stdarg.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <unistd.h>
42
#ifdef HAVE_SYS_PSTAT_H
43
#include <sys/pstat.h>
44
#endif
45
#include <string.h>
46
47
#include <vis.h>
48
49
#define SPT_NONE  0 /* don't use it at all */
50
#define SPT_PSTAT 1 /* use pstat(PSTAT_SETCMD, ...) */
51
#define SPT_REUSEARGV 2 /* cover argv with title information */
52
53
#ifndef SPT_TYPE
54
# define SPT_TYPE SPT_NONE
55
#endif
56
57
#ifndef SPT_PADCHAR
58
0
# define SPT_PADCHAR  '\0'
59
#endif
60
61
#if SPT_TYPE == SPT_REUSEARGV
62
static char *argv_start = NULL;
63
static size_t argv_env_len = 0;
64
#endif
65
66
#endif /* HAVE_SETPROCTITLE */
67
68
void
69
compat_init_setproctitle(int argc, char *argv[])
70
0
{
71
0
#if !defined(HAVE_SETPROCTITLE) && \
72
0
    defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV
73
0
  extern char **environ;
74
0
  char *lastargv = NULL;
75
0
  char **envp = environ;
76
0
  int i;
77
78
  /*
79
   * NB: This assumes that argv has already been copied out of the
80
   * way. This is true for sshd, but may not be true for other
81
   * programs. Beware.
82
   */
83
84
0
  if (argc == 0 || argv[0] == NULL)
85
0
    return;
86
87
  /* Fail if we can't allocate room for the new environment */
88
0
  for (i = 0; envp[i] != NULL; i++)
89
0
    ;
90
0
  if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) {
91
0
    environ = envp; /* put it back */
92
0
    return;
93
0
  }
94
95
  /*
96
   * Find the last argv string or environment variable within
97
   * our process memory area.
98
   */
99
0
  for (i = 0; i < argc; i++) {
100
0
    if (lastargv == NULL || lastargv + 1 == argv[i])
101
0
      lastargv = argv[i] + strlen(argv[i]);
102
0
  }
103
0
  for (i = 0; envp[i] != NULL; i++) {
104
0
    if (lastargv + 1 == envp[i])
105
0
      lastargv = envp[i] + strlen(envp[i]);
106
0
  }
107
108
0
  argv[1] = NULL;
109
0
  argv_start = argv[0];
110
0
  argv_env_len = lastargv - argv[0] - 1;
111
112
  /*
113
   * Copy environment
114
   * XXX - will truncate env on strdup fail
115
   */
116
0
  for (i = 0; envp[i] != NULL; i++)
117
0
    environ[i] = strdup(envp[i]);
118
0
  environ[i] = NULL;
119
0
#endif /* SPT_REUSEARGV */
120
0
}
121
122
#ifndef HAVE_SETPROCTITLE
123
void
124
setproctitle(const char *fmt, ...)
125
0
{
126
0
#if SPT_TYPE != SPT_NONE
127
0
  va_list ap;
128
0
  char buf[1024], ptitle[1024];
129
0
  size_t len = 0;
130
0
  int r;
131
0
  extern char *__progname;
132
#if SPT_TYPE == SPT_PSTAT
133
  union pstun pst;
134
#endif
135
136
0
#if SPT_TYPE == SPT_REUSEARGV
137
0
  if (argv_env_len <= 0)
138
0
    return;
139
0
#endif
140
141
0
  strlcpy(buf, __progname, sizeof(buf));
142
143
0
  r = -1;
144
0
  va_start(ap, fmt);
145
0
  if (fmt != NULL) {
146
0
    len = strlcat(buf, ": ", sizeof(buf));
147
0
    if (len < sizeof(buf))
148
0
      r = vsnprintf(buf + len, sizeof(buf) - len , fmt, ap);
149
0
  }
150
0
  va_end(ap);
151
0
  if (r == -1 || (size_t)r >= sizeof(buf) - len)
152
0
    return;
153
0
  strnvis(ptitle, buf, sizeof(ptitle),
154
0
      VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL);
155
156
#if SPT_TYPE == SPT_PSTAT
157
  pst.pst_command = ptitle;
158
  pstat(PSTAT_SETCMD, pst, strlen(ptitle), 0, 0);
159
#elif SPT_TYPE == SPT_REUSEARGV
160
/*  debug("setproctitle: copy \"%s\" into len %d",
161
      buf, argv_env_len); */
162
0
  len = strlcpy(argv_start, ptitle, argv_env_len);
163
0
  for(; len < argv_env_len; len++)
164
0
    argv_start[len] = SPT_PADCHAR;
165
0
#endif
166
167
0
#endif /* SPT_NONE */
168
0
}
169
170
#endif /* HAVE_SETPROCTITLE */
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strlcat.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strlcat.c.html index 2061b76be..f1bf3a133 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strlcat.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strlcat.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/strlcat.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $  */
2
3
/*
4
 * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
/* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */
20
21
#include "openbsd-compat.h"
22
23
#if !defined(HAVE_STRLCAT)
24
25
#include <sys/types.h>
26
#include <string.h>
27
28
/*
29
 * Appends src to string dst of size dsize (unlike strncat, dsize is the
30
 * full size of dst, not space left).  At most dsize-1 characters
31
 * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
32
 * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
33
 * If retval >= dsize, truncation occurred.
34
 */
35
size_t
36
strlcat(char *dst, const char *src, size_t dsize)
37
0
{
38
0
  const char *odst = dst;
39
0
  const char *osrc = src;
40
0
  size_t n = dsize;
41
0
  size_t dlen;
42
43
  /* Find the end of dst and adjust bytes left but don't go past end. */
44
0
  while (n-- != 0 && *dst != '\0')
45
0
    dst++;
46
0
  dlen = dst - odst;
47
0
  n = dsize - dlen;
48
49
0
  if (n-- == 0)
50
0
    return(dlen + strlen(src));
51
0
  while (*src != '\0') {
52
0
    if (n != 0) {
53
0
      *dst++ = *src;
54
0
      n--;
55
0
    }
56
0
    src++;
57
0
  }
58
0
  *dst = '\0';
59
60
0
  return(dlen + (src - osrc));  /* count does not include NUL */
61
0
}
62
63
#endif /* !defined(HAVE_STRLCAT) */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/strlcat.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $  */
2
3
/*
4
 * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
/* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */
20
21
#include "openbsd-compat.h"
22
23
#if !defined(HAVE_STRLCAT)
24
25
#include <sys/types.h>
26
#include <string.h>
27
28
/*
29
 * Appends src to string dst of size dsize (unlike strncat, dsize is the
30
 * full size of dst, not space left).  At most dsize-1 characters
31
 * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
32
 * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
33
 * If retval >= dsize, truncation occurred.
34
 */
35
size_t
36
strlcat(char *dst, const char *src, size_t dsize)
37
0
{
38
0
  const char *odst = dst;
39
0
  const char *osrc = src;
40
0
  size_t n = dsize;
41
0
  size_t dlen;
42
43
  /* Find the end of dst and adjust bytes left but don't go past end. */
44
0
  while (n-- != 0 && *dst != '\0')
45
0
    dst++;
46
0
  dlen = dst - odst;
47
0
  n = dsize - dlen;
48
49
0
  if (n-- == 0)
50
0
    return(dlen + strlen(src));
51
0
  while (*src != '\0') {
52
0
    if (n != 0) {
53
0
      *dst++ = *src;
54
0
      n--;
55
0
    }
56
0
    src++;
57
0
  }
58
0
  *dst = '\0';
59
60
0
  return(dlen + (src - osrc));  /* count does not include NUL */
61
0
}
62
63
#endif /* !defined(HAVE_STRLCAT) */
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strlcpy.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strlcpy.c.html index 00cf1d42d..3d13d855a 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strlcpy.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strlcpy.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/strlcpy.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $  */
2
3
/*
4
 * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <string.h>
21
22
/*
23
 * Copy string src to buffer dst of size dsize.  At most dsize-1
24
 * chars will be copied.  Always NUL terminates (unless dsize == 0).
25
 * Returns strlen(src); if retval >= dsize, truncation occurred.
26
 */
27
size_t
28
strlcpy(char *dst, const char *src, size_t dsize)
29
577k
{
30
577k
  const char *osrc = src;
31
577k
  size_t nleft = dsize;
32
33
  /* Copy as many bytes as will fit. */
34
577k
  if (nleft != 0) {
35
4.46M
    while (--nleft != 0) {
36
4.45M
      if ((*dst++ = *src++) == '\0')
37
576k
        break;
38
4.45M
    }
39
577k
  }
40
41
  /* Not enough room in dst, add NUL and traverse rest of src. */
42
577k
  if (nleft == 0) {
43
1.45k
    if (dsize != 0)
44
1.45k
      *dst = '\0';   /* NUL-terminate dst */
45
1.45k
    while (*src++)
46
0
      ;
47
1.45k
  }
48
49
577k
  return(src - osrc - 1); /* count does not include NUL */
50
577k
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/strlcpy.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $  */
2
3
/*
4
 * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <string.h>
21
22
/*
23
 * Copy string src to buffer dst of size dsize.  At most dsize-1
24
 * chars will be copied.  Always NUL terminates (unless dsize == 0).
25
 * Returns strlen(src); if retval >= dsize, truncation occurred.
26
 */
27
size_t
28
strlcpy(char *dst, const char *src, size_t dsize)
29
577k
{
30
577k
  const char *osrc = src;
31
577k
  size_t nleft = dsize;
32
33
  /* Copy as many bytes as will fit. */
34
577k
  if (nleft != 0) {
35
4.46M
    while (--nleft != 0) {
36
4.45M
      if ((*dst++ = *src++) == '\0')
37
576k
        break;
38
4.45M
    }
39
577k
  }
40
41
  /* Not enough room in dst, add NUL and traverse rest of src. */
42
577k
  if (nleft == 0) {
43
1.45k
    if (dsize != 0)
44
1.45k
      *dst = '\0';   /* NUL-terminate dst */
45
1.45k
    while (*src++)
46
0
      ;
47
1.45k
  }
48
49
577k
  return(src - osrc - 1); /* count does not include NUL */
50
577k
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strtonum.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strtonum.c.html index b7be42a38..ef4d69f03 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strtonum.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/strtonum.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/strtonum.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther Exp $ */
2
3
/*
4
 * Copyright (c) 2004 Ted Unangst and Todd Miller
5
 * All rights reserved.
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <errno.h>
21
#include <limits.h>
22
#include <stdlib.h>
23
24
0
#define INVALID   1
25
0
#define TOOSMALL  2
26
0
#define TOOLARGE  3
27
28
long long
29
strtonum(const char *numstr, long long minval, long long maxval,
30
    const char **errstrp)
31
0
{
32
0
  long long ll = 0;
33
0
  int error = 0;
34
0
  char *ep;
35
0
  struct errval {
36
0
    const char *errstr;
37
0
    int err;
38
0
  } ev[4] = {
39
0
    { NULL,   0 },
40
0
    { "invalid",  EINVAL },
41
0
    { "too small",  ERANGE },
42
0
    { "too large",  ERANGE },
43
0
  };
44
45
0
  ev[0].err = errno;
46
0
  errno = 0;
47
0
  if (minval > maxval) {
48
0
    error = INVALID;
49
0
  } else {
50
0
    ll = strtoll(numstr, &ep, 10);
51
0
    if (numstr == ep || *ep != '\0')
52
0
      error = INVALID;
53
0
    else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
54
0
      error = TOOSMALL;
55
0
    else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
56
0
      error = TOOLARGE;
57
0
  }
58
0
  if (errstrp != NULL)
59
0
    *errstrp = ev[error].errstr;
60
0
  errno = ev[error].err;
61
0
  if (error)
62
0
    ll = 0;
63
64
0
  return (ll);
65
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/strtonum.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther Exp $ */
2
3
/*
4
 * Copyright (c) 2004 Ted Unangst and Todd Miller
5
 * All rights reserved.
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <errno.h>
21
#include <limits.h>
22
#include <stdlib.h>
23
24
0
#define INVALID   1
25
0
#define TOOSMALL  2
26
0
#define TOOLARGE  3
27
28
long long
29
strtonum(const char *numstr, long long minval, long long maxval,
30
    const char **errstrp)
31
0
{
32
0
  long long ll = 0;
33
0
  int error = 0;
34
0
  char *ep;
35
0
  struct errval {
36
0
    const char *errstr;
37
0
    int err;
38
0
  } ev[4] = {
39
0
    { NULL,   0 },
40
0
    { "invalid",  EINVAL },
41
0
    { "too small",  ERANGE },
42
0
    { "too large",  ERANGE },
43
0
  };
44
45
0
  ev[0].err = errno;
46
0
  errno = 0;
47
0
  if (minval > maxval) {
48
0
    error = INVALID;
49
0
  } else {
50
0
    ll = strtoll(numstr, &ep, 10);
51
0
    if (numstr == ep || *ep != '\0')
52
0
      error = INVALID;
53
0
    else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
54
0
      error = TOOSMALL;
55
0
    else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
56
0
      error = TOOLARGE;
57
0
  }
58
0
  if (errstrp != NULL)
59
0
    *errstrp = ev[error].errstr;
60
0
  errno = ev[error].err;
61
0
  if (error)
62
0
    ll = 0;
63
64
0
  return (ll);
65
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/sys/queue.h.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/sys/queue.h.html index 7ec06dfbe..f25f3070e 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/sys/queue.h.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/sys/queue.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/sys/queue.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: queue.h,v 1.46 2020/12/30 13:33:12 millert Exp $  */
2
/*  $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
3
4
/*
5
 * Copyright (c) 1991, 1993
6
 *  The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 *
32
 *  @(#)queue.h 8.5 (Berkeley) 8/20/94
33
 */
34
35
#ifndef _SYS_QUEUE_H_
36
#define _SYS_QUEUE_H_
37
38
#include <sys/_null.h>
39
40
/*
41
 * This file defines five types of data structures: singly-linked lists,
42
 * lists, simple queues, tail queues and XOR simple queues.
43
 *
44
 *
45
 * A singly-linked list is headed by a single forward pointer. The elements
46
 * are singly linked for minimum space and pointer manipulation overhead at
47
 * the expense of O(n) removal for arbitrary elements. New elements can be
48
 * added to the list after an existing element or at the head of the list.
49
 * Elements being removed from the head of the list should use the explicit
50
 * macro for this purpose for optimum efficiency. A singly-linked list may
51
 * only be traversed in the forward direction.  Singly-linked lists are ideal
52
 * for applications with large datasets and few or no removals or for
53
 * implementing a LIFO queue.
54
 *
55
 * A list is headed by a single forward pointer (or an array of forward
56
 * pointers for a hash table header). The elements are doubly linked
57
 * so that an arbitrary element can be removed without a need to
58
 * traverse the list. New elements can be added to the list before
59
 * or after an existing element or at the head of the list. A list
60
 * may only be traversed in the forward direction.
61
 *
62
 * A simple queue is headed by a pair of pointers, one to the head of the
63
 * list and the other to the tail of the list. The elements are singly
64
 * linked to save space, so elements can only be removed from the
65
 * head of the list. New elements can be added to the list before or after
66
 * an existing element, at the head of the list, or at the end of the
67
 * list. A simple queue may only be traversed in the forward direction.
68
 *
69
 * A tail queue is headed by a pair of pointers, one to the head of the
70
 * list and the other to the tail of the list. The elements are doubly
71
 * linked so that an arbitrary element can be removed without a need to
72
 * traverse the list. New elements can be added to the list before or
73
 * after an existing element, at the head of the list, or at the end of
74
 * the list. A tail queue may be traversed in either direction.
75
 *
76
 * An XOR simple queue is used in the same way as a regular simple queue.
77
 * The difference is that the head structure also includes a "cookie" that
78
 * is XOR'd with the queue pointer (first, last or next) to generate the
79
 * real pointer value.
80
 *
81
 * For details on the use of these macros, see the queue(3) manual page.
82
 */
83
84
#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
85
#define _Q_INVALID ((void *)-1)
86
#define _Q_INVALIDATE(a) (a) = _Q_INVALID
87
#else
88
#define _Q_INVALIDATE(a)
89
#endif
90
91
/*
92
 * Singly-linked List definitions.
93
 */
94
#define SLIST_HEAD(name, type)            \
95
struct name {               \
96
  struct type *slh_first; /* first element */     \
97
}
98
99
#define SLIST_HEAD_INITIALIZER(head)          \
100
  { NULL }
101
102
#define SLIST_ENTRY(type)           \
103
struct {                \
104
  struct type *sle_next;  /* next element */      \
105
}
106
107
/*
108
 * Singly-linked List access methods.
109
 */
110
#define SLIST_FIRST(head) ((head)->slh_first)
111
#define SLIST_END(head)   NULL
112
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
113
#define SLIST_NEXT(elm, field)  ((elm)->field.sle_next)
114
115
#define SLIST_FOREACH(var, head, field)         \
116
  for((var) = SLIST_FIRST(head);          \
117
      (var) != SLIST_END(head);         \
118
      (var) = SLIST_NEXT(var, field))
119
120
#define SLIST_FOREACH_SAFE(var, head, field, tvar)      \
121
  for ((var) = SLIST_FIRST(head);       \
122
      (var) && ((tvar) = SLIST_NEXT(var, field), 1);    \
123
      (var) = (tvar))
124
125
/*
126
 * Singly-linked List functions.
127
 */
128
#define SLIST_INIT(head) {            \
129
  SLIST_FIRST(head) = SLIST_END(head);        \
130
}
131
132
#define SLIST_INSERT_AFTER(slistelm, elm, field) do {     \
133
  (elm)->field.sle_next = (slistelm)->field.sle_next;   \
134
  (slistelm)->field.sle_next = (elm);       \
135
} while (0)
136
137
#define SLIST_INSERT_HEAD(head, elm, field) do {      \
138
  (elm)->field.sle_next = (head)->slh_first;      \
139
  (head)->slh_first = (elm);          \
140
} while (0)
141
142
#define SLIST_REMOVE_AFTER(elm, field) do {       \
143
  (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
144
} while (0)
145
146
#define SLIST_REMOVE_HEAD(head, field) do {       \
147
  (head)->slh_first = (head)->slh_first->field.sle_next;    \
148
} while (0)
149
150
#define SLIST_REMOVE(head, elm, type, field) do {     \
151
  if ((head)->slh_first == (elm)) {       \
152
    SLIST_REMOVE_HEAD((head), field);     \
153
  } else {              \
154
    struct type *curelm = (head)->slh_first;    \
155
                  \
156
    while (curelm->field.sle_next != (elm))     \
157
      curelm = curelm->field.sle_next;    \
158
    curelm->field.sle_next =        \
159
        curelm->field.sle_next->field.sle_next;   \
160
  }               \
161
  _Q_INVALIDATE((elm)->field.sle_next);       \
162
} while (0)
163
164
/*
165
 * List definitions.
166
 */
167
#define LIST_HEAD(name, type)           \
168
struct name {               \
169
  struct type *lh_first;  /* first element */     \
170
}
171
172
#define LIST_HEAD_INITIALIZER(head)         \
173
  { NULL }
174
175
#define LIST_ENTRY(type)            \
176
struct {                \
177
  struct type *le_next; /* next element */      \
178
  struct type **le_prev;  /* address of previous next element */  \
179
}
180
181
/*
182
 * List access methods.
183
 */
184
#define LIST_FIRST(head)    ((head)->lh_first)
185
#define LIST_END(head)      NULL
186
#define LIST_EMPTY(head)    (LIST_FIRST(head) == LIST_END(head))
187
#define LIST_NEXT(elm, field)   ((elm)->field.le_next)
188
189
#define LIST_FOREACH(var, head, field)          \
190
  for((var) = LIST_FIRST(head);         \
191
      (var)!= LIST_END(head);         \
192
      (var) = LIST_NEXT(var, field))
193
194
#define LIST_FOREACH_SAFE(var, head, field, tvar)     \
195
  for ((var) = LIST_FIRST(head);        \
196
      (var) && ((tvar) = LIST_NEXT(var, field), 1);   \
197
      (var) = (tvar))
198
199
/*
200
 * List functions.
201
 */
202
#define LIST_INIT(head) do {            \
203
  LIST_FIRST(head) = LIST_END(head);        \
204
} while (0)
205
206
#define LIST_INSERT_AFTER(listelm, elm, field) do {     \
207
  if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
208
    (listelm)->field.le_next->field.le_prev =   \
209
        &(elm)->field.le_next;        \
210
  (listelm)->field.le_next = (elm);       \
211
  (elm)->field.le_prev = &(listelm)->field.le_next;   \
212
} while (0)
213
214
#define LIST_INSERT_BEFORE(listelm, elm, field) do {      \
215
  (elm)->field.le_prev = (listelm)->field.le_prev;    \
216
  (elm)->field.le_next = (listelm);       \
217
  *(listelm)->field.le_prev = (elm);        \
218
  (listelm)->field.le_prev = &(elm)->field.le_next;   \
219
} while (0)
220
221
#define LIST_INSERT_HEAD(head, elm, field) do {       \
222
  if (((elm)->field.le_next = (head)->lh_first) != NULL)    \
223
    (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
224
  (head)->lh_first = (elm);         \
225
  (elm)->field.le_prev = &(head)->lh_first;     \
226
} while (0)
227
228
#define LIST_REMOVE(elm, field) do {          \
229
  if ((elm)->field.le_next != NULL)       \
230
    (elm)->field.le_next->field.le_prev =     \
231
        (elm)->field.le_prev;       \
232
  *(elm)->field.le_prev = (elm)->field.le_next;     \
233
  _Q_INVALIDATE((elm)->field.le_prev);        \
234
  _Q_INVALIDATE((elm)->field.le_next);        \
235
} while (0)
236
237
#define LIST_REPLACE(elm, elm2, field) do {       \
238
  if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
239
    (elm2)->field.le_next->field.le_prev =      \
240
        &(elm2)->field.le_next;       \
241
  (elm2)->field.le_prev = (elm)->field.le_prev;     \
242
  *(elm2)->field.le_prev = (elm2);        \
243
  _Q_INVALIDATE((elm)->field.le_prev);        \
244
  _Q_INVALIDATE((elm)->field.le_next);        \
245
} while (0)
246
247
/*
248
 * Simple queue definitions.
249
 */
250
#define SIMPLEQ_HEAD(name, type)          \
251
struct name {               \
252
  struct type *sqh_first; /* first element */     \
253
  struct type **sqh_last; /* addr of last next element */   \
254
}
255
256
#define SIMPLEQ_HEAD_INITIALIZER(head)          \
257
  { NULL, &(head).sqh_first }
258
259
#define SIMPLEQ_ENTRY(type)           \
260
struct {                \
261
  struct type *sqe_next;  /* next element */      \
262
}
263
264
/*
265
 * Simple queue access methods.
266
 */
267
16.5k
#define SIMPLEQ_FIRST(head)     ((head)->sqh_first)
268
#define SIMPLEQ_END(head)     NULL
269
#define SIMPLEQ_EMPTY(head)     (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
270
#define SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
271
272
#define SIMPLEQ_FOREACH(var, head, field)       \
273
  for((var) = SIMPLEQ_FIRST(head);        \
274
      (var) != SIMPLEQ_END(head);         \
275
      (var) = SIMPLEQ_NEXT(var, field))
276
277
#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar)      \
278
  for ((var) = SIMPLEQ_FIRST(head);       \
279
      (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1);    \
280
      (var) = (tvar))
281
282
/*
283
 * Simple queue functions.
284
 */
285
15.4k
#define SIMPLEQ_INIT(head) do {           \
286
15.4k
  (head)->sqh_first = NULL;         \
287
15.4k
  (head)->sqh_last = &(head)->sqh_first;        \
288
15.4k
} while (0)
289
290
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do {      \
291
  if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)  \
292
    (head)->sqh_last = &(elm)->field.sqe_next;    \
293
  (head)->sqh_first = (elm);          \
294
} while (0)
295
296
1.04k
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do {     \
297
1.04k
  (elm)->field.sqe_next = NULL;         \
298
1.04k
  *(head)->sqh_last = (elm);          \
299
1.04k
  (head)->sqh_last = &(elm)->field.sqe_next;      \
300
1.04k
} while (0)
301
302
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {    \
303
  if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
304
    (head)->sqh_last = &(elm)->field.sqe_next;    \
305
  (listelm)->field.sqe_next = (elm);        \
306
} while (0)
307
308
1.04k
#define SIMPLEQ_REMOVE_HEAD(head, field) do {     \
309
1.04k
  if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
310
1.04k
    (head)->sqh_last = &(head)->sqh_first;     \
311
1.04k
} while (0)
312
313
#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do {     \
314
  if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
315
      == NULL)              \
316
    (head)->sqh_last = &(elm)->field.sqe_next;    \
317
} while (0)
318
319
#define SIMPLEQ_CONCAT(head1, head2) do {       \
320
  if (!SIMPLEQ_EMPTY((head2))) {          \
321
    *(head1)->sqh_last = (head2)->sqh_first;    \
322
    (head1)->sqh_last = (head2)->sqh_last;      \
323
    SIMPLEQ_INIT((head2));          \
324
  }               \
325
} while (0)
326
327
/*
328
 * XOR Simple queue definitions.
329
 */
330
#define XSIMPLEQ_HEAD(name, type)         \
331
struct name {               \
332
  struct type *sqx_first; /* first element */     \
333
  struct type **sqx_last; /* addr of last next element */   \
334
  unsigned long sqx_cookie;         \
335
}
336
337
#define XSIMPLEQ_ENTRY(type)            \
338
struct {                \
339
  struct type *sqx_next;  /* next element */      \
340
}
341
342
/*
343
 * XOR Simple queue access methods.
344
 */
345
#define XSIMPLEQ_XOR(head, ptr)     ((__typeof(ptr))((head)->sqx_cookie ^ \
346
          (unsigned long)(ptr)))
347
#define XSIMPLEQ_FIRST(head)      XSIMPLEQ_XOR(head, ((head)->sqx_first))
348
#define XSIMPLEQ_END(head)      NULL
349
#define XSIMPLEQ_EMPTY(head)      (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
350
#define XSIMPLEQ_NEXT(head, elm, field)    XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
351
352
353
#define XSIMPLEQ_FOREACH(var, head, field)        \
354
  for ((var) = XSIMPLEQ_FIRST(head);        \
355
      (var) != XSIMPLEQ_END(head);        \
356
      (var) = XSIMPLEQ_NEXT(head, var, field))
357
358
#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar)     \
359
  for ((var) = XSIMPLEQ_FIRST(head);        \
360
      (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
361
      (var) = (tvar))
362
363
/*
364
 * XOR Simple queue functions.
365
 */
366
#define XSIMPLEQ_INIT(head) do {          \
367
  arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
368
  (head)->sqx_first = XSIMPLEQ_XOR(head, NULL);     \
369
  (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first);  \
370
} while (0)
371
372
#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do {     \
373
  if (((elm)->field.sqx_next = (head)->sqx_first) ==    \
374
      XSIMPLEQ_XOR(head, NULL))         \
375
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
376
  (head)->sqx_first = XSIMPLEQ_XOR(head, (elm));      \
377
} while (0)
378
379
#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do {     \
380
  (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL);   \
381
  *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
382
  (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next);  \
383
} while (0)
384
385
#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {   \
386
  if (((elm)->field.sqx_next = (listelm)->field.sqx_next) ==  \
387
      XSIMPLEQ_XOR(head, NULL))         \
388
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
389
  (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm));    \
390
} while (0)
391
392
#define XSIMPLEQ_REMOVE_HEAD(head, field) do {        \
393
  if (((head)->sqx_first = XSIMPLEQ_XOR(head,     \
394
      (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
395
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
396
} while (0)
397
398
#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do {      \
399
  if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head,     \
400
      (elm)->field.sqx_next)->field.sqx_next)     \
401
      == XSIMPLEQ_XOR(head, NULL))        \
402
    (head)->sqx_last =          \
403
        XSIMPLEQ_XOR(head, &(elm)->field.sqx_next);   \
404
} while (0)
405
406
407
/*
408
 * Tail queue definitions.
409
 */
410
#define TAILQ_HEAD(name, type)            \
411
struct name {               \
412
  struct type *tqh_first; /* first element */     \
413
  struct type **tqh_last; /* addr of last next element */   \
414
}
415
416
#define TAILQ_HEAD_INITIALIZER(head)          \
417
  { NULL, &(head).tqh_first }
418
419
#define TAILQ_ENTRY(type)           \
420
struct {                \
421
  struct type *tqe_next;  /* next element */      \
422
  struct type **tqe_prev; /* address of previous next element */  \
423
}
424
425
/*
426
 * Tail queue access methods.
427
 */
428
15.4k
#define TAILQ_FIRST(head)   ((head)->tqh_first)
429
30.9k
#define TAILQ_END(head)     NULL
430
0
#define TAILQ_NEXT(elm, field)    ((elm)->field.tqe_next)
431
#define TAILQ_LAST(head, headname)          \
432
  (*(((struct headname *)((head)->tqh_last))->tqh_last))
433
/* XXX */
434
#define TAILQ_PREV(elm, headname, field)        \
435
  (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
436
#define TAILQ_EMPTY(head)           \
437
  (TAILQ_FIRST(head) == TAILQ_END(head))
438
439
#define TAILQ_FOREACH(var, head, field)         \
440
0
  for((var) = TAILQ_FIRST(head);         \
441
0
      (var) != TAILQ_END(head);         \
442
0
      (var) = TAILQ_NEXT(var, field))
443
444
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)      \
445
15.4k
  for ((var) = TAILQ_FIRST(head);         \
446
15.4k
      (var) != TAILQ_END(head) &&         \
447
15.4k
      ((tvar) = TAILQ_NEXT(var, field), 1);     \
448
15.4k
      (var) = (tvar))
449
450
451
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)   \
452
  for((var) = TAILQ_LAST(head, headname);       \
453
      (var) != TAILQ_END(head);         \
454
      (var) = TAILQ_PREV(var, headname, field))
455
456
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)  \
457
  for ((var) = TAILQ_LAST(head, headname);      \
458
      (var) != TAILQ_END(head) &&         \
459
      ((tvar) = TAILQ_PREV(var, headname, field), 1);   \
460
      (var) = (tvar))
461
462
/*
463
 * Tail queue functions.
464
 */
465
15.4k
#define TAILQ_INIT(head) do {           \
466
15.4k
  (head)->tqh_first = NULL;         \
467
15.4k
  (head)->tqh_last = &(head)->tqh_first;        \
468
15.4k
} while (0)
469
470
#define TAILQ_INSERT_HEAD(head, elm, field) do {      \
471
  if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)  \
472
    (head)->tqh_first->field.tqe_prev =     \
473
        &(elm)->field.tqe_next;       \
474
  else                \
475
    (head)->tqh_last = &(elm)->field.tqe_next;    \
476
  (head)->tqh_first = (elm);          \
477
  (elm)->field.tqe_prev = &(head)->tqh_first;     \
478
} while (0)
479
480
0
#define TAILQ_INSERT_TAIL(head, elm, field) do {     \
481
0
  (elm)->field.tqe_next = NULL;         \
482
0
  (elm)->field.tqe_prev = (head)->tqh_last;     \
483
0
  *(head)->tqh_last = (elm);          \
484
0
  (head)->tqh_last = &(elm)->field.tqe_next;      \
485
0
} while (0)
486
487
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {    \
488
  if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
489
    (elm)->field.tqe_next->field.tqe_prev =     \
490
        &(elm)->field.tqe_next;       \
491
  else                \
492
    (head)->tqh_last = &(elm)->field.tqe_next;    \
493
  (listelm)->field.tqe_next = (elm);        \
494
  (elm)->field.tqe_prev = &(listelm)->field.tqe_next;   \
495
} while (0)
496
497
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {     \
498
  (elm)->field.tqe_prev = (listelm)->field.tqe_prev;    \
499
  (elm)->field.tqe_next = (listelm);        \
500
  *(listelm)->field.tqe_prev = (elm);       \
501
  (listelm)->field.tqe_prev = &(elm)->field.tqe_next;   \
502
} while (0)
503
504
0
#define TAILQ_REMOVE(head, elm, field) do {       \
505
0
  if (((elm)->field.tqe_next) != NULL)       \
506
0
    (elm)->field.tqe_next->field.tqe_prev =     \
507
0
        (elm)->field.tqe_prev;       \
508
0
  else                \
509
0
    (head)->tqh_last = (elm)->field.tqe_prev;   \
510
0
  *(elm)->field.tqe_prev = (elm)->field.tqe_next;     \
511
0
  _Q_INVALIDATE((elm)->field.tqe_prev);       \
512
0
  _Q_INVALIDATE((elm)->field.tqe_next);       \
513
0
} while (0)
514
515
#define TAILQ_REPLACE(head, elm, elm2, field) do {      \
516
  if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
517
    (elm2)->field.tqe_next->field.tqe_prev =    \
518
        &(elm2)->field.tqe_next;        \
519
  else                \
520
    (head)->tqh_last = &(elm2)->field.tqe_next;   \
521
  (elm2)->field.tqe_prev = (elm)->field.tqe_prev;     \
522
  *(elm2)->field.tqe_prev = (elm2);       \
523
  _Q_INVALIDATE((elm)->field.tqe_prev);       \
524
  _Q_INVALIDATE((elm)->field.tqe_next);       \
525
} while (0)
526
527
#define TAILQ_CONCAT(head1, head2, field) do {        \
528
  if (!TAILQ_EMPTY(head2)) {          \
529
    *(head1)->tqh_last = (head2)->tqh_first;    \
530
    (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
531
    (head1)->tqh_last = (head2)->tqh_last;      \
532
    TAILQ_INIT((head2));          \
533
  }               \
534
} while (0)
535
536
/*
537
 * Singly-linked Tail queue declarations.
538
 */
539
#define STAILQ_HEAD(name, type)           \
540
struct name {               \
541
  struct type *stqh_first;  /* first element */   \
542
  struct type **stqh_last;  /* addr of last next element */ \
543
}
544
545
#define STAILQ_HEAD_INITIALIZER(head)         \
546
  { NULL, &(head).stqh_first }
547
548
#define STAILQ_ENTRY(type)            \
549
struct {                \
550
  struct type *stqe_next; /* next element */      \
551
}
552
553
/*
554
 * Singly-linked Tail queue access methods.
555
 */
556
#define STAILQ_FIRST(head)  ((head)->stqh_first)
557
#define STAILQ_END(head)  NULL
558
#define STAILQ_EMPTY(head)  (STAILQ_FIRST(head) == STAILQ_END(head))
559
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
560
561
#define STAILQ_FOREACH(var, head, field)        \
562
  for ((var) = STAILQ_FIRST(head);        \
563
      (var) != STAILQ_END(head);          \
564
      (var) = STAILQ_NEXT(var, field))
565
566
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)     \
567
  for ((var) = STAILQ_FIRST(head);        \
568
      (var) && ((tvar) = STAILQ_NEXT(var, field), 1);   \
569
      (var) = (tvar))
570
571
/*
572
 * Singly-linked Tail queue functions.
573
 */
574
#define STAILQ_INIT(head) do {            \
575
  STAILQ_FIRST((head)) = NULL;          \
576
  (head)->stqh_last = &STAILQ_FIRST((head));      \
577
} while (0)
578
579
#define STAILQ_INSERT_HEAD(head, elm, field) do {     \
580
  if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
581
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
582
  STAILQ_FIRST((head)) = (elm);         \
583
} while (0)
584
585
#define STAILQ_INSERT_TAIL(head, elm, field) do {     \
586
  STAILQ_NEXT((elm), field) = NULL;       \
587
  *(head)->stqh_last = (elm);         \
588
  (head)->stqh_last = &STAILQ_NEXT((elm), field);     \
589
} while (0)
590
591
#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do {   \
592
  if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((elm), field)) == NULL)\
593
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
594
  STAILQ_NEXT((elm), field) = (elm);        \
595
} while (0)
596
597
#define STAILQ_REMOVE_HEAD(head, field) do {                            \
598
  if ((STAILQ_FIRST((head)) =         \
599
      STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)    \
600
    (head)->stqh_last = &STAILQ_FIRST((head));    \
601
} while (0)
602
603
#define STAILQ_REMOVE_AFTER(head, elm, field) do {                      \
604
  if ((STAILQ_NEXT(elm, field) =          \
605
      STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
606
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
607
} while (0)
608
609
#define STAILQ_REMOVE(head, elm, type, field) do {      \
610
  if (STAILQ_FIRST((head)) == (elm)) {        \
611
    STAILQ_REMOVE_HEAD((head), field);      \
612
  } else {              \
613
    struct type *curelm = (head)->stqh_first;   \
614
    while (STAILQ_NEXT(curelm, field) != (elm))   \
615
      curelm = STAILQ_NEXT(curelm, field);    \
616
    STAILQ_REMOVE_AFTER(head, curelm, field);   \
617
  }               \
618
} while (0)
619
620
#define STAILQ_CONCAT(head1, head2) do {        \
621
  if (!STAILQ_EMPTY((head2))) {         \
622
    *(head1)->stqh_last = (head2)->stqh_first;    \
623
    (head1)->stqh_last = (head2)->stqh_last;    \
624
    STAILQ_INIT((head2));         \
625
  }               \
626
} while (0)
627
628
#define STAILQ_LAST(head, type, field)          \
629
  (STAILQ_EMPTY((head)) ? NULL :          \
630
          ((struct type *)(void *)        \
631
    ((char *)((head)->stqh_last) - offsetof(struct type, field))))
632
633
#endif  /* !_SYS_QUEUE_H_ */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/sys/queue.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: queue.h,v 1.46 2020/12/30 13:33:12 millert Exp $  */
2
/*  $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
3
4
/*
5
 * Copyright (c) 1991, 1993
6
 *  The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 *
32
 *  @(#)queue.h 8.5 (Berkeley) 8/20/94
33
 */
34
35
#ifndef _SYS_QUEUE_H_
36
#define _SYS_QUEUE_H_
37
38
#include <sys/_null.h>
39
40
/*
41
 * This file defines five types of data structures: singly-linked lists,
42
 * lists, simple queues, tail queues and XOR simple queues.
43
 *
44
 *
45
 * A singly-linked list is headed by a single forward pointer. The elements
46
 * are singly linked for minimum space and pointer manipulation overhead at
47
 * the expense of O(n) removal for arbitrary elements. New elements can be
48
 * added to the list after an existing element or at the head of the list.
49
 * Elements being removed from the head of the list should use the explicit
50
 * macro for this purpose for optimum efficiency. A singly-linked list may
51
 * only be traversed in the forward direction.  Singly-linked lists are ideal
52
 * for applications with large datasets and few or no removals or for
53
 * implementing a LIFO queue.
54
 *
55
 * A list is headed by a single forward pointer (or an array of forward
56
 * pointers for a hash table header). The elements are doubly linked
57
 * so that an arbitrary element can be removed without a need to
58
 * traverse the list. New elements can be added to the list before
59
 * or after an existing element or at the head of the list. A list
60
 * may only be traversed in the forward direction.
61
 *
62
 * A simple queue is headed by a pair of pointers, one to the head of the
63
 * list and the other to the tail of the list. The elements are singly
64
 * linked to save space, so elements can only be removed from the
65
 * head of the list. New elements can be added to the list before or after
66
 * an existing element, at the head of the list, or at the end of the
67
 * list. A simple queue may only be traversed in the forward direction.
68
 *
69
 * A tail queue is headed by a pair of pointers, one to the head of the
70
 * list and the other to the tail of the list. The elements are doubly
71
 * linked so that an arbitrary element can be removed without a need to
72
 * traverse the list. New elements can be added to the list before or
73
 * after an existing element, at the head of the list, or at the end of
74
 * the list. A tail queue may be traversed in either direction.
75
 *
76
 * An XOR simple queue is used in the same way as a regular simple queue.
77
 * The difference is that the head structure also includes a "cookie" that
78
 * is XOR'd with the queue pointer (first, last or next) to generate the
79
 * real pointer value.
80
 *
81
 * For details on the use of these macros, see the queue(3) manual page.
82
 */
83
84
#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
85
#define _Q_INVALID ((void *)-1)
86
#define _Q_INVALIDATE(a) (a) = _Q_INVALID
87
#else
88
#define _Q_INVALIDATE(a)
89
#endif
90
91
/*
92
 * Singly-linked List definitions.
93
 */
94
#define SLIST_HEAD(name, type)            \
95
struct name {               \
96
  struct type *slh_first; /* first element */     \
97
}
98
99
#define SLIST_HEAD_INITIALIZER(head)          \
100
  { NULL }
101
102
#define SLIST_ENTRY(type)           \
103
struct {                \
104
  struct type *sle_next;  /* next element */      \
105
}
106
107
/*
108
 * Singly-linked List access methods.
109
 */
110
#define SLIST_FIRST(head) ((head)->slh_first)
111
#define SLIST_END(head)   NULL
112
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
113
#define SLIST_NEXT(elm, field)  ((elm)->field.sle_next)
114
115
#define SLIST_FOREACH(var, head, field)         \
116
  for((var) = SLIST_FIRST(head);          \
117
      (var) != SLIST_END(head);         \
118
      (var) = SLIST_NEXT(var, field))
119
120
#define SLIST_FOREACH_SAFE(var, head, field, tvar)      \
121
  for ((var) = SLIST_FIRST(head);       \
122
      (var) && ((tvar) = SLIST_NEXT(var, field), 1);    \
123
      (var) = (tvar))
124
125
/*
126
 * Singly-linked List functions.
127
 */
128
#define SLIST_INIT(head) {            \
129
  SLIST_FIRST(head) = SLIST_END(head);        \
130
}
131
132
#define SLIST_INSERT_AFTER(slistelm, elm, field) do {     \
133
  (elm)->field.sle_next = (slistelm)->field.sle_next;   \
134
  (slistelm)->field.sle_next = (elm);       \
135
} while (0)
136
137
#define SLIST_INSERT_HEAD(head, elm, field) do {      \
138
  (elm)->field.sle_next = (head)->slh_first;      \
139
  (head)->slh_first = (elm);          \
140
} while (0)
141
142
#define SLIST_REMOVE_AFTER(elm, field) do {       \
143
  (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
144
} while (0)
145
146
#define SLIST_REMOVE_HEAD(head, field) do {       \
147
  (head)->slh_first = (head)->slh_first->field.sle_next;    \
148
} while (0)
149
150
#define SLIST_REMOVE(head, elm, type, field) do {     \
151
  if ((head)->slh_first == (elm)) {       \
152
    SLIST_REMOVE_HEAD((head), field);     \
153
  } else {              \
154
    struct type *curelm = (head)->slh_first;    \
155
                  \
156
    while (curelm->field.sle_next != (elm))     \
157
      curelm = curelm->field.sle_next;    \
158
    curelm->field.sle_next =        \
159
        curelm->field.sle_next->field.sle_next;   \
160
  }               \
161
  _Q_INVALIDATE((elm)->field.sle_next);       \
162
} while (0)
163
164
/*
165
 * List definitions.
166
 */
167
#define LIST_HEAD(name, type)           \
168
struct name {               \
169
  struct type *lh_first;  /* first element */     \
170
}
171
172
#define LIST_HEAD_INITIALIZER(head)         \
173
  { NULL }
174
175
#define LIST_ENTRY(type)            \
176
struct {                \
177
  struct type *le_next; /* next element */      \
178
  struct type **le_prev;  /* address of previous next element */  \
179
}
180
181
/*
182
 * List access methods.
183
 */
184
#define LIST_FIRST(head)    ((head)->lh_first)
185
#define LIST_END(head)      NULL
186
#define LIST_EMPTY(head)    (LIST_FIRST(head) == LIST_END(head))
187
#define LIST_NEXT(elm, field)   ((elm)->field.le_next)
188
189
#define LIST_FOREACH(var, head, field)          \
190
  for((var) = LIST_FIRST(head);         \
191
      (var)!= LIST_END(head);         \
192
      (var) = LIST_NEXT(var, field))
193
194
#define LIST_FOREACH_SAFE(var, head, field, tvar)     \
195
  for ((var) = LIST_FIRST(head);        \
196
      (var) && ((tvar) = LIST_NEXT(var, field), 1);   \
197
      (var) = (tvar))
198
199
/*
200
 * List functions.
201
 */
202
#define LIST_INIT(head) do {            \
203
  LIST_FIRST(head) = LIST_END(head);        \
204
} while (0)
205
206
#define LIST_INSERT_AFTER(listelm, elm, field) do {     \
207
  if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
208
    (listelm)->field.le_next->field.le_prev =   \
209
        &(elm)->field.le_next;        \
210
  (listelm)->field.le_next = (elm);       \
211
  (elm)->field.le_prev = &(listelm)->field.le_next;   \
212
} while (0)
213
214
#define LIST_INSERT_BEFORE(listelm, elm, field) do {      \
215
  (elm)->field.le_prev = (listelm)->field.le_prev;    \
216
  (elm)->field.le_next = (listelm);       \
217
  *(listelm)->field.le_prev = (elm);        \
218
  (listelm)->field.le_prev = &(elm)->field.le_next;   \
219
} while (0)
220
221
#define LIST_INSERT_HEAD(head, elm, field) do {       \
222
  if (((elm)->field.le_next = (head)->lh_first) != NULL)    \
223
    (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
224
  (head)->lh_first = (elm);         \
225
  (elm)->field.le_prev = &(head)->lh_first;     \
226
} while (0)
227
228
#define LIST_REMOVE(elm, field) do {          \
229
  if ((elm)->field.le_next != NULL)       \
230
    (elm)->field.le_next->field.le_prev =     \
231
        (elm)->field.le_prev;       \
232
  *(elm)->field.le_prev = (elm)->field.le_next;     \
233
  _Q_INVALIDATE((elm)->field.le_prev);        \
234
  _Q_INVALIDATE((elm)->field.le_next);        \
235
} while (0)
236
237
#define LIST_REPLACE(elm, elm2, field) do {       \
238
  if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
239
    (elm2)->field.le_next->field.le_prev =      \
240
        &(elm2)->field.le_next;       \
241
  (elm2)->field.le_prev = (elm)->field.le_prev;     \
242
  *(elm2)->field.le_prev = (elm2);        \
243
  _Q_INVALIDATE((elm)->field.le_prev);        \
244
  _Q_INVALIDATE((elm)->field.le_next);        \
245
} while (0)
246
247
/*
248
 * Simple queue definitions.
249
 */
250
#define SIMPLEQ_HEAD(name, type)          \
251
struct name {               \
252
  struct type *sqh_first; /* first element */     \
253
  struct type **sqh_last; /* addr of last next element */   \
254
}
255
256
#define SIMPLEQ_HEAD_INITIALIZER(head)          \
257
  { NULL, &(head).sqh_first }
258
259
#define SIMPLEQ_ENTRY(type)           \
260
struct {                \
261
  struct type *sqe_next;  /* next element */      \
262
}
263
264
/*
265
 * Simple queue access methods.
266
 */
267
16.5k
#define SIMPLEQ_FIRST(head)     ((head)->sqh_first)
268
#define SIMPLEQ_END(head)     NULL
269
#define SIMPLEQ_EMPTY(head)     (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
270
#define SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
271
272
#define SIMPLEQ_FOREACH(var, head, field)       \
273
  for((var) = SIMPLEQ_FIRST(head);        \
274
      (var) != SIMPLEQ_END(head);         \
275
      (var) = SIMPLEQ_NEXT(var, field))
276
277
#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar)      \
278
  for ((var) = SIMPLEQ_FIRST(head);       \
279
      (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1);    \
280
      (var) = (tvar))
281
282
/*
283
 * Simple queue functions.
284
 */
285
15.4k
#define SIMPLEQ_INIT(head) do {           \
286
15.4k
  (head)->sqh_first = NULL;         \
287
15.4k
  (head)->sqh_last = &(head)->sqh_first;        \
288
15.4k
} while (0)
289
290
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do {      \
291
  if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)  \
292
    (head)->sqh_last = &(elm)->field.sqe_next;    \
293
  (head)->sqh_first = (elm);          \
294
} while (0)
295
296
1.04k
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do {     \
297
1.04k
  (elm)->field.sqe_next = NULL;         \
298
1.04k
  *(head)->sqh_last = (elm);          \
299
1.04k
  (head)->sqh_last = &(elm)->field.sqe_next;      \
300
1.04k
} while (0)
301
302
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {    \
303
  if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
304
    (head)->sqh_last = &(elm)->field.sqe_next;    \
305
  (listelm)->field.sqe_next = (elm);        \
306
} while (0)
307
308
1.04k
#define SIMPLEQ_REMOVE_HEAD(head, field) do {     \
309
1.04k
  if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
310
1.04k
    (head)->sqh_last = &(head)->sqh_first;     \
311
1.04k
} while (0)
312
313
#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do {     \
314
  if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
315
      == NULL)              \
316
    (head)->sqh_last = &(elm)->field.sqe_next;    \
317
} while (0)
318
319
#define SIMPLEQ_CONCAT(head1, head2) do {       \
320
  if (!SIMPLEQ_EMPTY((head2))) {          \
321
    *(head1)->sqh_last = (head2)->sqh_first;    \
322
    (head1)->sqh_last = (head2)->sqh_last;      \
323
    SIMPLEQ_INIT((head2));          \
324
  }               \
325
} while (0)
326
327
/*
328
 * XOR Simple queue definitions.
329
 */
330
#define XSIMPLEQ_HEAD(name, type)         \
331
struct name {               \
332
  struct type *sqx_first; /* first element */     \
333
  struct type **sqx_last; /* addr of last next element */   \
334
  unsigned long sqx_cookie;         \
335
}
336
337
#define XSIMPLEQ_ENTRY(type)            \
338
struct {                \
339
  struct type *sqx_next;  /* next element */      \
340
}
341
342
/*
343
 * XOR Simple queue access methods.
344
 */
345
#define XSIMPLEQ_XOR(head, ptr)     ((__typeof(ptr))((head)->sqx_cookie ^ \
346
          (unsigned long)(ptr)))
347
#define XSIMPLEQ_FIRST(head)      XSIMPLEQ_XOR(head, ((head)->sqx_first))
348
#define XSIMPLEQ_END(head)      NULL
349
#define XSIMPLEQ_EMPTY(head)      (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
350
#define XSIMPLEQ_NEXT(head, elm, field)    XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
351
352
353
#define XSIMPLEQ_FOREACH(var, head, field)        \
354
  for ((var) = XSIMPLEQ_FIRST(head);        \
355
      (var) != XSIMPLEQ_END(head);        \
356
      (var) = XSIMPLEQ_NEXT(head, var, field))
357
358
#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar)     \
359
  for ((var) = XSIMPLEQ_FIRST(head);        \
360
      (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
361
      (var) = (tvar))
362
363
/*
364
 * XOR Simple queue functions.
365
 */
366
#define XSIMPLEQ_INIT(head) do {          \
367
  arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
368
  (head)->sqx_first = XSIMPLEQ_XOR(head, NULL);     \
369
  (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first);  \
370
} while (0)
371
372
#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do {     \
373
  if (((elm)->field.sqx_next = (head)->sqx_first) ==    \
374
      XSIMPLEQ_XOR(head, NULL))         \
375
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
376
  (head)->sqx_first = XSIMPLEQ_XOR(head, (elm));      \
377
} while (0)
378
379
#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do {     \
380
  (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL);   \
381
  *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
382
  (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next);  \
383
} while (0)
384
385
#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {   \
386
  if (((elm)->field.sqx_next = (listelm)->field.sqx_next) ==  \
387
      XSIMPLEQ_XOR(head, NULL))         \
388
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
389
  (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm));    \
390
} while (0)
391
392
#define XSIMPLEQ_REMOVE_HEAD(head, field) do {        \
393
  if (((head)->sqx_first = XSIMPLEQ_XOR(head,     \
394
      (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
395
    (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
396
} while (0)
397
398
#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do {      \
399
  if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head,     \
400
      (elm)->field.sqx_next)->field.sqx_next)     \
401
      == XSIMPLEQ_XOR(head, NULL))        \
402
    (head)->sqx_last =          \
403
        XSIMPLEQ_XOR(head, &(elm)->field.sqx_next);   \
404
} while (0)
405
406
407
/*
408
 * Tail queue definitions.
409
 */
410
#define TAILQ_HEAD(name, type)            \
411
struct name {               \
412
  struct type *tqh_first; /* first element */     \
413
  struct type **tqh_last; /* addr of last next element */   \
414
}
415
416
#define TAILQ_HEAD_INITIALIZER(head)          \
417
  { NULL, &(head).tqh_first }
418
419
#define TAILQ_ENTRY(type)           \
420
struct {                \
421
  struct type *tqe_next;  /* next element */      \
422
  struct type **tqe_prev; /* address of previous next element */  \
423
}
424
425
/*
426
 * Tail queue access methods.
427
 */
428
15.4k
#define TAILQ_FIRST(head)   ((head)->tqh_first)
429
30.9k
#define TAILQ_END(head)     NULL
430
0
#define TAILQ_NEXT(elm, field)    ((elm)->field.tqe_next)
431
#define TAILQ_LAST(head, headname)          \
432
  (*(((struct headname *)((head)->tqh_last))->tqh_last))
433
/* XXX */
434
#define TAILQ_PREV(elm, headname, field)        \
435
  (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
436
#define TAILQ_EMPTY(head)           \
437
  (TAILQ_FIRST(head) == TAILQ_END(head))
438
439
#define TAILQ_FOREACH(var, head, field)         \
440
0
  for((var) = TAILQ_FIRST(head);         \
441
0
      (var) != TAILQ_END(head);         \
442
0
      (var) = TAILQ_NEXT(var, field))
443
444
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)      \
445
15.4k
  for ((var) = TAILQ_FIRST(head);         \
446
15.4k
      (var) != TAILQ_END(head) &&         \
447
15.4k
      ((tvar) = TAILQ_NEXT(var, field), 1);     \
448
15.4k
      (var) = (tvar))
449
450
451
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)   \
452
  for((var) = TAILQ_LAST(head, headname);       \
453
      (var) != TAILQ_END(head);         \
454
      (var) = TAILQ_PREV(var, headname, field))
455
456
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)  \
457
  for ((var) = TAILQ_LAST(head, headname);      \
458
      (var) != TAILQ_END(head) &&         \
459
      ((tvar) = TAILQ_PREV(var, headname, field), 1);   \
460
      (var) = (tvar))
461
462
/*
463
 * Tail queue functions.
464
 */
465
15.4k
#define TAILQ_INIT(head) do {           \
466
15.4k
  (head)->tqh_first = NULL;         \
467
15.4k
  (head)->tqh_last = &(head)->tqh_first;        \
468
15.4k
} while (0)
469
470
#define TAILQ_INSERT_HEAD(head, elm, field) do {      \
471
  if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)  \
472
    (head)->tqh_first->field.tqe_prev =     \
473
        &(elm)->field.tqe_next;       \
474
  else                \
475
    (head)->tqh_last = &(elm)->field.tqe_next;    \
476
  (head)->tqh_first = (elm);          \
477
  (elm)->field.tqe_prev = &(head)->tqh_first;     \
478
} while (0)
479
480
0
#define TAILQ_INSERT_TAIL(head, elm, field) do {     \
481
0
  (elm)->field.tqe_next = NULL;         \
482
0
  (elm)->field.tqe_prev = (head)->tqh_last;     \
483
0
  *(head)->tqh_last = (elm);          \
484
0
  (head)->tqh_last = &(elm)->field.tqe_next;      \
485
0
} while (0)
486
487
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {    \
488
  if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
489
    (elm)->field.tqe_next->field.tqe_prev =     \
490
        &(elm)->field.tqe_next;       \
491
  else                \
492
    (head)->tqh_last = &(elm)->field.tqe_next;    \
493
  (listelm)->field.tqe_next = (elm);        \
494
  (elm)->field.tqe_prev = &(listelm)->field.tqe_next;   \
495
} while (0)
496
497
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {     \
498
  (elm)->field.tqe_prev = (listelm)->field.tqe_prev;    \
499
  (elm)->field.tqe_next = (listelm);        \
500
  *(listelm)->field.tqe_prev = (elm);       \
501
  (listelm)->field.tqe_prev = &(elm)->field.tqe_next;   \
502
} while (0)
503
504
0
#define TAILQ_REMOVE(head, elm, field) do {       \
505
0
  if (((elm)->field.tqe_next) != NULL)       \
506
0
    (elm)->field.tqe_next->field.tqe_prev =     \
507
0
        (elm)->field.tqe_prev;       \
508
0
  else                \
509
0
    (head)->tqh_last = (elm)->field.tqe_prev;   \
510
0
  *(elm)->field.tqe_prev = (elm)->field.tqe_next;     \
511
0
  _Q_INVALIDATE((elm)->field.tqe_prev);       \
512
0
  _Q_INVALIDATE((elm)->field.tqe_next);       \
513
0
} while (0)
514
515
#define TAILQ_REPLACE(head, elm, elm2, field) do {      \
516
  if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
517
    (elm2)->field.tqe_next->field.tqe_prev =    \
518
        &(elm2)->field.tqe_next;        \
519
  else                \
520
    (head)->tqh_last = &(elm2)->field.tqe_next;   \
521
  (elm2)->field.tqe_prev = (elm)->field.tqe_prev;     \
522
  *(elm2)->field.tqe_prev = (elm2);       \
523
  _Q_INVALIDATE((elm)->field.tqe_prev);       \
524
  _Q_INVALIDATE((elm)->field.tqe_next);       \
525
} while (0)
526
527
#define TAILQ_CONCAT(head1, head2, field) do {        \
528
  if (!TAILQ_EMPTY(head2)) {          \
529
    *(head1)->tqh_last = (head2)->tqh_first;    \
530
    (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
531
    (head1)->tqh_last = (head2)->tqh_last;      \
532
    TAILQ_INIT((head2));          \
533
  }               \
534
} while (0)
535
536
/*
537
 * Singly-linked Tail queue declarations.
538
 */
539
#define STAILQ_HEAD(name, type)           \
540
struct name {               \
541
  struct type *stqh_first;  /* first element */   \
542
  struct type **stqh_last;  /* addr of last next element */ \
543
}
544
545
#define STAILQ_HEAD_INITIALIZER(head)         \
546
  { NULL, &(head).stqh_first }
547
548
#define STAILQ_ENTRY(type)            \
549
struct {                \
550
  struct type *stqe_next; /* next element */      \
551
}
552
553
/*
554
 * Singly-linked Tail queue access methods.
555
 */
556
#define STAILQ_FIRST(head)  ((head)->stqh_first)
557
#define STAILQ_END(head)  NULL
558
#define STAILQ_EMPTY(head)  (STAILQ_FIRST(head) == STAILQ_END(head))
559
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
560
561
#define STAILQ_FOREACH(var, head, field)        \
562
  for ((var) = STAILQ_FIRST(head);        \
563
      (var) != STAILQ_END(head);          \
564
      (var) = STAILQ_NEXT(var, field))
565
566
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)     \
567
  for ((var) = STAILQ_FIRST(head);        \
568
      (var) && ((tvar) = STAILQ_NEXT(var, field), 1);   \
569
      (var) = (tvar))
570
571
/*
572
 * Singly-linked Tail queue functions.
573
 */
574
#define STAILQ_INIT(head) do {            \
575
  STAILQ_FIRST((head)) = NULL;          \
576
  (head)->stqh_last = &STAILQ_FIRST((head));      \
577
} while (0)
578
579
#define STAILQ_INSERT_HEAD(head, elm, field) do {     \
580
  if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
581
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
582
  STAILQ_FIRST((head)) = (elm);         \
583
} while (0)
584
585
#define STAILQ_INSERT_TAIL(head, elm, field) do {     \
586
  STAILQ_NEXT((elm), field) = NULL;       \
587
  *(head)->stqh_last = (elm);         \
588
  (head)->stqh_last = &STAILQ_NEXT((elm), field);     \
589
} while (0)
590
591
#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do {   \
592
  if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((elm), field)) == NULL)\
593
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
594
  STAILQ_NEXT((elm), field) = (elm);        \
595
} while (0)
596
597
#define STAILQ_REMOVE_HEAD(head, field) do {                            \
598
  if ((STAILQ_FIRST((head)) =         \
599
      STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)    \
600
    (head)->stqh_last = &STAILQ_FIRST((head));    \
601
} while (0)
602
603
#define STAILQ_REMOVE_AFTER(head, elm, field) do {                      \
604
  if ((STAILQ_NEXT(elm, field) =          \
605
      STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
606
    (head)->stqh_last = &STAILQ_NEXT((elm), field);   \
607
} while (0)
608
609
#define STAILQ_REMOVE(head, elm, type, field) do {      \
610
  if (STAILQ_FIRST((head)) == (elm)) {        \
611
    STAILQ_REMOVE_HEAD((head), field);      \
612
  } else {              \
613
    struct type *curelm = (head)->stqh_first;   \
614
    while (STAILQ_NEXT(curelm, field) != (elm))   \
615
      curelm = STAILQ_NEXT(curelm, field);    \
616
    STAILQ_REMOVE_AFTER(head, curelm, field);   \
617
  }               \
618
} while (0)
619
620
#define STAILQ_CONCAT(head1, head2) do {        \
621
  if (!STAILQ_EMPTY((head2))) {         \
622
    *(head1)->stqh_last = (head2)->stqh_first;    \
623
    (head1)->stqh_last = (head2)->stqh_last;    \
624
    STAILQ_INIT((head2));         \
625
  }               \
626
} while (0)
627
628
#define STAILQ_LAST(head, type, field)          \
629
  (STAILQ_EMPTY((head)) ? NULL :          \
630
          ((struct type *)(void *)        \
631
    ((char *)((head)->stqh_last) - offsetof(struct type, field))))
632
633
#endif  /* !_SYS_QUEUE_H_ */
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/sys/tree.h.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/sys/tree.h.html index c3bab5f3e..8c073885a 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/sys/tree.h.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/sys/tree.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/sys/tree.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: tree.h,v 1.31 2023/03/08 04:43:09 guenther Exp $  */
2
/*
3
 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#ifndef _SYS_TREE_H_
28
#define _SYS_TREE_H_
29
30
#include <sys/_null.h>
31
32
/*
33
 * This file defines data structures for different types of trees:
34
 * splay trees and red-black trees.
35
 *
36
 * A splay tree is a self-organizing data structure.  Every operation
37
 * on the tree causes a splay to happen.  The splay moves the requested
38
 * node to the root of the tree and partly rebalances it.
39
 *
40
 * This has the benefit that request locality causes faster lookups as
41
 * the requested nodes move to the top of the tree.  On the other hand,
42
 * every lookup causes memory writes.
43
 *
44
 * The Balance Theorem bounds the total access time for m operations
45
 * and n inserts on an initially empty tree as O((m + n)lg n).  The
46
 * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
47
 *
48
 * A red-black tree is a binary search tree with the node color as an
49
 * extra attribute.  It fulfills a set of conditions:
50
 *  - every search path from the root to a leaf consists of the
51
 *    same number of black nodes,
52
 *  - each red node (except for the root) has a black parent,
53
 *  - each leaf node is black.
54
 *
55
 * Every operation on a red-black tree is bounded as O(lg n).
56
 * The maximum height of a red-black tree is 2lg (n+1).
57
 */
58
59
#define SPLAY_HEAD(name, type)            \
60
struct name {               \
61
  struct type *sph_root; /* root of the tree */     \
62
}
63
64
#define SPLAY_INITIALIZER(root)           \
65
  { NULL }
66
67
#define SPLAY_INIT(root) do {           \
68
  (root)->sph_root = NULL;          \
69
} while (0)
70
71
#define SPLAY_ENTRY(type)           \
72
struct {                \
73
  struct type *spe_left; /* left element */     \
74
  struct type *spe_right; /* right element */     \
75
}
76
77
#define SPLAY_LEFT(elm, field)    (elm)->field.spe_left
78
#define SPLAY_RIGHT(elm, field)   (elm)->field.spe_right
79
#define SPLAY_ROOT(head)    (head)->sph_root
80
#define SPLAY_EMPTY(head)   (SPLAY_ROOT(head) == NULL)
81
82
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
83
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do {     \
84
  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);  \
85
  SPLAY_RIGHT(tmp, field) = (head)->sph_root;     \
86
  (head)->sph_root = tmp;           \
87
} while (0)
88
89
#define SPLAY_ROTATE_LEFT(head, tmp, field) do {      \
90
  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);  \
91
  SPLAY_LEFT(tmp, field) = (head)->sph_root;      \
92
  (head)->sph_root = tmp;           \
93
} while (0)
94
95
#define SPLAY_LINKLEFT(head, tmp, field) do {       \
96
  SPLAY_LEFT(tmp, field) = (head)->sph_root;      \
97
  tmp = (head)->sph_root;           \
98
  (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);   \
99
} while (0)
100
101
#define SPLAY_LINKRIGHT(head, tmp, field) do {        \
102
  SPLAY_RIGHT(tmp, field) = (head)->sph_root;     \
103
  tmp = (head)->sph_root;           \
104
  (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);  \
105
} while (0)
106
107
#define SPLAY_ASSEMBLE(head, node, left, right, field) do {   \
108
  SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
109
  SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
110
  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
111
  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
112
} while (0)
113
114
/* Generates prototypes and inline functions */
115
116
#define SPLAY_PROTOTYPE(name, type, field, cmp)       \
117
void name##_SPLAY(struct name *, struct type *);      \
118
void name##_SPLAY_MINMAX(struct name *, int);       \
119
struct type *name##_SPLAY_INSERT(struct name *, struct type *);   \
120
struct type *name##_SPLAY_REMOVE(struct name *, struct type *);   \
121
                  \
122
/* Finds the node with the same key as elm */       \
123
static __unused __inline struct type *          \
124
name##_SPLAY_FIND(struct name *head, struct type *elm)      \
125
{                 \
126
  if (SPLAY_EMPTY(head))            \
127
    return(NULL);           \
128
  name##_SPLAY(head, elm);          \
129
  if ((cmp)(elm, (head)->sph_root) == 0)        \
130
    return (head->sph_root);        \
131
  return (NULL);              \
132
}                 \
133
                  \
134
static __unused __inline struct type *          \
135
name##_SPLAY_NEXT(struct name *head, struct type *elm)      \
136
{                 \
137
  name##_SPLAY(head, elm);          \
138
  if (SPLAY_RIGHT(elm, field) != NULL) {        \
139
    elm = SPLAY_RIGHT(elm, field);        \
140
    while (SPLAY_LEFT(elm, field) != NULL) {    \
141
      elm = SPLAY_LEFT(elm, field);     \
142
    }             \
143
  } else                \
144
    elm = NULL;           \
145
  return (elm);             \
146
}                 \
147
                  \
148
static __unused __inline struct type *          \
149
name##_SPLAY_MIN_MAX(struct name *head, int val)      \
150
{                 \
151
  name##_SPLAY_MINMAX(head, val);         \
152
        return (SPLAY_ROOT(head));          \
153
}
154
155
/* Main splay operation.
156
 * Moves node close to the key of elm to top
157
 */
158
#define SPLAY_GENERATE(name, type, field, cmp)        \
159
struct type *               \
160
name##_SPLAY_INSERT(struct name *head, struct type *elm)    \
161
{                 \
162
    if (SPLAY_EMPTY(head)) {            \
163
      SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL;  \
164
    } else {                \
165
      int __comp;             \
166
      name##_SPLAY(head, elm);          \
167
      __comp = (cmp)(elm, (head)->sph_root);      \
168
      if(__comp < 0) {            \
169
        SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
170
        SPLAY_RIGHT(elm, field) = (head)->sph_root;   \
171
        SPLAY_LEFT((head)->sph_root, field) = NULL;   \
172
      } else if (__comp > 0) {          \
173
        SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
174
        SPLAY_LEFT(elm, field) = (head)->sph_root;    \
175
        SPLAY_RIGHT((head)->sph_root, field) = NULL;  \
176
      } else              \
177
        return ((head)->sph_root);        \
178
    }                 \
179
    (head)->sph_root = (elm);           \
180
    return (NULL);              \
181
}                 \
182
                  \
183
struct type *               \
184
name##_SPLAY_REMOVE(struct name *head, struct type *elm)    \
185
{                 \
186
  struct type *__tmp;           \
187
  if (SPLAY_EMPTY(head))            \
188
    return (NULL);            \
189
  name##_SPLAY(head, elm);          \
190
  if ((cmp)(elm, (head)->sph_root) == 0) {      \
191
    if (SPLAY_LEFT((head)->sph_root, field) == NULL) {  \
192
      (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
193
    } else {            \
194
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
195
      (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
196
      name##_SPLAY(head, elm);      \
197
      SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
198
    }             \
199
    return (elm);           \
200
  }               \
201
  return (NULL);              \
202
}                 \
203
                  \
204
void                  \
205
name##_SPLAY(struct name *head, struct type *elm)     \
206
{                 \
207
  struct type __node, *__left, *__right, *__tmp;      \
208
  int __comp;             \
209
\
210
  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
211
  __left = __right = &__node;         \
212
\
213
  while ((__comp = (cmp)(elm, (head)->sph_root))) {   \
214
    if (__comp < 0) {         \
215
      __tmp = SPLAY_LEFT((head)->sph_root, field);  \
216
      if (__tmp == NULL)        \
217
        break;          \
218
      if ((cmp)(elm, __tmp) < 0){     \
219
        SPLAY_ROTATE_RIGHT(head, __tmp, field); \
220
        if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
221
          break;        \
222
      }           \
223
      SPLAY_LINKLEFT(head, __right, field);   \
224
    } else if (__comp > 0) {        \
225
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
226
      if (__tmp == NULL)        \
227
        break;          \
228
      if ((cmp)(elm, __tmp) > 0){     \
229
        SPLAY_ROTATE_LEFT(head, __tmp, field);  \
230
        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
231
          break;        \
232
      }           \
233
      SPLAY_LINKRIGHT(head, __left, field);   \
234
    }             \
235
  }               \
236
  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);    \
237
}                 \
238
                  \
239
/* Splay with either the minimum or the maximum element     \
240
 * Used to find minimum or maximum element in tree.     \
241
 */                 \
242
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
243
{                 \
244
  struct type __node, *__left, *__right, *__tmp;      \
245
\
246
  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
247
  __left = __right = &__node;         \
248
\
249
  while (1) {             \
250
    if (__comp < 0) {         \
251
      __tmp = SPLAY_LEFT((head)->sph_root, field);  \
252
      if (__tmp == NULL)        \
253
        break;          \
254
      if (__comp < 0){        \
255
        SPLAY_ROTATE_RIGHT(head, __tmp, field); \
256
        if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
257
          break;        \
258
      }           \
259
      SPLAY_LINKLEFT(head, __right, field);   \
260
    } else if (__comp > 0) {        \
261
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
262
      if (__tmp == NULL)        \
263
        break;          \
264
      if (__comp > 0) {       \
265
        SPLAY_ROTATE_LEFT(head, __tmp, field);  \
266
        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
267
          break;        \
268
      }           \
269
      SPLAY_LINKRIGHT(head, __left, field);   \
270
    }             \
271
  }               \
272
  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);    \
273
}
274
275
#define SPLAY_NEGINF  -1
276
#define SPLAY_INF 1
277
278
#define SPLAY_INSERT(name, x, y)  name##_SPLAY_INSERT(x, y)
279
#define SPLAY_REMOVE(name, x, y)  name##_SPLAY_REMOVE(x, y)
280
#define SPLAY_FIND(name, x, y)    name##_SPLAY_FIND(x, y)
281
#define SPLAY_NEXT(name, x, y)    name##_SPLAY_NEXT(x, y)
282
#define SPLAY_MIN(name, x)    (SPLAY_EMPTY(x) ? NULL  \
283
          : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
284
#define SPLAY_MAX(name, x)    (SPLAY_EMPTY(x) ? NULL  \
285
          : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
286
287
#define SPLAY_FOREACH(x, name, head)          \
288
  for ((x) = SPLAY_MIN(name, head);       \
289
       (x) != NULL;           \
290
       (x) = SPLAY_NEXT(name, head, x))
291
292
/* Macros that define a red-black tree */
293
#define RB_HEAD(name, type)           \
294
struct name {               \
295
  struct type *rbh_root; /* root of the tree */     \
296
}
297
298
#define RB_INITIALIZER(root)            \
299
  { NULL }
300
301
#define RB_INIT(root) do {            \
302
  (root)->rbh_root = NULL;          \
303
} while (0)
304
305
#define RB_BLACK  0
306
#define RB_RED    1
307
#define RB_ENTRY(type)              \
308
struct {                \
309
  struct type *rbe_left;    /* left element */    \
310
  struct type *rbe_right;   /* right element */   \
311
  struct type *rbe_parent;  /* parent element */    \
312
  int rbe_color;      /* node color */    \
313
}
314
315
#define RB_LEFT(elm, field)   (elm)->field.rbe_left
316
#define RB_RIGHT(elm, field)    (elm)->field.rbe_right
317
#define RB_PARENT(elm, field)   (elm)->field.rbe_parent
318
#define RB_COLOR(elm, field)    (elm)->field.rbe_color
319
#define RB_ROOT(head)     (head)->rbh_root
320
#define RB_EMPTY(head)      (RB_ROOT(head) == NULL)
321
322
#define RB_SET(elm, parent, field) do {         \
323
  RB_PARENT(elm, field) = parent;         \
324
  RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;    \
325
  RB_COLOR(elm, field) = RB_RED;          \
326
} while (0)
327
328
#define RB_SET_BLACKRED(black, red, field) do {       \
329
  RB_COLOR(black, field) = RB_BLACK;        \
330
  RB_COLOR(red, field) = RB_RED;          \
331
} while (0)
332
333
#ifndef RB_AUGMENT
334
#define RB_AUGMENT(x) do {} while (0)
335
#endif
336
337
#define RB_ROTATE_LEFT(head, elm, tmp, field) do {      \
338
  (tmp) = RB_RIGHT(elm, field);         \
339
  if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) {   \
340
    RB_PARENT(RB_LEFT(tmp, field), field) = (elm);    \
341
  }               \
342
  RB_AUGMENT(elm);            \
343
  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {    \
344
    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
345
      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
346
    else              \
347
      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
348
  } else                \
349
    (head)->rbh_root = (tmp);       \
350
  RB_LEFT(tmp, field) = (elm);          \
351
  RB_PARENT(elm, field) = (tmp);          \
352
  RB_AUGMENT(tmp);            \
353
  if ((RB_PARENT(tmp, field)))          \
354
    RB_AUGMENT(RB_PARENT(tmp, field));      \
355
} while (0)
356
357
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do {     \
358
  (tmp) = RB_LEFT(elm, field);          \
359
  if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) {   \
360
    RB_PARENT(RB_RIGHT(tmp, field), field) = (elm);   \
361
  }               \
362
  RB_AUGMENT(elm);            \
363
  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {    \
364
    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
365
      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
366
    else              \
367
      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
368
  } else                \
369
    (head)->rbh_root = (tmp);       \
370
  RB_RIGHT(tmp, field) = (elm);         \
371
  RB_PARENT(elm, field) = (tmp);          \
372
  RB_AUGMENT(tmp);            \
373
  if ((RB_PARENT(tmp, field)))          \
374
    RB_AUGMENT(RB_PARENT(tmp, field));      \
375
} while (0)
376
377
/* Generates prototypes and inline functions */
378
#define RB_PROTOTYPE(name, type, field, cmp)        \
379
  RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
380
#define RB_PROTOTYPE_STATIC(name, type, field, cmp)     \
381
  RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
382
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr)   \
383
attr void name##_RB_INSERT_COLOR(struct name *, struct type *);   \
384
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
385
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
386
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
387
attr struct type *name##_RB_FIND(struct name *, struct type *);   \
388
attr struct type *name##_RB_NFIND(struct name *, struct type *);  \
389
attr struct type *name##_RB_NEXT(struct type *);      \
390
attr struct type *name##_RB_PREV(struct type *);      \
391
attr struct type *name##_RB_MINMAX(struct name *, int);     \
392
                  \
393
394
/* Main rb operation.
395
 * Moves node close to the key of elm to top
396
 */
397
#define RB_GENERATE(name, type, field, cmp)       \
398
  RB_GENERATE_INTERNAL(name, type, field, cmp,)
399
#define RB_GENERATE_STATIC(name, type, field, cmp)      \
400
  RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
401
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr)    \
402
attr void               \
403
name##_RB_INSERT_COLOR(struct name *head, struct type *elm)   \
404
{                 \
405
  struct type *parent, *gparent, *tmp;        \
406
  while ((parent = RB_PARENT(elm, field)) &&      \
407
      RB_COLOR(parent, field) == RB_RED) {      \
408
    gparent = RB_PARENT(parent, field);     \
409
    if (parent == RB_LEFT(gparent, field)) {    \
410
      tmp = RB_RIGHT(gparent, field);     \
411
      if (tmp && RB_COLOR(tmp, field) == RB_RED) {  \
412
        RB_COLOR(tmp, field) = RB_BLACK;  \
413
        RB_SET_BLACKRED(parent, gparent, field);\
414
        elm = gparent;        \
415
        continue;       \
416
      }           \
417
      if (RB_RIGHT(parent, field) == elm) {   \
418
        RB_ROTATE_LEFT(head, parent, tmp, field);\
419
        tmp = parent;       \
420
        parent = elm;       \
421
        elm = tmp;        \
422
      }           \
423
      RB_SET_BLACKRED(parent, gparent, field);  \
424
      RB_ROTATE_RIGHT(head, gparent, tmp, field); \
425
    } else {            \
426
      tmp = RB_LEFT(gparent, field);      \
427
      if (tmp && RB_COLOR(tmp, field) == RB_RED) {  \
428
        RB_COLOR(tmp, field) = RB_BLACK;  \
429
        RB_SET_BLACKRED(parent, gparent, field);\
430
        elm = gparent;        \
431
        continue;       \
432
      }           \
433
      if (RB_LEFT(parent, field) == elm) {    \
434
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
435
        tmp = parent;       \
436
        parent = elm;       \
437
        elm = tmp;        \
438
      }           \
439
      RB_SET_BLACKRED(parent, gparent, field);  \
440
      RB_ROTATE_LEFT(head, gparent, tmp, field);  \
441
    }             \
442
  }               \
443
  RB_COLOR(head->rbh_root, field) = RB_BLACK;     \
444
}                 \
445
                  \
446
attr void               \
447
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
448
{                 \
449
  struct type *tmp;           \
450
  while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
451
      elm != RB_ROOT(head)) {         \
452
    if (RB_LEFT(parent, field) == elm) {      \
453
      tmp = RB_RIGHT(parent, field);      \
454
      if (RB_COLOR(tmp, field) == RB_RED) {   \
455
        RB_SET_BLACKRED(tmp, parent, field);  \
456
        RB_ROTATE_LEFT(head, parent, tmp, field);\
457
        tmp = RB_RIGHT(parent, field);    \
458
      }           \
459
      if ((RB_LEFT(tmp, field) == NULL ||   \
460
          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
461
          (RB_RIGHT(tmp, field) == NULL ||    \
462
          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
463
        RB_COLOR(tmp, field) = RB_RED;    \
464
        elm = parent;       \
465
        parent = RB_PARENT(elm, field);   \
466
      } else {          \
467
        if (RB_RIGHT(tmp, field) == NULL || \
468
            RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
469
          struct type *oleft;   \
470
          if ((oleft = RB_LEFT(tmp, field)))\
471
            RB_COLOR(oleft, field) = RB_BLACK;\
472
          RB_COLOR(tmp, field) = RB_RED;  \
473
          RB_ROTATE_RIGHT(head, tmp, oleft, field);\
474
          tmp = RB_RIGHT(parent, field);  \
475
        }         \
476
        RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
477
        RB_COLOR(parent, field) = RB_BLACK; \
478
        if (RB_RIGHT(tmp, field))   \
479
          RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
480
        RB_ROTATE_LEFT(head, parent, tmp, field);\
481
        elm = RB_ROOT(head);      \
482
        break;          \
483
      }           \
484
    } else {            \
485
      tmp = RB_LEFT(parent, field);     \
486
      if (RB_COLOR(tmp, field) == RB_RED) {   \
487
        RB_SET_BLACKRED(tmp, parent, field);  \
488
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
489
        tmp = RB_LEFT(parent, field);   \
490
      }           \
491
      if ((RB_LEFT(tmp, field) == NULL ||   \
492
          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
493
          (RB_RIGHT(tmp, field) == NULL ||    \
494
          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
495
        RB_COLOR(tmp, field) = RB_RED;    \
496
        elm = parent;       \
497
        parent = RB_PARENT(elm, field);   \
498
      } else {          \
499
        if (RB_LEFT(tmp, field) == NULL ||  \
500
            RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
501
          struct type *oright;    \
502
          if ((oright = RB_RIGHT(tmp, field)))\
503
            RB_COLOR(oright, field) = RB_BLACK;\
504
          RB_COLOR(tmp, field) = RB_RED;  \
505
          RB_ROTATE_LEFT(head, tmp, oright, field);\
506
          tmp = RB_LEFT(parent, field); \
507
        }         \
508
        RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
509
        RB_COLOR(parent, field) = RB_BLACK; \
510
        if (RB_LEFT(tmp, field))    \
511
          RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
512
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
513
        elm = RB_ROOT(head);      \
514
        break;          \
515
      }           \
516
    }             \
517
  }               \
518
  if (elm)              \
519
    RB_COLOR(elm, field) = RB_BLACK;      \
520
}                 \
521
                  \
522
attr struct type *              \
523
name##_RB_REMOVE(struct name *head, struct type *elm)     \
524
{                 \
525
  struct type *child, *parent, *old = elm;      \
526
  int color;              \
527
  if (RB_LEFT(elm, field) == NULL)        \
528
    child = RB_RIGHT(elm, field);       \
529
  else if (RB_RIGHT(elm, field) == NULL)        \
530
    child = RB_LEFT(elm, field);        \
531
  else {                \
532
    struct type *left;          \
533
    elm = RB_RIGHT(elm, field);       \
534
    while ((left = RB_LEFT(elm, field)))      \
535
      elm = left;         \
536
    child = RB_RIGHT(elm, field);       \
537
    parent = RB_PARENT(elm, field);       \
538
    color = RB_COLOR(elm, field);       \
539
    if (child)            \
540
      RB_PARENT(child, field) = parent;   \
541
    if (parent) {           \
542
      if (RB_LEFT(parent, field) == elm)    \
543
        RB_LEFT(parent, field) = child;   \
544
      else            \
545
        RB_RIGHT(parent, field) = child;  \
546
      RB_AUGMENT(parent);       \
547
    } else              \
548
      RB_ROOT(head) = child;        \
549
    if (RB_PARENT(elm, field) == old)     \
550
      parent = elm;         \
551
    (elm)->field = (old)->field;        \
552
    if (RB_PARENT(old, field)) {        \
553
      if (RB_LEFT(RB_PARENT(old, field), field) == old)\
554
        RB_LEFT(RB_PARENT(old, field), field) = elm;\
555
      else            \
556
        RB_RIGHT(RB_PARENT(old, field), field) = elm;\
557
      RB_AUGMENT(RB_PARENT(old, field));    \
558
    } else              \
559
      RB_ROOT(head) = elm;        \
560
    RB_PARENT(RB_LEFT(old, field), field) = elm;    \
561
    if (RB_RIGHT(old, field))       \
562
      RB_PARENT(RB_RIGHT(old, field), field) = elm; \
563
    if (parent) {           \
564
      left = parent;          \
565
      do {            \
566
        RB_AUGMENT(left);     \
567
      } while ((left = RB_PARENT(left, field)));  \
568
    }             \
569
    goto color;           \
570
  }               \
571
  parent = RB_PARENT(elm, field);         \
572
  color = RB_COLOR(elm, field);         \
573
  if (child)              \
574
    RB_PARENT(child, field) = parent;     \
575
  if (parent) {             \
576
    if (RB_LEFT(parent, field) == elm)      \
577
      RB_LEFT(parent, field) = child;     \
578
    else              \
579
      RB_RIGHT(parent, field) = child;    \
580
    RB_AUGMENT(parent);         \
581
  } else                \
582
    RB_ROOT(head) = child;          \
583
color:                  \
584
  if (color == RB_BLACK)            \
585
    name##_RB_REMOVE_COLOR(head, parent, child);    \
586
  return (old);             \
587
}                 \
588
                  \
589
/* Inserts a node into the RB tree */         \
590
attr struct type *              \
591
name##_RB_INSERT(struct name *head, struct type *elm)     \
592
{                 \
593
  struct type *tmp;           \
594
  struct type *parent = NULL;         \
595
  int comp = 0;             \
596
  tmp = RB_ROOT(head);            \
597
  while (tmp) {             \
598
    parent = tmp;           \
599
    comp = (cmp)(elm, parent);        \
600
    if (comp < 0)           \
601
      tmp = RB_LEFT(tmp, field);      \
602
    else if (comp > 0)          \
603
      tmp = RB_RIGHT(tmp, field);     \
604
    else              \
605
      return (tmp);         \
606
  }               \
607
  RB_SET(elm, parent, field);         \
608
  if (parent != NULL) {           \
609
    if (comp < 0)           \
610
      RB_LEFT(parent, field) = elm;     \
611
    else              \
612
      RB_RIGHT(parent, field) = elm;      \
613
    RB_AUGMENT(parent);         \
614
  } else                \
615
    RB_ROOT(head) = elm;          \
616
  name##_RB_INSERT_COLOR(head, elm);        \
617
  return (NULL);              \
618
}                 \
619
                  \
620
/* Finds the node with the same key as elm */       \
621
attr struct type *              \
622
name##_RB_FIND(struct name *head, struct type *elm)     \
623
{                 \
624
  struct type *tmp = RB_ROOT(head);       \
625
  int comp;             \
626
  while (tmp) {             \
627
    comp = cmp(elm, tmp);         \
628
    if (comp < 0)           \
629
      tmp = RB_LEFT(tmp, field);      \
630
    else if (comp > 0)          \
631
      tmp = RB_RIGHT(tmp, field);     \
632
    else              \
633
      return (tmp);         \
634
  }               \
635
  return (NULL);              \
636
}                 \
637
                  \
638
/* Finds the first node greater than or equal to the search key */  \
639
attr struct type *              \
640
name##_RB_NFIND(struct name *head, struct type *elm)      \
641
{                 \
642
  struct type *tmp = RB_ROOT(head);       \
643
  struct type *res = NULL;          \
644
  int comp;             \
645
  while (tmp) {             \
646
    comp = cmp(elm, tmp);         \
647
    if (comp < 0) {           \
648
      res = tmp;          \
649
      tmp = RB_LEFT(tmp, field);      \
650
    }             \
651
    else if (comp > 0)          \
652
      tmp = RB_RIGHT(tmp, field);     \
653
    else              \
654
      return (tmp);         \
655
  }               \
656
  return (res);             \
657
}                 \
658
                  \
659
attr struct type *              \
660
name##_RB_NEXT(struct type *elm)          \
661
{                 \
662
  if (RB_RIGHT(elm, field)) {         \
663
    elm = RB_RIGHT(elm, field);       \
664
    while (RB_LEFT(elm, field))       \
665
      elm = RB_LEFT(elm, field);      \
666
  } else {              \
667
    if (RB_PARENT(elm, field) &&        \
668
        (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
669
      elm = RB_PARENT(elm, field);      \
670
    else {              \
671
      while (RB_PARENT(elm, field) &&     \
672
          (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
673
        elm = RB_PARENT(elm, field);    \
674
      elm = RB_PARENT(elm, field);      \
675
    }             \
676
  }               \
677
  return (elm);             \
678
}                 \
679
                  \
680
attr struct type *              \
681
name##_RB_PREV(struct type *elm)          \
682
{                 \
683
  if (RB_LEFT(elm, field)) {          \
684
    elm = RB_LEFT(elm, field);        \
685
    while (RB_RIGHT(elm, field))        \
686
      elm = RB_RIGHT(elm, field);     \
687
  } else {              \
688
    if (RB_PARENT(elm, field) &&        \
689
        (elm == RB_RIGHT(RB_PARENT(elm, field), field)))  \
690
      elm = RB_PARENT(elm, field);      \
691
    else {              \
692
      while (RB_PARENT(elm, field) &&     \
693
          (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
694
        elm = RB_PARENT(elm, field);    \
695
      elm = RB_PARENT(elm, field);      \
696
    }             \
697
  }               \
698
  return (elm);             \
699
}                 \
700
                  \
701
attr struct type *              \
702
name##_RB_MINMAX(struct name *head, int val)        \
703
{                 \
704
  struct type *tmp = RB_ROOT(head);       \
705
  struct type *parent = NULL;         \
706
  while (tmp) {             \
707
    parent = tmp;           \
708
    if (val < 0)            \
709
      tmp = RB_LEFT(tmp, field);      \
710
    else              \
711
      tmp = RB_RIGHT(tmp, field);     \
712
  }               \
713
  return (parent);            \
714
}
715
716
#define RB_NEGINF -1
717
#define RB_INF  1
718
719
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
720
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
721
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
722
#define RB_NFIND(name, x, y)  name##_RB_NFIND(x, y)
723
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
724
#define RB_PREV(name, x, y) name##_RB_PREV(y)
725
#define RB_MIN(name, x)   name##_RB_MINMAX(x, RB_NEGINF)
726
#define RB_MAX(name, x)   name##_RB_MINMAX(x, RB_INF)
727
728
#define RB_FOREACH(x, name, head)         \
729
  for ((x) = RB_MIN(name, head);          \
730
       (x) != NULL;           \
731
       (x) = name##_RB_NEXT(x))
732
733
#define RB_FOREACH_SAFE(x, name, head, y)       \
734
  for ((x) = RB_MIN(name, head);          \
735
      ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1);    \
736
       (x) = (y))
737
738
#define RB_FOREACH_REVERSE(x, name, head)       \
739
  for ((x) = RB_MAX(name, head);          \
740
       (x) != NULL;           \
741
       (x) = name##_RB_PREV(x))
742
743
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y)     \
744
  for ((x) = RB_MAX(name, head);          \
745
      ((x) != NULL) && ((y) = name##_RB_PREV(x), 1);    \
746
       (x) = (y))
747
748
749
/*
750
 * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
751
 *
752
 * Permission to use, copy, modify, and distribute this software for any
753
 * purpose with or without fee is hereby granted, provided that the above
754
 * copyright notice and this permission notice appear in all copies.
755
 *
756
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
757
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
758
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
759
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
760
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
761
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
762
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
763
 */
764
765
struct rb_type {
766
  int   (*t_compare)(const void *, const void *);
767
  void    (*t_augment)(void *);
768
  unsigned int    t_offset; /* offset of rb_entry in type */
769
};
770
771
struct rb_tree {
772
  struct rb_entry *rbt_root;
773
};
774
775
struct rb_entry {
776
  struct rb_entry  *rbt_parent;
777
  struct rb_entry  *rbt_left;
778
  struct rb_entry  *rbt_right;
779
  unsigned int    rbt_color;
780
};
781
782
#define RBT_HEAD(_name, _type)            \
783
struct _name {                \
784
  struct rb_tree rbh_root;          \
785
}
786
787
#define RBT_ENTRY(_type)  struct rb_entry
788
789
static inline void
790
_rb_init(struct rb_tree *rbt)
791
0
{
792
0
  rbt->rbt_root = NULL;
793
0
}
Unexecuted instantiation: common.c:_rb_init
Unexecuted instantiation: test_parser_fuzz.c:_rb_init
Unexecuted instantiation: ikev2_pld.c:_rb_init
Unexecuted instantiation: imsg_util.c:_rb_init
Unexecuted instantiation: util.c:_rb_init
794
795
static inline int
796
_rb_empty(struct rb_tree *rbt)
797
0
{
798
0
  return (rbt->rbt_root == NULL);
799
0
}
Unexecuted instantiation: common.c:_rb_empty
Unexecuted instantiation: test_parser_fuzz.c:_rb_empty
Unexecuted instantiation: ikev2_pld.c:_rb_empty
Unexecuted instantiation: imsg_util.c:_rb_empty
Unexecuted instantiation: util.c:_rb_empty
800
801
void  *_rb_insert(const struct rb_type *, struct rb_tree *, void *);
802
void  *_rb_remove(const struct rb_type *, struct rb_tree *, void *);
803
void  *_rb_find(const struct rb_type *, struct rb_tree *, const void *);
804
void  *_rb_nfind(const struct rb_type *, struct rb_tree *, const void *);
805
void  *_rb_root(const struct rb_type *, struct rb_tree *);
806
void  *_rb_min(const struct rb_type *, struct rb_tree *);
807
void  *_rb_max(const struct rb_type *, struct rb_tree *);
808
void  *_rb_next(const struct rb_type *, void *);
809
void  *_rb_prev(const struct rb_type *, void *);
810
void  *_rb_left(const struct rb_type *, void *);
811
void  *_rb_right(const struct rb_type *, void *);
812
void  *_rb_parent(const struct rb_type *, void *);
813
void   _rb_set_left(const struct rb_type *, void *, void *);
814
void   _rb_set_right(const struct rb_type *, void *, void *);
815
void   _rb_set_parent(const struct rb_type *, void *, void *);
816
void   _rb_poison(const struct rb_type *, void *, unsigned long);
817
int  _rb_check(const struct rb_type *, void *, unsigned long);
818
819
#define RBT_INITIALIZER(_head)  { { NULL } }
820
821
#define RBT_PROTOTYPE(_name, _type, _field, _cmp)     \
822
extern const struct rb_type *const _name##_RBT_TYPE;      \
823
                  \
824
__unused static inline void           \
825
_name##_RBT_INIT(struct _name *head)          \
826
{                 \
827
  _rb_init(&head->rbh_root);          \
828
}                 \
829
                  \
830
__unused static inline struct _type *         \
831
_name##_RBT_INSERT(struct _name *head, struct _type *elm)   \
832
{                 \
833
  return _rb_insert(_name##_RBT_TYPE, &head->rbh_root, elm);  \
834
}                 \
835
                  \
836
__unused static inline struct _type *         \
837
_name##_RBT_REMOVE(struct _name *head, struct _type *elm)   \
838
{                 \
839
  return _rb_remove(_name##_RBT_TYPE, &head->rbh_root, elm);  \
840
}                 \
841
                  \
842
__unused static inline struct _type *         \
843
_name##_RBT_FIND(struct _name *head, const struct _type *key)   \
844
{                 \
845
  return _rb_find(_name##_RBT_TYPE, &head->rbh_root, key);  \
846
}                 \
847
                  \
848
__unused static inline struct _type *         \
849
_name##_RBT_NFIND(struct _name *head, const struct _type *key)    \
850
{                 \
851
  return _rb_nfind(_name##_RBT_TYPE, &head->rbh_root, key); \
852
}                 \
853
                  \
854
__unused static inline struct _type *         \
855
_name##_RBT_ROOT(struct _name *head)          \
856
{                 \
857
  return _rb_root(_name##_RBT_TYPE, &head->rbh_root);   \
858
}                 \
859
                  \
860
__unused static inline int            \
861
_name##_RBT_EMPTY(struct _name *head)         \
862
{                 \
863
  return _rb_empty(&head->rbh_root);        \
864
}                 \
865
                  \
866
__unused static inline struct _type *         \
867
_name##_RBT_MIN(struct _name *head)         \
868
{                 \
869
  return _rb_min(_name##_RBT_TYPE, &head->rbh_root);    \
870
}                 \
871
                  \
872
__unused static inline struct _type *         \
873
_name##_RBT_MAX(struct _name *head)         \
874
{                 \
875
  return _rb_max(_name##_RBT_TYPE, &head->rbh_root);    \
876
}                 \
877
                  \
878
__unused static inline struct _type *         \
879
_name##_RBT_NEXT(struct _type *elm)         \
880
{                 \
881
  return _rb_next(_name##_RBT_TYPE, elm);       \
882
}                 \
883
                  \
884
__unused static inline struct _type *         \
885
_name##_RBT_PREV(struct _type *elm)         \
886
{                 \
887
  return _rb_prev(_name##_RBT_TYPE, elm);       \
888
}                 \
889
                  \
890
__unused static inline struct _type *         \
891
_name##_RBT_LEFT(struct _type *elm)         \
892
{                 \
893
  return _rb_left(_name##_RBT_TYPE, elm);       \
894
}                 \
895
                  \
896
__unused static inline struct _type *         \
897
_name##_RBT_RIGHT(struct _type *elm)          \
898
{                 \
899
  return _rb_right(_name##_RBT_TYPE, elm);      \
900
}                 \
901
                  \
902
__unused static inline struct _type *         \
903
_name##_RBT_PARENT(struct _type *elm)         \
904
{                 \
905
  return _rb_parent(_name##_RBT_TYPE, elm);     \
906
}                 \
907
                  \
908
__unused static inline void           \
909
_name##_RBT_SET_LEFT(struct _type *elm, struct _type *left)   \
910
{                 \
911
  _rb_set_left(_name##_RBT_TYPE, elm, left);      \
912
}                 \
913
                  \
914
__unused static inline void           \
915
_name##_RBT_SET_RIGHT(struct _type *elm, struct _type *right)   \
916
{                 \
917
  _rb_set_right(_name##_RBT_TYPE, elm, right);      \
918
}                 \
919
                  \
920
__unused static inline void           \
921
_name##_RBT_SET_PARENT(struct _type *elm, struct _type *parent)   \
922
{                 \
923
  _rb_set_parent(_name##_RBT_TYPE, elm, parent);      \
924
}                 \
925
                  \
926
__unused static inline void           \
927
_name##_RBT_POISON(struct _type *elm, unsigned long poison)   \
928
{                 \
929
  _rb_poison(_name##_RBT_TYPE, elm, poison);      \
930
}                 \
931
                  \
932
__unused static inline int            \
933
_name##_RBT_CHECK(struct _type *elm, unsigned long poison)    \
934
{                 \
935
  return _rb_check(_name##_RBT_TYPE, elm, poison);    \
936
}
937
938
#define RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug)   \
939
static int                \
940
_name##_RBT_COMPARE(const void *lptr, const void *rptr)     \
941
{                 \
942
  const struct _type *l = lptr, *r = rptr;      \
943
  return _cmp(l, r);            \
944
}                 \
945
static const struct rb_type _name##_RBT_INFO = {      \
946
  _name##_RBT_COMPARE,            \
947
  _aug,               \
948
  offsetof(struct _type, _field),         \
949
};                  \
950
const struct rb_type *const _name##_RBT_TYPE = &_name##_RBT_INFO
951
952
#define RBT_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug)    \
953
static void               \
954
_name##_RBT_AUGMENT(void *ptr)            \
955
{                 \
956
  struct _type *p = ptr;            \
957
  return _aug(p);             \
958
}                 \
959
RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RBT_AUGMENT)
960
961
#define RBT_GENERATE(_name, _type, _field, _cmp)      \
962
    RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL)
963
964
#define RBT_INIT(_name, _head)    _name##_RBT_INIT(_head)
965
#define RBT_INSERT(_name, _head, _elm)  _name##_RBT_INSERT(_head, _elm)
966
#define RBT_REMOVE(_name, _head, _elm)  _name##_RBT_REMOVE(_head, _elm)
967
#define RBT_FIND(_name, _head, _key)  _name##_RBT_FIND(_head, _key)
968
#define RBT_NFIND(_name, _head, _key) _name##_RBT_NFIND(_head, _key)
969
#define RBT_ROOT(_name, _head)    _name##_RBT_ROOT(_head)
970
#define RBT_EMPTY(_name, _head)   _name##_RBT_EMPTY(_head)
971
#define RBT_MIN(_name, _head)   _name##_RBT_MIN(_head)
972
#define RBT_MAX(_name, _head)   _name##_RBT_MAX(_head)
973
#define RBT_NEXT(_name, _elm)   _name##_RBT_NEXT(_elm)
974
#define RBT_PREV(_name, _elm)   _name##_RBT_PREV(_elm)
975
#define RBT_LEFT(_name, _elm)   _name##_RBT_LEFT(_elm)
976
#define RBT_RIGHT(_name, _elm)    _name##_RBT_RIGHT(_elm)
977
#define RBT_PARENT(_name, _elm)   _name##_RBT_PARENT(_elm)
978
#define RBT_SET_LEFT(_name, _elm, _l) _name##_RBT_SET_LEFT(_elm, _l)
979
#define RBT_SET_RIGHT(_name, _elm, _r)  _name##_RBT_SET_RIGHT(_elm, _r)
980
#define RBT_SET_PARENT(_name, _elm, _p) _name##_RBT_SET_PARENT(_elm, _p)
981
#define RBT_POISON(_name, _elm, _p) _name##_RBT_POISON(_elm, _p)
982
#define RBT_CHECK(_name, _elm, _p)  _name##_RBT_CHECK(_elm, _p)
983
984
#define RBT_FOREACH(_e, _name, _head)         \
985
  for ((_e) = RBT_MIN(_name, (_head));        \
986
       (_e) != NULL;            \
987
       (_e) = RBT_NEXT(_name, (_e)))
988
989
#define RBT_FOREACH_SAFE(_e, _name, _head, _n)        \
990
  for ((_e) = RBT_MIN(_name, (_head));        \
991
       (_e) != NULL && ((_n) = RBT_NEXT(_name, (_e)), 1); \
992
       (_e) = (_n))
993
994
#define RBT_FOREACH_REVERSE(_e, _name, _head)       \
995
  for ((_e) = RBT_MAX(_name, (_head));        \
996
       (_e) != NULL;            \
997
       (_e) = RBT_PREV(_name, (_e)))
998
999
#define RBT_FOREACH_REVERSE_SAFE(_e, _name, _head, _n)      \
1000
  for ((_e) = RBT_MAX(_name, (_head));        \
1001
       (_e) != NULL && ((_n) = RBT_PREV(_name, (_e)), 1); \
1002
       (_e) = (_n))
1003
1004
#endif  /* _SYS_TREE_H_ */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/sys/tree.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: tree.h,v 1.31 2023/03/08 04:43:09 guenther Exp $  */
2
/*
3
 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#ifndef _SYS_TREE_H_
28
#define _SYS_TREE_H_
29
30
#include <sys/_null.h>
31
32
/*
33
 * This file defines data structures for different types of trees:
34
 * splay trees and red-black trees.
35
 *
36
 * A splay tree is a self-organizing data structure.  Every operation
37
 * on the tree causes a splay to happen.  The splay moves the requested
38
 * node to the root of the tree and partly rebalances it.
39
 *
40
 * This has the benefit that request locality causes faster lookups as
41
 * the requested nodes move to the top of the tree.  On the other hand,
42
 * every lookup causes memory writes.
43
 *
44
 * The Balance Theorem bounds the total access time for m operations
45
 * and n inserts on an initially empty tree as O((m + n)lg n).  The
46
 * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
47
 *
48
 * A red-black tree is a binary search tree with the node color as an
49
 * extra attribute.  It fulfills a set of conditions:
50
 *  - every search path from the root to a leaf consists of the
51
 *    same number of black nodes,
52
 *  - each red node (except for the root) has a black parent,
53
 *  - each leaf node is black.
54
 *
55
 * Every operation on a red-black tree is bounded as O(lg n).
56
 * The maximum height of a red-black tree is 2lg (n+1).
57
 */
58
59
#define SPLAY_HEAD(name, type)            \
60
struct name {               \
61
  struct type *sph_root; /* root of the tree */     \
62
}
63
64
#define SPLAY_INITIALIZER(root)           \
65
  { NULL }
66
67
#define SPLAY_INIT(root) do {           \
68
  (root)->sph_root = NULL;          \
69
} while (0)
70
71
#define SPLAY_ENTRY(type)           \
72
struct {                \
73
  struct type *spe_left; /* left element */     \
74
  struct type *spe_right; /* right element */     \
75
}
76
77
#define SPLAY_LEFT(elm, field)    (elm)->field.spe_left
78
#define SPLAY_RIGHT(elm, field)   (elm)->field.spe_right
79
#define SPLAY_ROOT(head)    (head)->sph_root
80
#define SPLAY_EMPTY(head)   (SPLAY_ROOT(head) == NULL)
81
82
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
83
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do {     \
84
  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);  \
85
  SPLAY_RIGHT(tmp, field) = (head)->sph_root;     \
86
  (head)->sph_root = tmp;           \
87
} while (0)
88
89
#define SPLAY_ROTATE_LEFT(head, tmp, field) do {      \
90
  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);  \
91
  SPLAY_LEFT(tmp, field) = (head)->sph_root;      \
92
  (head)->sph_root = tmp;           \
93
} while (0)
94
95
#define SPLAY_LINKLEFT(head, tmp, field) do {       \
96
  SPLAY_LEFT(tmp, field) = (head)->sph_root;      \
97
  tmp = (head)->sph_root;           \
98
  (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);   \
99
} while (0)
100
101
#define SPLAY_LINKRIGHT(head, tmp, field) do {        \
102
  SPLAY_RIGHT(tmp, field) = (head)->sph_root;     \
103
  tmp = (head)->sph_root;           \
104
  (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);  \
105
} while (0)
106
107
#define SPLAY_ASSEMBLE(head, node, left, right, field) do {   \
108
  SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
109
  SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
110
  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
111
  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
112
} while (0)
113
114
/* Generates prototypes and inline functions */
115
116
#define SPLAY_PROTOTYPE(name, type, field, cmp)       \
117
void name##_SPLAY(struct name *, struct type *);      \
118
void name##_SPLAY_MINMAX(struct name *, int);       \
119
struct type *name##_SPLAY_INSERT(struct name *, struct type *);   \
120
struct type *name##_SPLAY_REMOVE(struct name *, struct type *);   \
121
                  \
122
/* Finds the node with the same key as elm */       \
123
static __unused __inline struct type *          \
124
name##_SPLAY_FIND(struct name *head, struct type *elm)      \
125
{                 \
126
  if (SPLAY_EMPTY(head))            \
127
    return(NULL);           \
128
  name##_SPLAY(head, elm);          \
129
  if ((cmp)(elm, (head)->sph_root) == 0)        \
130
    return (head->sph_root);        \
131
  return (NULL);              \
132
}                 \
133
                  \
134
static __unused __inline struct type *          \
135
name##_SPLAY_NEXT(struct name *head, struct type *elm)      \
136
{                 \
137
  name##_SPLAY(head, elm);          \
138
  if (SPLAY_RIGHT(elm, field) != NULL) {        \
139
    elm = SPLAY_RIGHT(elm, field);        \
140
    while (SPLAY_LEFT(elm, field) != NULL) {    \
141
      elm = SPLAY_LEFT(elm, field);     \
142
    }             \
143
  } else                \
144
    elm = NULL;           \
145
  return (elm);             \
146
}                 \
147
                  \
148
static __unused __inline struct type *          \
149
name##_SPLAY_MIN_MAX(struct name *head, int val)      \
150
{                 \
151
  name##_SPLAY_MINMAX(head, val);         \
152
        return (SPLAY_ROOT(head));          \
153
}
154
155
/* Main splay operation.
156
 * Moves node close to the key of elm to top
157
 */
158
#define SPLAY_GENERATE(name, type, field, cmp)        \
159
struct type *               \
160
name##_SPLAY_INSERT(struct name *head, struct type *elm)    \
161
{                 \
162
    if (SPLAY_EMPTY(head)) {            \
163
      SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL;  \
164
    } else {                \
165
      int __comp;             \
166
      name##_SPLAY(head, elm);          \
167
      __comp = (cmp)(elm, (head)->sph_root);      \
168
      if(__comp < 0) {            \
169
        SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
170
        SPLAY_RIGHT(elm, field) = (head)->sph_root;   \
171
        SPLAY_LEFT((head)->sph_root, field) = NULL;   \
172
      } else if (__comp > 0) {          \
173
        SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
174
        SPLAY_LEFT(elm, field) = (head)->sph_root;    \
175
        SPLAY_RIGHT((head)->sph_root, field) = NULL;  \
176
      } else              \
177
        return ((head)->sph_root);        \
178
    }                 \
179
    (head)->sph_root = (elm);           \
180
    return (NULL);              \
181
}                 \
182
                  \
183
struct type *               \
184
name##_SPLAY_REMOVE(struct name *head, struct type *elm)    \
185
{                 \
186
  struct type *__tmp;           \
187
  if (SPLAY_EMPTY(head))            \
188
    return (NULL);            \
189
  name##_SPLAY(head, elm);          \
190
  if ((cmp)(elm, (head)->sph_root) == 0) {      \
191
    if (SPLAY_LEFT((head)->sph_root, field) == NULL) {  \
192
      (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
193
    } else {            \
194
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
195
      (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
196
      name##_SPLAY(head, elm);      \
197
      SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
198
    }             \
199
    return (elm);           \
200
  }               \
201
  return (NULL);              \
202
}                 \
203
                  \
204
void                  \
205
name##_SPLAY(struct name *head, struct type *elm)     \
206
{                 \
207
  struct type __node, *__left, *__right, *__tmp;      \
208
  int __comp;             \
209
\
210
  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
211
  __left = __right = &__node;         \
212
\
213
  while ((__comp = (cmp)(elm, (head)->sph_root))) {   \
214
    if (__comp < 0) {         \
215
      __tmp = SPLAY_LEFT((head)->sph_root, field);  \
216
      if (__tmp == NULL)        \
217
        break;          \
218
      if ((cmp)(elm, __tmp) < 0){     \
219
        SPLAY_ROTATE_RIGHT(head, __tmp, field); \
220
        if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
221
          break;        \
222
      }           \
223
      SPLAY_LINKLEFT(head, __right, field);   \
224
    } else if (__comp > 0) {        \
225
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
226
      if (__tmp == NULL)        \
227
        break;          \
228
      if ((cmp)(elm, __tmp) > 0){     \
229
        SPLAY_ROTATE_LEFT(head, __tmp, field);  \
230
        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
231
          break;        \
232
      }           \
233
      SPLAY_LINKRIGHT(head, __left, field);   \
234
    }             \
235
  }               \
236
  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);    \
237
}                 \
238
                  \
239
/* Splay with either the minimum or the maximum element     \
240
 * Used to find minimum or maximum element in tree.     \
241
 */                 \
242
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
243
{                 \
244
  struct type __node, *__left, *__right, *__tmp;      \
245
\
246
  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
247
  __left = __right = &__node;         \
248
\
249
  while (1) {             \
250
    if (__comp < 0) {         \
251
      __tmp = SPLAY_LEFT((head)->sph_root, field);  \
252
      if (__tmp == NULL)        \
253
        break;          \
254
      if (__comp < 0){        \
255
        SPLAY_ROTATE_RIGHT(head, __tmp, field); \
256
        if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
257
          break;        \
258
      }           \
259
      SPLAY_LINKLEFT(head, __right, field);   \
260
    } else if (__comp > 0) {        \
261
      __tmp = SPLAY_RIGHT((head)->sph_root, field); \
262
      if (__tmp == NULL)        \
263
        break;          \
264
      if (__comp > 0) {       \
265
        SPLAY_ROTATE_LEFT(head, __tmp, field);  \
266
        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
267
          break;        \
268
      }           \
269
      SPLAY_LINKRIGHT(head, __left, field);   \
270
    }             \
271
  }               \
272
  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);    \
273
}
274
275
#define SPLAY_NEGINF  -1
276
#define SPLAY_INF 1
277
278
#define SPLAY_INSERT(name, x, y)  name##_SPLAY_INSERT(x, y)
279
#define SPLAY_REMOVE(name, x, y)  name##_SPLAY_REMOVE(x, y)
280
#define SPLAY_FIND(name, x, y)    name##_SPLAY_FIND(x, y)
281
#define SPLAY_NEXT(name, x, y)    name##_SPLAY_NEXT(x, y)
282
#define SPLAY_MIN(name, x)    (SPLAY_EMPTY(x) ? NULL  \
283
          : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
284
#define SPLAY_MAX(name, x)    (SPLAY_EMPTY(x) ? NULL  \
285
          : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
286
287
#define SPLAY_FOREACH(x, name, head)          \
288
  for ((x) = SPLAY_MIN(name, head);       \
289
       (x) != NULL;           \
290
       (x) = SPLAY_NEXT(name, head, x))
291
292
/* Macros that define a red-black tree */
293
#define RB_HEAD(name, type)           \
294
struct name {               \
295
  struct type *rbh_root; /* root of the tree */     \
296
}
297
298
#define RB_INITIALIZER(root)            \
299
  { NULL }
300
301
#define RB_INIT(root) do {            \
302
  (root)->rbh_root = NULL;          \
303
} while (0)
304
305
#define RB_BLACK  0
306
#define RB_RED    1
307
#define RB_ENTRY(type)              \
308
struct {                \
309
  struct type *rbe_left;    /* left element */    \
310
  struct type *rbe_right;   /* right element */   \
311
  struct type *rbe_parent;  /* parent element */    \
312
  int rbe_color;      /* node color */    \
313
}
314
315
#define RB_LEFT(elm, field)   (elm)->field.rbe_left
316
#define RB_RIGHT(elm, field)    (elm)->field.rbe_right
317
#define RB_PARENT(elm, field)   (elm)->field.rbe_parent
318
#define RB_COLOR(elm, field)    (elm)->field.rbe_color
319
#define RB_ROOT(head)     (head)->rbh_root
320
#define RB_EMPTY(head)      (RB_ROOT(head) == NULL)
321
322
#define RB_SET(elm, parent, field) do {         \
323
  RB_PARENT(elm, field) = parent;         \
324
  RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;    \
325
  RB_COLOR(elm, field) = RB_RED;          \
326
} while (0)
327
328
#define RB_SET_BLACKRED(black, red, field) do {       \
329
  RB_COLOR(black, field) = RB_BLACK;        \
330
  RB_COLOR(red, field) = RB_RED;          \
331
} while (0)
332
333
#ifndef RB_AUGMENT
334
#define RB_AUGMENT(x) do {} while (0)
335
#endif
336
337
#define RB_ROTATE_LEFT(head, elm, tmp, field) do {      \
338
  (tmp) = RB_RIGHT(elm, field);         \
339
  if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) {   \
340
    RB_PARENT(RB_LEFT(tmp, field), field) = (elm);    \
341
  }               \
342
  RB_AUGMENT(elm);            \
343
  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {    \
344
    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
345
      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
346
    else              \
347
      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
348
  } else                \
349
    (head)->rbh_root = (tmp);       \
350
  RB_LEFT(tmp, field) = (elm);          \
351
  RB_PARENT(elm, field) = (tmp);          \
352
  RB_AUGMENT(tmp);            \
353
  if ((RB_PARENT(tmp, field)))          \
354
    RB_AUGMENT(RB_PARENT(tmp, field));      \
355
} while (0)
356
357
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do {     \
358
  (tmp) = RB_LEFT(elm, field);          \
359
  if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) {   \
360
    RB_PARENT(RB_RIGHT(tmp, field), field) = (elm);   \
361
  }               \
362
  RB_AUGMENT(elm);            \
363
  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {    \
364
    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
365
      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
366
    else              \
367
      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
368
  } else                \
369
    (head)->rbh_root = (tmp);       \
370
  RB_RIGHT(tmp, field) = (elm);         \
371
  RB_PARENT(elm, field) = (tmp);          \
372
  RB_AUGMENT(tmp);            \
373
  if ((RB_PARENT(tmp, field)))          \
374
    RB_AUGMENT(RB_PARENT(tmp, field));      \
375
} while (0)
376
377
/* Generates prototypes and inline functions */
378
#define RB_PROTOTYPE(name, type, field, cmp)        \
379
  RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
380
#define RB_PROTOTYPE_STATIC(name, type, field, cmp)     \
381
  RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
382
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr)   \
383
attr void name##_RB_INSERT_COLOR(struct name *, struct type *);   \
384
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
385
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
386
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
387
attr struct type *name##_RB_FIND(struct name *, struct type *);   \
388
attr struct type *name##_RB_NFIND(struct name *, struct type *);  \
389
attr struct type *name##_RB_NEXT(struct type *);      \
390
attr struct type *name##_RB_PREV(struct type *);      \
391
attr struct type *name##_RB_MINMAX(struct name *, int);     \
392
                  \
393
394
/* Main rb operation.
395
 * Moves node close to the key of elm to top
396
 */
397
#define RB_GENERATE(name, type, field, cmp)       \
398
  RB_GENERATE_INTERNAL(name, type, field, cmp,)
399
#define RB_GENERATE_STATIC(name, type, field, cmp)      \
400
  RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
401
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr)    \
402
attr void               \
403
name##_RB_INSERT_COLOR(struct name *head, struct type *elm)   \
404
{                 \
405
  struct type *parent, *gparent, *tmp;        \
406
  while ((parent = RB_PARENT(elm, field)) &&      \
407
      RB_COLOR(parent, field) == RB_RED) {      \
408
    gparent = RB_PARENT(parent, field);     \
409
    if (parent == RB_LEFT(gparent, field)) {    \
410
      tmp = RB_RIGHT(gparent, field);     \
411
      if (tmp && RB_COLOR(tmp, field) == RB_RED) {  \
412
        RB_COLOR(tmp, field) = RB_BLACK;  \
413
        RB_SET_BLACKRED(parent, gparent, field);\
414
        elm = gparent;        \
415
        continue;       \
416
      }           \
417
      if (RB_RIGHT(parent, field) == elm) {   \
418
        RB_ROTATE_LEFT(head, parent, tmp, field);\
419
        tmp = parent;       \
420
        parent = elm;       \
421
        elm = tmp;        \
422
      }           \
423
      RB_SET_BLACKRED(parent, gparent, field);  \
424
      RB_ROTATE_RIGHT(head, gparent, tmp, field); \
425
    } else {            \
426
      tmp = RB_LEFT(gparent, field);      \
427
      if (tmp && RB_COLOR(tmp, field) == RB_RED) {  \
428
        RB_COLOR(tmp, field) = RB_BLACK;  \
429
        RB_SET_BLACKRED(parent, gparent, field);\
430
        elm = gparent;        \
431
        continue;       \
432
      }           \
433
      if (RB_LEFT(parent, field) == elm) {    \
434
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
435
        tmp = parent;       \
436
        parent = elm;       \
437
        elm = tmp;        \
438
      }           \
439
      RB_SET_BLACKRED(parent, gparent, field);  \
440
      RB_ROTATE_LEFT(head, gparent, tmp, field);  \
441
    }             \
442
  }               \
443
  RB_COLOR(head->rbh_root, field) = RB_BLACK;     \
444
}                 \
445
                  \
446
attr void               \
447
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
448
{                 \
449
  struct type *tmp;           \
450
  while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
451
      elm != RB_ROOT(head)) {         \
452
    if (RB_LEFT(parent, field) == elm) {      \
453
      tmp = RB_RIGHT(parent, field);      \
454
      if (RB_COLOR(tmp, field) == RB_RED) {   \
455
        RB_SET_BLACKRED(tmp, parent, field);  \
456
        RB_ROTATE_LEFT(head, parent, tmp, field);\
457
        tmp = RB_RIGHT(parent, field);    \
458
      }           \
459
      if ((RB_LEFT(tmp, field) == NULL ||   \
460
          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
461
          (RB_RIGHT(tmp, field) == NULL ||    \
462
          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
463
        RB_COLOR(tmp, field) = RB_RED;    \
464
        elm = parent;       \
465
        parent = RB_PARENT(elm, field);   \
466
      } else {          \
467
        if (RB_RIGHT(tmp, field) == NULL || \
468
            RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
469
          struct type *oleft;   \
470
          if ((oleft = RB_LEFT(tmp, field)))\
471
            RB_COLOR(oleft, field) = RB_BLACK;\
472
          RB_COLOR(tmp, field) = RB_RED;  \
473
          RB_ROTATE_RIGHT(head, tmp, oleft, field);\
474
          tmp = RB_RIGHT(parent, field);  \
475
        }         \
476
        RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
477
        RB_COLOR(parent, field) = RB_BLACK; \
478
        if (RB_RIGHT(tmp, field))   \
479
          RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
480
        RB_ROTATE_LEFT(head, parent, tmp, field);\
481
        elm = RB_ROOT(head);      \
482
        break;          \
483
      }           \
484
    } else {            \
485
      tmp = RB_LEFT(parent, field);     \
486
      if (RB_COLOR(tmp, field) == RB_RED) {   \
487
        RB_SET_BLACKRED(tmp, parent, field);  \
488
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
489
        tmp = RB_LEFT(parent, field);   \
490
      }           \
491
      if ((RB_LEFT(tmp, field) == NULL ||   \
492
          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
493
          (RB_RIGHT(tmp, field) == NULL ||    \
494
          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
495
        RB_COLOR(tmp, field) = RB_RED;    \
496
        elm = parent;       \
497
        parent = RB_PARENT(elm, field);   \
498
      } else {          \
499
        if (RB_LEFT(tmp, field) == NULL ||  \
500
            RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
501
          struct type *oright;    \
502
          if ((oright = RB_RIGHT(tmp, field)))\
503
            RB_COLOR(oright, field) = RB_BLACK;\
504
          RB_COLOR(tmp, field) = RB_RED;  \
505
          RB_ROTATE_LEFT(head, tmp, oright, field);\
506
          tmp = RB_LEFT(parent, field); \
507
        }         \
508
        RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
509
        RB_COLOR(parent, field) = RB_BLACK; \
510
        if (RB_LEFT(tmp, field))    \
511
          RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
512
        RB_ROTATE_RIGHT(head, parent, tmp, field);\
513
        elm = RB_ROOT(head);      \
514
        break;          \
515
      }           \
516
    }             \
517
  }               \
518
  if (elm)              \
519
    RB_COLOR(elm, field) = RB_BLACK;      \
520
}                 \
521
                  \
522
attr struct type *              \
523
name##_RB_REMOVE(struct name *head, struct type *elm)     \
524
{                 \
525
  struct type *child, *parent, *old = elm;      \
526
  int color;              \
527
  if (RB_LEFT(elm, field) == NULL)        \
528
    child = RB_RIGHT(elm, field);       \
529
  else if (RB_RIGHT(elm, field) == NULL)        \
530
    child = RB_LEFT(elm, field);        \
531
  else {                \
532
    struct type *left;          \
533
    elm = RB_RIGHT(elm, field);       \
534
    while ((left = RB_LEFT(elm, field)))      \
535
      elm = left;         \
536
    child = RB_RIGHT(elm, field);       \
537
    parent = RB_PARENT(elm, field);       \
538
    color = RB_COLOR(elm, field);       \
539
    if (child)            \
540
      RB_PARENT(child, field) = parent;   \
541
    if (parent) {           \
542
      if (RB_LEFT(parent, field) == elm)    \
543
        RB_LEFT(parent, field) = child;   \
544
      else            \
545
        RB_RIGHT(parent, field) = child;  \
546
      RB_AUGMENT(parent);       \
547
    } else              \
548
      RB_ROOT(head) = child;        \
549
    if (RB_PARENT(elm, field) == old)     \
550
      parent = elm;         \
551
    (elm)->field = (old)->field;        \
552
    if (RB_PARENT(old, field)) {        \
553
      if (RB_LEFT(RB_PARENT(old, field), field) == old)\
554
        RB_LEFT(RB_PARENT(old, field), field) = elm;\
555
      else            \
556
        RB_RIGHT(RB_PARENT(old, field), field) = elm;\
557
      RB_AUGMENT(RB_PARENT(old, field));    \
558
    } else              \
559
      RB_ROOT(head) = elm;        \
560
    RB_PARENT(RB_LEFT(old, field), field) = elm;    \
561
    if (RB_RIGHT(old, field))       \
562
      RB_PARENT(RB_RIGHT(old, field), field) = elm; \
563
    if (parent) {           \
564
      left = parent;          \
565
      do {            \
566
        RB_AUGMENT(left);     \
567
      } while ((left = RB_PARENT(left, field)));  \
568
    }             \
569
    goto color;           \
570
  }               \
571
  parent = RB_PARENT(elm, field);         \
572
  color = RB_COLOR(elm, field);         \
573
  if (child)              \
574
    RB_PARENT(child, field) = parent;     \
575
  if (parent) {             \
576
    if (RB_LEFT(parent, field) == elm)      \
577
      RB_LEFT(parent, field) = child;     \
578
    else              \
579
      RB_RIGHT(parent, field) = child;    \
580
    RB_AUGMENT(parent);         \
581
  } else                \
582
    RB_ROOT(head) = child;          \
583
color:                  \
584
  if (color == RB_BLACK)            \
585
    name##_RB_REMOVE_COLOR(head, parent, child);    \
586
  return (old);             \
587
}                 \
588
                  \
589
/* Inserts a node into the RB tree */         \
590
attr struct type *              \
591
name##_RB_INSERT(struct name *head, struct type *elm)     \
592
{                 \
593
  struct type *tmp;           \
594
  struct type *parent = NULL;         \
595
  int comp = 0;             \
596
  tmp = RB_ROOT(head);            \
597
  while (tmp) {             \
598
    parent = tmp;           \
599
    comp = (cmp)(elm, parent);        \
600
    if (comp < 0)           \
601
      tmp = RB_LEFT(tmp, field);      \
602
    else if (comp > 0)          \
603
      tmp = RB_RIGHT(tmp, field);     \
604
    else              \
605
      return (tmp);         \
606
  }               \
607
  RB_SET(elm, parent, field);         \
608
  if (parent != NULL) {           \
609
    if (comp < 0)           \
610
      RB_LEFT(parent, field) = elm;     \
611
    else              \
612
      RB_RIGHT(parent, field) = elm;      \
613
    RB_AUGMENT(parent);         \
614
  } else                \
615
    RB_ROOT(head) = elm;          \
616
  name##_RB_INSERT_COLOR(head, elm);        \
617
  return (NULL);              \
618
}                 \
619
                  \
620
/* Finds the node with the same key as elm */       \
621
attr struct type *              \
622
name##_RB_FIND(struct name *head, struct type *elm)     \
623
{                 \
624
  struct type *tmp = RB_ROOT(head);       \
625
  int comp;             \
626
  while (tmp) {             \
627
    comp = cmp(elm, tmp);         \
628
    if (comp < 0)           \
629
      tmp = RB_LEFT(tmp, field);      \
630
    else if (comp > 0)          \
631
      tmp = RB_RIGHT(tmp, field);     \
632
    else              \
633
      return (tmp);         \
634
  }               \
635
  return (NULL);              \
636
}                 \
637
                  \
638
/* Finds the first node greater than or equal to the search key */  \
639
attr struct type *              \
640
name##_RB_NFIND(struct name *head, struct type *elm)      \
641
{                 \
642
  struct type *tmp = RB_ROOT(head);       \
643
  struct type *res = NULL;          \
644
  int comp;             \
645
  while (tmp) {             \
646
    comp = cmp(elm, tmp);         \
647
    if (comp < 0) {           \
648
      res = tmp;          \
649
      tmp = RB_LEFT(tmp, field);      \
650
    }             \
651
    else if (comp > 0)          \
652
      tmp = RB_RIGHT(tmp, field);     \
653
    else              \
654
      return (tmp);         \
655
  }               \
656
  return (res);             \
657
}                 \
658
                  \
659
attr struct type *              \
660
name##_RB_NEXT(struct type *elm)          \
661
{                 \
662
  if (RB_RIGHT(elm, field)) {         \
663
    elm = RB_RIGHT(elm, field);       \
664
    while (RB_LEFT(elm, field))       \
665
      elm = RB_LEFT(elm, field);      \
666
  } else {              \
667
    if (RB_PARENT(elm, field) &&        \
668
        (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
669
      elm = RB_PARENT(elm, field);      \
670
    else {              \
671
      while (RB_PARENT(elm, field) &&     \
672
          (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
673
        elm = RB_PARENT(elm, field);    \
674
      elm = RB_PARENT(elm, field);      \
675
    }             \
676
  }               \
677
  return (elm);             \
678
}                 \
679
                  \
680
attr struct type *              \
681
name##_RB_PREV(struct type *elm)          \
682
{                 \
683
  if (RB_LEFT(elm, field)) {          \
684
    elm = RB_LEFT(elm, field);        \
685
    while (RB_RIGHT(elm, field))        \
686
      elm = RB_RIGHT(elm, field);     \
687
  } else {              \
688
    if (RB_PARENT(elm, field) &&        \
689
        (elm == RB_RIGHT(RB_PARENT(elm, field), field)))  \
690
      elm = RB_PARENT(elm, field);      \
691
    else {              \
692
      while (RB_PARENT(elm, field) &&     \
693
          (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
694
        elm = RB_PARENT(elm, field);    \
695
      elm = RB_PARENT(elm, field);      \
696
    }             \
697
  }               \
698
  return (elm);             \
699
}                 \
700
                  \
701
attr struct type *              \
702
name##_RB_MINMAX(struct name *head, int val)        \
703
{                 \
704
  struct type *tmp = RB_ROOT(head);       \
705
  struct type *parent = NULL;         \
706
  while (tmp) {             \
707
    parent = tmp;           \
708
    if (val < 0)            \
709
      tmp = RB_LEFT(tmp, field);      \
710
    else              \
711
      tmp = RB_RIGHT(tmp, field);     \
712
  }               \
713
  return (parent);            \
714
}
715
716
#define RB_NEGINF -1
717
#define RB_INF  1
718
719
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
720
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
721
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
722
#define RB_NFIND(name, x, y)  name##_RB_NFIND(x, y)
723
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
724
#define RB_PREV(name, x, y) name##_RB_PREV(y)
725
#define RB_MIN(name, x)   name##_RB_MINMAX(x, RB_NEGINF)
726
#define RB_MAX(name, x)   name##_RB_MINMAX(x, RB_INF)
727
728
#define RB_FOREACH(x, name, head)         \
729
  for ((x) = RB_MIN(name, head);          \
730
       (x) != NULL;           \
731
       (x) = name##_RB_NEXT(x))
732
733
#define RB_FOREACH_SAFE(x, name, head, y)       \
734
  for ((x) = RB_MIN(name, head);          \
735
      ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1);    \
736
       (x) = (y))
737
738
#define RB_FOREACH_REVERSE(x, name, head)       \
739
  for ((x) = RB_MAX(name, head);          \
740
       (x) != NULL;           \
741
       (x) = name##_RB_PREV(x))
742
743
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y)     \
744
  for ((x) = RB_MAX(name, head);          \
745
      ((x) != NULL) && ((y) = name##_RB_PREV(x), 1);    \
746
       (x) = (y))
747
748
749
/*
750
 * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
751
 *
752
 * Permission to use, copy, modify, and distribute this software for any
753
 * purpose with or without fee is hereby granted, provided that the above
754
 * copyright notice and this permission notice appear in all copies.
755
 *
756
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
757
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
758
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
759
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
760
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
761
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
762
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
763
 */
764
765
struct rb_type {
766
  int   (*t_compare)(const void *, const void *);
767
  void    (*t_augment)(void *);
768
  unsigned int    t_offset; /* offset of rb_entry in type */
769
};
770
771
struct rb_tree {
772
  struct rb_entry *rbt_root;
773
};
774
775
struct rb_entry {
776
  struct rb_entry  *rbt_parent;
777
  struct rb_entry  *rbt_left;
778
  struct rb_entry  *rbt_right;
779
  unsigned int    rbt_color;
780
};
781
782
#define RBT_HEAD(_name, _type)            \
783
struct _name {                \
784
  struct rb_tree rbh_root;          \
785
}
786
787
#define RBT_ENTRY(_type)  struct rb_entry
788
789
static inline void
790
_rb_init(struct rb_tree *rbt)
791
0
{
792
0
  rbt->rbt_root = NULL;
793
0
}
Unexecuted instantiation: common.c:_rb_init
Unexecuted instantiation: test_parser_fuzz.c:_rb_init
Unexecuted instantiation: ikev2_pld.c:_rb_init
Unexecuted instantiation: imsg_util.c:_rb_init
Unexecuted instantiation: util.c:_rb_init
794
795
static inline int
796
_rb_empty(struct rb_tree *rbt)
797
0
{
798
0
  return (rbt->rbt_root == NULL);
799
0
}
Unexecuted instantiation: common.c:_rb_empty
Unexecuted instantiation: test_parser_fuzz.c:_rb_empty
Unexecuted instantiation: ikev2_pld.c:_rb_empty
Unexecuted instantiation: imsg_util.c:_rb_empty
Unexecuted instantiation: util.c:_rb_empty
800
801
void  *_rb_insert(const struct rb_type *, struct rb_tree *, void *);
802
void  *_rb_remove(const struct rb_type *, struct rb_tree *, void *);
803
void  *_rb_find(const struct rb_type *, struct rb_tree *, const void *);
804
void  *_rb_nfind(const struct rb_type *, struct rb_tree *, const void *);
805
void  *_rb_root(const struct rb_type *, struct rb_tree *);
806
void  *_rb_min(const struct rb_type *, struct rb_tree *);
807
void  *_rb_max(const struct rb_type *, struct rb_tree *);
808
void  *_rb_next(const struct rb_type *, void *);
809
void  *_rb_prev(const struct rb_type *, void *);
810
void  *_rb_left(const struct rb_type *, void *);
811
void  *_rb_right(const struct rb_type *, void *);
812
void  *_rb_parent(const struct rb_type *, void *);
813
void   _rb_set_left(const struct rb_type *, void *, void *);
814
void   _rb_set_right(const struct rb_type *, void *, void *);
815
void   _rb_set_parent(const struct rb_type *, void *, void *);
816
void   _rb_poison(const struct rb_type *, void *, unsigned long);
817
int  _rb_check(const struct rb_type *, void *, unsigned long);
818
819
#define RBT_INITIALIZER(_head)  { { NULL } }
820
821
#define RBT_PROTOTYPE(_name, _type, _field, _cmp)     \
822
extern const struct rb_type *const _name##_RBT_TYPE;      \
823
                  \
824
__unused static inline void           \
825
_name##_RBT_INIT(struct _name *head)          \
826
{                 \
827
  _rb_init(&head->rbh_root);          \
828
}                 \
829
                  \
830
__unused static inline struct _type *         \
831
_name##_RBT_INSERT(struct _name *head, struct _type *elm)   \
832
{                 \
833
  return _rb_insert(_name##_RBT_TYPE, &head->rbh_root, elm);  \
834
}                 \
835
                  \
836
__unused static inline struct _type *         \
837
_name##_RBT_REMOVE(struct _name *head, struct _type *elm)   \
838
{                 \
839
  return _rb_remove(_name##_RBT_TYPE, &head->rbh_root, elm);  \
840
}                 \
841
                  \
842
__unused static inline struct _type *         \
843
_name##_RBT_FIND(struct _name *head, const struct _type *key)   \
844
{                 \
845
  return _rb_find(_name##_RBT_TYPE, &head->rbh_root, key);  \
846
}                 \
847
                  \
848
__unused static inline struct _type *         \
849
_name##_RBT_NFIND(struct _name *head, const struct _type *key)    \
850
{                 \
851
  return _rb_nfind(_name##_RBT_TYPE, &head->rbh_root, key); \
852
}                 \
853
                  \
854
__unused static inline struct _type *         \
855
_name##_RBT_ROOT(struct _name *head)          \
856
{                 \
857
  return _rb_root(_name##_RBT_TYPE, &head->rbh_root);   \
858
}                 \
859
                  \
860
__unused static inline int            \
861
_name##_RBT_EMPTY(struct _name *head)         \
862
{                 \
863
  return _rb_empty(&head->rbh_root);        \
864
}                 \
865
                  \
866
__unused static inline struct _type *         \
867
_name##_RBT_MIN(struct _name *head)         \
868
{                 \
869
  return _rb_min(_name##_RBT_TYPE, &head->rbh_root);    \
870
}                 \
871
                  \
872
__unused static inline struct _type *         \
873
_name##_RBT_MAX(struct _name *head)         \
874
{                 \
875
  return _rb_max(_name##_RBT_TYPE, &head->rbh_root);    \
876
}                 \
877
                  \
878
__unused static inline struct _type *         \
879
_name##_RBT_NEXT(struct _type *elm)         \
880
{                 \
881
  return _rb_next(_name##_RBT_TYPE, elm);       \
882
}                 \
883
                  \
884
__unused static inline struct _type *         \
885
_name##_RBT_PREV(struct _type *elm)         \
886
{                 \
887
  return _rb_prev(_name##_RBT_TYPE, elm);       \
888
}                 \
889
                  \
890
__unused static inline struct _type *         \
891
_name##_RBT_LEFT(struct _type *elm)         \
892
{                 \
893
  return _rb_left(_name##_RBT_TYPE, elm);       \
894
}                 \
895
                  \
896
__unused static inline struct _type *         \
897
_name##_RBT_RIGHT(struct _type *elm)          \
898
{                 \
899
  return _rb_right(_name##_RBT_TYPE, elm);      \
900
}                 \
901
                  \
902
__unused static inline struct _type *         \
903
_name##_RBT_PARENT(struct _type *elm)         \
904
{                 \
905
  return _rb_parent(_name##_RBT_TYPE, elm);     \
906
}                 \
907
                  \
908
__unused static inline void           \
909
_name##_RBT_SET_LEFT(struct _type *elm, struct _type *left)   \
910
{                 \
911
  _rb_set_left(_name##_RBT_TYPE, elm, left);      \
912
}                 \
913
                  \
914
__unused static inline void           \
915
_name##_RBT_SET_RIGHT(struct _type *elm, struct _type *right)   \
916
{                 \
917
  _rb_set_right(_name##_RBT_TYPE, elm, right);      \
918
}                 \
919
                  \
920
__unused static inline void           \
921
_name##_RBT_SET_PARENT(struct _type *elm, struct _type *parent)   \
922
{                 \
923
  _rb_set_parent(_name##_RBT_TYPE, elm, parent);      \
924
}                 \
925
                  \
926
__unused static inline void           \
927
_name##_RBT_POISON(struct _type *elm, unsigned long poison)   \
928
{                 \
929
  _rb_poison(_name##_RBT_TYPE, elm, poison);      \
930
}                 \
931
                  \
932
__unused static inline int            \
933
_name##_RBT_CHECK(struct _type *elm, unsigned long poison)    \
934
{                 \
935
  return _rb_check(_name##_RBT_TYPE, elm, poison);    \
936
}
937
938
#define RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug)   \
939
static int                \
940
_name##_RBT_COMPARE(const void *lptr, const void *rptr)     \
941
{                 \
942
  const struct _type *l = lptr, *r = rptr;      \
943
  return _cmp(l, r);            \
944
}                 \
945
static const struct rb_type _name##_RBT_INFO = {      \
946
  _name##_RBT_COMPARE,            \
947
  _aug,               \
948
  offsetof(struct _type, _field),         \
949
};                  \
950
const struct rb_type *const _name##_RBT_TYPE = &_name##_RBT_INFO
951
952
#define RBT_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug)    \
953
static void               \
954
_name##_RBT_AUGMENT(void *ptr)            \
955
{                 \
956
  struct _type *p = ptr;            \
957
  return _aug(p);             \
958
}                 \
959
RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RBT_AUGMENT)
960
961
#define RBT_GENERATE(_name, _type, _field, _cmp)      \
962
    RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL)
963
964
#define RBT_INIT(_name, _head)    _name##_RBT_INIT(_head)
965
#define RBT_INSERT(_name, _head, _elm)  _name##_RBT_INSERT(_head, _elm)
966
#define RBT_REMOVE(_name, _head, _elm)  _name##_RBT_REMOVE(_head, _elm)
967
#define RBT_FIND(_name, _head, _key)  _name##_RBT_FIND(_head, _key)
968
#define RBT_NFIND(_name, _head, _key) _name##_RBT_NFIND(_head, _key)
969
#define RBT_ROOT(_name, _head)    _name##_RBT_ROOT(_head)
970
#define RBT_EMPTY(_name, _head)   _name##_RBT_EMPTY(_head)
971
#define RBT_MIN(_name, _head)   _name##_RBT_MIN(_head)
972
#define RBT_MAX(_name, _head)   _name##_RBT_MAX(_head)
973
#define RBT_NEXT(_name, _elm)   _name##_RBT_NEXT(_elm)
974
#define RBT_PREV(_name, _elm)   _name##_RBT_PREV(_elm)
975
#define RBT_LEFT(_name, _elm)   _name##_RBT_LEFT(_elm)
976
#define RBT_RIGHT(_name, _elm)    _name##_RBT_RIGHT(_elm)
977
#define RBT_PARENT(_name, _elm)   _name##_RBT_PARENT(_elm)
978
#define RBT_SET_LEFT(_name, _elm, _l) _name##_RBT_SET_LEFT(_elm, _l)
979
#define RBT_SET_RIGHT(_name, _elm, _r)  _name##_RBT_SET_RIGHT(_elm, _r)
980
#define RBT_SET_PARENT(_name, _elm, _p) _name##_RBT_SET_PARENT(_elm, _p)
981
#define RBT_POISON(_name, _elm, _p) _name##_RBT_POISON(_elm, _p)
982
#define RBT_CHECK(_name, _elm, _p)  _name##_RBT_CHECK(_elm, _p)
983
984
#define RBT_FOREACH(_e, _name, _head)         \
985
  for ((_e) = RBT_MIN(_name, (_head));        \
986
       (_e) != NULL;            \
987
       (_e) = RBT_NEXT(_name, (_e)))
988
989
#define RBT_FOREACH_SAFE(_e, _name, _head, _n)        \
990
  for ((_e) = RBT_MIN(_name, (_head));        \
991
       (_e) != NULL && ((_n) = RBT_NEXT(_name, (_e)), 1); \
992
       (_e) = (_n))
993
994
#define RBT_FOREACH_REVERSE(_e, _name, _head)       \
995
  for ((_e) = RBT_MAX(_name, (_head));        \
996
       (_e) != NULL;            \
997
       (_e) = RBT_PREV(_name, (_e)))
998
999
#define RBT_FOREACH_REVERSE_SAFE(_e, _name, _head, _n)      \
1000
  for ((_e) = RBT_MAX(_name, (_head));        \
1001
       (_e) != NULL && ((_n) = RBT_PREV(_name, (_e)), 1); \
1002
       (_e) = (_n))
1003
1004
#endif  /* _SYS_TREE_H_ */
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/vis.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/vis.c.html index 2390311e2..89b461bcf 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/vis.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/vis.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/vis.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: vis.c,v 1.26 2022/05/04 18:57:50 deraadt Exp $ */
2
/*-
3
 * Copyright (c) 1989, 1993
4
 *  The Regents of the University of California.  All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 3. Neither the name of the University nor the names of its contributors
15
 *    may be used to endorse or promote products derived from this software
16
 *    without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
/* OPENBSD ORIGINAL: lib/libc/gen/vis.c */
32
33
#if !defined(HAVE_STRNVIS)
34
35
#include <sys/types.h>
36
#include <errno.h>
37
#include <ctype.h>
38
#include <limits.h>
39
#include <string.h>
40
#include <stdlib.h>
41
#include <vis.h>
42
43
static int
44
isoctal(int c)
45
0
{
46
0
  u_char uc = c;
47
48
0
  return uc >= '0' && uc <= '7';
49
0
}
50
51
static int
52
isvisible(int c, int flag)
53
0
{
54
0
  int vis_sp = flag & VIS_SP;
55
0
  int vis_tab = flag & VIS_TAB;
56
0
  int vis_nl = flag & VIS_NL;
57
0
  int vis_safe = flag & VIS_SAFE;
58
0
  int vis_glob = flag & VIS_GLOB;
59
0
  int vis_all = flag & VIS_ALL;
60
0
  u_char uc = c;
61
62
0
  if (c == '\\' || !vis_all) {
63
0
    if ((u_int)c <= UCHAR_MAX && isascii(uc) &&
64
0
        ((c != '*' && c != '?' && c != '[' && c != '#') || !vis_glob) &&
65
0
        isgraph(uc))
66
0
      return 1;
67
0
    if (!vis_sp && c == ' ')
68
0
      return 1;
69
0
    if (!vis_tab && c == '\t')
70
0
      return 1;
71
0
    if (!vis_nl && c == '\n')
72
0
      return 1;
73
0
    if (vis_safe && (c == '\b' || c == '\007' || c == '\r' || isgraph(uc)))
74
0
      return 1;
75
0
  }
76
0
  return 0;
77
0
}
78
79
/*
80
 * vis - visually encode characters
81
 */
82
char *
83
vis(char *dst, int c, int flag, int nextc)
84
0
{
85
0
  int vis_dq = flag & VIS_DQ;
86
0
  int vis_noslash = flag & VIS_NOSLASH;
87
0
  int vis_cstyle = flag & VIS_CSTYLE;
88
0
  int vis_octal = flag & VIS_OCTAL;
89
0
  int vis_glob = flag & VIS_GLOB;
90
91
0
  if (isvisible(c, flag)) {
92
0
    if ((c == '"' && vis_dq) ||
93
0
        (c == '\\' && !vis_noslash))
94
0
      *dst++ = '\\';
95
0
    *dst++ = c;
96
0
    *dst = '\0';
97
0
    return (dst);
98
0
  }
99
100
0
  if (vis_cstyle) {
101
0
    switch (c) {
102
0
    case '\n':
103
0
      *dst++ = '\\';
104
0
      *dst++ = 'n';
105
0
      goto done;
106
0
    case '\r':
107
0
      *dst++ = '\\';
108
0
      *dst++ = 'r';
109
0
      goto done;
110
0
    case '\b':
111
0
      *dst++ = '\\';
112
0
      *dst++ = 'b';
113
0
      goto done;
114
0
    case '\a':
115
0
      *dst++ = '\\';
116
0
      *dst++ = 'a';
117
0
      goto done;
118
0
    case '\v':
119
0
      *dst++ = '\\';
120
0
      *dst++ = 'v';
121
0
      goto done;
122
0
    case '\t':
123
0
      *dst++ = '\\';
124
0
      *dst++ = 't';
125
0
      goto done;
126
0
    case '\f':
127
0
      *dst++ = '\\';
128
0
      *dst++ = 'f';
129
0
      goto done;
130
0
    case ' ':
131
0
      *dst++ = '\\';
132
0
      *dst++ = 's';
133
0
      goto done;
134
0
    case '\0':
135
0
      *dst++ = '\\';
136
0
      *dst++ = '0';
137
0
      if (isoctal(nextc)) {
138
0
        *dst++ = '0';
139
0
        *dst++ = '0';
140
0
      }
141
0
      goto done;
142
0
    }
143
0
  }
144
0
  if (((c & 0177) == ' ') || vis_octal ||
145
0
      (vis_glob && (c == '*' || c == '?' || c == '[' || c == '#'))) {
146
0
    *dst++ = '\\';
147
0
    *dst++ = ((u_char)c >> 6 & 07) + '0';
148
0
    *dst++ = ((u_char)c >> 3 & 07) + '0';
149
0
    *dst++ = ((u_char)c & 07) + '0';
150
0
    goto done;
151
0
  }
152
0
  if (!vis_noslash)
153
0
    *dst++ = '\\';
154
0
  if (c & 0200) {
155
0
    c &= 0177;
156
0
    *dst++ = 'M';
157
0
  }
158
0
  if (iscntrl((u_char)c)) {
159
0
    *dst++ = '^';
160
0
    if (c == 0177)
161
0
      *dst++ = '?';
162
0
    else
163
0
      *dst++ = c + '@';
164
0
  } else {
165
0
    *dst++ = '-';
166
0
    *dst++ = c;
167
0
  }
168
0
done:
169
0
  *dst = '\0';
170
0
  return (dst);
171
0
}
172
173
/*
174
 * strvis, strnvis, strvisx - visually encode characters from src into dst
175
 *  
176
 *  Dst must be 4 times the size of src to account for possible
177
 *  expansion.  The length of dst, not including the trailing NULL,
178
 *  is returned. 
179
 *
180
 *  Strnvis will write no more than siz-1 bytes (and will NULL terminate).
181
 *  The number of bytes needed to fully encode the string is returned.
182
 *
183
 *  Strvisx encodes exactly len bytes from src into dst.
184
 *  This is useful for encoding a block of data.
185
 */
186
int
187
strvis(char *dst, const char *src, int flag)
188
0
{
189
0
  char c;
190
0
  char *start;
191
192
0
  for (start = dst; (c = *src);)
193
0
    dst = vis(dst, c, flag, *++src);
194
0
  *dst = '\0';
195
0
  return (dst - start);
196
0
}
197
198
int
199
strnvis(char *dst, const char *src, size_t siz, int flag)
200
0
{
201
0
  int vis_dq = flag & VIS_DQ;
202
0
  int vis_noslash = flag & VIS_NOSLASH;
203
0
  char *start, *end;
204
0
  char tbuf[5];
205
0
  int c, i;
206
207
0
  i = 0;
208
0
  for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
209
0
    if (isvisible(c, flag)) {
210
0
      if ((c == '"' && vis_dq) ||
211
0
          (c == '\\' && !vis_noslash)) {
212
        /* need space for the extra '\\' */
213
0
        if (dst + 1 >= end) {
214
0
          i = 2;
215
0
          break;
216
0
        }
217
0
        *dst++ = '\\';
218
0
      }
219
0
      i = 1;
220
0
      *dst++ = c;
221
0
      src++;
222
0
    } else {
223
0
      i = vis(tbuf, c, flag, *++src) - tbuf;
224
0
      if (dst + i <= end) {
225
0
        memcpy(dst, tbuf, i);
226
0
        dst += i;
227
0
      } else {
228
0
        src--;
229
0
        break;
230
0
      }
231
0
    }
232
0
  }
233
0
  if (siz > 0)
234
0
    *dst = '\0';
235
0
  if (dst + i > end) {
236
    /* adjust return value for truncation */
237
0
    while ((c = *src))
238
0
      dst += vis(tbuf, c, flag, *++src) - tbuf;
239
0
  }
240
0
  return (dst - start);
241
0
}
242
243
int
244
stravis(char **outp, const char *src, int flag)
245
0
{
246
0
  char *buf;
247
0
  int len, serrno;
248
249
0
  buf = reallocarray(NULL, 4, strlen(src) + 1);
250
0
  if (buf == NULL)
251
0
    return -1;
252
0
  len = strvis(buf, src, flag);
253
0
  serrno = errno;
254
0
  *outp = realloc(buf, len + 1);
255
0
  if (*outp == NULL) {
256
0
    *outp = buf;
257
0
    errno = serrno;
258
0
  }
259
0
  return (len);
260
0
}
261
262
int
263
strvisx(char *dst, const char *src, size_t len, int flag)
264
0
{
265
0
  char c;
266
0
  char *start;
267
268
0
  for (start = dst; len > 1; len--) {
269
0
    c = *src;
270
0
    dst = vis(dst, c, flag, *++src);
271
0
  }
272
0
  if (len)
273
0
    dst = vis(dst, *src, flag, '\0');
274
0
  *dst = '\0';
275
0
  return (dst - start);
276
0
}
277
278
#endif
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/vis.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: vis.c,v 1.26 2022/05/04 18:57:50 deraadt Exp $ */
2
/*-
3
 * Copyright (c) 1989, 1993
4
 *  The Regents of the University of California.  All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 3. Neither the name of the University nor the names of its contributors
15
 *    may be used to endorse or promote products derived from this software
16
 *    without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
/* OPENBSD ORIGINAL: lib/libc/gen/vis.c */
32
33
#if !defined(HAVE_STRNVIS)
34
35
#include <sys/types.h>
36
#include <errno.h>
37
#include <ctype.h>
38
#include <limits.h>
39
#include <string.h>
40
#include <stdlib.h>
41
#include <vis.h>
42
43
static int
44
isoctal(int c)
45
0
{
46
0
  u_char uc = c;
47
48
0
  return uc >= '0' && uc <= '7';
49
0
}
50
51
static int
52
isvisible(int c, int flag)
53
0
{
54
0
  int vis_sp = flag & VIS_SP;
55
0
  int vis_tab = flag & VIS_TAB;
56
0
  int vis_nl = flag & VIS_NL;
57
0
  int vis_safe = flag & VIS_SAFE;
58
0
  int vis_glob = flag & VIS_GLOB;
59
0
  int vis_all = flag & VIS_ALL;
60
0
  u_char uc = c;
61
62
0
  if (c == '\\' || !vis_all) {
63
0
    if ((u_int)c <= UCHAR_MAX && isascii(uc) &&
64
0
        ((c != '*' && c != '?' && c != '[' && c != '#') || !vis_glob) &&
65
0
        isgraph(uc))
66
0
      return 1;
67
0
    if (!vis_sp && c == ' ')
68
0
      return 1;
69
0
    if (!vis_tab && c == '\t')
70
0
      return 1;
71
0
    if (!vis_nl && c == '\n')
72
0
      return 1;
73
0
    if (vis_safe && (c == '\b' || c == '\007' || c == '\r' || isgraph(uc)))
74
0
      return 1;
75
0
  }
76
0
  return 0;
77
0
}
78
79
/*
80
 * vis - visually encode characters
81
 */
82
char *
83
vis(char *dst, int c, int flag, int nextc)
84
0
{
85
0
  int vis_dq = flag & VIS_DQ;
86
0
  int vis_noslash = flag & VIS_NOSLASH;
87
0
  int vis_cstyle = flag & VIS_CSTYLE;
88
0
  int vis_octal = flag & VIS_OCTAL;
89
0
  int vis_glob = flag & VIS_GLOB;
90
91
0
  if (isvisible(c, flag)) {
92
0
    if ((c == '"' && vis_dq) ||
93
0
        (c == '\\' && !vis_noslash))
94
0
      *dst++ = '\\';
95
0
    *dst++ = c;
96
0
    *dst = '\0';
97
0
    return (dst);
98
0
  }
99
100
0
  if (vis_cstyle) {
101
0
    switch (c) {
102
0
    case '\n':
103
0
      *dst++ = '\\';
104
0
      *dst++ = 'n';
105
0
      goto done;
106
0
    case '\r':
107
0
      *dst++ = '\\';
108
0
      *dst++ = 'r';
109
0
      goto done;
110
0
    case '\b':
111
0
      *dst++ = '\\';
112
0
      *dst++ = 'b';
113
0
      goto done;
114
0
    case '\a':
115
0
      *dst++ = '\\';
116
0
      *dst++ = 'a';
117
0
      goto done;
118
0
    case '\v':
119
0
      *dst++ = '\\';
120
0
      *dst++ = 'v';
121
0
      goto done;
122
0
    case '\t':
123
0
      *dst++ = '\\';
124
0
      *dst++ = 't';
125
0
      goto done;
126
0
    case '\f':
127
0
      *dst++ = '\\';
128
0
      *dst++ = 'f';
129
0
      goto done;
130
0
    case ' ':
131
0
      *dst++ = '\\';
132
0
      *dst++ = 's';
133
0
      goto done;
134
0
    case '\0':
135
0
      *dst++ = '\\';
136
0
      *dst++ = '0';
137
0
      if (isoctal(nextc)) {
138
0
        *dst++ = '0';
139
0
        *dst++ = '0';
140
0
      }
141
0
      goto done;
142
0
    }
143
0
  }
144
0
  if (((c & 0177) == ' ') || vis_octal ||
145
0
      (vis_glob && (c == '*' || c == '?' || c == '[' || c == '#'))) {
146
0
    *dst++ = '\\';
147
0
    *dst++ = ((u_char)c >> 6 & 07) + '0';
148
0
    *dst++ = ((u_char)c >> 3 & 07) + '0';
149
0
    *dst++ = ((u_char)c & 07) + '0';
150
0
    goto done;
151
0
  }
152
0
  if (!vis_noslash)
153
0
    *dst++ = '\\';
154
0
  if (c & 0200) {
155
0
    c &= 0177;
156
0
    *dst++ = 'M';
157
0
  }
158
0
  if (iscntrl((u_char)c)) {
159
0
    *dst++ = '^';
160
0
    if (c == 0177)
161
0
      *dst++ = '?';
162
0
    else
163
0
      *dst++ = c + '@';
164
0
  } else {
165
0
    *dst++ = '-';
166
0
    *dst++ = c;
167
0
  }
168
0
done:
169
0
  *dst = '\0';
170
0
  return (dst);
171
0
}
172
173
/*
174
 * strvis, strnvis, strvisx - visually encode characters from src into dst
175
 *  
176
 *  Dst must be 4 times the size of src to account for possible
177
 *  expansion.  The length of dst, not including the trailing NULL,
178
 *  is returned. 
179
 *
180
 *  Strnvis will write no more than siz-1 bytes (and will NULL terminate).
181
 *  The number of bytes needed to fully encode the string is returned.
182
 *
183
 *  Strvisx encodes exactly len bytes from src into dst.
184
 *  This is useful for encoding a block of data.
185
 */
186
int
187
strvis(char *dst, const char *src, int flag)
188
0
{
189
0
  char c;
190
0
  char *start;
191
192
0
  for (start = dst; (c = *src);)
193
0
    dst = vis(dst, c, flag, *++src);
194
0
  *dst = '\0';
195
0
  return (dst - start);
196
0
}
197
198
int
199
strnvis(char *dst, const char *src, size_t siz, int flag)
200
0
{
201
0
  int vis_dq = flag & VIS_DQ;
202
0
  int vis_noslash = flag & VIS_NOSLASH;
203
0
  char *start, *end;
204
0
  char tbuf[5];
205
0
  int c, i;
206
207
0
  i = 0;
208
0
  for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
209
0
    if (isvisible(c, flag)) {
210
0
      if ((c == '"' && vis_dq) ||
211
0
          (c == '\\' && !vis_noslash)) {
212
        /* need space for the extra '\\' */
213
0
        if (dst + 1 >= end) {
214
0
          i = 2;
215
0
          break;
216
0
        }
217
0
        *dst++ = '\\';
218
0
      }
219
0
      i = 1;
220
0
      *dst++ = c;
221
0
      src++;
222
0
    } else {
223
0
      i = vis(tbuf, c, flag, *++src) - tbuf;
224
0
      if (dst + i <= end) {
225
0
        memcpy(dst, tbuf, i);
226
0
        dst += i;
227
0
      } else {
228
0
        src--;
229
0
        break;
230
0
      }
231
0
    }
232
0
  }
233
0
  if (siz > 0)
234
0
    *dst = '\0';
235
0
  if (dst + i > end) {
236
    /* adjust return value for truncation */
237
0
    while ((c = *src))
238
0
      dst += vis(tbuf, c, flag, *++src) - tbuf;
239
0
  }
240
0
  return (dst - start);
241
0
}
242
243
int
244
stravis(char **outp, const char *src, int flag)
245
0
{
246
0
  char *buf;
247
0
  int len, serrno;
248
249
0
  buf = reallocarray(NULL, 4, strlen(src) + 1);
250
0
  if (buf == NULL)
251
0
    return -1;
252
0
  len = strvis(buf, src, flag);
253
0
  serrno = errno;
254
0
  *outp = realloc(buf, len + 1);
255
0
  if (*outp == NULL) {
256
0
    *outp = buf;
257
0
    errno = serrno;
258
0
  }
259
0
  return (len);
260
0
}
261
262
int
263
strvisx(char *dst, const char *src, size_t len, int flag)
264
0
{
265
0
  char c;
266
0
  char *start;
267
268
0
  for (start = dst; len > 1; len--) {
269
0
    c = *src;
270
0
    dst = vis(dst, c, flag, *++src);
271
0
  }
272
0
  if (len)
273
0
    dst = vis(dst, *src, flag, '\0');
274
0
  *dst = '\0';
275
0
  return (dst - start);
276
0
}
277
278
#endif
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/vis.h.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/vis.h.html index 670be8253..6a69d007d 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/vis.h.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/compat/vis.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/compat/vis.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: vis.h,v 1.15 2015/07/20 01:52:27 millert Exp $  */
2
/*  $NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $  */
3
4
/*-
5
 * Copyright (c) 1990 The Regents of the University of California.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 *
32
 *  @(#)vis.h 5.9 (Berkeley) 4/3/91
33
 */
34
35
/* OPENBSD ORIGINAL: include/vis.h */
36
37
#ifdef HAVE_CONFIG_H
38
#include "includes.h"
39
#endif
40
41
#ifndef _VIS_H_
42
#define _VIS_H_
43
44
#include <sys/types.h>
45
#include <limits.h>
46
47
/*
48
 * to select alternate encoding format
49
 */
50
0
#define VIS_OCTAL 0x01  /* use octal \ddd format */
51
0
#define VIS_CSTYLE  0x02  /* use \[nrft0..] where appropriate */
52
53
/*
54
 * to alter set of characters encoded (default is to encode all
55
 * non-graphic except space, tab, and newline).
56
 */
57
0
#define VIS_SP    0x04  /* also encode space */
58
0
#define VIS_TAB   0x08  /* also encode tab */
59
0
#define VIS_NL    0x10  /* also encode newline */
60
#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
61
0
#define VIS_SAFE  0x20  /* only encode "unsafe" characters */
62
0
#define VIS_DQ    0x200  /* backslash-escape double quotes */
63
0
#define VIS_ALL   0x400  /* encode all characters */
64
65
/*
66
 * other
67
 */
68
0
#define VIS_NOSLASH 0x40  /* inhibit printing '\' */
69
0
#define VIS_GLOB  0x100  /* encode glob(3) magics and '#' */
70
71
/*
72
 * unvis return codes
73
 */
74
#define UNVIS_VALID  1  /* character valid */
75
#define UNVIS_VALIDPUSH  2  /* character valid, push back passed char */
76
#define UNVIS_NOCHAR   3  /* valid sequence, no character produced */
77
#define UNVIS_SYNBAD  -1  /* unrecognized escape sequence */
78
#define UNVIS_ERROR -2  /* decoder in unknown state (unrecoverable) */
79
80
/*
81
 * unvis flags
82
 */
83
#define UNVIS_END 1 /* no more characters */
84
85
char  *vis(char *, int, int, int);
86
int strvis(char *, const char *, int);
87
int stravis(char **, const char *, int);
88
int strnvis(char *, const char *, size_t, int)
89
    __attribute__ ((__bounded__(__string__,1,3)));
90
int strvisx(char *, const char *, size_t, int)
91
    __attribute__ ((__bounded__(__string__,1,3)));
92
int strunvis(char *, const char *);
93
int unvis(char *, char, int *, int);
94
ssize_t strnunvis(char *, const char *, size_t)
95
    __attribute__ ((__bounded__(__string__,1,3)));
96
97
#endif /* !_VIS_H_ */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/compat/vis.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: vis.h,v 1.15 2015/07/20 01:52:27 millert Exp $  */
2
/*  $NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $  */
3
4
/*-
5
 * Copyright (c) 1990 The Regents of the University of California.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 *
32
 *  @(#)vis.h 5.9 (Berkeley) 4/3/91
33
 */
34
35
/* OPENBSD ORIGINAL: include/vis.h */
36
37
#ifdef HAVE_CONFIG_H
38
#include "includes.h"
39
#endif
40
41
#ifndef _VIS_H_
42
#define _VIS_H_
43
44
#include <sys/types.h>
45
#include <limits.h>
46
47
/*
48
 * to select alternate encoding format
49
 */
50
0
#define VIS_OCTAL 0x01  /* use octal \ddd format */
51
0
#define VIS_CSTYLE  0x02  /* use \[nrft0..] where appropriate */
52
53
/*
54
 * to alter set of characters encoded (default is to encode all
55
 * non-graphic except space, tab, and newline).
56
 */
57
0
#define VIS_SP    0x04  /* also encode space */
58
0
#define VIS_TAB   0x08  /* also encode tab */
59
0
#define VIS_NL    0x10  /* also encode newline */
60
#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
61
0
#define VIS_SAFE  0x20  /* only encode "unsafe" characters */
62
0
#define VIS_DQ    0x200  /* backslash-escape double quotes */
63
0
#define VIS_ALL   0x400  /* encode all characters */
64
65
/*
66
 * other
67
 */
68
0
#define VIS_NOSLASH 0x40  /* inhibit printing '\' */
69
0
#define VIS_GLOB  0x100  /* encode glob(3) magics and '#' */
70
71
/*
72
 * unvis return codes
73
 */
74
#define UNVIS_VALID  1  /* character valid */
75
#define UNVIS_VALIDPUSH  2  /* character valid, push back passed char */
76
#define UNVIS_NOCHAR   3  /* valid sequence, no character produced */
77
#define UNVIS_SYNBAD  -1  /* unrecognized escape sequence */
78
#define UNVIS_ERROR -2  /* decoder in unknown state (unrecoverable) */
79
80
/*
81
 * unvis flags
82
 */
83
#define UNVIS_END 1 /* no more characters */
84
85
char  *vis(char *, int, int, int);
86
int strvis(char *, const char *, int);
87
int stravis(char **, const char *, int);
88
int strnvis(char *, const char *, size_t, int)
89
    __attribute__ ((__bounded__(__string__,1,3)));
90
int strvisx(char *, const char *, size_t, int)
91
    __attribute__ ((__bounded__(__string__,1,3)));
92
int strunvis(char *, const char *);
93
int unvis(char *, char, int *, int);
94
ssize_t strnunvis(char *, const char *, size_t)
95
    __attribute__ ((__bounded__(__string__,1,3)));
96
97
#endif /* !_VIS_H_ */
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/iked.h.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/iked.h.html index 7f5db007b..d28a3fc8c 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/iked.h.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/iked.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/iked.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: iked.h,v 1.224 2023/08/11 11:24:55 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019-2021 Tobias Heider <tobhe@openbsd.org>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/tree.h>
22
#include <sys/queue.h>
23
#include <arpa/inet.h>
24
#include <limits.h>
25
#include <imsg.h>
26
27
#include <openssl/evp.h>
28
29
#include "openbsd-compat.h"
30
31
#include "types.h"
32
#include "dh.h"
33
34
#define MAXIMUM(a,b) (((a)>(b))?(a):(b))
35
#define MINIMUM(a,b) (((a)<(b))?(a):(b))
36
#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
37
38
#ifndef IKED_H
39
#define IKED_H
40
41
/*
42
 * Common IKEv1/IKEv2 header
43
 */
44
45
struct ike_header {
46
  uint64_t   ike_ispi;    /* Initiator cookie */
47
  uint64_t   ike_rspi;    /* Responder cookie */
48
  uint8_t    ike_nextpayload; /* Next payload type */
49
  uint8_t    ike_version;   /* Major/Minor version number */
50
  uint8_t    ike_exchange;    /* Exchange type */
51
  uint8_t    ike_flags;   /* Message options */
52
  uint32_t   ike_msgid;   /* Message identifier */
53
  uint32_t   ike_length;    /* Total message length */
54
} __packed;
55
56
/*
57
 * Common daemon infrastructure, local imsg etc.
58
 */
59
60
struct imsgev {
61
  struct imsgbuf     ibuf;
62
  void      (*handler)(int, short, void *);
63
  struct event     ev;
64
  struct privsep_proc *proc;
65
  void      *data;
66
  short      events;
67
  const char    *name;
68
};
69
70
#define IMSG_SIZE_CHECK(imsg, p) do {       \
71
  if (IMSG_DATA_SIZE(imsg) < sizeof(*p))      \
72
    fatalx("bad length imsg received");   \
73
} while (0)
74
#define IMSG_DATA_SIZE(imsg)  ((imsg)->hdr.len - IMSG_HEADER_SIZE)
75
76
#define IKED_ADDR_EQ(_a, _b)            \
77
  ((_a)->addr_mask == (_b)->addr_mask &&        \
78
  sockaddr_cmp((struct sockaddr *)&(_a)->addr,      \
79
  (struct sockaddr *)&(_b)->addr, (_a)->addr_mask) == 0)
80
81
#define IKED_ADDR_NEQ(_a, _b)           \
82
  ((_a)->addr_mask != (_b)->addr_mask ||        \
83
  sockaddr_cmp((struct sockaddr *)&(_a)->addr,      \
84
  (struct sockaddr *)&(_b)->addr, (_a)->addr_mask) != 0)
85
86
/* initially control.h */
87
struct control_sock {
88
  const char  *cs_name;
89
  struct event   cs_ev;
90
  struct event   cs_evt;
91
  int    cs_fd;
92
  int    cs_restricted;
93
  void    *cs_env;
94
95
  TAILQ_ENTRY(control_sock) cs_entry;
96
};
97
TAILQ_HEAD(control_socks, control_sock);
98
99
struct ctl_conn {
100
  TAILQ_ENTRY(ctl_conn)  entry;
101
  uint8_t      flags;
102
#define CTL_CONN_NOTIFY    0x01
103
  struct imsgev    iev;
104
};
105
TAILQ_HEAD(ctl_connlist, ctl_conn);
106
107
extern enum privsep_procid privsep_process;
108
109
/*
110
 * Runtime structures
111
 */
112
113
struct iked_timer {
114
  struct event   tmr_ev;
115
  struct iked *tmr_env;
116
  void    (*tmr_cb)(struct iked *, void *);
117
  void    *tmr_cbarg;
118
};
119
120
struct iked_spi {
121
  uint64_t   spi;
122
  uint8_t    spi_size;
123
  uint8_t    spi_protoid;
124
};
125
126
struct iked_proposal {
127
  uint8_t        prop_id;
128
  uint8_t        prop_protoid;
129
130
  struct iked_spi      prop_localspi;
131
  struct iked_spi      prop_peerspi;
132
133
  struct iked_transform   *prop_xforms;
134
  unsigned int       prop_nxforms;
135
136
  TAILQ_ENTRY(iked_proposal)   prop_entry;
137
};
138
TAILQ_HEAD(iked_proposals, iked_proposal);
139
140
struct iked_addr {
141
  int        addr_af;
142
  struct sockaddr_storage    addr;
143
  uint8_t        addr_mask;
144
  int        addr_net;
145
  in_port_t      addr_port;
146
};
147
148
struct iked_ts {
149
  struct iked_addr     ts_addr;
150
  uint8_t        ts_ipproto;
151
  TAILQ_ENTRY(iked_ts)     ts_entry;
152
};
153
TAILQ_HEAD(iked_tss, iked_ts);
154
155
struct iked_flow {
156
  struct iked_addr     flow_src;
157
  struct iked_addr     flow_dst;
158
  unsigned int       flow_dir;  /* in/out */
159
  int        flow_rdomain;
160
  struct iked_addr     flow_prenat;
161
  int        flow_fixed;
162
163
  unsigned int       flow_loaded; /* pfkey done */
164
165
  uint8_t        flow_saproto;
166
  uint8_t        flow_ipproto;
167
168
  struct iked_addr    *flow_local;  /* outer source */
169
  struct iked_addr    *flow_peer; /* outer dest */
170
  struct iked_sa      *flow_ikesa;  /* parent SA */
171
172
  int        flow_transport;
173
174
  RB_ENTRY(iked_flow)    flow_node;
175
  TAILQ_ENTRY(iked_flow)     flow_entry;
176
};
177
RB_HEAD(iked_flows, iked_flow);
178
TAILQ_HEAD(iked_saflows, iked_flow);
179
180
struct iked_childsa {
181
  uint8_t        csa_saproto; /* IPsec protocol */
182
  unsigned int       csa_dir; /* in/out */
183
184
  uint64_t       csa_peerspi; /* peer relation */
185
  uint8_t        csa_loaded;  /* pfkey done */
186
  uint8_t        csa_rekey; /* will be deleted */
187
  uint8_t        csa_allocated; /* from the kernel */
188
  uint8_t        csa_persistent;/* do not rekey */
189
  uint8_t        csa_esn; /* use ESN */
190
  uint8_t        csa_transport; /* transport mode */
191
192
  struct iked_spi      csa_spi;
193
194
  struct ibuf     *csa_encrkey; /* encryption key */
195
  uint16_t       csa_encrid;  /* encryption xform id */
196
197
  struct ibuf     *csa_integrkey; /* auth key */
198
  uint16_t       csa_integrid;  /* auth xform id */
199
200
  struct iked_addr    *csa_local; /* outer source */
201
  struct iked_addr    *csa_peer;  /* outer dest */
202
  struct iked_sa      *csa_ikesa; /* parent SA */
203
204
  struct iked_childsa   *csa_peersa;  /* peer */
205
206
  struct iked_childsa   *csa_bundled; /* IPCOMP */
207
208
  uint16_t       csa_pfsgrpid;  /* pfs group id */
209
210
  RB_ENTRY(iked_childsa)     csa_node;
211
  TAILQ_ENTRY(iked_childsa)  csa_entry;
212
};
213
RB_HEAD(iked_activesas, iked_childsa);
214
TAILQ_HEAD(iked_childsas, iked_childsa);
215
216
217
struct iked_static_id {
218
  uint8_t   id_type;
219
  uint8_t   id_length;
220
  uint8_t   id_offset;
221
  uint8_t   id_data[IKED_ID_SIZE];
222
};
223
224
struct iked_auth {
225
  uint8_t   auth_method;
226
  uint8_t   auth_eap;     /* optional EAP */
227
  uint8_t   auth_length;      /* zero if EAP */
228
  uint8_t   auth_data[IKED_PSK_SIZE];
229
};
230
231
struct iked_cfg {
232
  uint8_t        cfg_action;
233
  uint16_t       cfg_type;
234
  union {
235
    struct iked_addr   address;
236
  } cfg;
237
};
238
239
TAILQ_HEAD(iked_sapeers, iked_sa);
240
241
struct iked_lifetime {
242
  uint64_t       lt_bytes;
243
  uint64_t       lt_seconds;
244
};
245
246
struct iked_policy {
247
  unsigned int       pol_id;
248
  char         pol_name[IKED_ID_SIZE];
249
  unsigned int       pol_iface;
250
251
#define IKED_SKIP_FLAGS      0
252
#define IKED_SKIP_AF       1
253
#define IKED_SKIP_SRC_ADDR     2
254
#define IKED_SKIP_DST_ADDR     3
255
#define IKED_SKIP_COUNT      4
256
  struct iked_policy    *pol_skip[IKED_SKIP_COUNT];
257
258
  uint8_t        pol_flags;
259
#define IKED_POLICY_PASSIVE    0x00
260
#define IKED_POLICY_DEFAULT    0x01
261
#define IKED_POLICY_ACTIVE     0x02
262
#define IKED_POLICY_REFCNT     0x04
263
#define IKED_POLICY_QUICK    0x08
264
#define IKED_POLICY_SKIP     0x10
265
#define IKED_POLICY_IPCOMP     0x20
266
0
#define IKED_POLICY_TRANSPORT    0x40
267
#define IKED_POLICY_ROUTING    0x80
268
269
  int        pol_refcnt;
270
271
  uint8_t        pol_certreqtype;
272
273
  int        pol_af;
274
  int        pol_rdomain;
275
  uint8_t        pol_saproto;
276
  unsigned int       pol_ipproto[IKED_IPPROTO_MAX];
277
  unsigned int       pol_nipproto;
278
279
  struct iked_addr     pol_peer;
280
  struct iked_static_id    pol_peerid;
281
  uint32_t       pol_peerdh;
282
283
  struct iked_addr     pol_local;
284
  struct iked_static_id    pol_localid;
285
286
  struct iked_auth     pol_auth;
287
288
  char         pol_tag[IKED_TAG_SIZE];
289
  unsigned int       pol_tap;
290
291
  struct iked_proposals    pol_proposals;
292
  size_t         pol_nproposals;
293
294
  struct iked_flows    pol_flows;
295
  size_t         pol_nflows;
296
  struct iked_tss      pol_tssrc; /* Traffic Selectors Initiator*/
297
  size_t         pol_tssrc_count;
298
  struct iked_tss      pol_tsdst; /* Traffic Selectors Responder*/
299
  size_t         pol_tsdst_count;
300
301
  struct iked_cfg      pol_cfg[IKED_CFG_MAX];
302
  unsigned int       pol_ncfg;
303
304
  uint32_t       pol_rekey; /* ike SA lifetime */
305
  struct iked_lifetime     pol_lifetime;  /* child SA lifetime */
306
307
  struct iked_sapeers    pol_sapeers;
308
309
  TAILQ_ENTRY(iked_policy)   pol_entry;
310
};
311
TAILQ_HEAD(iked_policies, iked_policy);
312
313
struct iked_hash {
314
  uint8_t    hash_type; /* PRF or INTEGR */
315
  uint16_t   hash_id; /* IKE PRF/INTEGR hash id */
316
  const void  *hash_priv; /* Identifying the hash alg */
317
  void    *hash_ctx;  /* Context of the current invocation */
318
  int    hash_fixedkey; /* Requires fixed key length */
319
  struct ibuf *hash_key;  /* MAC key derived from key seed */
320
  size_t     hash_length; /* Output length */
321
  size_t     hash_trunc;  /* Truncate the output length */
322
  struct iked_hash *hash_prf; /* PRF pointer */
323
  int    hash_isaead;
324
};
325
326
struct iked_cipher {
327
  uint8_t    encr_type; /* ENCR */
328
  uint16_t   encr_id; /* IKE ENCR hash id */
329
  const void  *encr_priv; /* Identifying the hash alg */
330
  void    *encr_ctx;  /* Context of the current invocation */
331
  int    encr_fixedkey; /* Requires fixed key length */
332
  struct ibuf *encr_key;  /* MAC key derived from key seed */
333
  struct ibuf *encr_iv; /* Initialization Vector */
334
  uint64_t   encr_civ;  /* Counter IV for GCM */
335
  size_t     encr_ivlength; /* IV length */
336
  size_t     encr_length; /* Block length */
337
  size_t     encr_saltlength; /* IV salt length */
338
  uint16_t   encr_authid; /* ID of associated authentication */
339
};
340
341
struct iked_dsa {
342
  uint8_t    dsa_method;  /* AUTH method */
343
  const void  *dsa_priv;  /* PRF or signature hash function */
344
  void    *dsa_ctx; /* PRF or signature hash ctx */
345
  struct ibuf *dsa_keydata; /* public, private or shared key */
346
  void    *dsa_key; /* parsed public or private key */
347
  int    dsa_hmac;  /* HMAC or public/private key */
348
  int    dsa_sign;  /* Sign or verify operation */
349
  uint32_t   dsa_flags; /* State flags */
350
};
351
352
struct iked_id {
353
  uint8_t    id_type;
354
  uint8_t    id_offset;
355
  struct ibuf *id_buf;
356
};
357
358
#define IKED_REQ_CERT   0x0001  /* get local certificate (if required) */
359
#define IKED_REQ_CERTVALID  0x0002  /* validated the peer cert */
360
#define IKED_REQ_CERTREQ  0x0004  /* CERTREQ has been received */
361
#define IKED_REQ_AUTH   0x0008  /* AUTH payload */
362
#define IKED_REQ_AUTHVALID  0x0010  /* AUTH payload has been verified */
363
#define IKED_REQ_SA   0x0020  /* SA available */
364
#define IKED_REQ_EAPVALID 0x0040  /* EAP payload has been verified */
365
#define IKED_REQ_CHILDSA  0x0080  /* Child SA initiated */
366
#define IKED_REQ_INF    0x0100  /* Informational exchange initiated */
367
368
#define IKED_REQ_BITS \
369
    "\20\01CERT\02CERTVALID\03CERTREQ\04AUTH\05AUTHVALID\06SA\07EAPVALID" \
370
    "\10CHILDSA\11INF"
371
372
TAILQ_HEAD(iked_msgqueue, iked_msg_retransmit);
373
TAILQ_HEAD(iked_msg_fragqueue, iked_message);
374
375
struct iked_sahdr {
376
  uint64_t       sh_ispi; /* Initiator SPI */
377
  uint64_t       sh_rspi; /* Responder SPI */
378
  unsigned int       sh_initiator;  /* Is initiator? */
379
} __packed;
380
381
struct iked_kex {
382
  struct ibuf     *kex_inonce;  /* Ni */
383
  struct ibuf     *kex_rnonce;  /* Nr */
384
385
  struct dh_group     *kex_dhgroup; /* DH group */
386
  struct ibuf     *kex_dhiexchange;
387
  struct ibuf     *kex_dhrexchange;
388
  struct ibuf     *kex_dhpeer;  /* pointer to i or r */
389
};
390
391
struct iked_frag_entry {
392
  uint8_t *frag_data;
393
  size_t   frag_size;
394
};
395
396
struct iked_frag {
397
  struct iked_frag_entry  **frag_arr; /* list of fragment buffers */
398
  size_t        frag_count; /* number of fragments received */
399
0
#define IKED_FRAG_TOTAL_MAX   111    /* upper limit (64kB / 576B) */
400
  size_t        frag_total; /* total numbe of fragments */
401
  size_t        frag_total_size;
402
  uint8_t       frag_nextpayload;
403
404
};
405
406
struct iked_ipcomp {
407
  uint16_t       ic_cpi_out;  /* outgoing CPI */
408
  uint16_t       ic_cpi_in; /* incoming CPI */
409
  uint8_t        ic_transform;  /* transform */
410
};
411
412
struct iked_sa {
413
  struct iked_sahdr    sa_hdr;
414
  uint32_t       sa_msgid;  /* Last request rcvd */
415
  int        sa_msgid_set;  /* msgid initialized */
416
  uint32_t       sa_msgid_current;  /* Current requested rcvd */
417
  uint32_t       sa_reqid;  /* Next request sent */
418
419
  int        sa_type;
420
#define IKED_SATYPE_LOOKUP     0    /* Used for lookup */
421
#define IKED_SATYPE_LOCAL    1    /* Local SA */
422
423
  struct iked_addr     sa_peer;
424
  struct iked_addr     sa_peer_loaded;/* MOBIKE */
425
  struct iked_addr     sa_local;
426
  int        sa_fd;
427
428
  struct iked_frag     sa_fragments;
429
430
  int        sa_natt; /* for IKE messages */
431
  int        sa_udpencap; /* for pfkey */
432
  int        sa_usekeepalive;/* NAT-T keepalive */
433
434
  int        sa_state;
435
  unsigned int       sa_stateflags;
436
  unsigned int       sa_stateinit;  /* SA_INIT */
437
  unsigned int       sa_statevalid; /* IKE_AUTH */
438
439
  int        sa_cp;   /* XXX */
440
  struct iked_addr    *sa_cp_addr;  /* requested address */
441
  struct iked_addr    *sa_cp_addr6; /* requested address */
442
  struct iked_addr    *sa_cp_dns; /* requested dns */
443
444
  struct iked_policy    *sa_policy;
445
  struct timeval       sa_timecreated;
446
  struct timeval       sa_timeused;
447
448
  char        *sa_tag;
449
  const char      *sa_reason; /* reason for close */
450
451
  struct iked_kex      sa_kex;
452
/* XXX compat defines until everything is converted */
453
#define sa_inonce   sa_kex.kex_inonce
454
#define sa_rnonce   sa_kex.kex_rnonce
455
#define sa_dhgroup    sa_kex.kex_dhgroup
456
#define sa_dhiexchange    sa_kex.kex_dhiexchange
457
#define sa_dhrexchange    sa_kex.kex_dhrexchange
458
#define sa_dhpeer   sa_kex.kex_dhpeer
459
460
  struct iked_hash    *sa_prf;  /* PRF alg */
461
  struct iked_hash    *sa_integr; /* integrity alg */
462
  struct iked_cipher    *sa_encr; /* encryption alg */
463
464
  struct ibuf     *sa_key_d;  /* SK_d */
465
  struct ibuf     *sa_key_iauth;  /* SK_ai */
466
  struct ibuf     *sa_key_rauth;  /* SK_ar */
467
  struct ibuf     *sa_key_iencr;  /* SK_ei */
468
  struct ibuf     *sa_key_rencr;  /* SK_er */
469
  struct ibuf     *sa_key_iprf; /* SK_pi */
470
  struct ibuf     *sa_key_rprf; /* SK_pr */
471
472
  struct ibuf     *sa_1stmsg; /* for initiator AUTH */
473
  struct ibuf     *sa_2ndmsg; /* for responder AUTH */
474
  struct iked_id       sa_localauth;  /* local AUTH message */
475
  struct iked_id       sa_peerauth; /* peer AUTH message */
476
  int        sa_sigsha2;  /* use SHA2 for signatures */
477
130k
#define IKED_SCERT_MAX  3 /* max # of supplemental cert payloads */
478
479
  struct iked_id       sa_iid;  /* initiator id */
480
  struct iked_id       sa_rid;  /* responder id */
481
  struct iked_id       sa_icert;  /* initiator cert */
482
  struct iked_id       sa_rcert;  /* responder cert */
483
  struct iked_id       sa_scert[IKED_SCERT_MAX]; /* supplemental certs */
484
#define IKESA_SRCID(x) ((x)->sa_hdr.sh_initiator ? &(x)->sa_iid : &(x)->sa_rid)
485
#define IKESA_DSTID(x) ((x)->sa_hdr.sh_initiator ? &(x)->sa_rid : &(x)->sa_iid)
486
487
  char        *sa_eapid;  /* EAP identity */
488
  struct iked_id       sa_eap;  /* EAP challenge */
489
  struct ibuf     *sa_eapmsk; /* EAK session key */
490
491
  struct iked_proposals    sa_proposals;  /* SA proposals */
492
  struct iked_childsas     sa_childsas; /* IPsec Child SAs */
493
  struct iked_saflows    sa_flows;  /* IPsec flows */
494
495
  struct iked_sa      *sa_nexti;  /* initiated IKE SA */
496
  struct iked_sa      *sa_previ;  /* matching back pointer */
497
  struct iked_sa      *sa_nextr;  /* simultaneous rekey */
498
  struct iked_sa      *sa_prevr;  /* matching back pointer */
499
  uint64_t       sa_rekeyspi; /* peerspi CSA rekey */
500
  struct ibuf     *sa_simult; /* simultaneous rekey */
501
502
  struct iked_ipcomp     sa_ipcompi;  /* IPcomp initator */
503
  struct iked_ipcomp     sa_ipcompr;  /* IPcomp responder */
504
505
  int        sa_mobike; /* MOBIKE */
506
  int        sa_frag; /* fragmentation */
507
508
  int        sa_use_transport_mode; /* peer requested */
509
  int        sa_used_transport_mode; /* we enabled */
510
511
  struct iked_timer    sa_timer;  /* SA timeouts */
512
#define IKED_IKE_SA_EXCHANGE_TIMEOUT   300    /* 5 minutes */
513
#define IKED_IKE_SA_REKEY_TIMEOUT  120    /* 2 minutes */
514
#define IKED_IKE_SA_DELETE_TIMEOUT   120    /* 2 minutes */
515
#define IKED_IKE_SA_ALIVE_TIMEOUT  60   /* 1 minute */
516
517
  struct iked_timer    sa_keepalive;  /* keepalive timer */
518
#define IKED_IKE_SA_KEEPALIVE_TIMEOUT  20
519
520
  struct iked_timer    sa_rekey;  /* rekey timeout */
521
  int        sa_tmpfail;
522
523
  struct iked_msgqueue     sa_requests; /* request queue */
524
#define IKED_RETRANSMIT_TIMEOUT    2    /* 2 seconds */
525
526
  struct iked_msgqueue     sa_responses;  /* response queue */
527
#define IKED_RESPONSE_TIMEOUT    120    /* 2 minutes */
528
529
  TAILQ_ENTRY(iked_sa)     sa_peer_entry;
530
  RB_ENTRY(iked_sa)    sa_entry;  /* all SAs */
531
532
  RB_ENTRY(iked_sa)    sa_dstid_entry;  /* SAs by DSTID */
533
  int        sa_dstid_entry_valid;    /* sa_dstid_entry valid */
534
535
  struct iked_addr    *sa_addrpool; /* address from pool */
536
  RB_ENTRY(iked_sa)    sa_addrpool_entry; /* pool entries */
537
538
  struct iked_addr    *sa_addrpool6;  /* address from pool */
539
  RB_ENTRY(iked_sa)    sa_addrpool6_entry;  /* pool entries */
540
  time_t         sa_last_recvd;
541
#define IKED_IKE_SA_LAST_RECVD_TIMEOUT   300    /* 5 minutes */
542
};
543
RB_HEAD(iked_sas, iked_sa);
544
RB_HEAD(iked_dstid_sas, iked_sa);
545
RB_HEAD(iked_addrpool, iked_sa);
546
RB_HEAD(iked_addrpool6, iked_sa);
547
548
/* stats */
549
550
struct iked_stats {
551
  uint64_t  ikes_sa_created;
552
  uint64_t  ikes_sa_established_total;
553
  uint64_t  ikes_sa_established_current;  /* gauge */
554
  uint64_t  ikes_sa_established_failures;
555
  uint64_t  ikes_sa_proposals_negotiate_failures;
556
  uint64_t  ikes_sa_rekeyed;
557
  uint64_t  ikes_sa_removed;
558
  uint64_t  ikes_csa_created;
559
  uint64_t  ikes_csa_removed;
560
  uint64_t  ikes_msg_sent;
561
  uint64_t  ikes_msg_send_failures;
562
  uint64_t  ikes_msg_rcvd;
563
  uint64_t  ikes_msg_rcvd_busy;
564
  uint64_t  ikes_msg_rcvd_dropped;
565
  uint64_t  ikes_retransmit_request;
566
  uint64_t  ikes_retransmit_response;
567
  uint64_t  ikes_retransmit_limit;
568
  uint64_t  ikes_frag_sent;
569
  uint64_t  ikes_frag_send_failures;
570
  uint64_t  ikes_frag_rcvd;
571
  uint64_t  ikes_frag_rcvd_drop;
572
  uint64_t  ikes_frag_reass_ok;
573
  uint64_t  ikes_frag_reass_drop;
574
  uint64_t  ikes_update_addresses_sent;
575
  uint64_t  ikes_dpd_sent;
576
  uint64_t  ikes_keepalive_sent;
577
};
578
579
0
#define ikestat_add(env, c, n)  do { env->sc_stats.c += (n); } while(0)
580
0
#define ikestat_inc(env, c) ikestat_add(env, c, 1)
581
#define ikestat_dec(env, c) ikestat_add(env, c, -1)
582
583
struct iked_certreq {
584
  struct ibuf     *cr_data;
585
  uint8_t        cr_type;
586
  SIMPLEQ_ENTRY(iked_certreq)  cr_entry;
587
};
588
SIMPLEQ_HEAD(iked_certreqs, iked_certreq);
589
590
#define EAP_STATE_IDENTITY    (1)
591
#define EAP_STATE_MSCHAPV2_CHALLENGE  (2)
592
#define EAP_STATE_MSCHAPV2_SUCCESS  (3)
593
#define EAP_STATE_SUCCESS   (4)
594
595
struct eap_msg {
596
  char    *eam_identity;
597
  char    *eam_user;
598
  int    eam_type;
599
  uint8_t    eam_id;
600
  uint8_t    eam_msrid;
601
  int    eam_success;
602
  int    eam_found;
603
  int    eam_response;
604
  uint8_t    eam_challenge[16];
605
  uint8_t    eam_ntresponse[24];
606
  uint32_t   eam_state;
607
};
608
609
struct iked_message {
610
  struct ibuf   *msg_data;
611
  size_t       msg_offset;
612
613
  struct sockaddr_storage  msg_local;
614
  socklen_t    msg_locallen;
615
616
  struct sockaddr_storage  msg_peer;
617
  socklen_t    msg_peerlen;
618
619
  struct iked_socket  *msg_sock;
620
621
  int      msg_fd;
622
  int      msg_response;
623
  int      msg_responded;
624
  int      msg_valid;
625
  int      msg_natt;
626
  int      msg_natt_rcvd;
627
  int      msg_nat_detected;
628
  int      msg_error;
629
  int      msg_e;
630
  struct iked_message *msg_parent;
631
632
  /* Associated policy and SA */
633
  struct iked_policy  *msg_policy;
634
  struct iked_sa    *msg_sa;
635
636
  uint32_t     msg_msgid;
637
  uint8_t      msg_exchange;
638
639
  /* Parsed information */
640
  struct iked_proposals  msg_proposals;
641
  struct iked_certreqs   msg_certreqs;
642
  struct iked_spi    msg_rekey;
643
  struct ibuf   *msg_nonce; /* dh NONCE */
644
  uint16_t     msg_dhgroup; /* dh group */
645
  struct ibuf   *msg_ke;  /* dh key exchange */
646
  struct iked_id     msg_auth;  /* AUTH payload */
647
  struct iked_id     msg_peerid;
648
  struct iked_id     msg_localid;
649
  struct iked_id     msg_cert;
650
  struct iked_id     msg_scert[IKED_SCERT_MAX]; /* supplemental certs */
651
  struct ibuf   *msg_cookie;
652
  uint16_t     msg_group;
653
  uint16_t     msg_cpi;
654
  uint8_t      msg_transform;
655
  uint16_t     msg_flags;
656
  struct eap_msg     msg_eap;
657
  size_t       msg_del_spisize;
658
  size_t       msg_del_cnt;
659
  struct ibuf   *msg_del_buf;
660
  int      msg_del_protoid;
661
  int      msg_cp;
662
  struct iked_addr  *msg_cp_addr; /* requested address */
663
  struct iked_addr  *msg_cp_addr6;  /* requested address */
664
  struct iked_addr  *msg_cp_dns;  /* requested dns */
665
666
  /* MOBIKE */
667
  int      msg_update_sa_addresses;
668
  struct ibuf   *msg_cookie2;
669
670
  /* Parse stack */
671
  struct iked_proposal  *msg_prop;
672
  uint16_t     msg_attrlength;
673
674
  /* Retransmit queue */
675
  TAILQ_ENTRY(iked_message)
676
         msg_entry;
677
};
678
679
struct iked_msg_retransmit {
680
  struct iked_msg_fragqueue       mrt_frags;
681
  TAILQ_ENTRY(iked_msg_retransmit)      mrt_entry;
682
  struct iked_timer         mrt_timer;
683
  int             mrt_tries;
684
#define IKED_RETRANSMIT_TRIES  5    /* try 5 times */
685
};
686
687
3.34k
#define IKED_MSG_NAT_SRC_IP       0x01
688
22.4k
#define IKED_MSG_NAT_DST_IP       0x02
689
690
0
#define IKED_MSG_FLAGS_FRAGMENTATION      0x0001
691
159
#define IKED_MSG_FLAGS_MOBIKE       0x0002
692
0
#define IKED_MSG_FLAGS_SIGSHA2        0x0004
693
73
#define IKED_MSG_FLAGS_CHILD_SA_NOT_FOUND   0x0008
694
273
#define IKED_MSG_FLAGS_NO_ADDITIONAL_SAS    0x0010
695
0
#define IKED_MSG_FLAGS_AUTHENTICATION_FAILED    0x0020
696
139
#define IKED_MSG_FLAGS_INVALID_KE     0x0040
697
128
#define IKED_MSG_FLAGS_IPCOMP_SUPPORTED     0x0080
698
279
#define IKED_MSG_FLAGS_USE_TRANSPORT      0x0100
699
354
#define IKED_MSG_FLAGS_TEMPORARY_FAILURE    0x0200
700
36
#define IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN   0x0400
701
702
703
struct iked_user {
704
  char       usr_name[LOGIN_NAME_MAX];
705
  char       usr_pass[IKED_PASSWORD_SIZE];
706
  RB_ENTRY(iked_user)  usr_entry;
707
};
708
RB_HEAD(iked_users, iked_user);
709
710
struct privsep_pipes {
711
  int       *pp_pipes[PROC_MAX];
712
};
713
714
struct privsep {
715
  struct privsep_pipes    *ps_pipes[PROC_MAX];
716
  struct privsep_pipes    *ps_pp;
717
718
  struct imsgev     *ps_ievs[PROC_MAX];
719
  const char      *ps_title[PROC_MAX];
720
  pid_t        ps_pid[PROC_MAX];
721
  struct passwd     *ps_pw;
722
  int        ps_noaction;
723
724
  struct control_sock    ps_csock;
725
  struct control_socks     ps_rcsocks;
726
727
  unsigned int       ps_instances[PROC_MAX];
728
  unsigned int       ps_ninstances;
729
  unsigned int       ps_instance;
730
731
  /* Event and signal handlers */
732
  struct event       ps_evsigint;
733
  struct event       ps_evsigterm;
734
  struct event       ps_evsigchld;
735
  struct event       ps_evsighup;
736
  struct event       ps_evsigpipe;
737
  struct event       ps_evsigusr1;
738
739
  struct iked     *ps_env;
740
};
741
742
struct privsep_proc {
743
  const char    *p_title;
744
  enum privsep_procid  p_id;
745
  int     (*p_cb)(int, struct privsep_proc *,
746
            struct imsg *);
747
  void      (*p_init)(struct privsep *,
748
            struct privsep_proc *);
749
  const char    *p_chroot;
750
  struct passwd   *p_pw;
751
  struct privsep    *p_ps;
752
  void      (*p_shutdown)(void);
753
};
754
755
struct privsep_fd {
756
  enum privsep_procid    pf_procid;
757
  unsigned int       pf_instance;
758
};
759
760
#define PROC_PARENT_SOCK_FILENO 3
761
#define PROC_MAX_INSTANCES      32
762
763
struct iked_ocsp_entry {
764
  TAILQ_ENTRY(iked_ocsp_entry) ioe_entry; /* next request */
765
  void      *ioe_ocsp;  /* private ocsp request data */
766
};
767
TAILQ_HEAD(iked_ocsp_requests, iked_ocsp_entry);
768
769
/*
770
 * Daemon configuration
771
 */
772
773
enum natt_mode {
774
  NATT_DEFAULT, /* send/recv with both :500 and NAT-T port */
775
  NATT_DISABLE, /* send/recv with only :500 */
776
  NATT_FORCE, /* send/recv with only NAT-T port */
777
};
778
779
struct iked_static {
780
  uint64_t     st_alive_timeout;
781
  int      st_enforcesingleikesa;
782
  uint8_t      st_frag; /* fragmentation */
783
  uint8_t      st_mobike; /* MOBIKE */
784
  in_port_t    st_nattport;
785
  int      st_stickyaddress; /* addr per DSTID  */
786
  int      st_vendorid;
787
};
788
789
struct iked {
790
  char         sc_conffile[PATH_MAX];
791
792
  uint32_t       sc_opts;
793
  enum natt_mode       sc_nattmode;
794
  uint8_t        sc_passive;
795
  uint8_t        sc_decoupled;
796
797
  struct iked_static     sc_static;
798
799
#define sc_alive_timeout  sc_static.st_alive_timeout
800
#define sc_enforcesingleikesa sc_static.st_enforcesingleikesa
801
#define sc_frag     sc_static.st_frag
802
#define sc_mobike   sc_static.st_mobike
803
#define sc_nattport   sc_static.st_nattport
804
#define sc_stickyaddress  sc_static.st_stickyaddress
805
#define sc_vendorid   sc_static.st_vendorid
806
807
  struct iked_policies     sc_policies;
808
  struct iked_policy    *sc_defaultcon;
809
810
  struct iked_sas      sc_sas;
811
  struct iked_dstid_sas    sc_dstid_sas;
812
  struct iked_activesas    sc_activesas;
813
  struct iked_flows    sc_activeflows;
814
  struct iked_users    sc_users;
815
816
  struct iked_stats    sc_stats;
817
818
  void        *sc_priv; /* per-process */
819
820
  int        sc_pfkey;  /* ike process */
821
  struct event       sc_pfkeyev;
822
  struct event       sc_routeev;
823
  uint8_t        sc_certreqtype;
824
  struct ibuf     *sc_certreq;
825
  void        *sc_vroute;
826
827
  struct iked_socket    *sc_sock4[2];
828
  struct iked_socket    *sc_sock6[2];
829
830
  struct iked_timer    sc_inittmr;
831
#define IKED_INITIATOR_INITIAL     2
832
#define IKED_INITIATOR_INTERVAL    60
833
834
  struct privsep       sc_ps;
835
836
  struct iked_ocsp_requests  sc_ocsp;
837
  char        *sc_ocsp_url;
838
  long         sc_ocsp_tolerate;
839
  long         sc_ocsp_maxage;
840
841
  struct iked_addrpool     sc_addrpool;
842
  struct iked_addrpool6    sc_addrpool6;
843
844
  int        sc_cert_partial_chain;
845
#ifdef WITH_APPARMOR
846
  int        sc_apparmor;
847
#endif
848
};
849
850
struct iked_socket {
851
  int      sock_fd;
852
  struct event     sock_ev;
853
  struct iked   *sock_env;
854
  struct sockaddr_storage  sock_addr;
855
};
856
857
struct ipsec_xf {
858
  const char  *name;
859
  unsigned int   id;
860
  unsigned int   length;
861
  unsigned int   keylength;
862
  unsigned int   nonce;
863
  unsigned int   noauth;
864
};
865
866
struct ipsec_transforms {
867
  const struct ipsec_xf **authxf;
868
  unsigned int      nauthxf;
869
  const struct ipsec_xf **prfxf;
870
  unsigned int      nprfxf;
871
  const struct ipsec_xf **encxf;
872
  unsigned int      nencxf;
873
  const struct ipsec_xf **groupxf;
874
  unsigned int      ngroupxf;
875
  const struct ipsec_xf **esnxf;
876
  unsigned int      nesnxf;
877
};
878
879
struct ipsec_mode {
880
  struct ipsec_transforms **xfs;
881
  unsigned int      nxfs;
882
};
883
884
/* iked.c */
885
void   parent_reload(struct iked *, int, const char *);
886
887
extern struct iked  *iked_env;
888
889
/* control.c */
890
void   control(struct privsep *, struct privsep_proc *);
891
int  control_init(struct privsep *, struct control_sock *);
892
int  control_listen(struct control_sock *);
893
894
/* config.c */
895
struct iked_policy *
896
   config_new_policy(struct iked *);
897
void   config_free_kex(struct iked_kex *);
898
void   config_free_fragments(struct iked_frag *);
899
void   config_free_sa(struct iked *, struct iked_sa *);
900
struct iked_sa *
901
   config_new_sa(struct iked *, int);
902
struct iked_user *
903
   config_new_user(struct iked *, struct iked_user *);
904
uint64_t
905
   config_getspi(void);
906
struct iked_transform *
907
   config_findtransform(struct iked_proposals *, uint8_t, unsigned int);
908
struct iked_transform *
909
   config_findtransform_ext(struct iked_proposals *, uint8_t,int, unsigned int);
910
void   config_free_policy(struct iked *, struct iked_policy *);
911
struct iked_proposal *
912
   config_add_proposal(struct iked_proposals *, unsigned int,
913
      unsigned int);
914
void   config_free_proposal(struct iked_proposals *, struct iked_proposal *);
915
void   config_free_proposals(struct iked_proposals *, unsigned int);
916
void   config_free_flows(struct iked *, struct iked_flows *);
917
void   config_free_childsas(struct iked *, struct iked_childsas *,
918
      struct iked_spi *, struct iked_spi *);
919
int  config_add_transform(struct iked_proposal *,
920
      unsigned int, unsigned int, unsigned int, unsigned int);
921
int  config_setcoupled(struct iked *, unsigned int);
922
int  config_getcoupled(struct iked *, unsigned int);
923
int  config_setmode(struct iked *, unsigned int);
924
int  config_getmode(struct iked *, unsigned int);
925
int  config_setreset(struct iked *, unsigned int, enum privsep_procid);
926
int  config_getreset(struct iked *, struct imsg *);
927
int  config_doreset(struct iked *, unsigned int);
928
int  config_setpolicy(struct iked *, struct iked_policy *,
929
      enum privsep_procid);
930
int  config_getpolicy(struct iked *, struct imsg *);
931
int  config_setflow(struct iked *, struct iked_policy *,
932
      enum privsep_procid);
933
int  config_getflow(struct iked *, struct imsg *);
934
int  config_setsocket(struct iked *, struct sockaddr_storage *, in_port_t,
935
      enum privsep_procid, int);
936
int  config_getsocket(struct iked *env, struct imsg *,
937
      void (*cb)(int, short, void *));
938
int  config_setpfkey(struct iked *);
939
int  config_getpfkey(struct iked *, struct imsg *);
940
int  config_setuser(struct iked *, struct iked_user *, enum privsep_procid);
941
int  config_getuser(struct iked *, struct imsg *);
942
int  config_setcompile(struct iked *, enum privsep_procid);
943
int  config_getcompile(struct iked *);
944
int  config_setocsp(struct iked *);
945
int  config_getocsp(struct iked *, struct imsg *);
946
int  config_setkeys(struct iked *);
947
int  config_getkey(struct iked *, struct imsg *);
948
int  config_setstatic(struct iked *);
949
int  config_getstatic(struct iked *, struct imsg *);
950
int  config_setcertpartialchain(struct iked *);
951
int  config_getcertpartialchain(struct iked *, struct imsg *);
952
953
/* policy.c */
954
void   policy_init(struct iked *);
955
int  policy_lookup(struct iked *, struct iked_message *,
956
      struct iked_proposals *, struct iked_flows *, int);
957
int  policy_lookup_sa(struct iked *, struct iked_sa *);
958
struct iked_policy *
959
   policy_test(struct iked *, struct iked_policy *);
960
int  policy_generate_ts(struct iked_policy *);
961
void   policy_calc_skip_steps(struct iked_policies *);
962
void   policy_ref(struct iked *, struct iked_policy *);
963
void   policy_unref(struct iked *, struct iked_policy *);
964
void   sa_state(struct iked *, struct iked_sa *, int);
965
void   sa_stateflags(struct iked_sa *, unsigned int);
966
int  sa_stateok(const struct iked_sa *, int);
967
struct iked_sa *
968
   sa_new(struct iked *, uint64_t, uint64_t, unsigned int,
969
      struct iked_policy *);
970
void   sa_free(struct iked *, struct iked_sa *);
971
void   sa_free_flows(struct iked *, struct iked_saflows *);
972
int  sa_configure_iface(struct iked *, struct iked_sa *, int);
973
int  sa_address(struct iked_sa *, struct iked_addr *, struct sockaddr *);
974
void   childsa_free(struct iked_childsa *);
975
struct iked_childsa *
976
   childsa_lookup(struct iked_sa *, uint64_t, uint8_t);
977
void   flow_free(struct iked_flow *);
978
int  flow_equal(struct iked_flow *, struct iked_flow *);
979
struct iked_sa *
980
   sa_lookup(struct iked *, uint64_t, uint64_t, unsigned int);
981
struct iked_user *
982
   user_lookup(struct iked *, const char *);
983
struct iked_sa *
984
   sa_dstid_lookup(struct iked *, struct iked_sa *);
985
struct iked_sa *
986
   sa_dstid_insert(struct iked *, struct iked_sa *);
987
void   sa_dstid_remove(struct iked *, struct iked_sa *);
988
int  proposals_negotiate(struct iked_proposals *, struct iked_proposals *,
989
      struct iked_proposals *, int, int);
990
RB_PROTOTYPE(iked_sas, iked_sa, sa_entry, sa_cmp);
991
RB_PROTOTYPE(iked_dstid_sas, iked_sa, sa_dstid_entry, sa_dstid_cmp);
992
RB_PROTOTYPE(iked_addrpool, iked_sa, sa_addrpool_entry, sa_addrpool_cmp);
993
RB_PROTOTYPE(iked_addrpool6, iked_sa, sa_addrpool6_entry, sa_addrpool6_cmp);
994
RB_PROTOTYPE(iked_users, iked_user, user_entry, user_cmp);
995
RB_PROTOTYPE(iked_activesas, iked_childsa, csa_node, childsa_cmp);
996
RB_PROTOTYPE(iked_flows, iked_flow, flow_node, flow_cmp);
997
998
/* crypto.c */
999
struct iked_hash *
1000
   hash_new(uint8_t, uint16_t);
1001
struct ibuf *
1002
   hash_setkey(struct iked_hash *, void *, size_t);
1003
void   hash_free(struct iked_hash *);
1004
void   hash_init(struct iked_hash *);
1005
void   hash_update(struct iked_hash *, void *, size_t);
1006
void   hash_final(struct iked_hash *, void *, size_t *);
1007
size_t   hash_keylength(struct iked_hash *);
1008
size_t   hash_length(struct iked_hash *);
1009
1010
struct iked_cipher *
1011
   cipher_new(uint8_t, uint16_t, uint16_t);
1012
struct ibuf *
1013
   cipher_setkey(struct iked_cipher *, const void *, size_t);
1014
struct ibuf *
1015
   cipher_setiv(struct iked_cipher *, const void *, size_t);
1016
int  cipher_settag(struct iked_cipher *, uint8_t *, size_t);
1017
int  cipher_gettag(struct iked_cipher *, uint8_t *, size_t);
1018
void   cipher_free(struct iked_cipher *);
1019
int  cipher_init(struct iked_cipher *, int);
1020
int  cipher_init_encrypt(struct iked_cipher *);
1021
int  cipher_init_decrypt(struct iked_cipher *);
1022
void   cipher_aad(struct iked_cipher *, const void *, size_t, size_t *);
1023
int  cipher_update(struct iked_cipher *, const void *, size_t, void *, size_t *);
1024
int  cipher_final(struct iked_cipher *);
1025
size_t   cipher_length(struct iked_cipher *);
1026
size_t   cipher_keylength(struct iked_cipher *);
1027
size_t   cipher_ivlength(struct iked_cipher *);
1028
size_t   cipher_outlength(struct iked_cipher *, size_t);
1029
1030
struct iked_dsa *
1031
   dsa_new(uint8_t, struct iked_hash *, int);
1032
struct iked_dsa *
1033
   dsa_sign_new(uint8_t, struct iked_hash *);
1034
struct iked_dsa *
1035
   dsa_verify_new(uint8_t, struct iked_hash *);
1036
struct ibuf *
1037
   dsa_setkey(struct iked_dsa *, void *, size_t, uint8_t);
1038
void   dsa_free(struct iked_dsa *);
1039
int  dsa_init(struct iked_dsa *, const void *, size_t);
1040
size_t   dsa_prefix(struct iked_dsa *);
1041
size_t   dsa_length(struct iked_dsa *);
1042
int  dsa_update(struct iked_dsa *, const void *, size_t);
1043
ssize_t  dsa_sign_final(struct iked_dsa *, void *, size_t);
1044
ssize_t  dsa_verify_final(struct iked_dsa *, void *, size_t);
1045
1046
/* vroute.c */
1047
void vroute_init(struct iked *);
1048
int vroute_setaddr(struct iked *, int, struct sockaddr *, int, unsigned int);
1049
void vroute_cleanup(struct iked *);
1050
int vroute_getaddr(struct iked *, struct imsg *);
1051
int vroute_setdns(struct iked *, int, struct sockaddr *, unsigned int);
1052
int vroute_getdns(struct iked *, struct imsg *);
1053
int vroute_setaddroute(struct iked *, uint8_t, struct sockaddr *,
1054
    uint8_t, struct sockaddr *);
1055
int vroute_setcloneroute(struct iked *, uint8_t, struct sockaddr *,
1056
    uint8_t, struct sockaddr *);
1057
int vroute_setdelroute(struct iked *, uint8_t, struct sockaddr *,
1058
    uint8_t, struct sockaddr *);
1059
int vroute_getroute(struct iked *, struct imsg *);
1060
int vroute_getcloneroute(struct iked *, struct imsg *);
1061
1062
/* ikev2.c */
1063
void   ikev2(struct privsep *, struct privsep_proc *);
1064
void   ikev2_recv(struct iked *, struct iked_message *);
1065
void   ikev2_init_ike_sa(struct iked *, void *);
1066
int  ikev2_policy2id(struct iked_static_id *, struct iked_id *, int);
1067
int  ikev2_childsa_enable(struct iked *, struct iked_sa *);
1068
int  ikev2_childsa_delete(struct iked *, struct iked_sa *,
1069
      uint8_t, uint64_t, uint64_t *, int);
1070
void   ikev2_ikesa_recv_delete(struct iked *, struct iked_sa *);
1071
void   ikev2_ike_sa_timeout(struct iked *env, void *);
1072
void   ikev2_ike_sa_setreason(struct iked_sa *, char *);
1073
void   ikev2_reset_alive_timer(struct iked *);
1074
int  ikev2_ike_sa_delete(struct iked *, struct iked_sa *);
1075
1076
struct ibuf *
1077
   ikev2_prfplus(struct iked_hash *, struct ibuf *, struct ibuf *,
1078
      size_t);
1079
ssize_t  ikev2_psk(struct iked_sa *, uint8_t *, size_t, uint8_t **);
1080
ssize_t  ikev2_nat_detection(struct iked *, struct iked_message *,
1081
      void *, size_t, unsigned int, int);
1082
void   ikev2_enable_natt(struct iked *, struct iked_sa *,
1083
      struct iked_message *, int);
1084
int  ikev2_send_informational(struct iked *, struct iked_message *);
1085
int  ikev2_send_ike_e(struct iked *, struct iked_sa *, struct ibuf *,
1086
      uint8_t, uint8_t, int);
1087
struct ike_header *
1088
   ikev2_add_header(struct ibuf *, struct iked_sa *,
1089
      uint32_t, uint8_t, uint8_t, uint8_t);
1090
int  ikev2_set_header(struct ike_header *, size_t);
1091
struct ikev2_payload *
1092
   ikev2_add_payload(struct ibuf *);
1093
int  ikev2_next_payload(struct ikev2_payload *, size_t,
1094
      uint8_t);
1095
int  ikev2_child_sa_acquire(struct iked *, struct iked_flow *);
1096
int  ikev2_child_sa_drop(struct iked *, struct iked_spi *);
1097
int  ikev2_child_sa_rekey(struct iked *, struct iked_spi *);
1098
void   ikev2_disable_rekeying(struct iked *, struct iked_sa *);
1099
int  ikev2_print_id(struct iked_id *, char *, size_t);
1100
int  ikev2_print_static_id(struct iked_static_id *, char *, size_t);
1101
1102
const char  *ikev2_ikesa_info(uint64_t, const char *msg);
1103
#define SPI_IH(hdr)      ikev2_ikesa_info(betoh64((hdr)->ike_ispi), NULL)
1104
9.39k
#define SPI_SH(sh, f)    ikev2_ikesa_info((sh)->sh_ispi, (f))
1105
9.39k
#define SPI_SA(sa, f)    SPI_SH(&(sa)->sa_hdr, (f))
1106
1107
/* ikev2_msg.c */
1108
void   ikev2_msg_cb(int, short, void *);
1109
struct ibuf *
1110
   ikev2_msg_init(struct iked *, struct iked_message *,
1111
      struct sockaddr_storage *, socklen_t,
1112
      struct sockaddr_storage *, socklen_t, int);
1113
struct iked_message *
1114
   ikev2_msg_copy(struct iked *, struct iked_message *);
1115
void   ikev2_msg_cleanup(struct iked *, struct iked_message *);
1116
uint32_t
1117
   ikev2_msg_id(struct iked *, struct iked_sa *);
1118
struct ibuf
1119
  *ikev2_msg_auth(struct iked *, struct iked_sa *, int);
1120
int  ikev2_msg_authsign(struct iked *, struct iked_sa *,
1121
      struct iked_auth *, struct ibuf *);
1122
int  ikev2_msg_authverify(struct iked *, struct iked_sa *,
1123
      struct iked_auth *, uint8_t *, size_t, struct ibuf *);
1124
int  ikev2_msg_valid_ike_sa(struct iked *, struct ike_header *,
1125
      struct iked_message *);
1126
int  ikev2_msg_send(struct iked *, struct iked_message *);
1127
int  ikev2_msg_send_encrypt(struct iked *, struct iked_sa *,
1128
      struct ibuf **, uint8_t, uint8_t, int);
1129
struct ibuf
1130
  *ikev2_msg_encrypt(struct iked *, struct iked_sa *, struct ibuf *,
1131
      struct ibuf *);
1132
struct ibuf *
1133
   ikev2_msg_decrypt(struct iked *, struct iked_sa *,
1134
      struct ibuf *, struct ibuf *);
1135
int  ikev2_msg_integr(struct iked *, struct iked_sa *, struct ibuf *);
1136
int  ikev2_msg_frompeer(struct iked_message *);
1137
struct iked_socket *
1138
   ikev2_msg_getsocket(struct iked *, int, int);
1139
int  ikev2_msg_enqueue(struct iked *, struct iked_msgqueue *,
1140
      struct iked_message *, int);
1141
int  ikev2_msg_retransmit_response(struct iked *, struct iked_sa *,
1142
      struct iked_message *, uint8_t);
1143
void   ikev2_msg_prevail(struct iked *, struct iked_msgqueue *,
1144
      struct iked_message *);
1145
void   ikev2_msg_dispose(struct iked *, struct iked_msgqueue *,
1146
      struct iked_msg_retransmit *);
1147
void   ikev2_msg_flushqueue(struct iked *, struct iked_msgqueue *);
1148
struct iked_msg_retransmit *
1149
   ikev2_msg_lookup(struct iked *, struct iked_msgqueue *,
1150
      struct iked_message *, uint8_t);
1151
1152
/* ikev2_pld.c */
1153
int  ikev2_pld_parse(struct iked *, struct ike_header *,
1154
      struct iked_message *, size_t);
1155
1156
/* eap.c */
1157
int  eap_parse(struct iked *, const struct iked_sa *, struct iked_message*,
1158
      void *, int);
1159
int  eap_success(struct iked *, struct iked_sa *, int);
1160
int  eap_identity_request(struct iked *, struct iked_sa *);
1161
int  eap_mschap_challenge(struct iked *, struct iked_sa *, int, int,
1162
      uint8_t *, size_t);
1163
int  eap_mschap_success(struct iked *, struct iked_sa *, int);
1164
int  eap_challenge_request(struct iked *, struct iked_sa *, int);
1165
1166
/* pfkey.c */
1167
int  pfkey_couple(struct iked *, struct iked_sas *, int);
1168
int  pfkey_flow_add(struct iked *, struct iked_flow *);
1169
int  pfkey_flow_delete(struct iked *, struct iked_flow *);
1170
int  pfkey_sa_init(struct iked *, struct iked_childsa *, uint32_t *);
1171
int  pfkey_sa_add(struct iked *, struct iked_childsa *, struct iked_childsa *);
1172
int  pfkey_sa_update_addresses(struct iked *, struct iked_childsa *);
1173
int  pfkey_sa_delete(struct iked *, struct iked_childsa *);
1174
int  pfkey_sa_last_used(struct iked *, struct iked_childsa *, uint64_t *);
1175
int  pfkey_flush(struct iked *);
1176
int  pfkey_socket(struct iked *);
1177
void   pfkey_init(struct iked *, int fd);
1178
1179
/* ipsec.c */
1180
int  ipsec_couple(struct iked *, struct iked_sas *, int);
1181
int  ipsec_flow_add(struct iked *, struct iked_flow *);
1182
int  ipsec_flow_delete(struct iked *, struct iked_flow *);
1183
int  ipsec_sa_init(struct iked *, struct iked_childsa *, uint32_t *);
1184
int  ipsec_sa_add(struct iked *, struct iked_childsa *, struct iked_childsa *);
1185
int  ipsec_sa_update_addresses(struct iked *, struct iked_childsa *);
1186
int  ipsec_sa_delete(struct iked *, struct iked_childsa *);
1187
int  ipsec_sa_last_used(struct iked *, struct iked_childsa *, uint64_t *);
1188
int  ipsec_sa_rpl(struct iked *, struct iked_childsa *, uint32_t *);
1189
int  ipsec_sa_lifetimes(struct iked *, struct iked_childsa *, struct iked_lifetime *,
1190
       struct iked_lifetime *, struct iked_lifetime *);
1191
int  ipsec_flush(struct iked *);
1192
int  ipsec_socket(struct iked *);
1193
void   ipsec_init(struct iked *, int fd);
1194
1195
/* ca.c */
1196
void   caproc(struct privsep *, struct privsep_proc *);
1197
int  ca_setreq(struct iked *, struct iked_sa *, struct iked_static_id *,
1198
      uint8_t, uint8_t, uint8_t *, size_t, enum privsep_procid);
1199
int  ca_setcert(struct iked *, struct iked_sahdr *, struct iked_id *,
1200
      uint8_t, uint8_t *, size_t, enum privsep_procid);
1201
int  ca_setauth(struct iked *, struct iked_sa *,
1202
      struct ibuf *, enum privsep_procid);
1203
void   ca_getkey(struct privsep *, struct iked_id *, enum imsg_type);
1204
int  ca_certbundle_add(struct ibuf *, struct iked_id *);
1205
int  ca_privkey_serialize(EVP_PKEY *, struct iked_id *);
1206
int  ca_pubkey_serialize(EVP_PKEY *, struct iked_id *);
1207
void   ca_sslinit(void);
1208
void   ca_sslerror(const char *);
1209
char  *ca_asn1_name(uint8_t *, size_t);
1210
void  *ca_x509_name_parse(char *);
1211
void   ca_cert_info(const char *, X509 *);
1212
1213
/* timer.c */
1214
void   timer_set(struct iked *, struct iked_timer *,
1215
      void (*)(struct iked *, void *), void *);
1216
void   timer_add(struct iked *, struct iked_timer *, int);
1217
void   timer_del(struct iked *, struct iked_timer *);
1218
1219
/* proc.c */
1220
void   proc_init(struct privsep *, struct privsep_proc *, unsigned int, int,
1221
      int, char **, enum privsep_procid);
1222
void   proc_kill(struct privsep *);
1223
void   proc_connect(struct privsep *);
1224
void   proc_dispatch(int, short event, void *);
1225
void   proc_run(struct privsep *, struct privsep_proc *,
1226
      struct privsep_proc *, unsigned int,
1227
      void (*)(struct privsep *, struct privsep_proc *, void *), void *);
1228
void   imsg_event_add(struct imsgev *);
1229
int  imsg_compose_event(struct imsgev *, uint16_t, uint32_t,
1230
      pid_t, int, void *, uint16_t);
1231
int  imsg_composev_event(struct imsgev *, uint16_t, uint32_t,
1232
      pid_t, int, const struct iovec *, int);
1233
int  proc_compose_imsg(struct privsep *, enum privsep_procid, int,
1234
      uint16_t, uint32_t, int, void *, uint16_t);
1235
int  proc_compose(struct privsep *, enum privsep_procid,
1236
      uint16_t, void *, uint16_t);
1237
int  proc_composev_imsg(struct privsep *, enum privsep_procid, int,
1238
      uint16_t, uint32_t, int, const struct iovec *, int);
1239
int  proc_composev(struct privsep *, enum privsep_procid,
1240
      uint16_t, const struct iovec *, int);
1241
int  proc_forward_imsg(struct privsep *, struct imsg *,
1242
      enum privsep_procid, int);
1243
struct imsgbuf *
1244
   proc_ibuf(struct privsep *, enum privsep_procid, int);
1245
struct imsgev *
1246
   proc_iev(struct privsep *, enum privsep_procid, int);
1247
enum privsep_procid
1248
   proc_getid(struct privsep_proc *, unsigned int, const char *);
1249
int  proc_flush_imsg(struct privsep *, enum privsep_procid, int);
1250
1251
/* util.c */
1252
int  socket_af(struct sockaddr *, in_port_t);
1253
in_port_t
1254
   socket_getport(struct sockaddr *);
1255
int  socket_setport(struct sockaddr *, in_port_t);
1256
int  socket_getaddr(int, struct sockaddr_storage *);
1257
int  socket_bypass(int, struct sockaddr *);
1258
int  udp_bind(struct sockaddr *, in_port_t);
1259
ssize_t  sendtofrom(int, void *, size_t, int, struct sockaddr *,
1260
      socklen_t, struct sockaddr *, socklen_t);
1261
ssize_t  recvfromto(int, void *, size_t, int, struct sockaddr *,
1262
      socklen_t *, struct sockaddr *, socklen_t *);
1263
const char *
1264
   print_spi(uint64_t, int);
1265
const char *
1266
   print_map(unsigned int, struct iked_constmap *);
1267
void   lc_idtype(char *);
1268
void   print_hex(const uint8_t *, off_t, size_t);
1269
void   print_hexval(const uint8_t *, off_t, size_t);
1270
void   print_hexbuf(struct ibuf *);
1271
const char *
1272
   print_bits(unsigned short, unsigned char *);
1273
int  sockaddr_cmp(struct sockaddr *, struct sockaddr *, int);
1274
uint8_t mask2prefixlen(struct sockaddr *);
1275
uint8_t mask2prefixlen6(struct sockaddr *);
1276
struct in6_addr *
1277
   prefixlen2mask6(uint8_t, uint32_t *);
1278
uint32_t
1279
   prefixlen2mask(uint8_t);
1280
const char *
1281
   print_addr(void *);
1282
char  *get_string(uint8_t *, size_t);
1283
const char *
1284
   print_proto(uint8_t);
1285
int  expand_string(char *, size_t, const char *, const char *);
1286
uint8_t *string2unicode(const char *, size_t *);
1287
void   print_debug(const char *, ...)
1288
      __attribute__((format(printf, 1, 2)));
1289
void   print_verbose(const char *, ...)
1290
      __attribute__((format(printf, 1, 2)));
1291
1292
/* imsg_util.c */
1293
struct ibuf *
1294
   ibuf_new(const void *, size_t);
1295
struct ibuf *
1296
   ibuf_static(void);
1297
size_t   ibuf_length(struct ibuf *);
1298
int  ibuf_setsize(struct ibuf *, size_t);
1299
struct ibuf *
1300
   ibuf_getdata(struct ibuf *, size_t);
1301
struct ibuf *
1302
   ibuf_dup(struct ibuf *);
1303
struct ibuf *
1304
   ibuf_random(size_t);
1305
1306
/* log.c */
1307
void  log_init(int, int);
1308
void  log_procinit(const char *);
1309
void  log_setverbose(int);
1310
int log_getverbose(void);
1311
void  log_warn(const char *, ...)
1312
      __attribute__((__format__ (printf, 1, 2)));
1313
void  log_warnx(const char *, ...)
1314
      __attribute__((__format__ (printf, 1, 2)));
1315
void  log_info(const char *, ...)
1316
      __attribute__((__format__ (printf, 1, 2)));
1317
void  log_debug(const char *, ...)
1318
      __attribute__((__format__ (printf, 1, 2)));
1319
void  logit(int, const char *, ...)
1320
      __attribute__((__format__ (printf, 2, 3)));
1321
void  vlog(int, const char *, va_list)
1322
      __attribute__((__format__ (printf, 2, 0)));
1323
__dead void fatal(const char *, ...)
1324
      __attribute__((__format__ (printf, 1, 2)));
1325
__dead void fatalx(const char *, ...)
1326
      __attribute__((__format__ (printf, 1, 2)));
1327
1328
/* ocsp.c */
1329
int  ocsp_connect(struct iked *, struct imsg *);
1330
int  ocsp_receive_fd(struct iked *, struct imsg *);
1331
int  ocsp_validate_cert(struct iked *, void *, size_t, struct iked_sahdr,
1332
    uint8_t, X509 *);
1333
1334
/* parse.y */
1335
int  parse_config(const char *, struct iked *);
1336
int  cmdline_symset(char *);
1337
extern const struct ipsec_xf authxfs[];
1338
extern const struct ipsec_xf prfxfs[];
1339
extern const struct ipsec_xf *encxfs;
1340
extern const struct ipsec_xf ikeencxfs[];
1341
extern const struct ipsec_xf ipsecencxfs[];
1342
extern const struct ipsec_xf groupxfs[];
1343
extern const struct ipsec_xf esnxfs[];
1344
extern const struct ipsec_xf methodxfs[];
1345
extern const struct ipsec_xf saxfs[];
1346
extern const struct ipsec_xf cpxfs[];
1347
size_t   keylength_xf(unsigned int, unsigned int, unsigned int);
1348
size_t   noncelength_xf(unsigned int, unsigned int);
1349
int  encxf_noauth(unsigned int);
1350
1351
/* print.c */
1352
void   print_user(struct iked_user *);
1353
void   print_policy(struct iked_policy *);
1354
const char *print_xf(unsigned int, unsigned int, const struct ipsec_xf *);
1355
1356
#endif /* IKED_H */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/iked.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: iked.h,v 1.224 2023/08/11 11:24:55 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019-2021 Tobias Heider <tobhe@openbsd.org>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/tree.h>
22
#include <sys/queue.h>
23
#include <arpa/inet.h>
24
#include <limits.h>
25
#include <imsg.h>
26
27
#include <openssl/evp.h>
28
29
#include "openbsd-compat.h"
30
31
#include "types.h"
32
#include "dh.h"
33
34
#define MAXIMUM(a,b) (((a)>(b))?(a):(b))
35
#define MINIMUM(a,b) (((a)<(b))?(a):(b))
36
#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
37
38
#ifndef IKED_H
39
#define IKED_H
40
41
/*
42
 * Common IKEv1/IKEv2 header
43
 */
44
45
struct ike_header {
46
  uint64_t   ike_ispi;    /* Initiator cookie */
47
  uint64_t   ike_rspi;    /* Responder cookie */
48
  uint8_t    ike_nextpayload; /* Next payload type */
49
  uint8_t    ike_version;   /* Major/Minor version number */
50
  uint8_t    ike_exchange;    /* Exchange type */
51
  uint8_t    ike_flags;   /* Message options */
52
  uint32_t   ike_msgid;   /* Message identifier */
53
  uint32_t   ike_length;    /* Total message length */
54
} __packed;
55
56
/*
57
 * Common daemon infrastructure, local imsg etc.
58
 */
59
60
struct imsgev {
61
  struct imsgbuf     ibuf;
62
  void      (*handler)(int, short, void *);
63
  struct event     ev;
64
  struct privsep_proc *proc;
65
  void      *data;
66
  short      events;
67
  const char    *name;
68
};
69
70
#define IMSG_SIZE_CHECK(imsg, p) do {       \
71
  if (IMSG_DATA_SIZE(imsg) < sizeof(*p))      \
72
    fatalx("bad length imsg received");   \
73
} while (0)
74
#define IMSG_DATA_SIZE(imsg)  ((imsg)->hdr.len - IMSG_HEADER_SIZE)
75
76
#define IKED_ADDR_EQ(_a, _b)            \
77
  ((_a)->addr_mask == (_b)->addr_mask &&        \
78
  sockaddr_cmp((struct sockaddr *)&(_a)->addr,      \
79
  (struct sockaddr *)&(_b)->addr, (_a)->addr_mask) == 0)
80
81
#define IKED_ADDR_NEQ(_a, _b)           \
82
  ((_a)->addr_mask != (_b)->addr_mask ||        \
83
  sockaddr_cmp((struct sockaddr *)&(_a)->addr,      \
84
  (struct sockaddr *)&(_b)->addr, (_a)->addr_mask) != 0)
85
86
/* initially control.h */
87
struct control_sock {
88
  const char  *cs_name;
89
  struct event   cs_ev;
90
  struct event   cs_evt;
91
  int    cs_fd;
92
  int    cs_restricted;
93
  void    *cs_env;
94
95
  TAILQ_ENTRY(control_sock) cs_entry;
96
};
97
TAILQ_HEAD(control_socks, control_sock);
98
99
struct ctl_conn {
100
  TAILQ_ENTRY(ctl_conn)  entry;
101
  uint8_t      flags;
102
#define CTL_CONN_NOTIFY    0x01
103
  struct imsgev    iev;
104
};
105
TAILQ_HEAD(ctl_connlist, ctl_conn);
106
107
extern enum privsep_procid privsep_process;
108
109
/*
110
 * Runtime structures
111
 */
112
113
struct iked_timer {
114
  struct event   tmr_ev;
115
  struct iked *tmr_env;
116
  void    (*tmr_cb)(struct iked *, void *);
117
  void    *tmr_cbarg;
118
};
119
120
struct iked_spi {
121
  uint64_t   spi;
122
  uint8_t    spi_size;
123
  uint8_t    spi_protoid;
124
};
125
126
struct iked_proposal {
127
  uint8_t        prop_id;
128
  uint8_t        prop_protoid;
129
130
  struct iked_spi      prop_localspi;
131
  struct iked_spi      prop_peerspi;
132
133
  struct iked_transform   *prop_xforms;
134
  unsigned int       prop_nxforms;
135
136
  TAILQ_ENTRY(iked_proposal)   prop_entry;
137
};
138
TAILQ_HEAD(iked_proposals, iked_proposal);
139
140
struct iked_addr {
141
  int        addr_af;
142
  struct sockaddr_storage    addr;
143
  uint8_t        addr_mask;
144
  int        addr_net;
145
  in_port_t      addr_port;
146
};
147
148
struct iked_ts {
149
  struct iked_addr     ts_addr;
150
  uint8_t        ts_ipproto;
151
  TAILQ_ENTRY(iked_ts)     ts_entry;
152
};
153
TAILQ_HEAD(iked_tss, iked_ts);
154
155
struct iked_flow {
156
  struct iked_addr     flow_src;
157
  struct iked_addr     flow_dst;
158
  unsigned int       flow_dir;  /* in/out */
159
  int        flow_rdomain;
160
  struct iked_addr     flow_prenat;
161
  int        flow_fixed;
162
163
  unsigned int       flow_loaded; /* pfkey done */
164
165
  uint8_t        flow_saproto;
166
  uint8_t        flow_ipproto;
167
168
  struct iked_addr    *flow_local;  /* outer source */
169
  struct iked_addr    *flow_peer; /* outer dest */
170
  struct iked_sa      *flow_ikesa;  /* parent SA */
171
172
  int        flow_transport;
173
174
  RB_ENTRY(iked_flow)    flow_node;
175
  TAILQ_ENTRY(iked_flow)     flow_entry;
176
};
177
RB_HEAD(iked_flows, iked_flow);
178
TAILQ_HEAD(iked_saflows, iked_flow);
179
180
struct iked_childsa {
181
  uint8_t        csa_saproto; /* IPsec protocol */
182
  unsigned int       csa_dir; /* in/out */
183
184
  uint64_t       csa_peerspi; /* peer relation */
185
  uint8_t        csa_loaded;  /* pfkey done */
186
  uint8_t        csa_rekey; /* will be deleted */
187
  uint8_t        csa_allocated; /* from the kernel */
188
  uint8_t        csa_persistent;/* do not rekey */
189
  uint8_t        csa_esn; /* use ESN */
190
  uint8_t        csa_transport; /* transport mode */
191
192
  struct iked_spi      csa_spi;
193
194
  struct ibuf     *csa_encrkey; /* encryption key */
195
  uint16_t       csa_encrid;  /* encryption xform id */
196
197
  struct ibuf     *csa_integrkey; /* auth key */
198
  uint16_t       csa_integrid;  /* auth xform id */
199
200
  struct iked_addr    *csa_local; /* outer source */
201
  struct iked_addr    *csa_peer;  /* outer dest */
202
  struct iked_sa      *csa_ikesa; /* parent SA */
203
204
  struct iked_childsa   *csa_peersa;  /* peer */
205
206
  struct iked_childsa   *csa_bundled; /* IPCOMP */
207
208
  uint16_t       csa_pfsgrpid;  /* pfs group id */
209
210
  RB_ENTRY(iked_childsa)     csa_node;
211
  TAILQ_ENTRY(iked_childsa)  csa_entry;
212
};
213
RB_HEAD(iked_activesas, iked_childsa);
214
TAILQ_HEAD(iked_childsas, iked_childsa);
215
216
217
struct iked_static_id {
218
  uint8_t   id_type;
219
  uint8_t   id_length;
220
  uint8_t   id_offset;
221
  uint8_t   id_data[IKED_ID_SIZE];
222
};
223
224
struct iked_auth {
225
  uint8_t   auth_method;
226
  uint8_t   auth_eap;     /* optional EAP */
227
  uint8_t   auth_length;      /* zero if EAP */
228
  uint8_t   auth_data[IKED_PSK_SIZE];
229
};
230
231
struct iked_cfg {
232
  uint8_t        cfg_action;
233
  uint16_t       cfg_type;
234
  union {
235
    struct iked_addr   address;
236
  } cfg;
237
};
238
239
TAILQ_HEAD(iked_sapeers, iked_sa);
240
241
struct iked_lifetime {
242
  uint64_t       lt_bytes;
243
  uint64_t       lt_seconds;
244
};
245
246
struct iked_policy {
247
  unsigned int       pol_id;
248
  char         pol_name[IKED_ID_SIZE];
249
  unsigned int       pol_iface;
250
251
#define IKED_SKIP_FLAGS      0
252
#define IKED_SKIP_AF       1
253
#define IKED_SKIP_SRC_ADDR     2
254
#define IKED_SKIP_DST_ADDR     3
255
#define IKED_SKIP_COUNT      4
256
  struct iked_policy    *pol_skip[IKED_SKIP_COUNT];
257
258
  uint8_t        pol_flags;
259
#define IKED_POLICY_PASSIVE    0x00
260
#define IKED_POLICY_DEFAULT    0x01
261
#define IKED_POLICY_ACTIVE     0x02
262
#define IKED_POLICY_REFCNT     0x04
263
#define IKED_POLICY_QUICK    0x08
264
#define IKED_POLICY_SKIP     0x10
265
#define IKED_POLICY_IPCOMP     0x20
266
0
#define IKED_POLICY_TRANSPORT    0x40
267
#define IKED_POLICY_ROUTING    0x80
268
269
  int        pol_refcnt;
270
271
  uint8_t        pol_certreqtype;
272
273
  int        pol_af;
274
  int        pol_rdomain;
275
  uint8_t        pol_saproto;
276
  unsigned int       pol_ipproto[IKED_IPPROTO_MAX];
277
  unsigned int       pol_nipproto;
278
279
  struct iked_addr     pol_peer;
280
  struct iked_static_id    pol_peerid;
281
  uint32_t       pol_peerdh;
282
283
  struct iked_addr     pol_local;
284
  struct iked_static_id    pol_localid;
285
286
  struct iked_auth     pol_auth;
287
288
  char         pol_tag[IKED_TAG_SIZE];
289
  unsigned int       pol_tap;
290
291
  struct iked_proposals    pol_proposals;
292
  size_t         pol_nproposals;
293
294
  struct iked_flows    pol_flows;
295
  size_t         pol_nflows;
296
  struct iked_tss      pol_tssrc; /* Traffic Selectors Initiator*/
297
  size_t         pol_tssrc_count;
298
  struct iked_tss      pol_tsdst; /* Traffic Selectors Responder*/
299
  size_t         pol_tsdst_count;
300
301
  struct iked_cfg      pol_cfg[IKED_CFG_MAX];
302
  unsigned int       pol_ncfg;
303
304
  uint32_t       pol_rekey; /* ike SA lifetime */
305
  struct iked_lifetime     pol_lifetime;  /* child SA lifetime */
306
307
  struct iked_sapeers    pol_sapeers;
308
309
  TAILQ_ENTRY(iked_policy)   pol_entry;
310
};
311
TAILQ_HEAD(iked_policies, iked_policy);
312
313
struct iked_hash {
314
  uint8_t    hash_type; /* PRF or INTEGR */
315
  uint16_t   hash_id; /* IKE PRF/INTEGR hash id */
316
  const void  *hash_priv; /* Identifying the hash alg */
317
  void    *hash_ctx;  /* Context of the current invocation */
318
  int    hash_fixedkey; /* Requires fixed key length */
319
  struct ibuf *hash_key;  /* MAC key derived from key seed */
320
  size_t     hash_length; /* Output length */
321
  size_t     hash_trunc;  /* Truncate the output length */
322
  struct iked_hash *hash_prf; /* PRF pointer */
323
  int    hash_isaead;
324
};
325
326
struct iked_cipher {
327
  uint8_t    encr_type; /* ENCR */
328
  uint16_t   encr_id; /* IKE ENCR hash id */
329
  const void  *encr_priv; /* Identifying the hash alg */
330
  void    *encr_ctx;  /* Context of the current invocation */
331
  int    encr_fixedkey; /* Requires fixed key length */
332
  struct ibuf *encr_key;  /* MAC key derived from key seed */
333
  struct ibuf *encr_iv; /* Initialization Vector */
334
  uint64_t   encr_civ;  /* Counter IV for GCM */
335
  size_t     encr_ivlength; /* IV length */
336
  size_t     encr_length; /* Block length */
337
  size_t     encr_saltlength; /* IV salt length */
338
  uint16_t   encr_authid; /* ID of associated authentication */
339
};
340
341
struct iked_dsa {
342
  uint8_t    dsa_method;  /* AUTH method */
343
  const void  *dsa_priv;  /* PRF or signature hash function */
344
  void    *dsa_ctx; /* PRF or signature hash ctx */
345
  struct ibuf *dsa_keydata; /* public, private or shared key */
346
  void    *dsa_key; /* parsed public or private key */
347
  int    dsa_hmac;  /* HMAC or public/private key */
348
  int    dsa_sign;  /* Sign or verify operation */
349
  uint32_t   dsa_flags; /* State flags */
350
};
351
352
struct iked_id {
353
  uint8_t    id_type;
354
  uint8_t    id_offset;
355
  struct ibuf *id_buf;
356
};
357
358
#define IKED_REQ_CERT   0x0001  /* get local certificate (if required) */
359
#define IKED_REQ_CERTVALID  0x0002  /* validated the peer cert */
360
#define IKED_REQ_CERTREQ  0x0004  /* CERTREQ has been received */
361
#define IKED_REQ_AUTH   0x0008  /* AUTH payload */
362
#define IKED_REQ_AUTHVALID  0x0010  /* AUTH payload has been verified */
363
#define IKED_REQ_SA   0x0020  /* SA available */
364
#define IKED_REQ_EAPVALID 0x0040  /* EAP payload has been verified */
365
#define IKED_REQ_CHILDSA  0x0080  /* Child SA initiated */
366
#define IKED_REQ_INF    0x0100  /* Informational exchange initiated */
367
368
#define IKED_REQ_BITS \
369
    "\20\01CERT\02CERTVALID\03CERTREQ\04AUTH\05AUTHVALID\06SA\07EAPVALID" \
370
    "\10CHILDSA\11INF"
371
372
TAILQ_HEAD(iked_msgqueue, iked_msg_retransmit);
373
TAILQ_HEAD(iked_msg_fragqueue, iked_message);
374
375
struct iked_sahdr {
376
  uint64_t       sh_ispi; /* Initiator SPI */
377
  uint64_t       sh_rspi; /* Responder SPI */
378
  unsigned int       sh_initiator;  /* Is initiator? */
379
} __packed;
380
381
struct iked_kex {
382
  struct ibuf     *kex_inonce;  /* Ni */
383
  struct ibuf     *kex_rnonce;  /* Nr */
384
385
  struct dh_group     *kex_dhgroup; /* DH group */
386
  struct ibuf     *kex_dhiexchange;
387
  struct ibuf     *kex_dhrexchange;
388
  struct ibuf     *kex_dhpeer;  /* pointer to i or r */
389
};
390
391
struct iked_frag_entry {
392
  uint8_t *frag_data;
393
  size_t   frag_size;
394
};
395
396
struct iked_frag {
397
  struct iked_frag_entry  **frag_arr; /* list of fragment buffers */
398
  size_t        frag_count; /* number of fragments received */
399
0
#define IKED_FRAG_TOTAL_MAX   111    /* upper limit (64kB / 576B) */
400
  size_t        frag_total; /* total numbe of fragments */
401
  size_t        frag_total_size;
402
  uint8_t       frag_nextpayload;
403
404
};
405
406
struct iked_ipcomp {
407
  uint16_t       ic_cpi_out;  /* outgoing CPI */
408
  uint16_t       ic_cpi_in; /* incoming CPI */
409
  uint8_t        ic_transform;  /* transform */
410
};
411
412
struct iked_sa {
413
  struct iked_sahdr    sa_hdr;
414
  uint32_t       sa_msgid;  /* Last request rcvd */
415
  int        sa_msgid_set;  /* msgid initialized */
416
  uint32_t       sa_msgid_current;  /* Current requested rcvd */
417
  uint32_t       sa_reqid;  /* Next request sent */
418
419
  int        sa_type;
420
#define IKED_SATYPE_LOOKUP     0    /* Used for lookup */
421
#define IKED_SATYPE_LOCAL    1    /* Local SA */
422
423
  struct iked_addr     sa_peer;
424
  struct iked_addr     sa_peer_loaded;/* MOBIKE */
425
  struct iked_addr     sa_local;
426
  int        sa_fd;
427
428
  struct iked_frag     sa_fragments;
429
430
  int        sa_natt; /* for IKE messages */
431
  int        sa_udpencap; /* for pfkey */
432
  int        sa_usekeepalive;/* NAT-T keepalive */
433
434
  int        sa_state;
435
  unsigned int       sa_stateflags;
436
  unsigned int       sa_stateinit;  /* SA_INIT */
437
  unsigned int       sa_statevalid; /* IKE_AUTH */
438
439
  int        sa_cp;   /* XXX */
440
  struct iked_addr    *sa_cp_addr;  /* requested address */
441
  struct iked_addr    *sa_cp_addr6; /* requested address */
442
  struct iked_addr    *sa_cp_dns; /* requested dns */
443
444
  struct iked_policy    *sa_policy;
445
  struct timeval       sa_timecreated;
446
  struct timeval       sa_timeused;
447
448
  char        *sa_tag;
449
  const char      *sa_reason; /* reason for close */
450
451
  struct iked_kex      sa_kex;
452
/* XXX compat defines until everything is converted */
453
#define sa_inonce   sa_kex.kex_inonce
454
#define sa_rnonce   sa_kex.kex_rnonce
455
#define sa_dhgroup    sa_kex.kex_dhgroup
456
#define sa_dhiexchange    sa_kex.kex_dhiexchange
457
#define sa_dhrexchange    sa_kex.kex_dhrexchange
458
#define sa_dhpeer   sa_kex.kex_dhpeer
459
460
  struct iked_hash    *sa_prf;  /* PRF alg */
461
  struct iked_hash    *sa_integr; /* integrity alg */
462
  struct iked_cipher    *sa_encr; /* encryption alg */
463
464
  struct ibuf     *sa_key_d;  /* SK_d */
465
  struct ibuf     *sa_key_iauth;  /* SK_ai */
466
  struct ibuf     *sa_key_rauth;  /* SK_ar */
467
  struct ibuf     *sa_key_iencr;  /* SK_ei */
468
  struct ibuf     *sa_key_rencr;  /* SK_er */
469
  struct ibuf     *sa_key_iprf; /* SK_pi */
470
  struct ibuf     *sa_key_rprf; /* SK_pr */
471
472
  struct ibuf     *sa_1stmsg; /* for initiator AUTH */
473
  struct ibuf     *sa_2ndmsg; /* for responder AUTH */
474
  struct iked_id       sa_localauth;  /* local AUTH message */
475
  struct iked_id       sa_peerauth; /* peer AUTH message */
476
  int        sa_sigsha2;  /* use SHA2 for signatures */
477
130k
#define IKED_SCERT_MAX  3 /* max # of supplemental cert payloads */
478
479
  struct iked_id       sa_iid;  /* initiator id */
480
  struct iked_id       sa_rid;  /* responder id */
481
  struct iked_id       sa_icert;  /* initiator cert */
482
  struct iked_id       sa_rcert;  /* responder cert */
483
  struct iked_id       sa_scert[IKED_SCERT_MAX]; /* supplemental certs */
484
#define IKESA_SRCID(x) ((x)->sa_hdr.sh_initiator ? &(x)->sa_iid : &(x)->sa_rid)
485
#define IKESA_DSTID(x) ((x)->sa_hdr.sh_initiator ? &(x)->sa_rid : &(x)->sa_iid)
486
487
  char        *sa_eapid;  /* EAP identity */
488
  struct iked_id       sa_eap;  /* EAP challenge */
489
  struct ibuf     *sa_eapmsk; /* EAK session key */
490
491
  struct iked_proposals    sa_proposals;  /* SA proposals */
492
  struct iked_childsas     sa_childsas; /* IPsec Child SAs */
493
  struct iked_saflows    sa_flows;  /* IPsec flows */
494
495
  struct iked_sa      *sa_nexti;  /* initiated IKE SA */
496
  struct iked_sa      *sa_previ;  /* matching back pointer */
497
  struct iked_sa      *sa_nextr;  /* simultaneous rekey */
498
  struct iked_sa      *sa_prevr;  /* matching back pointer */
499
  uint64_t       sa_rekeyspi; /* peerspi CSA rekey */
500
  struct ibuf     *sa_simult; /* simultaneous rekey */
501
502
  struct iked_ipcomp     sa_ipcompi;  /* IPcomp initator */
503
  struct iked_ipcomp     sa_ipcompr;  /* IPcomp responder */
504
505
  int        sa_mobike; /* MOBIKE */
506
  int        sa_frag; /* fragmentation */
507
508
  int        sa_use_transport_mode; /* peer requested */
509
  int        sa_used_transport_mode; /* we enabled */
510
511
  struct iked_timer    sa_timer;  /* SA timeouts */
512
#define IKED_IKE_SA_EXCHANGE_TIMEOUT   300    /* 5 minutes */
513
#define IKED_IKE_SA_REKEY_TIMEOUT  120    /* 2 minutes */
514
#define IKED_IKE_SA_DELETE_TIMEOUT   120    /* 2 minutes */
515
#define IKED_IKE_SA_ALIVE_TIMEOUT  60   /* 1 minute */
516
517
  struct iked_timer    sa_keepalive;  /* keepalive timer */
518
#define IKED_IKE_SA_KEEPALIVE_TIMEOUT  20
519
520
  struct iked_timer    sa_rekey;  /* rekey timeout */
521
  int        sa_tmpfail;
522
523
  struct iked_msgqueue     sa_requests; /* request queue */
524
#define IKED_RETRANSMIT_TIMEOUT    2    /* 2 seconds */
525
526
  struct iked_msgqueue     sa_responses;  /* response queue */
527
#define IKED_RESPONSE_TIMEOUT    120    /* 2 minutes */
528
529
  TAILQ_ENTRY(iked_sa)     sa_peer_entry;
530
  RB_ENTRY(iked_sa)    sa_entry;  /* all SAs */
531
532
  RB_ENTRY(iked_sa)    sa_dstid_entry;  /* SAs by DSTID */
533
  int        sa_dstid_entry_valid;    /* sa_dstid_entry valid */
534
535
  struct iked_addr    *sa_addrpool; /* address from pool */
536
  RB_ENTRY(iked_sa)    sa_addrpool_entry; /* pool entries */
537
538
  struct iked_addr    *sa_addrpool6;  /* address from pool */
539
  RB_ENTRY(iked_sa)    sa_addrpool6_entry;  /* pool entries */
540
  time_t         sa_last_recvd;
541
#define IKED_IKE_SA_LAST_RECVD_TIMEOUT   300    /* 5 minutes */
542
};
543
RB_HEAD(iked_sas, iked_sa);
544
RB_HEAD(iked_dstid_sas, iked_sa);
545
RB_HEAD(iked_addrpool, iked_sa);
546
RB_HEAD(iked_addrpool6, iked_sa);
547
548
/* stats */
549
550
struct iked_stats {
551
  uint64_t  ikes_sa_created;
552
  uint64_t  ikes_sa_established_total;
553
  uint64_t  ikes_sa_established_current;  /* gauge */
554
  uint64_t  ikes_sa_established_failures;
555
  uint64_t  ikes_sa_proposals_negotiate_failures;
556
  uint64_t  ikes_sa_rekeyed;
557
  uint64_t  ikes_sa_removed;
558
  uint64_t  ikes_csa_created;
559
  uint64_t  ikes_csa_removed;
560
  uint64_t  ikes_msg_sent;
561
  uint64_t  ikes_msg_send_failures;
562
  uint64_t  ikes_msg_rcvd;
563
  uint64_t  ikes_msg_rcvd_busy;
564
  uint64_t  ikes_msg_rcvd_dropped;
565
  uint64_t  ikes_retransmit_request;
566
  uint64_t  ikes_retransmit_response;
567
  uint64_t  ikes_retransmit_limit;
568
  uint64_t  ikes_frag_sent;
569
  uint64_t  ikes_frag_send_failures;
570
  uint64_t  ikes_frag_rcvd;
571
  uint64_t  ikes_frag_rcvd_drop;
572
  uint64_t  ikes_frag_reass_ok;
573
  uint64_t  ikes_frag_reass_drop;
574
  uint64_t  ikes_update_addresses_sent;
575
  uint64_t  ikes_dpd_sent;
576
  uint64_t  ikes_keepalive_sent;
577
};
578
579
0
#define ikestat_add(env, c, n)  do { env->sc_stats.c += (n); } while(0)
580
0
#define ikestat_inc(env, c) ikestat_add(env, c, 1)
581
#define ikestat_dec(env, c) ikestat_add(env, c, -1)
582
583
struct iked_certreq {
584
  struct ibuf     *cr_data;
585
  uint8_t        cr_type;
586
  SIMPLEQ_ENTRY(iked_certreq)  cr_entry;
587
};
588
SIMPLEQ_HEAD(iked_certreqs, iked_certreq);
589
590
#define EAP_STATE_IDENTITY    (1)
591
#define EAP_STATE_MSCHAPV2_CHALLENGE  (2)
592
#define EAP_STATE_MSCHAPV2_SUCCESS  (3)
593
#define EAP_STATE_SUCCESS   (4)
594
595
struct eap_msg {
596
  char    *eam_identity;
597
  char    *eam_user;
598
  int    eam_type;
599
  uint8_t    eam_id;
600
  uint8_t    eam_msrid;
601
  int    eam_success;
602
  int    eam_found;
603
  int    eam_response;
604
  uint8_t    eam_challenge[16];
605
  uint8_t    eam_ntresponse[24];
606
  uint32_t   eam_state;
607
};
608
609
struct iked_message {
610
  struct ibuf   *msg_data;
611
  size_t       msg_offset;
612
613
  struct sockaddr_storage  msg_local;
614
  socklen_t    msg_locallen;
615
616
  struct sockaddr_storage  msg_peer;
617
  socklen_t    msg_peerlen;
618
619
  struct iked_socket  *msg_sock;
620
621
  int      msg_fd;
622
  int      msg_response;
623
  int      msg_responded;
624
  int      msg_valid;
625
  int      msg_natt;
626
  int      msg_natt_rcvd;
627
  int      msg_nat_detected;
628
  int      msg_error;
629
  int      msg_e;
630
  struct iked_message *msg_parent;
631
632
  /* Associated policy and SA */
633
  struct iked_policy  *msg_policy;
634
  struct iked_sa    *msg_sa;
635
636
  uint32_t     msg_msgid;
637
  uint8_t      msg_exchange;
638
639
  /* Parsed information */
640
  struct iked_proposals  msg_proposals;
641
  struct iked_certreqs   msg_certreqs;
642
  struct iked_spi    msg_rekey;
643
  struct ibuf   *msg_nonce; /* dh NONCE */
644
  uint16_t     msg_dhgroup; /* dh group */
645
  struct ibuf   *msg_ke;  /* dh key exchange */
646
  struct iked_id     msg_auth;  /* AUTH payload */
647
  struct iked_id     msg_peerid;
648
  struct iked_id     msg_localid;
649
  struct iked_id     msg_cert;
650
  struct iked_id     msg_scert[IKED_SCERT_MAX]; /* supplemental certs */
651
  struct ibuf   *msg_cookie;
652
  uint16_t     msg_group;
653
  uint16_t     msg_cpi;
654
  uint8_t      msg_transform;
655
  uint16_t     msg_flags;
656
  struct eap_msg     msg_eap;
657
  size_t       msg_del_spisize;
658
  size_t       msg_del_cnt;
659
  struct ibuf   *msg_del_buf;
660
  int      msg_del_protoid;
661
  int      msg_cp;
662
  struct iked_addr  *msg_cp_addr; /* requested address */
663
  struct iked_addr  *msg_cp_addr6;  /* requested address */
664
  struct iked_addr  *msg_cp_dns;  /* requested dns */
665
666
  /* MOBIKE */
667
  int      msg_update_sa_addresses;
668
  struct ibuf   *msg_cookie2;
669
670
  /* Parse stack */
671
  struct iked_proposal  *msg_prop;
672
  uint16_t     msg_attrlength;
673
674
  /* Retransmit queue */
675
  TAILQ_ENTRY(iked_message)
676
         msg_entry;
677
};
678
679
struct iked_msg_retransmit {
680
  struct iked_msg_fragqueue       mrt_frags;
681
  TAILQ_ENTRY(iked_msg_retransmit)      mrt_entry;
682
  struct iked_timer         mrt_timer;
683
  int             mrt_tries;
684
#define IKED_RETRANSMIT_TRIES  5    /* try 5 times */
685
};
686
687
3.34k
#define IKED_MSG_NAT_SRC_IP       0x01
688
22.4k
#define IKED_MSG_NAT_DST_IP       0x02
689
690
0
#define IKED_MSG_FLAGS_FRAGMENTATION      0x0001
691
159
#define IKED_MSG_FLAGS_MOBIKE       0x0002
692
0
#define IKED_MSG_FLAGS_SIGSHA2        0x0004
693
73
#define IKED_MSG_FLAGS_CHILD_SA_NOT_FOUND   0x0008
694
273
#define IKED_MSG_FLAGS_NO_ADDITIONAL_SAS    0x0010
695
0
#define IKED_MSG_FLAGS_AUTHENTICATION_FAILED    0x0020
696
139
#define IKED_MSG_FLAGS_INVALID_KE     0x0040
697
128
#define IKED_MSG_FLAGS_IPCOMP_SUPPORTED     0x0080
698
279
#define IKED_MSG_FLAGS_USE_TRANSPORT      0x0100
699
354
#define IKED_MSG_FLAGS_TEMPORARY_FAILURE    0x0200
700
36
#define IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN   0x0400
701
702
703
struct iked_user {
704
  char       usr_name[LOGIN_NAME_MAX];
705
  char       usr_pass[IKED_PASSWORD_SIZE];
706
  RB_ENTRY(iked_user)  usr_entry;
707
};
708
RB_HEAD(iked_users, iked_user);
709
710
struct privsep_pipes {
711
  int       *pp_pipes[PROC_MAX];
712
};
713
714
struct privsep {
715
  struct privsep_pipes    *ps_pipes[PROC_MAX];
716
  struct privsep_pipes    *ps_pp;
717
718
  struct imsgev     *ps_ievs[PROC_MAX];
719
  const char      *ps_title[PROC_MAX];
720
  pid_t        ps_pid[PROC_MAX];
721
  struct passwd     *ps_pw;
722
  int        ps_noaction;
723
724
  struct control_sock    ps_csock;
725
  struct control_socks     ps_rcsocks;
726
727
  unsigned int       ps_instances[PROC_MAX];
728
  unsigned int       ps_ninstances;
729
  unsigned int       ps_instance;
730
731
  /* Event and signal handlers */
732
  struct event       ps_evsigint;
733
  struct event       ps_evsigterm;
734
  struct event       ps_evsigchld;
735
  struct event       ps_evsighup;
736
  struct event       ps_evsigpipe;
737
  struct event       ps_evsigusr1;
738
739
  struct iked     *ps_env;
740
};
741
742
struct privsep_proc {
743
  const char    *p_title;
744
  enum privsep_procid  p_id;
745
  int     (*p_cb)(int, struct privsep_proc *,
746
            struct imsg *);
747
  void      (*p_init)(struct privsep *,
748
            struct privsep_proc *);
749
  const char    *p_chroot;
750
  struct passwd   *p_pw;
751
  struct privsep    *p_ps;
752
  void      (*p_shutdown)(void);
753
};
754
755
struct privsep_fd {
756
  enum privsep_procid    pf_procid;
757
  unsigned int       pf_instance;
758
};
759
760
#define PROC_PARENT_SOCK_FILENO 3
761
#define PROC_MAX_INSTANCES      32
762
763
struct iked_ocsp_entry {
764
  TAILQ_ENTRY(iked_ocsp_entry) ioe_entry; /* next request */
765
  void      *ioe_ocsp;  /* private ocsp request data */
766
};
767
TAILQ_HEAD(iked_ocsp_requests, iked_ocsp_entry);
768
769
/*
770
 * Daemon configuration
771
 */
772
773
enum natt_mode {
774
  NATT_DEFAULT, /* send/recv with both :500 and NAT-T port */
775
  NATT_DISABLE, /* send/recv with only :500 */
776
  NATT_FORCE, /* send/recv with only NAT-T port */
777
};
778
779
struct iked_static {
780
  uint64_t     st_alive_timeout;
781
  int      st_enforcesingleikesa;
782
  uint8_t      st_frag; /* fragmentation */
783
  uint8_t      st_mobike; /* MOBIKE */
784
  in_port_t    st_nattport;
785
  int      st_stickyaddress; /* addr per DSTID  */
786
  int      st_vendorid;
787
};
788
789
struct iked {
790
  char         sc_conffile[PATH_MAX];
791
792
  uint32_t       sc_opts;
793
  enum natt_mode       sc_nattmode;
794
  uint8_t        sc_passive;
795
  uint8_t        sc_decoupled;
796
797
  struct iked_static     sc_static;
798
799
#define sc_alive_timeout  sc_static.st_alive_timeout
800
#define sc_enforcesingleikesa sc_static.st_enforcesingleikesa
801
#define sc_frag     sc_static.st_frag
802
#define sc_mobike   sc_static.st_mobike
803
#define sc_nattport   sc_static.st_nattport
804
#define sc_stickyaddress  sc_static.st_stickyaddress
805
#define sc_vendorid   sc_static.st_vendorid
806
807
  struct iked_policies     sc_policies;
808
  struct iked_policy    *sc_defaultcon;
809
810
  struct iked_sas      sc_sas;
811
  struct iked_dstid_sas    sc_dstid_sas;
812
  struct iked_activesas    sc_activesas;
813
  struct iked_flows    sc_activeflows;
814
  struct iked_users    sc_users;
815
816
  struct iked_stats    sc_stats;
817
818
  void        *sc_priv; /* per-process */
819
820
  int        sc_pfkey;  /* ike process */
821
  struct event       sc_pfkeyev;
822
  struct event       sc_routeev;
823
  uint8_t        sc_certreqtype;
824
  struct ibuf     *sc_certreq;
825
  void        *sc_vroute;
826
827
  struct iked_socket    *sc_sock4[2];
828
  struct iked_socket    *sc_sock6[2];
829
830
  struct iked_timer    sc_inittmr;
831
#define IKED_INITIATOR_INITIAL     2
832
#define IKED_INITIATOR_INTERVAL    60
833
834
  struct privsep       sc_ps;
835
836
  struct iked_ocsp_requests  sc_ocsp;
837
  char        *sc_ocsp_url;
838
  long         sc_ocsp_tolerate;
839
  long         sc_ocsp_maxage;
840
841
  struct iked_addrpool     sc_addrpool;
842
  struct iked_addrpool6    sc_addrpool6;
843
844
  int        sc_cert_partial_chain;
845
#ifdef WITH_APPARMOR
846
  int        sc_apparmor;
847
#endif
848
};
849
850
struct iked_socket {
851
  int      sock_fd;
852
  struct event     sock_ev;
853
  struct iked   *sock_env;
854
  struct sockaddr_storage  sock_addr;
855
};
856
857
struct ipsec_xf {
858
  const char  *name;
859
  unsigned int   id;
860
  unsigned int   length;
861
  unsigned int   keylength;
862
  unsigned int   nonce;
863
  unsigned int   noauth;
864
};
865
866
struct ipsec_transforms {
867
  const struct ipsec_xf **authxf;
868
  unsigned int      nauthxf;
869
  const struct ipsec_xf **prfxf;
870
  unsigned int      nprfxf;
871
  const struct ipsec_xf **encxf;
872
  unsigned int      nencxf;
873
  const struct ipsec_xf **groupxf;
874
  unsigned int      ngroupxf;
875
  const struct ipsec_xf **esnxf;
876
  unsigned int      nesnxf;
877
};
878
879
struct ipsec_mode {
880
  struct ipsec_transforms **xfs;
881
  unsigned int      nxfs;
882
};
883
884
/* iked.c */
885
void   parent_reload(struct iked *, int, const char *);
886
887
extern struct iked  *iked_env;
888
889
/* control.c */
890
void   control(struct privsep *, struct privsep_proc *);
891
int  control_init(struct privsep *, struct control_sock *);
892
int  control_listen(struct control_sock *);
893
894
/* config.c */
895
struct iked_policy *
896
   config_new_policy(struct iked *);
897
void   config_free_kex(struct iked_kex *);
898
void   config_free_fragments(struct iked_frag *);
899
void   config_free_sa(struct iked *, struct iked_sa *);
900
struct iked_sa *
901
   config_new_sa(struct iked *, int);
902
struct iked_user *
903
   config_new_user(struct iked *, struct iked_user *);
904
uint64_t
905
   config_getspi(void);
906
struct iked_transform *
907
   config_findtransform(struct iked_proposals *, uint8_t, unsigned int);
908
struct iked_transform *
909
   config_findtransform_ext(struct iked_proposals *, uint8_t,int, unsigned int);
910
void   config_free_policy(struct iked *, struct iked_policy *);
911
struct iked_proposal *
912
   config_add_proposal(struct iked_proposals *, unsigned int,
913
      unsigned int);
914
void   config_free_proposal(struct iked_proposals *, struct iked_proposal *);
915
void   config_free_proposals(struct iked_proposals *, unsigned int);
916
void   config_free_flows(struct iked *, struct iked_flows *);
917
void   config_free_childsas(struct iked *, struct iked_childsas *,
918
      struct iked_spi *, struct iked_spi *);
919
int  config_add_transform(struct iked_proposal *,
920
      unsigned int, unsigned int, unsigned int, unsigned int);
921
int  config_setcoupled(struct iked *, unsigned int);
922
int  config_getcoupled(struct iked *, unsigned int);
923
int  config_setmode(struct iked *, unsigned int);
924
int  config_getmode(struct iked *, unsigned int);
925
int  config_setreset(struct iked *, unsigned int, enum privsep_procid);
926
int  config_getreset(struct iked *, struct imsg *);
927
int  config_doreset(struct iked *, unsigned int);
928
int  config_setpolicy(struct iked *, struct iked_policy *,
929
      enum privsep_procid);
930
int  config_getpolicy(struct iked *, struct imsg *);
931
int  config_setflow(struct iked *, struct iked_policy *,
932
      enum privsep_procid);
933
int  config_getflow(struct iked *, struct imsg *);
934
int  config_setsocket(struct iked *, struct sockaddr_storage *, in_port_t,
935
      enum privsep_procid, int);
936
int  config_getsocket(struct iked *env, struct imsg *,
937
      void (*cb)(int, short, void *));
938
int  config_setpfkey(struct iked *);
939
int  config_getpfkey(struct iked *, struct imsg *);
940
int  config_setuser(struct iked *, struct iked_user *, enum privsep_procid);
941
int  config_getuser(struct iked *, struct imsg *);
942
int  config_setcompile(struct iked *, enum privsep_procid);
943
int  config_getcompile(struct iked *);
944
int  config_setocsp(struct iked *);
945
int  config_getocsp(struct iked *, struct imsg *);
946
int  config_setkeys(struct iked *);
947
int  config_getkey(struct iked *, struct imsg *);
948
int  config_setstatic(struct iked *);
949
int  config_getstatic(struct iked *, struct imsg *);
950
int  config_setcertpartialchain(struct iked *);
951
int  config_getcertpartialchain(struct iked *, struct imsg *);
952
953
/* policy.c */
954
void   policy_init(struct iked *);
955
int  policy_lookup(struct iked *, struct iked_message *,
956
      struct iked_proposals *, struct iked_flows *, int);
957
int  policy_lookup_sa(struct iked *, struct iked_sa *);
958
struct iked_policy *
959
   policy_test(struct iked *, struct iked_policy *);
960
int  policy_generate_ts(struct iked_policy *);
961
void   policy_calc_skip_steps(struct iked_policies *);
962
void   policy_ref(struct iked *, struct iked_policy *);
963
void   policy_unref(struct iked *, struct iked_policy *);
964
void   sa_state(struct iked *, struct iked_sa *, int);
965
void   sa_stateflags(struct iked_sa *, unsigned int);
966
int  sa_stateok(const struct iked_sa *, int);
967
struct iked_sa *
968
   sa_new(struct iked *, uint64_t, uint64_t, unsigned int,
969
      struct iked_policy *);
970
void   sa_free(struct iked *, struct iked_sa *);
971
void   sa_free_flows(struct iked *, struct iked_saflows *);
972
int  sa_configure_iface(struct iked *, struct iked_sa *, int);
973
int  sa_address(struct iked_sa *, struct iked_addr *, struct sockaddr *);
974
void   childsa_free(struct iked_childsa *);
975
struct iked_childsa *
976
   childsa_lookup(struct iked_sa *, uint64_t, uint8_t);
977
void   flow_free(struct iked_flow *);
978
int  flow_equal(struct iked_flow *, struct iked_flow *);
979
struct iked_sa *
980
   sa_lookup(struct iked *, uint64_t, uint64_t, unsigned int);
981
struct iked_user *
982
   user_lookup(struct iked *, const char *);
983
struct iked_sa *
984
   sa_dstid_lookup(struct iked *, struct iked_sa *);
985
struct iked_sa *
986
   sa_dstid_insert(struct iked *, struct iked_sa *);
987
void   sa_dstid_remove(struct iked *, struct iked_sa *);
988
int  proposals_negotiate(struct iked_proposals *, struct iked_proposals *,
989
      struct iked_proposals *, int, int);
990
RB_PROTOTYPE(iked_sas, iked_sa, sa_entry, sa_cmp);
991
RB_PROTOTYPE(iked_dstid_sas, iked_sa, sa_dstid_entry, sa_dstid_cmp);
992
RB_PROTOTYPE(iked_addrpool, iked_sa, sa_addrpool_entry, sa_addrpool_cmp);
993
RB_PROTOTYPE(iked_addrpool6, iked_sa, sa_addrpool6_entry, sa_addrpool6_cmp);
994
RB_PROTOTYPE(iked_users, iked_user, user_entry, user_cmp);
995
RB_PROTOTYPE(iked_activesas, iked_childsa, csa_node, childsa_cmp);
996
RB_PROTOTYPE(iked_flows, iked_flow, flow_node, flow_cmp);
997
998
/* crypto.c */
999
struct iked_hash *
1000
   hash_new(uint8_t, uint16_t);
1001
struct ibuf *
1002
   hash_setkey(struct iked_hash *, void *, size_t);
1003
void   hash_free(struct iked_hash *);
1004
void   hash_init(struct iked_hash *);
1005
void   hash_update(struct iked_hash *, void *, size_t);
1006
void   hash_final(struct iked_hash *, void *, size_t *);
1007
size_t   hash_keylength(struct iked_hash *);
1008
size_t   hash_length(struct iked_hash *);
1009
1010
struct iked_cipher *
1011
   cipher_new(uint8_t, uint16_t, uint16_t);
1012
struct ibuf *
1013
   cipher_setkey(struct iked_cipher *, const void *, size_t);
1014
struct ibuf *
1015
   cipher_setiv(struct iked_cipher *, const void *, size_t);
1016
int  cipher_settag(struct iked_cipher *, uint8_t *, size_t);
1017
int  cipher_gettag(struct iked_cipher *, uint8_t *, size_t);
1018
void   cipher_free(struct iked_cipher *);
1019
int  cipher_init(struct iked_cipher *, int);
1020
int  cipher_init_encrypt(struct iked_cipher *);
1021
int  cipher_init_decrypt(struct iked_cipher *);
1022
void   cipher_aad(struct iked_cipher *, const void *, size_t, size_t *);
1023
int  cipher_update(struct iked_cipher *, const void *, size_t, void *, size_t *);
1024
int  cipher_final(struct iked_cipher *);
1025
size_t   cipher_length(struct iked_cipher *);
1026
size_t   cipher_keylength(struct iked_cipher *);
1027
size_t   cipher_ivlength(struct iked_cipher *);
1028
size_t   cipher_outlength(struct iked_cipher *, size_t);
1029
1030
struct iked_dsa *
1031
   dsa_new(uint8_t, struct iked_hash *, int);
1032
struct iked_dsa *
1033
   dsa_sign_new(uint8_t, struct iked_hash *);
1034
struct iked_dsa *
1035
   dsa_verify_new(uint8_t, struct iked_hash *);
1036
struct ibuf *
1037
   dsa_setkey(struct iked_dsa *, void *, size_t, uint8_t);
1038
void   dsa_free(struct iked_dsa *);
1039
int  dsa_init(struct iked_dsa *, const void *, size_t);
1040
size_t   dsa_prefix(struct iked_dsa *);
1041
size_t   dsa_length(struct iked_dsa *);
1042
int  dsa_update(struct iked_dsa *, const void *, size_t);
1043
ssize_t  dsa_sign_final(struct iked_dsa *, void *, size_t);
1044
ssize_t  dsa_verify_final(struct iked_dsa *, void *, size_t);
1045
1046
/* vroute.c */
1047
void vroute_init(struct iked *);
1048
int vroute_setaddr(struct iked *, int, struct sockaddr *, int, unsigned int);
1049
void vroute_cleanup(struct iked *);
1050
int vroute_getaddr(struct iked *, struct imsg *);
1051
int vroute_setdns(struct iked *, int, struct sockaddr *, unsigned int);
1052
int vroute_getdns(struct iked *, struct imsg *);
1053
int vroute_setaddroute(struct iked *, uint8_t, struct sockaddr *,
1054
    uint8_t, struct sockaddr *);
1055
int vroute_setcloneroute(struct iked *, uint8_t, struct sockaddr *,
1056
    uint8_t, struct sockaddr *);
1057
int vroute_setdelroute(struct iked *, uint8_t, struct sockaddr *,
1058
    uint8_t, struct sockaddr *);
1059
int vroute_getroute(struct iked *, struct imsg *);
1060
int vroute_getcloneroute(struct iked *, struct imsg *);
1061
1062
/* ikev2.c */
1063
void   ikev2(struct privsep *, struct privsep_proc *);
1064
void   ikev2_recv(struct iked *, struct iked_message *);
1065
void   ikev2_init_ike_sa(struct iked *, void *);
1066
int  ikev2_policy2id(struct iked_static_id *, struct iked_id *, int);
1067
int  ikev2_childsa_enable(struct iked *, struct iked_sa *);
1068
int  ikev2_childsa_delete(struct iked *, struct iked_sa *,
1069
      uint8_t, uint64_t, uint64_t *, int);
1070
void   ikev2_ikesa_recv_delete(struct iked *, struct iked_sa *);
1071
void   ikev2_ike_sa_timeout(struct iked *env, void *);
1072
void   ikev2_ike_sa_setreason(struct iked_sa *, char *);
1073
void   ikev2_reset_alive_timer(struct iked *);
1074
int  ikev2_ike_sa_delete(struct iked *, struct iked_sa *);
1075
1076
struct ibuf *
1077
   ikev2_prfplus(struct iked_hash *, struct ibuf *, struct ibuf *,
1078
      size_t);
1079
ssize_t  ikev2_psk(struct iked_sa *, uint8_t *, size_t, uint8_t **);
1080
ssize_t  ikev2_nat_detection(struct iked *, struct iked_message *,
1081
      void *, size_t, unsigned int, int);
1082
void   ikev2_enable_natt(struct iked *, struct iked_sa *,
1083
      struct iked_message *, int);
1084
int  ikev2_send_informational(struct iked *, struct iked_message *);
1085
int  ikev2_send_ike_e(struct iked *, struct iked_sa *, struct ibuf *,
1086
      uint8_t, uint8_t, int);
1087
struct ike_header *
1088
   ikev2_add_header(struct ibuf *, struct iked_sa *,
1089
      uint32_t, uint8_t, uint8_t, uint8_t);
1090
int  ikev2_set_header(struct ike_header *, size_t);
1091
struct ikev2_payload *
1092
   ikev2_add_payload(struct ibuf *);
1093
int  ikev2_next_payload(struct ikev2_payload *, size_t,
1094
      uint8_t);
1095
int  ikev2_child_sa_acquire(struct iked *, struct iked_flow *);
1096
int  ikev2_child_sa_drop(struct iked *, struct iked_spi *);
1097
int  ikev2_child_sa_rekey(struct iked *, struct iked_spi *);
1098
void   ikev2_disable_rekeying(struct iked *, struct iked_sa *);
1099
int  ikev2_print_id(struct iked_id *, char *, size_t);
1100
int  ikev2_print_static_id(struct iked_static_id *, char *, size_t);
1101
1102
const char  *ikev2_ikesa_info(uint64_t, const char *msg);
1103
#define SPI_IH(hdr)      ikev2_ikesa_info(betoh64((hdr)->ike_ispi), NULL)
1104
9.39k
#define SPI_SH(sh, f)    ikev2_ikesa_info((sh)->sh_ispi, (f))
1105
9.39k
#define SPI_SA(sa, f)    SPI_SH(&(sa)->sa_hdr, (f))
1106
1107
/* ikev2_msg.c */
1108
void   ikev2_msg_cb(int, short, void *);
1109
struct ibuf *
1110
   ikev2_msg_init(struct iked *, struct iked_message *,
1111
      struct sockaddr_storage *, socklen_t,
1112
      struct sockaddr_storage *, socklen_t, int);
1113
struct iked_message *
1114
   ikev2_msg_copy(struct iked *, struct iked_message *);
1115
void   ikev2_msg_cleanup(struct iked *, struct iked_message *);
1116
uint32_t
1117
   ikev2_msg_id(struct iked *, struct iked_sa *);
1118
struct ibuf
1119
  *ikev2_msg_auth(struct iked *, struct iked_sa *, int);
1120
int  ikev2_msg_authsign(struct iked *, struct iked_sa *,
1121
      struct iked_auth *, struct ibuf *);
1122
int  ikev2_msg_authverify(struct iked *, struct iked_sa *,
1123
      struct iked_auth *, uint8_t *, size_t, struct ibuf *);
1124
int  ikev2_msg_valid_ike_sa(struct iked *, struct ike_header *,
1125
      struct iked_message *);
1126
int  ikev2_msg_send(struct iked *, struct iked_message *);
1127
int  ikev2_msg_send_encrypt(struct iked *, struct iked_sa *,
1128
      struct ibuf **, uint8_t, uint8_t, int);
1129
struct ibuf
1130
  *ikev2_msg_encrypt(struct iked *, struct iked_sa *, struct ibuf *,
1131
      struct ibuf *);
1132
struct ibuf *
1133
   ikev2_msg_decrypt(struct iked *, struct iked_sa *,
1134
      struct ibuf *, struct ibuf *);
1135
int  ikev2_msg_integr(struct iked *, struct iked_sa *, struct ibuf *);
1136
int  ikev2_msg_frompeer(struct iked_message *);
1137
struct iked_socket *
1138
   ikev2_msg_getsocket(struct iked *, int, int);
1139
int  ikev2_msg_enqueue(struct iked *, struct iked_msgqueue *,
1140
      struct iked_message *, int);
1141
int  ikev2_msg_retransmit_response(struct iked *, struct iked_sa *,
1142
      struct iked_message *, uint8_t);
1143
void   ikev2_msg_prevail(struct iked *, struct iked_msgqueue *,
1144
      struct iked_message *);
1145
void   ikev2_msg_dispose(struct iked *, struct iked_msgqueue *,
1146
      struct iked_msg_retransmit *);
1147
void   ikev2_msg_flushqueue(struct iked *, struct iked_msgqueue *);
1148
struct iked_msg_retransmit *
1149
   ikev2_msg_lookup(struct iked *, struct iked_msgqueue *,
1150
      struct iked_message *, uint8_t);
1151
1152
/* ikev2_pld.c */
1153
int  ikev2_pld_parse(struct iked *, struct ike_header *,
1154
      struct iked_message *, size_t);
1155
1156
/* eap.c */
1157
int  eap_parse(struct iked *, const struct iked_sa *, struct iked_message*,
1158
      void *, int);
1159
int  eap_success(struct iked *, struct iked_sa *, int);
1160
int  eap_identity_request(struct iked *, struct iked_sa *);
1161
int  eap_mschap_challenge(struct iked *, struct iked_sa *, int, int,
1162
      uint8_t *, size_t);
1163
int  eap_mschap_success(struct iked *, struct iked_sa *, int);
1164
int  eap_challenge_request(struct iked *, struct iked_sa *, int);
1165
1166
/* pfkey.c */
1167
int  pfkey_couple(struct iked *, struct iked_sas *, int);
1168
int  pfkey_flow_add(struct iked *, struct iked_flow *);
1169
int  pfkey_flow_delete(struct iked *, struct iked_flow *);
1170
int  pfkey_sa_init(struct iked *, struct iked_childsa *, uint32_t *);
1171
int  pfkey_sa_add(struct iked *, struct iked_childsa *, struct iked_childsa *);
1172
int  pfkey_sa_update_addresses(struct iked *, struct iked_childsa *);
1173
int  pfkey_sa_delete(struct iked *, struct iked_childsa *);
1174
int  pfkey_sa_last_used(struct iked *, struct iked_childsa *, uint64_t *);
1175
int  pfkey_flush(struct iked *);
1176
int  pfkey_socket(struct iked *);
1177
void   pfkey_init(struct iked *, int fd);
1178
1179
/* ipsec.c */
1180
int  ipsec_couple(struct iked *, struct iked_sas *, int);
1181
int  ipsec_flow_add(struct iked *, struct iked_flow *);
1182
int  ipsec_flow_delete(struct iked *, struct iked_flow *);
1183
int  ipsec_sa_init(struct iked *, struct iked_childsa *, uint32_t *);
1184
int  ipsec_sa_add(struct iked *, struct iked_childsa *, struct iked_childsa *);
1185
int  ipsec_sa_update_addresses(struct iked *, struct iked_childsa *);
1186
int  ipsec_sa_delete(struct iked *, struct iked_childsa *);
1187
int  ipsec_sa_last_used(struct iked *, struct iked_childsa *, uint64_t *);
1188
int  ipsec_sa_rpl(struct iked *, struct iked_childsa *, uint32_t *);
1189
int  ipsec_sa_lifetimes(struct iked *, struct iked_childsa *, struct iked_lifetime *,
1190
       struct iked_lifetime *, struct iked_lifetime *);
1191
int  ipsec_flush(struct iked *);
1192
int  ipsec_socket(struct iked *);
1193
void   ipsec_init(struct iked *, int fd);
1194
1195
/* ca.c */
1196
void   caproc(struct privsep *, struct privsep_proc *);
1197
int  ca_setreq(struct iked *, struct iked_sa *, struct iked_static_id *,
1198
      uint8_t, uint8_t, uint8_t *, size_t, enum privsep_procid);
1199
int  ca_setcert(struct iked *, struct iked_sahdr *, struct iked_id *,
1200
      uint8_t, uint8_t *, size_t, enum privsep_procid);
1201
int  ca_setauth(struct iked *, struct iked_sa *,
1202
      struct ibuf *, enum privsep_procid);
1203
void   ca_getkey(struct privsep *, struct iked_id *, enum imsg_type);
1204
int  ca_certbundle_add(struct ibuf *, struct iked_id *);
1205
int  ca_privkey_serialize(EVP_PKEY *, struct iked_id *);
1206
int  ca_pubkey_serialize(EVP_PKEY *, struct iked_id *);
1207
void   ca_sslinit(void);
1208
void   ca_sslerror(const char *);
1209
char  *ca_asn1_name(uint8_t *, size_t);
1210
void  *ca_x509_name_parse(char *);
1211
void   ca_cert_info(const char *, X509 *);
1212
1213
/* timer.c */
1214
void   timer_set(struct iked *, struct iked_timer *,
1215
      void (*)(struct iked *, void *), void *);
1216
void   timer_add(struct iked *, struct iked_timer *, int);
1217
void   timer_del(struct iked *, struct iked_timer *);
1218
1219
/* proc.c */
1220
void   proc_init(struct privsep *, struct privsep_proc *, unsigned int, int,
1221
      int, char **, enum privsep_procid);
1222
void   proc_kill(struct privsep *);
1223
void   proc_connect(struct privsep *);
1224
void   proc_dispatch(int, short event, void *);
1225
void   proc_run(struct privsep *, struct privsep_proc *,
1226
      struct privsep_proc *, unsigned int,
1227
      void (*)(struct privsep *, struct privsep_proc *, void *), void *);
1228
void   imsg_event_add(struct imsgev *);
1229
int  imsg_compose_event(struct imsgev *, uint16_t, uint32_t,
1230
      pid_t, int, void *, uint16_t);
1231
int  imsg_composev_event(struct imsgev *, uint16_t, uint32_t,
1232
      pid_t, int, const struct iovec *, int);
1233
int  proc_compose_imsg(struct privsep *, enum privsep_procid, int,
1234
      uint16_t, uint32_t, int, void *, uint16_t);
1235
int  proc_compose(struct privsep *, enum privsep_procid,
1236
      uint16_t, void *, uint16_t);
1237
int  proc_composev_imsg(struct privsep *, enum privsep_procid, int,
1238
      uint16_t, uint32_t, int, const struct iovec *, int);
1239
int  proc_composev(struct privsep *, enum privsep_procid,
1240
      uint16_t, const struct iovec *, int);
1241
int  proc_forward_imsg(struct privsep *, struct imsg *,
1242
      enum privsep_procid, int);
1243
struct imsgbuf *
1244
   proc_ibuf(struct privsep *, enum privsep_procid, int);
1245
struct imsgev *
1246
   proc_iev(struct privsep *, enum privsep_procid, int);
1247
enum privsep_procid
1248
   proc_getid(struct privsep_proc *, unsigned int, const char *);
1249
int  proc_flush_imsg(struct privsep *, enum privsep_procid, int);
1250
1251
/* util.c */
1252
int  socket_af(struct sockaddr *, in_port_t);
1253
in_port_t
1254
   socket_getport(struct sockaddr *);
1255
int  socket_setport(struct sockaddr *, in_port_t);
1256
int  socket_getaddr(int, struct sockaddr_storage *);
1257
int  socket_bypass(int, struct sockaddr *);
1258
int  udp_bind(struct sockaddr *, in_port_t);
1259
ssize_t  sendtofrom(int, void *, size_t, int, struct sockaddr *,
1260
      socklen_t, struct sockaddr *, socklen_t);
1261
ssize_t  recvfromto(int, void *, size_t, int, struct sockaddr *,
1262
      socklen_t *, struct sockaddr *, socklen_t *);
1263
const char *
1264
   print_spi(uint64_t, int);
1265
const char *
1266
   print_map(unsigned int, struct iked_constmap *);
1267
void   lc_idtype(char *);
1268
void   print_hex(const uint8_t *, off_t, size_t);
1269
void   print_hexval(const uint8_t *, off_t, size_t);
1270
void   print_hexbuf(struct ibuf *);
1271
const char *
1272
   print_bits(unsigned short, unsigned char *);
1273
int  sockaddr_cmp(struct sockaddr *, struct sockaddr *, int);
1274
uint8_t mask2prefixlen(struct sockaddr *);
1275
uint8_t mask2prefixlen6(struct sockaddr *);
1276
struct in6_addr *
1277
   prefixlen2mask6(uint8_t, uint32_t *);
1278
uint32_t
1279
   prefixlen2mask(uint8_t);
1280
const char *
1281
   print_addr(void *);
1282
char  *get_string(uint8_t *, size_t);
1283
const char *
1284
   print_proto(uint8_t);
1285
int  expand_string(char *, size_t, const char *, const char *);
1286
uint8_t *string2unicode(const char *, size_t *);
1287
void   print_debug(const char *, ...)
1288
      __attribute__((format(printf, 1, 2)));
1289
void   print_verbose(const char *, ...)
1290
      __attribute__((format(printf, 1, 2)));
1291
1292
/* imsg_util.c */
1293
struct ibuf *
1294
   ibuf_new(const void *, size_t);
1295
struct ibuf *
1296
   ibuf_static(void);
1297
size_t   ibuf_length(struct ibuf *);
1298
int  ibuf_setsize(struct ibuf *, size_t);
1299
struct ibuf *
1300
   ibuf_getdata(struct ibuf *, size_t);
1301
struct ibuf *
1302
   ibuf_dup(struct ibuf *);
1303
struct ibuf *
1304
   ibuf_random(size_t);
1305
1306
/* log.c */
1307
void  log_init(int, int);
1308
void  log_procinit(const char *);
1309
void  log_setverbose(int);
1310
int log_getverbose(void);
1311
void  log_warn(const char *, ...)
1312
      __attribute__((__format__ (printf, 1, 2)));
1313
void  log_warnx(const char *, ...)
1314
      __attribute__((__format__ (printf, 1, 2)));
1315
void  log_info(const char *, ...)
1316
      __attribute__((__format__ (printf, 1, 2)));
1317
void  log_debug(const char *, ...)
1318
      __attribute__((__format__ (printf, 1, 2)));
1319
void  logit(int, const char *, ...)
1320
      __attribute__((__format__ (printf, 2, 3)));
1321
void  vlog(int, const char *, va_list)
1322
      __attribute__((__format__ (printf, 2, 0)));
1323
__dead void fatal(const char *, ...)
1324
      __attribute__((__format__ (printf, 1, 2)));
1325
__dead void fatalx(const char *, ...)
1326
      __attribute__((__format__ (printf, 1, 2)));
1327
1328
/* ocsp.c */
1329
int  ocsp_connect(struct iked *, struct imsg *);
1330
int  ocsp_receive_fd(struct iked *, struct imsg *);
1331
int  ocsp_validate_cert(struct iked *, void *, size_t, struct iked_sahdr,
1332
    uint8_t, X509 *);
1333
1334
/* parse.y */
1335
int  parse_config(const char *, struct iked *);
1336
int  cmdline_symset(char *);
1337
extern const struct ipsec_xf authxfs[];
1338
extern const struct ipsec_xf prfxfs[];
1339
extern const struct ipsec_xf *encxfs;
1340
extern const struct ipsec_xf ikeencxfs[];
1341
extern const struct ipsec_xf ipsecencxfs[];
1342
extern const struct ipsec_xf groupxfs[];
1343
extern const struct ipsec_xf esnxfs[];
1344
extern const struct ipsec_xf methodxfs[];
1345
extern const struct ipsec_xf saxfs[];
1346
extern const struct ipsec_xf cpxfs[];
1347
size_t   keylength_xf(unsigned int, unsigned int, unsigned int);
1348
size_t   noncelength_xf(unsigned int, unsigned int);
1349
int  encxf_noauth(unsigned int);
1350
1351
/* print.c */
1352
void   print_user(struct iked_user *);
1353
void   print_policy(struct iked_policy *);
1354
const char *print_xf(unsigned int, unsigned int, const struct ipsec_xf *);
1355
1356
#endif /* IKED_H */
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/ikev2.h.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/ikev2.h.html index 8a80e5c77..ab96c128e 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/ikev2.h.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/ikev2.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/ikev2.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: ikev2.h,v 1.35 2023/06/28 14:10:24 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#ifndef IKED_IKEV2_H
21
#define IKED_IKEV2_H
22
23
#include "openbsd-compat.h"
24
25
#define IKEV2_VERSION   0x20  /* IKE version 2.0 */
26
#define IKEV1_VERSION   0x10  /* IKE version 1.0 */
27
28
#define IKEV2_KEYPAD    "Key Pad for IKEv2" /* don't change! */
29
30
/*
31
 * IKEv2 pseudo states
32
 */
33
34
#define IKEV2_STATE_INIT    0 /* new IKE SA */
35
#define IKEV2_STATE_COOKIE    1 /* cookie requested */
36
#define IKEV2_STATE_SA_INIT   2 /* init IKE SA */
37
#define IKEV2_STATE_EAP     3 /* EAP requested */
38
#define IKEV2_STATE_EAP_SUCCESS   4 /* EAP succeeded */
39
#define IKEV2_STATE_AUTH_REQUEST  5 /* auth received */
40
#define IKEV2_STATE_AUTH_SUCCESS  6 /* authenticated */
41
149
#define IKEV2_STATE_VALID   7  /* authenticated AND validated certs */
42
#define IKEV2_STATE_EAP_VALID   8 /* EAP validated */
43
#define IKEV2_STATE_ESTABLISHED   9 /* active IKE SA */
44
#define IKEV2_STATE_CLOSING   10  /* expect delete for this SA */
45
#define IKEV2_STATE_CLOSED    11  /* delete this SA */
46
47
extern struct iked_constmap ikev2_state_map[];
48
49
/*
50
 * "IKEv2 Parameters" based on the official RFC-based assignments by IANA
51
 * (http://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.txt)
52
 */
53
54
/*
55
 * IKEv2 definitions of the IKE header
56
 */
57
58
/* IKEv2 exchange types */
59
#define IKEV2_EXCHANGE_IKE_SA_INIT    34  /* Initial Exchange */
60
#define IKEV2_EXCHANGE_IKE_AUTH     35  /* Authentication */
61
#define IKEV2_EXCHANGE_CREATE_CHILD_SA    36  /* Create Child SA */
62
#define IKEV2_EXCHANGE_INFORMATIONAL    37  /* Informational */
63
#define IKEV2_EXCHANGE_IKE_SESSION_RESUME 38  /* RFC5723 */
64
65
extern struct iked_constmap ikev2_exchange_map[];
66
67
/* IKEv2 message flags */
68
#define IKEV2_FLAG_INITIATOR    0x08  /* Sent by the initiator */
69
#define IKEV2_FLAG_OLDVERSION   0x10  /* Supports a higher IKE version */
70
#define IKEV2_FLAG_RESPONSE   0x20  /* Message is a response */
71
72
extern struct iked_constmap ikev2_flag_map[];
73
74
/*
75
 * IKEv2 payloads
76
 */
77
78
struct ikev2_payload {
79
  uint8_t    pld_nextpayload; /* Next payload type */
80
  uint8_t    pld_reserved;    /* Contains the critical bit */
81
  uint16_t   pld_length;    /* Payload length with header */
82
} __packed;
83
84
struct ikev2_frag_payload {
85
  uint16_t   frag_num;    /* current fragment message number */
86
  uint16_t   frag_total;    /* total number of fragment messages */
87
} __packed;
88
89
279k
#define IKEV2_CRITICAL_PAYLOAD  0x01  /* First bit in the reserved field */
90
91
/* IKEv2 payload types */
92
#define IKEV2_PAYLOAD_NONE  0 /* No payload */
93
32.7k
#define IKEV2_PAYLOAD_SA  33  /* Security Association */
94
10.9k
#define IKEV2_PAYLOAD_KE  34  /* Key Exchange */
95
14.1k
#define IKEV2_PAYLOAD_IDi 35  /* Identification - Initiator */
96
23.8k
#define IKEV2_PAYLOAD_IDr 36  /* Identification - Responder */
97
6.90k
#define IKEV2_PAYLOAD_CERT  37  /* Certificate */
98
15.4k
#define IKEV2_PAYLOAD_CERTREQ 38  /* Certificate Request */
99
10.5k
#define IKEV2_PAYLOAD_AUTH  39  /* Authentication */
100
3.51k
#define IKEV2_PAYLOAD_NONCE 40  /* Nonce */
101
39.8k
#define IKEV2_PAYLOAD_NOTIFY  41  /* Notify */
102
7.54k
#define IKEV2_PAYLOAD_DELETE  42  /* Delete */
103
#define IKEV2_PAYLOAD_VENDOR  43  /* Vendor ID */
104
5.65k
#define IKEV2_PAYLOAD_TSi 44  /* Traffic Selector - Initiator */
105
23.0k
#define IKEV2_PAYLOAD_TSr 45  /* Traffic Selector - Responder */
106
278k
#define IKEV2_PAYLOAD_SK  46  /* Encrypted */
107
11.6k
#define IKEV2_PAYLOAD_CP  47  /* Configuration Payload */
108
21.2k
#define IKEV2_PAYLOAD_EAP 48  /* Extensible Authentication */
109
#define IKEV2_PAYLOAD_GSPM  49  /* RFC6467 Generic Secure Password */
110
278k
#define IKEV2_PAYLOAD_SKF 53  /* RFC7383 Encrypted Fragment Payload */
111
112
extern struct iked_constmap ikev2_payload_map[];
113
114
/*
115
 * SA payload
116
 */
117
118
struct ikev2_sa_proposal {
119
  uint8_t    sap_more;    /* Last proposal or more */
120
  uint8_t    sap_reserved;    /* Must be set to zero */
121
  uint16_t   sap_length;    /* Proposal length */
122
  uint8_t    sap_proposalnr;  /* Proposal number */
123
  uint8_t    sap_protoid;   /* Protocol Id */
124
  uint8_t    sap_spisize;   /* SPI size */
125
  uint8_t    sap_transforms;  /* Number of transforms */
126
  /* Followed by variable-length SPI */
127
  /* Followed by variable-length transforms */
128
} __packed;
129
130
#define IKEV2_SAP_LAST  0
131
#define IKEV2_SAP_MORE  2
132
133
#define IKEV2_SAPROTO_NONE    0 /* None */
134
#define IKEV2_SAPROTO_IKE   1 /* IKEv2 */
135
#define IKEV2_SAPROTO_AH    2 /* AH */
136
#define IKEV2_SAPROTO_ESP   3 /* ESP */
137
#define IKEV2_SAPROTO_FC_ESP_HEADER 4 /* RFC4595 */
138
#define IKEV2_SAPROTO_FC_CT_AUTH  5 /* RFC4595 */
139
#define IKEV2_SAPROTO_IPCOMP    204 /* private, should be 4 */
140
141
extern struct iked_constmap ikev2_saproto_map[];
142
143
struct ikev2_transform {
144
  uint8_t   xfrm_more;    /* Last transform or more */
145
  uint8_t   xfrm_reserved;    /* Must be set to zero */
146
  uint16_t  xfrm_length;    /* Transform length */
147
  uint8_t   xfrm_type;    /* Transform type */
148
  uint8_t   xfrm_reserved1;   /* Must be set to zero */
149
  uint16_t  xfrm_id;    /* Transform Id */
150
  /* Followed by variable-length transform attributes */
151
} __packed;
152
153
#define IKEV2_XFORM_LAST    0
154
3.63k
#define IKEV2_XFORM_MORE    3
155
156
1.27k
#define IKEV2_XFORMTYPE_ENCR    1  /* Encryption */
157
789
#define IKEV2_XFORMTYPE_PRF   2  /* Pseudo-Random Function */
158
174
#define IKEV2_XFORMTYPE_INTEGR    3  /* Integrity Algorithm */
159
861
#define IKEV2_XFORMTYPE_DH    4  /* Diffie-Hellman Group */
160
1.01k
#define IKEV2_XFORMTYPE_ESN   5  /* Extended Sequence Numbers */
161
#define IKEV2_XFORMTYPE_MAX   6
162
163
extern struct iked_constmap ikev2_xformtype_map[];
164
165
#define IKEV2_XFORMENCR_NONE    0 /* None */
166
#define IKEV2_XFORMENCR_DES_IV64  1 /* RFC1827 */
167
#define IKEV2_XFORMENCR_DES   2 /* RFC2405 */
168
#define IKEV2_XFORMENCR_3DES    3 /* RFC2451 */
169
#define IKEV2_XFORMENCR_RC5   4 /* RFC2451 */
170
#define IKEV2_XFORMENCR_IDEA    5 /* RFC2451 */
171
#define IKEV2_XFORMENCR_CAST    6 /* RFC2451 */
172
#define IKEV2_XFORMENCR_BLOWFISH  7 /* RFC2451 */
173
#define IKEV2_XFORMENCR_3IDEA   8 /* RFC2451 */
174
#define IKEV2_XFORMENCR_DES_IV32  9 /* DESIV32 */
175
#define IKEV2_XFORMENCR_RC4   10  /* RFC2451 */
176
#define IKEV2_XFORMENCR_NULL    11  /* RFC2410 */
177
#define IKEV2_XFORMENCR_AES_CBC   12  /* RFC3602 */
178
#define IKEV2_XFORMENCR_AES_CTR   13  /* RFC3664 */
179
#define IKEV2_XFORMENCR_AES_CCM_8 14  /* RFC5282 */
180
#define IKEV2_XFORMENCR_AES_CCM_12  15  /* RFC5282 */
181
#define IKEV2_XFORMENCR_AES_CCM_16  16  /* RFC5282 */
182
#define IKEV2_XFORMENCR_AES_GCM_8 18  /* RFC5282 */
183
#define IKEV2_XFORMENCR_AES_GCM_12  19  /* RFC5282 */
184
#define IKEV2_XFORMENCR_AES_GCM_16  20  /* RFC5282 */
185
#define IKEV2_XFORMENCR_NULL_AES_GMAC 21  /* RFC4543 */
186
#define IKEV2_XFORMENCR_XTS_AES   22  /* IEEE P1619 */
187
#define IKEV2_XFORMENCR_CAMELLIA_CBC  23  /* RFC5529 */
188
#define IKEV2_XFORMENCR_CAMELLIA_CTR  24  /* RFC5529 */
189
#define IKEV2_XFORMENCR_CAMELLIA_CCM_8  25  /* RFC5529 */
190
#define IKEV2_XFORMENCR_CAMELLIA_CCM_12 26  /* RFC5529 */
191
#define IKEV2_XFORMENCR_CAMELLIA_CCM_16 27  /* RFC5529 */
192
#define IKEV2_XFORMENCR_CHACHA20_POLY1305 28  /* RFC7634 */
193
194
extern struct iked_constmap ikev2_xformencr_map[];
195
196
#define IKEV2_IPCOMP_OUI    1 /* UNSPECIFIED */
197
#define IKEV2_IPCOMP_DEFLATE    2 /* RFC2394 */
198
#define IKEV2_IPCOMP_LZS    3 /* RFC2395 */
199
#define IKEV2_IPCOMP_LZJH   4 /* RFC3051 */
200
201
extern struct iked_constmap ikev2_ipcomp_map[];
202
203
#define IKEV2_XFORMPRF_HMAC_MD5   1 /* RFC2104 */
204
#define IKEV2_XFORMPRF_HMAC_SHA1  2 /* RFC2104 */
205
#define IKEV2_XFORMPRF_HMAC_TIGER 3 /* RFC2104 */
206
#define IKEV2_XFORMPRF_AES128_XCBC  4 /* RFC3664 */
207
#define IKEV2_XFORMPRF_HMAC_SHA2_256  5 /* RFC4868 */
208
#define IKEV2_XFORMPRF_HMAC_SHA2_384  6 /* RFC4868 */
209
#define IKEV2_XFORMPRF_HMAC_SHA2_512  7 /* RFC4868 */
210
#define IKEV2_XFORMPRF_AES128_CMAC  8 /* RFC4615 */
211
212
extern struct iked_constmap ikev2_xformprf_map[];
213
214
#define IKEV2_XFORMAUTH_NONE    0 /* No Authentication */
215
#define IKEV2_XFORMAUTH_HMAC_MD5_96 1 /* RFC2403 */
216
#define IKEV2_XFORMAUTH_HMAC_SHA1_96  2 /* RFC2404 */
217
#define IKEV2_XFORMAUTH_DES_MAC   3 /* DES-MAC */
218
#define IKEV2_XFORMAUTH_KPDK_MD5  4 /* RFC1826 */
219
#define IKEV2_XFORMAUTH_AES_XCBC_96 5 /* RFC3566 */
220
#define IKEV2_XFORMAUTH_HMAC_MD5_128  6 /* RFC4595 */
221
#define IKEV2_XFORMAUTH_HMAC_SHA1_160 7 /* RFC4595 */
222
#define IKEV2_XFORMAUTH_AES_CMAC_96 8 /* RFC4494 */
223
#define IKEV2_XFORMAUTH_AES_128_GMAC  9 /* RFC4543 */
224
#define IKEV2_XFORMAUTH_AES_192_GMAC  10  /* RFC4543 */
225
#define IKEV2_XFORMAUTH_AES_256_GMAC  11  /* RFC4543 */
226
#define IKEV2_XFORMAUTH_HMAC_SHA2_256_128 12  /* RFC4868 */
227
#define IKEV2_XFORMAUTH_HMAC_SHA2_384_192 13  /* RFC4868 */
228
#define IKEV2_XFORMAUTH_HMAC_SHA2_512_256 14  /* RFC4868 */
229
230
/* Placeholders for AEAD ciphers (only used internally) */
231
#define IKEV2_XFORMAUTH_AES_GCM_8 2018  /* internal */
232
#define IKEV2_XFORMAUTH_AES_GCM_12  2019  /* internal */
233
#define IKEV2_XFORMAUTH_AES_GCM_16  2020  /* internal */
234
235
extern struct iked_constmap ikev2_xformauth_map[];
236
237
#define IKEV2_XFORMDH_NONE    0 /* No DH */
238
#define IKEV2_XFORMDH_MODP_768    1 /* DH Group 1 */
239
#define IKEV2_XFORMDH_MODP_1024   2 /* DH Group 2 */
240
#define IKEV2_XFORMDH_MODP_1536   5 /* DH Group 5 */
241
#define IKEV2_XFORMDH_MODP_2048   14  /* DH Group 14 */
242
#define IKEV2_XFORMDH_MODP_3072   15  /* DH Group 15 */
243
#define IKEV2_XFORMDH_MODP_4096   16  /* DH Group 16 */
244
#define IKEV2_XFORMDH_MODP_6144   17  /* DH Group 17 */
245
#define IKEV2_XFORMDH_MODP_8192   18  /* DH Group 18 */
246
#define IKEV2_XFORMDH_ECP_256   19  /* RFC5114 */
247
#define IKEV2_XFORMDH_ECP_384   20  /* RFC5114 */
248
#define IKEV2_XFORMDH_ECP_521   21  /* RFC5114 */
249
#define IKEV2_XFORMDH_ECP_192   25  /* RFC5114 */
250
#define IKEV2_XFORMDH_ECP_224   26  /* RFC5114 */
251
#define IKEV2_XFORMDH_BRAINPOOL_P224R1  27  /* RFC6954 */
252
#define IKEV2_XFORMDH_BRAINPOOL_P256R1  28  /* RFC6954 */
253
#define IKEV2_XFORMDH_BRAINPOOL_P384R1  29  /* RFC6954 */
254
#define IKEV2_XFORMDH_BRAINPOOL_P512R1  30  /* RFC6954 */
255
#define IKEV2_XFORMDH_CURVE25519  31  /* RFC8031 */
256
#define IKEV2_XFORMDH_X_SNTRUP761X25519 1035  /* private */
257
258
extern struct iked_constmap ikev2_xformdh_map[];
259
260
#define IKEV2_IPV4_OVERHEAD   (20 + 8 + 28) /* IPv4 + UDP + IKE_HDR*/
261
#define IKEV2_MAXLEN_IPV4_FRAG    (576 - IKEV2_IPV4_OVERHEAD)
262
#define IKEV2_IPV6_OVERHEAD   (40 + 8 + 28) /* IPv6 + UDP + IKE_HDR*/
263
#define IKEV2_MAXLEN_IPV6_FRAG    (1280 - IKEV2_IPV6_OVERHEAD)
264
265
#define IKEV2_MAXNUM_TSS    255 /* 8 bit Number of TSs field */
266
267
#define IKEV2_XFORMESN_NONE   0 /* No ESN */
268
#define IKEV2_XFORMESN_ESN    1 /* ESN */
269
270
extern struct iked_constmap ikev2_xformesn_map[];
271
272
struct ikev2_attribute {
273
  uint16_t  attr_type;  /* Attribute type */
274
  uint16_t  attr_length;  /* Attribute length or value */
275
  /* Followed by variable length (TLV) */
276
} __packed;
277
278
#define IKEV2_ATTRAF_TLV    0x0000  /* Type-Length-Value format */
279
105k
#define IKEV2_ATTRAF_TV     0x8000  /* Type-Value format */
280
281
41.9k
#define IKEV2_ATTRTYPE_KEY_LENGTH 14  /* Key length */
282
283
extern struct iked_constmap ikev2_attrtype_map[];
284
285
/*
286
 * KE Payload
287
 */
288
289
struct ikev2_keyexchange {
290
  uint16_t   kex_dhgroup;   /* DH Group # */
291
  uint16_t   kex_reserved;    /* Reserved */
292
} __packed;
293
294
/*
295
 * N payload
296
 */
297
298
struct ikev2_notify {
299
  uint8_t    n_protoid;   /* Protocol Id */
300
  uint8_t    n_spisize;   /* SPI size */
301
  uint16_t   n_type;    /* Notify message type */
302
  /* Followed by variable length SPI */
303
  /* Followed by variable length notification data */
304
} __packed;
305
306
#define IKEV2_N_UNSUPPORTED_CRITICAL_PAYLOAD  1 /* RFC7296 */
307
#define IKEV2_N_INVALID_IKE_SPI     4 /* RFC7296 */
308
#define IKEV2_N_INVALID_MAJOR_VERSION   5 /* RFC7296 */
309
#define IKEV2_N_INVALID_SYNTAX      7 /* RFC7296 */
310
#define IKEV2_N_INVALID_MESSAGE_ID    9 /* RFC7296 */
311
#define IKEV2_N_INVALID_SPI     11  /* RFC7296 */
312
36
#define IKEV2_N_NO_PROPOSAL_CHOSEN    14  /* RFC7296 */
313
143
#define IKEV2_N_INVALID_KE_PAYLOAD    17  /* RFC7296 */
314
6
#define IKEV2_N_AUTHENTICATION_FAILED   24  /* RFC7296 */
315
#define IKEV2_N_SINGLE_PAIR_REQUIRED    34  /* RFC7296 */
316
273
#define IKEV2_N_NO_ADDITIONAL_SAS   35  /* RFC7296 */
317
#define IKEV2_N_INTERNAL_ADDRESS_FAILURE  36  /* RFC7296 */
318
#define IKEV2_N_FAILED_CP_REQUIRED    37  /* RFC7296 */
319
#define IKEV2_N_TS_UNACCEPTABLE     38  /* RFC7296 */
320
#define IKEV2_N_INVALID_SELECTORS   39  /* RFC7296 */
321
#define IKEV2_N_UNACCEPTABLE_ADDRESSES    40  /* RFC4555 */
322
#define IKEV2_N_UNEXPECTED_NAT_DETECTED   41  /* RFC4555 */
323
#define IKEV2_N_USE_ASSIGNED_HoA    42  /* RFC5026 */
324
354
#define IKEV2_N_TEMPORARY_FAILURE   43  /* RFC7296 */
325
73
#define IKEV2_N_CHILD_SA_NOT_FOUND    44  /* RFC7296 */
326
#define IKEV2_N_INITIAL_CONTACT     16384 /* RFC7296 */
327
#define IKEV2_N_SET_WINDOW_SIZE     16385 /* RFC7296 */
328
#define IKEV2_N_ADDITIONAL_TS_POSSIBLE    16386 /* RFC7296 */
329
255
#define IKEV2_N_IPCOMP_SUPPORTED    16387  /* RFC7296 */
330
29.1k
#define IKEV2_N_NAT_DETECTION_SOURCE_IP   16388  /* RFC7296 */
331
26.0k
#define IKEV2_N_NAT_DETECTION_DESTINATION_IP  16389  /* RFC7296 */
332
2
#define IKEV2_N_COOKIE        16390  /* RFC7296 */
333
356
#define IKEV2_N_USE_TRANSPORT_MODE    16391  /* RFC7296 */
334
#define IKEV2_N_HTTP_CERT_LOOKUP_SUPPORTED  16392 /* RFC7296 */
335
82
#define IKEV2_N_REKEY_SA      16393  /* RFC7296 */
336
#define IKEV2_N_ESP_TFC_PADDING_NOT_SUPPORTED 16394 /* RFC7296 */
337
#define IKEV2_N_NON_FIRST_FRAGMENTS_ALSO  16395 /* RFC7296 */
338
1.81k
#define IKEV2_N_MOBIKE_SUPPORTED    16396  /* RFC4555 */
339
#define IKEV2_N_ADDITIONAL_IP4_ADDRESS    16397 /* RFC4555 */
340
#define IKEV2_N_ADDITIONAL_IP6_ADDRESS    16398 /* RFC4555 */
341
#define IKEV2_N_NO_ADDITIONAL_ADDRESSES   16399 /* RFC4555 */
342
388
#define IKEV2_N_UPDATE_SA_ADDRESSES   16400  /* RFC4555 */
343
242
#define IKEV2_N_COOKIE2       16401  /* RFC4555 */
344
#define IKEV2_N_NO_NATS_ALLOWED     16402 /* RFC4555 */
345
#define IKEV2_N_AUTH_LIFETIME     16403 /* RFC4478 */
346
#define IKEV2_N_MULTIPLE_AUTH_SUPPORTED   16404 /* RFC4739 */
347
#define IKEV2_N_ANOTHER_AUTH_FOLLOWS    16405 /* RFC4739 */
348
#define IKEV2_N_REDIRECT_SUPPORTED    16406 /* RFC5685 */
349
#define IKEV2_N_REDIRECT      16407 /* RFC5685 */
350
#define IKEV2_N_REDIRECTED_FROM     16408 /* RFC5685 */
351
#define IKEV2_N_TICKET_LT_OPAQUE    16409 /* RFC5723 */
352
#define IKEV2_N_TICKET_REQUEST      16410 /* RFC5723 */
353
#define IKEV2_N_TICKET_ACK      16411 /* RFC5723 */
354
#define IKEV2_N_TICKET_NACK     16412 /* RFC5723 */
355
#define IKEV2_N_TICKET_OPAQUE     16413 /* RFC5723 */
356
#define IKEV2_N_LINK_ID       16414 /* RFC5739 */
357
#define IKEV2_N_USE_WESP_MODE     16415 /* RFC5415 */
358
#define IKEV2_N_ROHC_SUPPORTED      16416 /* RFC5857 */
359
#define IKEV2_N_EAP_ONLY_AUTHENTICATION   16417 /* RFC5998 */
360
#define IKEV2_N_CHILDLESS_IKEV2_SUPPORTED 16418 /* RFC6023 */
361
#define IKEV2_N_QUICK_CRASH_DETECTION   16419 /* RFC6290 */
362
#define IKEV2_N_IKEV2_MESSAGE_ID_SYNC_SUPPORTED 16420 /* RFC6311 */
363
#define IKEV2_N_IPSEC_REPLAY_CTR_SYNC_SUPPORTED 16421 /* RFC6311 */
364
#define IKEV2_N_IKEV2_MESSAGE_ID_SYNC   16422 /* RFC6311 */
365
#define IKEV2_N_IPSEC_REPLAY_CTR_SYNC   16423 /* RFC6311 */
366
#define IKEV2_N_SECURE_PASSWORD_METHODS   16424 /* RFC6467 */
367
#define IKEV2_N_PSK_PERSIST     16425 /* RFC6631 */
368
#define IKEV2_N_PSK_CONFIRM     16426 /* RFC6631 */
369
#define IKEV2_N_ERX_SUPPORTED     16427 /* RFC6867 */
370
#define IKEV2_N_IFOM_CAPABILITY     16428 /* OA3GPP */
371
14
#define IKEV2_N_FRAGMENTATION_SUPPORTED   16430  /* RFC7383 */
372
7
#define IKEV2_N_SIGNATURE_HASH_ALGORITHMS 16431  /* RFC7427 */
373
374
extern struct iked_constmap ikev2_n_map[];
375
376
/*
377
 * DELETE payload
378
 */
379
380
struct ikev2_delete {
381
  uint8_t    del_protoid;   /* Protocol Id */
382
  uint8_t    del_spisize;   /* SPI size */
383
  uint16_t   del_nspi;    /* Number of SPIs */
384
  /* Followed by variable length SPIs */
385
} __packed;
386
387
/*
388
 * ID payload
389
 */
390
391
struct ikev2_id {
392
  uint8_t    id_type;   /* Id type */
393
  uint8_t    id_reserved[3];  /* Reserved */
394
  /* Followed by the identification data */
395
} __packed;
396
397
14.3k
#define IKEV2_ID_NONE   0  /* No ID */
398
#define IKEV2_ID_IPV4   1 /* RFC7296 (ID_IPV4_ADDR) */
399
#define IKEV2_ID_FQDN   2 /* RFC7296 */
400
#define IKEV2_ID_UFQDN    3 /* RFC7296 (ID_RFC822_ADDR) */
401
#define IKEV2_ID_IPV6   5 /* RFC7296 (ID_IPV6_ADDR) */
402
#define IKEV2_ID_ASN1_DN  9 /* RFC7296 */
403
#define IKEV2_ID_ASN1_GN  10  /* RFC7296 */
404
#define IKEV2_ID_KEY_ID   11  /* RFC7296 */
405
#define IKEV2_ID_FC_NAME  12  /* RFC4595 */
406
407
extern struct iked_constmap ikev2_id_map[];
408
409
/*
410
 * CERT/CERTREQ payloads
411
 */
412
413
struct ikev2_cert {
414
  uint8_t   cert_type;  /* Encoding */
415
  /* Followed by the certificate data */
416
} __packed;
417
418
5.37k
#define IKEV2_CERT_NONE     0  /* None */
419
#define IKEV2_CERT_X509_PKCS7   1 /* UNSPECIFIED */
420
#define IKEV2_CERT_PGP      2 /* UNSPECIFIED */
421
#define IKEV2_CERT_DNS_SIGNED_KEY 3 /* UNSPECIFIED */
422
1.34k
#define IKEV2_CERT_X509_CERT    4  /* RFC7296 */
423
#define IKEV2_CERT_KERBEROS_TOKEN 6 /* UNSPECIFIED */
424
#define IKEV2_CERT_CRL      7 /* RFC7296 */
425
#define IKEV2_CERT_ARL      8 /* UNSPECIFIED */
426
#define IKEV2_CERT_SPKI     9 /* UNSPECIFIED */
427
#define IKEV2_CERT_X509_ATTR    10  /* UNSPECIFIED */
428
#define IKEV2_CERT_RSA_KEY    11  /* RFC7296 */
429
#define IKEV2_CERT_HASHURL_X509   12  /* RFC7296 */
430
#define IKEV2_CERT_HASHURL_X509_BUNDLE  13  /* RFC7296 */
431
#define IKEV2_CERT_OCSP     14  /* RFC4806 */
432
/*
433
 * As of November 2014, work was still in progress to add a more generic
434
 * format for raw public keys (RFC7296), so we use a number in IANA's private
435
 * use range (201-255, same RFC) for ECDSA.
436
 */
437
#define IKEV2_CERT_ECDSA    201 /* Private */
438
2.78k
#define IKEV2_CERT_BUNDLE   254  /* Private */
439
440
extern struct iked_constmap ikev2_cert_map[];
441
442
/*
443
 * TSi/TSr payloads
444
 */
445
446
struct ikev2_tsp {
447
  uint8_t   tsp_count;    /* Number of TSs */
448
  uint8_t   tsp_reserved[3];  /* Reserved */
449
  /* Followed by the traffic selectors */
450
} __packed;
451
452
struct ikev2_ts {
453
  uint8_t   ts_type;    /* TS type */
454
  uint8_t   ts_protoid;   /* Protocol Id */
455
  uint16_t  ts_length;    /* Length */
456
  uint16_t  ts_startport;   /* Start port */
457
  uint16_t  ts_endport;   /* End port */
458
} __packed;
459
460
9.66k
#define IKEV2_TS_IPV4_ADDR_RANGE  7  /* RFC7296 */
461
1.54k
#define IKEV2_TS_IPV6_ADDR_RANGE  8  /* RFC7296 */
462
#define IKEV2_TS_FC_ADDR_RANGE    9 /* RFC4595 */
463
464
extern struct iked_constmap ikev2_ts_map[];
465
466
/*
467
 * AUTH payload
468
 */
469
470
struct ikev2_auth {
471
  uint8_t   auth_method;    /* Signature type */
472
  uint8_t   auth_reserved[3]; /* Reserved */
473
  /* Followed by the signature */
474
} __packed;
475
476
#define IKEV2_AUTH_NONE     0 /* None */
477
#define IKEV2_AUTH_RSA_SIG    1 /* RFC7296 */
478
#define IKEV2_AUTH_SHARED_KEY_MIC 2 /* RFC7296 */
479
#define IKEV2_AUTH_DSS_SIG    3 /* RFC7296 */
480
#define IKEV2_AUTH_ECDSA_256    9 /* RFC4754 */
481
#define IKEV2_AUTH_ECDSA_384    10  /* RFC4754 */
482
#define IKEV2_AUTH_ECDSA_521    11  /* RFC4754 */
483
#define IKEV2_AUTH_GSPM     12  /* RFC6467 */
484
#define IKEV2_AUTH_NULL     13  /* RFC7619 */
485
#define IKEV2_AUTH_SIG      14  /* RFC7427 */
486
#define IKEV2_AUTH_SIG_ANY    255 /* Internal (any signature) */
487
/*
488
 * AUTH_SIG also serves as an indication that a given policy has
489
 * been configured to accept RSA or ECDSA payloads, as long as it
490
 * successfully authenticates against a configured CA.
491
 */
492
493
extern struct iked_constmap ikev2_auth_map[];
494
495
/* Notifications used together with IKEV2_AUTH_SIG */
496
497
#define IKEV2_SIGHASH_RESERVED    0 /* RFC7427 */
498
#define IKEV2_SIGHASH_SHA1    1 /* RFC7427 */
499
0
#define IKEV2_SIGHASH_SHA2_256    2  /* RFC7427 */
500
#define IKEV2_SIGHASH_SHA2_384    3 /* RFC7427 */
501
#define IKEV2_SIGHASH_SHA2_512    4 /* RFC7427 */
502
503
extern struct iked_constmap ikev2_sighash_map[];
504
505
/*
506
 * CP payload
507
 */
508
509
struct ikev2_cp {
510
  uint8_t   cp_type;
511
  uint8_t   cp_reserved[3];
512
  /* Followed by the attributes */
513
} __packed;
514
515
#define IKEV2_CP_REQUEST  1 /* CFG-Request */
516
#define IKEV2_CP_REPLY    2 /* CFG-Reply */
517
#define IKEV2_CP_SET    3 /* CFG-SET */
518
#define IKEV2_CP_ACK    4 /* CFG-ACK */
519
520
extern struct iked_constmap ikev2_cp_map[];
521
522
struct ikev2_cfg {
523
  uint16_t  cfg_type; /* first bit must be set to zero */
524
  uint16_t  cfg_length;
525
  /* Followed by variable-length data */
526
} __packed;
527
528
1.32k
#define IKEV2_CFG_INTERNAL_IP4_ADDRESS    1  /* RFC7296 */
529
#define IKEV2_CFG_INTERNAL_IP4_NETMASK    2 /* RFC7296 */
530
1.67k
#define IKEV2_CFG_INTERNAL_IP4_DNS    3  /* RFC7296 */
531
#define IKEV2_CFG_INTERNAL_IP4_NBNS   4 /* RFC7296 */
532
#define IKEV2_CFG_INTERNAL_ADDRESS_EXPIRY 5 /* RFC4306 */
533
#define IKEV2_CFG_INTERNAL_IP4_DHCP   6 /* RFC7296 */
534
#define IKEV2_CFG_APPLICATION_VERSION   7 /* RFC7296 */
535
2.41k
#define IKEV2_CFG_INTERNAL_IP6_ADDRESS    8  /* RFC7296 */
536
3.18k
#define IKEV2_CFG_INTERNAL_IP6_DNS    10  /* RFC7296 */
537
#define IKEV2_CFG_INTERNAL_IP6_NBNS   11  /* RFC4306 */
538
#define IKEV2_CFG_INTERNAL_IP6_DHCP   12  /* RFC7296 */
539
#define IKEV2_CFG_INTERNAL_IP4_SUBNET   13  /* RFC7296 */
540
#define IKEV2_CFG_SUPPORTED_ATTRIBUTES    14  /* RFC7296 */
541
#define IKEV2_CFG_INTERNAL_IP6_SUBNET   15  /* RFC7296 */
542
#define IKEV2_CFG_MIP6_HOME_PREFIX    16  /* RFC5026 */
543
#define IKEV2_CFG_INTERNAL_IP6_LINK   17  /* RFC5739 */
544
#define IKEV2_CFG_INTERNAL_IP6_PREFIX   18  /* RFC5739 */
545
#define IKEV2_CFG_HOME_AGENT_ADDRESS    19  /* http://www.3gpp.org/ftp/Specs/html-info/24302.htm */
546
#define IKEV2_CFG_INTERNAL_IP4_SERVER   23456 /* MS-IKEE */
547
#define IKEV2_CFG_INTERNAL_IP6_SERVER   23457 /* MS-IKEE */
548
549
extern struct iked_constmap ikev2_cfg_map[];
550
551
/* IKEv1 payload types */
552
#define IKEV1_PAYLOAD_NONE  0 /* No payload */
553
#define IKEV1_PAYLOAD_PROPOSAL  2 /* Proposal */
554
555
#endif /* IKED_IKEV2_H */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/ikev2.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: ikev2.h,v 1.35 2023/06/28 14:10:24 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#ifndef IKED_IKEV2_H
21
#define IKED_IKEV2_H
22
23
#include "openbsd-compat.h"
24
25
#define IKEV2_VERSION   0x20  /* IKE version 2.0 */
26
#define IKEV1_VERSION   0x10  /* IKE version 1.0 */
27
28
#define IKEV2_KEYPAD    "Key Pad for IKEv2" /* don't change! */
29
30
/*
31
 * IKEv2 pseudo states
32
 */
33
34
#define IKEV2_STATE_INIT    0 /* new IKE SA */
35
#define IKEV2_STATE_COOKIE    1 /* cookie requested */
36
#define IKEV2_STATE_SA_INIT   2 /* init IKE SA */
37
#define IKEV2_STATE_EAP     3 /* EAP requested */
38
#define IKEV2_STATE_EAP_SUCCESS   4 /* EAP succeeded */
39
#define IKEV2_STATE_AUTH_REQUEST  5 /* auth received */
40
#define IKEV2_STATE_AUTH_SUCCESS  6 /* authenticated */
41
149
#define IKEV2_STATE_VALID   7  /* authenticated AND validated certs */
42
#define IKEV2_STATE_EAP_VALID   8 /* EAP validated */
43
#define IKEV2_STATE_ESTABLISHED   9 /* active IKE SA */
44
#define IKEV2_STATE_CLOSING   10  /* expect delete for this SA */
45
#define IKEV2_STATE_CLOSED    11  /* delete this SA */
46
47
extern struct iked_constmap ikev2_state_map[];
48
49
/*
50
 * "IKEv2 Parameters" based on the official RFC-based assignments by IANA
51
 * (http://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.txt)
52
 */
53
54
/*
55
 * IKEv2 definitions of the IKE header
56
 */
57
58
/* IKEv2 exchange types */
59
#define IKEV2_EXCHANGE_IKE_SA_INIT    34  /* Initial Exchange */
60
#define IKEV2_EXCHANGE_IKE_AUTH     35  /* Authentication */
61
#define IKEV2_EXCHANGE_CREATE_CHILD_SA    36  /* Create Child SA */
62
#define IKEV2_EXCHANGE_INFORMATIONAL    37  /* Informational */
63
#define IKEV2_EXCHANGE_IKE_SESSION_RESUME 38  /* RFC5723 */
64
65
extern struct iked_constmap ikev2_exchange_map[];
66
67
/* IKEv2 message flags */
68
#define IKEV2_FLAG_INITIATOR    0x08  /* Sent by the initiator */
69
#define IKEV2_FLAG_OLDVERSION   0x10  /* Supports a higher IKE version */
70
#define IKEV2_FLAG_RESPONSE   0x20  /* Message is a response */
71
72
extern struct iked_constmap ikev2_flag_map[];
73
74
/*
75
 * IKEv2 payloads
76
 */
77
78
struct ikev2_payload {
79
  uint8_t    pld_nextpayload; /* Next payload type */
80
  uint8_t    pld_reserved;    /* Contains the critical bit */
81
  uint16_t   pld_length;    /* Payload length with header */
82
} __packed;
83
84
struct ikev2_frag_payload {
85
  uint16_t   frag_num;    /* current fragment message number */
86
  uint16_t   frag_total;    /* total number of fragment messages */
87
} __packed;
88
89
279k
#define IKEV2_CRITICAL_PAYLOAD  0x01  /* First bit in the reserved field */
90
91
/* IKEv2 payload types */
92
#define IKEV2_PAYLOAD_NONE  0 /* No payload */
93
32.7k
#define IKEV2_PAYLOAD_SA  33  /* Security Association */
94
10.9k
#define IKEV2_PAYLOAD_KE  34  /* Key Exchange */
95
14.1k
#define IKEV2_PAYLOAD_IDi 35  /* Identification - Initiator */
96
23.8k
#define IKEV2_PAYLOAD_IDr 36  /* Identification - Responder */
97
6.90k
#define IKEV2_PAYLOAD_CERT  37  /* Certificate */
98
15.4k
#define IKEV2_PAYLOAD_CERTREQ 38  /* Certificate Request */
99
10.5k
#define IKEV2_PAYLOAD_AUTH  39  /* Authentication */
100
3.51k
#define IKEV2_PAYLOAD_NONCE 40  /* Nonce */
101
39.8k
#define IKEV2_PAYLOAD_NOTIFY  41  /* Notify */
102
7.54k
#define IKEV2_PAYLOAD_DELETE  42  /* Delete */
103
#define IKEV2_PAYLOAD_VENDOR  43  /* Vendor ID */
104
5.65k
#define IKEV2_PAYLOAD_TSi 44  /* Traffic Selector - Initiator */
105
23.0k
#define IKEV2_PAYLOAD_TSr 45  /* Traffic Selector - Responder */
106
278k
#define IKEV2_PAYLOAD_SK  46  /* Encrypted */
107
11.6k
#define IKEV2_PAYLOAD_CP  47  /* Configuration Payload */
108
21.2k
#define IKEV2_PAYLOAD_EAP 48  /* Extensible Authentication */
109
#define IKEV2_PAYLOAD_GSPM  49  /* RFC6467 Generic Secure Password */
110
278k
#define IKEV2_PAYLOAD_SKF 53  /* RFC7383 Encrypted Fragment Payload */
111
112
extern struct iked_constmap ikev2_payload_map[];
113
114
/*
115
 * SA payload
116
 */
117
118
struct ikev2_sa_proposal {
119
  uint8_t    sap_more;    /* Last proposal or more */
120
  uint8_t    sap_reserved;    /* Must be set to zero */
121
  uint16_t   sap_length;    /* Proposal length */
122
  uint8_t    sap_proposalnr;  /* Proposal number */
123
  uint8_t    sap_protoid;   /* Protocol Id */
124
  uint8_t    sap_spisize;   /* SPI size */
125
  uint8_t    sap_transforms;  /* Number of transforms */
126
  /* Followed by variable-length SPI */
127
  /* Followed by variable-length transforms */
128
} __packed;
129
130
#define IKEV2_SAP_LAST  0
131
#define IKEV2_SAP_MORE  2
132
133
#define IKEV2_SAPROTO_NONE    0 /* None */
134
#define IKEV2_SAPROTO_IKE   1 /* IKEv2 */
135
#define IKEV2_SAPROTO_AH    2 /* AH */
136
#define IKEV2_SAPROTO_ESP   3 /* ESP */
137
#define IKEV2_SAPROTO_FC_ESP_HEADER 4 /* RFC4595 */
138
#define IKEV2_SAPROTO_FC_CT_AUTH  5 /* RFC4595 */
139
#define IKEV2_SAPROTO_IPCOMP    204 /* private, should be 4 */
140
141
extern struct iked_constmap ikev2_saproto_map[];
142
143
struct ikev2_transform {
144
  uint8_t   xfrm_more;    /* Last transform or more */
145
  uint8_t   xfrm_reserved;    /* Must be set to zero */
146
  uint16_t  xfrm_length;    /* Transform length */
147
  uint8_t   xfrm_type;    /* Transform type */
148
  uint8_t   xfrm_reserved1;   /* Must be set to zero */
149
  uint16_t  xfrm_id;    /* Transform Id */
150
  /* Followed by variable-length transform attributes */
151
} __packed;
152
153
#define IKEV2_XFORM_LAST    0
154
3.63k
#define IKEV2_XFORM_MORE    3
155
156
1.27k
#define IKEV2_XFORMTYPE_ENCR    1  /* Encryption */
157
789
#define IKEV2_XFORMTYPE_PRF   2  /* Pseudo-Random Function */
158
174
#define IKEV2_XFORMTYPE_INTEGR    3  /* Integrity Algorithm */
159
861
#define IKEV2_XFORMTYPE_DH    4  /* Diffie-Hellman Group */
160
1.01k
#define IKEV2_XFORMTYPE_ESN   5  /* Extended Sequence Numbers */
161
#define IKEV2_XFORMTYPE_MAX   6
162
163
extern struct iked_constmap ikev2_xformtype_map[];
164
165
#define IKEV2_XFORMENCR_NONE    0 /* None */
166
#define IKEV2_XFORMENCR_DES_IV64  1 /* RFC1827 */
167
#define IKEV2_XFORMENCR_DES   2 /* RFC2405 */
168
#define IKEV2_XFORMENCR_3DES    3 /* RFC2451 */
169
#define IKEV2_XFORMENCR_RC5   4 /* RFC2451 */
170
#define IKEV2_XFORMENCR_IDEA    5 /* RFC2451 */
171
#define IKEV2_XFORMENCR_CAST    6 /* RFC2451 */
172
#define IKEV2_XFORMENCR_BLOWFISH  7 /* RFC2451 */
173
#define IKEV2_XFORMENCR_3IDEA   8 /* RFC2451 */
174
#define IKEV2_XFORMENCR_DES_IV32  9 /* DESIV32 */
175
#define IKEV2_XFORMENCR_RC4   10  /* RFC2451 */
176
#define IKEV2_XFORMENCR_NULL    11  /* RFC2410 */
177
#define IKEV2_XFORMENCR_AES_CBC   12  /* RFC3602 */
178
#define IKEV2_XFORMENCR_AES_CTR   13  /* RFC3664 */
179
#define IKEV2_XFORMENCR_AES_CCM_8 14  /* RFC5282 */
180
#define IKEV2_XFORMENCR_AES_CCM_12  15  /* RFC5282 */
181
#define IKEV2_XFORMENCR_AES_CCM_16  16  /* RFC5282 */
182
#define IKEV2_XFORMENCR_AES_GCM_8 18  /* RFC5282 */
183
#define IKEV2_XFORMENCR_AES_GCM_12  19  /* RFC5282 */
184
#define IKEV2_XFORMENCR_AES_GCM_16  20  /* RFC5282 */
185
#define IKEV2_XFORMENCR_NULL_AES_GMAC 21  /* RFC4543 */
186
#define IKEV2_XFORMENCR_XTS_AES   22  /* IEEE P1619 */
187
#define IKEV2_XFORMENCR_CAMELLIA_CBC  23  /* RFC5529 */
188
#define IKEV2_XFORMENCR_CAMELLIA_CTR  24  /* RFC5529 */
189
#define IKEV2_XFORMENCR_CAMELLIA_CCM_8  25  /* RFC5529 */
190
#define IKEV2_XFORMENCR_CAMELLIA_CCM_12 26  /* RFC5529 */
191
#define IKEV2_XFORMENCR_CAMELLIA_CCM_16 27  /* RFC5529 */
192
#define IKEV2_XFORMENCR_CHACHA20_POLY1305 28  /* RFC7634 */
193
194
extern struct iked_constmap ikev2_xformencr_map[];
195
196
#define IKEV2_IPCOMP_OUI    1 /* UNSPECIFIED */
197
#define IKEV2_IPCOMP_DEFLATE    2 /* RFC2394 */
198
#define IKEV2_IPCOMP_LZS    3 /* RFC2395 */
199
#define IKEV2_IPCOMP_LZJH   4 /* RFC3051 */
200
201
extern struct iked_constmap ikev2_ipcomp_map[];
202
203
#define IKEV2_XFORMPRF_HMAC_MD5   1 /* RFC2104 */
204
#define IKEV2_XFORMPRF_HMAC_SHA1  2 /* RFC2104 */
205
#define IKEV2_XFORMPRF_HMAC_TIGER 3 /* RFC2104 */
206
#define IKEV2_XFORMPRF_AES128_XCBC  4 /* RFC3664 */
207
#define IKEV2_XFORMPRF_HMAC_SHA2_256  5 /* RFC4868 */
208
#define IKEV2_XFORMPRF_HMAC_SHA2_384  6 /* RFC4868 */
209
#define IKEV2_XFORMPRF_HMAC_SHA2_512  7 /* RFC4868 */
210
#define IKEV2_XFORMPRF_AES128_CMAC  8 /* RFC4615 */
211
212
extern struct iked_constmap ikev2_xformprf_map[];
213
214
#define IKEV2_XFORMAUTH_NONE    0 /* No Authentication */
215
#define IKEV2_XFORMAUTH_HMAC_MD5_96 1 /* RFC2403 */
216
#define IKEV2_XFORMAUTH_HMAC_SHA1_96  2 /* RFC2404 */
217
#define IKEV2_XFORMAUTH_DES_MAC   3 /* DES-MAC */
218
#define IKEV2_XFORMAUTH_KPDK_MD5  4 /* RFC1826 */
219
#define IKEV2_XFORMAUTH_AES_XCBC_96 5 /* RFC3566 */
220
#define IKEV2_XFORMAUTH_HMAC_MD5_128  6 /* RFC4595 */
221
#define IKEV2_XFORMAUTH_HMAC_SHA1_160 7 /* RFC4595 */
222
#define IKEV2_XFORMAUTH_AES_CMAC_96 8 /* RFC4494 */
223
#define IKEV2_XFORMAUTH_AES_128_GMAC  9 /* RFC4543 */
224
#define IKEV2_XFORMAUTH_AES_192_GMAC  10  /* RFC4543 */
225
#define IKEV2_XFORMAUTH_AES_256_GMAC  11  /* RFC4543 */
226
#define IKEV2_XFORMAUTH_HMAC_SHA2_256_128 12  /* RFC4868 */
227
#define IKEV2_XFORMAUTH_HMAC_SHA2_384_192 13  /* RFC4868 */
228
#define IKEV2_XFORMAUTH_HMAC_SHA2_512_256 14  /* RFC4868 */
229
230
/* Placeholders for AEAD ciphers (only used internally) */
231
#define IKEV2_XFORMAUTH_AES_GCM_8 2018  /* internal */
232
#define IKEV2_XFORMAUTH_AES_GCM_12  2019  /* internal */
233
#define IKEV2_XFORMAUTH_AES_GCM_16  2020  /* internal */
234
235
extern struct iked_constmap ikev2_xformauth_map[];
236
237
#define IKEV2_XFORMDH_NONE    0 /* No DH */
238
#define IKEV2_XFORMDH_MODP_768    1 /* DH Group 1 */
239
#define IKEV2_XFORMDH_MODP_1024   2 /* DH Group 2 */
240
#define IKEV2_XFORMDH_MODP_1536   5 /* DH Group 5 */
241
#define IKEV2_XFORMDH_MODP_2048   14  /* DH Group 14 */
242
#define IKEV2_XFORMDH_MODP_3072   15  /* DH Group 15 */
243
#define IKEV2_XFORMDH_MODP_4096   16  /* DH Group 16 */
244
#define IKEV2_XFORMDH_MODP_6144   17  /* DH Group 17 */
245
#define IKEV2_XFORMDH_MODP_8192   18  /* DH Group 18 */
246
#define IKEV2_XFORMDH_ECP_256   19  /* RFC5114 */
247
#define IKEV2_XFORMDH_ECP_384   20  /* RFC5114 */
248
#define IKEV2_XFORMDH_ECP_521   21  /* RFC5114 */
249
#define IKEV2_XFORMDH_ECP_192   25  /* RFC5114 */
250
#define IKEV2_XFORMDH_ECP_224   26  /* RFC5114 */
251
#define IKEV2_XFORMDH_BRAINPOOL_P224R1  27  /* RFC6954 */
252
#define IKEV2_XFORMDH_BRAINPOOL_P256R1  28  /* RFC6954 */
253
#define IKEV2_XFORMDH_BRAINPOOL_P384R1  29  /* RFC6954 */
254
#define IKEV2_XFORMDH_BRAINPOOL_P512R1  30  /* RFC6954 */
255
#define IKEV2_XFORMDH_CURVE25519  31  /* RFC8031 */
256
#define IKEV2_XFORMDH_X_SNTRUP761X25519 1035  /* private */
257
258
extern struct iked_constmap ikev2_xformdh_map[];
259
260
#define IKEV2_IPV4_OVERHEAD   (20 + 8 + 28) /* IPv4 + UDP + IKE_HDR*/
261
#define IKEV2_MAXLEN_IPV4_FRAG    (576 - IKEV2_IPV4_OVERHEAD)
262
#define IKEV2_IPV6_OVERHEAD   (40 + 8 + 28) /* IPv6 + UDP + IKE_HDR*/
263
#define IKEV2_MAXLEN_IPV6_FRAG    (1280 - IKEV2_IPV6_OVERHEAD)
264
265
#define IKEV2_MAXNUM_TSS    255 /* 8 bit Number of TSs field */
266
267
#define IKEV2_XFORMESN_NONE   0 /* No ESN */
268
#define IKEV2_XFORMESN_ESN    1 /* ESN */
269
270
extern struct iked_constmap ikev2_xformesn_map[];
271
272
struct ikev2_attribute {
273
  uint16_t  attr_type;  /* Attribute type */
274
  uint16_t  attr_length;  /* Attribute length or value */
275
  /* Followed by variable length (TLV) */
276
} __packed;
277
278
#define IKEV2_ATTRAF_TLV    0x0000  /* Type-Length-Value format */
279
105k
#define IKEV2_ATTRAF_TV     0x8000  /* Type-Value format */
280
281
41.9k
#define IKEV2_ATTRTYPE_KEY_LENGTH 14  /* Key length */
282
283
extern struct iked_constmap ikev2_attrtype_map[];
284
285
/*
286
 * KE Payload
287
 */
288
289
struct ikev2_keyexchange {
290
  uint16_t   kex_dhgroup;   /* DH Group # */
291
  uint16_t   kex_reserved;    /* Reserved */
292
} __packed;
293
294
/*
295
 * N payload
296
 */
297
298
struct ikev2_notify {
299
  uint8_t    n_protoid;   /* Protocol Id */
300
  uint8_t    n_spisize;   /* SPI size */
301
  uint16_t   n_type;    /* Notify message type */
302
  /* Followed by variable length SPI */
303
  /* Followed by variable length notification data */
304
} __packed;
305
306
#define IKEV2_N_UNSUPPORTED_CRITICAL_PAYLOAD  1 /* RFC7296 */
307
#define IKEV2_N_INVALID_IKE_SPI     4 /* RFC7296 */
308
#define IKEV2_N_INVALID_MAJOR_VERSION   5 /* RFC7296 */
309
#define IKEV2_N_INVALID_SYNTAX      7 /* RFC7296 */
310
#define IKEV2_N_INVALID_MESSAGE_ID    9 /* RFC7296 */
311
#define IKEV2_N_INVALID_SPI     11  /* RFC7296 */
312
36
#define IKEV2_N_NO_PROPOSAL_CHOSEN    14  /* RFC7296 */
313
143
#define IKEV2_N_INVALID_KE_PAYLOAD    17  /* RFC7296 */
314
6
#define IKEV2_N_AUTHENTICATION_FAILED   24  /* RFC7296 */
315
#define IKEV2_N_SINGLE_PAIR_REQUIRED    34  /* RFC7296 */
316
273
#define IKEV2_N_NO_ADDITIONAL_SAS   35  /* RFC7296 */
317
#define IKEV2_N_INTERNAL_ADDRESS_FAILURE  36  /* RFC7296 */
318
#define IKEV2_N_FAILED_CP_REQUIRED    37  /* RFC7296 */
319
#define IKEV2_N_TS_UNACCEPTABLE     38  /* RFC7296 */
320
#define IKEV2_N_INVALID_SELECTORS   39  /* RFC7296 */
321
#define IKEV2_N_UNACCEPTABLE_ADDRESSES    40  /* RFC4555 */
322
#define IKEV2_N_UNEXPECTED_NAT_DETECTED   41  /* RFC4555 */
323
#define IKEV2_N_USE_ASSIGNED_HoA    42  /* RFC5026 */
324
354
#define IKEV2_N_TEMPORARY_FAILURE   43  /* RFC7296 */
325
73
#define IKEV2_N_CHILD_SA_NOT_FOUND    44  /* RFC7296 */
326
#define IKEV2_N_INITIAL_CONTACT     16384 /* RFC7296 */
327
#define IKEV2_N_SET_WINDOW_SIZE     16385 /* RFC7296 */
328
#define IKEV2_N_ADDITIONAL_TS_POSSIBLE    16386 /* RFC7296 */
329
255
#define IKEV2_N_IPCOMP_SUPPORTED    16387  /* RFC7296 */
330
29.1k
#define IKEV2_N_NAT_DETECTION_SOURCE_IP   16388  /* RFC7296 */
331
26.0k
#define IKEV2_N_NAT_DETECTION_DESTINATION_IP  16389  /* RFC7296 */
332
2
#define IKEV2_N_COOKIE        16390  /* RFC7296 */
333
356
#define IKEV2_N_USE_TRANSPORT_MODE    16391  /* RFC7296 */
334
#define IKEV2_N_HTTP_CERT_LOOKUP_SUPPORTED  16392 /* RFC7296 */
335
82
#define IKEV2_N_REKEY_SA      16393  /* RFC7296 */
336
#define IKEV2_N_ESP_TFC_PADDING_NOT_SUPPORTED 16394 /* RFC7296 */
337
#define IKEV2_N_NON_FIRST_FRAGMENTS_ALSO  16395 /* RFC7296 */
338
1.81k
#define IKEV2_N_MOBIKE_SUPPORTED    16396  /* RFC4555 */
339
#define IKEV2_N_ADDITIONAL_IP4_ADDRESS    16397 /* RFC4555 */
340
#define IKEV2_N_ADDITIONAL_IP6_ADDRESS    16398 /* RFC4555 */
341
#define IKEV2_N_NO_ADDITIONAL_ADDRESSES   16399 /* RFC4555 */
342
388
#define IKEV2_N_UPDATE_SA_ADDRESSES   16400  /* RFC4555 */
343
242
#define IKEV2_N_COOKIE2       16401  /* RFC4555 */
344
#define IKEV2_N_NO_NATS_ALLOWED     16402 /* RFC4555 */
345
#define IKEV2_N_AUTH_LIFETIME     16403 /* RFC4478 */
346
#define IKEV2_N_MULTIPLE_AUTH_SUPPORTED   16404 /* RFC4739 */
347
#define IKEV2_N_ANOTHER_AUTH_FOLLOWS    16405 /* RFC4739 */
348
#define IKEV2_N_REDIRECT_SUPPORTED    16406 /* RFC5685 */
349
#define IKEV2_N_REDIRECT      16407 /* RFC5685 */
350
#define IKEV2_N_REDIRECTED_FROM     16408 /* RFC5685 */
351
#define IKEV2_N_TICKET_LT_OPAQUE    16409 /* RFC5723 */
352
#define IKEV2_N_TICKET_REQUEST      16410 /* RFC5723 */
353
#define IKEV2_N_TICKET_ACK      16411 /* RFC5723 */
354
#define IKEV2_N_TICKET_NACK     16412 /* RFC5723 */
355
#define IKEV2_N_TICKET_OPAQUE     16413 /* RFC5723 */
356
#define IKEV2_N_LINK_ID       16414 /* RFC5739 */
357
#define IKEV2_N_USE_WESP_MODE     16415 /* RFC5415 */
358
#define IKEV2_N_ROHC_SUPPORTED      16416 /* RFC5857 */
359
#define IKEV2_N_EAP_ONLY_AUTHENTICATION   16417 /* RFC5998 */
360
#define IKEV2_N_CHILDLESS_IKEV2_SUPPORTED 16418 /* RFC6023 */
361
#define IKEV2_N_QUICK_CRASH_DETECTION   16419 /* RFC6290 */
362
#define IKEV2_N_IKEV2_MESSAGE_ID_SYNC_SUPPORTED 16420 /* RFC6311 */
363
#define IKEV2_N_IPSEC_REPLAY_CTR_SYNC_SUPPORTED 16421 /* RFC6311 */
364
#define IKEV2_N_IKEV2_MESSAGE_ID_SYNC   16422 /* RFC6311 */
365
#define IKEV2_N_IPSEC_REPLAY_CTR_SYNC   16423 /* RFC6311 */
366
#define IKEV2_N_SECURE_PASSWORD_METHODS   16424 /* RFC6467 */
367
#define IKEV2_N_PSK_PERSIST     16425 /* RFC6631 */
368
#define IKEV2_N_PSK_CONFIRM     16426 /* RFC6631 */
369
#define IKEV2_N_ERX_SUPPORTED     16427 /* RFC6867 */
370
#define IKEV2_N_IFOM_CAPABILITY     16428 /* OA3GPP */
371
14
#define IKEV2_N_FRAGMENTATION_SUPPORTED   16430  /* RFC7383 */
372
7
#define IKEV2_N_SIGNATURE_HASH_ALGORITHMS 16431  /* RFC7427 */
373
374
extern struct iked_constmap ikev2_n_map[];
375
376
/*
377
 * DELETE payload
378
 */
379
380
struct ikev2_delete {
381
  uint8_t    del_protoid;   /* Protocol Id */
382
  uint8_t    del_spisize;   /* SPI size */
383
  uint16_t   del_nspi;    /* Number of SPIs */
384
  /* Followed by variable length SPIs */
385
} __packed;
386
387
/*
388
 * ID payload
389
 */
390
391
struct ikev2_id {
392
  uint8_t    id_type;   /* Id type */
393
  uint8_t    id_reserved[3];  /* Reserved */
394
  /* Followed by the identification data */
395
} __packed;
396
397
14.3k
#define IKEV2_ID_NONE   0  /* No ID */
398
#define IKEV2_ID_IPV4   1 /* RFC7296 (ID_IPV4_ADDR) */
399
#define IKEV2_ID_FQDN   2 /* RFC7296 */
400
#define IKEV2_ID_UFQDN    3 /* RFC7296 (ID_RFC822_ADDR) */
401
#define IKEV2_ID_IPV6   5 /* RFC7296 (ID_IPV6_ADDR) */
402
#define IKEV2_ID_ASN1_DN  9 /* RFC7296 */
403
#define IKEV2_ID_ASN1_GN  10  /* RFC7296 */
404
#define IKEV2_ID_KEY_ID   11  /* RFC7296 */
405
#define IKEV2_ID_FC_NAME  12  /* RFC4595 */
406
407
extern struct iked_constmap ikev2_id_map[];
408
409
/*
410
 * CERT/CERTREQ payloads
411
 */
412
413
struct ikev2_cert {
414
  uint8_t   cert_type;  /* Encoding */
415
  /* Followed by the certificate data */
416
} __packed;
417
418
5.37k
#define IKEV2_CERT_NONE     0  /* None */
419
#define IKEV2_CERT_X509_PKCS7   1 /* UNSPECIFIED */
420
#define IKEV2_CERT_PGP      2 /* UNSPECIFIED */
421
#define IKEV2_CERT_DNS_SIGNED_KEY 3 /* UNSPECIFIED */
422
1.34k
#define IKEV2_CERT_X509_CERT    4  /* RFC7296 */
423
#define IKEV2_CERT_KERBEROS_TOKEN 6 /* UNSPECIFIED */
424
#define IKEV2_CERT_CRL      7 /* RFC7296 */
425
#define IKEV2_CERT_ARL      8 /* UNSPECIFIED */
426
#define IKEV2_CERT_SPKI     9 /* UNSPECIFIED */
427
#define IKEV2_CERT_X509_ATTR    10  /* UNSPECIFIED */
428
#define IKEV2_CERT_RSA_KEY    11  /* RFC7296 */
429
#define IKEV2_CERT_HASHURL_X509   12  /* RFC7296 */
430
#define IKEV2_CERT_HASHURL_X509_BUNDLE  13  /* RFC7296 */
431
#define IKEV2_CERT_OCSP     14  /* RFC4806 */
432
/*
433
 * As of November 2014, work was still in progress to add a more generic
434
 * format for raw public keys (RFC7296), so we use a number in IANA's private
435
 * use range (201-255, same RFC) for ECDSA.
436
 */
437
#define IKEV2_CERT_ECDSA    201 /* Private */
438
2.78k
#define IKEV2_CERT_BUNDLE   254  /* Private */
439
440
extern struct iked_constmap ikev2_cert_map[];
441
442
/*
443
 * TSi/TSr payloads
444
 */
445
446
struct ikev2_tsp {
447
  uint8_t   tsp_count;    /* Number of TSs */
448
  uint8_t   tsp_reserved[3];  /* Reserved */
449
  /* Followed by the traffic selectors */
450
} __packed;
451
452
struct ikev2_ts {
453
  uint8_t   ts_type;    /* TS type */
454
  uint8_t   ts_protoid;   /* Protocol Id */
455
  uint16_t  ts_length;    /* Length */
456
  uint16_t  ts_startport;   /* Start port */
457
  uint16_t  ts_endport;   /* End port */
458
} __packed;
459
460
9.66k
#define IKEV2_TS_IPV4_ADDR_RANGE  7  /* RFC7296 */
461
1.54k
#define IKEV2_TS_IPV6_ADDR_RANGE  8  /* RFC7296 */
462
#define IKEV2_TS_FC_ADDR_RANGE    9 /* RFC4595 */
463
464
extern struct iked_constmap ikev2_ts_map[];
465
466
/*
467
 * AUTH payload
468
 */
469
470
struct ikev2_auth {
471
  uint8_t   auth_method;    /* Signature type */
472
  uint8_t   auth_reserved[3]; /* Reserved */
473
  /* Followed by the signature */
474
} __packed;
475
476
#define IKEV2_AUTH_NONE     0 /* None */
477
#define IKEV2_AUTH_RSA_SIG    1 /* RFC7296 */
478
#define IKEV2_AUTH_SHARED_KEY_MIC 2 /* RFC7296 */
479
#define IKEV2_AUTH_DSS_SIG    3 /* RFC7296 */
480
#define IKEV2_AUTH_ECDSA_256    9 /* RFC4754 */
481
#define IKEV2_AUTH_ECDSA_384    10  /* RFC4754 */
482
#define IKEV2_AUTH_ECDSA_521    11  /* RFC4754 */
483
#define IKEV2_AUTH_GSPM     12  /* RFC6467 */
484
#define IKEV2_AUTH_NULL     13  /* RFC7619 */
485
#define IKEV2_AUTH_SIG      14  /* RFC7427 */
486
#define IKEV2_AUTH_SIG_ANY    255 /* Internal (any signature) */
487
/*
488
 * AUTH_SIG also serves as an indication that a given policy has
489
 * been configured to accept RSA or ECDSA payloads, as long as it
490
 * successfully authenticates against a configured CA.
491
 */
492
493
extern struct iked_constmap ikev2_auth_map[];
494
495
/* Notifications used together with IKEV2_AUTH_SIG */
496
497
#define IKEV2_SIGHASH_RESERVED    0 /* RFC7427 */
498
#define IKEV2_SIGHASH_SHA1    1 /* RFC7427 */
499
0
#define IKEV2_SIGHASH_SHA2_256    2  /* RFC7427 */
500
#define IKEV2_SIGHASH_SHA2_384    3 /* RFC7427 */
501
#define IKEV2_SIGHASH_SHA2_512    4 /* RFC7427 */
502
503
extern struct iked_constmap ikev2_sighash_map[];
504
505
/*
506
 * CP payload
507
 */
508
509
struct ikev2_cp {
510
  uint8_t   cp_type;
511
  uint8_t   cp_reserved[3];
512
  /* Followed by the attributes */
513
} __packed;
514
515
#define IKEV2_CP_REQUEST  1 /* CFG-Request */
516
#define IKEV2_CP_REPLY    2 /* CFG-Reply */
517
#define IKEV2_CP_SET    3 /* CFG-SET */
518
#define IKEV2_CP_ACK    4 /* CFG-ACK */
519
520
extern struct iked_constmap ikev2_cp_map[];
521
522
struct ikev2_cfg {
523
  uint16_t  cfg_type; /* first bit must be set to zero */
524
  uint16_t  cfg_length;
525
  /* Followed by variable-length data */
526
} __packed;
527
528
1.32k
#define IKEV2_CFG_INTERNAL_IP4_ADDRESS    1  /* RFC7296 */
529
#define IKEV2_CFG_INTERNAL_IP4_NETMASK    2 /* RFC7296 */
530
1.67k
#define IKEV2_CFG_INTERNAL_IP4_DNS    3  /* RFC7296 */
531
#define IKEV2_CFG_INTERNAL_IP4_NBNS   4 /* RFC7296 */
532
#define IKEV2_CFG_INTERNAL_ADDRESS_EXPIRY 5 /* RFC4306 */
533
#define IKEV2_CFG_INTERNAL_IP4_DHCP   6 /* RFC7296 */
534
#define IKEV2_CFG_APPLICATION_VERSION   7 /* RFC7296 */
535
2.41k
#define IKEV2_CFG_INTERNAL_IP6_ADDRESS    8  /* RFC7296 */
536
3.18k
#define IKEV2_CFG_INTERNAL_IP6_DNS    10  /* RFC7296 */
537
#define IKEV2_CFG_INTERNAL_IP6_NBNS   11  /* RFC4306 */
538
#define IKEV2_CFG_INTERNAL_IP6_DHCP   12  /* RFC7296 */
539
#define IKEV2_CFG_INTERNAL_IP4_SUBNET   13  /* RFC7296 */
540
#define IKEV2_CFG_SUPPORTED_ATTRIBUTES    14  /* RFC7296 */
541
#define IKEV2_CFG_INTERNAL_IP6_SUBNET   15  /* RFC7296 */
542
#define IKEV2_CFG_MIP6_HOME_PREFIX    16  /* RFC5026 */
543
#define IKEV2_CFG_INTERNAL_IP6_LINK   17  /* RFC5739 */
544
#define IKEV2_CFG_INTERNAL_IP6_PREFIX   18  /* RFC5739 */
545
#define IKEV2_CFG_HOME_AGENT_ADDRESS    19  /* http://www.3gpp.org/ftp/Specs/html-info/24302.htm */
546
#define IKEV2_CFG_INTERNAL_IP4_SERVER   23456 /* MS-IKEE */
547
#define IKEV2_CFG_INTERNAL_IP6_SERVER   23457 /* MS-IKEE */
548
549
extern struct iked_constmap ikev2_cfg_map[];
550
551
/* IKEv1 payload types */
552
#define IKEV1_PAYLOAD_NONE  0 /* No payload */
553
#define IKEV1_PAYLOAD_PROPOSAL  2 /* Proposal */
554
555
#endif /* IKED_IKEV2_H */
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/ikev2_pld.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/ikev2_pld.c.html index ba36ae8e0..9562d48ea 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/ikev2_pld.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/ikev2_pld.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/ikev2_pld.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: ikev2_pld.c,v 1.133 2023/09/02 18:36:30 tobhe Exp $ */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 * Copyright (c) 2014 Hans-Joerg Hoexer
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#include <sys/queue.h>
22
#include <sys/socket.h>
23
#include <sys/uio.h>
24
25
#include <netinet/in.h>
26
#include <arpa/inet.h>
27
28
#include <stdlib.h>
29
#include <stdio.h>
30
#include <unistd.h>
31
#include <string.h>
32
#include <signal.h>
33
#include <endian.h>
34
#include <errno.h>
35
#include <err.h>
36
#include <event.h>
37
38
#include <openssl/sha.h>
39
#include <openssl/evp.h>
40
41
#include "iked.h"
42
#include "ikev2.h"
43
#include "eap.h"
44
#include "dh.h"
45
46
int  ikev2_validate_pld(struct iked_message *, size_t, size_t,
47
      struct ikev2_payload *);
48
int  ikev2_pld_payloads(struct iked *, struct iked_message *,
49
      size_t, size_t, unsigned int);
50
int  ikev2_validate_sa(struct iked_message *, size_t, size_t,
51
      struct ikev2_sa_proposal *);
52
int  ikev2_pld_sa(struct iked *, struct ikev2_payload *,
53
      struct iked_message *, size_t, size_t);
54
int  ikev2_validate_xform(struct iked_message *, size_t, size_t,
55
      struct ikev2_transform *);
56
int  ikev2_pld_xform(struct iked *, struct iked_message *,
57
      size_t, size_t);
58
int  ikev2_validate_attr(struct iked_message *, size_t, size_t,
59
      struct ikev2_attribute *);
60
int  ikev2_pld_attr(struct iked *, struct ikev2_transform *,
61
      struct iked_message *, size_t, size_t);
62
int  ikev2_validate_ke(struct iked_message *, size_t, size_t,
63
      struct ikev2_keyexchange *);
64
int  ikev2_pld_ke(struct iked *, struct ikev2_payload *,
65
      struct iked_message *, size_t, size_t);
66
int  ikev2_validate_id(struct iked_message *, size_t, size_t,
67
      struct ikev2_id *);
68
int  ikev2_pld_id(struct iked *, struct ikev2_payload *,
69
      struct iked_message *, size_t, size_t, unsigned int);
70
int  ikev2_validate_cert(struct iked_message *, size_t, size_t,
71
      struct ikev2_cert *);
72
int  ikev2_pld_cert(struct iked *, struct ikev2_payload *,
73
      struct iked_message *, size_t, size_t);
74
int  ikev2_validate_certreq(struct iked_message *, size_t, size_t,
75
      struct ikev2_cert *);
76
int  ikev2_pld_certreq(struct iked *, struct ikev2_payload *,
77
      struct iked_message *, size_t, size_t);
78
int  ikev2_pld_nonce(struct iked *, struct ikev2_payload *,
79
      struct iked_message *, size_t, size_t);
80
int  ikev2_validate_notify(struct iked_message *, size_t, size_t,
81
      struct ikev2_notify *);
82
int  ikev2_pld_notify(struct iked *, struct ikev2_payload *,
83
      struct iked_message *, size_t, size_t);
84
int  ikev2_validate_delete(struct iked_message *, size_t, size_t,
85
      struct ikev2_delete *);
86
int  ikev2_pld_delete(struct iked *, struct ikev2_payload *,
87
      struct iked_message *, size_t, size_t);
88
int  ikev2_validate_tss(struct iked_message *, size_t, size_t,
89
      struct ikev2_tsp *);
90
int  ikev2_pld_tss(struct iked *, struct ikev2_payload *,
91
      struct iked_message *, size_t, size_t);
92
int  ikev2_validate_ts(struct iked_message *, size_t, size_t,
93
      struct ikev2_ts *);
94
int  ikev2_pld_ts(struct iked *, struct ikev2_payload *,
95
      struct iked_message *, size_t, size_t, unsigned int);
96
int  ikev2_validate_auth(struct iked_message *, size_t, size_t,
97
      struct ikev2_auth *);
98
int  ikev2_pld_auth(struct iked *, struct ikev2_payload *,
99
      struct iked_message *, size_t, size_t);
100
int  ikev2_pld_e(struct iked *, struct ikev2_payload *,
101
      struct iked_message *, size_t, size_t);
102
int  ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
103
      struct iked_message *msg, size_t offset, size_t left);
104
int  ikev2_frags_reassemble(struct iked *env,
105
      struct ikev2_payload *pld, struct iked_message *msg);
106
int  ikev2_validate_cp(struct iked_message *, size_t, size_t,
107
      struct ikev2_cp *);
108
int  ikev2_pld_cp(struct iked *, struct ikev2_payload *,
109
      struct iked_message *, size_t, size_t);
110
int  ikev2_validate_eap(struct iked_message *, size_t, size_t,
111
      struct eap_header *);
112
int  ikev2_pld_eap(struct iked *, struct ikev2_payload *,
113
      struct iked_message *, size_t, size_t);
114
115
int
116
ikev2_pld_parse(struct iked *env, struct ike_header *hdr,
117
    struct iked_message *msg, size_t offset)
118
15.4k
{
119
15.4k
  log_debug("%s: header ispi %s rspi %s"
120
15.4k
      " nextpayload %s version 0x%02x exchange %s flags 0x%02x"
121
15.4k
      " msgid %d length %u response %d", __func__,
122
15.4k
      print_spi(betoh64(hdr->ike_ispi), 8),
123
15.4k
      print_spi(betoh64(hdr->ike_rspi), 8),
124
15.4k
      print_map(hdr->ike_nextpayload, ikev2_payload_map),
125
15.4k
      hdr->ike_version,
126
15.4k
      print_map(hdr->ike_exchange, ikev2_exchange_map),
127
15.4k
      hdr->ike_flags,
128
15.4k
      betoh32(hdr->ike_msgid),
129
15.4k
      betoh32(hdr->ike_length),
130
15.4k
      msg->msg_response);
131
132
15.4k
  if (ibuf_size(msg->msg_data) < betoh32(hdr->ike_length)) {
133
6
    log_debug("%s: short message", __func__);
134
6
    return (-1);
135
6
  }
136
137
15.4k
  offset += sizeof(*hdr);
138
139
15.4k
  return (ikev2_pld_payloads(env, msg, offset,
140
15.4k
      betoh32(hdr->ike_length), hdr->ike_nextpayload));
141
15.4k
}
142
143
int
144
ikev2_validate_pld(struct iked_message *msg, size_t offset, size_t left,
145
    struct ikev2_payload *pld)
146
291k
{
147
291k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
148
291k
  size_t     pld_length;
149
150
  /* We need at least the generic header. */
151
291k
  if (left < sizeof(*pld)) {
152
2.01k
    log_debug("%s: malformed payload: too short for generic "
153
2.01k
        "header (%zu < %zu)", __func__, left, sizeof(*pld));
154
2.01k
    return (-1);
155
2.01k
  }
156
289k
  memcpy(pld, msgbuf + offset, sizeof(*pld));
157
158
  /*
159
   * We need at least the specified number of bytes.
160
   * pld_length is the full size of the payload including
161
   * the generic payload header.
162
   */
163
289k
  pld_length = betoh16(pld->pld_length);
164
289k
  if (left < pld_length) {
165
6.81k
    log_debug("%s: malformed payload: shorter than specified "
166
6.81k
        "(%zu < %zu)", __func__, left, pld_length);
167
6.81k
    return (-1);
168
6.81k
  }
169
  /*
170
   * Sanity check the specified payload size, it must
171
   * be at least the size of the generic payload header.
172
   */
173
282k
  if (pld_length < sizeof(*pld)) {
174
2.83k
    log_debug("%s: malformed payload: shorter than minimum "
175
2.83k
        "header size (%zu < %zu)", __func__, pld_length,
176
2.83k
        sizeof(*pld));
177
2.83k
    return (-1);
178
2.83k
  }
179
180
279k
  return (0);
181
282k
}
182
183
int
184
ikev2_pld_payloads(struct iked *env, struct iked_message *msg,
185
    size_t offset, size_t length, unsigned int payload)
186
15.4k
{
187
15.4k
  struct ikev2_payload   pld;
188
15.4k
  unsigned int     e;
189
15.4k
  int      ret;
190
15.4k
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
191
15.4k
  size_t       total, left;
192
193
  /* Check if message was decrypted in an E payload */
194
15.4k
  e = msg->msg_e ? IKED_E : 0;
195
196
  /* Bytes left in datagram. */
197
15.4k
  total = length - offset;
198
199
294k
  while (payload != 0 && offset < length) {
200
291k
    if (ikev2_validate_pld(msg, offset, total, &pld))
201
11.6k
      return (-1);
202
203
279k
    log_debug("%s: %spayload %s"
204
279k
        " nextpayload %s critical 0x%02x length %d",
205
279k
        __func__, e ? "decrypted " : "",
206
279k
        print_map(payload, ikev2_payload_map),
207
279k
        print_map(pld.pld_nextpayload, ikev2_payload_map),
208
279k
        pld.pld_reserved & IKEV2_CRITICAL_PAYLOAD,
209
279k
        betoh16(pld.pld_length));
210
211
    /* Skip over generic payload header. */
212
279k
    offset += sizeof(pld);
213
279k
    total -= sizeof(pld);
214
279k
    left = betoh16(pld.pld_length) - sizeof(pld);
215
279k
    ret = 0;
216
217
279k
    switch (payload | e) {
218
0
    case IKEV2_PAYLOAD_SA:
219
32.7k
    case IKEV2_PAYLOAD_SA | IKED_E:
220
32.7k
      ret = ikev2_pld_sa(env, &pld, msg, offset, left);
221
32.7k
      break;
222
0
    case IKEV2_PAYLOAD_KE:
223
10.9k
    case IKEV2_PAYLOAD_KE | IKED_E:
224
10.9k
      ret = ikev2_pld_ke(env, &pld, msg, offset, left);
225
10.9k
      break;
226
13.9k
    case IKEV2_PAYLOAD_IDi | IKED_E:
227
23.7k
    case IKEV2_PAYLOAD_IDr | IKED_E:
228
23.7k
      ret = ikev2_pld_id(env, &pld, msg, offset, left,
229
23.7k
          payload);
230
23.7k
      break;
231
6.90k
    case IKEV2_PAYLOAD_CERT | IKED_E:
232
6.90k
      ret = ikev2_pld_cert(env, &pld, msg, offset, left);
233
6.90k
      break;
234
0
    case IKEV2_PAYLOAD_CERTREQ:
235
15.4k
    case IKEV2_PAYLOAD_CERTREQ | IKED_E:
236
15.4k
      ret = ikev2_pld_certreq(env, &pld, msg, offset, left);
237
15.4k
      break;
238
10.5k
    case IKEV2_PAYLOAD_AUTH | IKED_E:
239
10.5k
      ret = ikev2_pld_auth(env, &pld, msg, offset, left);
240
10.5k
      break;
241
0
    case IKEV2_PAYLOAD_NONCE:
242
3.51k
    case IKEV2_PAYLOAD_NONCE | IKED_E:
243
3.51k
      ret = ikev2_pld_nonce(env, &pld, msg, offset, left);
244
3.51k
      break;
245
0
    case IKEV2_PAYLOAD_NOTIFY:
246
39.8k
    case IKEV2_PAYLOAD_NOTIFY | IKED_E:
247
39.8k
      ret = ikev2_pld_notify(env, &pld, msg, offset, left);
248
39.8k
      break;
249
7.54k
    case IKEV2_PAYLOAD_DELETE | IKED_E:
250
7.54k
      ret = ikev2_pld_delete(env, &pld, msg, offset, left);
251
7.54k
      break;
252
5.65k
    case IKEV2_PAYLOAD_TSi | IKED_E:
253
23.0k
    case IKEV2_PAYLOAD_TSr | IKED_E:
254
23.0k
      ret = ikev2_pld_tss(env, &pld, msg, offset, left);
255
23.0k
      break;
256
0
    case IKEV2_PAYLOAD_SK:
257
0
      ret = ikev2_pld_e(env, &pld, msg, offset, left);
258
0
      break;
259
0
    case IKEV2_PAYLOAD_SKF:
260
0
      ret = ikev2_pld_ef(env, &pld, msg, offset, left);
261
0
      break;
262
11.6k
    case IKEV2_PAYLOAD_CP | IKED_E:
263
11.6k
      ret = ikev2_pld_cp(env, &pld, msg, offset, left);
264
11.6k
      break;
265
21.2k
    case IKEV2_PAYLOAD_EAP | IKED_E:
266
21.2k
      ret = ikev2_pld_eap(env, &pld, msg, offset, left);
267
21.2k
      break;
268
72.4k
    default:
269
72.4k
      print_hex(msgbuf, offset,
270
72.4k
          betoh16(pld.pld_length) - sizeof(pld));
271
72.4k
      break;
272
279k
    }
273
274
279k
    if (ret != 0 && ikev2_msg_frompeer(msg)) {
275
748
      (void)ikev2_send_informational(env, msg);
276
748
      return (-1);
277
748
    }
278
279
    /* Encrypted payloads must appear last */
280
278k
    if ((payload == IKEV2_PAYLOAD_SK) ||
281
278k
        (payload == IKEV2_PAYLOAD_SKF))
282
4
      return (0);
283
284
278k
    payload = pld.pld_nextpayload;
285
278k
    offset += left;
286
278k
    total -= left;
287
278k
  }
288
289
3.06k
  return (0);
290
15.4k
}
291
292
int
293
ikev2_validate_sa(struct iked_message *msg, size_t offset, size_t left,
294
    struct ikev2_sa_proposal *sap)
295
37.6k
{
296
37.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
297
37.6k
  size_t     sap_length;
298
299
37.6k
  if (left < sizeof(*sap)) {
300
15.9k
    log_debug("%s: malformed payload: too short for header "
301
15.9k
        "(%zu < %zu)", __func__, left, sizeof(*sap));
302
15.9k
    return (-1);
303
15.9k
  }
304
21.6k
  memcpy(sap, msgbuf + offset, sizeof(*sap));
305
306
21.6k
  sap_length = betoh16(sap->sap_length);
307
21.6k
  if (sap_length < sizeof(*sap)) {
308
5.62k
    log_debug("%s: malformed payload: shorter than minimum header "
309
5.62k
        "size (%zu < %zu)", __func__, sap_length, sizeof(*sap));
310
5.62k
    return (-1);
311
5.62k
  }
312
16.0k
  if (left < sap_length) {
313
3.10k
    log_debug("%s: malformed payload: too long for actual payload "
314
3.10k
        "size (%zu < %zu)", __func__, left, sap_length);
315
3.10k
    return (-1);
316
3.10k
  }
317
  /*
318
   * If there is only one proposal, sap_length must be the
319
   * total payload size.
320
   */
321
12.9k
  if (!sap->sap_more && left != sap_length) {
322
30
    log_debug("%s: malformed payload: SA payload length mismatches "
323
30
        "single proposal substructure length (%zu != %zu)",
324
30
        __func__, left, sap_length);
325
30
    return (-1);
326
30
  }
327
  /*
328
   * If there are more than one proposal, there must be bytes
329
   * left in the payload.
330
   */
331
12.9k
  if (sap->sap_more && left <= sap_length) {
332
1.00k
    log_debug("%s: malformed payload: SA payload too small for "
333
1.00k
        "further proposals (%zu <= %zu)", __func__,
334
1.00k
        left, sap_length);
335
1.00k
    return (-1);
336
1.00k
  }
337
11.9k
  return (0);
338
12.9k
}
339
340
int
341
ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld,
342
    struct iked_message *msg, size_t offset, size_t left)
343
32.7k
{
344
32.7k
  struct ikev2_sa_proposal   sap;
345
32.7k
  struct iked_proposal    *prop = NULL;
346
32.7k
  uint32_t       spi32;
347
32.7k
  uint64_t       spi = 0, spi64;
348
32.7k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
349
32.7k
  int        r;
350
32.7k
  struct iked_proposals   *props;
351
32.7k
  size_t         total;
352
353
37.6k
  do {
354
37.6k
    if (ikev2_validate_sa(msg, offset, left, &sap))
355
25.6k
      return (-1);
356
357
    /* Assumed size of the first proposals, including SPI if present. */
358
11.9k
    total = (betoh16(sap.sap_length) - sizeof(sap));
359
360
11.9k
    props = &msg->msg_parent->msg_proposals;
361
362
11.9k
    offset += sizeof(sap);
363
11.9k
    left -= sizeof(sap);
364
365
11.9k
    if (sap.sap_spisize) {
366
1.66k
      if (left < sap.sap_spisize) {
367
758
        log_debug("%s: malformed payload: SPI larger than "
368
758
            "actual payload (%zu < %d)", __func__, left,
369
758
            sap.sap_spisize);
370
758
        return (-1);
371
758
      }
372
905
      if (total < sap.sap_spisize) {
373
183
        log_debug("%s: malformed payload: SPI larger than "
374
183
            "proposal (%zu < %d)", __func__, total,
375
183
            sap.sap_spisize);
376
183
        return (-1);
377
183
      }
378
722
      switch (sap.sap_spisize) {
379
356
      case 4:
380
356
        memcpy(&spi32, msgbuf + offset, 4);
381
356
        spi = betoh32(spi32);
382
356
        break;
383
236
      case 8:
384
236
        memcpy(&spi64, msgbuf + offset, 8);
385
236
        spi = betoh64(spi64);
386
236
        break;
387
130
      default:
388
130
        log_debug("%s: unsupported SPI size %d",
389
130
            __func__, sap.sap_spisize);
390
130
        return (-1);
391
722
      }
392
393
592
      offset += sap.sap_spisize;
394
592
      left -= sap.sap_spisize;
395
396
      /* Assumed size of the proposal, now without SPI. */
397
592
      total -= sap.sap_spisize;
398
592
    }
399
400
    /*
401
     * As we verified sanity of packet headers, this check will
402
     * be always false, but just to be sure we keep it.
403
     */
404
10.8k
    if (left < total) {
405
0
      log_debug("%s: malformed payload: too long for payload "
406
0
          "(%zu < %zu)", __func__, left, total);
407
0
      return (-1);
408
0
    }
409
410
10.8k
    log_debug("%s: more %d reserved %d length %d"
411
10.8k
        " proposal #%d protoid %s spisize %d xforms %d spi %s",
412
10.8k
        __func__, sap.sap_more, sap.sap_reserved,
413
10.8k
        betoh16(sap.sap_length), sap.sap_proposalnr,
414
10.8k
        print_map(sap.sap_protoid, ikev2_saproto_map), sap.sap_spisize,
415
10.8k
        sap.sap_transforms, print_spi(spi, sap.sap_spisize));
416
417
10.8k
    if (ikev2_msg_frompeer(msg)) {
418
69
      if ((msg->msg_parent->msg_prop = config_add_proposal(props,
419
69
          sap.sap_proposalnr, sap.sap_protoid)) == NULL) {
420
69
        log_debug("%s: invalid proposal", __func__);
421
69
        return (-1);
422
69
      }
423
0
      prop = msg->msg_parent->msg_prop;
424
0
      prop->prop_peerspi.spi = spi;
425
0
      prop->prop_peerspi.spi_protoid = sap.sap_protoid;
426
0
      prop->prop_peerspi.spi_size = sap.sap_spisize;
427
428
0
      prop->prop_localspi.spi_protoid = sap.sap_protoid;
429
0
      prop->prop_localspi.spi_size = sap.sap_spisize;
430
0
    }
431
432
    /*
433
     * Parse the attached transforms
434
     */
435
10.7k
    if (sap.sap_transforms) {
436
6.27k
      r = ikev2_pld_xform(env, msg, offset, total);
437
6.27k
      if ((r == -2) && ikev2_msg_frompeer(msg)) {
438
0
        log_debug("%s: invalid proposal transform",
439
0
            __func__);
440
441
        /* cleanup and ignore proposal */
442
0
        config_free_proposal(props, prop);
443
0
        prop = msg->msg_parent->msg_prop = NULL;
444
6.27k
      } else if (r != 0) {
445
5.04k
        log_debug("%s: invalid proposal transforms",
446
5.04k
            __func__);
447
5.04k
        return (-1);
448
5.04k
      }
449
6.27k
    }
450
451
5.74k
    offset += total;
452
5.74k
    left -= total;
453
5.74k
  } while (sap.sap_more);
454
455
846
  return (0);
456
32.7k
}
457
458
int
459
ikev2_validate_xform(struct iked_message *msg, size_t offset, size_t total,
460
    struct ikev2_transform *xfrm)
461
8.43k
{
462
8.43k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
463
8.43k
  size_t     xfrm_length;
464
465
8.43k
  if (total < sizeof(*xfrm)) {
466
772
    log_debug("%s: malformed payload: too short for header "
467
772
        "(%zu < %zu)", __func__, total, sizeof(*xfrm));
468
772
    return (-1);
469
772
  }
470
7.66k
  memcpy(xfrm, msgbuf + offset, sizeof(*xfrm));
471
472
7.66k
  xfrm_length = betoh16(xfrm->xfrm_length);
473
7.66k
  if (xfrm_length < sizeof(*xfrm)) {
474
1.14k
    log_debug("%s: malformed payload: shorter than minimum header "
475
1.14k
        "size (%zu < %zu)", __func__, xfrm_length, sizeof(*xfrm));
476
1.14k
    return (-1);
477
1.14k
  }
478
6.51k
  if (total < xfrm_length) {
479
706
    log_debug("%s: malformed payload: too long for payload size "
480
706
        "(%zu < %zu)", __func__, total, xfrm_length);
481
706
    return (-1);
482
706
  }
483
484
5.81k
  return (0);
485
6.51k
}
486
487
int
488
ikev2_pld_xform(struct iked *env, struct iked_message *msg,
489
    size_t offset, size_t total)
490
8.43k
{
491
8.43k
  struct ikev2_transform     xfrm;
492
8.43k
  char         id[BUFSIZ];
493
8.43k
  int        ret = 0;
494
8.43k
  int        r;
495
8.43k
  size_t         xfrm_length;
496
497
8.43k
  if (ikev2_validate_xform(msg, offset, total, &xfrm))
498
2.62k
    return (-1);
499
500
5.81k
  xfrm_length = betoh16(xfrm.xfrm_length);
501
502
5.81k
  switch (xfrm.xfrm_type) {
503
1.27k
  case IKEV2_XFORMTYPE_ENCR:
504
1.27k
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
505
1.27k
        ikev2_xformencr_map), sizeof(id));
506
1.27k
    break;
507
789
  case IKEV2_XFORMTYPE_PRF:
508
789
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
509
789
        ikev2_xformprf_map), sizeof(id));
510
789
    break;
511
174
  case IKEV2_XFORMTYPE_INTEGR:
512
174
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
513
174
        ikev2_xformauth_map), sizeof(id));
514
174
    break;
515
861
  case IKEV2_XFORMTYPE_DH:
516
861
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
517
861
        ikev2_xformdh_map), sizeof(id));
518
861
    break;
519
1.01k
  case IKEV2_XFORMTYPE_ESN:
520
1.01k
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
521
1.01k
        ikev2_xformesn_map), sizeof(id));
522
1.01k
    break;
523
1.69k
  default:
524
1.69k
    snprintf(id, sizeof(id), "<%d>", betoh16(xfrm.xfrm_id));
525
1.69k
    break;
526
5.81k
  }
527
528
5.81k
  log_debug("%s: more %d reserved %d length %zu"
529
5.81k
      " type %s id %s",
530
5.81k
      __func__, xfrm.xfrm_more, xfrm.xfrm_reserved, xfrm_length,
531
5.81k
      print_map(xfrm.xfrm_type, ikev2_xformtype_map), id);
532
533
  /*
534
   * Parse transform attributes, if available
535
   */
536
5.81k
  msg->msg_attrlength = 0;
537
5.81k
  if (xfrm_length > sizeof(xfrm)) {
538
2.77k
    if (ikev2_pld_attr(env, &xfrm, msg, offset + sizeof(xfrm),
539
2.77k
        xfrm_length - sizeof(xfrm)) != 0) {
540
2.17k
      return (-1);
541
2.17k
    }
542
2.77k
  }
543
544
3.63k
  if (ikev2_msg_frompeer(msg)) {
545
0
    r = config_add_transform(msg->msg_parent->msg_prop,
546
0
        xfrm.xfrm_type, betoh16(xfrm.xfrm_id),
547
0
        msg->msg_attrlength, msg->msg_attrlength);
548
0
    if (r == -1) {
549
0
      log_debug("%s: failed to add transform: alloc error",
550
0
          __func__);
551
0
      return (r);
552
0
    } else if (r == -2) {
553
0
      log_debug("%s: failed to add transform: unknown type",
554
0
          __func__);
555
0
      return (r);
556
0
    }
557
0
  }
558
559
  /* Next transform */
560
3.63k
  offset += xfrm_length;
561
3.63k
  total -= xfrm_length;
562
3.63k
  if (xfrm.xfrm_more == IKEV2_XFORM_MORE)
563
2.16k
    ret = ikev2_pld_xform(env, msg, offset, total);
564
1.46k
  else if (total != 0) {
565
    /* No more transforms but still some data left. */
566
245
    log_debug("%s: less data than specified, %zu bytes left",
567
245
        __func__, total);
568
245
    ret = -1;
569
245
  }
570
571
3.63k
  return (ret);
572
3.63k
}
573
574
int
575
ikev2_validate_attr(struct iked_message *msg, size_t offset, size_t total,
576
    struct ikev2_attribute *attr)
577
53.6k
{
578
53.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
579
580
53.6k
  if (total < sizeof(*attr)) {
581
1.04k
    log_debug("%s: malformed payload: too short for header "
582
1.04k
        "(%zu < %zu)", __func__, total, sizeof(*attr));
583
1.04k
    return (-1);
584
1.04k
  }
585
52.6k
  memcpy(attr, msgbuf + offset, sizeof(*attr));
586
587
52.6k
  return (0);
588
53.6k
}
589
590
int
591
ikev2_pld_attr(struct iked *env, struct ikev2_transform *xfrm,
592
    struct iked_message *msg, size_t offset, size_t total)
593
53.6k
{
594
53.6k
  struct ikev2_attribute     attr;
595
53.6k
  unsigned int       type;
596
53.6k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
597
53.6k
  int        ret = 0;
598
53.6k
  size_t         attr_length;
599
600
53.6k
  if (ikev2_validate_attr(msg, offset, total, &attr))
601
1.04k
    return (-1);
602
603
52.6k
  type = betoh16(attr.attr_type) & ~IKEV2_ATTRAF_TV;
604
605
52.6k
  log_debug("%s: attribute type %s length %d total %zu",
606
52.6k
      __func__, print_map(type, ikev2_attrtype_map),
607
52.6k
      betoh16(attr.attr_length), total);
608
609
52.6k
  if (betoh16(attr.attr_type) & IKEV2_ATTRAF_TV) {
610
    /* Type-Value attribute */
611
41.9k
    offset += sizeof(attr);
612
41.9k
    total -= sizeof(attr);
613
614
41.9k
    if (type == IKEV2_ATTRTYPE_KEY_LENGTH)
615
48
      msg->msg_attrlength = betoh16(attr.attr_length);
616
41.9k
  } else {
617
    /* Type-Length-Value attribute */
618
10.7k
    attr_length = betoh16(attr.attr_length);
619
10.7k
    if (attr_length < sizeof(attr)) {
620
605
      log_debug("%s: malformed payload: shorter than "
621
605
          "minimum header size (%zu < %zu)", __func__,
622
605
          attr_length, sizeof(attr));
623
605
      return (-1);
624
605
    }
625
10.1k
    if (total < attr_length) {
626
529
      log_debug("%s: malformed payload: attribute larger "
627
529
          "than actual payload (%zu < %zu)", __func__,
628
529
          total, attr_length);
629
529
      return (-1);
630
529
    }
631
9.57k
    print_hex(msgbuf, offset + sizeof(attr),
632
9.57k
        attr_length - sizeof(attr));
633
9.57k
    offset += attr_length;
634
9.57k
    total -= attr_length;
635
9.57k
  }
636
637
51.4k
  if (total > 0) {
638
    /* Next attribute */
639
50.9k
    ret = ikev2_pld_attr(env, xfrm, msg, offset, total);
640
50.9k
  }
641
642
51.4k
  return (ret);
643
52.6k
}
644
645
int
646
ikev2_validate_ke(struct iked_message *msg, size_t offset, size_t left,
647
    struct ikev2_keyexchange *kex)
648
10.9k
{
649
10.9k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
650
651
10.9k
  if (left < sizeof(*kex)) {
652
6.72k
    log_debug("%s: malformed payload: too short for header "
653
6.72k
        "(%zu < %zu)", __func__, left, sizeof(*kex));
654
6.72k
    return (-1);
655
6.72k
  }
656
4.22k
  memcpy(kex, msgbuf + offset, sizeof(*kex));
657
658
4.22k
  return (0);
659
10.9k
}
660
661
int
662
ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld,
663
    struct iked_message *msg, size_t offset, size_t left)
664
10.9k
{
665
10.9k
  struct ikev2_keyexchange   kex;
666
10.9k
  uint8_t       *buf;
667
10.9k
  size_t         len;
668
10.9k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
669
670
10.9k
  if (ikev2_validate_ke(msg, offset, left, &kex))
671
6.72k
    return (-1);
672
673
4.22k
  log_debug("%s: dh group %s reserved %d", __func__,
674
4.22k
      print_map(betoh16(kex.kex_dhgroup), ikev2_xformdh_map),
675
4.22k
      betoh16(kex.kex_reserved));
676
677
4.22k
  buf = msgbuf + offset + sizeof(kex);
678
4.22k
  len = left - sizeof(kex);
679
680
4.22k
  if (len == 0) {
681
2.08k
    log_debug("%s: malformed payload: no KE data given", __func__);
682
2.08k
    return (-1);
683
2.08k
  }
684
685
2.14k
  print_hex(buf, 0, len);
686
687
2.14k
  if (ikev2_msg_frompeer(msg)) {
688
27
    if (msg->msg_parent->msg_ke != NULL) {
689
4
      log_info("%s: duplicate KE payload", __func__);
690
4
      return (-1);
691
4
    }
692
23
    if ((msg->msg_parent->msg_ke = ibuf_new(buf, len)) == NULL) {
693
0
      log_debug("%s: failed to get exchange", __func__);
694
0
      return (-1);
695
0
    }
696
23
    msg->msg_parent->msg_dhgroup = betoh16(kex.kex_dhgroup);
697
23
  }
698
699
2.13k
  return (0);
700
2.14k
}
701
702
int
703
ikev2_validate_id(struct iked_message *msg, size_t offset, size_t left,
704
    struct ikev2_id *id)
705
23.7k
{
706
23.7k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
707
708
23.7k
  if (left < sizeof(*id)) {
709
9.33k
    log_debug("%s: malformed payload: too short for header "
710
9.33k
        "(%zu < %zu)", __func__, left, sizeof(*id));
711
9.33k
    return (-1);
712
9.33k
  }
713
14.3k
  memcpy(id, msgbuf + offset, sizeof(*id));
714
715
14.3k
  if (id->id_type == IKEV2_ID_NONE) {
716
6.62k
    log_debug("%s: malformed payload: invalid ID type.",
717
6.62k
        __func__);
718
6.62k
    return (-1);
719
6.62k
  }
720
721
7.77k
  return (0);
722
14.3k
}
723
724
int
725
ikev2_pld_id(struct iked *env, struct ikev2_payload *pld,
726
    struct iked_message *msg, size_t offset, size_t left, unsigned int payload)
727
23.7k
{
728
23.7k
  uint8_t       *ptr;
729
23.7k
  struct ikev2_id      id;
730
23.7k
  size_t         len;
731
23.7k
  struct iked_id      *idp, idb;
732
23.7k
  const struct iked_sa    *sa = msg->msg_sa;
733
23.7k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
734
23.7k
  char         idstr[IKED_ID_SIZE];
735
736
23.7k
  if (ikev2_validate_id(msg, offset, left, &id))
737
15.9k
    return (-1);
738
739
7.77k
  bzero(&idb, sizeof(idb));
740
741
  /* Don't strip the Id payload header */
742
7.77k
  ptr = msgbuf + offset;
743
7.77k
  len = left;
744
745
7.77k
  idb.id_type = id.id_type;
746
7.77k
  idb.id_offset = sizeof(id);
747
7.77k
  if ((idb.id_buf = ibuf_new(ptr, len)) == NULL)
748
0
    return (-1);
749
750
7.77k
  if (ikev2_print_id(&idb, idstr, sizeof(idstr)) == -1) {
751
0
    ibuf_free(idb.id_buf);
752
0
    log_debug("%s: malformed id", __func__);
753
0
    return (-1);
754
0
  }
755
756
7.77k
  log_debug("%s: id %s length %zu", __func__, idstr, len);
757
758
7.77k
  if (!ikev2_msg_frompeer(msg)) {
759
7.61k
    ibuf_free(idb.id_buf);
760
7.61k
    return (0);
761
7.61k
  }
762
763
157
  if (((sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr) ||
764
157
      (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDi)))
765
77
    idp = &msg->msg_parent->msg_peerid;
766
80
  else if (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr)
767
80
    idp = &msg->msg_parent->msg_localid;
768
0
  else {
769
0
    ibuf_free(idb.id_buf);
770
0
    log_debug("%s: unexpected id payload", __func__);
771
0
    return (0);
772
0
  }
773
774
157
  if (idp->id_type) {
775
33
    ibuf_free(idb.id_buf);
776
33
    log_debug("%s: duplicate id payload", __func__);
777
33
    return (-1);
778
33
  }
779
780
124
  idp->id_buf = idb.id_buf;
781
124
  idp->id_offset = idb.id_offset;
782
124
  idp->id_type = idb.id_type;
783
784
124
  return (0);
785
157
}
786
787
int
788
ikev2_validate_cert(struct iked_message *msg, size_t offset, size_t left,
789
    struct ikev2_cert *cert)
790
6.90k
{
791
6.90k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
792
793
6.90k
  if (left < sizeof(*cert)) {
794
1.53k
    log_debug("%s: malformed payload: too short for header "
795
1.53k
        "(%zu < %zu)", __func__, left, sizeof(*cert));
796
1.53k
    return (-1);
797
1.53k
  }
798
5.37k
  memcpy(cert, msgbuf + offset, sizeof(*cert));
799
5.37k
  if (cert->cert_type == IKEV2_CERT_NONE) {
800
1.03k
    log_debug("%s: malformed payload: invalid cert type", __func__);
801
1.03k
    return (-1);
802
1.03k
  }
803
804
4.33k
  return (0);
805
5.37k
}
806
807
int
808
ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld,
809
    struct iked_message *msg, size_t offset, size_t left)
810
6.90k
{
811
6.90k
  struct ikev2_cert    cert;
812
6.90k
  uint8_t       *buf;
813
6.90k
  size_t         len;
814
6.90k
  struct iked_id      *certid;
815
6.90k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
816
6.90k
  const struct iked_sa    *sa = msg->msg_sa;
817
6.90k
  int        i;
818
819
6.90k
  if (ikev2_validate_cert(msg, offset, left, &cert))
820
2.56k
    return (-1);
821
4.33k
  offset += sizeof(cert);
822
823
4.33k
  buf = msgbuf + offset;
824
4.33k
  len = left - sizeof(cert);
825
826
4.33k
  log_debug("%s: type %s length %zu",
827
4.33k
      __func__, print_map(cert.cert_type, ikev2_cert_map), len);
828
829
4.33k
  print_hex(buf, 0, len);
830
831
4.33k
  if (!ikev2_msg_frompeer(msg))
832
1.54k
    return (0);
833
834
  /* do not accept internal encoding in the wire */
835
2.78k
  if (cert.cert_type == IKEV2_CERT_BUNDLE) {
836
290
    log_debug("%s: ignoring IKEV2_CERT_BUNDLE",
837
290
       SPI_SA(sa, __func__));
838
290
    return (0);
839
290
  }
840
841
2.49k
  certid = &msg->msg_parent->msg_cert;
842
2.49k
  if (certid->id_type) {
843
    /* try to set supplemental certs */
844
6.88k
    for (i = 0; i < IKED_SCERT_MAX; i++) {
845
5.52k
      certid = &msg->msg_parent->msg_scert[i];
846
5.52k
      if (!certid->id_type)
847
778
        break;
848
5.52k
    }
849
2.13k
    if (certid->id_type) {
850
1.35k
      log_debug("%s: too many cert payloads, ignoring",
851
1.35k
         SPI_SA(sa, __func__));
852
1.35k
      return (0);
853
1.35k
    }
854
2.13k
  }
855
856
1.14k
  if ((certid->id_buf = ibuf_new(buf, len)) == NULL) {
857
0
    log_debug("%s: failed to save cert", __func__);
858
0
    return (-1);
859
0
  }
860
1.14k
  certid->id_type = cert.cert_type;
861
1.14k
  certid->id_offset = 0;
862
863
1.14k
  return (0);
864
1.14k
}
865
866
int
867
ikev2_validate_certreq(struct iked_message *msg, size_t offset, size_t left,
868
    struct ikev2_cert *cert)
869
15.4k
{
870
15.4k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
871
872
15.4k
  if (left < sizeof(*cert)) {
873
3.58k
    log_debug("%s: malformed payload: too short for header "
874
3.58k
        "(%zu < %zu)", __func__, left, sizeof(*cert));
875
3.58k
    return (-1);
876
3.58k
  }
877
11.8k
  memcpy(cert, msgbuf + offset, sizeof(*cert));
878
879
11.8k
  return (0);
880
15.4k
}
881
882
int
883
ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld,
884
    struct iked_message *msg, size_t offset, size_t left)
885
15.4k
{
886
15.4k
  struct ikev2_cert    cert;
887
15.4k
  struct iked_certreq   *cr;
888
15.4k
  uint8_t       *buf;
889
15.4k
  ssize_t        len;
890
15.4k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
891
892
15.4k
  if (ikev2_validate_certreq(msg, offset, left, &cert))
893
3.58k
    return (-1);
894
11.8k
  offset += sizeof(cert);
895
896
11.8k
  buf = msgbuf + offset;
897
11.8k
  len = left - sizeof(cert);
898
899
11.8k
  log_debug("%s: type %s length %zd",
900
11.8k
      __func__, print_map(cert.cert_type, ikev2_cert_map), len);
901
902
11.8k
  print_hex(buf, 0, len);
903
904
11.8k
  if (!ikev2_msg_frompeer(msg))
905
10.4k
    return (0);
906
907
1.34k
  if (cert.cert_type == IKEV2_CERT_X509_CERT) {
908
330
    if (len == 0) {
909
288
      log_info("%s: invalid length 0", __func__);
910
288
      return (0);
911
288
    }
912
42
    if ((len % SHA_DIGEST_LENGTH) != 0) {
913
9
      log_info("%s: invalid certificate request",
914
9
          __func__);
915
9
      return (-1);
916
9
    }
917
42
  }
918
919
1.04k
  if ((cr = calloc(1, sizeof(struct iked_certreq))) == NULL) {
920
0
    log_info("%s: failed to allocate certreq.", __func__);
921
0
    return (-1);
922
0
  }
923
1.04k
  if ((cr->cr_data = ibuf_new(buf, len)) == NULL) {
924
0
    log_info("%s: failed to allocate buffer.", __func__);
925
0
    free(cr);
926
0
    return (-1);
927
0
  }
928
1.04k
  cr->cr_type = cert.cert_type;
929
1.04k
  SIMPLEQ_INSERT_TAIL(&msg->msg_parent->msg_certreqs, cr, cr_entry);
930
931
1.04k
  return (0);
932
1.04k
}
933
934
int
935
ikev2_validate_auth(struct iked_message *msg, size_t offset, size_t left,
936
    struct ikev2_auth *auth)
937
10.5k
{
938
10.5k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
939
940
10.5k
  if (left < sizeof(*auth)) {
941
2.04k
    log_debug("%s: malformed payload: too short for header "
942
2.04k
        "(%zu < %zu)", __func__, left, sizeof(*auth));
943
2.04k
    return (-1);
944
2.04k
  }
945
8.50k
  memcpy(auth, msgbuf + offset, sizeof(*auth));
946
947
8.50k
  if (auth->auth_method == 0) {
948
4.72k
    log_info("%s: malformed payload: invalid auth method",
949
4.72k
        __func__);
950
4.72k
    return (-1);
951
4.72k
  }
952
953
3.78k
  return (0);
954
8.50k
}
955
956
int
957
ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld,
958
    struct iked_message *msg, size_t offset, size_t left)
959
10.5k
{
960
10.5k
  struct ikev2_auth    auth;
961
10.5k
  struct iked_id      *idp;
962
10.5k
  uint8_t       *buf;
963
10.5k
  size_t         len;
964
10.5k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
965
966
10.5k
  if (ikev2_validate_auth(msg, offset, left, &auth))
967
6.76k
    return (-1);
968
3.78k
  offset += sizeof(auth);
969
970
3.78k
  buf = msgbuf + offset;
971
3.78k
  len = left - sizeof(auth);
972
973
3.78k
  log_debug("%s: method %s length %zu",
974
3.78k
      __func__, print_map(auth.auth_method, ikev2_auth_map), len);
975
976
3.78k
  print_hex(buf, 0, len);
977
978
3.78k
  if (!ikev2_msg_frompeer(msg))
979
3.74k
    return (0);
980
981
42
  idp = &msg->msg_parent->msg_auth;
982
42
  if (idp->id_type) {
983
1
    log_debug("%s: duplicate auth payload", __func__);
984
1
    return (-1);
985
1
  }
986
987
41
  ibuf_free(idp->id_buf);
988
41
  idp->id_type = auth.auth_method;
989
41
  idp->id_offset = 0;
990
41
  if ((idp->id_buf = ibuf_new(buf, len)) == NULL)
991
0
    return (-1);
992
993
41
  return (0);
994
41
}
995
996
int
997
ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld,
998
    struct iked_message *msg, size_t offset, size_t left)
999
3.51k
{
1000
3.51k
  size_t     len;
1001
3.51k
  uint8_t   *buf;
1002
3.51k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1003
1004
3.51k
  buf = msgbuf + offset;
1005
3.51k
  len = left;
1006
1007
3.51k
  if (len == 0) {
1008
3.21k
    log_debug("%s: malformed payload: no NONCE given", __func__);
1009
3.21k
    return (-1);
1010
3.21k
  }
1011
1012
298
  print_hex(buf, 0, len);
1013
1014
298
  if (ikev2_msg_frompeer(msg)) {
1015
62
    if (msg->msg_parent->msg_nonce != NULL) {
1016
19
      log_info("%s: duplicate NONCE payload", __func__);
1017
19
      return (-1);
1018
19
    }
1019
43
    if ((msg->msg_nonce = ibuf_new(buf, len)) == NULL) {
1020
0
      log_debug("%s: failed to get peer nonce", __func__);
1021
0
      return (-1);
1022
0
    }
1023
43
    msg->msg_parent->msg_nonce = msg->msg_nonce;
1024
43
  }
1025
1026
279
  return (0);
1027
298
}
1028
1029
int
1030
ikev2_validate_notify(struct iked_message *msg, size_t offset, size_t left,
1031
    struct ikev2_notify *n)
1032
39.8k
{
1033
39.8k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1034
1035
39.8k
  if (left < sizeof(*n)) {
1036
5.32k
    log_debug("%s: malformed payload: too short for header "
1037
5.32k
        "(%zu < %zu)", __func__, left, sizeof(*n));
1038
5.32k
    return (-1);
1039
5.32k
  }
1040
34.4k
  memcpy(n, msgbuf + offset, sizeof(*n));
1041
1042
34.4k
  return (0);
1043
39.8k
}
1044
1045
int
1046
ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld,
1047
    struct iked_message *msg, size_t offset, size_t left)
1048
39.8k
{
1049
39.8k
  struct ikev2_notify  n;
1050
39.8k
  const struct iked_sa  *sa = msg->msg_sa;
1051
39.8k
  uint8_t     *buf, md[SHA_DIGEST_LENGTH];
1052
39.8k
  uint32_t     spi32;
1053
39.8k
  uint64_t     spi64;
1054
39.8k
  struct iked_spi   *rekey;
1055
39.8k
  uint16_t     type;
1056
39.8k
  uint16_t     signature_hash;
1057
1058
39.8k
  if (ikev2_validate_notify(msg, offset, left, &n))
1059
5.32k
    return (-1);
1060
34.4k
  type = betoh16(n.n_type);
1061
1062
34.4k
  log_debug("%s: protoid %s spisize %d type %s",
1063
34.4k
      __func__,
1064
34.4k
      print_map(n.n_protoid, ikev2_saproto_map), n.n_spisize,
1065
34.4k
      print_map(type, ikev2_n_map));
1066
1067
34.4k
  left -= sizeof(n);
1068
34.4k
  if ((buf = ibuf_seek(msg->msg_data, offset + sizeof(n), left)) == NULL)
1069
0
    return (-1);
1070
1071
34.4k
  print_hex(buf, 0, left);
1072
1073
34.4k
  if (!ikev2_msg_frompeer(msg))
1074
2.00k
    return (0);
1075
1076
32.4k
  switch (type) {
1077
3.34k
  case IKEV2_N_NAT_DETECTION_SOURCE_IP:
1078
26.0k
  case IKEV2_N_NAT_DETECTION_DESTINATION_IP:
1079
26.0k
    if (left != sizeof(md)) {
1080
17
      log_debug("%s: malformed payload: hash size mismatch"
1081
17
          " (%zu != %zu)", __func__, left, sizeof(md));
1082
17
      return (-1);
1083
17
    }
1084
26.0k
    if (ikev2_nat_detection(env, msg, md, sizeof(md), type,
1085
26.0k
        ikev2_msg_frompeer(msg)) == -1)
1086
0
      return (-1);
1087
26.0k
    if (memcmp(buf, md, left) != 0) {
1088
25.8k
      log_debug("%s: %s detected NAT", __func__,
1089
25.8k
          print_map(type, ikev2_n_map));
1090
25.8k
      if (type == IKEV2_N_NAT_DETECTION_SOURCE_IP)
1091
3.34k
        msg->msg_parent->msg_nat_detected
1092
3.34k
            |= IKED_MSG_NAT_SRC_IP;
1093
22.4k
      else
1094
22.4k
        msg->msg_parent->msg_nat_detected
1095
22.4k
            |= IKED_MSG_NAT_DST_IP;
1096
25.8k
    }
1097
26.0k
    print_hex(md, 0, sizeof(md));
1098
    /* remember for MOBIKE */
1099
26.0k
    msg->msg_parent->msg_natt_rcvd = 1;
1100
26.0k
    break;
1101
6
  case IKEV2_N_AUTHENTICATION_FAILED:
1102
6
    if (!msg->msg_e) {
1103
0
      log_debug("%s: AUTHENTICATION_FAILED not encrypted",
1104
0
          __func__);
1105
0
      return (-1);
1106
0
    }
1107
    /*
1108
     * If we are the responder, then we only accept
1109
     * AUTHENTICATION_FAILED from authenticated peers.
1110
     * If we are the initiator, the peer cannot be authenticated.
1111
     */
1112
6
    if (!sa->sa_hdr.sh_initiator) {
1113
6
      if (!sa_stateok(sa, IKEV2_STATE_VALID)) {
1114
6
        log_debug("%s: ignoring AUTHENTICATION_FAILED"
1115
6
            " from unauthenticated initiator",
1116
6
            __func__);
1117
6
        return (-1);
1118
6
      }
1119
6
    } else {
1120
0
      if (sa_stateok(sa, IKEV2_STATE_VALID)) {
1121
0
        log_debug("%s: ignoring AUTHENTICATION_FAILED"
1122
0
            " from authenticated responder",
1123
0
            __func__);
1124
0
        return (-1);
1125
0
      }
1126
0
    }
1127
0
    msg->msg_parent->msg_flags
1128
0
        |= IKED_MSG_FLAGS_AUTHENTICATION_FAILED;
1129
0
    break;
1130
143
  case IKEV2_N_INVALID_KE_PAYLOAD:
1131
143
    if (sa_stateok(sa, IKEV2_STATE_VALID) &&
1132
143
        !msg->msg_e) {
1133
0
      log_debug("%s: INVALID_KE_PAYLOAD not encrypted",
1134
0
          __func__);
1135
0
      return (-1);
1136
0
    }
1137
143
    if (left != sizeof(msg->msg_parent->msg_group)) {
1138
4
      log_debug("%s: malformed payload: group size mismatch"
1139
4
          " (%zu != %zu)", __func__, left,
1140
4
          sizeof(msg->msg_parent->msg_group));
1141
4
      return (-1);
1142
4
    }
1143
139
    memcpy(&msg->msg_parent->msg_group, buf, left);
1144
139
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_INVALID_KE;
1145
139
    break;
1146
273
  case IKEV2_N_NO_ADDITIONAL_SAS:
1147
273
    if (!msg->msg_e) {
1148
0
      log_debug("%s: NO_ADDITIONAL_SAS not encrypted",
1149
0
          __func__);
1150
0
      return (-1);
1151
0
    }
1152
273
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_NO_ADDITIONAL_SAS;
1153
273
    break;
1154
82
  case IKEV2_N_REKEY_SA:
1155
82
    if (!msg->msg_e) {
1156
0
      log_debug("%s: N_REKEY_SA not encrypted", __func__);
1157
0
      return (-1);
1158
0
    }
1159
82
    if (left != n.n_spisize) {
1160
5
      log_debug("%s: malformed notification", __func__);
1161
5
      return (-1);
1162
5
    }
1163
77
    rekey = &msg->msg_parent->msg_rekey;
1164
77
    if (rekey->spi != 0) {
1165
5
      log_debug("%s: rekeying of multiple SAs not supported",
1166
5
          __func__);
1167
5
      return (-1);
1168
5
    }
1169
72
    switch (n.n_spisize) {
1170
65
    case 4:
1171
65
      memcpy(&spi32, buf, left);
1172
65
      rekey->spi = betoh32(spi32);
1173
65
      break;
1174
4
    case 8:
1175
4
      memcpy(&spi64, buf, left);
1176
4
      rekey->spi = betoh64(spi64);
1177
4
      break;
1178
3
    default:
1179
3
      log_debug("%s: invalid spi size %d", __func__,
1180
3
          n.n_spisize);
1181
3
      return (-1);
1182
72
    }
1183
69
    rekey->spi_size = n.n_spisize;
1184
69
    rekey->spi_protoid = n.n_protoid;
1185
1186
69
    log_debug("%s: rekey %s spi %s", __func__,
1187
69
        print_map(n.n_protoid, ikev2_saproto_map),
1188
69
        print_spi(rekey->spi, n.n_spisize));
1189
69
    break;
1190
354
  case IKEV2_N_TEMPORARY_FAILURE:
1191
354
    if (!msg->msg_e) {
1192
0
      log_debug("%s: IKEV2_N_TEMPORARY_FAILURE not encrypted",
1193
0
          __func__);
1194
0
      return (-1);
1195
0
    }
1196
354
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_TEMPORARY_FAILURE;
1197
354
    break;
1198
255
  case IKEV2_N_IPCOMP_SUPPORTED:
1199
255
    if (!msg->msg_e) {
1200
0
      log_debug("%s: N_IPCOMP_SUPPORTED not encrypted",
1201
0
          __func__);
1202
0
      return (-1);
1203
0
    }
1204
255
    if (left < sizeof(msg->msg_parent->msg_cpi) +
1205
255
        sizeof(msg->msg_parent->msg_transform)) {
1206
127
      log_debug("%s: ignoring malformed ipcomp notification",
1207
127
          __func__);
1208
127
      return (0);
1209
127
    }
1210
128
    memcpy(&msg->msg_parent->msg_cpi, buf,
1211
128
        sizeof(msg->msg_parent->msg_cpi));
1212
128
    memcpy(&msg->msg_parent->msg_transform,
1213
128
        buf + sizeof(msg->msg_parent->msg_cpi),
1214
128
        sizeof(msg->msg_parent->msg_transform));
1215
1216
128
    log_debug("%s: %s cpi 0x%x, transform %s, length %zu", __func__,
1217
128
        msg->msg_parent->msg_response ? "res" : "req",
1218
128
        betoh16(msg->msg_parent->msg_cpi),
1219
128
        print_map(msg->msg_parent->msg_transform,
1220
128
        ikev2_ipcomp_map), left);
1221
1222
128
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_IPCOMP_SUPPORTED;
1223
128
    break;
1224
73
  case IKEV2_N_CHILD_SA_NOT_FOUND:
1225
73
    if (!msg->msg_e) {
1226
0
      log_debug("%s: N_CHILD_SA_NOT_FOUND not encrypted",
1227
0
          __func__);
1228
0
      return (-1);
1229
0
    }
1230
73
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_CHILD_SA_NOT_FOUND;
1231
73
    break;
1232
36
  case IKEV2_N_NO_PROPOSAL_CHOSEN:
1233
36
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN;
1234
36
    break;
1235
1.81k
  case IKEV2_N_MOBIKE_SUPPORTED:
1236
1.81k
    if (!msg->msg_e) {
1237
0
      log_debug("%s: N_MOBIKE_SUPPORTED not encrypted",
1238
0
          __func__);
1239
0
      return (-1);
1240
0
    }
1241
1.81k
    if (left != 0) {
1242
1.65k
      log_debug("%s: ignoring malformed mobike"
1243
1.65k
          " notification: %zu", __func__, left);
1244
1.65k
      return (0);
1245
1.65k
    }
1246
159
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_MOBIKE;
1247
159
    break;
1248
356
  case IKEV2_N_USE_TRANSPORT_MODE:
1249
356
    if (!msg->msg_e) {
1250
0
      log_debug("%s: N_USE_TRANSPORT_MODE not encrypted",
1251
0
          __func__);
1252
0
      return (-1);
1253
0
    }
1254
356
    if (left != 0) {
1255
77
      log_debug("%s: ignoring malformed transport mode"
1256
77
          " notification: %zu", __func__, left);
1257
77
      return (0);
1258
77
    }
1259
279
    if (msg->msg_parent->msg_response) {
1260
0
      if (!(msg->msg_policy->pol_flags & IKED_POLICY_TRANSPORT)) {
1261
0
        log_debug("%s: ignoring transport mode"
1262
0
            " notification (policy)", __func__);
1263
0
        return (0);
1264
0
      }
1265
0
    }
1266
279
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_USE_TRANSPORT;
1267
279
    break;
1268
388
  case IKEV2_N_UPDATE_SA_ADDRESSES:
1269
388
    if (!msg->msg_e) {
1270
0
      log_debug("%s: N_UPDATE_SA_ADDRESSES not encrypted",
1271
0
          __func__);
1272
0
      return (-1);
1273
0
    }
1274
388
    if (!sa->sa_mobike) {
1275
388
      log_debug("%s: ignoring update sa addresses"
1276
388
          " notification w/o mobike: %zu", __func__, left);
1277
388
      return (0);
1278
388
    }
1279
0
    if (left != 0) {
1280
0
      log_debug("%s: ignoring malformed update sa addresses"
1281
0
          " notification: %zu", __func__, left);
1282
0
      return (0);
1283
0
    }
1284
0
    msg->msg_parent->msg_update_sa_addresses = 1;
1285
0
    break;
1286
242
  case IKEV2_N_COOKIE2:
1287
242
    if (!msg->msg_e) {
1288
0
      log_debug("%s: N_COOKIE2 not encrypted",
1289
0
          __func__);
1290
0
      return (-1);
1291
0
    }
1292
242
    if (!sa->sa_mobike) {
1293
242
      log_debug("%s: ignoring cookie2 notification"
1294
242
          " w/o mobike: %zu", __func__, left);
1295
242
      return (0);
1296
242
    }
1297
0
    if (left < IKED_COOKIE2_MIN || left > IKED_COOKIE2_MAX) {
1298
0
      log_debug("%s: ignoring malformed cookie2"
1299
0
          " notification: %zu", __func__, left);
1300
0
      return (0);
1301
0
    }
1302
0
    ibuf_free(msg->msg_cookie2);  /* should not happen */
1303
0
    if ((msg->msg_cookie2 = ibuf_new(buf, left)) == NULL) {
1304
0
      log_debug("%s: failed to get peer cookie2", __func__);
1305
0
      return (-1);
1306
0
    }
1307
0
    msg->msg_parent->msg_cookie2 = msg->msg_cookie2;
1308
0
    break;
1309
2
  case IKEV2_N_COOKIE:
1310
2
    if (msg->msg_e) {
1311
2
      log_debug("%s: N_COOKIE encrypted",
1312
2
          __func__);
1313
2
      return (-1);
1314
2
    }
1315
0
    if (left < IKED_COOKIE_MIN || left > IKED_COOKIE_MAX) {
1316
0
      log_debug("%s: ignoring malformed cookie"
1317
0
          " notification: %zu", __func__, left);
1318
0
      return (0);
1319
0
    }
1320
0
    log_debug("%s: received cookie, len %zu", __func__, left);
1321
0
    print_hex(buf, 0, left);
1322
1323
0
    ibuf_free(msg->msg_cookie);
1324
0
    if ((msg->msg_cookie = ibuf_new(buf, left)) == NULL) {
1325
0
      log_debug("%s: failed to get peer cookie", __func__);
1326
0
      return (-1);
1327
0
    }
1328
0
    msg->msg_parent->msg_cookie = msg->msg_cookie;
1329
0
    break;
1330
14
  case IKEV2_N_FRAGMENTATION_SUPPORTED:
1331
14
    if (msg->msg_e) {
1332
14
      log_debug("%s: N_FRAGMENTATION_SUPPORTED encrypted",
1333
14
          __func__);
1334
14
      return (-1);
1335
14
    }
1336
0
    if (left != 0) {
1337
0
      log_debug("%s: ignoring malformed fragmentation"
1338
0
          " notification: %zu", __func__, left);
1339
0
      return (0);
1340
0
    }
1341
0
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_FRAGMENTATION;
1342
0
    break;
1343
7
  case IKEV2_N_SIGNATURE_HASH_ALGORITHMS:
1344
7
    if (msg->msg_e) {
1345
7
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: encrypted",
1346
7
          __func__);
1347
7
      return (-1);
1348
7
    }
1349
0
    if (sa == NULL) {
1350
0
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: no SA",
1351
0
          __func__);
1352
0
      return (-1);
1353
0
    }
1354
0
    if (sa->sa_sigsha2) {
1355
0
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: "
1356
0
          "duplicate notify", __func__);
1357
0
      return (0);
1358
0
    }
1359
0
    if (left < sizeof(signature_hash) ||
1360
0
        left % sizeof(signature_hash)) {
1361
0
      log_debug("%s: malformed signature hash notification"
1362
0
          "(%zu bytes)", __func__, left);
1363
0
      return (0);
1364
0
    }
1365
0
    while (left >= sizeof(signature_hash)) {
1366
0
      memcpy(&signature_hash, buf, sizeof(signature_hash));
1367
0
      signature_hash = betoh16(signature_hash);
1368
0
      log_debug("%s: signature hash %s (%x)", __func__,
1369
0
          print_map(signature_hash, ikev2_sighash_map),
1370
0
          signature_hash);
1371
0
      left -= sizeof(signature_hash);
1372
0
      buf += sizeof(signature_hash);
1373
0
      if (signature_hash == IKEV2_SIGHASH_SHA2_256)
1374
0
        msg->msg_parent->msg_flags
1375
0
            |= IKED_MSG_FLAGS_SIGSHA2;
1376
0
    }
1377
0
    break;
1378
32.4k
  }
1379
1380
29.9k
  return (0);
1381
32.4k
}
1382
1383
int
1384
ikev2_validate_delete(struct iked_message *msg, size_t offset, size_t left,
1385
    struct ikev2_delete *del)
1386
7.54k
{
1387
7.54k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1388
1389
7.54k
  if (left < sizeof(*del)) {
1390
1.53k
    log_debug("%s: malformed payload: too short for header "
1391
1.53k
        "(%zu < %zu)", __func__, left, sizeof(*del));
1392
1.53k
    return (-1);
1393
1.53k
  }
1394
6.01k
  memcpy(del, msgbuf + offset, sizeof(*del));
1395
1396
6.01k
  if (del->del_protoid == 0) {
1397
84
    log_info("%s: malformed payload: invalid protoid", __func__);
1398
84
    return (-1);
1399
84
  }
1400
1401
5.92k
  return (0);
1402
6.01k
}
1403
1404
int
1405
ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld,
1406
    struct iked_message *msg, size_t offset, size_t left)
1407
7.54k
{
1408
7.54k
  struct ikev2_delete  del;
1409
7.54k
  uint8_t     *buf, *msgbuf = ibuf_data(msg->msg_data);
1410
7.54k
  size_t       cnt, sz, len;
1411
1412
7.54k
  if (ikev2_validate_delete(msg, offset, left, &del))
1413
1.62k
    return (-1);
1414
1415
  /* Skip if it's a response, then we don't have to deal with it */
1416
5.92k
  if (ikev2_msg_frompeer(msg) &&
1417
5.92k
      msg->msg_parent->msg_response)
1418
0
    return (0);
1419
1420
5.92k
  cnt = betoh16(del.del_nspi);
1421
5.92k
  sz = del.del_spisize;
1422
1423
5.92k
  log_debug("%s: proto %s spisize %zu nspi %zu",
1424
5.92k
      __func__, print_map(del.del_protoid, ikev2_saproto_map),
1425
5.92k
      sz, cnt);
1426
1427
5.92k
  if (msg->msg_parent->msg_del_protoid) {
1428
5.54k
    log_debug("%s: duplicate delete payload", __func__);
1429
5.54k
    return (0);
1430
5.54k
  }
1431
1432
380
  msg->msg_parent->msg_del_protoid = del.del_protoid;
1433
380
  msg->msg_parent->msg_del_cnt = cnt;
1434
380
  msg->msg_parent->msg_del_spisize = sz;
1435
1436
380
  buf = msgbuf + offset + sizeof(del);
1437
380
  len = left - sizeof(del);
1438
380
  if (len == 0 || sz == 0 || cnt == 0)
1439
357
    return (0);
1440
1441
23
  if ((len / sz) != cnt) {
1442
21
    log_debug("%s: invalid payload length %zu/%zu != %zu",
1443
21
        __func__, len, sz, cnt);
1444
21
    return (-1);
1445
21
  }
1446
1447
2
  print_hex(buf, 0, len);
1448
1449
2
  msg->msg_parent->msg_del_buf = ibuf_new(buf, len);
1450
1451
2
  return (0);
1452
23
}
1453
1454
int
1455
ikev2_validate_tss(struct iked_message *msg, size_t offset, size_t left,
1456
    struct ikev2_tsp *tsp)
1457
23.0k
{
1458
23.0k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1459
1460
23.0k
  if (left < sizeof(*tsp)) {
1461
2.69k
    log_debug("%s: malformed payload: too short for header "
1462
2.69k
        "(%zu < %zu)", __func__, left, sizeof(*tsp));
1463
2.69k
    return (-1);
1464
2.69k
  }
1465
20.4k
  memcpy(tsp, msgbuf + offset, sizeof(*tsp));
1466
1467
20.4k
  return (0);
1468
23.0k
}
1469
1470
int
1471
ikev2_pld_tss(struct iked *env, struct ikev2_payload *pld,
1472
    struct iked_message *msg, size_t offset, size_t left)
1473
23.0k
{
1474
23.0k
  struct ikev2_tsp     tsp;
1475
23.0k
  struct ikev2_ts      ts;
1476
23.0k
  size_t         ts_len, i;
1477
1478
23.0k
  if (ikev2_validate_tss(msg, offset, left, &tsp))
1479
2.69k
    return (-1);
1480
1481
20.4k
  offset += sizeof(tsp);
1482
20.4k
  left -= sizeof(tsp);
1483
1484
20.4k
  log_debug("%s: count %d length %zu", __func__,
1485
20.4k
      tsp.tsp_count, left);
1486
1487
40.3k
  for (i = 0; i < tsp.tsp_count; i++) {
1488
38.6k
    if (ikev2_validate_ts(msg, offset, left, &ts))
1489
15.9k
      return (-1);
1490
1491
22.6k
    log_debug("%s: type %s protoid %u length %d "
1492
22.6k
        "startport %u endport %u", __func__,
1493
22.6k
        print_map(ts.ts_type, ikev2_ts_map),
1494
22.6k
        ts.ts_protoid, betoh16(ts.ts_length),
1495
22.6k
        betoh16(ts.ts_startport),
1496
22.6k
        betoh16(ts.ts_endport));
1497
1498
22.6k
    offset += sizeof(ts);
1499
22.6k
    left -= sizeof(ts);
1500
1501
22.6k
    ts_len = betoh16(ts.ts_length) - sizeof(ts);
1502
22.6k
    if (ikev2_pld_ts(env, pld, msg, offset, ts_len, ts.ts_type))
1503
2.71k
      return (-1);
1504
1505
19.9k
    offset += ts_len;
1506
19.9k
    left -= ts_len;
1507
19.9k
  }
1508
1509
1.70k
  return (0);
1510
20.4k
}
1511
1512
int
1513
ikev2_validate_ts(struct iked_message *msg, size_t offset, size_t left,
1514
    struct ikev2_ts *ts)
1515
38.6k
{
1516
38.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1517
38.6k
  size_t     ts_length;
1518
1519
38.6k
  if (left < sizeof(*ts)) {
1520
14.4k
    log_debug("%s: malformed payload: too short for header "
1521
14.4k
        "(%zu < %zu)", __func__, left, sizeof(*ts));
1522
14.4k
    return (-1);
1523
14.4k
  }
1524
24.1k
  memcpy(ts, msgbuf + offset, sizeof(*ts));
1525
1526
24.1k
  ts_length = betoh16(ts->ts_length);
1527
24.1k
  if (ts_length < sizeof(*ts)) {
1528
349
    log_debug("%s: malformed payload: shorter than minimum header "
1529
349
        "size (%zu < %zu)", __func__, ts_length, sizeof(*ts));
1530
349
    return (-1);
1531
349
  }
1532
23.8k
  if (left < ts_length) {
1533
1.21k
    log_debug("%s: malformed payload: too long for payload size "
1534
1.21k
        "(%zu < %zu)", __func__, left, ts_length);
1535
1.21k
    return (-1);
1536
1.21k
  }
1537
1538
22.6k
  return (0);
1539
23.8k
}
1540
1541
int
1542
ikev2_pld_ts(struct iked *env, struct ikev2_payload *pld,
1543
    struct iked_message *msg, size_t offset, size_t left, unsigned int type)
1544
22.6k
{
1545
22.6k
  struct sockaddr_in     start4, end4;
1546
22.6k
  struct sockaddr_in6    start6, end6;
1547
22.6k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
1548
22.6k
  uint8_t       *ptr;
1549
1550
22.6k
  ptr = msgbuf + offset;
1551
1552
22.6k
  switch (type) {
1553
9.66k
  case IKEV2_TS_IPV4_ADDR_RANGE:
1554
9.66k
    if (left < 2 * 4) {
1555
1.16k
      log_debug("%s: malformed payload: too short "
1556
1.16k
          "for ipv4 addr range (%zu < %u)",
1557
1.16k
          __func__, left, 2 * 4);
1558
1.16k
      return (-1);
1559
1.16k
    }
1560
1561
8.50k
    bzero(&start4, sizeof(start4));
1562
8.50k
    start4.sin_family = AF_INET;
1563
#ifdef HAVE_SOCKADDR_SA_LEN
1564
    start4.sin_len = sizeof(start4);
1565
#endif
1566
8.50k
    memcpy(&start4.sin_addr.s_addr, ptr, 4);
1567
8.50k
    ptr += 4;
1568
8.50k
    left -= 4;
1569
1570
8.50k
    bzero(&end4, sizeof(end4));
1571
8.50k
    end4.sin_family = AF_INET;
1572
#ifdef HAVE_SOCKADDR_SA_LEN
1573
    end4.sin_len = sizeof(end4);
1574
#endif
1575
8.50k
    memcpy(&end4.sin_addr.s_addr, ptr, 4);
1576
8.50k
    left -= 4;
1577
1578
8.50k
    log_debug("%s: start %s end %s", __func__,
1579
8.50k
        print_addr(&start4), print_addr(&end4));
1580
8.50k
    break;
1581
1.54k
  case IKEV2_TS_IPV6_ADDR_RANGE:
1582
1.54k
    if (left < 2 * 16) {
1583
252
      log_debug("%s: malformed payload: too short "
1584
252
          "for ipv6 addr range (%zu < %u)",
1585
252
          __func__, left, 2 * 16);
1586
252
      return (-1);
1587
252
    }
1588
1.29k
    bzero(&start6, sizeof(start6));
1589
1.29k
    start6.sin6_family = AF_INET6;
1590
#ifdef HAVE_SOCKADDR_SA_LEN
1591
    start6.sin6_len = sizeof(start6);
1592
#endif
1593
1.29k
    memcpy(&start6.sin6_addr, ptr, 16);
1594
1.29k
    ptr += 16;
1595
1.29k
    left -= 16;
1596
1597
1.29k
    bzero(&end6, sizeof(end6));
1598
1.29k
    end6.sin6_family = AF_INET6;
1599
#ifdef HAVE_SOCKADDR_SA_LEN
1600
    end6.sin6_len = sizeof(end6);
1601
#endif
1602
1.29k
    memcpy(&end6.sin6_addr, ptr, 16);
1603
1.29k
    left -= 16;
1604
1605
1.29k
    log_debug("%s: start %s end %s", __func__,
1606
1.29k
        print_addr(&start6), print_addr(&end6));
1607
1.29k
    break;
1608
11.4k
  default:
1609
11.4k
    log_debug("%s: ignoring unknown TS type %u", __func__, type);
1610
11.4k
    return (0);
1611
22.6k
  }
1612
1613
9.79k
  if (left > 0) {
1614
1.30k
    log_debug("%s: malformed payload: left (%zu) > 0",
1615
1.30k
        __func__, left);
1616
1.30k
    return (-1);
1617
1.30k
  }
1618
1619
8.49k
  return (0);
1620
9.79k
}
1621
1622
int
1623
ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
1624
    struct iked_message *msg, size_t offset, size_t left)
1625
0
{
1626
0
  struct iked_sa      *sa = msg->msg_sa;
1627
0
  struct iked_frag    *sa_frag = &sa->sa_fragments;
1628
0
  struct iked_frag_entry    *el;
1629
0
  struct ikev2_frag_payload  frag;
1630
0
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
1631
0
  uint8_t       *buf;
1632
0
  struct ibuf     *e = NULL;
1633
0
  size_t         frag_num, frag_total;
1634
0
  size_t         len;
1635
0
  int        ret = -1;
1636
0
  int        processed = 0;
1637
0
  ssize_t        elen;
1638
1639
0
  buf = msgbuf + offset;
1640
0
  memcpy(&frag, buf, sizeof(frag));
1641
0
  frag_num = betoh16(frag.frag_num);
1642
0
  frag_total = betoh16(frag.frag_total);
1643
1644
0
  offset += sizeof(frag);
1645
0
  buf = msgbuf + offset;
1646
0
  len = left - sizeof(frag);
1647
1648
0
  ikestat_inc(env, ikes_frag_rcvd);
1649
1650
  /* Limit number of total fragments to avoid DOS */
1651
0
  if (frag_total > IKED_FRAG_TOTAL_MAX ) {
1652
0
    log_debug("%s: Total Fragments too big  %zu",
1653
0
        __func__, frag_total);
1654
0
    goto dropall;
1655
0
  }
1656
1657
  /* Check sanity of fragment header */
1658
0
  if (frag_num == 0 || frag_total == 0) {
1659
0
    log_debug("%s: Malformed fragment received: %zu of %zu",
1660
0
        __func__, frag_num, frag_total);
1661
0
    goto done;
1662
0
  }
1663
0
  log_debug("%s: Received fragment: %zu of %zu",
1664
0
      __func__, frag_num, frag_total);
1665
1666
  /* Drop fragment if frag_num and frag_total don't match */
1667
0
  if (frag_num > frag_total)
1668
0
    goto done;
1669
1670
  /* Decrypt fragment */
1671
0
  if ((e = ibuf_new(buf, len)) == NULL)
1672
0
    goto done;
1673
1674
0
  if ((e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e))
1675
0
      == NULL ) {
1676
0
    log_debug("%s: Failed to decrypt fragment: %zu of %zu",
1677
0
        __func__, frag_num, frag_total);
1678
0
    goto done;
1679
0
  }
1680
0
  elen = ibuf_size(e);
1681
1682
  /* Check new fragmented message */
1683
0
  if (sa_frag->frag_arr == NULL) {
1684
0
    sa_frag->frag_arr = recallocarray(NULL, 0, frag_total,
1685
0
        sizeof(struct iked_frag_entry*));
1686
0
    if (sa_frag->frag_arr == NULL) {
1687
0
      log_info("%s: recallocarray sa_frag->frag_arr.", __func__);
1688
0
      goto done;
1689
0
    }
1690
0
    sa_frag->frag_total = frag_total;
1691
0
  } else {
1692
    /* Drop all fragments if frag_total doesn't match previous */
1693
0
    if (frag_total != sa_frag->frag_total)
1694
0
      goto dropall;
1695
1696
    /* Silent drop if fragment already stored */
1697
0
    if (sa_frag->frag_arr[frag_num-1] != NULL)
1698
0
      goto done;
1699
0
  }
1700
1701
  /* The first fragments IKE header determines pld_nextpayload */
1702
0
  if (frag_num == 1)
1703
0
    sa_frag->frag_nextpayload = pld->pld_nextpayload;
1704
1705
  /* Insert new list element */
1706
0
  el = calloc(1, sizeof(struct iked_frag_entry));
1707
0
  if (el == NULL) {
1708
0
    log_info("%s: Failed allocating new fragment: %zu of %zu",
1709
0
        __func__, frag_num, frag_total);
1710
0
    goto done;
1711
0
  }
1712
1713
0
  sa_frag->frag_arr[frag_num-1] = el;
1714
0
  el->frag_size = elen;
1715
0
  el->frag_data = calloc(1, elen);
1716
0
  if (el->frag_data == NULL) {
1717
0
    log_debug("%s: Failed allocating new fragment data: %zu of %zu",
1718
0
        __func__, frag_num, frag_total);
1719
0
    goto done;
1720
0
  }
1721
1722
  /* Copy plaintext to fragment */
1723
0
  memcpy(el->frag_data, ibuf_seek(e, 0, 0), elen);
1724
0
  sa_frag->frag_total_size += elen;
1725
0
  sa_frag->frag_count++;
1726
1727
  /* If all frags are received start reassembly */
1728
0
  if (sa_frag->frag_count == sa_frag->frag_total) {
1729
0
    log_debug("%s: All fragments received: %zu of %zu",
1730
0
        __func__, frag_num, frag_total);
1731
0
    ret = ikev2_frags_reassemble(env, pld, msg);
1732
0
  } else {
1733
0
    ret = 0;
1734
0
  }
1735
0
  processed = 1;
1736
1737
0
done:
1738
0
  if (!processed)
1739
0
    ikestat_inc(env, ikes_frag_rcvd_drop);
1740
0
  ibuf_free(e);
1741
0
  return (ret);
1742
0
dropall:
1743
0
  ikestat_add(env, ikes_frag_rcvd_drop, sa_frag->frag_count + 1);
1744
0
  config_free_fragments(sa_frag);
1745
0
  ibuf_free(e);
1746
0
  return -1;
1747
0
}
1748
1749
int
1750
ikev2_frags_reassemble(struct iked *env, struct ikev2_payload *pld,
1751
    struct iked_message *msg)
1752
0
{
1753
0
  struct iked_frag    *sa_frag = &msg->msg_sa->sa_fragments;
1754
0
  struct ibuf     *e = NULL;
1755
0
  struct iked_frag_entry    *el;
1756
0
  uint8_t       *ptr;
1757
0
  size_t         offset;
1758
0
  size_t         i;
1759
0
  struct iked_message    emsg;
1760
0
  int        ret = -1;
1761
0
  int        processed = 0;
1762
1763
  /* Reassemble fragments to single buffer */
1764
0
  if ((e = ibuf_new(NULL, sa_frag->frag_total_size)) == NULL) {
1765
0
    log_debug("%s: Failed allocating SK buffer.", __func__);
1766
0
    goto done;
1767
0
  }
1768
1769
  /* Empty queue to new buffer */
1770
0
  offset = 0;
1771
0
  for (i = 0; i < sa_frag->frag_total; i++) {
1772
0
    if ((el = sa_frag->frag_arr[i]) == NULL)
1773
0
      fatalx("Tried to reassemble shallow frag_arr");
1774
0
    ptr = ibuf_seek(e, offset, el->frag_size);
1775
0
    if (ptr == NULL) {
1776
0
      log_info("%s: failed to reassemble fragments", __func__);
1777
0
      goto done;
1778
0
    }
1779
0
    memcpy(ptr, el->frag_data, el->frag_size);
1780
0
    offset += el->frag_size;
1781
0
  }
1782
1783
0
  log_debug("%s: Defragmented length %zd", __func__,
1784
0
      sa_frag->frag_total_size);
1785
0
  print_hex(ibuf_data(e), 0,  sa_frag->frag_total_size);
1786
1787
  /* Drop the original request's packets from the retransmit queue */
1788
0
  if (msg->msg_response)
1789
0
    ikev2_msg_dispose(env, &msg->msg_sa->sa_requests,
1790
0
        ikev2_msg_lookup(env, &msg->msg_sa->sa_requests, msg,
1791
0
        msg->msg_exchange));
1792
1793
  /*
1794
   * Parse decrypted payload
1795
   */
1796
0
  bzero(&emsg, sizeof(emsg));
1797
0
  memcpy(&emsg, msg, sizeof(*msg));
1798
0
  emsg.msg_data = e;
1799
0
  emsg.msg_e = 1;
1800
0
  emsg.msg_parent = msg;
1801
0
  TAILQ_INIT(&emsg.msg_proposals);
1802
1803
0
  ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
1804
0
      sa_frag->frag_nextpayload);
1805
0
  processed = 1;
1806
0
done:
1807
0
  if (processed)
1808
0
    ikestat_add(env, ikes_frag_reass_ok, sa_frag->frag_total);
1809
0
  else
1810
0
    ikestat_add(env, ikes_frag_reass_drop, sa_frag->frag_total);
1811
0
  config_free_fragments(sa_frag);
1812
0
  ibuf_free(e);
1813
1814
0
  return (ret);
1815
0
}
1816
1817
int
1818
ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
1819
    struct iked_message *msg, size_t offset, size_t left)
1820
0
{
1821
0
  struct iked_sa    *sa = msg->msg_sa;
1822
0
  struct ibuf   *e = NULL;
1823
0
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
1824
0
  struct iked_message  emsg;
1825
0
  uint8_t     *buf;
1826
0
  size_t       len;
1827
0
  int      ret = -1;
1828
1829
0
  if (sa->sa_fragments.frag_arr != NULL) {
1830
0
    log_warn("%s: Received SK payload when SKFs are in queue.",
1831
0
        __func__);
1832
0
    config_free_fragments(&sa->sa_fragments);
1833
0
    return (ret);
1834
0
  }
1835
1836
0
  buf = msgbuf + offset;
1837
0
  len = left;
1838
1839
0
  if ((e = ibuf_new(buf, len)) == NULL)
1840
0
    goto done;
1841
1842
0
  if (ikev2_msg_frompeer(msg)) {
1843
0
    e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
1844
0
  } else {
1845
0
    sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
1846
0
    e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
1847
0
    sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
1848
0
  }
1849
1850
0
  if (e == NULL)
1851
0
    goto done;
1852
1853
  /*
1854
   * Parse decrypted payload
1855
   */
1856
0
  bzero(&emsg, sizeof(emsg));
1857
0
  memcpy(&emsg, msg, sizeof(*msg));
1858
0
  emsg.msg_data = e;
1859
0
  emsg.msg_e = 1;
1860
0
  emsg.msg_parent = msg;
1861
0
  TAILQ_INIT(&emsg.msg_proposals);
1862
1863
0
  ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
1864
0
      pld->pld_nextpayload);
1865
1866
0
 done:
1867
0
  ibuf_free(e);
1868
1869
0
  return (ret);
1870
0
}
1871
1872
int
1873
ikev2_validate_cp(struct iked_message *msg, size_t offset, size_t left,
1874
    struct ikev2_cp *cp)
1875
11.6k
{
1876
11.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1877
1878
11.6k
  if (left < sizeof(*cp)) {
1879
3.58k
    log_debug("%s: malformed payload: too short for header "
1880
3.58k
        "(%zu < %zu)", __func__, left, sizeof(*cp));
1881
3.58k
    return (-1);
1882
3.58k
  }
1883
8.11k
  memcpy(cp, msgbuf + offset, sizeof(*cp));
1884
1885
8.11k
  return (0);
1886
11.6k
}
1887
1888
int
1889
ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld,
1890
    struct iked_message *msg, size_t offset, size_t left)
1891
11.6k
{
1892
11.6k
  struct ikev2_cp    cp;
1893
11.6k
  struct ikev2_cfg  *cfg;
1894
11.6k
  struct iked_addr  *addr;
1895
11.6k
  struct sockaddr_in  *in4;
1896
11.6k
  struct sockaddr_in6 *in6;
1897
11.6k
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
1898
11.6k
  uint8_t     *ptr;
1899
11.6k
  size_t       len;
1900
11.6k
  int      cfg_type;
1901
1902
11.6k
  if (ikev2_validate_cp(msg, offset, left, &cp))
1903
3.58k
    return (-1);
1904
1905
8.11k
  ptr = msgbuf + offset + sizeof(cp);
1906
8.11k
  len = left - sizeof(cp);
1907
1908
8.11k
  log_debug("%s: type %s length %zu",
1909
8.11k
      __func__, print_map(cp.cp_type, ikev2_cp_map), len);
1910
8.11k
  print_hex(ptr, 0, len);
1911
1912
16.4k
  while (len > 0) {
1913
10.1k
    if (len < sizeof(*cfg)) {
1914
367
      log_debug("%s: malformed payload: too short for cfg "
1915
367
          "(%zu < %zu)", __func__, len, sizeof(*cfg));
1916
367
      return (-1);
1917
367
    }
1918
9.74k
    cfg = (struct ikev2_cfg *)ptr;
1919
1920
9.74k
    log_debug("%s: %s 0x%04x length %d", __func__,
1921
9.74k
        print_map(betoh16(cfg->cfg_type), ikev2_cfg_map),
1922
9.74k
        betoh16(cfg->cfg_type),
1923
9.74k
        betoh16(cfg->cfg_length));
1924
1925
9.74k
    ptr += sizeof(*cfg);
1926
9.74k
    len -= sizeof(*cfg);
1927
1928
9.74k
    if (len < betoh16(cfg->cfg_length)) {
1929
1.42k
      log_debug("%s: malformed payload: too short for "
1930
1.42k
          "cfg_length (%zu < %u)", __func__, len,
1931
1.42k
          betoh16(cfg->cfg_length));
1932
1.42k
      return (-1);
1933
1.42k
    }
1934
1935
8.32k
    print_hex(ptr, sizeof(*cfg), betoh16(cfg->cfg_length));
1936
1937
8.32k
    cfg_type = betoh16(cfg->cfg_type);
1938
8.32k
    switch (cfg_type) {
1939
848
    case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1940
1.51k
    case IKEV2_CFG_INTERNAL_IP4_DNS:
1941
1.51k
      if (!ikev2_msg_frompeer(msg))
1942
741
        break;
1943
777
      if (betoh16(cfg->cfg_length) == 0)
1944
309
        break;
1945
      /* XXX multiple-valued */
1946
468
      if (betoh16(cfg->cfg_length) < 4) {
1947
6
        log_debug("%s: malformed payload: too short "
1948
6
            "for ipv4 addr (%u < %u)",
1949
6
            __func__, betoh16(cfg->cfg_length), 4);
1950
6
        return (-1);
1951
6
      }
1952
462
      switch(cfg_type) {
1953
359
      case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1954
359
        if (msg->msg_parent->msg_cp_addr != NULL) {
1955
240
          log_debug("%s: address already set", __func__);
1956
240
          goto skip;
1957
240
        }
1958
119
        break;
1959
119
      case IKEV2_CFG_INTERNAL_IP4_DNS:
1960
103
        if (msg->msg_parent->msg_cp_dns != NULL) {
1961
53
          log_debug("%s: dns already set", __func__);
1962
53
          goto skip;
1963
53
        }
1964
50
        break;
1965
50
      default:
1966
0
        break;
1967
462
      }
1968
169
      if ((addr = calloc(1, sizeof(*addr))) == NULL) {
1969
0
        log_debug("%s: malloc failed", __func__);
1970
0
        break;
1971
0
      }
1972
169
      addr->addr_af = AF_INET;
1973
169
      in4 = (struct sockaddr_in *)&addr->addr;
1974
169
      in4->sin_family = AF_INET;
1975
#ifdef HAVE_SOCKADDR_SA_LEN
1976
      in4->sin_len = sizeof(*in4);
1977
#endif
1978
169
      memcpy(&in4->sin_addr.s_addr, ptr, 4);
1979
169
      switch(cfg_type) {
1980
119
      case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1981
119
        msg->msg_parent->msg_cp_addr = addr;
1982
119
        log_debug("%s: IP4_ADDRESS %s", __func__,
1983
119
            print_addr(&addr->addr));
1984
119
        break;
1985
50
      case IKEV2_CFG_INTERNAL_IP4_DNS:
1986
50
        msg->msg_parent->msg_cp_dns = addr;
1987
50
        log_debug("%s: IP4_DNS %s", __func__,
1988
50
            print_addr(&addr->addr));
1989
50
        break;
1990
0
      default:
1991
0
        log_debug("%s: cfg %s", __func__,
1992
0
            print_addr(&addr->addr));
1993
0
        break;
1994
169
      }
1995
169
      break;
1996
2.28k
    case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
1997
3.13k
    case IKEV2_CFG_INTERNAL_IP6_DNS:
1998
3.13k
      if (!ikev2_msg_frompeer(msg))
1999
2.90k
        break;
2000
230
      if (betoh16(cfg->cfg_length) == 0)
2001
94
        break;
2002
      /* XXX multiple-valued */
2003
136
      if (betoh16(cfg->cfg_length) < 16) {
2004
5
        log_debug("%s: malformed payload: too short "
2005
5
            "for ipv6 addr w/prefixlen (%u < %u)",
2006
5
            __func__, betoh16(cfg->cfg_length), 16);
2007
5
        return (-1);
2008
5
      }
2009
131
      switch(cfg_type) {
2010
89
      case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
2011
89
        if (msg->msg_parent->msg_cp_addr6 != NULL) {
2012
47
          log_debug("%s: address6 already set", __func__);
2013
47
          goto skip;
2014
47
        }
2015
42
        break;
2016
42
      case IKEV2_CFG_INTERNAL_IP6_DNS:
2017
42
        if (msg->msg_parent->msg_cp_dns != NULL) {
2018
36
          log_debug("%s: dns already set", __func__);
2019
36
          goto skip;
2020
36
        }
2021
6
        break;
2022
131
      }
2023
48
      if ((addr = calloc(1, sizeof(*addr))) == NULL) {
2024
0
        log_debug("%s: malloc failed", __func__);
2025
0
        break;
2026
0
      }
2027
48
      addr->addr_af = AF_INET6;
2028
48
      in6 = (struct sockaddr_in6 *)&addr->addr;
2029
48
      in6->sin6_family = AF_INET6;
2030
#ifdef HAVE_SOCKADDR_SA_LEN
2031
      in6->sin6_len = sizeof(*in6);
2032
#endif
2033
48
      memcpy(&in6->sin6_addr, ptr, 16);
2034
48
      switch(cfg_type) {
2035
42
      case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
2036
42
        msg->msg_parent->msg_cp_addr6 = addr;
2037
42
        log_debug("%s: IP6_ADDRESS %s", __func__,
2038
42
            print_addr(&addr->addr));
2039
42
        break;
2040
6
      case IKEV2_CFG_INTERNAL_IP6_DNS:
2041
6
        msg->msg_parent->msg_cp_dns = addr;
2042
6
        log_debug("%s: IP6_DNS %s", __func__,
2043
6
            print_addr(&addr->addr));
2044
6
        break;
2045
0
      default:
2046
0
        log_debug("%s: cfg %s/%d", __func__,
2047
0
            print_addr(&addr->addr), ptr[16]);
2048
0
        break;
2049
48
      }
2050
48
      break;
2051
8.32k
    }
2052
2053
8.31k
 skip:
2054
8.31k
    ptr += betoh16(cfg->cfg_length);
2055
8.31k
    len -= betoh16(cfg->cfg_length);
2056
8.31k
  }
2057
2058
6.31k
  if (!ikev2_msg_frompeer(msg))
2059
6.10k
    return (0);
2060
2061
207
  msg->msg_parent->msg_cp = cp.cp_type;
2062
2063
207
  return (0);
2064
6.31k
}
2065
2066
int
2067
ikev2_validate_eap(struct iked_message *msg, size_t offset, size_t left,
2068
    struct eap_header *hdr)
2069
21.2k
{
2070
21.2k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
2071
2072
21.2k
  if (left < sizeof(*hdr)) {
2073
9.30k
    log_debug("%s: malformed payload: too short for header "
2074
9.30k
        "(%zu < %zu)", __func__, left, sizeof(*hdr));
2075
9.30k
    return (-1);
2076
9.30k
  }
2077
11.9k
  memcpy(hdr, msgbuf + offset, sizeof(*hdr));
2078
2079
11.9k
  return (0);
2080
21.2k
}
2081
2082
int
2083
ikev2_pld_eap(struct iked *env, struct ikev2_payload *pld,
2084
    struct iked_message *msg, size_t offset, size_t left)
2085
21.2k
{
2086
21.2k
  struct eap_header    hdr;
2087
21.2k
  struct eap_message    *eap = NULL;
2088
21.2k
  const struct iked_sa    *sa = msg->msg_sa;
2089
21.2k
  size_t         len;
2090
2091
21.2k
  if (ikev2_validate_eap(msg, offset, left, &hdr))
2092
9.30k
    return (-1);
2093
11.9k
  len = betoh16(hdr.eap_length);
2094
2095
11.9k
  if (len < sizeof(*eap)) {
2096
3.88k
    log_info("%s: %s id %d length %d", SPI_SA(sa, __func__),
2097
3.88k
        print_map(hdr.eap_code, eap_code_map),
2098
3.88k
        hdr.eap_id, betoh16(hdr.eap_length));
2099
8.07k
  } else {
2100
    /* Now try to get the indicated length */
2101
8.07k
    if ((eap = ibuf_seek(msg->msg_data, offset, len)) == NULL) {
2102
4.20k
      log_debug("%s: invalid EAP length", __func__);
2103
4.20k
      return (-1);
2104
4.20k
    }
2105
2106
3.86k
    log_info("%s: %s id %d length %d EAP-%s", SPI_SA(sa, __func__),
2107
3.86k
        print_map(eap->eap_code, eap_code_map),
2108
3.86k
        eap->eap_id, betoh16(eap->eap_length),
2109
3.86k
        print_map(eap->eap_type, eap_type_map));
2110
2111
3.86k
    if (eap_parse(env, sa, msg, eap, msg->msg_response) == -1)
2112
0
      return (-1);
2113
3.86k
    msg->msg_parent->msg_eap.eam_found = 1;
2114
3.86k
  }
2115
2116
7.75k
  return (0);
2117
11.9k
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/ikev2_pld.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: ikev2_pld.c,v 1.133 2023/09/02 18:36:30 tobhe Exp $ */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 * Copyright (c) 2014 Hans-Joerg Hoexer
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 */
20
21
#include <sys/queue.h>
22
#include <sys/socket.h>
23
#include <sys/uio.h>
24
25
#include <netinet/in.h>
26
#include <arpa/inet.h>
27
28
#include <stdlib.h>
29
#include <stdio.h>
30
#include <unistd.h>
31
#include <string.h>
32
#include <signal.h>
33
#include <endian.h>
34
#include <errno.h>
35
#include <err.h>
36
#include <event.h>
37
38
#include <openssl/sha.h>
39
#include <openssl/evp.h>
40
41
#include "iked.h"
42
#include "ikev2.h"
43
#include "eap.h"
44
#include "dh.h"
45
46
int  ikev2_validate_pld(struct iked_message *, size_t, size_t,
47
      struct ikev2_payload *);
48
int  ikev2_pld_payloads(struct iked *, struct iked_message *,
49
      size_t, size_t, unsigned int);
50
int  ikev2_validate_sa(struct iked_message *, size_t, size_t,
51
      struct ikev2_sa_proposal *);
52
int  ikev2_pld_sa(struct iked *, struct ikev2_payload *,
53
      struct iked_message *, size_t, size_t);
54
int  ikev2_validate_xform(struct iked_message *, size_t, size_t,
55
      struct ikev2_transform *);
56
int  ikev2_pld_xform(struct iked *, struct iked_message *,
57
      size_t, size_t);
58
int  ikev2_validate_attr(struct iked_message *, size_t, size_t,
59
      struct ikev2_attribute *);
60
int  ikev2_pld_attr(struct iked *, struct ikev2_transform *,
61
      struct iked_message *, size_t, size_t);
62
int  ikev2_validate_ke(struct iked_message *, size_t, size_t,
63
      struct ikev2_keyexchange *);
64
int  ikev2_pld_ke(struct iked *, struct ikev2_payload *,
65
      struct iked_message *, size_t, size_t);
66
int  ikev2_validate_id(struct iked_message *, size_t, size_t,
67
      struct ikev2_id *);
68
int  ikev2_pld_id(struct iked *, struct ikev2_payload *,
69
      struct iked_message *, size_t, size_t, unsigned int);
70
int  ikev2_validate_cert(struct iked_message *, size_t, size_t,
71
      struct ikev2_cert *);
72
int  ikev2_pld_cert(struct iked *, struct ikev2_payload *,
73
      struct iked_message *, size_t, size_t);
74
int  ikev2_validate_certreq(struct iked_message *, size_t, size_t,
75
      struct ikev2_cert *);
76
int  ikev2_pld_certreq(struct iked *, struct ikev2_payload *,
77
      struct iked_message *, size_t, size_t);
78
int  ikev2_pld_nonce(struct iked *, struct ikev2_payload *,
79
      struct iked_message *, size_t, size_t);
80
int  ikev2_validate_notify(struct iked_message *, size_t, size_t,
81
      struct ikev2_notify *);
82
int  ikev2_pld_notify(struct iked *, struct ikev2_payload *,
83
      struct iked_message *, size_t, size_t);
84
int  ikev2_validate_delete(struct iked_message *, size_t, size_t,
85
      struct ikev2_delete *);
86
int  ikev2_pld_delete(struct iked *, struct ikev2_payload *,
87
      struct iked_message *, size_t, size_t);
88
int  ikev2_validate_tss(struct iked_message *, size_t, size_t,
89
      struct ikev2_tsp *);
90
int  ikev2_pld_tss(struct iked *, struct ikev2_payload *,
91
      struct iked_message *, size_t, size_t);
92
int  ikev2_validate_ts(struct iked_message *, size_t, size_t,
93
      struct ikev2_ts *);
94
int  ikev2_pld_ts(struct iked *, struct ikev2_payload *,
95
      struct iked_message *, size_t, size_t, unsigned int);
96
int  ikev2_validate_auth(struct iked_message *, size_t, size_t,
97
      struct ikev2_auth *);
98
int  ikev2_pld_auth(struct iked *, struct ikev2_payload *,
99
      struct iked_message *, size_t, size_t);
100
int  ikev2_pld_e(struct iked *, struct ikev2_payload *,
101
      struct iked_message *, size_t, size_t);
102
int  ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
103
      struct iked_message *msg, size_t offset, size_t left);
104
int  ikev2_frags_reassemble(struct iked *env,
105
      struct ikev2_payload *pld, struct iked_message *msg);
106
int  ikev2_validate_cp(struct iked_message *, size_t, size_t,
107
      struct ikev2_cp *);
108
int  ikev2_pld_cp(struct iked *, struct ikev2_payload *,
109
      struct iked_message *, size_t, size_t);
110
int  ikev2_validate_eap(struct iked_message *, size_t, size_t,
111
      struct eap_header *);
112
int  ikev2_pld_eap(struct iked *, struct ikev2_payload *,
113
      struct iked_message *, size_t, size_t);
114
115
int
116
ikev2_pld_parse(struct iked *env, struct ike_header *hdr,
117
    struct iked_message *msg, size_t offset)
118
15.4k
{
119
15.4k
  log_debug("%s: header ispi %s rspi %s"
120
15.4k
      " nextpayload %s version 0x%02x exchange %s flags 0x%02x"
121
15.4k
      " msgid %d length %u response %d", __func__,
122
15.4k
      print_spi(betoh64(hdr->ike_ispi), 8),
123
15.4k
      print_spi(betoh64(hdr->ike_rspi), 8),
124
15.4k
      print_map(hdr->ike_nextpayload, ikev2_payload_map),
125
15.4k
      hdr->ike_version,
126
15.4k
      print_map(hdr->ike_exchange, ikev2_exchange_map),
127
15.4k
      hdr->ike_flags,
128
15.4k
      betoh32(hdr->ike_msgid),
129
15.4k
      betoh32(hdr->ike_length),
130
15.4k
      msg->msg_response);
131
132
15.4k
  if (ibuf_size(msg->msg_data) < betoh32(hdr->ike_length)) {
133
6
    log_debug("%s: short message", __func__);
134
6
    return (-1);
135
6
  }
136
137
15.4k
  offset += sizeof(*hdr);
138
139
15.4k
  return (ikev2_pld_payloads(env, msg, offset,
140
15.4k
      betoh32(hdr->ike_length), hdr->ike_nextpayload));
141
15.4k
}
142
143
int
144
ikev2_validate_pld(struct iked_message *msg, size_t offset, size_t left,
145
    struct ikev2_payload *pld)
146
291k
{
147
291k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
148
291k
  size_t     pld_length;
149
150
  /* We need at least the generic header. */
151
291k
  if (left < sizeof(*pld)) {
152
2.01k
    log_debug("%s: malformed payload: too short for generic "
153
2.01k
        "header (%zu < %zu)", __func__, left, sizeof(*pld));
154
2.01k
    return (-1);
155
2.01k
  }
156
289k
  memcpy(pld, msgbuf + offset, sizeof(*pld));
157
158
  /*
159
   * We need at least the specified number of bytes.
160
   * pld_length is the full size of the payload including
161
   * the generic payload header.
162
   */
163
289k
  pld_length = betoh16(pld->pld_length);
164
289k
  if (left < pld_length) {
165
6.81k
    log_debug("%s: malformed payload: shorter than specified "
166
6.81k
        "(%zu < %zu)", __func__, left, pld_length);
167
6.81k
    return (-1);
168
6.81k
  }
169
  /*
170
   * Sanity check the specified payload size, it must
171
   * be at least the size of the generic payload header.
172
   */
173
282k
  if (pld_length < sizeof(*pld)) {
174
2.83k
    log_debug("%s: malformed payload: shorter than minimum "
175
2.83k
        "header size (%zu < %zu)", __func__, pld_length,
176
2.83k
        sizeof(*pld));
177
2.83k
    return (-1);
178
2.83k
  }
179
180
279k
  return (0);
181
282k
}
182
183
int
184
ikev2_pld_payloads(struct iked *env, struct iked_message *msg,
185
    size_t offset, size_t length, unsigned int payload)
186
15.4k
{
187
15.4k
  struct ikev2_payload   pld;
188
15.4k
  unsigned int     e;
189
15.4k
  int      ret;
190
15.4k
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
191
15.4k
  size_t       total, left;
192
193
  /* Check if message was decrypted in an E payload */
194
15.4k
  e = msg->msg_e ? IKED_E : 0;
195
196
  /* Bytes left in datagram. */
197
15.4k
  total = length - offset;
198
199
294k
  while (payload != 0 && offset < length) {
200
291k
    if (ikev2_validate_pld(msg, offset, total, &pld))
201
11.6k
      return (-1);
202
203
279k
    log_debug("%s: %spayload %s"
204
279k
        " nextpayload %s critical 0x%02x length %d",
205
279k
        __func__, e ? "decrypted " : "",
206
279k
        print_map(payload, ikev2_payload_map),
207
279k
        print_map(pld.pld_nextpayload, ikev2_payload_map),
208
279k
        pld.pld_reserved & IKEV2_CRITICAL_PAYLOAD,
209
279k
        betoh16(pld.pld_length));
210
211
    /* Skip over generic payload header. */
212
279k
    offset += sizeof(pld);
213
279k
    total -= sizeof(pld);
214
279k
    left = betoh16(pld.pld_length) - sizeof(pld);
215
279k
    ret = 0;
216
217
279k
    switch (payload | e) {
218
0
    case IKEV2_PAYLOAD_SA:
219
32.7k
    case IKEV2_PAYLOAD_SA | IKED_E:
220
32.7k
      ret = ikev2_pld_sa(env, &pld, msg, offset, left);
221
32.7k
      break;
222
0
    case IKEV2_PAYLOAD_KE:
223
10.9k
    case IKEV2_PAYLOAD_KE | IKED_E:
224
10.9k
      ret = ikev2_pld_ke(env, &pld, msg, offset, left);
225
10.9k
      break;
226
13.9k
    case IKEV2_PAYLOAD_IDi | IKED_E:
227
23.7k
    case IKEV2_PAYLOAD_IDr | IKED_E:
228
23.7k
      ret = ikev2_pld_id(env, &pld, msg, offset, left,
229
23.7k
          payload);
230
23.7k
      break;
231
6.90k
    case IKEV2_PAYLOAD_CERT | IKED_E:
232
6.90k
      ret = ikev2_pld_cert(env, &pld, msg, offset, left);
233
6.90k
      break;
234
0
    case IKEV2_PAYLOAD_CERTREQ:
235
15.4k
    case IKEV2_PAYLOAD_CERTREQ | IKED_E:
236
15.4k
      ret = ikev2_pld_certreq(env, &pld, msg, offset, left);
237
15.4k
      break;
238
10.5k
    case IKEV2_PAYLOAD_AUTH | IKED_E:
239
10.5k
      ret = ikev2_pld_auth(env, &pld, msg, offset, left);
240
10.5k
      break;
241
0
    case IKEV2_PAYLOAD_NONCE:
242
3.51k
    case IKEV2_PAYLOAD_NONCE | IKED_E:
243
3.51k
      ret = ikev2_pld_nonce(env, &pld, msg, offset, left);
244
3.51k
      break;
245
0
    case IKEV2_PAYLOAD_NOTIFY:
246
39.8k
    case IKEV2_PAYLOAD_NOTIFY | IKED_E:
247
39.8k
      ret = ikev2_pld_notify(env, &pld, msg, offset, left);
248
39.8k
      break;
249
7.54k
    case IKEV2_PAYLOAD_DELETE | IKED_E:
250
7.54k
      ret = ikev2_pld_delete(env, &pld, msg, offset, left);
251
7.54k
      break;
252
5.65k
    case IKEV2_PAYLOAD_TSi | IKED_E:
253
23.0k
    case IKEV2_PAYLOAD_TSr | IKED_E:
254
23.0k
      ret = ikev2_pld_tss(env, &pld, msg, offset, left);
255
23.0k
      break;
256
0
    case IKEV2_PAYLOAD_SK:
257
0
      ret = ikev2_pld_e(env, &pld, msg, offset, left);
258
0
      break;
259
0
    case IKEV2_PAYLOAD_SKF:
260
0
      ret = ikev2_pld_ef(env, &pld, msg, offset, left);
261
0
      break;
262
11.6k
    case IKEV2_PAYLOAD_CP | IKED_E:
263
11.6k
      ret = ikev2_pld_cp(env, &pld, msg, offset, left);
264
11.6k
      break;
265
21.2k
    case IKEV2_PAYLOAD_EAP | IKED_E:
266
21.2k
      ret = ikev2_pld_eap(env, &pld, msg, offset, left);
267
21.2k
      break;
268
72.4k
    default:
269
72.4k
      print_hex(msgbuf, offset,
270
72.4k
          betoh16(pld.pld_length) - sizeof(pld));
271
72.4k
      break;
272
279k
    }
273
274
279k
    if (ret != 0 && ikev2_msg_frompeer(msg)) {
275
748
      (void)ikev2_send_informational(env, msg);
276
748
      return (-1);
277
748
    }
278
279
    /* Encrypted payloads must appear last */
280
278k
    if ((payload == IKEV2_PAYLOAD_SK) ||
281
278k
        (payload == IKEV2_PAYLOAD_SKF))
282
4
      return (0);
283
284
278k
    payload = pld.pld_nextpayload;
285
278k
    offset += left;
286
278k
    total -= left;
287
278k
  }
288
289
3.06k
  return (0);
290
15.4k
}
291
292
int
293
ikev2_validate_sa(struct iked_message *msg, size_t offset, size_t left,
294
    struct ikev2_sa_proposal *sap)
295
37.6k
{
296
37.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
297
37.6k
  size_t     sap_length;
298
299
37.6k
  if (left < sizeof(*sap)) {
300
15.9k
    log_debug("%s: malformed payload: too short for header "
301
15.9k
        "(%zu < %zu)", __func__, left, sizeof(*sap));
302
15.9k
    return (-1);
303
15.9k
  }
304
21.6k
  memcpy(sap, msgbuf + offset, sizeof(*sap));
305
306
21.6k
  sap_length = betoh16(sap->sap_length);
307
21.6k
  if (sap_length < sizeof(*sap)) {
308
5.62k
    log_debug("%s: malformed payload: shorter than minimum header "
309
5.62k
        "size (%zu < %zu)", __func__, sap_length, sizeof(*sap));
310
5.62k
    return (-1);
311
5.62k
  }
312
16.0k
  if (left < sap_length) {
313
3.10k
    log_debug("%s: malformed payload: too long for actual payload "
314
3.10k
        "size (%zu < %zu)", __func__, left, sap_length);
315
3.10k
    return (-1);
316
3.10k
  }
317
  /*
318
   * If there is only one proposal, sap_length must be the
319
   * total payload size.
320
   */
321
12.9k
  if (!sap->sap_more && left != sap_length) {
322
30
    log_debug("%s: malformed payload: SA payload length mismatches "
323
30
        "single proposal substructure length (%zu != %zu)",
324
30
        __func__, left, sap_length);
325
30
    return (-1);
326
30
  }
327
  /*
328
   * If there are more than one proposal, there must be bytes
329
   * left in the payload.
330
   */
331
12.9k
  if (sap->sap_more && left <= sap_length) {
332
1.00k
    log_debug("%s: malformed payload: SA payload too small for "
333
1.00k
        "further proposals (%zu <= %zu)", __func__,
334
1.00k
        left, sap_length);
335
1.00k
    return (-1);
336
1.00k
  }
337
11.9k
  return (0);
338
12.9k
}
339
340
int
341
ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld,
342
    struct iked_message *msg, size_t offset, size_t left)
343
32.7k
{
344
32.7k
  struct ikev2_sa_proposal   sap;
345
32.7k
  struct iked_proposal    *prop = NULL;
346
32.7k
  uint32_t       spi32;
347
32.7k
  uint64_t       spi = 0, spi64;
348
32.7k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
349
32.7k
  int        r;
350
32.7k
  struct iked_proposals   *props;
351
32.7k
  size_t         total;
352
353
37.6k
  do {
354
37.6k
    if (ikev2_validate_sa(msg, offset, left, &sap))
355
25.6k
      return (-1);
356
357
    /* Assumed size of the first proposals, including SPI if present. */
358
11.9k
    total = (betoh16(sap.sap_length) - sizeof(sap));
359
360
11.9k
    props = &msg->msg_parent->msg_proposals;
361
362
11.9k
    offset += sizeof(sap);
363
11.9k
    left -= sizeof(sap);
364
365
11.9k
    if (sap.sap_spisize) {
366
1.66k
      if (left < sap.sap_spisize) {
367
758
        log_debug("%s: malformed payload: SPI larger than "
368
758
            "actual payload (%zu < %d)", __func__, left,
369
758
            sap.sap_spisize);
370
758
        return (-1);
371
758
      }
372
905
      if (total < sap.sap_spisize) {
373
183
        log_debug("%s: malformed payload: SPI larger than "
374
183
            "proposal (%zu < %d)", __func__, total,
375
183
            sap.sap_spisize);
376
183
        return (-1);
377
183
      }
378
722
      switch (sap.sap_spisize) {
379
356
      case 4:
380
356
        memcpy(&spi32, msgbuf + offset, 4);
381
356
        spi = betoh32(spi32);
382
356
        break;
383
236
      case 8:
384
236
        memcpy(&spi64, msgbuf + offset, 8);
385
236
        spi = betoh64(spi64);
386
236
        break;
387
130
      default:
388
130
        log_debug("%s: unsupported SPI size %d",
389
130
            __func__, sap.sap_spisize);
390
130
        return (-1);
391
722
      }
392
393
592
      offset += sap.sap_spisize;
394
592
      left -= sap.sap_spisize;
395
396
      /* Assumed size of the proposal, now without SPI. */
397
592
      total -= sap.sap_spisize;
398
592
    }
399
400
    /*
401
     * As we verified sanity of packet headers, this check will
402
     * be always false, but just to be sure we keep it.
403
     */
404
10.8k
    if (left < total) {
405
0
      log_debug("%s: malformed payload: too long for payload "
406
0
          "(%zu < %zu)", __func__, left, total);
407
0
      return (-1);
408
0
    }
409
410
10.8k
    log_debug("%s: more %d reserved %d length %d"
411
10.8k
        " proposal #%d protoid %s spisize %d xforms %d spi %s",
412
10.8k
        __func__, sap.sap_more, sap.sap_reserved,
413
10.8k
        betoh16(sap.sap_length), sap.sap_proposalnr,
414
10.8k
        print_map(sap.sap_protoid, ikev2_saproto_map), sap.sap_spisize,
415
10.8k
        sap.sap_transforms, print_spi(spi, sap.sap_spisize));
416
417
10.8k
    if (ikev2_msg_frompeer(msg)) {
418
69
      if ((msg->msg_parent->msg_prop = config_add_proposal(props,
419
69
          sap.sap_proposalnr, sap.sap_protoid)) == NULL) {
420
69
        log_debug("%s: invalid proposal", __func__);
421
69
        return (-1);
422
69
      }
423
0
      prop = msg->msg_parent->msg_prop;
424
0
      prop->prop_peerspi.spi = spi;
425
0
      prop->prop_peerspi.spi_protoid = sap.sap_protoid;
426
0
      prop->prop_peerspi.spi_size = sap.sap_spisize;
427
428
0
      prop->prop_localspi.spi_protoid = sap.sap_protoid;
429
0
      prop->prop_localspi.spi_size = sap.sap_spisize;
430
0
    }
431
432
    /*
433
     * Parse the attached transforms
434
     */
435
10.7k
    if (sap.sap_transforms) {
436
6.27k
      r = ikev2_pld_xform(env, msg, offset, total);
437
6.27k
      if ((r == -2) && ikev2_msg_frompeer(msg)) {
438
0
        log_debug("%s: invalid proposal transform",
439
0
            __func__);
440
441
        /* cleanup and ignore proposal */
442
0
        config_free_proposal(props, prop);
443
0
        prop = msg->msg_parent->msg_prop = NULL;
444
6.27k
      } else if (r != 0) {
445
5.04k
        log_debug("%s: invalid proposal transforms",
446
5.04k
            __func__);
447
5.04k
        return (-1);
448
5.04k
      }
449
6.27k
    }
450
451
5.74k
    offset += total;
452
5.74k
    left -= total;
453
5.74k
  } while (sap.sap_more);
454
455
846
  return (0);
456
32.7k
}
457
458
int
459
ikev2_validate_xform(struct iked_message *msg, size_t offset, size_t total,
460
    struct ikev2_transform *xfrm)
461
8.43k
{
462
8.43k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
463
8.43k
  size_t     xfrm_length;
464
465
8.43k
  if (total < sizeof(*xfrm)) {
466
772
    log_debug("%s: malformed payload: too short for header "
467
772
        "(%zu < %zu)", __func__, total, sizeof(*xfrm));
468
772
    return (-1);
469
772
  }
470
7.66k
  memcpy(xfrm, msgbuf + offset, sizeof(*xfrm));
471
472
7.66k
  xfrm_length = betoh16(xfrm->xfrm_length);
473
7.66k
  if (xfrm_length < sizeof(*xfrm)) {
474
1.14k
    log_debug("%s: malformed payload: shorter than minimum header "
475
1.14k
        "size (%zu < %zu)", __func__, xfrm_length, sizeof(*xfrm));
476
1.14k
    return (-1);
477
1.14k
  }
478
6.51k
  if (total < xfrm_length) {
479
706
    log_debug("%s: malformed payload: too long for payload size "
480
706
        "(%zu < %zu)", __func__, total, xfrm_length);
481
706
    return (-1);
482
706
  }
483
484
5.81k
  return (0);
485
6.51k
}
486
487
int
488
ikev2_pld_xform(struct iked *env, struct iked_message *msg,
489
    size_t offset, size_t total)
490
8.43k
{
491
8.43k
  struct ikev2_transform     xfrm;
492
8.43k
  char         id[BUFSIZ];
493
8.43k
  int        ret = 0;
494
8.43k
  int        r;
495
8.43k
  size_t         xfrm_length;
496
497
8.43k
  if (ikev2_validate_xform(msg, offset, total, &xfrm))
498
2.62k
    return (-1);
499
500
5.81k
  xfrm_length = betoh16(xfrm.xfrm_length);
501
502
5.81k
  switch (xfrm.xfrm_type) {
503
1.27k
  case IKEV2_XFORMTYPE_ENCR:
504
1.27k
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
505
1.27k
        ikev2_xformencr_map), sizeof(id));
506
1.27k
    break;
507
789
  case IKEV2_XFORMTYPE_PRF:
508
789
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
509
789
        ikev2_xformprf_map), sizeof(id));
510
789
    break;
511
174
  case IKEV2_XFORMTYPE_INTEGR:
512
174
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
513
174
        ikev2_xformauth_map), sizeof(id));
514
174
    break;
515
861
  case IKEV2_XFORMTYPE_DH:
516
861
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
517
861
        ikev2_xformdh_map), sizeof(id));
518
861
    break;
519
1.01k
  case IKEV2_XFORMTYPE_ESN:
520
1.01k
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),
521
1.01k
        ikev2_xformesn_map), sizeof(id));
522
1.01k
    break;
523
1.69k
  default:
524
1.69k
    snprintf(id, sizeof(id), "<%d>", betoh16(xfrm.xfrm_id));
525
1.69k
    break;
526
5.81k
  }
527
528
5.81k
  log_debug("%s: more %d reserved %d length %zu"
529
5.81k
      " type %s id %s",
530
5.81k
      __func__, xfrm.xfrm_more, xfrm.xfrm_reserved, xfrm_length,
531
5.81k
      print_map(xfrm.xfrm_type, ikev2_xformtype_map), id);
532
533
  /*
534
   * Parse transform attributes, if available
535
   */
536
5.81k
  msg->msg_attrlength = 0;
537
5.81k
  if (xfrm_length > sizeof(xfrm)) {
538
2.77k
    if (ikev2_pld_attr(env, &xfrm, msg, offset + sizeof(xfrm),
539
2.77k
        xfrm_length - sizeof(xfrm)) != 0) {
540
2.17k
      return (-1);
541
2.17k
    }
542
2.77k
  }
543
544
3.63k
  if (ikev2_msg_frompeer(msg)) {
545
0
    r = config_add_transform(msg->msg_parent->msg_prop,
546
0
        xfrm.xfrm_type, betoh16(xfrm.xfrm_id),
547
0
        msg->msg_attrlength, msg->msg_attrlength);
548
0
    if (r == -1) {
549
0
      log_debug("%s: failed to add transform: alloc error",
550
0
          __func__);
551
0
      return (r);
552
0
    } else if (r == -2) {
553
0
      log_debug("%s: failed to add transform: unknown type",
554
0
          __func__);
555
0
      return (r);
556
0
    }
557
0
  }
558
559
  /* Next transform */
560
3.63k
  offset += xfrm_length;
561
3.63k
  total -= xfrm_length;
562
3.63k
  if (xfrm.xfrm_more == IKEV2_XFORM_MORE)
563
2.16k
    ret = ikev2_pld_xform(env, msg, offset, total);
564
1.46k
  else if (total != 0) {
565
    /* No more transforms but still some data left. */
566
245
    log_debug("%s: less data than specified, %zu bytes left",
567
245
        __func__, total);
568
245
    ret = -1;
569
245
  }
570
571
3.63k
  return (ret);
572
3.63k
}
573
574
int
575
ikev2_validate_attr(struct iked_message *msg, size_t offset, size_t total,
576
    struct ikev2_attribute *attr)
577
53.6k
{
578
53.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
579
580
53.6k
  if (total < sizeof(*attr)) {
581
1.04k
    log_debug("%s: malformed payload: too short for header "
582
1.04k
        "(%zu < %zu)", __func__, total, sizeof(*attr));
583
1.04k
    return (-1);
584
1.04k
  }
585
52.6k
  memcpy(attr, msgbuf + offset, sizeof(*attr));
586
587
52.6k
  return (0);
588
53.6k
}
589
590
int
591
ikev2_pld_attr(struct iked *env, struct ikev2_transform *xfrm,
592
    struct iked_message *msg, size_t offset, size_t total)
593
53.6k
{
594
53.6k
  struct ikev2_attribute     attr;
595
53.6k
  unsigned int       type;
596
53.6k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
597
53.6k
  int        ret = 0;
598
53.6k
  size_t         attr_length;
599
600
53.6k
  if (ikev2_validate_attr(msg, offset, total, &attr))
601
1.04k
    return (-1);
602
603
52.6k
  type = betoh16(attr.attr_type) & ~IKEV2_ATTRAF_TV;
604
605
52.6k
  log_debug("%s: attribute type %s length %d total %zu",
606
52.6k
      __func__, print_map(type, ikev2_attrtype_map),
607
52.6k
      betoh16(attr.attr_length), total);
608
609
52.6k
  if (betoh16(attr.attr_type) & IKEV2_ATTRAF_TV) {
610
    /* Type-Value attribute */
611
41.9k
    offset += sizeof(attr);
612
41.9k
    total -= sizeof(attr);
613
614
41.9k
    if (type == IKEV2_ATTRTYPE_KEY_LENGTH)
615
48
      msg->msg_attrlength = betoh16(attr.attr_length);
616
41.9k
  } else {
617
    /* Type-Length-Value attribute */
618
10.7k
    attr_length = betoh16(attr.attr_length);
619
10.7k
    if (attr_length < sizeof(attr)) {
620
605
      log_debug("%s: malformed payload: shorter than "
621
605
          "minimum header size (%zu < %zu)", __func__,
622
605
          attr_length, sizeof(attr));
623
605
      return (-1);
624
605
    }
625
10.1k
    if (total < attr_length) {
626
529
      log_debug("%s: malformed payload: attribute larger "
627
529
          "than actual payload (%zu < %zu)", __func__,
628
529
          total, attr_length);
629
529
      return (-1);
630
529
    }
631
9.57k
    print_hex(msgbuf, offset + sizeof(attr),
632
9.57k
        attr_length - sizeof(attr));
633
9.57k
    offset += attr_length;
634
9.57k
    total -= attr_length;
635
9.57k
  }
636
637
51.4k
  if (total > 0) {
638
    /* Next attribute */
639
50.9k
    ret = ikev2_pld_attr(env, xfrm, msg, offset, total);
640
50.9k
  }
641
642
51.4k
  return (ret);
643
52.6k
}
644
645
int
646
ikev2_validate_ke(struct iked_message *msg, size_t offset, size_t left,
647
    struct ikev2_keyexchange *kex)
648
10.9k
{
649
10.9k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
650
651
10.9k
  if (left < sizeof(*kex)) {
652
6.72k
    log_debug("%s: malformed payload: too short for header "
653
6.72k
        "(%zu < %zu)", __func__, left, sizeof(*kex));
654
6.72k
    return (-1);
655
6.72k
  }
656
4.22k
  memcpy(kex, msgbuf + offset, sizeof(*kex));
657
658
4.22k
  return (0);
659
10.9k
}
660
661
int
662
ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld,
663
    struct iked_message *msg, size_t offset, size_t left)
664
10.9k
{
665
10.9k
  struct ikev2_keyexchange   kex;
666
10.9k
  uint8_t       *buf;
667
10.9k
  size_t         len;
668
10.9k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
669
670
10.9k
  if (ikev2_validate_ke(msg, offset, left, &kex))
671
6.72k
    return (-1);
672
673
4.22k
  log_debug("%s: dh group %s reserved %d", __func__,
674
4.22k
      print_map(betoh16(kex.kex_dhgroup), ikev2_xformdh_map),
675
4.22k
      betoh16(kex.kex_reserved));
676
677
4.22k
  buf = msgbuf + offset + sizeof(kex);
678
4.22k
  len = left - sizeof(kex);
679
680
4.22k
  if (len == 0) {
681
2.08k
    log_debug("%s: malformed payload: no KE data given", __func__);
682
2.08k
    return (-1);
683
2.08k
  }
684
685
2.14k
  print_hex(buf, 0, len);
686
687
2.14k
  if (ikev2_msg_frompeer(msg)) {
688
27
    if (msg->msg_parent->msg_ke != NULL) {
689
4
      log_info("%s: duplicate KE payload", __func__);
690
4
      return (-1);
691
4
    }
692
23
    if ((msg->msg_parent->msg_ke = ibuf_new(buf, len)) == NULL) {
693
0
      log_debug("%s: failed to get exchange", __func__);
694
0
      return (-1);
695
0
    }
696
23
    msg->msg_parent->msg_dhgroup = betoh16(kex.kex_dhgroup);
697
23
  }
698
699
2.13k
  return (0);
700
2.14k
}
701
702
int
703
ikev2_validate_id(struct iked_message *msg, size_t offset, size_t left,
704
    struct ikev2_id *id)
705
23.7k
{
706
23.7k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
707
708
23.7k
  if (left < sizeof(*id)) {
709
9.33k
    log_debug("%s: malformed payload: too short for header "
710
9.33k
        "(%zu < %zu)", __func__, left, sizeof(*id));
711
9.33k
    return (-1);
712
9.33k
  }
713
14.3k
  memcpy(id, msgbuf + offset, sizeof(*id));
714
715
14.3k
  if (id->id_type == IKEV2_ID_NONE) {
716
6.62k
    log_debug("%s: malformed payload: invalid ID type.",
717
6.62k
        __func__);
718
6.62k
    return (-1);
719
6.62k
  }
720
721
7.77k
  return (0);
722
14.3k
}
723
724
int
725
ikev2_pld_id(struct iked *env, struct ikev2_payload *pld,
726
    struct iked_message *msg, size_t offset, size_t left, unsigned int payload)
727
23.7k
{
728
23.7k
  uint8_t       *ptr;
729
23.7k
  struct ikev2_id      id;
730
23.7k
  size_t         len;
731
23.7k
  struct iked_id      *idp, idb;
732
23.7k
  const struct iked_sa    *sa = msg->msg_sa;
733
23.7k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
734
23.7k
  char         idstr[IKED_ID_SIZE];
735
736
23.7k
  if (ikev2_validate_id(msg, offset, left, &id))
737
15.9k
    return (-1);
738
739
7.77k
  bzero(&idb, sizeof(idb));
740
741
  /* Don't strip the Id payload header */
742
7.77k
  ptr = msgbuf + offset;
743
7.77k
  len = left;
744
745
7.77k
  idb.id_type = id.id_type;
746
7.77k
  idb.id_offset = sizeof(id);
747
7.77k
  if ((idb.id_buf = ibuf_new(ptr, len)) == NULL)
748
0
    return (-1);
749
750
7.77k
  if (ikev2_print_id(&idb, idstr, sizeof(idstr)) == -1) {
751
0
    ibuf_free(idb.id_buf);
752
0
    log_debug("%s: malformed id", __func__);
753
0
    return (-1);
754
0
  }
755
756
7.77k
  log_debug("%s: id %s length %zu", __func__, idstr, len);
757
758
7.77k
  if (!ikev2_msg_frompeer(msg)) {
759
7.61k
    ibuf_free(idb.id_buf);
760
7.61k
    return (0);
761
7.61k
  }
762
763
157
  if (((sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr) ||
764
157
      (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDi)))
765
77
    idp = &msg->msg_parent->msg_peerid;
766
80
  else if (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr)
767
80
    idp = &msg->msg_parent->msg_localid;
768
0
  else {
769
0
    ibuf_free(idb.id_buf);
770
0
    log_debug("%s: unexpected id payload", __func__);
771
0
    return (0);
772
0
  }
773
774
157
  if (idp->id_type) {
775
33
    ibuf_free(idb.id_buf);
776
33
    log_debug("%s: duplicate id payload", __func__);
777
33
    return (-1);
778
33
  }
779
780
124
  idp->id_buf = idb.id_buf;
781
124
  idp->id_offset = idb.id_offset;
782
124
  idp->id_type = idb.id_type;
783
784
124
  return (0);
785
157
}
786
787
int
788
ikev2_validate_cert(struct iked_message *msg, size_t offset, size_t left,
789
    struct ikev2_cert *cert)
790
6.90k
{
791
6.90k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
792
793
6.90k
  if (left < sizeof(*cert)) {
794
1.53k
    log_debug("%s: malformed payload: too short for header "
795
1.53k
        "(%zu < %zu)", __func__, left, sizeof(*cert));
796
1.53k
    return (-1);
797
1.53k
  }
798
5.37k
  memcpy(cert, msgbuf + offset, sizeof(*cert));
799
5.37k
  if (cert->cert_type == IKEV2_CERT_NONE) {
800
1.03k
    log_debug("%s: malformed payload: invalid cert type", __func__);
801
1.03k
    return (-1);
802
1.03k
  }
803
804
4.33k
  return (0);
805
5.37k
}
806
807
int
808
ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld,
809
    struct iked_message *msg, size_t offset, size_t left)
810
6.90k
{
811
6.90k
  struct ikev2_cert    cert;
812
6.90k
  uint8_t       *buf;
813
6.90k
  size_t         len;
814
6.90k
  struct iked_id      *certid;
815
6.90k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
816
6.90k
  const struct iked_sa    *sa = msg->msg_sa;
817
6.90k
  int        i;
818
819
6.90k
  if (ikev2_validate_cert(msg, offset, left, &cert))
820
2.56k
    return (-1);
821
4.33k
  offset += sizeof(cert);
822
823
4.33k
  buf = msgbuf + offset;
824
4.33k
  len = left - sizeof(cert);
825
826
4.33k
  log_debug("%s: type %s length %zu",
827
4.33k
      __func__, print_map(cert.cert_type, ikev2_cert_map), len);
828
829
4.33k
  print_hex(buf, 0, len);
830
831
4.33k
  if (!ikev2_msg_frompeer(msg))
832
1.54k
    return (0);
833
834
  /* do not accept internal encoding in the wire */
835
2.78k
  if (cert.cert_type == IKEV2_CERT_BUNDLE) {
836
290
    log_debug("%s: ignoring IKEV2_CERT_BUNDLE",
837
290
       SPI_SA(sa, __func__));
838
290
    return (0);
839
290
  }
840
841
2.49k
  certid = &msg->msg_parent->msg_cert;
842
2.49k
  if (certid->id_type) {
843
    /* try to set supplemental certs */
844
6.88k
    for (i = 0; i < IKED_SCERT_MAX; i++) {
845
5.52k
      certid = &msg->msg_parent->msg_scert[i];
846
5.52k
      if (!certid->id_type)
847
778
        break;
848
5.52k
    }
849
2.13k
    if (certid->id_type) {
850
1.35k
      log_debug("%s: too many cert payloads, ignoring",
851
1.35k
         SPI_SA(sa, __func__));
852
1.35k
      return (0);
853
1.35k
    }
854
2.13k
  }
855
856
1.14k
  if ((certid->id_buf = ibuf_new(buf, len)) == NULL) {
857
0
    log_debug("%s: failed to save cert", __func__);
858
0
    return (-1);
859
0
  }
860
1.14k
  certid->id_type = cert.cert_type;
861
1.14k
  certid->id_offset = 0;
862
863
1.14k
  return (0);
864
1.14k
}
865
866
int
867
ikev2_validate_certreq(struct iked_message *msg, size_t offset, size_t left,
868
    struct ikev2_cert *cert)
869
15.4k
{
870
15.4k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
871
872
15.4k
  if (left < sizeof(*cert)) {
873
3.58k
    log_debug("%s: malformed payload: too short for header "
874
3.58k
        "(%zu < %zu)", __func__, left, sizeof(*cert));
875
3.58k
    return (-1);
876
3.58k
  }
877
11.8k
  memcpy(cert, msgbuf + offset, sizeof(*cert));
878
879
11.8k
  return (0);
880
15.4k
}
881
882
int
883
ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld,
884
    struct iked_message *msg, size_t offset, size_t left)
885
15.4k
{
886
15.4k
  struct ikev2_cert    cert;
887
15.4k
  struct iked_certreq   *cr;
888
15.4k
  uint8_t       *buf;
889
15.4k
  ssize_t        len;
890
15.4k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
891
892
15.4k
  if (ikev2_validate_certreq(msg, offset, left, &cert))
893
3.58k
    return (-1);
894
11.8k
  offset += sizeof(cert);
895
896
11.8k
  buf = msgbuf + offset;
897
11.8k
  len = left - sizeof(cert);
898
899
11.8k
  log_debug("%s: type %s length %zd",
900
11.8k
      __func__, print_map(cert.cert_type, ikev2_cert_map), len);
901
902
11.8k
  print_hex(buf, 0, len);
903
904
11.8k
  if (!ikev2_msg_frompeer(msg))
905
10.4k
    return (0);
906
907
1.34k
  if (cert.cert_type == IKEV2_CERT_X509_CERT) {
908
330
    if (len == 0) {
909
288
      log_info("%s: invalid length 0", __func__);
910
288
      return (0);
911
288
    }
912
42
    if ((len % SHA_DIGEST_LENGTH) != 0) {
913
9
      log_info("%s: invalid certificate request",
914
9
          __func__);
915
9
      return (-1);
916
9
    }
917
42
  }
918
919
1.04k
  if ((cr = calloc(1, sizeof(struct iked_certreq))) == NULL) {
920
0
    log_info("%s: failed to allocate certreq.", __func__);
921
0
    return (-1);
922
0
  }
923
1.04k
  if ((cr->cr_data = ibuf_new(buf, len)) == NULL) {
924
0
    log_info("%s: failed to allocate buffer.", __func__);
925
0
    free(cr);
926
0
    return (-1);
927
0
  }
928
1.04k
  cr->cr_type = cert.cert_type;
929
1.04k
  SIMPLEQ_INSERT_TAIL(&msg->msg_parent->msg_certreqs, cr, cr_entry);
930
931
1.04k
  return (0);
932
1.04k
}
933
934
int
935
ikev2_validate_auth(struct iked_message *msg, size_t offset, size_t left,
936
    struct ikev2_auth *auth)
937
10.5k
{
938
10.5k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
939
940
10.5k
  if (left < sizeof(*auth)) {
941
2.04k
    log_debug("%s: malformed payload: too short for header "
942
2.04k
        "(%zu < %zu)", __func__, left, sizeof(*auth));
943
2.04k
    return (-1);
944
2.04k
  }
945
8.50k
  memcpy(auth, msgbuf + offset, sizeof(*auth));
946
947
8.50k
  if (auth->auth_method == 0) {
948
4.72k
    log_info("%s: malformed payload: invalid auth method",
949
4.72k
        __func__);
950
4.72k
    return (-1);
951
4.72k
  }
952
953
3.78k
  return (0);
954
8.50k
}
955
956
int
957
ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld,
958
    struct iked_message *msg, size_t offset, size_t left)
959
10.5k
{
960
10.5k
  struct ikev2_auth    auth;
961
10.5k
  struct iked_id      *idp;
962
10.5k
  uint8_t       *buf;
963
10.5k
  size_t         len;
964
10.5k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
965
966
10.5k
  if (ikev2_validate_auth(msg, offset, left, &auth))
967
6.76k
    return (-1);
968
3.78k
  offset += sizeof(auth);
969
970
3.78k
  buf = msgbuf + offset;
971
3.78k
  len = left - sizeof(auth);
972
973
3.78k
  log_debug("%s: method %s length %zu",
974
3.78k
      __func__, print_map(auth.auth_method, ikev2_auth_map), len);
975
976
3.78k
  print_hex(buf, 0, len);
977
978
3.78k
  if (!ikev2_msg_frompeer(msg))
979
3.74k
    return (0);
980
981
42
  idp = &msg->msg_parent->msg_auth;
982
42
  if (idp->id_type) {
983
1
    log_debug("%s: duplicate auth payload", __func__);
984
1
    return (-1);
985
1
  }
986
987
41
  ibuf_free(idp->id_buf);
988
41
  idp->id_type = auth.auth_method;
989
41
  idp->id_offset = 0;
990
41
  if ((idp->id_buf = ibuf_new(buf, len)) == NULL)
991
0
    return (-1);
992
993
41
  return (0);
994
41
}
995
996
int
997
ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld,
998
    struct iked_message *msg, size_t offset, size_t left)
999
3.51k
{
1000
3.51k
  size_t     len;
1001
3.51k
  uint8_t   *buf;
1002
3.51k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1003
1004
3.51k
  buf = msgbuf + offset;
1005
3.51k
  len = left;
1006
1007
3.51k
  if (len == 0) {
1008
3.21k
    log_debug("%s: malformed payload: no NONCE given", __func__);
1009
3.21k
    return (-1);
1010
3.21k
  }
1011
1012
298
  print_hex(buf, 0, len);
1013
1014
298
  if (ikev2_msg_frompeer(msg)) {
1015
62
    if (msg->msg_parent->msg_nonce != NULL) {
1016
19
      log_info("%s: duplicate NONCE payload", __func__);
1017
19
      return (-1);
1018
19
    }
1019
43
    if ((msg->msg_nonce = ibuf_new(buf, len)) == NULL) {
1020
0
      log_debug("%s: failed to get peer nonce", __func__);
1021
0
      return (-1);
1022
0
    }
1023
43
    msg->msg_parent->msg_nonce = msg->msg_nonce;
1024
43
  }
1025
1026
279
  return (0);
1027
298
}
1028
1029
int
1030
ikev2_validate_notify(struct iked_message *msg, size_t offset, size_t left,
1031
    struct ikev2_notify *n)
1032
39.8k
{
1033
39.8k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1034
1035
39.8k
  if (left < sizeof(*n)) {
1036
5.32k
    log_debug("%s: malformed payload: too short for header "
1037
5.32k
        "(%zu < %zu)", __func__, left, sizeof(*n));
1038
5.32k
    return (-1);
1039
5.32k
  }
1040
34.4k
  memcpy(n, msgbuf + offset, sizeof(*n));
1041
1042
34.4k
  return (0);
1043
39.8k
}
1044
1045
int
1046
ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld,
1047
    struct iked_message *msg, size_t offset, size_t left)
1048
39.8k
{
1049
39.8k
  struct ikev2_notify  n;
1050
39.8k
  const struct iked_sa  *sa = msg->msg_sa;
1051
39.8k
  uint8_t     *buf, md[SHA_DIGEST_LENGTH];
1052
39.8k
  uint32_t     spi32;
1053
39.8k
  uint64_t     spi64;
1054
39.8k
  struct iked_spi   *rekey;
1055
39.8k
  uint16_t     type;
1056
39.8k
  uint16_t     signature_hash;
1057
1058
39.8k
  if (ikev2_validate_notify(msg, offset, left, &n))
1059
5.32k
    return (-1);
1060
34.4k
  type = betoh16(n.n_type);
1061
1062
34.4k
  log_debug("%s: protoid %s spisize %d type %s",
1063
34.4k
      __func__,
1064
34.4k
      print_map(n.n_protoid, ikev2_saproto_map), n.n_spisize,
1065
34.4k
      print_map(type, ikev2_n_map));
1066
1067
34.4k
  left -= sizeof(n);
1068
34.4k
  if ((buf = ibuf_seek(msg->msg_data, offset + sizeof(n), left)) == NULL)
1069
0
    return (-1);
1070
1071
34.4k
  print_hex(buf, 0, left);
1072
1073
34.4k
  if (!ikev2_msg_frompeer(msg))
1074
2.00k
    return (0);
1075
1076
32.4k
  switch (type) {
1077
3.34k
  case IKEV2_N_NAT_DETECTION_SOURCE_IP:
1078
26.0k
  case IKEV2_N_NAT_DETECTION_DESTINATION_IP:
1079
26.0k
    if (left != sizeof(md)) {
1080
17
      log_debug("%s: malformed payload: hash size mismatch"
1081
17
          " (%zu != %zu)", __func__, left, sizeof(md));
1082
17
      return (-1);
1083
17
    }
1084
26.0k
    if (ikev2_nat_detection(env, msg, md, sizeof(md), type,
1085
26.0k
        ikev2_msg_frompeer(msg)) == -1)
1086
0
      return (-1);
1087
26.0k
    if (memcmp(buf, md, left) != 0) {
1088
25.8k
      log_debug("%s: %s detected NAT", __func__,
1089
25.8k
          print_map(type, ikev2_n_map));
1090
25.8k
      if (type == IKEV2_N_NAT_DETECTION_SOURCE_IP)
1091
3.34k
        msg->msg_parent->msg_nat_detected
1092
3.34k
            |= IKED_MSG_NAT_SRC_IP;
1093
22.4k
      else
1094
22.4k
        msg->msg_parent->msg_nat_detected
1095
22.4k
            |= IKED_MSG_NAT_DST_IP;
1096
25.8k
    }
1097
26.0k
    print_hex(md, 0, sizeof(md));
1098
    /* remember for MOBIKE */
1099
26.0k
    msg->msg_parent->msg_natt_rcvd = 1;
1100
26.0k
    break;
1101
6
  case IKEV2_N_AUTHENTICATION_FAILED:
1102
6
    if (!msg->msg_e) {
1103
0
      log_debug("%s: AUTHENTICATION_FAILED not encrypted",
1104
0
          __func__);
1105
0
      return (-1);
1106
0
    }
1107
    /*
1108
     * If we are the responder, then we only accept
1109
     * AUTHENTICATION_FAILED from authenticated peers.
1110
     * If we are the initiator, the peer cannot be authenticated.
1111
     */
1112
6
    if (!sa->sa_hdr.sh_initiator) {
1113
6
      if (!sa_stateok(sa, IKEV2_STATE_VALID)) {
1114
6
        log_debug("%s: ignoring AUTHENTICATION_FAILED"
1115
6
            " from unauthenticated initiator",
1116
6
            __func__);
1117
6
        return (-1);
1118
6
      }
1119
6
    } else {
1120
0
      if (sa_stateok(sa, IKEV2_STATE_VALID)) {
1121
0
        log_debug("%s: ignoring AUTHENTICATION_FAILED"
1122
0
            " from authenticated responder",
1123
0
            __func__);
1124
0
        return (-1);
1125
0
      }
1126
0
    }
1127
0
    msg->msg_parent->msg_flags
1128
0
        |= IKED_MSG_FLAGS_AUTHENTICATION_FAILED;
1129
0
    break;
1130
143
  case IKEV2_N_INVALID_KE_PAYLOAD:
1131
143
    if (sa_stateok(sa, IKEV2_STATE_VALID) &&
1132
143
        !msg->msg_e) {
1133
0
      log_debug("%s: INVALID_KE_PAYLOAD not encrypted",
1134
0
          __func__);
1135
0
      return (-1);
1136
0
    }
1137
143
    if (left != sizeof(msg->msg_parent->msg_group)) {
1138
4
      log_debug("%s: malformed payload: group size mismatch"
1139
4
          " (%zu != %zu)", __func__, left,
1140
4
          sizeof(msg->msg_parent->msg_group));
1141
4
      return (-1);
1142
4
    }
1143
139
    memcpy(&msg->msg_parent->msg_group, buf, left);
1144
139
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_INVALID_KE;
1145
139
    break;
1146
273
  case IKEV2_N_NO_ADDITIONAL_SAS:
1147
273
    if (!msg->msg_e) {
1148
0
      log_debug("%s: NO_ADDITIONAL_SAS not encrypted",
1149
0
          __func__);
1150
0
      return (-1);
1151
0
    }
1152
273
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_NO_ADDITIONAL_SAS;
1153
273
    break;
1154
82
  case IKEV2_N_REKEY_SA:
1155
82
    if (!msg->msg_e) {
1156
0
      log_debug("%s: N_REKEY_SA not encrypted", __func__);
1157
0
      return (-1);
1158
0
    }
1159
82
    if (left != n.n_spisize) {
1160
5
      log_debug("%s: malformed notification", __func__);
1161
5
      return (-1);
1162
5
    }
1163
77
    rekey = &msg->msg_parent->msg_rekey;
1164
77
    if (rekey->spi != 0) {
1165
5
      log_debug("%s: rekeying of multiple SAs not supported",
1166
5
          __func__);
1167
5
      return (-1);
1168
5
    }
1169
72
    switch (n.n_spisize) {
1170
65
    case 4:
1171
65
      memcpy(&spi32, buf, left);
1172
65
      rekey->spi = betoh32(spi32);
1173
65
      break;
1174
4
    case 8:
1175
4
      memcpy(&spi64, buf, left);
1176
4
      rekey->spi = betoh64(spi64);
1177
4
      break;
1178
3
    default:
1179
3
      log_debug("%s: invalid spi size %d", __func__,
1180
3
          n.n_spisize);
1181
3
      return (-1);
1182
72
    }
1183
69
    rekey->spi_size = n.n_spisize;
1184
69
    rekey->spi_protoid = n.n_protoid;
1185
1186
69
    log_debug("%s: rekey %s spi %s", __func__,
1187
69
        print_map(n.n_protoid, ikev2_saproto_map),
1188
69
        print_spi(rekey->spi, n.n_spisize));
1189
69
    break;
1190
354
  case IKEV2_N_TEMPORARY_FAILURE:
1191
354
    if (!msg->msg_e) {
1192
0
      log_debug("%s: IKEV2_N_TEMPORARY_FAILURE not encrypted",
1193
0
          __func__);
1194
0
      return (-1);
1195
0
    }
1196
354
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_TEMPORARY_FAILURE;
1197
354
    break;
1198
255
  case IKEV2_N_IPCOMP_SUPPORTED:
1199
255
    if (!msg->msg_e) {
1200
0
      log_debug("%s: N_IPCOMP_SUPPORTED not encrypted",
1201
0
          __func__);
1202
0
      return (-1);
1203
0
    }
1204
255
    if (left < sizeof(msg->msg_parent->msg_cpi) +
1205
255
        sizeof(msg->msg_parent->msg_transform)) {
1206
127
      log_debug("%s: ignoring malformed ipcomp notification",
1207
127
          __func__);
1208
127
      return (0);
1209
127
    }
1210
128
    memcpy(&msg->msg_parent->msg_cpi, buf,
1211
128
        sizeof(msg->msg_parent->msg_cpi));
1212
128
    memcpy(&msg->msg_parent->msg_transform,
1213
128
        buf + sizeof(msg->msg_parent->msg_cpi),
1214
128
        sizeof(msg->msg_parent->msg_transform));
1215
1216
128
    log_debug("%s: %s cpi 0x%x, transform %s, length %zu", __func__,
1217
128
        msg->msg_parent->msg_response ? "res" : "req",
1218
128
        betoh16(msg->msg_parent->msg_cpi),
1219
128
        print_map(msg->msg_parent->msg_transform,
1220
128
        ikev2_ipcomp_map), left);
1221
1222
128
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_IPCOMP_SUPPORTED;
1223
128
    break;
1224
73
  case IKEV2_N_CHILD_SA_NOT_FOUND:
1225
73
    if (!msg->msg_e) {
1226
0
      log_debug("%s: N_CHILD_SA_NOT_FOUND not encrypted",
1227
0
          __func__);
1228
0
      return (-1);
1229
0
    }
1230
73
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_CHILD_SA_NOT_FOUND;
1231
73
    break;
1232
36
  case IKEV2_N_NO_PROPOSAL_CHOSEN:
1233
36
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN;
1234
36
    break;
1235
1.81k
  case IKEV2_N_MOBIKE_SUPPORTED:
1236
1.81k
    if (!msg->msg_e) {
1237
0
      log_debug("%s: N_MOBIKE_SUPPORTED not encrypted",
1238
0
          __func__);
1239
0
      return (-1);
1240
0
    }
1241
1.81k
    if (left != 0) {
1242
1.65k
      log_debug("%s: ignoring malformed mobike"
1243
1.65k
          " notification: %zu", __func__, left);
1244
1.65k
      return (0);
1245
1.65k
    }
1246
159
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_MOBIKE;
1247
159
    break;
1248
356
  case IKEV2_N_USE_TRANSPORT_MODE:
1249
356
    if (!msg->msg_e) {
1250
0
      log_debug("%s: N_USE_TRANSPORT_MODE not encrypted",
1251
0
          __func__);
1252
0
      return (-1);
1253
0
    }
1254
356
    if (left != 0) {
1255
77
      log_debug("%s: ignoring malformed transport mode"
1256
77
          " notification: %zu", __func__, left);
1257
77
      return (0);
1258
77
    }
1259
279
    if (msg->msg_parent->msg_response) {
1260
0
      if (!(msg->msg_policy->pol_flags & IKED_POLICY_TRANSPORT)) {
1261
0
        log_debug("%s: ignoring transport mode"
1262
0
            " notification (policy)", __func__);
1263
0
        return (0);
1264
0
      }
1265
0
    }
1266
279
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_USE_TRANSPORT;
1267
279
    break;
1268
388
  case IKEV2_N_UPDATE_SA_ADDRESSES:
1269
388
    if (!msg->msg_e) {
1270
0
      log_debug("%s: N_UPDATE_SA_ADDRESSES not encrypted",
1271
0
          __func__);
1272
0
      return (-1);
1273
0
    }
1274
388
    if (!sa->sa_mobike) {
1275
388
      log_debug("%s: ignoring update sa addresses"
1276
388
          " notification w/o mobike: %zu", __func__, left);
1277
388
      return (0);
1278
388
    }
1279
0
    if (left != 0) {
1280
0
      log_debug("%s: ignoring malformed update sa addresses"
1281
0
          " notification: %zu", __func__, left);
1282
0
      return (0);
1283
0
    }
1284
0
    msg->msg_parent->msg_update_sa_addresses = 1;
1285
0
    break;
1286
242
  case IKEV2_N_COOKIE2:
1287
242
    if (!msg->msg_e) {
1288
0
      log_debug("%s: N_COOKIE2 not encrypted",
1289
0
          __func__);
1290
0
      return (-1);
1291
0
    }
1292
242
    if (!sa->sa_mobike) {
1293
242
      log_debug("%s: ignoring cookie2 notification"
1294
242
          " w/o mobike: %zu", __func__, left);
1295
242
      return (0);
1296
242
    }
1297
0
    if (left < IKED_COOKIE2_MIN || left > IKED_COOKIE2_MAX) {
1298
0
      log_debug("%s: ignoring malformed cookie2"
1299
0
          " notification: %zu", __func__, left);
1300
0
      return (0);
1301
0
    }
1302
0
    ibuf_free(msg->msg_cookie2);  /* should not happen */
1303
0
    if ((msg->msg_cookie2 = ibuf_new(buf, left)) == NULL) {
1304
0
      log_debug("%s: failed to get peer cookie2", __func__);
1305
0
      return (-1);
1306
0
    }
1307
0
    msg->msg_parent->msg_cookie2 = msg->msg_cookie2;
1308
0
    break;
1309
2
  case IKEV2_N_COOKIE:
1310
2
    if (msg->msg_e) {
1311
2
      log_debug("%s: N_COOKIE encrypted",
1312
2
          __func__);
1313
2
      return (-1);
1314
2
    }
1315
0
    if (left < IKED_COOKIE_MIN || left > IKED_COOKIE_MAX) {
1316
0
      log_debug("%s: ignoring malformed cookie"
1317
0
          " notification: %zu", __func__, left);
1318
0
      return (0);
1319
0
    }
1320
0
    log_debug("%s: received cookie, len %zu", __func__, left);
1321
0
    print_hex(buf, 0, left);
1322
1323
0
    ibuf_free(msg->msg_cookie);
1324
0
    if ((msg->msg_cookie = ibuf_new(buf, left)) == NULL) {
1325
0
      log_debug("%s: failed to get peer cookie", __func__);
1326
0
      return (-1);
1327
0
    }
1328
0
    msg->msg_parent->msg_cookie = msg->msg_cookie;
1329
0
    break;
1330
14
  case IKEV2_N_FRAGMENTATION_SUPPORTED:
1331
14
    if (msg->msg_e) {
1332
14
      log_debug("%s: N_FRAGMENTATION_SUPPORTED encrypted",
1333
14
          __func__);
1334
14
      return (-1);
1335
14
    }
1336
0
    if (left != 0) {
1337
0
      log_debug("%s: ignoring malformed fragmentation"
1338
0
          " notification: %zu", __func__, left);
1339
0
      return (0);
1340
0
    }
1341
0
    msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_FRAGMENTATION;
1342
0
    break;
1343
7
  case IKEV2_N_SIGNATURE_HASH_ALGORITHMS:
1344
7
    if (msg->msg_e) {
1345
7
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: encrypted",
1346
7
          __func__);
1347
7
      return (-1);
1348
7
    }
1349
0
    if (sa == NULL) {
1350
0
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: no SA",
1351
0
          __func__);
1352
0
      return (-1);
1353
0
    }
1354
0
    if (sa->sa_sigsha2) {
1355
0
      log_debug("%s: SIGNATURE_HASH_ALGORITHMS: "
1356
0
          "duplicate notify", __func__);
1357
0
      return (0);
1358
0
    }
1359
0
    if (left < sizeof(signature_hash) ||
1360
0
        left % sizeof(signature_hash)) {
1361
0
      log_debug("%s: malformed signature hash notification"
1362
0
          "(%zu bytes)", __func__, left);
1363
0
      return (0);
1364
0
    }
1365
0
    while (left >= sizeof(signature_hash)) {
1366
0
      memcpy(&signature_hash, buf, sizeof(signature_hash));
1367
0
      signature_hash = betoh16(signature_hash);
1368
0
      log_debug("%s: signature hash %s (%x)", __func__,
1369
0
          print_map(signature_hash, ikev2_sighash_map),
1370
0
          signature_hash);
1371
0
      left -= sizeof(signature_hash);
1372
0
      buf += sizeof(signature_hash);
1373
0
      if (signature_hash == IKEV2_SIGHASH_SHA2_256)
1374
0
        msg->msg_parent->msg_flags
1375
0
            |= IKED_MSG_FLAGS_SIGSHA2;
1376
0
    }
1377
0
    break;
1378
32.4k
  }
1379
1380
29.9k
  return (0);
1381
32.4k
}
1382
1383
int
1384
ikev2_validate_delete(struct iked_message *msg, size_t offset, size_t left,
1385
    struct ikev2_delete *del)
1386
7.54k
{
1387
7.54k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1388
1389
7.54k
  if (left < sizeof(*del)) {
1390
1.53k
    log_debug("%s: malformed payload: too short for header "
1391
1.53k
        "(%zu < %zu)", __func__, left, sizeof(*del));
1392
1.53k
    return (-1);
1393
1.53k
  }
1394
6.01k
  memcpy(del, msgbuf + offset, sizeof(*del));
1395
1396
6.01k
  if (del->del_protoid == 0) {
1397
84
    log_info("%s: malformed payload: invalid protoid", __func__);
1398
84
    return (-1);
1399
84
  }
1400
1401
5.92k
  return (0);
1402
6.01k
}
1403
1404
int
1405
ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld,
1406
    struct iked_message *msg, size_t offset, size_t left)
1407
7.54k
{
1408
7.54k
  struct ikev2_delete  del;
1409
7.54k
  uint8_t     *buf, *msgbuf = ibuf_data(msg->msg_data);
1410
7.54k
  size_t       cnt, sz, len;
1411
1412
7.54k
  if (ikev2_validate_delete(msg, offset, left, &del))
1413
1.62k
    return (-1);
1414
1415
  /* Skip if it's a response, then we don't have to deal with it */
1416
5.92k
  if (ikev2_msg_frompeer(msg) &&
1417
5.92k
      msg->msg_parent->msg_response)
1418
0
    return (0);
1419
1420
5.92k
  cnt = betoh16(del.del_nspi);
1421
5.92k
  sz = del.del_spisize;
1422
1423
5.92k
  log_debug("%s: proto %s spisize %zu nspi %zu",
1424
5.92k
      __func__, print_map(del.del_protoid, ikev2_saproto_map),
1425
5.92k
      sz, cnt);
1426
1427
5.92k
  if (msg->msg_parent->msg_del_protoid) {
1428
5.54k
    log_debug("%s: duplicate delete payload", __func__);
1429
5.54k
    return (0);
1430
5.54k
  }
1431
1432
380
  msg->msg_parent->msg_del_protoid = del.del_protoid;
1433
380
  msg->msg_parent->msg_del_cnt = cnt;
1434
380
  msg->msg_parent->msg_del_spisize = sz;
1435
1436
380
  buf = msgbuf + offset + sizeof(del);
1437
380
  len = left - sizeof(del);
1438
380
  if (len == 0 || sz == 0 || cnt == 0)
1439
357
    return (0);
1440
1441
23
  if ((len / sz) != cnt) {
1442
21
    log_debug("%s: invalid payload length %zu/%zu != %zu",
1443
21
        __func__, len, sz, cnt);
1444
21
    return (-1);
1445
21
  }
1446
1447
2
  print_hex(buf, 0, len);
1448
1449
2
  msg->msg_parent->msg_del_buf = ibuf_new(buf, len);
1450
1451
2
  return (0);
1452
23
}
1453
1454
int
1455
ikev2_validate_tss(struct iked_message *msg, size_t offset, size_t left,
1456
    struct ikev2_tsp *tsp)
1457
23.0k
{
1458
23.0k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1459
1460
23.0k
  if (left < sizeof(*tsp)) {
1461
2.69k
    log_debug("%s: malformed payload: too short for header "
1462
2.69k
        "(%zu < %zu)", __func__, left, sizeof(*tsp));
1463
2.69k
    return (-1);
1464
2.69k
  }
1465
20.4k
  memcpy(tsp, msgbuf + offset, sizeof(*tsp));
1466
1467
20.4k
  return (0);
1468
23.0k
}
1469
1470
int
1471
ikev2_pld_tss(struct iked *env, struct ikev2_payload *pld,
1472
    struct iked_message *msg, size_t offset, size_t left)
1473
23.0k
{
1474
23.0k
  struct ikev2_tsp     tsp;
1475
23.0k
  struct ikev2_ts      ts;
1476
23.0k
  size_t         ts_len, i;
1477
1478
23.0k
  if (ikev2_validate_tss(msg, offset, left, &tsp))
1479
2.69k
    return (-1);
1480
1481
20.4k
  offset += sizeof(tsp);
1482
20.4k
  left -= sizeof(tsp);
1483
1484
20.4k
  log_debug("%s: count %d length %zu", __func__,
1485
20.4k
      tsp.tsp_count, left);
1486
1487
40.3k
  for (i = 0; i < tsp.tsp_count; i++) {
1488
38.6k
    if (ikev2_validate_ts(msg, offset, left, &ts))
1489
15.9k
      return (-1);
1490
1491
22.6k
    log_debug("%s: type %s protoid %u length %d "
1492
22.6k
        "startport %u endport %u", __func__,
1493
22.6k
        print_map(ts.ts_type, ikev2_ts_map),
1494
22.6k
        ts.ts_protoid, betoh16(ts.ts_length),
1495
22.6k
        betoh16(ts.ts_startport),
1496
22.6k
        betoh16(ts.ts_endport));
1497
1498
22.6k
    offset += sizeof(ts);
1499
22.6k
    left -= sizeof(ts);
1500
1501
22.6k
    ts_len = betoh16(ts.ts_length) - sizeof(ts);
1502
22.6k
    if (ikev2_pld_ts(env, pld, msg, offset, ts_len, ts.ts_type))
1503
2.71k
      return (-1);
1504
1505
19.9k
    offset += ts_len;
1506
19.9k
    left -= ts_len;
1507
19.9k
  }
1508
1509
1.70k
  return (0);
1510
20.4k
}
1511
1512
int
1513
ikev2_validate_ts(struct iked_message *msg, size_t offset, size_t left,
1514
    struct ikev2_ts *ts)
1515
38.6k
{
1516
38.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1517
38.6k
  size_t     ts_length;
1518
1519
38.6k
  if (left < sizeof(*ts)) {
1520
14.4k
    log_debug("%s: malformed payload: too short for header "
1521
14.4k
        "(%zu < %zu)", __func__, left, sizeof(*ts));
1522
14.4k
    return (-1);
1523
14.4k
  }
1524
24.1k
  memcpy(ts, msgbuf + offset, sizeof(*ts));
1525
1526
24.1k
  ts_length = betoh16(ts->ts_length);
1527
24.1k
  if (ts_length < sizeof(*ts)) {
1528
349
    log_debug("%s: malformed payload: shorter than minimum header "
1529
349
        "size (%zu < %zu)", __func__, ts_length, sizeof(*ts));
1530
349
    return (-1);
1531
349
  }
1532
23.8k
  if (left < ts_length) {
1533
1.21k
    log_debug("%s: malformed payload: too long for payload size "
1534
1.21k
        "(%zu < %zu)", __func__, left, ts_length);
1535
1.21k
    return (-1);
1536
1.21k
  }
1537
1538
22.6k
  return (0);
1539
23.8k
}
1540
1541
int
1542
ikev2_pld_ts(struct iked *env, struct ikev2_payload *pld,
1543
    struct iked_message *msg, size_t offset, size_t left, unsigned int type)
1544
22.6k
{
1545
22.6k
  struct sockaddr_in     start4, end4;
1546
22.6k
  struct sockaddr_in6    start6, end6;
1547
22.6k
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
1548
22.6k
  uint8_t       *ptr;
1549
1550
22.6k
  ptr = msgbuf + offset;
1551
1552
22.6k
  switch (type) {
1553
9.66k
  case IKEV2_TS_IPV4_ADDR_RANGE:
1554
9.66k
    if (left < 2 * 4) {
1555
1.16k
      log_debug("%s: malformed payload: too short "
1556
1.16k
          "for ipv4 addr range (%zu < %u)",
1557
1.16k
          __func__, left, 2 * 4);
1558
1.16k
      return (-1);
1559
1.16k
    }
1560
1561
8.50k
    bzero(&start4, sizeof(start4));
1562
8.50k
    start4.sin_family = AF_INET;
1563
#ifdef HAVE_SOCKADDR_SA_LEN
1564
    start4.sin_len = sizeof(start4);
1565
#endif
1566
8.50k
    memcpy(&start4.sin_addr.s_addr, ptr, 4);
1567
8.50k
    ptr += 4;
1568
8.50k
    left -= 4;
1569
1570
8.50k
    bzero(&end4, sizeof(end4));
1571
8.50k
    end4.sin_family = AF_INET;
1572
#ifdef HAVE_SOCKADDR_SA_LEN
1573
    end4.sin_len = sizeof(end4);
1574
#endif
1575
8.50k
    memcpy(&end4.sin_addr.s_addr, ptr, 4);
1576
8.50k
    left -= 4;
1577
1578
8.50k
    log_debug("%s: start %s end %s", __func__,
1579
8.50k
        print_addr(&start4), print_addr(&end4));
1580
8.50k
    break;
1581
1.54k
  case IKEV2_TS_IPV6_ADDR_RANGE:
1582
1.54k
    if (left < 2 * 16) {
1583
252
      log_debug("%s: malformed payload: too short "
1584
252
          "for ipv6 addr range (%zu < %u)",
1585
252
          __func__, left, 2 * 16);
1586
252
      return (-1);
1587
252
    }
1588
1.29k
    bzero(&start6, sizeof(start6));
1589
1.29k
    start6.sin6_family = AF_INET6;
1590
#ifdef HAVE_SOCKADDR_SA_LEN
1591
    start6.sin6_len = sizeof(start6);
1592
#endif
1593
1.29k
    memcpy(&start6.sin6_addr, ptr, 16);
1594
1.29k
    ptr += 16;
1595
1.29k
    left -= 16;
1596
1597
1.29k
    bzero(&end6, sizeof(end6));
1598
1.29k
    end6.sin6_family = AF_INET6;
1599
#ifdef HAVE_SOCKADDR_SA_LEN
1600
    end6.sin6_len = sizeof(end6);
1601
#endif
1602
1.29k
    memcpy(&end6.sin6_addr, ptr, 16);
1603
1.29k
    left -= 16;
1604
1605
1.29k
    log_debug("%s: start %s end %s", __func__,
1606
1.29k
        print_addr(&start6), print_addr(&end6));
1607
1.29k
    break;
1608
11.4k
  default:
1609
11.4k
    log_debug("%s: ignoring unknown TS type %u", __func__, type);
1610
11.4k
    return (0);
1611
22.6k
  }
1612
1613
9.79k
  if (left > 0) {
1614
1.30k
    log_debug("%s: malformed payload: left (%zu) > 0",
1615
1.30k
        __func__, left);
1616
1.30k
    return (-1);
1617
1.30k
  }
1618
1619
8.49k
  return (0);
1620
9.79k
}
1621
1622
int
1623
ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
1624
    struct iked_message *msg, size_t offset, size_t left)
1625
0
{
1626
0
  struct iked_sa      *sa = msg->msg_sa;
1627
0
  struct iked_frag    *sa_frag = &sa->sa_fragments;
1628
0
  struct iked_frag_entry    *el;
1629
0
  struct ikev2_frag_payload  frag;
1630
0
  uint8_t       *msgbuf = ibuf_data(msg->msg_data);
1631
0
  uint8_t       *buf;
1632
0
  struct ibuf     *e = NULL;
1633
0
  size_t         frag_num, frag_total;
1634
0
  size_t         len;
1635
0
  int        ret = -1;
1636
0
  int        processed = 0;
1637
0
  ssize_t        elen;
1638
1639
0
  buf = msgbuf + offset;
1640
0
  memcpy(&frag, buf, sizeof(frag));
1641
0
  frag_num = betoh16(frag.frag_num);
1642
0
  frag_total = betoh16(frag.frag_total);
1643
1644
0
  offset += sizeof(frag);
1645
0
  buf = msgbuf + offset;
1646
0
  len = left - sizeof(frag);
1647
1648
0
  ikestat_inc(env, ikes_frag_rcvd);
1649
1650
  /* Limit number of total fragments to avoid DOS */
1651
0
  if (frag_total > IKED_FRAG_TOTAL_MAX ) {
1652
0
    log_debug("%s: Total Fragments too big  %zu",
1653
0
        __func__, frag_total);
1654
0
    goto dropall;
1655
0
  }
1656
1657
  /* Check sanity of fragment header */
1658
0
  if (frag_num == 0 || frag_total == 0) {
1659
0
    log_debug("%s: Malformed fragment received: %zu of %zu",
1660
0
        __func__, frag_num, frag_total);
1661
0
    goto done;
1662
0
  }
1663
0
  log_debug("%s: Received fragment: %zu of %zu",
1664
0
      __func__, frag_num, frag_total);
1665
1666
  /* Drop fragment if frag_num and frag_total don't match */
1667
0
  if (frag_num > frag_total)
1668
0
    goto done;
1669
1670
  /* Decrypt fragment */
1671
0
  if ((e = ibuf_new(buf, len)) == NULL)
1672
0
    goto done;
1673
1674
0
  if ((e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e))
1675
0
      == NULL ) {
1676
0
    log_debug("%s: Failed to decrypt fragment: %zu of %zu",
1677
0
        __func__, frag_num, frag_total);
1678
0
    goto done;
1679
0
  }
1680
0
  elen = ibuf_size(e);
1681
1682
  /* Check new fragmented message */
1683
0
  if (sa_frag->frag_arr == NULL) {
1684
0
    sa_frag->frag_arr = recallocarray(NULL, 0, frag_total,
1685
0
        sizeof(struct iked_frag_entry*));
1686
0
    if (sa_frag->frag_arr == NULL) {
1687
0
      log_info("%s: recallocarray sa_frag->frag_arr.", __func__);
1688
0
      goto done;
1689
0
    }
1690
0
    sa_frag->frag_total = frag_total;
1691
0
  } else {
1692
    /* Drop all fragments if frag_total doesn't match previous */
1693
0
    if (frag_total != sa_frag->frag_total)
1694
0
      goto dropall;
1695
1696
    /* Silent drop if fragment already stored */
1697
0
    if (sa_frag->frag_arr[frag_num-1] != NULL)
1698
0
      goto done;
1699
0
  }
1700
1701
  /* The first fragments IKE header determines pld_nextpayload */
1702
0
  if (frag_num == 1)
1703
0
    sa_frag->frag_nextpayload = pld->pld_nextpayload;
1704
1705
  /* Insert new list element */
1706
0
  el = calloc(1, sizeof(struct iked_frag_entry));
1707
0
  if (el == NULL) {
1708
0
    log_info("%s: Failed allocating new fragment: %zu of %zu",
1709
0
        __func__, frag_num, frag_total);
1710
0
    goto done;
1711
0
  }
1712
1713
0
  sa_frag->frag_arr[frag_num-1] = el;
1714
0
  el->frag_size = elen;
1715
0
  el->frag_data = calloc(1, elen);
1716
0
  if (el->frag_data == NULL) {
1717
0
    log_debug("%s: Failed allocating new fragment data: %zu of %zu",
1718
0
        __func__, frag_num, frag_total);
1719
0
    goto done;
1720
0
  }
1721
1722
  /* Copy plaintext to fragment */
1723
0
  memcpy(el->frag_data, ibuf_seek(e, 0, 0), elen);
1724
0
  sa_frag->frag_total_size += elen;
1725
0
  sa_frag->frag_count++;
1726
1727
  /* If all frags are received start reassembly */
1728
0
  if (sa_frag->frag_count == sa_frag->frag_total) {
1729
0
    log_debug("%s: All fragments received: %zu of %zu",
1730
0
        __func__, frag_num, frag_total);
1731
0
    ret = ikev2_frags_reassemble(env, pld, msg);
1732
0
  } else {
1733
0
    ret = 0;
1734
0
  }
1735
0
  processed = 1;
1736
1737
0
done:
1738
0
  if (!processed)
1739
0
    ikestat_inc(env, ikes_frag_rcvd_drop);
1740
0
  ibuf_free(e);
1741
0
  return (ret);
1742
0
dropall:
1743
0
  ikestat_add(env, ikes_frag_rcvd_drop, sa_frag->frag_count + 1);
1744
0
  config_free_fragments(sa_frag);
1745
0
  ibuf_free(e);
1746
0
  return -1;
1747
0
}
1748
1749
int
1750
ikev2_frags_reassemble(struct iked *env, struct ikev2_payload *pld,
1751
    struct iked_message *msg)
1752
0
{
1753
0
  struct iked_frag    *sa_frag = &msg->msg_sa->sa_fragments;
1754
0
  struct ibuf     *e = NULL;
1755
0
  struct iked_frag_entry    *el;
1756
0
  uint8_t       *ptr;
1757
0
  size_t         offset;
1758
0
  size_t         i;
1759
0
  struct iked_message    emsg;
1760
0
  int        ret = -1;
1761
0
  int        processed = 0;
1762
1763
  /* Reassemble fragments to single buffer */
1764
0
  if ((e = ibuf_new(NULL, sa_frag->frag_total_size)) == NULL) {
1765
0
    log_debug("%s: Failed allocating SK buffer.", __func__);
1766
0
    goto done;
1767
0
  }
1768
1769
  /* Empty queue to new buffer */
1770
0
  offset = 0;
1771
0
  for (i = 0; i < sa_frag->frag_total; i++) {
1772
0
    if ((el = sa_frag->frag_arr[i]) == NULL)
1773
0
      fatalx("Tried to reassemble shallow frag_arr");
1774
0
    ptr = ibuf_seek(e, offset, el->frag_size);
1775
0
    if (ptr == NULL) {
1776
0
      log_info("%s: failed to reassemble fragments", __func__);
1777
0
      goto done;
1778
0
    }
1779
0
    memcpy(ptr, el->frag_data, el->frag_size);
1780
0
    offset += el->frag_size;
1781
0
  }
1782
1783
0
  log_debug("%s: Defragmented length %zd", __func__,
1784
0
      sa_frag->frag_total_size);
1785
0
  print_hex(ibuf_data(e), 0,  sa_frag->frag_total_size);
1786
1787
  /* Drop the original request's packets from the retransmit queue */
1788
0
  if (msg->msg_response)
1789
0
    ikev2_msg_dispose(env, &msg->msg_sa->sa_requests,
1790
0
        ikev2_msg_lookup(env, &msg->msg_sa->sa_requests, msg,
1791
0
        msg->msg_exchange));
1792
1793
  /*
1794
   * Parse decrypted payload
1795
   */
1796
0
  bzero(&emsg, sizeof(emsg));
1797
0
  memcpy(&emsg, msg, sizeof(*msg));
1798
0
  emsg.msg_data = e;
1799
0
  emsg.msg_e = 1;
1800
0
  emsg.msg_parent = msg;
1801
0
  TAILQ_INIT(&emsg.msg_proposals);
1802
1803
0
  ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
1804
0
      sa_frag->frag_nextpayload);
1805
0
  processed = 1;
1806
0
done:
1807
0
  if (processed)
1808
0
    ikestat_add(env, ikes_frag_reass_ok, sa_frag->frag_total);
1809
0
  else
1810
0
    ikestat_add(env, ikes_frag_reass_drop, sa_frag->frag_total);
1811
0
  config_free_fragments(sa_frag);
1812
0
  ibuf_free(e);
1813
1814
0
  return (ret);
1815
0
}
1816
1817
int
1818
ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
1819
    struct iked_message *msg, size_t offset, size_t left)
1820
0
{
1821
0
  struct iked_sa    *sa = msg->msg_sa;
1822
0
  struct ibuf   *e = NULL;
1823
0
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
1824
0
  struct iked_message  emsg;
1825
0
  uint8_t     *buf;
1826
0
  size_t       len;
1827
0
  int      ret = -1;
1828
1829
0
  if (sa->sa_fragments.frag_arr != NULL) {
1830
0
    log_warn("%s: Received SK payload when SKFs are in queue.",
1831
0
        __func__);
1832
0
    config_free_fragments(&sa->sa_fragments);
1833
0
    return (ret);
1834
0
  }
1835
1836
0
  buf = msgbuf + offset;
1837
0
  len = left;
1838
1839
0
  if ((e = ibuf_new(buf, len)) == NULL)
1840
0
    goto done;
1841
1842
0
  if (ikev2_msg_frompeer(msg)) {
1843
0
    e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
1844
0
  } else {
1845
0
    sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
1846
0
    e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
1847
0
    sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
1848
0
  }
1849
1850
0
  if (e == NULL)
1851
0
    goto done;
1852
1853
  /*
1854
   * Parse decrypted payload
1855
   */
1856
0
  bzero(&emsg, sizeof(emsg));
1857
0
  memcpy(&emsg, msg, sizeof(*msg));
1858
0
  emsg.msg_data = e;
1859
0
  emsg.msg_e = 1;
1860
0
  emsg.msg_parent = msg;
1861
0
  TAILQ_INIT(&emsg.msg_proposals);
1862
1863
0
  ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
1864
0
      pld->pld_nextpayload);
1865
1866
0
 done:
1867
0
  ibuf_free(e);
1868
1869
0
  return (ret);
1870
0
}
1871
1872
int
1873
ikev2_validate_cp(struct iked_message *msg, size_t offset, size_t left,
1874
    struct ikev2_cp *cp)
1875
11.6k
{
1876
11.6k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
1877
1878
11.6k
  if (left < sizeof(*cp)) {
1879
3.58k
    log_debug("%s: malformed payload: too short for header "
1880
3.58k
        "(%zu < %zu)", __func__, left, sizeof(*cp));
1881
3.58k
    return (-1);
1882
3.58k
  }
1883
8.11k
  memcpy(cp, msgbuf + offset, sizeof(*cp));
1884
1885
8.11k
  return (0);
1886
11.6k
}
1887
1888
int
1889
ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld,
1890
    struct iked_message *msg, size_t offset, size_t left)
1891
11.6k
{
1892
11.6k
  struct ikev2_cp    cp;
1893
11.6k
  struct ikev2_cfg  *cfg;
1894
11.6k
  struct iked_addr  *addr;
1895
11.6k
  struct sockaddr_in  *in4;
1896
11.6k
  struct sockaddr_in6 *in6;
1897
11.6k
  uint8_t     *msgbuf = ibuf_data(msg->msg_data);
1898
11.6k
  uint8_t     *ptr;
1899
11.6k
  size_t       len;
1900
11.6k
  int      cfg_type;
1901
1902
11.6k
  if (ikev2_validate_cp(msg, offset, left, &cp))
1903
3.58k
    return (-1);
1904
1905
8.11k
  ptr = msgbuf + offset + sizeof(cp);
1906
8.11k
  len = left - sizeof(cp);
1907
1908
8.11k
  log_debug("%s: type %s length %zu",
1909
8.11k
      __func__, print_map(cp.cp_type, ikev2_cp_map), len);
1910
8.11k
  print_hex(ptr, 0, len);
1911
1912
16.4k
  while (len > 0) {
1913
10.1k
    if (len < sizeof(*cfg)) {
1914
367
      log_debug("%s: malformed payload: too short for cfg "
1915
367
          "(%zu < %zu)", __func__, len, sizeof(*cfg));
1916
367
      return (-1);
1917
367
    }
1918
9.74k
    cfg = (struct ikev2_cfg *)ptr;
1919
1920
9.74k
    log_debug("%s: %s 0x%04x length %d", __func__,
1921
9.74k
        print_map(betoh16(cfg->cfg_type), ikev2_cfg_map),
1922
9.74k
        betoh16(cfg->cfg_type),
1923
9.74k
        betoh16(cfg->cfg_length));
1924
1925
9.74k
    ptr += sizeof(*cfg);
1926
9.74k
    len -= sizeof(*cfg);
1927
1928
9.74k
    if (len < betoh16(cfg->cfg_length)) {
1929
1.42k
      log_debug("%s: malformed payload: too short for "
1930
1.42k
          "cfg_length (%zu < %u)", __func__, len,
1931
1.42k
          betoh16(cfg->cfg_length));
1932
1.42k
      return (-1);
1933
1.42k
    }
1934
1935
8.32k
    print_hex(ptr, sizeof(*cfg), betoh16(cfg->cfg_length));
1936
1937
8.32k
    cfg_type = betoh16(cfg->cfg_type);
1938
8.32k
    switch (cfg_type) {
1939
848
    case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1940
1.51k
    case IKEV2_CFG_INTERNAL_IP4_DNS:
1941
1.51k
      if (!ikev2_msg_frompeer(msg))
1942
741
        break;
1943
777
      if (betoh16(cfg->cfg_length) == 0)
1944
309
        break;
1945
      /* XXX multiple-valued */
1946
468
      if (betoh16(cfg->cfg_length) < 4) {
1947
6
        log_debug("%s: malformed payload: too short "
1948
6
            "for ipv4 addr (%u < %u)",
1949
6
            __func__, betoh16(cfg->cfg_length), 4);
1950
6
        return (-1);
1951
6
      }
1952
462
      switch(cfg_type) {
1953
359
      case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1954
359
        if (msg->msg_parent->msg_cp_addr != NULL) {
1955
240
          log_debug("%s: address already set", __func__);
1956
240
          goto skip;
1957
240
        }
1958
119
        break;
1959
119
      case IKEV2_CFG_INTERNAL_IP4_DNS:
1960
103
        if (msg->msg_parent->msg_cp_dns != NULL) {
1961
53
          log_debug("%s: dns already set", __func__);
1962
53
          goto skip;
1963
53
        }
1964
50
        break;
1965
50
      default:
1966
0
        break;
1967
462
      }
1968
169
      if ((addr = calloc(1, sizeof(*addr))) == NULL) {
1969
0
        log_debug("%s: malloc failed", __func__);
1970
0
        break;
1971
0
      }
1972
169
      addr->addr_af = AF_INET;
1973
169
      in4 = (struct sockaddr_in *)&addr->addr;
1974
169
      in4->sin_family = AF_INET;
1975
#ifdef HAVE_SOCKADDR_SA_LEN
1976
      in4->sin_len = sizeof(*in4);
1977
#endif
1978
169
      memcpy(&in4->sin_addr.s_addr, ptr, 4);
1979
169
      switch(cfg_type) {
1980
119
      case IKEV2_CFG_INTERNAL_IP4_ADDRESS:
1981
119
        msg->msg_parent->msg_cp_addr = addr;
1982
119
        log_debug("%s: IP4_ADDRESS %s", __func__,
1983
119
            print_addr(&addr->addr));
1984
119
        break;
1985
50
      case IKEV2_CFG_INTERNAL_IP4_DNS:
1986
50
        msg->msg_parent->msg_cp_dns = addr;
1987
50
        log_debug("%s: IP4_DNS %s", __func__,
1988
50
            print_addr(&addr->addr));
1989
50
        break;
1990
0
      default:
1991
0
        log_debug("%s: cfg %s", __func__,
1992
0
            print_addr(&addr->addr));
1993
0
        break;
1994
169
      }
1995
169
      break;
1996
2.28k
    case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
1997
3.13k
    case IKEV2_CFG_INTERNAL_IP6_DNS:
1998
3.13k
      if (!ikev2_msg_frompeer(msg))
1999
2.90k
        break;
2000
230
      if (betoh16(cfg->cfg_length) == 0)
2001
94
        break;
2002
      /* XXX multiple-valued */
2003
136
      if (betoh16(cfg->cfg_length) < 16) {
2004
5
        log_debug("%s: malformed payload: too short "
2005
5
            "for ipv6 addr w/prefixlen (%u < %u)",
2006
5
            __func__, betoh16(cfg->cfg_length), 16);
2007
5
        return (-1);
2008
5
      }
2009
131
      switch(cfg_type) {
2010
89
      case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
2011
89
        if (msg->msg_parent->msg_cp_addr6 != NULL) {
2012
47
          log_debug("%s: address6 already set", __func__);
2013
47
          goto skip;
2014
47
        }
2015
42
        break;
2016
42
      case IKEV2_CFG_INTERNAL_IP6_DNS:
2017
42
        if (msg->msg_parent->msg_cp_dns != NULL) {
2018
36
          log_debug("%s: dns already set", __func__);
2019
36
          goto skip;
2020
36
        }
2021
6
        break;
2022
131
      }
2023
48
      if ((addr = calloc(1, sizeof(*addr))) == NULL) {
2024
0
        log_debug("%s: malloc failed", __func__);
2025
0
        break;
2026
0
      }
2027
48
      addr->addr_af = AF_INET6;
2028
48
      in6 = (struct sockaddr_in6 *)&addr->addr;
2029
48
      in6->sin6_family = AF_INET6;
2030
#ifdef HAVE_SOCKADDR_SA_LEN
2031
      in6->sin6_len = sizeof(*in6);
2032
#endif
2033
48
      memcpy(&in6->sin6_addr, ptr, 16);
2034
48
      switch(cfg_type) {
2035
42
      case IKEV2_CFG_INTERNAL_IP6_ADDRESS:
2036
42
        msg->msg_parent->msg_cp_addr6 = addr;
2037
42
        log_debug("%s: IP6_ADDRESS %s", __func__,
2038
42
            print_addr(&addr->addr));
2039
42
        break;
2040
6
      case IKEV2_CFG_INTERNAL_IP6_DNS:
2041
6
        msg->msg_parent->msg_cp_dns = addr;
2042
6
        log_debug("%s: IP6_DNS %s", __func__,
2043
6
            print_addr(&addr->addr));
2044
6
        break;
2045
0
      default:
2046
0
        log_debug("%s: cfg %s/%d", __func__,
2047
0
            print_addr(&addr->addr), ptr[16]);
2048
0
        break;
2049
48
      }
2050
48
      break;
2051
8.32k
    }
2052
2053
8.31k
 skip:
2054
8.31k
    ptr += betoh16(cfg->cfg_length);
2055
8.31k
    len -= betoh16(cfg->cfg_length);
2056
8.31k
  }
2057
2058
6.31k
  if (!ikev2_msg_frompeer(msg))
2059
6.10k
    return (0);
2060
2061
207
  msg->msg_parent->msg_cp = cp.cp_type;
2062
2063
207
  return (0);
2064
6.31k
}
2065
2066
int
2067
ikev2_validate_eap(struct iked_message *msg, size_t offset, size_t left,
2068
    struct eap_header *hdr)
2069
21.2k
{
2070
21.2k
  uint8_t   *msgbuf = ibuf_data(msg->msg_data);
2071
2072
21.2k
  if (left < sizeof(*hdr)) {
2073
9.30k
    log_debug("%s: malformed payload: too short for header "
2074
9.30k
        "(%zu < %zu)", __func__, left, sizeof(*hdr));
2075
9.30k
    return (-1);
2076
9.30k
  }
2077
11.9k
  memcpy(hdr, msgbuf + offset, sizeof(*hdr));
2078
2079
11.9k
  return (0);
2080
21.2k
}
2081
2082
int
2083
ikev2_pld_eap(struct iked *env, struct ikev2_payload *pld,
2084
    struct iked_message *msg, size_t offset, size_t left)
2085
21.2k
{
2086
21.2k
  struct eap_header    hdr;
2087
21.2k
  struct eap_message    *eap = NULL;
2088
21.2k
  const struct iked_sa    *sa = msg->msg_sa;
2089
21.2k
  size_t         len;
2090
2091
21.2k
  if (ikev2_validate_eap(msg, offset, left, &hdr))
2092
9.30k
    return (-1);
2093
11.9k
  len = betoh16(hdr.eap_length);
2094
2095
11.9k
  if (len < sizeof(*eap)) {
2096
3.88k
    log_info("%s: %s id %d length %d", SPI_SA(sa, __func__),
2097
3.88k
        print_map(hdr.eap_code, eap_code_map),
2098
3.88k
        hdr.eap_id, betoh16(hdr.eap_length));
2099
8.07k
  } else {
2100
    /* Now try to get the indicated length */
2101
8.07k
    if ((eap = ibuf_seek(msg->msg_data, offset, len)) == NULL) {
2102
4.20k
      log_debug("%s: invalid EAP length", __func__);
2103
4.20k
      return (-1);
2104
4.20k
    }
2105
2106
3.86k
    log_info("%s: %s id %d length %d EAP-%s", SPI_SA(sa, __func__),
2107
3.86k
        print_map(eap->eap_code, eap_code_map),
2108
3.86k
        eap->eap_id, betoh16(eap->eap_length),
2109
3.86k
        print_map(eap->eap_type, eap_type_map));
2110
2111
3.86k
    if (eap_parse(env, sa, msg, eap, msg->msg_response) == -1)
2112
0
      return (-1);
2113
3.86k
    msg->msg_parent->msg_eap.eam_found = 1;
2114
3.86k
  }
2115
2116
7.75k
  return (0);
2117
11.9k
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/imsg_util.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/imsg_util.c.html index b6f52e38e..a4a7852e7 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/imsg_util.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/imsg_util.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/imsg_util.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg_util.c,v 1.21 2023/07/18 15:07:41 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/queue.h>
20
#include <sys/socket.h>
21
#include <sys/uio.h>
22
23
#include <netdb.h>
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <unistd.h>
27
#include <string.h>
28
#include <errno.h>
29
#include <fcntl.h>
30
#include <ctype.h>
31
#include <event.h>
32
33
#include "iked.h"
34
35
/*
36
 * Extending the imsg buffer API for internal use
37
 */
38
39
struct ibuf *
40
ibuf_new(const void *data, size_t len)
41
25.5k
{
42
25.5k
  struct ibuf *buf;
43
44
25.5k
  if ((buf = ibuf_dynamic(len,
45
25.5k
      IKED_MSGBUF_MAX)) == NULL)
46
0
    return (NULL);
47
48
25.5k
  if (len == 0)
49
1.74k
    return (buf);
50
51
23.8k
  if (data == NULL) {
52
0
    if (ibuf_add_zero(buf, len) != 0) {
53
0
      ibuf_free(buf);
54
0
      return (NULL);
55
0
    }
56
23.8k
  } else {
57
23.8k
    if (ibuf_add(buf, data, len) != 0) {
58
0
      ibuf_free(buf);
59
0
      return (NULL);
60
0
    }
61
23.8k
  }
62
63
23.8k
  return (buf);
64
23.8k
}
65
66
struct ibuf *
67
ibuf_static(void)
68
0
{
69
0
  return ibuf_open(IKED_MSGBUF_MAX);
70
0
}
71
72
size_t
73
ibuf_length(struct ibuf *buf)
74
0
{
75
0
  if (buf == NULL)
76
0
    return (0);
77
0
  return (ibuf_size(buf));
78
0
}
79
80
struct ibuf *
81
ibuf_getdata(struct ibuf *buf, size_t len)
82
0
{
83
0
  void  *data;
84
85
0
  if ((data = ibuf_seek(buf, buf->rpos, len)) == NULL)
86
0
    return (NULL);
87
0
  buf->rpos += len;
88
89
0
  return (ibuf_new(data, len));
90
0
}
91
92
struct ibuf *
93
ibuf_dup(struct ibuf *buf)
94
0
{
95
0
  if (buf == NULL)
96
0
    return (NULL);
97
0
  return (ibuf_new(ibuf_data(buf), ibuf_size(buf)));
98
0
}
99
100
struct ibuf *
101
ibuf_random(size_t len)
102
0
{
103
0
  struct ibuf *buf;
104
0
  void    *ptr;
105
106
0
  if ((buf = ibuf_open(len)) == NULL)
107
0
    return (NULL);
108
0
  if ((ptr = ibuf_reserve(buf, len)) == NULL) {
109
0
    ibuf_free(buf);
110
0
    return (NULL);
111
0
  }
112
0
  arc4random_buf(ptr, len);
113
0
  return (buf);
114
0
}
115
116
int
117
ibuf_setsize(struct ibuf *buf, size_t len)
118
0
{
119
0
  if (len > buf->size)
120
0
    return (-1);
121
0
  buf->wpos = len;
122
0
  return (0);
123
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/imsg_util.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: imsg_util.c,v 1.21 2023/07/18 15:07:41 claudio Exp $  */
2
3
/*
4
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/queue.h>
20
#include <sys/socket.h>
21
#include <sys/uio.h>
22
23
#include <netdb.h>
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <unistd.h>
27
#include <string.h>
28
#include <errno.h>
29
#include <fcntl.h>
30
#include <ctype.h>
31
#include <event.h>
32
33
#include "iked.h"
34
35
/*
36
 * Extending the imsg buffer API for internal use
37
 */
38
39
struct ibuf *
40
ibuf_new(const void *data, size_t len)
41
25.5k
{
42
25.5k
  struct ibuf *buf;
43
44
25.5k
  if ((buf = ibuf_dynamic(len,
45
25.5k
      IKED_MSGBUF_MAX)) == NULL)
46
0
    return (NULL);
47
48
25.5k
  if (len == 0)
49
1.74k
    return (buf);
50
51
23.8k
  if (data == NULL) {
52
0
    if (ibuf_add_zero(buf, len) != 0) {
53
0
      ibuf_free(buf);
54
0
      return (NULL);
55
0
    }
56
23.8k
  } else {
57
23.8k
    if (ibuf_add(buf, data, len) != 0) {
58
0
      ibuf_free(buf);
59
0
      return (NULL);
60
0
    }
61
23.8k
  }
62
63
23.8k
  return (buf);
64
23.8k
}
65
66
struct ibuf *
67
ibuf_static(void)
68
0
{
69
0
  return ibuf_open(IKED_MSGBUF_MAX);
70
0
}
71
72
size_t
73
ibuf_length(struct ibuf *buf)
74
0
{
75
0
  if (buf == NULL)
76
0
    return (0);
77
0
  return (ibuf_size(buf));
78
0
}
79
80
struct ibuf *
81
ibuf_getdata(struct ibuf *buf, size_t len)
82
0
{
83
0
  void  *data;
84
85
0
  if ((data = ibuf_seek(buf, buf->rpos, len)) == NULL)
86
0
    return (NULL);
87
0
  buf->rpos += len;
88
89
0
  return (ibuf_new(data, len));
90
0
}
91
92
struct ibuf *
93
ibuf_dup(struct ibuf *buf)
94
0
{
95
0
  if (buf == NULL)
96
0
    return (NULL);
97
0
  return (ibuf_new(ibuf_data(buf), ibuf_size(buf)));
98
0
}
99
100
struct ibuf *
101
ibuf_random(size_t len)
102
0
{
103
0
  struct ibuf *buf;
104
0
  void    *ptr;
105
106
0
  if ((buf = ibuf_open(len)) == NULL)
107
0
    return (NULL);
108
0
  if ((ptr = ibuf_reserve(buf, len)) == NULL) {
109
0
    ibuf_free(buf);
110
0
    return (NULL);
111
0
  }
112
0
  arc4random_buf(ptr, len);
113
0
  return (buf);
114
0
}
115
116
int
117
ibuf_setsize(struct ibuf *buf, size_t len)
118
0
{
119
0
  if (len > buf->size)
120
0
    return (-1);
121
0
  buf->wpos = len;
122
0
  return (0);
123
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/log.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/log.c.html index 289332b21..a8f120030 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/log.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/log.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/log.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: log.c,v 1.12 2017/03/21 12:06:55 bluhm Exp $  */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <stdarg.h>
22
#include <string.h>
23
#include <syslog.h>
24
#include <errno.h>
25
#include <time.h>
26
27
static int   debug;
28
static int   verbose;
29
const char  *log_procname;
30
31
void  log_init(int, int);
32
void  log_procinit(const char *);
33
void  log_setverbose(int);
34
int log_getverbose(void);
35
void  log_warn(const char *, ...)
36
      __attribute__((__format__ (printf, 1, 2)));
37
void  log_warnx(const char *, ...)
38
      __attribute__((__format__ (printf, 1, 2)));
39
void  log_info(const char *, ...)
40
      __attribute__((__format__ (printf, 1, 2)));
41
void  log_debug(const char *, ...)
42
      __attribute__((__format__ (printf, 1, 2)));
43
void  logit(int, const char *, ...)
44
      __attribute__((__format__ (printf, 2, 3)));
45
void  vlog(int, const char *, va_list)
46
      __attribute__((__format__ (printf, 2, 0)));
47
__dead void fatal(const char *, ...)
48
      __attribute__((__format__ (printf, 1, 2)));
49
__dead void fatalx(const char *, ...)
50
      __attribute__((__format__ (printf, 1, 2)));
51
52
void
53
log_init(int n_debug, int facility)
54
0
{
55
0
  extern char *__progname;
56
57
0
  debug = n_debug;
58
0
  verbose = n_debug;
59
0
  log_procinit(__progname);
60
61
0
  if (!debug)
62
0
    openlog(__progname, LOG_PID | LOG_NDELAY, facility);
63
64
0
  tzset();
65
0
}
66
67
void
68
log_procinit(const char *procname)
69
0
{
70
0
  if (procname != NULL)
71
0
    log_procname = procname;
72
0
}
73
74
void
75
log_setverbose(int v)
76
0
{
77
0
  verbose = v;
78
0
}
79
80
int
81
log_getverbose(void)
82
181k
{
83
181k
  return (verbose);
84
181k
}
85
86
void
87
logit(int pri, const char *fmt, ...)
88
0
{
89
0
  va_list ap;
90
91
0
  va_start(ap, fmt);
92
0
  vlog(pri, fmt, ap);
93
0
  va_end(ap);
94
0
}
95
96
void
97
vlog(int pri, const char *fmt, va_list ap)
98
12.8k
{
99
12.8k
  char  *nfmt;
100
12.8k
  int  saved_errno = errno;
101
102
12.8k
  if (debug) {
103
    /* best effort in out of mem situations */
104
0
    if (asprintf(&nfmt, "%s\n", fmt) == -1) {
105
0
      vfprintf(stderr, fmt, ap);
106
0
      fprintf(stderr, "\n");
107
0
    } else {
108
0
      vfprintf(stderr, nfmt, ap);
109
0
      free(nfmt);
110
0
    }
111
0
    fflush(stderr);
112
0
  } else
113
12.8k
    vsyslog(pri, fmt, ap);
114
115
12.8k
  errno = saved_errno;
116
12.8k
}
117
118
void
119
log_warn(const char *emsg, ...)
120
0
{
121
0
  char    *nfmt;
122
0
  va_list    ap;
123
0
  int    saved_errno = errno;
124
125
  /* best effort to even work in out of memory situations */
126
0
  if (emsg == NULL)
127
0
    logit(LOG_ERR, "%s", strerror(saved_errno));
128
0
  else {
129
0
    va_start(ap, emsg);
130
131
0
    if (asprintf(&nfmt, "%s: %s", emsg,
132
0
        strerror(saved_errno)) == -1) {
133
      /* we tried it... */
134
0
      vlog(LOG_ERR, emsg, ap);
135
0
      logit(LOG_ERR, "%s", strerror(saved_errno));
136
0
    } else {
137
0
      vlog(LOG_ERR, nfmt, ap);
138
0
      free(nfmt);
139
0
    }
140
0
    va_end(ap);
141
0
  }
142
143
0
  errno = saved_errno;
144
0
}
145
146
void
147
log_warnx(const char *emsg, ...)
148
0
{
149
0
  va_list  ap;
150
151
0
  va_start(ap, emsg);
152
0
  vlog(LOG_ERR, emsg, ap);
153
0
  va_end(ap);
154
0
}
155
156
void
157
log_info(const char *emsg, ...)
158
12.8k
{
159
12.8k
  va_list  ap;
160
161
12.8k
  va_start(ap, emsg);
162
12.8k
  vlog(LOG_INFO, emsg, ap);
163
12.8k
  va_end(ap);
164
12.8k
}
165
166
void
167
log_debug(const char *emsg, ...)
168
687k
{
169
687k
  va_list  ap;
170
171
687k
  if (verbose > 1) {
172
0
    va_start(ap, emsg);
173
0
    vlog(LOG_DEBUG, emsg, ap);
174
0
    va_end(ap);
175
0
  }
176
687k
}
177
178
static void
179
vfatalc(int code, const char *emsg, va_list ap)
180
0
{
181
0
  static char s[BUFSIZ];
182
0
  const char  *sep;
183
184
0
  if (emsg != NULL) {
185
0
    (void)vsnprintf(s, sizeof(s), emsg, ap);
186
0
    sep = ": ";
187
0
  } else {
188
0
    s[0] = '\0';
189
0
    sep = "";
190
0
  }
191
0
  if (code)
192
0
    logit(LOG_CRIT, "%s: %s%s%s",
193
0
        log_procname, s, sep, strerror(code));
194
0
  else
195
0
    logit(LOG_CRIT, "%s%s%s", log_procname, sep, s);
196
0
}
197
198
void
199
fatal(const char *emsg, ...)
200
0
{
201
0
  va_list ap;
202
203
0
  va_start(ap, emsg);
204
0
  vfatalc(errno, emsg, ap);
205
0
  va_end(ap);
206
0
  exit(1);
207
0
}
208
209
void
210
fatalx(const char *emsg, ...)
211
0
{
212
0
  va_list ap;
213
214
0
  va_start(ap, emsg);
215
0
  vfatalc(0, emsg, ap);
216
0
  va_end(ap);
217
0
  exit(1);
218
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/log.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: log.c,v 1.12 2017/03/21 12:06:55 bluhm Exp $  */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <stdarg.h>
22
#include <string.h>
23
#include <syslog.h>
24
#include <errno.h>
25
#include <time.h>
26
27
static int   debug;
28
static int   verbose;
29
const char  *log_procname;
30
31
void  log_init(int, int);
32
void  log_procinit(const char *);
33
void  log_setverbose(int);
34
int log_getverbose(void);
35
void  log_warn(const char *, ...)
36
      __attribute__((__format__ (printf, 1, 2)));
37
void  log_warnx(const char *, ...)
38
      __attribute__((__format__ (printf, 1, 2)));
39
void  log_info(const char *, ...)
40
      __attribute__((__format__ (printf, 1, 2)));
41
void  log_debug(const char *, ...)
42
      __attribute__((__format__ (printf, 1, 2)));
43
void  logit(int, const char *, ...)
44
      __attribute__((__format__ (printf, 2, 3)));
45
void  vlog(int, const char *, va_list)
46
      __attribute__((__format__ (printf, 2, 0)));
47
__dead void fatal(const char *, ...)
48
      __attribute__((__format__ (printf, 1, 2)));
49
__dead void fatalx(const char *, ...)
50
      __attribute__((__format__ (printf, 1, 2)));
51
52
void
53
log_init(int n_debug, int facility)
54
0
{
55
0
  extern char *__progname;
56
57
0
  debug = n_debug;
58
0
  verbose = n_debug;
59
0
  log_procinit(__progname);
60
61
0
  if (!debug)
62
0
    openlog(__progname, LOG_PID | LOG_NDELAY, facility);
63
64
0
  tzset();
65
0
}
66
67
void
68
log_procinit(const char *procname)
69
0
{
70
0
  if (procname != NULL)
71
0
    log_procname = procname;
72
0
}
73
74
void
75
log_setverbose(int v)
76
0
{
77
0
  verbose = v;
78
0
}
79
80
int
81
log_getverbose(void)
82
181k
{
83
181k
  return (verbose);
84
181k
}
85
86
void
87
logit(int pri, const char *fmt, ...)
88
0
{
89
0
  va_list ap;
90
91
0
  va_start(ap, fmt);
92
0
  vlog(pri, fmt, ap);
93
0
  va_end(ap);
94
0
}
95
96
void
97
vlog(int pri, const char *fmt, va_list ap)
98
12.8k
{
99
12.8k
  char  *nfmt;
100
12.8k
  int  saved_errno = errno;
101
102
12.8k
  if (debug) {
103
    /* best effort in out of mem situations */
104
0
    if (asprintf(&nfmt, "%s\n", fmt) == -1) {
105
0
      vfprintf(stderr, fmt, ap);
106
0
      fprintf(stderr, "\n");
107
0
    } else {
108
0
      vfprintf(stderr, nfmt, ap);
109
0
      free(nfmt);
110
0
    }
111
0
    fflush(stderr);
112
0
  } else
113
12.8k
    vsyslog(pri, fmt, ap);
114
115
12.8k
  errno = saved_errno;
116
12.8k
}
117
118
void
119
log_warn(const char *emsg, ...)
120
0
{
121
0
  char    *nfmt;
122
0
  va_list    ap;
123
0
  int    saved_errno = errno;
124
125
  /* best effort to even work in out of memory situations */
126
0
  if (emsg == NULL)
127
0
    logit(LOG_ERR, "%s", strerror(saved_errno));
128
0
  else {
129
0
    va_start(ap, emsg);
130
131
0
    if (asprintf(&nfmt, "%s: %s", emsg,
132
0
        strerror(saved_errno)) == -1) {
133
      /* we tried it... */
134
0
      vlog(LOG_ERR, emsg, ap);
135
0
      logit(LOG_ERR, "%s", strerror(saved_errno));
136
0
    } else {
137
0
      vlog(LOG_ERR, nfmt, ap);
138
0
      free(nfmt);
139
0
    }
140
0
    va_end(ap);
141
0
  }
142
143
0
  errno = saved_errno;
144
0
}
145
146
void
147
log_warnx(const char *emsg, ...)
148
0
{
149
0
  va_list  ap;
150
151
0
  va_start(ap, emsg);
152
0
  vlog(LOG_ERR, emsg, ap);
153
0
  va_end(ap);
154
0
}
155
156
void
157
log_info(const char *emsg, ...)
158
12.8k
{
159
12.8k
  va_list  ap;
160
161
12.8k
  va_start(ap, emsg);
162
12.8k
  vlog(LOG_INFO, emsg, ap);
163
12.8k
  va_end(ap);
164
12.8k
}
165
166
void
167
log_debug(const char *emsg, ...)
168
687k
{
169
687k
  va_list  ap;
170
171
687k
  if (verbose > 1) {
172
0
    va_start(ap, emsg);
173
0
    vlog(LOG_DEBUG, emsg, ap);
174
0
    va_end(ap);
175
0
  }
176
687k
}
177
178
static void
179
vfatalc(int code, const char *emsg, va_list ap)
180
0
{
181
0
  static char s[BUFSIZ];
182
0
  const char  *sep;
183
184
0
  if (emsg != NULL) {
185
0
    (void)vsnprintf(s, sizeof(s), emsg, ap);
186
0
    sep = ": ";
187
0
  } else {
188
0
    s[0] = '\0';
189
0
    sep = "";
190
0
  }
191
0
  if (code)
192
0
    logit(LOG_CRIT, "%s: %s%s%s",
193
0
        log_procname, s, sep, strerror(code));
194
0
  else
195
0
    logit(LOG_CRIT, "%s%s%s", log_procname, sep, s);
196
0
}
197
198
void
199
fatal(const char *emsg, ...)
200
0
{
201
0
  va_list ap;
202
203
0
  va_start(ap, emsg);
204
0
  vfatalc(errno, emsg, ap);
205
0
  va_end(ap);
206
0
  exit(1);
207
0
}
208
209
void
210
fatalx(const char *emsg, ...)
211
0
{
212
0
  va_list ap;
213
214
0
  va_start(ap, emsg);
215
0
  vfatalc(0, emsg, ap);
216
0
  va_end(ap);
217
0
  exit(1);
218
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/types.h.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/types.h.html index c10cb2916..c9b88ea7d 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/types.h.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/types.h.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/types.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: types.h,v 1.52 2023/03/04 22:22:51 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#ifndef IKED_TYPES_H
21
#define IKED_TYPES_H
22
23
#ifndef IKED_USER
24
#define IKED_USER   "_iked"
25
#endif
26
27
#ifndef IKED_CONFIG
28
#define IKED_CONFIG   "/etc/iked.conf"
29
#endif
30
31
#define IKED_SOCKET   "/var/run/iked.sock"
32
33
#ifndef IKED_CA
34
#define IKED_CA     "/etc/iked/"
35
#endif
36
37
#define IKED_CA_DIR   "ca/"
38
#define IKED_CRL_DIR    "crls/"
39
#define IKED_CERT_DIR   "certs/"
40
#define IKED_PUBKEY_DIR   "pubkeys/"
41
#define IKED_PRIVKEY    IKED_CA "private/local.key"
42
#define IKED_PUBKEY   "local.pub"
43
44
#define IKED_VENDOR_ID    "OpenIKED-"
45
46
#define IKED_OCSP_RESPCERT  "ocsp/responder.crt"
47
48
#define IKED_OPT_VERBOSE  0x00000001
49
#define IKED_OPT_NOACTION 0x00000002
50
#define IKED_OPT_PASSIVE  0x00000004
51
52
#define IKED_IKE_PORT   500
53
#define IKED_NATT_PORT    4500
54
55
#define IKED_NONCE_MIN    16  /* XXX 128 bits */
56
#define IKED_NONCE_SIZE   32  /* XXX 256 bits */
57
58
0
#define IKED_COOKIE_MIN   1  /* min 1 bytes */
59
0
#define IKED_COOKIE_MAX   64  /* max 64 bytes */
60
61
0
#define IKED_COOKIE2_MIN  8  /* min 8 bytes */
62
0
#define IKED_COOKIE2_MAX  64  /* max 64 bytes */
63
64
#define IKED_ID_SIZE    1024  /* XXX should be dynamic */
65
#define IKED_PSK_SIZE   1024  /* XXX should be dynamic */
66
25.5k
#define IKED_MSGBUF_MAX   8192
67
#define IKED_CFG_MAX    16  /* maximum CP attributes */
68
#define IKED_IPPROTO_MAX  16
69
#define IKED_TAG_SIZE   64
70
902k
#define IKED_CYCLE_BUFFERS  8  /* # of static buffers for mapping */
71
#define IKED_PASSWORD_SIZE  256 /* limited by most EAP types */
72
73
#define IKED_LIFETIME_BYTES 4294967296ULL /* 4 GB */
74
#define IKED_LIFETIME_SECONDS 10800     /* 3 hours */
75
76
242k
#define IKED_E      0x1000  /* Decrypted flag */
77
78
struct iked_constmap {
79
  unsigned int   cm_type;
80
  const char  *cm_name;
81
  const char  *cm_descr;
82
};
83
84
struct iked_transform {
85
  uint8_t        xform_type;
86
  uint16_t       xform_id;
87
  uint16_t       xform_length;
88
  uint16_t       xform_keylength;
89
  unsigned int       xform_score;
90
  struct iked_constmap    *xform_map;
91
};
92
93
enum imsg_type {
94
  IMSG_NONE,
95
  IMSG_CTL_OK,
96
  IMSG_CTL_FAIL,
97
  IMSG_CTL_VERBOSE,
98
  IMSG_CTL_NOTIFY,
99
  IMSG_CTL_RELOAD,
100
  IMSG_CTL_RESET,
101
  IMSG_CTL_COUPLE,
102
  IMSG_CTL_DECOUPLE,
103
  IMSG_CTL_ACTIVE,
104
  IMSG_CTL_PASSIVE,
105
  IMSG_CTL_RESET_ID,
106
  IMSG_CTL_SHOW_SA,
107
  IMSG_CTL_STATIC,
108
  IMSG_COMPILE,
109
  IMSG_UDP_SOCKET,
110
  IMSG_PFKEY_SOCKET,
111
  IMSG_IKE_MESSAGE,
112
  IMSG_CFG_POLICY,
113
  IMSG_CFG_FLOW,
114
  IMSG_CFG_USER,
115
  IMSG_CERTREQ,
116
  IMSG_CERT,
117
  IMSG_CERTVALID,
118
  IMSG_CERTINVALID,
119
  IMSG_CERT_PARTIAL_CHAIN,
120
  IMSG_SCERT,
121
  IMSG_IF_ADDADDR,
122
  IMSG_IF_DELADDR,
123
  IMSG_VROUTE_ADD,
124
  IMSG_VROUTE_DEL,
125
  IMSG_VROUTE_CLONE,
126
  IMSG_VDNS_ADD,
127
  IMSG_VDNS_DEL,
128
  IMSG_OCSP_FD,
129
  IMSG_OCSP_CFG,
130
  IMSG_AUTH,
131
  IMSG_PRIVKEY,
132
  IMSG_PUBKEY,
133
  IMSG_CTL_SHOW_CERTSTORE,
134
  IMSG_CTL_SHOW_STATS,
135
  IMSG_CTL_PROCFD,
136
};
137
138
enum privsep_procid {
139
  PROC_PARENT = 0,
140
  PROC_CONTROL,
141
  PROC_CERT,
142
  PROC_IKEV2,
143
  PROC_MAX
144
};
145
146
enum flushmode {
147
  RESET_RELOAD  = 0,
148
  RESET_ALL,
149
  RESET_CA,
150
  RESET_POLICY,
151
  RESET_SA,
152
  RESET_USER,
153
};
154
155
#ifndef nitems
156
#define nitems(_a)   (sizeof((_a)) / sizeof((_a)[0]))
157
#endif
158
159
#endif /* IKED_TYPES_H */
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/types.h
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: types.h,v 1.52 2023/03/04 22:22:51 tobhe Exp $  */
2
3
/*
4
 * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#ifndef IKED_TYPES_H
21
#define IKED_TYPES_H
22
23
#ifndef IKED_USER
24
#define IKED_USER   "_iked"
25
#endif
26
27
#ifndef IKED_CONFIG
28
#define IKED_CONFIG   "/etc/iked.conf"
29
#endif
30
31
#define IKED_SOCKET   "/var/run/iked.sock"
32
33
#ifndef IKED_CA
34
#define IKED_CA     "/etc/iked/"
35
#endif
36
37
#define IKED_CA_DIR   "ca/"
38
#define IKED_CRL_DIR    "crls/"
39
#define IKED_CERT_DIR   "certs/"
40
#define IKED_PUBKEY_DIR   "pubkeys/"
41
#define IKED_PRIVKEY    IKED_CA "private/local.key"
42
#define IKED_PUBKEY   "local.pub"
43
44
#define IKED_VENDOR_ID    "OpenIKED-"
45
46
#define IKED_OCSP_RESPCERT  "ocsp/responder.crt"
47
48
#define IKED_OPT_VERBOSE  0x00000001
49
#define IKED_OPT_NOACTION 0x00000002
50
#define IKED_OPT_PASSIVE  0x00000004
51
52
#define IKED_IKE_PORT   500
53
#define IKED_NATT_PORT    4500
54
55
#define IKED_NONCE_MIN    16  /* XXX 128 bits */
56
#define IKED_NONCE_SIZE   32  /* XXX 256 bits */
57
58
0
#define IKED_COOKIE_MIN   1  /* min 1 bytes */
59
0
#define IKED_COOKIE_MAX   64  /* max 64 bytes */
60
61
0
#define IKED_COOKIE2_MIN  8  /* min 8 bytes */
62
0
#define IKED_COOKIE2_MAX  64  /* max 64 bytes */
63
64
#define IKED_ID_SIZE    1024  /* XXX should be dynamic */
65
#define IKED_PSK_SIZE   1024  /* XXX should be dynamic */
66
25.5k
#define IKED_MSGBUF_MAX   8192
67
#define IKED_CFG_MAX    16  /* maximum CP attributes */
68
#define IKED_IPPROTO_MAX  16
69
#define IKED_TAG_SIZE   64
70
902k
#define IKED_CYCLE_BUFFERS  8  /* # of static buffers for mapping */
71
#define IKED_PASSWORD_SIZE  256 /* limited by most EAP types */
72
73
#define IKED_LIFETIME_BYTES 4294967296ULL /* 4 GB */
74
#define IKED_LIFETIME_SECONDS 10800     /* 3 hours */
75
76
242k
#define IKED_E      0x1000  /* Decrypted flag */
77
78
struct iked_constmap {
79
  unsigned int   cm_type;
80
  const char  *cm_name;
81
  const char  *cm_descr;
82
};
83
84
struct iked_transform {
85
  uint8_t        xform_type;
86
  uint16_t       xform_id;
87
  uint16_t       xform_length;
88
  uint16_t       xform_keylength;
89
  unsigned int       xform_score;
90
  struct iked_constmap    *xform_map;
91
};
92
93
enum imsg_type {
94
  IMSG_NONE,
95
  IMSG_CTL_OK,
96
  IMSG_CTL_FAIL,
97
  IMSG_CTL_VERBOSE,
98
  IMSG_CTL_NOTIFY,
99
  IMSG_CTL_RELOAD,
100
  IMSG_CTL_RESET,
101
  IMSG_CTL_COUPLE,
102
  IMSG_CTL_DECOUPLE,
103
  IMSG_CTL_ACTIVE,
104
  IMSG_CTL_PASSIVE,
105
  IMSG_CTL_RESET_ID,
106
  IMSG_CTL_SHOW_SA,
107
  IMSG_CTL_STATIC,
108
  IMSG_COMPILE,
109
  IMSG_UDP_SOCKET,
110
  IMSG_PFKEY_SOCKET,
111
  IMSG_IKE_MESSAGE,
112
  IMSG_CFG_POLICY,
113
  IMSG_CFG_FLOW,
114
  IMSG_CFG_USER,
115
  IMSG_CERTREQ,
116
  IMSG_CERT,
117
  IMSG_CERTVALID,
118
  IMSG_CERTINVALID,
119
  IMSG_CERT_PARTIAL_CHAIN,
120
  IMSG_SCERT,
121
  IMSG_IF_ADDADDR,
122
  IMSG_IF_DELADDR,
123
  IMSG_VROUTE_ADD,
124
  IMSG_VROUTE_DEL,
125
  IMSG_VROUTE_CLONE,
126
  IMSG_VDNS_ADD,
127
  IMSG_VDNS_DEL,
128
  IMSG_OCSP_FD,
129
  IMSG_OCSP_CFG,
130
  IMSG_AUTH,
131
  IMSG_PRIVKEY,
132
  IMSG_PUBKEY,
133
  IMSG_CTL_SHOW_CERTSTORE,
134
  IMSG_CTL_SHOW_STATS,
135
  IMSG_CTL_PROCFD,
136
};
137
138
enum privsep_procid {
139
  PROC_PARENT = 0,
140
  PROC_CONTROL,
141
  PROC_CERT,
142
  PROC_IKEV2,
143
  PROC_MAX
144
};
145
146
enum flushmode {
147
  RESET_RELOAD  = 0,
148
  RESET_ALL,
149
  RESET_CA,
150
  RESET_POLICY,
151
  RESET_SA,
152
  RESET_USER,
153
};
154
155
#ifndef nitems
156
#define nitems(_a)   (sizeof((_a)) / sizeof((_a)[0]))
157
#endif
158
159
#endif /* IKED_TYPES_H */
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/util.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/util.c.html index 01423c044..f82c19f39 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/util.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/iked/util.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/iked/util.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: util.c,v 1.43 2023/07/28 11:23:03 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2021 Tobias Heider <tobhe@openbsd.org>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/queue.h>
22
#include <sys/socket.h>
23
#include <sys/uio.h>
24
25
#include <netinet/in.h>
26
#include <netinet/ip_ipsp.h>
27
28
#include <netdb.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <unistd.h>
32
#include <string.h>
33
#include <errno.h>
34
#include <limits.h>
35
#include <fcntl.h>
36
#include <ctype.h>
37
#include <event.h>
38
39
#include "iked.h"
40
#include "ikev2.h"
41
42
int
43
socket_af(struct sockaddr *sa, in_port_t port)
44
0
{
45
0
  errno = 0;
46
0
  switch (sa->sa_family) {
47
0
  case AF_INET:
48
0
    ((struct sockaddr_in *)sa)->sin_port = port;
49
#ifdef HAVE_SOCKADDR_SA_LEN
50
    ((struct sockaddr_in *)sa)->sin_len =
51
        sizeof(struct sockaddr_in);
52
#endif
53
0
    break;
54
0
  case AF_INET6:
55
0
    ((struct sockaddr_in6 *)sa)->sin6_port = port;
56
#ifdef HAVE_SOCKADDR_SA_LEN
57
    ((struct sockaddr_in6 *)sa)->sin6_len =
58
        sizeof(struct sockaddr_in6);
59
#endif
60
0
    break;
61
0
  default:
62
0
    errno = EPFNOSUPPORT;
63
0
    return (-1);
64
0
  }
65
66
0
  return (0);
67
0
}
68
69
in_port_t
70
socket_getport(struct sockaddr *sa)
71
19.8k
{
72
19.8k
  switch (sa->sa_family) {
73
17.1k
  case AF_INET:
74
17.1k
    return (ntohs(((struct sockaddr_in *)sa)->sin_port));
75
2.63k
  case AF_INET6:
76
2.63k
    return (ntohs(((struct sockaddr_in6 *)sa)->sin6_port));
77
0
  default:
78
0
    return (0);
79
19.8k
  }
80
81
  /* NOTREACHED */
82
0
  return (0);
83
19.8k
}
84
85
int
86
socket_setport(struct sockaddr *sa, in_port_t port)
87
0
{
88
0
  switch (sa->sa_family) {
89
0
  case AF_INET:
90
0
    ((struct sockaddr_in *)sa)->sin_port = htons(port);
91
0
    break;
92
0
  case AF_INET6:
93
0
    ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
94
0
    break;
95
0
  default:
96
0
    return (-1);
97
0
  }
98
0
  return (0);
99
0
}
100
101
int
102
socket_getaddr(int s, struct sockaddr_storage *ss)
103
0
{
104
0
  socklen_t sslen = sizeof(*ss);
105
106
0
  return (getsockname(s, (struct sockaddr *)ss, &sslen));
107
0
}
108
109
int
110
socket_bypass(int s, struct sockaddr *sa)
111
0
{
112
#if defined(__OpenBSD__)
113
  int  v, *a;
114
  int  a4[] = {
115
        IPPROTO_IP,
116
        IP_AUTH_LEVEL,
117
        IP_ESP_TRANS_LEVEL,
118
        IP_ESP_NETWORK_LEVEL,
119
#ifdef IPV6_IPCOMP_LEVEL
120
        IP_IPCOMP_LEVEL
121
#endif
122
  };
123
  int  a6[] = {
124
        IPPROTO_IPV6,
125
        IPV6_AUTH_LEVEL,
126
        IPV6_ESP_TRANS_LEVEL,
127
        IPV6_ESP_NETWORK_LEVEL,
128
#ifdef IPV6_IPCOMP_LEVEL
129
        IPV6_IPCOMP_LEVEL
130
#endif
131
  };
132
133
  switch (sa->sa_family) {
134
  case AF_INET:
135
    a = a4;
136
    break;
137
  case AF_INET6:
138
    a = a6;
139
    break;
140
  default:
141
    log_warn("%s: invalid address family", __func__);
142
    return (-1);
143
  }
144
145
  v = IPSEC_LEVEL_BYPASS;
146
  if (setsockopt(s, a[0], a[1], &v, sizeof(v)) == -1) {
147
    log_warn("%s: AUTH_LEVEL", __func__);
148
    return (-1);
149
  }
150
  if (setsockopt(s, a[0], a[2], &v, sizeof(v)) == -1) {
151
    log_warn("%s: ESP_TRANS_LEVEL", __func__);
152
    return (-1);
153
  }
154
  if (setsockopt(s, a[0], a[3], &v, sizeof(v)) == -1) {
155
    log_warn("%s: ESP_NETWORK_LEVEL", __func__);
156
    return (-1);
157
  }
158
#ifdef IP_IPCOMP_LEVEL
159
  if (setsockopt(s, a[0], a[4], &v, sizeof(v)) == -1) {
160
    log_warn("%s: IPCOMP_LEVEL", __func__);
161
    return (-1);
162
  }
163
#endif
164
#else /* __OpenBSD__ */
165
0
  int *a;
166
0
  int  a4[] = {
167
0
        IPPROTO_IP,
168
0
        IP_IPSEC_POLICY
169
0
  };
170
0
  int  a6[] = {
171
0
        IPPROTO_IPV6,
172
0
        IPV6_IPSEC_POLICY,
173
0
  };
174
0
  struct sadb_x_policy pol = {
175
0
        SADB_UPDATE,
176
0
        SADB_EXT_SENSITIVITY,
177
0
        IPSEC_POLICY_BYPASS,
178
0
        0, 0, 0, 0
179
0
  };
180
181
0
  switch (sa->sa_family) {
182
0
  case AF_INET:
183
0
    a = a4;
184
0
    break;
185
0
  case AF_INET6:
186
0
    a = a6;
187
0
    break;
188
0
  default:
189
0
    log_warn("%s: invalid address family", __func__);
190
0
    return (-1);
191
0
  }
192
193
0
  pol.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
194
0
  if (setsockopt(s, a[0], a[1], &pol, sizeof(pol)) == -1) {
195
0
    log_warn("%s: IPSEC_DIR_INBOUND", __func__);
196
0
    return (-1);
197
0
  }
198
0
  pol.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
199
0
  if (setsockopt(s, a[0], a[1], &pol, sizeof(pol)) == -1) {
200
0
    log_warn("%s: IPSEC_DIR_OUTBOUND", __func__);
201
0
    return (-1);
202
0
  }
203
0
#endif /* !__OpenBSD__ */
204
205
0
  return (0);
206
0
}
207
208
int
209
udp_bind(struct sockaddr *sa, in_port_t port)
210
0
{
211
0
  int  s, val;
212
213
0
  if (socket_af(sa, port) == -1) {
214
0
    log_warn("%s: failed to set UDP port", __func__);
215
0
    return (-1);
216
0
  }
217
218
0
  if ((s = socket(sa->sa_family,
219
0
      SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP)) == -1) {
220
0
    log_warn("%s: failed to get UDP socket", __func__);
221
0
    return (-1);
222
0
  }
223
224
  /* Skip IPsec processing (don't encrypt) for IKE messages */
225
0
  if (socket_bypass(s, sa) == -1) {
226
0
    log_warn("%s: failed to bypass IPsec on IKE socket",
227
0
        __func__);
228
0
    goto bad;
229
0
  }
230
231
0
  val = 1;
232
0
  if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(int)) == -1) {
233
0
    log_warn("%s: failed to set reuseport", __func__);
234
0
    goto bad;
235
0
  }
236
0
  val = 1;
237
0
  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int)) == -1) {
238
0
    log_warn("%s: failed to set reuseaddr", __func__);
239
0
    goto bad;
240
0
  }
241
242
0
  if (sa->sa_family == AF_INET) {
243
0
#if defined(IP_RECVORIGDSTADDR)
244
0
    val = 1;
245
0
    if (setsockopt(s, IPPROTO_IP, IP_RECVORIGDSTADDR,
246
0
        &val, sizeof(int)) == -1) {
247
0
      log_warn("%s: failed to set IPv4 packet info",
248
0
          __func__);
249
0
      goto bad;
250
0
    }
251
#elif defined(IP_RECVDSTADDR)
252
    val = 1;
253
    if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
254
        &val, sizeof(int)) == -1) {
255
      log_warn("%s: failed to set IPv4 packet info",
256
          __func__);
257
      goto bad;
258
    }
259
#endif
260
0
  } else {
261
0
#ifdef IPV6_RECVPKTINFO
262
0
    val = 1;
263
0
    if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
264
0
        &val, sizeof(int)) == -1) {
265
0
      log_warn("%s: failed to set IPv6 packet info",
266
0
          __func__);
267
0
      goto bad;
268
0
    }
269
0
#endif
270
0
  }
271
272
0
  if (bind(s, sa, SA_LEN(sa)) == -1) {
273
0
    log_warn("%s: failed to bind UDP socket", __func__);
274
0
    goto bad;
275
0
  }
276
277
0
  return (s);
278
0
 bad:
279
0
  close(s);
280
0
  return (-1);
281
0
}
282
283
int
284
sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen)
285
0
{
286
0
  struct sockaddr_in  *a4, *b4;
287
0
  struct sockaddr_in6 *a6, *b6;
288
0
  uint32_t     av[4], bv[4], mv[4];
289
290
0
  if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC)
291
0
    return (0);
292
0
  else if (a->sa_family > b->sa_family)
293
0
    return (1);
294
0
  else if (a->sa_family < b->sa_family)
295
0
    return (-1);
296
297
0
  if (prefixlen == -1)
298
0
    memset(&mv, 0xff, sizeof(mv));
299
300
0
  switch (a->sa_family) {
301
0
  case AF_INET:
302
0
    a4 = (struct sockaddr_in *)a;
303
0
    b4 = (struct sockaddr_in *)b;
304
305
0
    av[0] = a4->sin_addr.s_addr;
306
0
    bv[0] = b4->sin_addr.s_addr;
307
0
    if (prefixlen != -1)
308
0
      mv[0] = prefixlen2mask(prefixlen);
309
310
0
    if ((av[0] & mv[0]) > (bv[0] & mv[0]))
311
0
      return (1);
312
0
    if ((av[0] & mv[0]) < (bv[0] & mv[0]))
313
0
      return (-1);
314
0
    break;
315
0
  case AF_INET6:
316
0
    a6 = (struct sockaddr_in6 *)a;
317
0
    b6 = (struct sockaddr_in6 *)b;
318
319
0
    memcpy(&av, &a6->sin6_addr.s6_addr, 16);
320
0
    memcpy(&bv, &b6->sin6_addr.s6_addr, 16);
321
0
    if (prefixlen != -1)
322
0
      prefixlen2mask6(prefixlen, mv);
323
324
0
    if ((av[3] & mv[3]) > (bv[3] & mv[3]))
325
0
      return (1);
326
0
    if ((av[3] & mv[3]) < (bv[3] & mv[3]))
327
0
      return (-1);
328
0
    if ((av[2] & mv[2]) > (bv[2] & mv[2]))
329
0
      return (1);
330
0
    if ((av[2] & mv[2]) < (bv[2] & mv[2]))
331
0
      return (-1);
332
0
    if ((av[1] & mv[1]) > (bv[1] & mv[1]))
333
0
      return (1);
334
0
    if ((av[1] & mv[1]) < (bv[1] & mv[1]))
335
0
      return (-1);
336
0
    if ((av[0] & mv[0]) > (bv[0] & mv[0]))
337
0
      return (1);
338
0
    if ((av[0] & mv[0]) < (bv[0] & mv[0]))
339
0
      return (-1);
340
0
    break;
341
0
  }
342
343
0
  return (0);
344
0
}
345
346
ssize_t
347
sendtofrom(int s, void *buf, size_t len, int flags, struct sockaddr *to,
348
    socklen_t tolen, struct sockaddr *from, socklen_t fromlen)
349
0
{
350
0
  struct iovec     iov;
351
0
  struct msghdr    msg;
352
0
  struct cmsghdr    *cmsg;
353
#ifdef IP_SENDSRCADDR
354
  struct sockaddr_in  *in;
355
#endif
356
0
#ifdef IPV6_PKTINFO
357
0
  struct in6_pktinfo  *pkt6;
358
0
  struct sockaddr_in6 *in6;
359
0
#endif
360
0
  union {
361
0
    struct cmsghdr  hdr;
362
0
    char    inbuf[CMSG_SPACE(sizeof(struct in_addr))];
363
0
    char    in6buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
364
0
  } cmsgbuf;
365
366
0
  bzero(&msg, sizeof(msg));
367
0
  bzero(&cmsgbuf, sizeof(cmsgbuf));
368
369
0
  iov.iov_base = buf;
370
0
  iov.iov_len = len;
371
0
  msg.msg_iov = &iov;
372
0
  msg.msg_iovlen = 1;
373
0
  msg.msg_name = to;
374
0
  msg.msg_namelen = tolen;
375
0
  msg.msg_controllen = 0;
376
377
0
  switch (to->sa_family) {
378
0
  case AF_INET:
379
#ifdef IP_SENDSRCADDR
380
    in = (struct sockaddr_in *)from;
381
    if (in->sin_addr.s_addr == INADDR_ANY)
382
      break;
383
    msg.msg_control = &cmsgbuf;
384
    msg.msg_controllen += sizeof(cmsgbuf.inbuf);
385
    cmsg = CMSG_FIRSTHDR(&msg);
386
    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
387
    cmsg->cmsg_level = IPPROTO_IP;
388
    cmsg->cmsg_type = IP_SENDSRCADDR;
389
    memcpy(CMSG_DATA(cmsg), &in->sin_addr, sizeof(struct in_addr));
390
#endif
391
0
    break;
392
0
  case AF_INET6:
393
0
#ifdef IPV6_PKTINFO
394
0
    msg.msg_control = &cmsgbuf;
395
0
    msg.msg_controllen += sizeof(cmsgbuf.in6buf);
396
0
    cmsg = CMSG_FIRSTHDR(&msg);
397
0
    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
398
0
    cmsg->cmsg_level = IPPROTO_IPV6;
399
0
    cmsg->cmsg_type = IPV6_PKTINFO;
400
0
    in6 = (struct sockaddr_in6 *)from;
401
0
    pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
402
0
    pkt6->ipi6_addr = in6->sin6_addr;
403
0
#endif
404
0
    break;
405
0
  }
406
407
0
  return sendmsg(s, &msg, flags);
408
0
}
409
410
ssize_t
411
recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from,
412
    socklen_t *fromlen, struct sockaddr *to, socklen_t *tolen)
413
0
{
414
0
  struct iovec     iov;
415
0
  struct msghdr    msg;
416
0
  struct cmsghdr    *cmsg;
417
#if !defined(IP_RECVORIGDSTADDR) && defined(IP_RECVDSTADDR)
418
  struct sockaddr_in  *in;
419
#endif
420
0
#ifdef IPV6_PKTINFO
421
0
  struct in6_pktinfo  *pkt6;
422
0
  struct sockaddr_in6 *in6;
423
0
#endif
424
0
  ssize_t      ret;
425
0
  union {
426
0
    struct cmsghdr hdr;
427
0
    char  buf[CMSG_SPACE(sizeof(struct sockaddr_storage))];
428
0
  } cmsgbuf;
429
430
0
  bzero(&msg, sizeof(msg));
431
0
  bzero(&cmsgbuf.buf, sizeof(cmsgbuf.buf));
432
433
0
  iov.iov_base = buf;
434
0
  iov.iov_len = len;
435
0
  msg.msg_iov = &iov;
436
0
  msg.msg_iovlen = 1;
437
0
  msg.msg_name = from;
438
0
  msg.msg_namelen = *fromlen;
439
0
  msg.msg_control = &cmsgbuf.buf;
440
0
  msg.msg_controllen = sizeof(cmsgbuf.buf);
441
442
0
  if ((ret = recvmsg(s, &msg, flags)) == -1)
443
0
    return (-1);
444
445
0
  *fromlen = SA_LEN(from);
446
447
0
  if (getsockname(s, to, tolen) != 0)
448
0
    *tolen = 0;
449
450
0
  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
451
0
      cmsg = CMSG_NXTHDR(&msg, cmsg)) {
452
0
    switch (from->sa_family) {
453
0
    case AF_INET:
454
0
#if defined(IP_RECVORIGDSTADDR)
455
0
      if (cmsg->cmsg_level == IPPROTO_IP &&
456
0
          cmsg->cmsg_type == IP_RECVORIGDSTADDR) {
457
0
        memcpy(to, CMSG_DATA(cmsg),
458
0
            sizeof(struct sockaddr_in));
459
0
      }
460
#elif defined(IP_RECVDSTADDR)
461
      if (cmsg->cmsg_level == IPPROTO_IP &&
462
          cmsg->cmsg_type == IP_RECVDSTADDR) {
463
        in = (struct sockaddr_in *)to;
464
        in->sin_family = AF_INET;
465
#ifdef HAVE_SOCKADDR_SA_LEN
466
        in->sin_len = *tolen = sizeof(*in);
467
#endif
468
        memcpy(&in->sin_addr, CMSG_DATA(cmsg),
469
            sizeof(struct in_addr));
470
      }
471
#endif /* defined(IP_RECVDSTADDR) */
472
0
      break;
473
0
    case AF_INET6:
474
0
#ifdef IPV6_PKTINFO
475
0
      if (cmsg->cmsg_level == IPPROTO_IPV6 &&
476
0
          cmsg->cmsg_type == IPV6_PKTINFO) {
477
0
        in6 = (struct sockaddr_in6 *)to;
478
0
        in6->sin6_family = AF_INET6;
479
#ifdef HAVE_SOCKADDR_SA_LEN
480
        in6->sin6_len = *tolen = sizeof(*in6);
481
#endif
482
0
        pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
483
0
        memcpy(&in6->sin6_addr, &pkt6->ipi6_addr,
484
0
            sizeof(struct in6_addr));
485
0
        if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
486
0
          in6->sin6_scope_id =
487
0
              pkt6->ipi6_ifindex;
488
0
      }
489
0
#endif
490
0
      break;
491
0
    }
492
0
  }
493
494
0
  return (ret);
495
0
}
496
497
const char *
498
print_spi(uint64_t spi, int size)
499
41.9k
{
500
41.9k
  static char    buf[IKED_CYCLE_BUFFERS][32];
501
41.9k
  static int     i = 0;
502
41.9k
  char      *ptr;
503
504
41.9k
  ptr = buf[i];
505
506
41.9k
  switch (size) {
507
0
  case 2:
508
0
    snprintf(ptr, 32, "0x%04x", (uint16_t)spi);
509
0
    break;
510
421
  case 4:
511
421
    snprintf(ptr, 32, "0x%08x", (uint32_t)spi);
512
421
    break;
513
31.2k
  case 8:
514
31.2k
    snprintf(ptr, 32, "0x%016llx", (long long unsigned)spi);
515
31.2k
    break;
516
10.2k
  default:
517
10.2k
    snprintf(ptr, 32, "%llu", (long long unsigned)spi);
518
10.2k
    break;
519
41.9k
  }
520
521
41.9k
  if (++i >= IKED_CYCLE_BUFFERS)
522
5.23k
    i = 0;
523
524
41.9k
  return (ptr);
525
41.9k
}
526
527
const char *
528
print_map(unsigned int type, struct iked_constmap *map)
529
840k
{
530
840k
  unsigned int     i;
531
840k
  static char    buf[IKED_CYCLE_BUFFERS][32];
532
840k
  static int     idx = 0;
533
840k
  const char    *name = NULL;
534
535
840k
  if (idx >= IKED_CYCLE_BUFFERS)
536
105k
    idx = 0;
537
840k
  bzero(buf[idx], sizeof(buf[idx]));
538
539
17.2M
  for (i = 0; map[i].cm_name != NULL; i++) {
540
16.4M
    if (map[i].cm_type == type)
541
573k
      name = map[i].cm_name;
542
16.4M
  }
543
544
840k
  if (name == NULL)
545
267k
    snprintf(buf[idx], sizeof(buf[idx]), "<UNKNOWN:%u>", type);
546
573k
  else
547
573k
    strlcpy(buf[idx], name, sizeof(buf[idx]));
548
549
840k
  return (buf[idx++]);
550
840k
}
551
552
void
553
lc_idtype(char *str)
554
0
{
555
0
  for (; *str != '\0' && *str != '/'; str++)
556
0
    *str = tolower((unsigned char)*str);
557
0
}
558
559
void
560
print_hex(const uint8_t *buf, off_t offset, size_t length)
561
181k
{
562
181k
  unsigned int   i;
563
564
181k
  if (log_getverbose() < 3 || !length)
565
181k
    return;
566
567
0
  for (i = 0; i < length; i++) {
568
0
    if (i && (i % 4) == 0) {
569
0
      if ((i % 32) == 0)
570
0
        print_debug("\n");
571
0
      else
572
0
        print_debug(" ");
573
0
    }
574
0
    print_debug("%02x", buf[offset + i]);
575
0
  }
576
0
  print_debug("\n");
577
0
}
578
579
void
580
print_hexval(const uint8_t *buf, off_t offset, size_t length)
581
0
{
582
0
  unsigned int   i;
583
584
0
  if (log_getverbose() < 2 || !length)
585
0
    return;
586
587
0
  print_debug("0x");
588
0
  for (i = 0; i < length; i++)
589
0
    print_debug("%02x", buf[offset + i]);
590
0
  print_debug("\n");
591
0
}
592
593
void
594
print_hexbuf(struct ibuf *ibuf)
595
0
{
596
0
  print_hex(ibuf_data(ibuf), 0, ibuf_size(ibuf));
597
0
}
598
599
const char *
600
print_bits(unsigned short v, unsigned char *bits)
601
0
{
602
0
  static char  buf[IKED_CYCLE_BUFFERS][BUFSIZ];
603
0
  static int   idx = 0;
604
0
  unsigned int   i, any = 0, j = 0;
605
0
  unsigned char  c;
606
607
0
  if (!bits)
608
0
    return ("");
609
610
0
  if (++idx >= IKED_CYCLE_BUFFERS)
611
0
    idx = 0;
612
613
0
  bzero(buf[idx], sizeof(buf[idx]));
614
615
0
  bits++;
616
0
  while ((i = *bits++)) {
617
0
    if (v & (1 << (i-1))) {
618
0
      if (any) {
619
0
        buf[idx][j++] = ',';
620
0
        if (j >= sizeof(buf[idx]))
621
0
          return (buf[idx]);
622
0
      }
623
0
      any = 1;
624
0
      for (; (c = *bits) > 32; bits++) {
625
0
        buf[idx][j++] = tolower((unsigned char)c);
626
0
        if (j >= sizeof(buf[idx]))
627
0
          return (buf[idx]);
628
0
      }
629
0
    } else
630
0
      for (; *bits > 32; bits++)
631
0
        ;
632
0
  }
633
634
0
  return (buf[idx]);
635
0
}
636
637
uint8_t
638
mask2prefixlen(struct sockaddr *sa)
639
0
{
640
0
  struct sockaddr_in  *sa_in = (struct sockaddr_in *)sa;
641
0
  in_addr_t    ina = sa_in->sin_addr.s_addr;
642
643
0
  if (ina == 0)
644
0
    return (0);
645
0
  else
646
0
    return (33 - ffs(ntohl(ina)));
647
0
}
648
649
uint8_t
650
mask2prefixlen6(struct sockaddr *sa)
651
0
{
652
0
  struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa;
653
0
  uint8_t     *ap, *ep;
654
0
  unsigned int     l = 0;
655
656
  /*
657
   * sin6_len is the size of the sockaddr so substract the offset of
658
   * the possibly truncated sin6_addr struct.
659
   */
660
0
  ap = (uint8_t *)&sa_in6->sin6_addr;
661
0
  ep = (uint8_t *)sa_in6 + SA_LEN(sa);
662
0
  for (; ap < ep; ap++) {
663
    /* this "beauty" is adopted from sbin/route/show.c ... */
664
0
    switch (*ap) {
665
0
    case 0xff:
666
0
      l += 8;
667
0
      break;
668
0
    case 0xfe:
669
0
      l += 7;
670
0
      goto done;
671
0
    case 0xfc:
672
0
      l += 6;
673
0
      goto done;
674
0
    case 0xf8:
675
0
      l += 5;
676
0
      goto done;
677
0
    case 0xf0:
678
0
      l += 4;
679
0
      goto done;
680
0
    case 0xe0:
681
0
      l += 3;
682
0
      goto done;
683
0
    case 0xc0:
684
0
      l += 2;
685
0
      goto done;
686
0
    case 0x80:
687
0
      l += 1;
688
0
      goto done;
689
0
    case 0x00:
690
0
      goto done;
691
0
    default:
692
0
      fatalx("non contiguous inet6 netmask");
693
0
    }
694
0
  }
695
696
0
done:
697
0
  if (l > sizeof(struct in6_addr) * 8)
698
0
    fatalx("%s: prefixlen %d out of bound", __func__, l);
699
0
  return (l);
700
0
}
701
702
uint32_t
703
prefixlen2mask(uint8_t prefixlen)
704
0
{
705
0
  if (prefixlen == 0)
706
0
    return (0);
707
708
0
  if (prefixlen > 32)
709
0
    prefixlen = 32;
710
711
0
  return (htonl(0xffffffff << (32 - prefixlen)));
712
0
}
713
714
struct in6_addr *
715
prefixlen2mask6(uint8_t prefixlen, uint32_t *mask)
716
0
{
717
0
  static struct in6_addr  s6;
718
0
  int     i;
719
720
0
  if (prefixlen > 128)
721
0
    prefixlen = 128;
722
723
0
  bzero(&s6, sizeof(s6));
724
0
  for (i = 0; i < prefixlen / 8; i++)
725
0
    s6.s6_addr[i] = 0xff;
726
0
  i = prefixlen % 8;
727
0
  if (i)
728
0
    s6.s6_addr[prefixlen / 8] = 0xff00 >> i;
729
730
0
  memcpy(mask, &s6, sizeof(s6));
731
732
0
  return (&s6);
733
0
}
734
735
const char *
736
print_addr(void *addr)
737
19.8k
{
738
19.8k
  static char  sbuf[IKED_CYCLE_BUFFERS][NI_MAXHOST + 7];
739
19.8k
  static int   idx;
740
19.8k
  struct sockaddr *sa = addr;
741
19.8k
  char    *buf;
742
19.8k
  size_t     len;
743
19.8k
  char     pbuf[7];
744
19.8k
  in_port_t  port;
745
746
19.8k
  buf = sbuf[idx];
747
19.8k
  len = sizeof(sbuf[idx]);
748
19.8k
  if (++idx >= IKED_CYCLE_BUFFERS)
749
2.47k
    idx = 0;
750
751
19.8k
  if (sa->sa_family == AF_UNSPEC) {
752
0
    strlcpy(buf, "any", len);
753
0
    return (buf);
754
0
  }
755
756
19.8k
  if (getnameinfo(sa, SA_LEN(sa),
757
19.8k
      buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
758
0
    strlcpy(buf, "unknown", len);
759
0
    return (buf);
760
0
  }
761
762
19.8k
  if ((port = socket_getport(sa)) != 0) {
763
0
    snprintf(pbuf, sizeof(pbuf), ":%d", port);
764
0
    (void)strlcat(buf, pbuf, len);
765
0
  }
766
767
19.8k
  return (buf);
768
19.8k
}
769
770
char *
771
get_string(uint8_t *ptr, size_t len)
772
0
{
773
0
  size_t   i;
774
775
0
  for (i = 0; i < len; i++)
776
0
    if (!isprint(ptr[i]))
777
0
      break;
778
779
0
  return strndup(ptr, i);
780
0
}
781
782
const char *
783
print_proto(uint8_t proto)
784
0
{
785
0
  struct protoent *p;
786
0
  static char  buf[IKED_CYCLE_BUFFERS][BUFSIZ];
787
0
  static int   idx = 0;
788
789
0
  if (idx >= IKED_CYCLE_BUFFERS)
790
0
    idx = 0;
791
792
0
  if ((p = getprotobynumber(proto)) != NULL)
793
0
    strlcpy(buf[idx], p->p_name, sizeof(buf[idx]));
794
0
  else
795
0
    snprintf(buf[idx], sizeof(buf), "%u", proto);
796
797
798
0
  return (buf[idx++]);
799
0
}
800
801
int
802
expand_string(char *label, size_t len, const char *srch, const char *repl)
803
0
{
804
0
  char *tmp;
805
0
  char *p, *q;
806
807
0
  if ((tmp = calloc(1, len)) == NULL) {
808
0
    log_debug("%s: calloc", __func__);
809
0
    return (-1);
810
0
  }
811
0
  p = label;
812
0
  while ((q = strstr(p, srch)) != NULL) {
813
0
    *q = '\0';
814
0
    if ((strlcat(tmp, p, len) >= len) ||
815
0
        (strlcat(tmp, repl, len) >= len)) {
816
0
      log_debug("%s: string too long", __func__);
817
0
      free(tmp);
818
0
      return (-1);
819
0
    }
820
0
    q += strlen(srch);
821
0
    p = q;
822
0
  }
823
0
  if (strlcat(tmp, p, len) >= len) {
824
0
    log_debug("%s: string too long", __func__);
825
0
    free(tmp);
826
0
    return (-1);
827
0
  }
828
0
  strlcpy(label, tmp, len); /* always fits */
829
0
  free(tmp);
830
831
0
  return (0);
832
0
}
833
834
uint8_t *
835
string2unicode(const char *ascii, size_t *outlen)
836
0
{
837
0
  uint8_t   *uc = NULL;
838
0
  size_t     i, len = strlen(ascii);
839
840
0
  if ((uc = calloc(1, (len * 2) + 2)) == NULL)
841
0
    return (NULL);
842
843
0
  for (i = 0; i < len; i++) {
844
    /* XXX what about the byte order? */
845
0
    uc[i * 2] = ascii[i];
846
0
  }
847
0
  *outlen = len * 2;
848
849
0
  return (uc);
850
0
}
851
852
void
853
print_debug(const char *emsg, ...)
854
0
{
855
0
  va_list  ap;
856
857
0
  if (log_getverbose() > 2) {
858
0
    va_start(ap, emsg);
859
0
    vfprintf(stderr, emsg, ap);
860
0
    va_end(ap);
861
0
  }
862
0
}
863
864
void
865
print_verbose(const char *emsg, ...)
866
0
{
867
0
  va_list  ap;
868
869
0
  if (log_getverbose()) {
870
0
    va_start(ap, emsg);
871
0
    vfprintf(stderr, emsg, ap);
872
0
    va_end(ap);
873
0
  }
874
0
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/iked/util.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: util.c,v 1.43 2023/07/28 11:23:03 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2021 Tobias Heider <tobhe@openbsd.org>
5
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/queue.h>
22
#include <sys/socket.h>
23
#include <sys/uio.h>
24
25
#include <netinet/in.h>
26
#include <netinet/ip_ipsp.h>
27
28
#include <netdb.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <unistd.h>
32
#include <string.h>
33
#include <errno.h>
34
#include <limits.h>
35
#include <fcntl.h>
36
#include <ctype.h>
37
#include <event.h>
38
39
#include "iked.h"
40
#include "ikev2.h"
41
42
int
43
socket_af(struct sockaddr *sa, in_port_t port)
44
0
{
45
0
  errno = 0;
46
0
  switch (sa->sa_family) {
47
0
  case AF_INET:
48
0
    ((struct sockaddr_in *)sa)->sin_port = port;
49
#ifdef HAVE_SOCKADDR_SA_LEN
50
    ((struct sockaddr_in *)sa)->sin_len =
51
        sizeof(struct sockaddr_in);
52
#endif
53
0
    break;
54
0
  case AF_INET6:
55
0
    ((struct sockaddr_in6 *)sa)->sin6_port = port;
56
#ifdef HAVE_SOCKADDR_SA_LEN
57
    ((struct sockaddr_in6 *)sa)->sin6_len =
58
        sizeof(struct sockaddr_in6);
59
#endif
60
0
    break;
61
0
  default:
62
0
    errno = EPFNOSUPPORT;
63
0
    return (-1);
64
0
  }
65
66
0
  return (0);
67
0
}
68
69
in_port_t
70
socket_getport(struct sockaddr *sa)
71
19.8k
{
72
19.8k
  switch (sa->sa_family) {
73
17.1k
  case AF_INET:
74
17.1k
    return (ntohs(((struct sockaddr_in *)sa)->sin_port));
75
2.63k
  case AF_INET6:
76
2.63k
    return (ntohs(((struct sockaddr_in6 *)sa)->sin6_port));
77
0
  default:
78
0
    return (0);
79
19.8k
  }
80
81
  /* NOTREACHED */
82
0
  return (0);
83
19.8k
}
84
85
int
86
socket_setport(struct sockaddr *sa, in_port_t port)
87
0
{
88
0
  switch (sa->sa_family) {
89
0
  case AF_INET:
90
0
    ((struct sockaddr_in *)sa)->sin_port = htons(port);
91
0
    break;
92
0
  case AF_INET6:
93
0
    ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
94
0
    break;
95
0
  default:
96
0
    return (-1);
97
0
  }
98
0
  return (0);
99
0
}
100
101
int
102
socket_getaddr(int s, struct sockaddr_storage *ss)
103
0
{
104
0
  socklen_t sslen = sizeof(*ss);
105
106
0
  return (getsockname(s, (struct sockaddr *)ss, &sslen));
107
0
}
108
109
int
110
socket_bypass(int s, struct sockaddr *sa)
111
0
{
112
#if defined(__OpenBSD__)
113
  int  v, *a;
114
  int  a4[] = {
115
        IPPROTO_IP,
116
        IP_AUTH_LEVEL,
117
        IP_ESP_TRANS_LEVEL,
118
        IP_ESP_NETWORK_LEVEL,
119
#ifdef IPV6_IPCOMP_LEVEL
120
        IP_IPCOMP_LEVEL
121
#endif
122
  };
123
  int  a6[] = {
124
        IPPROTO_IPV6,
125
        IPV6_AUTH_LEVEL,
126
        IPV6_ESP_TRANS_LEVEL,
127
        IPV6_ESP_NETWORK_LEVEL,
128
#ifdef IPV6_IPCOMP_LEVEL
129
        IPV6_IPCOMP_LEVEL
130
#endif
131
  };
132
133
  switch (sa->sa_family) {
134
  case AF_INET:
135
    a = a4;
136
    break;
137
  case AF_INET6:
138
    a = a6;
139
    break;
140
  default:
141
    log_warn("%s: invalid address family", __func__);
142
    return (-1);
143
  }
144
145
  v = IPSEC_LEVEL_BYPASS;
146
  if (setsockopt(s, a[0], a[1], &v, sizeof(v)) == -1) {
147
    log_warn("%s: AUTH_LEVEL", __func__);
148
    return (-1);
149
  }
150
  if (setsockopt(s, a[0], a[2], &v, sizeof(v)) == -1) {
151
    log_warn("%s: ESP_TRANS_LEVEL", __func__);
152
    return (-1);
153
  }
154
  if (setsockopt(s, a[0], a[3], &v, sizeof(v)) == -1) {
155
    log_warn("%s: ESP_NETWORK_LEVEL", __func__);
156
    return (-1);
157
  }
158
#ifdef IP_IPCOMP_LEVEL
159
  if (setsockopt(s, a[0], a[4], &v, sizeof(v)) == -1) {
160
    log_warn("%s: IPCOMP_LEVEL", __func__);
161
    return (-1);
162
  }
163
#endif
164
#else /* __OpenBSD__ */
165
0
  int *a;
166
0
  int  a4[] = {
167
0
        IPPROTO_IP,
168
0
        IP_IPSEC_POLICY
169
0
  };
170
0
  int  a6[] = {
171
0
        IPPROTO_IPV6,
172
0
        IPV6_IPSEC_POLICY,
173
0
  };
174
0
  struct sadb_x_policy pol = {
175
0
        SADB_UPDATE,
176
0
        SADB_EXT_SENSITIVITY,
177
0
        IPSEC_POLICY_BYPASS,
178
0
        0, 0, 0, 0
179
0
  };
180
181
0
  switch (sa->sa_family) {
182
0
  case AF_INET:
183
0
    a = a4;
184
0
    break;
185
0
  case AF_INET6:
186
0
    a = a6;
187
0
    break;
188
0
  default:
189
0
    log_warn("%s: invalid address family", __func__);
190
0
    return (-1);
191
0
  }
192
193
0
  pol.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
194
0
  if (setsockopt(s, a[0], a[1], &pol, sizeof(pol)) == -1) {
195
0
    log_warn("%s: IPSEC_DIR_INBOUND", __func__);
196
0
    return (-1);
197
0
  }
198
0
  pol.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
199
0
  if (setsockopt(s, a[0], a[1], &pol, sizeof(pol)) == -1) {
200
0
    log_warn("%s: IPSEC_DIR_OUTBOUND", __func__);
201
0
    return (-1);
202
0
  }
203
0
#endif /* !__OpenBSD__ */
204
205
0
  return (0);
206
0
}
207
208
int
209
udp_bind(struct sockaddr *sa, in_port_t port)
210
0
{
211
0
  int  s, val;
212
213
0
  if (socket_af(sa, port) == -1) {
214
0
    log_warn("%s: failed to set UDP port", __func__);
215
0
    return (-1);
216
0
  }
217
218
0
  if ((s = socket(sa->sa_family,
219
0
      SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP)) == -1) {
220
0
    log_warn("%s: failed to get UDP socket", __func__);
221
0
    return (-1);
222
0
  }
223
224
  /* Skip IPsec processing (don't encrypt) for IKE messages */
225
0
  if (socket_bypass(s, sa) == -1) {
226
0
    log_warn("%s: failed to bypass IPsec on IKE socket",
227
0
        __func__);
228
0
    goto bad;
229
0
  }
230
231
0
  val = 1;
232
0
  if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(int)) == -1) {
233
0
    log_warn("%s: failed to set reuseport", __func__);
234
0
    goto bad;
235
0
  }
236
0
  val = 1;
237
0
  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int)) == -1) {
238
0
    log_warn("%s: failed to set reuseaddr", __func__);
239
0
    goto bad;
240
0
  }
241
242
0
  if (sa->sa_family == AF_INET) {
243
0
#if defined(IP_RECVORIGDSTADDR)
244
0
    val = 1;
245
0
    if (setsockopt(s, IPPROTO_IP, IP_RECVORIGDSTADDR,
246
0
        &val, sizeof(int)) == -1) {
247
0
      log_warn("%s: failed to set IPv4 packet info",
248
0
          __func__);
249
0
      goto bad;
250
0
    }
251
#elif defined(IP_RECVDSTADDR)
252
    val = 1;
253
    if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
254
        &val, sizeof(int)) == -1) {
255
      log_warn("%s: failed to set IPv4 packet info",
256
          __func__);
257
      goto bad;
258
    }
259
#endif
260
0
  } else {
261
0
#ifdef IPV6_RECVPKTINFO
262
0
    val = 1;
263
0
    if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
264
0
        &val, sizeof(int)) == -1) {
265
0
      log_warn("%s: failed to set IPv6 packet info",
266
0
          __func__);
267
0
      goto bad;
268
0
    }
269
0
#endif
270
0
  }
271
272
0
  if (bind(s, sa, SA_LEN(sa)) == -1) {
273
0
    log_warn("%s: failed to bind UDP socket", __func__);
274
0
    goto bad;
275
0
  }
276
277
0
  return (s);
278
0
 bad:
279
0
  close(s);
280
0
  return (-1);
281
0
}
282
283
int
284
sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen)
285
0
{
286
0
  struct sockaddr_in  *a4, *b4;
287
0
  struct sockaddr_in6 *a6, *b6;
288
0
  uint32_t     av[4], bv[4], mv[4];
289
290
0
  if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC)
291
0
    return (0);
292
0
  else if (a->sa_family > b->sa_family)
293
0
    return (1);
294
0
  else if (a->sa_family < b->sa_family)
295
0
    return (-1);
296
297
0
  if (prefixlen == -1)
298
0
    memset(&mv, 0xff, sizeof(mv));
299
300
0
  switch (a->sa_family) {
301
0
  case AF_INET:
302
0
    a4 = (struct sockaddr_in *)a;
303
0
    b4 = (struct sockaddr_in *)b;
304
305
0
    av[0] = a4->sin_addr.s_addr;
306
0
    bv[0] = b4->sin_addr.s_addr;
307
0
    if (prefixlen != -1)
308
0
      mv[0] = prefixlen2mask(prefixlen);
309
310
0
    if ((av[0] & mv[0]) > (bv[0] & mv[0]))
311
0
      return (1);
312
0
    if ((av[0] & mv[0]) < (bv[0] & mv[0]))
313
0
      return (-1);
314
0
    break;
315
0
  case AF_INET6:
316
0
    a6 = (struct sockaddr_in6 *)a;
317
0
    b6 = (struct sockaddr_in6 *)b;
318
319
0
    memcpy(&av, &a6->sin6_addr.s6_addr, 16);
320
0
    memcpy(&bv, &b6->sin6_addr.s6_addr, 16);
321
0
    if (prefixlen != -1)
322
0
      prefixlen2mask6(prefixlen, mv);
323
324
0
    if ((av[3] & mv[3]) > (bv[3] & mv[3]))
325
0
      return (1);
326
0
    if ((av[3] & mv[3]) < (bv[3] & mv[3]))
327
0
      return (-1);
328
0
    if ((av[2] & mv[2]) > (bv[2] & mv[2]))
329
0
      return (1);
330
0
    if ((av[2] & mv[2]) < (bv[2] & mv[2]))
331
0
      return (-1);
332
0
    if ((av[1] & mv[1]) > (bv[1] & mv[1]))
333
0
      return (1);
334
0
    if ((av[1] & mv[1]) < (bv[1] & mv[1]))
335
0
      return (-1);
336
0
    if ((av[0] & mv[0]) > (bv[0] & mv[0]))
337
0
      return (1);
338
0
    if ((av[0] & mv[0]) < (bv[0] & mv[0]))
339
0
      return (-1);
340
0
    break;
341
0
  }
342
343
0
  return (0);
344
0
}
345
346
ssize_t
347
sendtofrom(int s, void *buf, size_t len, int flags, struct sockaddr *to,
348
    socklen_t tolen, struct sockaddr *from, socklen_t fromlen)
349
0
{
350
0
  struct iovec     iov;
351
0
  struct msghdr    msg;
352
0
  struct cmsghdr    *cmsg;
353
#ifdef IP_SENDSRCADDR
354
  struct sockaddr_in  *in;
355
#endif
356
0
#ifdef IPV6_PKTINFO
357
0
  struct in6_pktinfo  *pkt6;
358
0
  struct sockaddr_in6 *in6;
359
0
#endif
360
0
  union {
361
0
    struct cmsghdr  hdr;
362
0
    char    inbuf[CMSG_SPACE(sizeof(struct in_addr))];
363
0
    char    in6buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
364
0
  } cmsgbuf;
365
366
0
  bzero(&msg, sizeof(msg));
367
0
  bzero(&cmsgbuf, sizeof(cmsgbuf));
368
369
0
  iov.iov_base = buf;
370
0
  iov.iov_len = len;
371
0
  msg.msg_iov = &iov;
372
0
  msg.msg_iovlen = 1;
373
0
  msg.msg_name = to;
374
0
  msg.msg_namelen = tolen;
375
0
  msg.msg_controllen = 0;
376
377
0
  switch (to->sa_family) {
378
0
  case AF_INET:
379
#ifdef IP_SENDSRCADDR
380
    in = (struct sockaddr_in *)from;
381
    if (in->sin_addr.s_addr == INADDR_ANY)
382
      break;
383
    msg.msg_control = &cmsgbuf;
384
    msg.msg_controllen += sizeof(cmsgbuf.inbuf);
385
    cmsg = CMSG_FIRSTHDR(&msg);
386
    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
387
    cmsg->cmsg_level = IPPROTO_IP;
388
    cmsg->cmsg_type = IP_SENDSRCADDR;
389
    memcpy(CMSG_DATA(cmsg), &in->sin_addr, sizeof(struct in_addr));
390
#endif
391
0
    break;
392
0
  case AF_INET6:
393
0
#ifdef IPV6_PKTINFO
394
0
    msg.msg_control = &cmsgbuf;
395
0
    msg.msg_controllen += sizeof(cmsgbuf.in6buf);
396
0
    cmsg = CMSG_FIRSTHDR(&msg);
397
0
    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
398
0
    cmsg->cmsg_level = IPPROTO_IPV6;
399
0
    cmsg->cmsg_type = IPV6_PKTINFO;
400
0
    in6 = (struct sockaddr_in6 *)from;
401
0
    pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
402
0
    pkt6->ipi6_addr = in6->sin6_addr;
403
0
#endif
404
0
    break;
405
0
  }
406
407
0
  return sendmsg(s, &msg, flags);
408
0
}
409
410
ssize_t
411
recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from,
412
    socklen_t *fromlen, struct sockaddr *to, socklen_t *tolen)
413
0
{
414
0
  struct iovec     iov;
415
0
  struct msghdr    msg;
416
0
  struct cmsghdr    *cmsg;
417
#if !defined(IP_RECVORIGDSTADDR) && defined(IP_RECVDSTADDR)
418
  struct sockaddr_in  *in;
419
#endif
420
0
#ifdef IPV6_PKTINFO
421
0
  struct in6_pktinfo  *pkt6;
422
0
  struct sockaddr_in6 *in6;
423
0
#endif
424
0
  ssize_t      ret;
425
0
  union {
426
0
    struct cmsghdr hdr;
427
0
    char  buf[CMSG_SPACE(sizeof(struct sockaddr_storage))];
428
0
  } cmsgbuf;
429
430
0
  bzero(&msg, sizeof(msg));
431
0
  bzero(&cmsgbuf.buf, sizeof(cmsgbuf.buf));
432
433
0
  iov.iov_base = buf;
434
0
  iov.iov_len = len;
435
0
  msg.msg_iov = &iov;
436
0
  msg.msg_iovlen = 1;
437
0
  msg.msg_name = from;
438
0
  msg.msg_namelen = *fromlen;
439
0
  msg.msg_control = &cmsgbuf.buf;
440
0
  msg.msg_controllen = sizeof(cmsgbuf.buf);
441
442
0
  if ((ret = recvmsg(s, &msg, flags)) == -1)
443
0
    return (-1);
444
445
0
  *fromlen = SA_LEN(from);
446
447
0
  if (getsockname(s, to, tolen) != 0)
448
0
    *tolen = 0;
449
450
0
  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
451
0
      cmsg = CMSG_NXTHDR(&msg, cmsg)) {
452
0
    switch (from->sa_family) {
453
0
    case AF_INET:
454
0
#if defined(IP_RECVORIGDSTADDR)
455
0
      if (cmsg->cmsg_level == IPPROTO_IP &&
456
0
          cmsg->cmsg_type == IP_RECVORIGDSTADDR) {
457
0
        memcpy(to, CMSG_DATA(cmsg),
458
0
            sizeof(struct sockaddr_in));
459
0
      }
460
#elif defined(IP_RECVDSTADDR)
461
      if (cmsg->cmsg_level == IPPROTO_IP &&
462
          cmsg->cmsg_type == IP_RECVDSTADDR) {
463
        in = (struct sockaddr_in *)to;
464
        in->sin_family = AF_INET;
465
#ifdef HAVE_SOCKADDR_SA_LEN
466
        in->sin_len = *tolen = sizeof(*in);
467
#endif
468
        memcpy(&in->sin_addr, CMSG_DATA(cmsg),
469
            sizeof(struct in_addr));
470
      }
471
#endif /* defined(IP_RECVDSTADDR) */
472
0
      break;
473
0
    case AF_INET6:
474
0
#ifdef IPV6_PKTINFO
475
0
      if (cmsg->cmsg_level == IPPROTO_IPV6 &&
476
0
          cmsg->cmsg_type == IPV6_PKTINFO) {
477
0
        in6 = (struct sockaddr_in6 *)to;
478
0
        in6->sin6_family = AF_INET6;
479
#ifdef HAVE_SOCKADDR_SA_LEN
480
        in6->sin6_len = *tolen = sizeof(*in6);
481
#endif
482
0
        pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
483
0
        memcpy(&in6->sin6_addr, &pkt6->ipi6_addr,
484
0
            sizeof(struct in6_addr));
485
0
        if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
486
0
          in6->sin6_scope_id =
487
0
              pkt6->ipi6_ifindex;
488
0
      }
489
0
#endif
490
0
      break;
491
0
    }
492
0
  }
493
494
0
  return (ret);
495
0
}
496
497
const char *
498
print_spi(uint64_t spi, int size)
499
41.9k
{
500
41.9k
  static char    buf[IKED_CYCLE_BUFFERS][32];
501
41.9k
  static int     i = 0;
502
41.9k
  char      *ptr;
503
504
41.9k
  ptr = buf[i];
505
506
41.9k
  switch (size) {
507
0
  case 2:
508
0
    snprintf(ptr, 32, "0x%04x", (uint16_t)spi);
509
0
    break;
510
421
  case 4:
511
421
    snprintf(ptr, 32, "0x%08x", (uint32_t)spi);
512
421
    break;
513
31.2k
  case 8:
514
31.2k
    snprintf(ptr, 32, "0x%016llx", (long long unsigned)spi);
515
31.2k
    break;
516
10.2k
  default:
517
10.2k
    snprintf(ptr, 32, "%llu", (long long unsigned)spi);
518
10.2k
    break;
519
41.9k
  }
520
521
41.9k
  if (++i >= IKED_CYCLE_BUFFERS)
522
5.23k
    i = 0;
523
524
41.9k
  return (ptr);
525
41.9k
}
526
527
const char *
528
print_map(unsigned int type, struct iked_constmap *map)
529
840k
{
530
840k
  unsigned int     i;
531
840k
  static char    buf[IKED_CYCLE_BUFFERS][32];
532
840k
  static int     idx = 0;
533
840k
  const char    *name = NULL;
534
535
840k
  if (idx >= IKED_CYCLE_BUFFERS)
536
105k
    idx = 0;
537
840k
  bzero(buf[idx], sizeof(buf[idx]));
538
539
17.2M
  for (i = 0; map[i].cm_name != NULL; i++) {
540
16.4M
    if (map[i].cm_type == type)
541
573k
      name = map[i].cm_name;
542
16.4M
  }
543
544
840k
  if (name == NULL)
545
267k
    snprintf(buf[idx], sizeof(buf[idx]), "<UNKNOWN:%u>", type);
546
573k
  else
547
573k
    strlcpy(buf[idx], name, sizeof(buf[idx]));
548
549
840k
  return (buf[idx++]);
550
840k
}
551
552
void
553
lc_idtype(char *str)
554
0
{
555
0
  for (; *str != '\0' && *str != '/'; str++)
556
0
    *str = tolower((unsigned char)*str);
557
0
}
558
559
void
560
print_hex(const uint8_t *buf, off_t offset, size_t length)
561
181k
{
562
181k
  unsigned int   i;
563
564
181k
  if (log_getverbose() < 3 || !length)
565
181k
    return;
566
567
0
  for (i = 0; i < length; i++) {
568
0
    if (i && (i % 4) == 0) {
569
0
      if ((i % 32) == 0)
570
0
        print_debug("\n");
571
0
      else
572
0
        print_debug(" ");
573
0
    }
574
0
    print_debug("%02x", buf[offset + i]);
575
0
  }
576
0
  print_debug("\n");
577
0
}
578
579
void
580
print_hexval(const uint8_t *buf, off_t offset, size_t length)
581
0
{
582
0
  unsigned int   i;
583
584
0
  if (log_getverbose() < 2 || !length)
585
0
    return;
586
587
0
  print_debug("0x");
588
0
  for (i = 0; i < length; i++)
589
0
    print_debug("%02x", buf[offset + i]);
590
0
  print_debug("\n");
591
0
}
592
593
void
594
print_hexbuf(struct ibuf *ibuf)
595
0
{
596
0
  print_hex(ibuf_data(ibuf), 0, ibuf_size(ibuf));
597
0
}
598
599
const char *
600
print_bits(unsigned short v, unsigned char *bits)
601
0
{
602
0
  static char  buf[IKED_CYCLE_BUFFERS][BUFSIZ];
603
0
  static int   idx = 0;
604
0
  unsigned int   i, any = 0, j = 0;
605
0
  unsigned char  c;
606
607
0
  if (!bits)
608
0
    return ("");
609
610
0
  if (++idx >= IKED_CYCLE_BUFFERS)
611
0
    idx = 0;
612
613
0
  bzero(buf[idx], sizeof(buf[idx]));
614
615
0
  bits++;
616
0
  while ((i = *bits++)) {
617
0
    if (v & (1 << (i-1))) {
618
0
      if (any) {
619
0
        buf[idx][j++] = ',';
620
0
        if (j >= sizeof(buf[idx]))
621
0
          return (buf[idx]);
622
0
      }
623
0
      any = 1;
624
0
      for (; (c = *bits) > 32; bits++) {
625
0
        buf[idx][j++] = tolower((unsigned char)c);
626
0
        if (j >= sizeof(buf[idx]))
627
0
          return (buf[idx]);
628
0
      }
629
0
    } else
630
0
      for (; *bits > 32; bits++)
631
0
        ;
632
0
  }
633
634
0
  return (buf[idx]);
635
0
}
636
637
uint8_t
638
mask2prefixlen(struct sockaddr *sa)
639
0
{
640
0
  struct sockaddr_in  *sa_in = (struct sockaddr_in *)sa;
641
0
  in_addr_t    ina = sa_in->sin_addr.s_addr;
642
643
0
  if (ina == 0)
644
0
    return (0);
645
0
  else
646
0
    return (33 - ffs(ntohl(ina)));
647
0
}
648
649
uint8_t
650
mask2prefixlen6(struct sockaddr *sa)
651
0
{
652
0
  struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa;
653
0
  uint8_t     *ap, *ep;
654
0
  unsigned int     l = 0;
655
656
  /*
657
   * sin6_len is the size of the sockaddr so substract the offset of
658
   * the possibly truncated sin6_addr struct.
659
   */
660
0
  ap = (uint8_t *)&sa_in6->sin6_addr;
661
0
  ep = (uint8_t *)sa_in6 + SA_LEN(sa);
662
0
  for (; ap < ep; ap++) {
663
    /* this "beauty" is adopted from sbin/route/show.c ... */
664
0
    switch (*ap) {
665
0
    case 0xff:
666
0
      l += 8;
667
0
      break;
668
0
    case 0xfe:
669
0
      l += 7;
670
0
      goto done;
671
0
    case 0xfc:
672
0
      l += 6;
673
0
      goto done;
674
0
    case 0xf8:
675
0
      l += 5;
676
0
      goto done;
677
0
    case 0xf0:
678
0
      l += 4;
679
0
      goto done;
680
0
    case 0xe0:
681
0
      l += 3;
682
0
      goto done;
683
0
    case 0xc0:
684
0
      l += 2;
685
0
      goto done;
686
0
    case 0x80:
687
0
      l += 1;
688
0
      goto done;
689
0
    case 0x00:
690
0
      goto done;
691
0
    default:
692
0
      fatalx("non contiguous inet6 netmask");
693
0
    }
694
0
  }
695
696
0
done:
697
0
  if (l > sizeof(struct in6_addr) * 8)
698
0
    fatalx("%s: prefixlen %d out of bound", __func__, l);
699
0
  return (l);
700
0
}
701
702
uint32_t
703
prefixlen2mask(uint8_t prefixlen)
704
0
{
705
0
  if (prefixlen == 0)
706
0
    return (0);
707
708
0
  if (prefixlen > 32)
709
0
    prefixlen = 32;
710
711
0
  return (htonl(0xffffffff << (32 - prefixlen)));
712
0
}
713
714
struct in6_addr *
715
prefixlen2mask6(uint8_t prefixlen, uint32_t *mask)
716
0
{
717
0
  static struct in6_addr  s6;
718
0
  int     i;
719
720
0
  if (prefixlen > 128)
721
0
    prefixlen = 128;
722
723
0
  bzero(&s6, sizeof(s6));
724
0
  for (i = 0; i < prefixlen / 8; i++)
725
0
    s6.s6_addr[i] = 0xff;
726
0
  i = prefixlen % 8;
727
0
  if (i)
728
0
    s6.s6_addr[prefixlen / 8] = 0xff00 >> i;
729
730
0
  memcpy(mask, &s6, sizeof(s6));
731
732
0
  return (&s6);
733
0
}
734
735
const char *
736
print_addr(void *addr)
737
19.8k
{
738
19.8k
  static char  sbuf[IKED_CYCLE_BUFFERS][NI_MAXHOST + 7];
739
19.8k
  static int   idx;
740
19.8k
  struct sockaddr *sa = addr;
741
19.8k
  char    *buf;
742
19.8k
  size_t     len;
743
19.8k
  char     pbuf[7];
744
19.8k
  in_port_t  port;
745
746
19.8k
  buf = sbuf[idx];
747
19.8k
  len = sizeof(sbuf[idx]);
748
19.8k
  if (++idx >= IKED_CYCLE_BUFFERS)
749
2.47k
    idx = 0;
750
751
19.8k
  if (sa->sa_family == AF_UNSPEC) {
752
0
    strlcpy(buf, "any", len);
753
0
    return (buf);
754
0
  }
755
756
19.8k
  if (getnameinfo(sa, SA_LEN(sa),
757
19.8k
      buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
758
0
    strlcpy(buf, "unknown", len);
759
0
    return (buf);
760
0
  }
761
762
19.8k
  if ((port = socket_getport(sa)) != 0) {
763
0
    snprintf(pbuf, sizeof(pbuf), ":%d", port);
764
0
    (void)strlcat(buf, pbuf, len);
765
0
  }
766
767
19.8k
  return (buf);
768
19.8k
}
769
770
char *
771
get_string(uint8_t *ptr, size_t len)
772
0
{
773
0
  size_t   i;
774
775
0
  for (i = 0; i < len; i++)
776
0
    if (!isprint(ptr[i]))
777
0
      break;
778
779
0
  return strndup(ptr, i);
780
0
}
781
782
const char *
783
print_proto(uint8_t proto)
784
0
{
785
0
  struct protoent *p;
786
0
  static char  buf[IKED_CYCLE_BUFFERS][BUFSIZ];
787
0
  static int   idx = 0;
788
789
0
  if (idx >= IKED_CYCLE_BUFFERS)
790
0
    idx = 0;
791
792
0
  if ((p = getprotobynumber(proto)) != NULL)
793
0
    strlcpy(buf[idx], p->p_name, sizeof(buf[idx]));
794
0
  else
795
0
    snprintf(buf[idx], sizeof(buf), "%u", proto);
796
797
798
0
  return (buf[idx++]);
799
0
}
800
801
int
802
expand_string(char *label, size_t len, const char *srch, const char *repl)
803
0
{
804
0
  char *tmp;
805
0
  char *p, *q;
806
807
0
  if ((tmp = calloc(1, len)) == NULL) {
808
0
    log_debug("%s: calloc", __func__);
809
0
    return (-1);
810
0
  }
811
0
  p = label;
812
0
  while ((q = strstr(p, srch)) != NULL) {
813
0
    *q = '\0';
814
0
    if ((strlcat(tmp, p, len) >= len) ||
815
0
        (strlcat(tmp, repl, len) >= len)) {
816
0
      log_debug("%s: string too long", __func__);
817
0
      free(tmp);
818
0
      return (-1);
819
0
    }
820
0
    q += strlen(srch);
821
0
    p = q;
822
0
  }
823
0
  if (strlcat(tmp, p, len) >= len) {
824
0
    log_debug("%s: string too long", __func__);
825
0
    free(tmp);
826
0
    return (-1);
827
0
  }
828
0
  strlcpy(label, tmp, len); /* always fits */
829
0
  free(tmp);
830
831
0
  return (0);
832
0
}
833
834
uint8_t *
835
string2unicode(const char *ascii, size_t *outlen)
836
0
{
837
0
  uint8_t   *uc = NULL;
838
0
  size_t     i, len = strlen(ascii);
839
840
0
  if ((uc = calloc(1, (len * 2) + 2)) == NULL)
841
0
    return (NULL);
842
843
0
  for (i = 0; i < len; i++) {
844
    /* XXX what about the byte order? */
845
0
    uc[i * 2] = ascii[i];
846
0
  }
847
0
  *outlen = len * 2;
848
849
0
  return (uc);
850
0
}
851
852
void
853
print_debug(const char *emsg, ...)
854
0
{
855
0
  va_list  ap;
856
857
0
  if (log_getverbose() > 2) {
858
0
    va_start(ap, emsg);
859
0
    vfprintf(stderr, emsg, ap);
860
0
    va_end(ap);
861
0
  }
862
0
}
863
864
void
865
print_verbose(const char *emsg, ...)
866
0
{
867
0
  va_list  ap;
868
869
0
  if (log_getverbose()) {
870
0
    va_start(ap, emsg);
871
0
    vfprintf(stderr, emsg, ap);
872
0
    va_end(ap);
873
0
  }
874
0
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/regress/parser-libfuzzer/common.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/regress/parser-libfuzzer/common.c.html index e02411af6..c32f8b438 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/regress/parser-libfuzzer/common.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/regress/parser-libfuzzer/common.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/regress/parser-libfuzzer/common.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: common.c,v 1.9 2020/11/26 22:29:32 tobhe Exp $ */
2
/*
3
 * A bunch of stub functions so we can compile and link ikev2_pld.c
4
 * in a standalone program for testing purposes.
5
 *
6
 * Placed in the public domain
7
 */
8
9
#include <sys/socket.h>
10
#include <sys/time.h>
11
#include <sys/uio.h>
12
13
#include <event.h>
14
#include <limits.h>
15
#include <string.h>
16
17
#include "iked.h"
18
#include "types.h"
19
20
242k
#define IKEV2_FLAG_INITIATOR            0x08    /* Sent by the initiator */
21
22
int  eap_parse(struct iked *, const struct iked_sa *,
23
      struct iked_message *, void *, int);
24
int  ikev2_msg_frompeer(struct iked_message *);
25
int  ikev2_send_ike_e(struct iked *, struct iked_sa *, struct ibuf *,
26
      u_int8_t, u_int8_t, int);
27
void   ikev2_ikesa_recv_delete(struct iked *, struct iked_sa *);
28
struct iked_childsa *
29
   childsa_lookup(struct iked_sa *, u_int64_t, u_int8_t);
30
int   ikev2_childsa_delete(struct iked *, struct iked_sa *,
31
      u_int8_t, u_int64_t, u_int64_t *, int);
32
int  sa_stateok(const struct iked_sa *, int);
33
void   sa_state(struct iked *, struct iked_sa *, int);
34
void   ikev2_disable_rekeying(struct iked *, struct iked_sa *);
35
void   ikev2_init_ike_sa(struct iked *, void *);
36
struct dh_group *
37
   group_get(u_int32_t);
38
void   timer_set(struct iked *, struct iked_timer *,
39
       void (*)(struct iked *, void *), void *);
40
void   timer_add(struct iked *, struct iked_timer *, int);
41
void   timer_del(struct iked *, struct iked_timer *);
42
ssize_t  ikev2_nat_detection(struct iked *, struct iked_message *,
43
       void *, size_t, u_int, int);
44
int  ca_setreq(struct iked *, struct iked_sa *, struct iked_static_id *,
45
       u_int8_t, u_int8_t, u_int8_t *, size_t, enum privsep_procid);
46
int  ikev2_print_id(struct iked_id *, char *, size_t);
47
int  config_add_transform(struct iked_proposal *, u_int, u_int, u_int,
48
       u_int);
49
struct iked_proposal *
50
   config_add_proposal(struct iked_proposals *, u_int, u_int);
51
void   config_free_proposal(struct iked_proposals *, struct iked_proposal *);
52
int  ikev2_send_informational(struct iked *, struct iked_message *);
53
struct ibuf *
54
   ikev2_msg_decrypt(struct iked *, struct iked_sa *, struct ibuf *,
55
       struct ibuf *);
56
void ikev2_msg_cleanup(struct iked *, struct iked_message *);
57
58
int
59
eap_parse(struct iked *env, const struct iked_sa *sa, struct iked_message *msg,
60
    void *data, int response)
61
3.86k
{
62
3.86k
  return (0);
63
3.86k
}
64
65
/* Copied from ikev2_msg.c for better coverage */
66
int
67
ikev2_msg_frompeer(struct iked_message *msg)
68
242k
{
69
242k
  struct iked_sa    *sa = msg->msg_sa;
70
242k
  struct ike_header *hdr;
71
72
242k
  msg = msg->msg_parent;
73
74
242k
  if (sa == NULL ||
75
242k
      (hdr = ibuf_seek(msg->msg_data, 0, sizeof(*hdr))) == NULL)
76
0
    return (0);
77
78
242k
  if (!sa->sa_hdr.sh_initiator &&
79
242k
      (hdr->ike_flags & IKEV2_FLAG_INITIATOR))
80
65.1k
    return (1);
81
177k
  else if (sa->sa_hdr.sh_initiator &&
82
177k
      (hdr->ike_flags & IKEV2_FLAG_INITIATOR) == 0)
83
0
    return (1);
84
85
177k
  return (0);
86
242k
}
87
88
int
89
ikev2_send_ike_e(struct iked *env, struct iked_sa *sa, struct ibuf *buf,
90
    u_int8_t firstpayload, u_int8_t exchange, int response)
91
0
{
92
0
  return (0);
93
0
}
94
95
void
96
ikev2_ikesa_recv_delete(struct iked *env, struct iked_sa *sa)
97
0
{
98
0
}
99
100
const char *
101
ikev2_ikesa_info(uint64_t spi, const char *msg)
102
9.39k
{
103
9.39k
  return "";
104
9.39k
}
105
106
struct iked_childsa *
107
childsa_lookup(struct iked_sa *a, u_int64_t b, u_int8_t c)
108
0
{
109
0
  return (NULL);
110
0
}
111
112
int
113
ikev2_childsa_delete(struct iked *a, struct iked_sa *b, u_int8_t c,
114
    u_int64_t d, u_int64_t *e , int f)
115
0
{
116
0
  return (0);
117
0
}
118
119
int
120
sa_stateok(const struct iked_sa *a, int b)
121
149
{
122
149
  return (0);
123
149
}
124
125
void
126
sa_state(struct iked * a, struct iked_sa *b, int c)
127
0
{
128
0
}
129
130
void
131
ikev2_disable_rekeying(struct iked *a, struct iked_sa *b)
132
0
{
133
0
}
134
135
void
136
ikev2_init_ike_sa(struct iked *a, void *b)
137
0
{
138
0
}
139
140
const struct group_id *
141
group_getid(u_int32_t id)
142
0
{
143
0
  return (NULL);
144
0
}
145
146
void
147
timer_set(struct iked *env, struct iked_timer *tmr,
148
    void (*cb)(struct iked *, void *), void *arg)
149
0
{
150
0
}
151
152
void
153
timer_add(struct iked *env, struct iked_timer *tmr, int timeout)
154
0
{
155
0
}
156
157
void
158
timer_del(struct iked *env, struct iked_timer *tmr)
159
0
{
160
0
}
161
162
ssize_t
163
ikev2_nat_detection(struct iked *env, struct iked_message *msg,
164
    void *ptr, size_t len, u_int type, int frompeer)
165
26.0k
{
166
26.0k
  bzero(ptr, len);
167
26.0k
  return (0);
168
26.0k
}
169
170
int
171
ca_setreq(struct iked *env, struct iked_sa *sh, struct iked_static_id *localid,
172
    u_int8_t type, u_int8_t more, u_int8_t *data, size_t len,
173
    enum privsep_procid procid)
174
0
{
175
0
  return (0);
176
0
}
177
178
int
179
ikev2_print_id(struct iked_id *id, char *idstr, size_t idstrlen)
180
7.77k
{
181
7.77k
  return (0);
182
7.77k
}
183
184
int
185
config_add_transform(struct iked_proposal *prop, u_int type,
186
    u_int id, u_int length, u_int keylength)
187
0
{
188
0
  return (0);
189
0
}
190
191
struct iked_proposal *
192
config_add_proposal(struct iked_proposals *head, u_int id, u_int proto)
193
69
{
194
69
  return (NULL);
195
69
}
196
197
void
198
config_free_proposal(struct iked_proposals *head, struct iked_proposal *prop)
199
0
{
200
0
  return;
201
0
}
202
203
void config_free_fragments(struct iked_frag *frag)
204
0
{
205
0
  return;
206
0
}
207
208
int
209
ikev2_send_informational(struct iked *env, struct iked_message *msg)
210
748
{
211
748
  return (0);
212
748
}
213
214
struct ibuf *
215
ikev2_msg_decrypt(struct iked *env, struct iked_sa *sa,
216
    struct ibuf *msg, struct ibuf *src)
217
0
{
218
0
  if (src == NULL){
219
0
                fprintf(stderr, "%s\n", "msg_decrypt: src == NULL!");
220
0
                exit(-1);
221
0
        }
222
223
  /*
224
   * Free src as caller uses ikev2_msg_decrypt() like this:
225
   * src = ikev2_msg_decrypt(..., src);
226
   */
227
0
  ibuf_free(src); 
228
0
  return (NULL);
229
0
}
230
231
void
232
ikev2_ike_sa_setreason(struct iked_sa *sa, char *r)
233
0
{
234
0
}
235
236
void
237
ikev2_msg_dispose(struct iked *env, struct iked_msgqueue *queue,
238
    struct iked_msg_retransmit *mr)
239
0
{
240
0
}
241
242
struct iked_msg_retransmit *
243
ikev2_msg_lookup(struct iked *env, struct iked_msgqueue *queue,
244
    struct iked_message *msg, uint8_t exchange)
245
0
{
246
0
  return NULL;
247
0
}
248
249
/* copied from ikev2_msg.c */
250
void
251
ikev2_msg_cleanup(struct iked *env, struct iked_message *msg)
252
15.4k
{
253
15.4k
  struct iked_certreq *cr;
254
15.4k
  struct iked_proposal *prop, *proptmp;
255
15.4k
  int      i;
256
257
15.4k
  if (msg == msg->msg_parent) {
258
15.4k
    ibuf_free(msg->msg_nonce);
259
15.4k
    ibuf_free(msg->msg_ke);
260
15.4k
    ibuf_free(msg->msg_auth.id_buf);
261
15.4k
    ibuf_free(msg->msg_peerid.id_buf);
262
15.4k
    ibuf_free(msg->msg_localid.id_buf);
263
15.4k
    ibuf_free(msg->msg_cert.id_buf);
264
61.9k
    for (i = 0; i < IKED_SCERT_MAX; i++)
265
46.4k
      ibuf_free(msg->msg_scert[i].id_buf);
266
15.4k
    ibuf_free(msg->msg_cookie);
267
15.4k
    ibuf_free(msg->msg_cookie2);
268
15.4k
    ibuf_free(msg->msg_del_buf);
269
15.4k
    free(msg->msg_eap.eam_user);
270
15.4k
    free(msg->msg_cp_addr);
271
15.4k
    free(msg->msg_cp_addr6);
272
15.4k
    free(msg->msg_cp_dns);
273
274
15.4k
    TAILQ_FOREACH_SAFE(prop, &msg->msg_proposals, prop_entry,
275
15.4k
        proptmp) {
276
0
      TAILQ_REMOVE(&msg->msg_proposals, prop, prop_entry);
277
0
      if (prop->prop_nxforms)
278
0
        free(prop->prop_xforms);
279
0
      free(prop);
280
0
    }
281
282
15.4k
    msg->msg_nonce = NULL;
283
15.4k
    msg->msg_ke = NULL;
284
15.4k
    msg->msg_auth.id_buf = NULL;
285
15.4k
    msg->msg_peerid.id_buf = NULL;
286
15.4k
    msg->msg_localid.id_buf = NULL;
287
15.4k
    msg->msg_cert.id_buf = NULL;
288
61.9k
    for (i = 0; i < IKED_SCERT_MAX; i++)
289
46.4k
      msg->msg_scert[i].id_buf = NULL;
290
15.4k
    msg->msg_cookie = NULL;
291
15.4k
    msg->msg_cookie2 = NULL;
292
15.4k
    msg->msg_del_buf = NULL;
293
15.4k
    msg->msg_eap.eam_user = NULL;
294
15.4k
    msg->msg_cp_addr = NULL;
295
15.4k
    msg->msg_cp_addr6 = NULL;
296
15.4k
    msg->msg_cp_dns = NULL;
297
298
16.5k
    while ((cr = SIMPLEQ_FIRST(&msg->msg_certreqs))) {
299
1.04k
      ibuf_free(cr->cr_data);
300
1.04k
      SIMPLEQ_REMOVE_HEAD(&msg->msg_certreqs, cr_entry);
301
1.04k
      free(cr);
302
1.04k
    }
303
15.4k
  }
304
305
15.4k
  if (msg->msg_data != NULL) {
306
15.4k
    ibuf_free(msg->msg_data);
307
15.4k
    msg->msg_data = NULL;
308
15.4k
  }
309
15.4k
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/regress/parser-libfuzzer/common.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: common.c,v 1.9 2020/11/26 22:29:32 tobhe Exp $ */
2
/*
3
 * A bunch of stub functions so we can compile and link ikev2_pld.c
4
 * in a standalone program for testing purposes.
5
 *
6
 * Placed in the public domain
7
 */
8
9
#include <sys/socket.h>
10
#include <sys/time.h>
11
#include <sys/uio.h>
12
13
#include <event.h>
14
#include <limits.h>
15
#include <string.h>
16
17
#include "iked.h"
18
#include "types.h"
19
20
242k
#define IKEV2_FLAG_INITIATOR            0x08    /* Sent by the initiator */
21
22
int  eap_parse(struct iked *, const struct iked_sa *,
23
      struct iked_message *, void *, int);
24
int  ikev2_msg_frompeer(struct iked_message *);
25
int  ikev2_send_ike_e(struct iked *, struct iked_sa *, struct ibuf *,
26
      u_int8_t, u_int8_t, int);
27
void   ikev2_ikesa_recv_delete(struct iked *, struct iked_sa *);
28
struct iked_childsa *
29
   childsa_lookup(struct iked_sa *, u_int64_t, u_int8_t);
30
int   ikev2_childsa_delete(struct iked *, struct iked_sa *,
31
      u_int8_t, u_int64_t, u_int64_t *, int);
32
int  sa_stateok(const struct iked_sa *, int);
33
void   sa_state(struct iked *, struct iked_sa *, int);
34
void   ikev2_disable_rekeying(struct iked *, struct iked_sa *);
35
void   ikev2_init_ike_sa(struct iked *, void *);
36
struct dh_group *
37
   group_get(u_int32_t);
38
void   timer_set(struct iked *, struct iked_timer *,
39
       void (*)(struct iked *, void *), void *);
40
void   timer_add(struct iked *, struct iked_timer *, int);
41
void   timer_del(struct iked *, struct iked_timer *);
42
ssize_t  ikev2_nat_detection(struct iked *, struct iked_message *,
43
       void *, size_t, u_int, int);
44
int  ca_setreq(struct iked *, struct iked_sa *, struct iked_static_id *,
45
       u_int8_t, u_int8_t, u_int8_t *, size_t, enum privsep_procid);
46
int  ikev2_print_id(struct iked_id *, char *, size_t);
47
int  config_add_transform(struct iked_proposal *, u_int, u_int, u_int,
48
       u_int);
49
struct iked_proposal *
50
   config_add_proposal(struct iked_proposals *, u_int, u_int);
51
void   config_free_proposal(struct iked_proposals *, struct iked_proposal *);
52
int  ikev2_send_informational(struct iked *, struct iked_message *);
53
struct ibuf *
54
   ikev2_msg_decrypt(struct iked *, struct iked_sa *, struct ibuf *,
55
       struct ibuf *);
56
void ikev2_msg_cleanup(struct iked *, struct iked_message *);
57
58
int
59
eap_parse(struct iked *env, const struct iked_sa *sa, struct iked_message *msg,
60
    void *data, int response)
61
3.86k
{
62
3.86k
  return (0);
63
3.86k
}
64
65
/* Copied from ikev2_msg.c for better coverage */
66
int
67
ikev2_msg_frompeer(struct iked_message *msg)
68
242k
{
69
242k
  struct iked_sa    *sa = msg->msg_sa;
70
242k
  struct ike_header *hdr;
71
72
242k
  msg = msg->msg_parent;
73
74
242k
  if (sa == NULL ||
75
242k
      (hdr = ibuf_seek(msg->msg_data, 0, sizeof(*hdr))) == NULL)
76
0
    return (0);
77
78
242k
  if (!sa->sa_hdr.sh_initiator &&
79
242k
      (hdr->ike_flags & IKEV2_FLAG_INITIATOR))
80
65.1k
    return (1);
81
177k
  else if (sa->sa_hdr.sh_initiator &&
82
177k
      (hdr->ike_flags & IKEV2_FLAG_INITIATOR) == 0)
83
0
    return (1);
84
85
177k
  return (0);
86
242k
}
87
88
int
89
ikev2_send_ike_e(struct iked *env, struct iked_sa *sa, struct ibuf *buf,
90
    u_int8_t firstpayload, u_int8_t exchange, int response)
91
0
{
92
0
  return (0);
93
0
}
94
95
void
96
ikev2_ikesa_recv_delete(struct iked *env, struct iked_sa *sa)
97
0
{
98
0
}
99
100
const char *
101
ikev2_ikesa_info(uint64_t spi, const char *msg)
102
9.39k
{
103
9.39k
  return "";
104
9.39k
}
105
106
struct iked_childsa *
107
childsa_lookup(struct iked_sa *a, u_int64_t b, u_int8_t c)
108
0
{
109
0
  return (NULL);
110
0
}
111
112
int
113
ikev2_childsa_delete(struct iked *a, struct iked_sa *b, u_int8_t c,
114
    u_int64_t d, u_int64_t *e , int f)
115
0
{
116
0
  return (0);
117
0
}
118
119
int
120
sa_stateok(const struct iked_sa *a, int b)
121
149
{
122
149
  return (0);
123
149
}
124
125
void
126
sa_state(struct iked * a, struct iked_sa *b, int c)
127
0
{
128
0
}
129
130
void
131
ikev2_disable_rekeying(struct iked *a, struct iked_sa *b)
132
0
{
133
0
}
134
135
void
136
ikev2_init_ike_sa(struct iked *a, void *b)
137
0
{
138
0
}
139
140
const struct group_id *
141
group_getid(u_int32_t id)
142
0
{
143
0
  return (NULL);
144
0
}
145
146
void
147
timer_set(struct iked *env, struct iked_timer *tmr,
148
    void (*cb)(struct iked *, void *), void *arg)
149
0
{
150
0
}
151
152
void
153
timer_add(struct iked *env, struct iked_timer *tmr, int timeout)
154
0
{
155
0
}
156
157
void
158
timer_del(struct iked *env, struct iked_timer *tmr)
159
0
{
160
0
}
161
162
ssize_t
163
ikev2_nat_detection(struct iked *env, struct iked_message *msg,
164
    void *ptr, size_t len, u_int type, int frompeer)
165
26.0k
{
166
26.0k
  bzero(ptr, len);
167
26.0k
  return (0);
168
26.0k
}
169
170
int
171
ca_setreq(struct iked *env, struct iked_sa *sh, struct iked_static_id *localid,
172
    u_int8_t type, u_int8_t more, u_int8_t *data, size_t len,
173
    enum privsep_procid procid)
174
0
{
175
0
  return (0);
176
0
}
177
178
int
179
ikev2_print_id(struct iked_id *id, char *idstr, size_t idstrlen)
180
7.77k
{
181
7.77k
  return (0);
182
7.77k
}
183
184
int
185
config_add_transform(struct iked_proposal *prop, u_int type,
186
    u_int id, u_int length, u_int keylength)
187
0
{
188
0
  return (0);
189
0
}
190
191
struct iked_proposal *
192
config_add_proposal(struct iked_proposals *head, u_int id, u_int proto)
193
69
{
194
69
  return (NULL);
195
69
}
196
197
void
198
config_free_proposal(struct iked_proposals *head, struct iked_proposal *prop)
199
0
{
200
0
  return;
201
0
}
202
203
void config_free_fragments(struct iked_frag *frag)
204
0
{
205
0
  return;
206
0
}
207
208
int
209
ikev2_send_informational(struct iked *env, struct iked_message *msg)
210
748
{
211
748
  return (0);
212
748
}
213
214
struct ibuf *
215
ikev2_msg_decrypt(struct iked *env, struct iked_sa *sa,
216
    struct ibuf *msg, struct ibuf *src)
217
0
{
218
0
  if (src == NULL){
219
0
                fprintf(stderr, "%s\n", "msg_decrypt: src == NULL!");
220
0
                exit(-1);
221
0
        }
222
223
  /*
224
   * Free src as caller uses ikev2_msg_decrypt() like this:
225
   * src = ikev2_msg_decrypt(..., src);
226
   */
227
0
  ibuf_free(src); 
228
0
  return (NULL);
229
0
}
230
231
void
232
ikev2_ike_sa_setreason(struct iked_sa *sa, char *r)
233
0
{
234
0
}
235
236
void
237
ikev2_msg_dispose(struct iked *env, struct iked_msgqueue *queue,
238
    struct iked_msg_retransmit *mr)
239
0
{
240
0
}
241
242
struct iked_msg_retransmit *
243
ikev2_msg_lookup(struct iked *env, struct iked_msgqueue *queue,
244
    struct iked_message *msg, uint8_t exchange)
245
0
{
246
0
  return NULL;
247
0
}
248
249
/* copied from ikev2_msg.c */
250
void
251
ikev2_msg_cleanup(struct iked *env, struct iked_message *msg)
252
15.4k
{
253
15.4k
  struct iked_certreq *cr;
254
15.4k
  struct iked_proposal *prop, *proptmp;
255
15.4k
  int      i;
256
257
15.4k
  if (msg == msg->msg_parent) {
258
15.4k
    ibuf_free(msg->msg_nonce);
259
15.4k
    ibuf_free(msg->msg_ke);
260
15.4k
    ibuf_free(msg->msg_auth.id_buf);
261
15.4k
    ibuf_free(msg->msg_peerid.id_buf);
262
15.4k
    ibuf_free(msg->msg_localid.id_buf);
263
15.4k
    ibuf_free(msg->msg_cert.id_buf);
264
61.9k
    for (i = 0; i < IKED_SCERT_MAX; i++)
265
46.4k
      ibuf_free(msg->msg_scert[i].id_buf);
266
15.4k
    ibuf_free(msg->msg_cookie);
267
15.4k
    ibuf_free(msg->msg_cookie2);
268
15.4k
    ibuf_free(msg->msg_del_buf);
269
15.4k
    free(msg->msg_eap.eam_user);
270
15.4k
    free(msg->msg_cp_addr);
271
15.4k
    free(msg->msg_cp_addr6);
272
15.4k
    free(msg->msg_cp_dns);
273
274
15.4k
    TAILQ_FOREACH_SAFE(prop, &msg->msg_proposals, prop_entry,
275
15.4k
        proptmp) {
276
0
      TAILQ_REMOVE(&msg->msg_proposals, prop, prop_entry);
277
0
      if (prop->prop_nxforms)
278
0
        free(prop->prop_xforms);
279
0
      free(prop);
280
0
    }
281
282
15.4k
    msg->msg_nonce = NULL;
283
15.4k
    msg->msg_ke = NULL;
284
15.4k
    msg->msg_auth.id_buf = NULL;
285
15.4k
    msg->msg_peerid.id_buf = NULL;
286
15.4k
    msg->msg_localid.id_buf = NULL;
287
15.4k
    msg->msg_cert.id_buf = NULL;
288
61.9k
    for (i = 0; i < IKED_SCERT_MAX; i++)
289
46.4k
      msg->msg_scert[i].id_buf = NULL;
290
15.4k
    msg->msg_cookie = NULL;
291
15.4k
    msg->msg_cookie2 = NULL;
292
15.4k
    msg->msg_del_buf = NULL;
293
15.4k
    msg->msg_eap.eam_user = NULL;
294
15.4k
    msg->msg_cp_addr = NULL;
295
15.4k
    msg->msg_cp_addr6 = NULL;
296
15.4k
    msg->msg_cp_dns = NULL;
297
298
16.5k
    while ((cr = SIMPLEQ_FIRST(&msg->msg_certreqs))) {
299
1.04k
      ibuf_free(cr->cr_data);
300
1.04k
      SIMPLEQ_REMOVE_HEAD(&msg->msg_certreqs, cr_entry);
301
1.04k
      free(cr);
302
1.04k
    }
303
15.4k
  }
304
305
15.4k
  if (msg->msg_data != NULL) {
306
15.4k
    ibuf_free(msg->msg_data);
307
15.4k
    msg->msg_data = NULL;
308
15.4k
  }
309
15.4k
}
\ No newline at end of file diff --git a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c.html b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c.html index e1b06fa49..971454157 100644 --- a/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c.html +++ b/coverage/latest/report_target/test_libfuzzer/linux/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c.html @@ -1 +1 @@ -

Coverage Report

Created: 2024-02-21 00:55

/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD$ */
2
/*
3
 * Fuzz tests for payload parsing
4
 *
5
 * Placed in the public domain
6
 */
7
8
#include <sys/socket.h>
9
#include <sys/queue.h>
10
#include <sys/uio.h>
11
12
#include <event.h>
13
#include <imsg.h>
14
#include <string.h>
15
16
#include "iked.h"
17
#include "ikev2.h"
18
19
u_int8_t cookies[] = {
20
  0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x01, /* initator cookie */
21
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* responder cookie */
22
};
23
24
u_int8_t genhdr[] = {
25
  0x00, 0x20, 0x22, 0x08, /* next, major/minor, exchange type, flags */
26
  0x00, 0x00, 0x00, 0x00, /* message ID */
27
  0x00, 0x00, 0x00, 0x00  /* total length */
28
};
29
30
15.4k
#define OFFSET_ICOOKIE    0
31
15.4k
#define OFFSET_RCOOKIE    8
32
15.4k
#define OFFSET_NEXTPAYLOAD  (0 + sizeof(cookies))
33
15.4k
#define OFFSET_VERSION    (1 + sizeof(cookies))
34
15.4k
#define OFFSET_EXCHANGE   (2 + sizeof(cookies))
35
15.4k
#define OFFSET_LENGTH   (8 + sizeof(cookies))
36
37
static u_int8_t *
38
get_icookie(u_int8_t *data)
39
15.4k
{
40
15.4k
  return &data[OFFSET_ICOOKIE];
41
15.4k
}
42
43
static u_int8_t *
44
get_rcookie(u_int8_t *data)
45
15.4k
{
46
15.4k
  return &data[OFFSET_RCOOKIE];
47
15.4k
}
48
49
static u_int8_t
50
get_nextpayload(u_int8_t *data)
51
15.4k
{
52
15.4k
  return data[OFFSET_NEXTPAYLOAD];
53
15.4k
}
54
55
static u_int8_t
56
get_version(u_int8_t *data)
57
15.4k
{
58
15.4k
  return data[OFFSET_VERSION];
59
15.4k
}
60
61
static u_int8_t
62
get_exchange(u_int8_t *data)
63
15.4k
{
64
15.4k
  return data[OFFSET_EXCHANGE];
65
15.4k
}
66
67
static u_int32_t
68
get_length(u_int8_t *data)
69
15.4k
{
70
15.4k
  return *(u_int32_t *)&data[OFFSET_LENGTH];
71
15.4k
}
72
73
static void
74
prepare_header(struct ike_header *hdr, struct ibuf *data)
75
15.4k
{
76
15.4k
  bzero(hdr, sizeof(*hdr));
77
15.4k
  bcopy(get_icookie(ibuf_data(data)), &hdr->ike_ispi,
78
15.4k
      sizeof(hdr->ike_ispi));
79
15.4k
  bcopy(get_rcookie(ibuf_data(data)), &hdr->ike_rspi,
80
15.4k
      sizeof(hdr->ike_rspi));
81
15.4k
  hdr->ike_nextpayload = get_nextpayload(ibuf_data(data));
82
15.4k
  hdr->ike_version = get_version(ibuf_data(data));
83
15.4k
  hdr->ike_exchange = get_exchange(ibuf_data(data));
84
15.4k
  hdr->ike_length = get_length(ibuf_data(data));
85
15.4k
}
86
87
static void
88
prepare_message(struct iked_message *msg, struct ibuf *data)
89
15.4k
{
90
15.4k
  static struct iked_sa sa;
91
92
15.4k
  bzero(&sa, sizeof(sa));
93
15.4k
  bzero(msg, sizeof(*msg));
94
95
15.4k
  msg->msg_sa = &sa;
96
15.4k
  msg->msg_data = data;
97
15.4k
  msg->msg_e = 1;
98
15.4k
  msg->msg_parent = msg;
99
100
15.4k
  TAILQ_INIT(&msg->msg_proposals);
101
15.4k
  SIMPLEQ_INIT(&msg->msg_certreqs);
102
15.4k
}
103
104
/* Entry-Point for libFuzzer */
105
int
106
LLVMFuzzerTestOneInput(const char *data, size_t size)
107
15.4k
{
108
15.4k
  struct ibuf   *fuzzed;
109
15.4k
  struct ike_header  hdr;
110
15.4k
  struct iked_message  msg;
111
112
15.4k
  bzero(&hdr, sizeof(hdr));
113
15.4k
  bzero(&msg, sizeof(msg));
114
115
15.4k
  fuzzed = ibuf_new(data, size);
116
15.4k
  if (fuzzed == NULL){
117
0
    fprintf(stderr, "%s\n", "ERROR: fuzzed == NULL! "
118
0
        "(hint: fuzz-input too long?)");
119
0
    return -1;
120
0
  }  
121
  
122
  /* size too small? */
123
15.4k
  if (size < sizeof(cookies) + sizeof(genhdr)){
124
1
    ibuf_free(fuzzed);
125
1
    return 0;
126
1
  }         
127
128
15.4k
  prepare_header(&hdr, fuzzed);
129
15.4k
  prepare_message(&msg, fuzzed);
130
131
15.4k
  ikev2_pld_parse(NULL, &hdr, &msg, 0);
132
133
15.4k
  ikev2_msg_cleanup(NULL, &msg);
134
135
15.4k
  return 0;
136
15.4k
}
\ No newline at end of file +

Coverage Report

Created: 2024-02-22 00:54

/src/openiked-portable/regress/parser-libfuzzer/test_parser_fuzz.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD$ */
2
/*
3
 * Fuzz tests for payload parsing
4
 *
5
 * Placed in the public domain
6
 */
7
8
#include <sys/socket.h>
9
#include <sys/queue.h>
10
#include <sys/uio.h>
11
12
#include <event.h>
13
#include <imsg.h>
14
#include <string.h>
15
16
#include "iked.h"
17
#include "ikev2.h"
18
19
u_int8_t cookies[] = {
20
  0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x01, /* initator cookie */
21
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* responder cookie */
22
};
23
24
u_int8_t genhdr[] = {
25
  0x00, 0x20, 0x22, 0x08, /* next, major/minor, exchange type, flags */
26
  0x00, 0x00, 0x00, 0x00, /* message ID */
27
  0x00, 0x00, 0x00, 0x00  /* total length */
28
};
29
30
15.4k
#define OFFSET_ICOOKIE    0
31
15.4k
#define OFFSET_RCOOKIE    8
32
15.4k
#define OFFSET_NEXTPAYLOAD  (0 + sizeof(cookies))
33
15.4k
#define OFFSET_VERSION    (1 + sizeof(cookies))
34
15.4k
#define OFFSET_EXCHANGE   (2 + sizeof(cookies))
35
15.4k
#define OFFSET_LENGTH   (8 + sizeof(cookies))
36
37
static u_int8_t *
38
get_icookie(u_int8_t *data)
39
15.4k
{
40
15.4k
  return &data[OFFSET_ICOOKIE];
41
15.4k
}
42
43
static u_int8_t *
44
get_rcookie(u_int8_t *data)
45
15.4k
{
46
15.4k
  return &data[OFFSET_RCOOKIE];
47
15.4k
}
48
49
static u_int8_t
50
get_nextpayload(u_int8_t *data)
51
15.4k
{
52
15.4k
  return data[OFFSET_NEXTPAYLOAD];
53
15.4k
}
54
55
static u_int8_t
56
get_version(u_int8_t *data)
57
15.4k
{
58
15.4k
  return data[OFFSET_VERSION];
59
15.4k
}
60
61
static u_int8_t
62
get_exchange(u_int8_t *data)
63
15.4k
{
64
15.4k
  return data[OFFSET_EXCHANGE];
65
15.4k
}
66
67
static u_int32_t
68
get_length(u_int8_t *data)
69
15.4k
{
70
15.4k
  return *(u_int32_t *)&data[OFFSET_LENGTH];
71
15.4k
}
72
73
static void
74
prepare_header(struct ike_header *hdr, struct ibuf *data)
75
15.4k
{
76
15.4k
  bzero(hdr, sizeof(*hdr));
77
15.4k
  bcopy(get_icookie(ibuf_data(data)), &hdr->ike_ispi,
78
15.4k
      sizeof(hdr->ike_ispi));
79
15.4k
  bcopy(get_rcookie(ibuf_data(data)), &hdr->ike_rspi,
80
15.4k
      sizeof(hdr->ike_rspi));
81
15.4k
  hdr->ike_nextpayload = get_nextpayload(ibuf_data(data));
82
15.4k
  hdr->ike_version = get_version(ibuf_data(data));
83
15.4k
  hdr->ike_exchange = get_exchange(ibuf_data(data));
84
15.4k
  hdr->ike_length = get_length(ibuf_data(data));
85
15.4k
}
86
87
static void
88
prepare_message(struct iked_message *msg, struct ibuf *data)
89
15.4k
{
90
15.4k
  static struct iked_sa sa;
91
92
15.4k
  bzero(&sa, sizeof(sa));
93
15.4k
  bzero(msg, sizeof(*msg));
94
95
15.4k
  msg->msg_sa = &sa;
96
15.4k
  msg->msg_data = data;
97
15.4k
  msg->msg_e = 1;
98
15.4k
  msg->msg_parent = msg;
99
100
15.4k
  TAILQ_INIT(&msg->msg_proposals);
101
15.4k
  SIMPLEQ_INIT(&msg->msg_certreqs);
102
15.4k
}
103
104
/* Entry-Point for libFuzzer */
105
int
106
LLVMFuzzerTestOneInput(const char *data, size_t size)
107
15.4k
{
108
15.4k
  struct ibuf   *fuzzed;
109
15.4k
  struct ike_header  hdr;
110
15.4k
  struct iked_message  msg;
111
112
15.4k
  bzero(&hdr, sizeof(hdr));
113
15.4k
  bzero(&msg, sizeof(msg));
114
115
15.4k
  fuzzed = ibuf_new(data, size);
116
15.4k
  if (fuzzed == NULL){
117
0
    fprintf(stderr, "%s\n", "ERROR: fuzzed == NULL! "
118
0
        "(hint: fuzz-input too long?)");
119
0
    return -1;
120
0
  }  
121
  
122
  /* size too small? */
123
15.4k
  if (size < sizeof(cookies) + sizeof(genhdr)){
124
1
    ibuf_free(fuzzed);
125
1
    return 0;
126
1
  }         
127
128
15.4k
  prepare_header(&hdr, fuzzed);
129
15.4k
  prepare_message(&msg, fuzzed);
130
131
15.4k
  ikev2_pld_parse(NULL, &hdr, &msg, 0);
132
133
15.4k
  ikev2_msg_cleanup(NULL, &msg);
134
135
15.4k
  return 0;
136
15.4k
}
\ No newline at end of file