File: iface.h

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 (224 lines) | stat: -rw-r--r-- 7,392 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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/* iface, for libreswan
 *
 * Copyright (C) 1998-2001,2013  D. Hugh Redelmeier <hugh@mimosa.com>
 * Copyright (C) 2012-2013 Paul Wouters <paul@libreswan.org>
 * Copyright (C) 2013 Florian Weimer <fweimer@redhat.com>
 * Copyright (C) 2019-2020 Andrew Cagney
 * Copyright (C) 2017 Mayank Totale <mtotale@gmail.com>
 *
 * 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.
 */

#ifndef IFACE_H
#define IFACE_H

#include "ip_endpoint.h"
#include "refcnt.h"
#include "list_entry.h"
#include "shunk.h"

struct fd;
struct kernel_iface;
struct iface_endpoint;
struct show;
struct iface_device;
struct logger;

struct iface_packet {
	ssize_t len;
	ip_endpoint sender;
	uint8_t *ptr;
	struct logger *logger; /*global*/
};

struct iface_io {
	bool send_keepalive;
	struct {
		int type;
		const char *type_name;
	} socket;
	const struct ip_protocol *protocol;
	struct msg_digest *(*read_packet)(struct iface_endpoint **ifp,
					  struct logger *logger);
	ssize_t (*write_packet)(const struct iface_endpoint *ifp,
				shunk_t packet,
				const ip_endpoint *remote_endpoint,
				struct logger *logger);
	void (*cleanup)(struct iface_endpoint *ifp);
	void (*listen)(struct iface_endpoint *fip, struct logger *logger);
	/* returns 0 or ERRNO */
	int (*enable_esp_encapsulation)(int fd, struct logger *logger);
};

extern const struct iface_io udp_iface_io;
extern const struct iface_io iketcp_iface_io; /*IKETCP specific*/

/* interface: a terminal point for IKE traffic, IPsec transport mode
 * and IPsec tunnels.
 * Essentially:
 * - an IP device (eg. eth1), and
 * - its partner, an ipsec device (eg. ipsec0), and
 * - their shared IP address (eg. 10.7.3.2)
 * Note: the port for IKE is always implicitly UDP/pluto_port.
 *
 * The iface is a unique IP address on a system. It may be used by
 * multiple port numbers. In general, two conns have the same
 * interface if they have the same iface_endpoint->iface_alias.
 */

struct iface_device {
	struct list_entry entry;
	refcnt_t refcnt;
	char *real_device_name;
	bool nic_offload;
	ip_address local_address;
	enum { IFD_ADD, IFD_KEEP, IFD_DELETE } ifd_change;
};

struct iface_device *next_iface_device(struct iface_device *);

struct iface_device *find_iface_device_by_address(const ip_address *address);

struct iface_device *iface_device_addref_where(struct iface_device *ifp, where_t where);
#define iface_addref(IFP) iface_device_addref_where(IFP, HERE)

void iface_device_delref_where(struct iface_device **ifp, where_t where);
#define iface_device_delref(IFP) iface_device_delref_where(IFP, HERE)

