File: kernel_sadb.c

package info (click to toggle)
libreswan 5.2-2.3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 81,644 kB
  • sloc: ansic: 129,988; sh: 32,018; xml: 20,646; python: 10,303; makefile: 3,022; javascript: 1,506; sed: 574; yacc: 511; perl: 264; awk: 52
file content (150 lines) | stat: -rw-r--r-- 4,634 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* Interface to the PF_KEY v2 IPsec mechanism, for Libreswan
 *
 * Copyright (C)  2022  Andrew Cagney
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.  See <https://www.gnu.org/licenses/gpl2.txt>.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

#include "kernel_sadb.h"

#include "lswlog.h"
#include "ip_protocol.h"
#include "ip_sockaddr.h"
#include "ip_info.h"
#include "verbose.h"

bool get_sadb_sockaddr_address_port(shunk_t *cursor,
				    ip_address *address,
				    ip_port *port,
				    struct verbose verbose)
{
	err_t err = sockaddr_to_address_port(cursor->ptr, cursor->len,
					     address, port);
	if (err != NULL) {
		llog_pexpect(verbose.logger, HERE, "invalid sockaddr: %s", err);
		return false;
	}
	const struct ip_info *afi = address_type(address);
	cursor->ptr += afi->sockaddr_size;
	cursor->len -= afi->sockaddr_size;
	return true;
}

const struct sadb_ext *get_sadb_ext(shunk_t *msgbase,
				    shunk_t *msgext,
				    struct verbose verbose)
{
	shunk_t tmp = *msgbase;
	const struct sadb_ext *ext =
		hunk_get_thing(&tmp, const struct sadb_ext);
	vassert(ext != NULL);

	size_t len = ext->sadb_ext_len * sizeof(uint64_t);
	if (len == 0) {
		llog_passert(verbose.logger, HERE,
			     "have zero bytes");
	}
	if (msgbase->len < len) {
		llog_passert(verbose.logger, HERE,
			     "have %zu bytes but should be %zu",
			     msgbase->len, len);
	}

	/* note: include EXT read above; will re-read */
	*msgext = shunk2(msgbase->ptr, len);

	/* then advance */
	msgbase->ptr += len;
	msgbase->len -= len;

	return ext;
}

/*
 * XXX: the x_ipsecrequest extension messed up the convention by
 * storing the nr-bytes in len.  Hence LEN_MULTIPLIER.
 */

#define GET_SADB(TYPE, LEN_MULTIPLIER) X_GET_SADB(TYPE, LEN_MULTIPLIER)
#define X_GET_SADB(TYPE, LEN_MULTIPLIER)				\
	const struct TYPE *get_##TYPE(shunk_t *cursor,			\
				      shunk_t *type_cursor,		\
				      struct verbose verbose)		\
	{								\
		*type_cursor = null_shunk;				\
		if (sizeof(struct TYPE) > cursor->len) {		\
			llog_pexpect(verbose.logger, HERE,		\
				     "%zu-byte buffer too small for %zu-byte "#TYPE, \
				     cursor->len, sizeof(struct TYPE));	\
			return NULL;					\
		}							\
		/* SADB stream is aligned */				\
		const struct TYPE *type = cursor->ptr;			\
		size_t type_len = type->TYPE##_len * LEN_MULTIPLIER;	\
		if (type_len < sizeof(struct TYPE)) {			\
			llog_pexpect(verbose.logger, HERE,		\
				     "%zu-byte "#TYPE" bigger than "#TYPE"_len=%u(%zu-bytes)", \
				     sizeof(struct TYPE), type->TYPE##_len, type_len); \
			return NULL;					\
		}							\
		if (type_len > (cursor)->len) {				\
			llog_pexpect(verbose.logger, HERE,		\
				     "%zu-byte buffer too small for "#TYPE"_len=%u(%zu-bytes)", \
				     cursor->len, type->TYPE##_len, type_len); \
			return NULL;					\
		}							\
		/* type_cursor */					\
		(type_cursor)->ptr = (cursor)->ptr + sizeof(struct TYPE); \
		(type_cursor)->len = type_len - sizeof(struct TYPE);	\
		/* now skip to next field */				\
		(cursor)->ptr += type_len;				\
		(cursor)->len -= type_len;				\
		return type;						\
	}

GET_SADB(sadb_address, sizeof(uint64_t));
GET_SADB(sadb_key, sizeof(uint64_t));
GET_SADB(sadb_lifetime, sizeof(uint64_t));
GET_SADB(sadb_msg, sizeof(uint64_t));
GET_SADB(sadb_prop, sizeof(uint64_t));
GET_SADB(sadb_sa, sizeof(uint64_t));
GET_SADB(sadb_spirange, sizeof(uint64_t));
GET_SADB(sadb_supported, sizeof(uint64_t));
#ifdef SADB_X_EXT_POLICY
GET_SADB(sadb_x_ipsecrequest, sizeof(uint8_t)); /* XXX: see rfc, screwup */
#endif
#ifdef SADB_X_EXT_NAT_T_TYPE
GET_SADB(sadb_x_nat_t_type, sizeof(uint64_t));
#endif
#ifdef SADB_X_EXT_POLICY
GET_SADB(sadb_x_policy, sizeof(uint64_t));
#endif
#ifdef SADB_X_EXT_SA2
GET_SADB(sadb_x_sa2, sizeof(uint64_t));
#endif
#ifdef SADB_X_EXT_SA_REPLAY
GET_SADB(sadb_x_sa_replay, sizeof(uint64_t));
#endif
#ifdef SADB_X_EXT_COUNTER
GET_SADB(sadb_x_counter, sizeof(uint64_t));
#endif
#ifdef SADB_X_EXT_PROTOCOL
GET_SADB(sadb_protocol, sizeof(uint64_t));
#endif
#ifdef SADB_X_EXT_REPLAY /* OpenBSD */
GET_SADB(sadb_x_replay, sizeof(uint64_t));
#endif
#ifdef SADB_X_EXT_UDPENCAP
GET_SADB(sadb_x_udpencap, sizeof(uint64_t));
#endif
#ifdef SADB_X_EXT_IFACE
GET_SADB(sadb_x_iface, sizeof(uint64_t));
#endif