aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/interceptor/sshinet.h
blob: ac18c53f30dfe341f8f44d4d6caface88b64ce06 (plain)
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
/* 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.
 */

/*
 * sshinet.h
 *
 * Inet API.
 *
 */

#ifndef SSHINET_H
#define SSHINET_H

#include "sshgetput.h"

/*************************** Ethernet definitions ***************************/

/* Etherenet header things we need */
#define SSH_ETHERH_HDRLEN       14
#define SSH_ETHERH_OFS_DST      0
#define SSH_ETHERH_OFS_SRC      6
#define SSH_ETHERH_OFS_TYPE     12
#define SSH_ETHERH_ADDRLEN      6

/* Known values for the ethernet type field.  The same values are used for
   both ethernet (rfc894) and IEEE 802 encapsulation (the type will just
   be in a different position in the header). */
#define SSH_ETHERTYPE_IP        0x0800 /* IPv4, as per rfc894 */
#define SSH_ETHERTYPE_ARP       0x0806 /* ARP, as per rfc826 */
#define SSH_ETHERTYPE_IPv6      0x86dd /* IPv6, as per rfc1972 */


/***************************** SshIpAddr stuff ******************************/

typedef enum {
    SSH_IP_TYPE_NONE = 0,
    SSH_IP_TYPE_IPV4 = 1,
    SSH_IP_TYPE_IPV6 = 2
} SshIpAddrType;

#if defined(WITH_IPV6)
/* An IPv6 link-local address scope ID. */
struct SshScopeIdRec
{
  union
  {
    SshUInt32 ui32;
  } scope_id_union;
};

typedef struct SshScopeIdRec SshScopeIdStruct;
typedef struct SshScopeIdRec *SshScopeId;

#endif /* WITH_IPV6 */

#if !defined(WITH_IPV6)
#define SSH_IP_ADDR_SIZE 4
#define SSH_IP_ADDR_STRING_SIZE 32
#else /* WITH_IPV6 */
#define SSH_IP_ADDR_SIZE 16
#define SSH_IP_ADDR_STRING_SIZE 64
#endif /* !WITH_IPV6 */

typedef struct SshIpAddrRec
{
  /* Note: All fields of this data structure are private, and should
     not be accessed except using the macros and functions defined in
     this header.  They should never be accessed directly; the
     internal definition of this structure is subject to change
     without notice. */
  SshUInt8 type; /* KEEP type first if changing rest of the contents */
  SshUInt8 mask_len;

  /* There is a hole of 16 bits here */

  /* For optimised mask comparison routine _addr_data has to be 32-bit
     aligned so it can be read as words on machines requiring
     alignment */
  union {
    unsigned char _addr_data[SSH_IP_ADDR_SIZE];
    SshUInt32 _addr_align;
  } addr_union;

#define addr_data addr_union._addr_data

#if defined(WITH_IPV6)
  SshScopeIdStruct scope_id;
#endif /* WITH_IPV6 */

} *SshIpAddr, SshIpAddrStruct;

#define SSH_IP_DEFINED(ip_addr) ((ip_addr)->type != SSH_IP_TYPE_NONE)
#define SSH_IP_IS4(ip_addr)     ((ip_addr)->type == SSH_IP_TYPE_IPV4)
#define SSH_IP_IS6(ip_addr)     ((ip_addr)->type == SSH_IP_TYPE_IPV6)

#define SSH_IP_ADDR_LEN(ip_addr)        \
  (SSH_PREDICT_TRUE(SSH_IP_IS4(ip_addr))\
   ? (4)                                \
   : (SSH_IP_IS6(ip_addr)               \
      ? (16)                            \
      : 0))

/* Make given IP address undefined. */
#define SSH_IP_UNDEFINE(IPADDR)         \
do {                                    \
  (IPADDR)->type = SSH_IP_TYPE_NONE;    \
} while (0)


#if defined(WITH_IPV6)
/* Decode, that is fill given 'ipaddr', with given 'type', 'bytes' and
   'masklen' information. */
#define __SSH_IP_MASK_DECODE(IPADDR,TYPE,BYTES,BYTELEN,MASKLEN) \
  do {                                                          \
    (IPADDR)->type = (TYPE);                                    \
    memmove((IPADDR)->addr_data, (BYTES), (BYTELEN));           \
    memset(&(IPADDR)->scope_id, 0, sizeof((IPADDR)->scope_id)); \
    (IPADDR)->mask_len = (MASKLEN);                             \
  } while (0)
#else /* WITH_IPV6 */
#define __SSH_IP_MASK_DECODE(IPADDR,TYPE,BYTES,BYTELEN,MASKLEN) \
  do {                                                          \
    (IPADDR)->type = (TYPE);                                    \
    memmove((IPADDR)->addr_data, (BYTES), (BYTELEN));           \
    (IPADDR)->mask_len = (MASKLEN);                             \
  } while (0)
#endif /* WITH_IPV6 */

/* Encode, that is copy from 'ipaddr' into 'bytes' and 'maskptr'.  The
   input 'ipaddr' needs to be of given 'type'. It is an fatal error
   to call this for invalid address type. */
