1ipnat(7I) Ioctl Requests ipnat(7I)
2
3
4
6 ipnat - IP Filter/NAT module interface
7
9 The ipnat device provides interfaction with the NAT features of the
10 Solaris IPFilter.
11
13 The NAT features programming model is a component of the Solaris IP
14 Filter and is accessed via the NAT device file /dev/ipnat. Opening the
15 device for reading or writing determines which ioctl calls can be suc‐
16 cessfully made.
17
19 The caller must construct a ipfobj structure when issuing a SIOCGNATL
20 or SIOCSTPUT. The ipfobj structure is then passed to the ioctl call and
21 is filled out with ipfo_type set to IPFOBJ_value. IPFOBJ_ value pro‐
22 vides a matching name for the structure, while ipfo_size is set to the
23 total size of the structure being passed and ipfo_ptr is set to the
24 structure address. The ipfo_rev structure should be set to the current
25 value of IPFILTER_VERSION, while ipfo_offset and ipfo_xxxpad should be
26 set to 0.
27
28 /*
29 * Structure used with SIOCGNATL/SIOCSTPUT.
30 */
31 /*
32 * Object structure description. For passing through in ioctls.
33 */
34 typedef struct ipfobj {
35 u_32_t ipfo_rev; /* IPFilter version (IPFILTER_VERSION) */
36 u_32_t ipfo_size; /* size of object at ipfo_ptr */
37 void *ipfo_ptr; /* pointer to object */
38 int ipfo_type; /* type of object being pointed to */
39 int ipfo_offset; /* bytes from ipfo_ptr where to start */
40 u_char ipfo_xxxpad[32]; /* reserved for future use */
41 } ipfobj_t;
42
43 #define IPFILTER_VERSION 4010901 /* IPFilter version */
44 #define IPFOBJ_NATSAVE 8 /* struct nat_save */
45 #define IPFOBJ_NATLOOKUP 9 /* struct natlookup */
46
47
48
49 The following ioctl() calls may be used to manipulate the ipnat sub-
50 system inside of ipf. Note that the ipnat driver only accept calls from
51 applications using the same data model as the kernel. In other words,
52 64-bit kernels can only accept calls from 64-bit applications. Calls
53 from 32-bit applications fail with EINVAL.
54
55 SIOCSTLCK Set or clear the NAT lock to prevent table updates attrib‐
56 utable to packet flow-through.
57
58
59 SIOCGNATL Search the NAT table for the rdr entry that matches the
60 fields in the natlookup structure. The caller must popu‐
61 late the structure with the address/port information of
62 the accepted TCP connection (nl_inip, nl_inport) and the
63 address/port information of the peer (nl_outip, nl_out‐
64 port). The nl_flags field must have the IPN_TCP option
65 set. All other fields must be set to 0. If the call
66 succeeds, nl_realip and nl_realport are set to the real
67 destination address and port, respectively. The nl_inport
68 and nl_outport fields must be in host byte order.
69
70 If IPN_FINDFORWARD is set in nl_flags, a check is made to
71 see if it is possible to create an outgoing NAT session by
72 checking if a packet coming from (nl_realip,nl_realport)
73 and destined for (nl_outip,nl_outport) can be translated.
74 If translation is possible, the flag remains set, other‐
75 wise it is cleared in the structure returned to the call‐
76 er.
77
78 /*
79 * Structure used with SIOCGNATL.
80 */
81 typedef struct natlookup {
82 i6addr_t nl_inipaddr;
83 i6addr_t nl_outipaddr;
84 i6addr_t nl_realipaddr;
85 int nl_v;
86 int nl_flags;
87 u_short nl_inport;
88 u_short nl_outport;
89 u_short nl_realport;
90 } natlookup_t
91
92 #define nl_inip nl_inipaddr.in4
93 #define nl_outip nl_outipaddr.in4
94 #define nl_realip nl_realipaddr.in4
95 #define nl_inip6 nl_inipaddr.in6
96 #define nl_outip6 nl_outipaddr.in6
97 #define nl_realip6 nl_realipaddr.in6
98
99 /*
100 * Accepted values for nl_flags
101 */
102 #define IPN_TCP 0x00001
103 #define IPN_FINDFORWARD 0x400000
104
105
106
107 SIOCSTPUT Move a NAT mapping structure from user space into the
108 kernel. This ioctl is used by ipfs(1M) to restore NAT ses‐
109 sions saved in /var/db/ipf/ipnat.ipf. The nat_save struc‐
110 ture must have its ipn_nat and ipn_ipnat structures filled
111 out correctly. Fields not assigned a value must be ini‐
112 tialised to 0. All pointer fields are adjusted, as appro‐
113 priate, once the structure is passed into the kernel and
114 none are preserved.
115
116 To create a translation, the following fields must be set:
117 Interface name - The interface name on which the host is
118 to be exited must be set in nat_ifnames[0].
119 Local IP address and port number - The connection's
120 local IP address and port number are stored in network
121 byte order using nat_inip/nat_inport.
122 Destination address/port - The destination address/port
123 are stored in nat_oip/nat_oport.
124 Target address/port - The translation's target
125 address/port is stored in nat_outip/nat_outport.
126 The caller must also precalculate the checksum adjustments
127 necessary to complete the translation and store those val‐
128 ues in nat_sumd (delta required for TCP header) and
129 nat_ipsumd (delta required for IP header).
130
131 /*
132 * Structures used with SIOCSTPUT.
133 */
134 typedef struct nat_save {
135 void *ipn_next;
136 struct nat ipn_nat;
137 struct ipnat ipn_ipnat;
138 struct frentry ipn_fr;
139 int ipn_dsize;
140 char ipn_data[4];
141 } nat_save_t;
142
143 typedef struct nat {
144 ipfmutex_t nat_lock;
145 struct nat *nat_next;
146 struct nat **nat_pnext;
147 struct nat *nat_hnext[2];
148 struct nat **nat_phnext[2];
149 struct hostmap *nat_hm;
150 void *nat_data;
151 struct nat **nat_me;
152 struct ipstate *nat_state;
153 struct ap_session *nat_aps;
154 frentry_t *nat_fr;
155 struct ipnat *nat_ptr;
156 void *nat_ifps[2];
157 void *nat_sync;
158 ipftqent_t nat_tqe;
159 u_32_t nat_flags;
160 u_32_t nat_sumd[2];
161 u_32_t nat_ipsumd;
162 u_32_t nat_mssclamp;
163 i6addr_t nat_inip6;
164 i6addr_t nat_outip6;
165 i6addr_t nat_oip6;
166 U_QUAD_T nat_pkts[2];
167 U_QUAD_T nat_bytes[2];
168 union {
169 udpinfo_t nat_unu;
170 tcpinfo_t nat_unt;
171 icmpinfo_t nat_uni;
172 greinfo_t nat_ugre;
173 } nat_un;
174 u_short nat_oport;
175 u_short nat_use;
176 u_char nat_p;
177 int nat_dir;
178 int nat_ref;
179 int nat_hv[2];
180 char nat_ifnames[2][LIFNAMSIZ];
181 int nat_rev;
182 int nat_v;
183 } nat_t;
184
185 #define nat_inip nat_inip6.in4
186 #define nat_outip nat_outip6.in4
187 #define nat_oip nat_oip6.in4
188 #define nat_inport nat_un.nat_unt.ts_sport
189 #define nat_outport nat_un.nat_unt.ts_dport
190 /*
191 * Values for nat_dir
192 */
193 #define NAT_INBOUND 0
194 #define NAT_OUTBOUND 1
195 /*
196 * Definitions for nat_flags
197 */
198 #define NAT_TCP 0x0001 /* IPN_TCP */
199
200
201
203 The following example shows how to prepare and use SIOCSTPUT to insert
204 a NAT session directly into the table. Note that the usual TCP/IP code
205 is omitted is this example.
206
207
208 In the code segment below, incoming_fd is the TCP connection file
209 descriptor that is accepted as part of the redirect process, while
210 remote_fd is the outgoing TCP connection to the remote server being
211 translated back to the original IP address/port pair.
212
213 Note -
214
215 The following ipnat headers must be included before you can use the
216 code shown in this example:
217
218 #include <netinet/in.h>
219 #include <arpa/inet.h>
220 #include <net/if.h>
221 #include <netinet/ipl.h>
222 #include <netinet/ip_compat.h>
223 #include <netinet/ip_fil.h>
224 #include <netinet/ip_nat.h>
225 #include <string.h>
226 #include <fcntl.h>
227
228
229 Note -
230
231 In the example below, various code fragments have been excluded to
232 enhance clarity.
233
234 int
235 translate_connection(int incoming_fd)
236 {
237 struct sockaddr_in usin;
238 struct natlookup nlp;
239 struct nat_save ns;
240 struct ipfobj obj;
241 struct nat *nat;
242 int remote_fd;
243 int nat_fd;
244 int onoff;
245
246 memset(&ns, 0, sizeof(ns));
247 nat = &ns.ipn_nat
248
249 namelen = sizeof(usin);
250 getsockname(remote_fd, (struct sockaddr *)&usin, &namelen);
251
252 namelen = sizeof(sin);
253 getpeername(incoming_fd, (struct sockaddr *) &sin, &namelen);
254
255 namelen = sizeof(sloc);
256 getsockname(incoming_fd, (struct sockaddr *) &sloc, &namelen);
257
258 bzero((char *) &obi, sizeof(obj));
259 obj.ipfo_rev = IPFILTER_VERSION;
260 obj.ipfo_size = sizeof(nlp);
261 obj.ipfo_ptr = &nip;
262 obj.ipfo_type = IPFOBJ_NATLOOKUP;
263
264 /*
265 * Build up the NAT natlookup structure.
266 */
267 bzero((char *) &nlp, sizeof(nlp));
268 nlp.nl_outip = sin.sin_addr;
269 nlp.nl_inip = sloc.sin_addr;
270 nlp.nl_flags = IPN_TCP;
271 nlp.nl_outport = ntohs(sin.sin_port);
272 nlp.nl_inport = ntohs(sloc.sin_port);
273
274 /*
275 * Open the NAT device and lookup the mapping pair.
276 */
277 nat_fd = open(IPNAT_NAME, O_RDWR);
278 if (ioctl(nat_fd, SIOCGNATL, &obj) != 0)
279 return -1;
280
281 nat->nat_inip = usin.sin_addr;
282 nat->nat_outip = nlp.nl_outip;
283 nat->nat_oip = nlp.nl_realip;
284
285 sum1 = LONG_SUM(ntohl(usin.sin_addr.s_addr)) +
286 ntohs(usin.sin_port);
287 sum2 = LONG_SUM(ntohl(nat->nat_outip.s_addr)) +
288 ntohs(nlp.nl_outport);
289 CALC_SUMD(sum1, sum2, sumd);
290 nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16);
291 nat->nat_sumd[1] = nat->nat_sumd[0];
292
293 sum1 = LONG_SUM(ntohl(usin.sin_addr.s_addr));
294 sum2 = LONG_SUM(ntohl(nat->nat_outip.s_addr));
295 CALC_SUMD(sum1, sum2, sumd);
296 nat->nat_ipsumd = (sumd & 0xffff) + (sumd >> 16);
297
298 nat->nat_inport = usin.sin_port;
299 nat->nat_outport = nlp.nl_outport;
300 nat->nat_oport = nlp.nl_realport;
301
302 nat->nat_flags = IPN_TCPUDP;
303
304 /*
305 * Prepare the ipfobj structure, accordingly.
306 */
307 bzero((char *)&obi, sizeof(obj));
308 obj.ipfo_rev = IPFILTER_VERSION;
309 obj.ipfo_size = sizeof(*nsp);
310 obj.ipfo_ptr = nsp;
311 obj.ipfo_type = IPFOBJ_NATSAVE;
312
313 onoff = 1;
314 if (ioctl(nat_fd, SIOCSTPUT, &obj) != 0)
315 fprintf(stderr, "Error occurred\n");
316
317 return connect(rem_fd, (struct sockaddr ) &usin, sizeof(usin));
318 }
319
320
322 EPERM The device has been opened for reading only. To succeed, the
323 ioctl call must be opened for both reading and writing. The
324 call may be returned if it is privileged and the calling
325 process did not assert {PRIV_SYS_NET_CONFIG} in the effec‐
326 tive set.
327
328
329 ENOMEM More memory was allocated than the kernel can provide. The
330 call may also be returned if the application inserts a NAT
331 entry that exceeds the hash bucket chain's maximum length.
332
333
334 EFAULT The calling process specified an invalid pointer in the
335 ipfobj structure.
336
337
338 EINVAL The calling process detected a parameter or field set to an
339 unacceptable value.
340
341
342 EEXIST The calling process, via SIOCSTPUT, attempted to add a NAT
343 entry that already exists in the NAT table.
344
345
346 ESRCH The calling process called SIOCSTPUT before setting the
347 SI_NEWFR flag and providing a pointer in the nat_fr field
348 that cannot be found in the current rule set.
349
350
351 EACESS The calling process issued a SIOCSTPUT before issuing a SIOC‐
352 STLCK.
353
354
356 See attributes(5) for descriptions of the following attributes:
357
358
359
360
361 ┌─────────────────────────────┬─────────────────────────────┐
362 │ ATTRIBUTE TYPE │ ATTRIBUTE VALUE │
363 ├─────────────────────────────┼─────────────────────────────┤
364 │Interface Stability │Committed │
365 └─────────────────────────────┴─────────────────────────────┘
366
368 ipfs(1M), ipnat(1M), ioctl(2), attributes(5)
369
370
371
372SunOS 5.11 22 May 2008 ipnat(7I)