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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
|
/* Netfilter Driver for IPSec VPN Client
*
* Copyright(c) 2012 Samsung Electronics
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* interceptor.h
*
* Interceptor API specifies the Interceptor side interface between
* the Interceptor and Engine components. This API contains functions
* for Interceptor initialization, packet allocation, packet data access,
* routing and packet sending.
*
*/
#ifndef INTERCEPTOR_H
#define INTERCEPTOR_H
#include "sshinet.h"
/** The amount of space to reserve in packet header for the IPsec engine. */
#define SSH_INTERCEPTOR_UPPER_DATA_SIZE 192
/** The number of available extension selectors for platform-specific
extensions. */
#define SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS 1
/** Size of interface system name. */
#define SSH_INTERCEPTOR_IFNAME_SIZE 64
/** Data type for the interceptor context. */
typedef struct SshInterceptorRec *SshInterceptor;
/** This type defines the type of a network interface interface. The
type is supposed to be sufficient to determine how to process the
packets. It is not expected to provide maximal detail to the
user. Regardless of the interface type, the higher-level code
should not assume that incoming packets have been defragmented,
nor will it assume that the interceptor will perform fragmentation
for outgoing packets. Thus, it will perform these functions
itself. It will not assume the underlying interceptor will do it.
Routing will also be done by the higher level to determine which
interface a packet should go out from. */
typedef enum {
SSH_INTERCEPTOR_MEDIA_NONEXISTENT, /** The interface is not available */
SSH_INTERCEPTOR_MEDIA_PLAIN, /** Any interceptor w/o media headers*/
SSH_INTERCEPTOR_MEDIA_ETHERNET, /** Ethernet (rfc894) framing */
SSH_INTERCEPTOR_MEDIA_FDDI, /** FDDI (rfc1042/rfc1103) framing */
SSH_INTERCEPTOR_MEDIA_TOKENRING, /** Tokenring (rfc1042/rfc1469) framing */
/** New types may be added here. Look for one of the existing types
to find all places in code that should be updated. */
SSH_INTERCEPTOR_NUM_MEDIAS /** Must be the last entry! */
} SshInterceptorMedia;
/** Protocol identifiers. These identify recognized protocols (packet
formats) in a portable manner. This enumeration includes media
types, but also all recognized higher-level protocols. */
typedef enum
{
SSH_PROTOCOL_IP4, /** IPv4 frame */
SSH_PROTOCOL_IP6, /** IPv6 frame */
SSH_PROTOCOL_IPX, /** IPX frame */
SSH_PROTOCOL_ETHERNET, /** Ethernet frame */
SSH_PROTOCOL_FDDI, /** FDDI frame */
SSH_PROTOCOL_TOKENRING, /** Token Ring frame */
SSH_PROTOCOL_ARP, /** ARP frame */
SSH_PROTOCOL_OTHER, /** some other type frame */
SSH_PROTOCOL_NUM_PROTOCOLS /** must be the last entry! */
} SshInterceptorProtocol;
/** Data type for an interface number. This type must be atleast as big as
the system interface index. */
typedef SshUInt32 SshInterceptorIfnum;
/** Maximum value of interface number.
All valid interface numbers must be smaller than this value. */
#define SSH_INTERCEPTOR_MAX_IFNUM ((SshInterceptorIfnum) 0xffffffff)
/** Reserved value for invalid interface number. */
#define SSH_INTERCEPTOR_INVALID_IFNUM SSH_INTERCEPTOR_MAX_IFNUM
/** Data structure for representing an address for a network interface. */
typedef struct SshInterfaceAddressRec
{
/** Protocol for which the address is. */
SshInterceptorProtocol protocol;
/** The address itself. */
union
{
/** IPv4 and IPv6. */
struct
{
SshIpAddrStruct ip;
SshIpAddrStruct mask;
SshIpAddrStruct broadcast;
} ip;
/** IPX */
struct
{
SshUInt32 net;
unsigned char host[6];
} ns;
} addr;
} *SshInterfaceAddress, SshInterfaceAddressStruct;
/** Flags for the media direction information. */
/** Do not fragment before sending from engine. */
#define SSH_INTERCEPTOR_MEDIA_INFO_NO_FRAGMENT 0x0001
/** Accessor for mtu member in SshInterceptorMediaDirectionInfo. */
#ifdef WITH_IPV6
#define SSH_INTERCEPTOR_MEDIA_INFO_MTU(info, is_ipv6) \
((is_ipv6) ? (info)->mtu_ipv6 : (info)->mtu_ipv4)
#else /* WITH_IPV6 */
#define SSH_INTERCEPTOR_MEDIA_INFO_MTU(info, is_ipv6) \
((info)->mtu_ipv4)
#endif /* WITH_IPV6 */
/** Media direction information. This information is used when engine
is sending packets to the interceptor. */
typedef struct SshInterceptorMediaDirectionInfoRec
{
SshInterceptorMedia media; /* media type */
SshUInt32 flags; /* flags */
size_t mtu_ipv4; /* mtu for the direction (ipv4) */
#ifdef WITH_IPV6
size_t mtu_ipv6; /* mtu for the direction (ipv6) */
#endif /* WITH_IPV6 */
} *SshInterceptorMediaDirectionInfo, SshInterceptorMediaDirectionInfoStruct;
/** Flag values for flags in SshInterceptorInterface */
/* Interface type */
#define SSH_INTERFACE_FLAG_VIP 0x0001
#define SSH_INTERFACE_FLAG_POINTOPOINT 0x0002
#define SSH_INTERFACE_FLAG_BROADCAST 0x0004
/* Interface link status */
#define SSH_INTERFACE_FLAG_LINK_DOWN 0x0100
/** Data structure for providing information about a network
interface. */
typedef struct
{
SshInterceptorMediaDirectionInfoStruct to_protocol;
SshInterceptorMediaDirectionInfoStruct to_adapter;
char name[SSH_INTERCEPTOR_IFNAME_SIZE]; /** system name for the interface */
SshInterceptorIfnum ifnum; /** Interface number */
SshUInt32 num_addrs; /** Number of addresses for the interface. */
SshInterfaceAddress addrs; /** mallocated array of address structures. */
unsigned char media_addr[16]; /** MAC address, medium size and format */
size_t media_addr_len; /** Length of the MAC address. */
SshUInt32 flags; /** Flags for the interface. */
/** Context pointer for owner/user for this SshInterceptorInterface.
Can be used for e.g. storing interface-specific
NAT-configuration. */
void *ctx_user;
} SshInterceptorInterface;
/* Packet flag bits. */
#define SSH_PACKET_FROMPROTOCOL 0x00000001U /** Packet from the protocol. */
#define SSH_PACKET_FROMADAPTER 0x00000002U /** Packet from the adapter. */
#define SSH_PACKET_IP4HDRCKSUMOK 0x00000004U /** IPv4 header cksum checked. */
#define SSH_PACKET_FORWARDED 0x00000008U /** Packet was forwarded. */
#define SSH_PACKET_HWCKSUM 0x00000010U /** TCP/UDP cksum done by NIC. */
#define SSH_PACKET_MEDIABCAST 0x00000020U /** Packet was media broadcast. */
#define SSH_PACKET_UNMODIFIED 0x00000200U /** Unmodified packet. */
/* This flag specifies that the engine is allowed to fragment the packet if
the packet is too large to fit into interafce MTU. Some operating
system handle the fragmentation after us and therefore this flag
may be set for some outbound data packets. The packet is guaranteed
to have been originated from local stack and stack has indicated
that this packet can be fragmented. */
#define SSH_PACKET_FRAGMENTATION_ALLOWED 0x00000400U
/* Flag bits with mask 0x00000fff are reserved for interceptor. */
/* Flag bits with mask 0xfffff000 are reserved for IPSEC engine. */
/** Macro to access upper-level data in the packet header. */
#define SSH_INTERCEPTOR_PACKET_DATA(packet, type) \
((type)(&(packet)->upper_data))
/** Data structure for a packet. These data structures can only be
allocated by the interceptor; higher-level code must never
directly allocate these (the interceptor implementation may
actually use a larger structure containing this public
structure). */
typedef struct SshInterceptorPacketRec
{
/** Flags for the packet. The SSH_PACKET_* bitmasks are used. Code
above the interceptor is not allowed to modify flags 0x001-0x800;
they may be used internally by the interceptor to pass
information from packet_cb/ssh_interceptor_packet_alloc to
ssh_interceptor_send/ssh_interceptor_packet_free. During
certain times, such when applying asynchronous IPSEC
transformations, this field may be changed concurrently by
another thread (or interrupt) even when another thread is
processing the packet. Care should be taken with locking in
those situations. */
SshUInt32 flags;
/** Number of the interface that this packet arrived from */
SshInterceptorIfnum ifnum_in;
/** Number of the interface that this packet going out */
SshInterceptorIfnum ifnum_out;
/** Format of the packet (protocol identifier). */
SshInterceptorProtocol protocol;
/** Path MTU stored for this packet, which must be respected at
media send (if interface MTU is smaller than this value, then
the media send routine must send ICMP PMTU message and discard
the packet). If 0, means use the interface MTU only. */
SshUInt32 pmtu;
#if (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0)
/** Platform-dependent extension selectors for things like user id,
virtual network identifier, etc. */
SshUInt32 extension[SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS];
#endif /* (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0) */
#ifdef SSH_IPSEC_IP_ONLY_INTERCEPTOR
/** Route key selector that was used in the route lookup */
SshUInt16 route_selector;
#endif /* SSH_IPSEC_IP_ONLY_INTERCEPTOR */
/** Buffer that can be used by higher level software to store its
data (such as cached media addresses). This field can only be
accessed using the SSH_INTERCEPTOR_PACKET_DATA macro. */
union {
/** Contents of this union are private (they are there to
guarantee proper alignment for any data structure stored
here). */
long force_alignment_l; int force_alignment_i; short force_alignment_s;
void *force_alignment_v;
SshUInt16 force_alignment_i16; SshUInt32 force_alignment_i32;
SshUInt64 force_alignment_i64;
char force_size_dont_use_this_directly[SSH_INTERCEPTOR_UPPER_DATA_SIZE];
/* Should have double here if floating point was allowed. */
} upper_data;
/** Next pointer on freelist. This can also be used by higher-level
code to put the packet on a list. */
struct SshInterceptorPacketRec *next;
} *SshInterceptorPacket, SshInterceptorPacketStruct;
/** Error codes for route add / remove functions. */
typedef enum {
SSH_INTERCEPTOR_ROUTE_ERROR_OK = 0,
SSH_INTERCEPTOR_ROUTE_ERROR_NONEXISTENT = 1,
SSH_INTERCEPTOR_ROUTE_ERROR_OUT_OF_MEMORY = 2,
SSH_INTERCEPTOR_ROUTE_ERROR_ALREADY_EXISTS = 3,
SSH_INTERCEPTOR_ROUTE_ERROR_UNDEFINED = 255
} SshInterceptorRouteError;
/** Flag values for the route add / remove functions. */
/** Ignore non-existent routes when attempting to remove the route. */
#define SSH_INTERCEPTOR_ROUTE_FLAG_IGNORE_NONEXISTENT 0x0001
/** Data structure for routing key, used in route lookups and routing table
manipulation.
The route lookup is performed for the destination address, using other
fields in the routing key to enforce routing policies. It is a fatal
error to call ssh_interceptor_route using a SshInterceptorRouteKey
which does not have the destination address set.
Use the provided macros for setting fields in SshInterceptorRouteKey.
Note that on platforms that do not support policy routing, the route lookup
uses only the destination address. On other platforms other fields of the
SshInterceptorRouteKey may be used in the route lookup. */
typedef struct SshInterceptorRouteKeyRec
{
/** Destination address, mandatory */
SshIpAddrStruct dst;
/** Source address, optional */
SshIpAddrStruct src;
/** IP protocol identifier, optional */
SshUInt32 ipproto;
/** Interface number, optional.
Note that this field specifies either the inbound interface number
or the outbound interface number, depending on the value of the
'selector' field. */
SshUInt32 ifnum;
/** Network layer fields */
union
{
/** IPv4 TOS, optional */
struct
{
SshUInt8 tos;
} ip4;
/** IPv6 priority and flow label, optional */
struct
{
SshUInt8 priority;
SshUInt32 flow;
} ip6;
/** For encoding / decoding */
unsigned char raw[5];
} nh;
/** Transport layer fields */
union
{
/** TCP / UDP ports, optional */
struct
{
SshUInt16 dst_port;
SshUInt16 src_port;
} tcp;
/** ICMP type and code, optional */
struct
{
SshUInt8 type;
SshUInt8 code;
} icmp;
/** ESP / AH spi, optional */
struct
{
SshUInt32 spi;
} ipsec;
/** For encoding / decoding */
unsigned char raw[4];
} th;
#if (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0)
/** Platform-dependent extension selectors, optional */
SshUInt32 extension[SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS];
#endif /* (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0) */
/** Bitmap of selectors that are to be used in the route lookup.
Use the provided macros to add selectors to the routing key,
do not access this field directly. The highest 3 bits of
'selector' are reserved for flags defined below. */
SshUInt16 selector;
} *SshInterceptorRouteKey, SshInterceptorRouteKeyStruct;
/* Selector values for 'selector' bitmap */
/** Source address */
#define SSH_INTERCEPTOR_ROUTE_KEY_SRC 0x0001
/** IP protocol identifier */
#define SSH_INTERCEPTOR_ROUTE_KEY_IPPROTO 0x0002
/** Inbound interface number */
#define SSH_INTERCEPTOR_ROUTE_KEY_IN_IFNUM 0x0004
/** Outbound interface number */
#define SSH_INTERCEPTOR_ROUTE_KEY_OUT_IFNUM 0x0008
/** IPv4 type of service */
#define SSH_INTERCEPTOR_ROUTE_KEY_IP4_TOS 0x0010
/** Platform-dependent Extension selectors */
#define SSH_INTERCEPTOR_ROUTE_KEY_EXTENSION 0x1000
/* Flag values for 'selector' bitmap */
/** Packets going to this destination are transformed by the engine and the
resulting packet may be larger than the path MTU reported to the IP stack
by the engine. */
#define SSH_INTERCEPTOR_ROUTE_KEY_FLAG_TRANSFORM_APPLIED 0x2000
/** Source address belongs to one of the local interfaces. */
#define SSH_INTERCEPTOR_ROUTE_KEY_FLAG_LOCAL_SRC 0x4000
/** A callback function of this type will be called when the
interceptor is first opened, and from then on whenever there is a
change in the interface list (e.g., a new interface goes up or
down or the address of an interface changes). This function will
be given a list of the interfaces. The supplied array will only
be valid for the duration of this call; the implementation of this
function is supposed to copy the information if it is going to
need it later. Note that this function may be called
asynchronously, concurrently with any other functions. */
typedef void (*SshInterceptorInterfacesCB)(SshUInt32 num_interfaces,
SshInterceptorInterface *ifs,
void *context);
/** Callback functions of this type are called whenever a packet is
received from the network or from a protocol. This function must
eventually free the packet, either by calling
ssh_interceptor_packet_free on the packet or by passing it to the
ssh_interceptor_send function. Note that this function may be
called asynchronously, concurrently with any other functions.
When a packet is passed to this callback, the `pp->flags' field
may contain arbitrary flags in the bits reserved for the
interceptor (mask 0x00000fff). This callback is not allowed to
modify any of those bits; they must be passed intact to
ssh_interceptor_send or ssh_interceptor_packet_free. Any other
bits (mask 0xfffff000) will be zero when the packet is sent to
this callback; those bits may be used freely by this callback.
They are not used by the interceptor. */
typedef void (*SshInterceptorPacketCB)(SshInterceptorPacket pp, void *context);
/** A callback function of this type is used to notify code above the
interceptor that routing information has changed, and any cached
routing data should be thrown away and refreshed by a new route
lookup. */
typedef void (*SshInterceptorRouteChangeCB)(void *context);
/** Opens the packet interceptor. This must be called before using
any other interceptor functions. This registers the callbacks
that the interceptor will use to notify the higher levels of
received packets or changes in the interface list. The interface
callback will be called once either during this call or soon after
this has returned.
The `machine_context' argument is intended to be meaningful only
to machine-specific code. It is passed through from the
machine-specific main program. One example of its possible uses
is to identify a virtual router in systems that implement multiple
virtual routers in a single software environment. Most
implementations will ignore this argument.
The `packet_cb' callback will be called whenever a packet is
received from either a network adapter or a protocol stack. The
first calls may arrive already before this function has returned.
The `interfaces_cb' callback will be called once soon after
opening the interceptor (possibly before this call returns). From
then on, it will be called whenever there is a change in the
interface list (e.g., the IP address of an interface is changed,
or a PPP interface goes up or down).
The `route_change_cb' callback should be called whenever there is
a change in routing information. Implementing this callback is
optional but beneficial in e.g. router environments (the
information is not easily available on all systems).
The `context' argument is passed to the callbacks.
This function returns TRUE if opening the interceptor was
successful. The interceptor object is returned in the
`interceptor_return' argument. Most systems will only allow a
single interceptor to be opened; however, some systems may support
multiple interceptors identified by the `machine_context'
argument. This returns FALSE if an error occurs (e.g., no
interceptor kernel module is loaded on this system, or the
interceptor is already open).
Care must be taken regarding concurrency control in systems that have
multithreaded IP stacks. In particular:
- packet_cb and interfaces_cb may get called before this function
returns. It is, however, guaranteed that `*interceptor_return'
has been set before the first call to either of them.
- the interceptor cannot be closed while there are calls or packets
out. The ssh_interceptor_stop function must be used.
In such systems, additional concurrency may be introduced by timeouts
and actions from the policy manager connection. */
Boolean ssh_interceptor_open(void *machine_context,
SshInterceptorPacketCB packet_cb,
SshInterceptorInterfacesCB interfaces_cb,
SshInterceptorRouteChangeCB route_change_cb,
void *context,
SshInterceptor *interceptor_return);
/** Sends a packet to the network or to the protocol stacks. This
will eventually free the packet by calling
ssh_interceptor_packet_free. The `media_header_len' argument
specifies how many bytes from the start of the packet are media
(link-level) headers. It will be 0 if the interceptor operates
directly at protocol level. If the configure define
INTERCEPTOR_IP_ALIGNS_PACKETS is set, this function must ensure
that the IP header of the packet is aligned to a word boundary.
This function relies on 'pp->ifnum_out' being an 'ifnum' which has
previously been reported via a SshInterceptorInterfacesCB. It does
not have to be valid at that precise point in time. If 'pp->ifnum_out'
is an ifnum which may have been previously reported to the
SshInterceptorInterfacesCB, then ssh_interceptor_send() MUST check
that it is valid, or otherwise discard the packet. Also,
pp->protocol (and the corresponding encapsulation) may be
incorrect for the interface denoted by 'pp->ifnum_out'. The packet
should be dropped also in this case.
This function can be called concurrently from multiple threads,
but only for one packet at a time. It is ok to call this even
before ssh_interceptor_open has actually returned (from a
`packet_cb' or `interface_cb' callback). */
void ssh_interceptor_send(SshInterceptor interceptor,
SshInterceptorPacket pp,
size_t media_header_len);
/** Enables or disables packet interception. */
void ssh_interceptor_enable_interception(SshInterceptor interceptor,
Boolean enable);
/** Stops the packet interceptor. After this call has returned, no
new calls to the packet and interfaces callbacks will be made.
The interceptor keeps track of how many threads are processing
packet, interface, or have pending route callbacks, and this
function returns TRUE if there are no callbacks/pending calls to
those functions. This returns FALSE if threads are still
executing in those callbacks or routing callbacks are pending.
After calling this function, the higher-level code should wait for
packet processing to continue, free all packet structures received
from that interceptor, and then call ssh_interceptor_close. It is
not an error to call this multiple times (the latter calls are
ignored).
It is forbidden to hold ANY locks when calling
ssh_interceptor_stop(). */
Boolean ssh_interceptor_stop(SshInterceptor interceptor);
/** Closes the packet interceptor. This function can only be called when
- ssh_interceptor_stop has been called
- all packet and interface callbacks from this interceptor have
returned.
- all ssh_interceptor_route completions have been called
- all packets received from the packet callbacks from this interceptor
have been freed.
It is illegal to call any packet interceptor functions (other than
ssh_interceptor_open) after this call. This function cannot be
called from an interceptor callback.
This function can be called from one thread only for any particular
interceptor. If multiple interceptors are supported, then this may be
called for different interceptors asynchronously. */
void ssh_interceptor_close(SshInterceptor interceptor);
/** Completion function for route lookup. This function is called when the
route lookup is complete.
reachable FALSE if the destination cannot be reached, TRUE otherwise
next_hop_gw IP address of next hop gw or destination
ifnum network interface to which to send the packet
mtu path mtu, or 0 if not known (= should use link mtu)
context context argument supplied to route request.
This function may get called concurrently from multiple threads. */
typedef void (*SshInterceptorRouteCompletion)(Boolean reachable,
SshIpAddr next_hop_gw,
SshInterceptorIfnum ifnum,
size_t mtu,
void *context);
/** Looks up routing information for the routing key specified
by `key'. Calls the callback function either during this
call or some time later. The purpose of the callback function is
to allow this function to perform asynchronous operations, such as
forwarding the routing request to a user-level process. This
function will not be very efficient on some systems, and calling
this on a per-packet basis should be avoided if possible.
This function expects that 'key' is valid only for the duration
of the call, and will take a local copy of it, if necessary.
Note that if this function is implemented by forwarding the
request to a user-level process, care must be taken to never lose
replies. The completion function must *always* be called. For
example, if the policy manager interface is used to pass the
requests to the policy manager process, and the interface is
closed, the completion function must still be called for all
requests. Code may be needed to keep track of which requests are
waiting for replies from the user-level process.
This function can be called concurrently from multiple threads.
While legal, new calls to this function after calling
ssh_interceptor_stop should be avoided, because it is not possible
to call ssh_interceptor_close until all route lookup completions
have been called. */
void ssh_interceptor_route(SshInterceptor interceptor,
SshInterceptorRouteKey key,
SshInterceptorRouteCompletion completion,
void *context);
/** Allocates a packet of at least the given size. Packets can only
be allocated using this function (either internally by the
interceptor or by other code by calling this function).
Typically, this takes a packet header from a free list, stores a
pointer to a platform-specific packet object, and returns the
packet header. This should be re-entrant and support concurrent
operations if the IPSEC engine is re-entrant on the target
platform. Other functions in this interface should be re-entrant
for different packet objects, but only one operation will be in
progress at any given time for a single packet object. This
returns NULL if no more packets can be allocated. On systems that
support concurrency, this can be called from multiple threads
concurrently.
This sets initial values for the mandatory fields of the packet
that always need to be initialized. However, any of these fields
can be modified later. */
SshInterceptorPacket ssh_interceptor_packet_alloc(SshInterceptor interceptor,
SshUInt32 flags,
SshInterceptorProtocol proto,
SshInterceptorIfnum ifnum_in,
SshInterceptorIfnum ifnum_out,
size_t total_len);
/** Frees the packet.
All packets allocated by ssh_interceptor_packet_alloc must
eventually be freed using this function by either calling this
explicitly or by passing the packet to the ssh_interceptor_send
function. Typically, this calls a suitable function to
free/release the platform-specific packet object, and puts the
packet header on a free list. This function should be re-entrant,
so if a free list is used, it should be protected by a lock in
systems that implement concurrency in the IPSEC Engine. Multiple
threads may call this function concurrently for different packets,
but not for the same packet. */
void ssh_interceptor_packet_free(SshInterceptorPacket pp);
/** Returns the total length of the packet in bytes. Multiple threads may
call this function concurrently, but not for the same packet. */
size_t ssh_interceptor_packet_len(SshInterceptorPacket pp);
/** Copies data into the packet. Space for the new data must already
have been allocated. It is a fatal error to attempt to copy beyond
the allocated packet. Multiple threads may call this function
concurrently, but not for the same packet. Returns TRUE if
successfull and FALSE otherwise. If error occurs then the pp is
already freed by this function, and the caller must not refer to
it anymore.
There is a generic version of this function inside the engine, in
case interceptor does not want to implement this. If interceptor
implements this function it must define the
INTERCEPTOR_HAS_PACKET_COPYIN pre-processor symbol. */
Boolean ssh_interceptor_packet_copyin(SshInterceptorPacket pp, size_t offset,
const unsigned char *buf, size_t len);
/** Copies data out from the packet. Space for the new data must
already have been allocated. It is a fatal error to attempt to
copy beyond the allocated packet. Multiple threads may call this
function concurrently, but not for the same packet.
There is a generic version of this function inside the engine, in
case interceptor does not want to implement this. If interceptor
implements this function it must define the
INTERCEPTOR_HAS_PACKET_COPYOUT pre-processor symbol. */
void ssh_interceptor_packet_copyout(SshInterceptorPacket pp, size_t offset,
unsigned char *buf, size_t len);
/** These two routines provide way to export and import
interceptor-specific internal packet data as an opaque binary data
block.
If the export routine returns FALSE, the packet `pp' is
invalidated. If it returnes TRUE, but *data_ret is NULL, then no
internal data was exported. If *data_ret is non-NULL, then
*len_return contains the length of *data_ret in bytes. The caller
must free the *data_ret value using ssh_free.
The import routine returns TRUE if the data was imported
successfully, otherwise it returns FALSE and the packet `pp' is
invalidated. It is a fatal error to call import routine on the
same packet more than once.
Notice: If the interceptor does not define these routines, then
the engine provides dummy versions.
Notice: This routine overlaps a bit with
ssh_interceptor_packet_alloc_and_copy_ext_data, as it could be
implemented as:
new_pp = ssh_interceptor_packet_alloc(...);
ssh_interceptor_packet_copy(pp, 0, ..., new_pp, 0);
ssh_interceptor_packet_export_internal_data(pp, &data, &len);
ssh_interceptor_packet_import_internal_data(new_pp, data, len);
ssh_free(data);
The main purpose of these routines is to allow some per-packet
interceptor-specific data to be transported to the usermode
engine. Under the kernel IPSec Engine, these routines are not
actually used at all. */
Boolean ssh_interceptor_packet_export_internal_data(SshInterceptorPacket pp,
unsigned char **data_ret,
size_t *len_return);
Boolean ssh_interceptor_packet_import_internal_data(SshInterceptorPacket pp,
const unsigned char *data,
size_t len);
void ssh_interceptor_packet_discard_internal_data(unsigned char *data,
size_t data_len);
/** Copy data from one packet to another. Start from the
`source_offset' and copy `bytes_to_copy' bytes to
`destination_offset' in the destination packet. If the destination
packet cannot be written then return FALSE, and the destination
packet has been freed by this function. The source packet is not
freed even in case of error. If data copying was successfull then
return TRUE.
This function can also be implemented so that it will simply
increment the reference counts in the source packet and share the
actual data without copying it at all. There is a generic version
of this function inside the engine, in case interceptor does not
want to implement this. If interceptor implements this function it
must define INTERCEPTOR_HAS_PACKET_COPY pre-processor symbol. */
Boolean ssh_interceptor_packet_copy(SshInterceptorPacket source_pp,
size_t source_offset,
size_t bytes_to_copy,
SshInterceptorPacket destination_pp,
size_t destination_offset);
#ifdef DEBUG_LIGHT
#define KERNEL_INTERCEPTOR_USE_FUNCTIONS
#endif /* DEBUG_LIGHT */
#ifdef INTERCEPTOR_HAS_PLATFORM_INCLUDE
#include "platform_interceptor.h"
#endif /* INTERCEPTOR_HAS_PLATFORM_INCLUDE */
#endif /* INTERCEPTOR_H */
|