#define __SSH_IP_MASK_ENCODE(IPADDR,TYPE,BYTES,BYTELEN,MASKPTR) \
  do {                                                          \
    SSH_VERIFY((IPADDR)->type == (TYPE));                       \
    memmove((BYTES), (IPADDR)->addr_data, (BYTELEN));           \
    if (SSH_PREDICT_FALSE(MASKPTR))                             \
      *((SshUInt32 *) (MASKPTR)) = (IPADDR)->mask_len;          \
  } while (0)

/* IPv4 Address manipulation */
#define SSH_IP4_ENCODE(ip_addr,bytes) \
  __SSH_IP_MASK_ENCODE(ip_addr,SSH_IP_TYPE_IPV4,bytes,4,NULL)
#define SSH_IP4_DECODE(ip_addr,bytes) \
  __SSH_IP_MASK_DECODE(ip_addr,SSH_IP_TYPE_IPV4,bytes,4,32)

/* IPv6 address manipulation */
#define SSH_IP6_ENCODE(ip_addr,bytes) \
  __SSH_IP_MASK_ENCODE(ip_addr,SSH_IP_TYPE_IPV6,bytes,16,NULL)

#if !defined(WITH_IPV6)
#define SSH_IP6_DECODE(ip_addr,bytes) SSH_IP_UNDEFINE(ip_addr)
#else /* WITH_IPV6 */
#define SSH_IP6_DECODE(ip_addr,bytes) \
  __SSH_IP_MASK_DECODE(ip_addr,SSH_IP_TYPE_IPV6,bytes,16,128)
#endif /* !WITH_IPV6 */

#define SSH_IP_MASK_LEN(ip_addr) ((ip_addr)->mask_len)

#if defined(WITH_IPV6)
#define SSH_IP6_SCOPE_ID(ip_addr) ((ip_addr)->scope_id.scope_id_union.ui32)
#endif /* WITH_IPV6 */

/*********************** Definitions for IPv4 packets ***********************/


/* IPv4 header lengths. */
#define SSH_IPH4_HDRLEN 20
#define SSH_IPH4_HLEN(ucp) SSH_GET_4BIT_LOW(ucp)
#define SSH_IPH4_LEN(ucp) SSH_GET_16BIT((ucp) + 2)
#define SSH_IPH4_SRC(ipaddr, ucp) SSH_IP4_DECODE((ipaddr), (ucp) + 12)

/*********************** Definitions for IPv6 packets ***********************/

/* IPv6 header length. Extension headers are not counted in IPv6
   header */
#define SSH_IPH6_HDRLEN 40

#define SSH_IPH6_OFS_LEN                4
#define SSH_IPH6_OFS_NH                 6

#define SSH_IPH6_ADDRLEN               16
#define SSH_IPH6_OFS_SRC               8

#define SSH_IP6_WORD0_TO_INT(ip_addr) SSH_GET_32BIT((ip_addr)->addr_data)
#define SSH_IP6_WORD1_TO_INT(ip_addr) SSH_GET_32BIT((ip_addr)->addr_data + 4)
#define SSH_IP6_WORD2_TO_INT(ip_addr) SSH_GET_32BIT((ip_addr)->addr_data + 8)
#define SSH_IP6_WORD3_TO_INT(ip_addr) SSH_GET_32BIT((ip_addr)->addr_data + 12)

#define SSH_IPH6_LEN(ucp) SSH_GET_16BIT((ucp) + SSH_IPH6_OFS_LEN)
#define SSH_IPH6_NH(ucp) SSH_GET_8BIT((ucp) + SSH_IPH6_OFS_NH)
#define SSH_IPH6_SRC(ipaddr, ucp) SSH_IP6_DECODE((ipaddr), \
                                                 (ucp) + SSH_IPH6_OFS_SRC)

/****************** Definitions for IPv6 extension headers ******************/

#define SSH_IP6_EXT_COMMON_NH(ucp)      SSH_GET_8BIT((ucp))
#define SSH_IP6_EXT_COMMON_LEN(ucp)     SSH_GET_8BIT((ucp) + 1)
#define SSH_IP6_EXT_COMMON_LENB(ucp)		\
  ((SSH_IP6_EXT_COMMON_LEN((ucp)) + 1) << 3)

/*************************** Link definitions *******************************/

/* Reserved value for invalid interface index. */
#define SSH_INVALID_IFNUM       0xffffffff

/***************************** Helper functions *****************************/

/* Sets all rightmost bits after keeping `keep_bits' bits on the left
   to the value specified by `value'. */
void ssh_ipaddr_set_bits(SshIpAddr result, SshIpAddr ip,
                         unsigned int keep_bits, unsigned int value);

/* Prints the IP address into the buffer in string format.  If the buffer
   is too short, the address is truncated.  This returns `buf'. */
unsigned char *ssh_ipaddr_print(const SshIpAddr ip, unsigned char *buf,
                                size_t buflen);

/* Prints the IP address into the buffer in string format.  If the buffer
   is too short, the address is truncated.  This returns `buf'. */
void ssh_ipaddr_ipv4_print(const unsigned char *data,
			   unsigned char *buf, size_t buflen);
void ssh_ipaddr_ipv6_print(const unsigned char *data,
			   unsigned char *buf, size_t buflen,
			   SshUInt32 scope);

#endif /* SSHINET_H */