1ipnat(7I)                       Ioctl Requests                       ipnat(7I)
2
3
4

NAME

6       ipnat - IP Filter/NAT module interface
7

DESCRIPTION

9       The  ipnat  device  provides  interfaction with the NAT features of the
10       Solaris IPFilter.
11

APPLICATION PROGRAMMING INTERFACE

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

IOCTLS

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

EXAMPLES

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

ERRORS

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

ATTRIBUTES

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

SEE ALSO

368       ipfs(1M), ipnat(1M), ioctl(2), attributes(5)
369
370
371
372SunOS 5.11                        22 May 2008                        ipnat(7I)
Impressum