struct iface_endpoint {
	refcnt_t refcnt;
	struct iface_device *ip_dev;
	const struct iface_io *io;
	ip_endpoint local_endpoint;	/* interface IP address:port */
	int fd;                 /* file descriptor of socket for IKE UDP messages */
	struct iface_endpoint *next;
	struct list_entry entry;
	/*
	 * Here's what the RFC has to say:
	 *
	 * 2.  IKE Protocol Details and Variations
	 *
	 *     The UDP payload of all packets containing IKE messages
	 *     sent on port 4500 MUST begin with the prefix of four
	 *     zeros; otherwise, the receiver won't know how to handle
	 *     them.
	 *
	 * 2.23.  NAT Traversal
	 *
	 *     ... UDP encapsulation MUST NOT be done on port 500.
	 *
	 * 3.1.  The IKE Header
	 *
	 *     When sent on UDP port 500, IKE messages begin
	 *     immediately following the UDP header.  When sent on UDP
	 *     port 4500, IKE messages have prepended four octets of
	 *     zeros.
	 *
	 * I'm assuming that "sent on port ..." is intended to mean
	 * "sent from port ... to port ...".  But now we've got us
	 * deliberately sending from a random port to ...
	 *
	 * to port 500 with no ESP=0:
	 * -> since esp encal is disabled, the kernel passes the packet through
	 * -> pluto responds with no ESP=0
	 *
	 * to port 500 with ESP=0:
	 * -> since esp encal is disabled, the kernel passes the packet through
	 * -> pluto sees the ESP=0 prefix and rejects it
	 *
	 * to port 4500 with no ESP=0:
	 * -> since esp encap is enabled, the kernel will see the leading bytes
	 * are non-zero and eats an ESP packet
	 *
	 * to port 4500 with ESP=0:
	 * -> since esp encap is enabled, and ESP=0, kernel passes the packet through
	 * -> pluto sees ESP=0 prefix
	 * -> pluto responds with ESP=0 prefix
	 *
	 * to a random port:
	 * - to be able to work with NAT esp encap needs to be enabled and that
	 * in turn means all incoming messages must have the ESP=0 prefix
	 * - trying to negotiate to port 500 will fail - the incoming message
	 * will be missing the ESP=0 prefix
	 */
	bool esp_encapsulation_enabled;
	/*
	 * For IKEv2 2.23.  NAT Traversal.  When NAT is detected, must
	 * the initiators float away, switching to port 4500?  This
	 * doesn't make sense for TCP, and this doesn't make sense
	 * when using IKEPORT.
	 */
	bool float_nat_initiator;
	/* udp only */
	struct {
		struct fd_read_listener *read_listener;
	} udp;
	struct {
		/* tcp port only */
		struct fd_accept_listener *accept_listener;
		/* tcp stream only */
		struct timeout *prefix_timeout;
		struct fd_read_listener *read_listener;
	} iketcp;
	ip_endpoint iketcp_remote_endpoint;
	bool iketcp_server;
	enum iketcp_state {
		IKETCP_ACCEPTED = 1,
		IKETCP_PREFIX_RECEIVED, /* received IKETCP */
		IKETCP_ENABLED, /* received at least one packet */
		IKETCP_STOPPED, /* waiting on state to close */
	} iketcp_state;
};

void stop_iketcp_iface_endpoint(struct iface_endpoint **ifp);

struct iface_endpoint *iface_endpoint_addref_where(struct iface_endpoint *ifp, where_t where);
#define iface_endpoint_addref(IFP) iface_endpoint_addref_where(IFP, HERE)

void iface_endpoint_delref_where(struct iface_endpoint **ifp, where_t where);
#define iface_endpoint_delref(IFP) iface_endpoint_delref_where(IFP, HERE)

extern struct iface_endpoint *find_iface_endpoint_by_local_endpoint(ip_endpoint local_endpoint);
extern void find_ifaces(bool rm_dead, struct logger *logger);
extern void show_ifaces_status(struct show *s);
void listen_on_iface_endpoint(struct iface_endpoint *ifp, struct logger *logger);

enum iface_esp_encapsulation {
	ESP_ENCAPSULATION_ENABLED = 1,
	ESP_ENCAPSULATION_DISABLED,
};

enum iface_initiator_port {
	INITIATOR_PORT_FIXED = 1,
	INITIATOR_PORT_FLOATS,
};

struct iface_endpoint *bind_iface_endpoint(struct iface_device *ifd,
					   const struct iface_io *io,
					   ip_port port,
					   enum iface_esp_encapsulation esp_encapsulation,
					   enum iface_initiator_port initiator_port,
					   struct logger *logger);

/* internal */
struct iface_endpoint *alloc_iface_endpoint(int fd,
					    struct iface_device *ifd,
					    const struct iface_io *io,
					    enum iface_esp_encapsulation esp_encapsulation,
					    enum iface_initiator_port initiator_port,
					    ip_endpoint local_endpoint,
					    where_t where);

extern char *pluto_listen;	/* from --listen flag */

extern void shutdown_ifaces(struct logger *logger);

#endif