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
|
/* $FreeBSD$ */
/*
* Copyright (C) 1995-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_nat.h 1.5 2/4/96
* $FreeBSD$
* Id: ip_nat.h,v 2.90.2.9 2005/03/28 11:09:55 darrenr Exp
*/
#ifndef __IP_NAT_H__
#define __IP_NAT_H__
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51)
#define SIOCADNAT _IOW('r', 60, struct ipfobj)
#define SIOCRMNAT _IOW('r', 61, struct ipfobj)
#define SIOCGNATS _IOWR('r', 62, struct ipfobj)
#define SIOCGNATL _IOWR('r', 63, struct ipfobj)
#else
#define SIOCADNAT _IOW(r, 60, struct ipfobj)
#define SIOCRMNAT _IOW(r, 61, struct ipfobj)
#define SIOCGNATS _IOWR(r, 62, struct ipfobj)
#define SIOCGNATL _IOWR(r, 63, struct ipfobj)
#endif
#undef LARGE_NAT /* define this if you're setting up a system to NAT
* LARGE numbers of networks/hosts - i.e. in the
* hundreds or thousands. In such a case, you should
* also change the RDR_SIZE and NAT_SIZE below to more
* appropriate sizes. The figures below were used for
* a setup with 1000-2000 networks to NAT.
*/
#ifndef NAT_SIZE
# ifdef LARGE_NAT
# define NAT_SIZE 2047
# else
# define NAT_SIZE 127
# endif
#endif
#ifndef RDR_SIZE
# ifdef LARGE_NAT
# define RDR_SIZE 2047
# else
# define RDR_SIZE 127
# endif
#endif
#ifndef HOSTMAP_SIZE
# ifdef LARGE_NAT
# define HOSTMAP_SIZE 8191
# else
# define HOSTMAP_SIZE 2047
# endif
#endif
#ifndef NAT_TABLE_MAX
/*
* This is newly introduced and for the sake of "least surprise", the numbers
* present aren't what we'd normally use for creating a proper hash table.
*/
# ifdef LARGE_NAT
# define NAT_TABLE_MAX 180000
# else
# define NAT_TABLE_MAX 30000
# endif
#endif
#ifndef NAT_TABLE_SZ
# ifdef LARGE_NAT
# define NAT_TABLE_SZ 16383
# else
# define NAT_TABLE_SZ 2047
# endif
#endif
#ifndef APR_LABELLEN
#define APR_LABELLEN 16
#endif
#define NAT_HW_CKSUM 0x80000000
#define DEF_NAT_AGE 1200 /* 10 minutes (600 seconds) */
struct ipstate;
struct ap_session;
typedef struct nat {
ipfmutex_t nat_lock;
struct nat *nat_next;
struct nat **nat_pnext;
struct nat *nat_hnext[2];
struct nat **nat_phnext[2];
struct hostmap *nat_hm;
void *nat_data;
struct nat **nat_me;
struct ipstate *nat_state;
struct ap_session *nat_aps; /* proxy session */
frentry_t *nat_fr; /* filter rule ptr if appropriate */
struct ipnat *nat_ptr; /* pointer back to the rule */
void *nat_ifps[2];
void *nat_sync;
ipftqent_t nat_tqe;
u_32_t nat_flags;
u_32_t nat_sumd[2]; /* ip checksum delta for data segment*/
u_32_t nat_ipsumd; /* ip checksum delta for ip header */
u_32_t nat_mssclamp; /* if != zero clamp MSS to this */
i6addr_t nat_inip6;
i6addr_t nat_outip6;
i6addr_t nat_oip6; /* other ip */
U_QUAD_T nat_pkts[2];
U_QUAD_T nat_bytes[2];
union {
udpinfo_t nat_unu;
tcpinfo_t nat_unt;
icmpinfo_t nat_uni;
greinfo_t nat_ugre;
} nat_un;
u_short nat_oport; /* other port */
u_short nat_use;
u_char nat_p; /* protocol for NAT */
int nat_dir;
int nat_ref; /* reference count */
int nat_hv[2];
char nat_ifnames[2][LIFNAMSIZ];
int nat_rev; /* 0 = forward, 1 = reverse */
} nat_t;
#define nat_inip nat_inip6.in4
#define nat_outip nat_outip6.in4
#define nat_oip nat_oip6.in4
#define nat_age nat_tqe.tqe_die
#define nat_inport nat_un.nat_unt.ts_sport
#define nat_outport nat_un.nat_unt.ts_dport
#define nat_type nat_un.nat_uni.ici_type
#define nat_seq nat_un.nat_uni.ici_seq
#define nat_id nat_un.nat_uni.ici_id
#define nat_tcpstate nat_tqe.tqe_state
/*
* Values for nat_dir
*/
#define NAT_INBOUND 0
#define NAT_OUTBOUND 1
/*
* Definitions for nat_flags
*/
#define NAT_TCP 0x0001 /* IPN_TCP */
#define NAT_UDP 0x0002 /* IPN_UDP */
#define NAT_ICMPERR 0x0004 /* IPN_ICMPERR */
#define NAT_ICMPQUERY 0x0008 /* IPN_ICMPQUERY */
#define NAT_SEARCH 0x0010
#define NAT_SLAVE 0x0020 /* Slave connection for a proxy */
#define NAT_NOTRULEPORT 0x0040
#define NAT_TCPUDP (NAT_TCP|NAT_UDP)
#define NAT_TCPUDPICMP (NAT_TCP|NAT_UDP|NAT_ICMPERR)
#define NAT_TCPUDPICMPQ (NAT_TCP|NAT_UDP|NAT_ICMPQUERY)
#define NAT_FROMRULE (NAT_TCP|NAT_UDP)
/* 0x0100 reserved for FI_W_SPORT */
/* 0x0200 reserved for FI_W_DPORT */
/* 0x0400 reserved for FI_W_SADDR */
/* 0x0800 reserved for FI_W_DADDR */
/* 0x1000 reserved for FI_W_NEWFR */
/* 0x2000 reserved for SI_CLONE */
/* 0x4000 reserved for SI_CLONED */
/* 0x8000 reserved for SI_IGNOREPKT */
#define NAT_DEBUG 0x800000
typedef struct ipnat {
struct ipnat *in_next; /* NAT rule list next */
struct ipnat *in_rnext; /* rdr rule hash next */
struct ipnat **in_prnext; /* prior rdr next ptr */
struct ipnat *in_mnext; /* map rule hash next */
struct ipnat **in_pmnext; /* prior map next ptr */
struct ipftq *in_tqehead[2];
void *in_ifps[2];
void *in_apr;
char *in_comment;
i6addr_t in_next6;
u_long in_space;
u_long in_hits;
u_int in_use;
u_int in_hv;
int in_flineno; /* conf. file line number */
u_short in_pnext;
u_char in_v;
u_char in_xxx;
/* From here to the end is covered by IPN_CMPSIZ */
u_32_t in_flags;
u_32_t in_mssclamp; /* if != 0 clamp MSS to this */
u_int in_age[2];
int in_redir; /* see below for values */
int in_p; /* protocol. */
i6addr_t in_in[2];
i6addr_t in_out[2];
i6addr_t in_src[2];
frtuc_t in_tuc;
u_short in_port[2];
u_short in_ppip; /* ports per IP. */
u_short in_ippip; /* IP #'s per IP# */
char in_ifnames[2][LIFNAMSIZ];
char in_plabel[APR_LABELLEN]; /* proxy label. */
ipftag_t in_tag;
} ipnat_t;
#define in_pmin in_port[0] /* Also holds static redir port */
#define in_pmax in_port[1]
#define in_nextip in_next6.in4
#define in_nip in_next6.in4.s_addr
#define in_inip in_in[0].in4.s_addr
#define in_inmsk in_in[1].in4.s_addr
#define in_outip in_out[0].in4.s_addr
#define in_outmsk in_out[1].in4.s_addr
#define in_srcip in_src[0].in4.s_addr
#define in_srcmsk in_src[1].in4.s_addr
#define in_scmp in_tuc.ftu_scmp
#define in_dcmp in_tuc.ftu_dcmp
#define in_stop in_tuc.ftu_stop
#define in_dtop in_tuc.ftu_dtop
#define in_sport in_tuc.ftu_sport
#define in_dport in_tuc.ftu_dport
/*
* Bit definitions for in_flags
*/
#define IPN_ANY 0x00000
#define IPN_TCP 0x00001
#define IPN_UDP 0x00002
#define IPN_TCPUDP (IPN_TCP|IPN_UDP)
#define IPN_ICMPERR 0x00004
#define IPN_TCPUDPICMP (IPN_TCP|IPN_UDP|IPN_ICMPERR)
#define IPN_ICMPQUERY 0x00008
#define IPN_TCPUDPICMPQ (IPN_TCP|IPN_UDP|IPN_ICMPQUERY)
#define IPN_RF (IPN_TCPUDP|IPN_DELETE|IPN_ICMPERR)
#define IPN_AUTOPORTMAP 0x00010
#define IPN_IPRANGE 0x00020
#define IPN_FILTER 0x00040
#define IPN_SPLIT 0x00080
#define IPN_ROUNDR 0x00100
#define IPN_NOTSRC 0x04000
#define IPN_NOTDST 0x08000
#define IPN_DYNSRCIP 0x10000 /* dynamic src IP# */
#define IPN_DYNDSTIP 0x20000 /* dynamic dst IP# */
#define IPN_DELETE 0x40000
#define IPN_STICKY 0x80000
#define IPN_FRAG 0x100000
#define IPN_FIXEDDPORT 0x200000
#define IPN_FINDFORWARD 0x400000
#define IPN_IN 0x800000
#define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_IPRANGE|IPN_SPLIT|\
IPN_ROUNDR|IPN_FILTER|IPN_NOTSRC|IPN_NOTDST|\
IPN_FRAG|IPN_STICKY|IPN_FIXEDDPORT|IPN_ICMPQUERY)
/*
* Values for in_redir
*/
#define NAT_MAP 0x01
#define NAT_REDIRECT 0x02
#define NAT_BIMAP (NAT_MAP|NAT_REDIRECT)
#define NAT_MAPBLK 0x04
#define MAPBLK_MINPORT 1024 /* don't use reserved ports for src port */
#define USABLE_PORTS (65536 - MAPBLK_MINPORT)
#define IPN_CMPSIZ (sizeof(ipnat_t) - offsetof(ipnat_t, in_flags))
typedef struct natlookup {
struct in_addr nl_inip;
struct in_addr nl_outip;
struct in_addr nl_realip;
int nl_flags;
u_short nl_inport;
u_short nl_outport;
u_short nl_realport;
} natlookup_t;
typedef struct nat_save {
void *ipn_next;
struct nat ipn_nat;
struct ipnat ipn_ipnat;
struct frentry ipn_fr;
int ipn_dsize;
char ipn_data[4];
} nat_save_t;
#define ipn_rule ipn_nat.nat_fr
typedef struct natget {
void *ng_ptr;
int ng_sz;
} natget_t;
#undef tr_flags
typedef struct nattrpnt {
struct in_addr tr_dstip; /* real destination IP# */
struct in_addr tr_srcip; /* real source IP# */
struct in_addr tr_locip; /* local source IP# */
u_int tr_flags;
int tr_expire;
u_short tr_dstport; /* real destination port# */
u_short tr_srcport; /* real source port# */
u_short tr_locport; /* local source port# */
struct nattrpnt *tr_hnext;
struct nattrpnt **tr_phnext;
struct nattrpnt *tr_next;
struct nattrpnt **tr_pnext; /* previous next */
} nattrpnt_t;
#define TN_CMPSIZ offsetof(nattrpnt_t, tr_hnext)
/*
* This structure gets used to help NAT sessions keep the same NAT rule (and
* thus translation for IP address) when:
* (a) round-robin redirects are in use
* (b) different IP add
*/
typedef struct hostmap {
struct hostmap *hm_next;
struct hostmap **hm_pnext;
struct ipnat *hm_ipnat;
struct in_addr hm_srcip;
struct in_addr hm_dstip;
struct in_addr hm_mapip;
u_32_t hm_port;
int hm_ref;
} hostmap_t;
/*
* Structure used to pass information in to nat_newmap and nat_newrdr.
*/
typedef struct natinfo {
ipnat_t *nai_np;
u_32_t nai_sum1;
u_32_t nai_sum2;
u_32_t nai_nflags;
u_32_t nai_flags;
struct in_addr nai_ip;
u_short nai_port;
u_short nai_nport;
u_short nai_sport;
u_short nai_dport;
} natinfo_t;
typedef struct natstat {
u_long ns_mapped[2];
u_long ns_rules;
u_long ns_added;
u_long ns_expire;
u_long ns_inuse;
u_long ns_logged;
u_long ns_logfail;
u_long ns_memfail;
u_long ns_badnat;
u_long ns_addtrpnt;
nat_t **ns_table[2];
hostmap_t **ns_maptable;
ipnat_t *ns_list;
void *ns_apslist;
u_int ns_wilds;
u_int ns_nattab_sz;
u_int ns_nattab_max;
u_int ns_rultab_sz;
u_int ns_rdrtab_sz;
u_int ns_trpntab_sz;
u_int ns_hostmap_sz;
nat_t *ns_instances;
nattrpnt_t *ns_trpntlist;
u_long *ns_bucketlen[2];
} natstat_t;
typedef struct natlog {
struct in_addr nl_origip;
struct in_addr nl_outip;
struct in_addr nl_inip;
u_short nl_origport;
u_short nl_outport;
u_short nl_inport;
u_short nl_type;
int nl_rule;
U_QUAD_T nl_pkts[2];
U_QUAD_T nl_bytes[2];
u_char nl_p;
} natlog_t;
#define NL_NEWMAP NAT_MAP
#define NL_NEWRDR NAT_REDIRECT
#define NL_NEWBIMAP NAT_BIMAP
#define NL_NEWBLOCK NAT_MAPBLK
#define NL_CLONE 0xfffd
#define NL_FLUSH 0xfffe
#define NL_EXPIRE 0xffff
#define NAT_HASH_FN(k,l,m) (((k) + ((k) >> 12) + l) % (m))
#define LONG_SUM(in) (((in) & 0xffff) + ((in) >> 16))
#define CALC_SUMD(s1, s2, sd) { \
(s1) = ((s1) & 0xffff) + ((s1) >> 16); \
(s2) = ((s2) & 0xffff) + ((s2) >> 16); \
/* Do it twice */ \
(s1) = ((s1) & 0xffff) + ((s1) >> 16); \
(s2) = ((s2) & 0xffff) + ((s2) >> 16); \
/* Because ~1 == -2, We really need ~1 == -1 */ \
if ((s1) > (s2)) (s2)--; \
(sd) = (s2) - (s1); \
(sd) = ((sd) & 0xffff) + ((sd) >> 16); }
#define NAT_SYSSPACE 0x80000000
#define NAT_LOCKHELD 0x40000000
extern u_int ipf_nattable_sz;
extern u_int ipf_nattable_max;
extern u_int ipf_natrules_sz;
extern u_int ipf_rdrrules_sz;
extern u_int ipf_hostmap_sz;
extern u_int fr_nat_maxbucket;
extern u_int fr_nat_maxbucket_reset;
extern int fr_nat_lock;
extern void fr_natsync __P((void *));
extern u_long fr_defnatage;
extern u_long fr_defnaticmpage;
extern u_long fr_defnatipage;
/* nat_table[0] -> hashed list sorted by inside (ip, port) */
/* nat_table[1] -> hashed list sorted by outside (ip, port) */
extern nat_t **nat_table[2];
extern nat_t *nat_instances;
extern ipnat_t *nat_list;
extern ipnat_t **nat_rules;
extern ipnat_t **rdr_rules;
extern ipftq_t *nat_utqe;
extern natstat_t nat_stats;
#if defined(__OpenBSD__)
extern void nat_ifdetach __P((void *));
#endif
extern int fr_nat_ioctl __P((caddr_t, ioctlcmd_t, int));
extern int fr_natinit __P((void));
extern nat_t *nat_new __P((fr_info_t *, ipnat_t *, nat_t **, u_int, int));
extern nat_t *nat_outlookup __P((fr_info_t *, u_int, u_int, struct in_addr,
struct in_addr));
extern void fix_datacksum __P((u_short *, u_32_t));
extern nat_t *nat_inlookup __P((fr_info_t *, u_int, u_int, struct in_addr,
struct in_addr));
extern nat_t *nat_tnlookup __P((fr_info_t *, int));
extern nat_t *nat_maplookup __P((void *, u_int, struct in_addr,
struct in_addr));
extern nat_t *nat_lookupredir __P((natlookup_t *));
extern nat_t *nat_icmperrorlookup __P((fr_info_t *, int));
extern nat_t *nat_icmperror __P((fr_info_t *, u_int *, int));
extern int nat_insert __P((nat_t *, int));
extern int fr_checknatout __P((fr_info_t *, u_32_t *));
extern int fr_natout __P((fr_info_t *, nat_t *, int, u_32_t));
extern int fr_checknatin __P((fr_info_t *, u_32_t *));
extern int fr_natin __P((fr_info_t *, nat_t *, int, u_32_t));
extern void fr_natunload __P((void));
extern void fr_natexpire __P((void));
extern void nat_log __P((struct nat *, u_int));
extern void fix_incksum __P((fr_info_t *, u_short *, u_32_t));
extern void fix_outcksum __P((fr_info_t *, u_short *, u_32_t));
extern void fr_natderef __P((nat_t **));
extern u_short *nat_proto __P((fr_info_t *, nat_t *, u_int));
extern void nat_update __P((fr_info_t *, nat_t *, ipnat_t *));
extern void fr_setnatqueue __P((nat_t *, int));
#endif /* __IP_NAT_H__ */
|