]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/tools/ipnat.c
This commit was generated by cvs2svn to compensate for changes in r169185,
[FreeBSD/FreeBSD.git] / contrib / ipfilter / tools / ipnat.c
1 /*      $FreeBSD$       */
2
3 /*
4  * Copyright (C) 1993-2001 by Darren Reed.
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  *
8  * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
9  */
10 #include <stdio.h>
11 #include <string.h>
12 #include <fcntl.h>
13 #include <errno.h>
14 #include <sys/types.h>
15 #if !defined(__SVR4) && !defined(__svr4__)
16 #include <strings.h>
17 #else
18 #include <sys/byteorder.h>
19 #endif
20 #include <sys/time.h>
21 #include <sys/param.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <stddef.h>
25 #include <sys/file.h>
26 #define _KERNEL
27 #include <sys/uio.h>
28 #undef _KERNEL
29 #include <sys/socket.h>
30 #include <sys/ioctl.h>
31 #if defined(sun) && (defined(__svr4__) || defined(__SVR4))
32 # include <sys/ioccom.h>
33 # include <sys/sysmacros.h>
34 #endif
35 #include <netinet/in.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/ip.h>
38 #include <netinet/tcp.h>
39 #include <net/if.h>
40 #if __FreeBSD_version >= 300000
41 # include <net/if_var.h>
42 #endif
43 #include <netdb.h>
44 #include <arpa/nameser.h>
45 #include <arpa/inet.h>
46 #include <resolv.h>
47 #include <ctype.h>
48 #if defined(linux)
49 # include <linux/a.out.h>
50 #else
51 # include <nlist.h>
52 #endif
53 #include "ipf.h"
54 #include "netinet/ipl.h"
55 #include "kmem.h"
56
57 #ifdef  __hpux
58 # define        nlist   nlist64
59 #endif
60
61 #if     defined(sun) && !SOLARIS2
62 # define        STRERROR(x)     sys_errlist[x]
63 extern  char    *sys_errlist[];
64 #else
65 # define        STRERROR(x)     strerror(x)
66 #endif
67
68 #if !defined(lint)
69 static const char sccsid[] ="@(#)ipnat.c        1.9 6/5/96 (C) 1993 Darren Reed";
70 static const char rcsid[] = "@(#)$Id: ipnat.c,v 1.24.2.2 2005/05/10 21:19:30 darrenr Exp $";
71 #endif
72
73
74 #if     SOLARIS
75 #define bzero(a,b)      memset(a,0,b)
76 #endif
77 int     use_inet6 = 0;
78 char    thishost[MAXHOSTNAMELEN];
79
80 extern  char    *optarg;
81
82 void    dostats __P((natstat_t *, int)), flushtable __P((int, int));
83 void    usage __P((char *));
84 int     main __P((int, char*[]));
85 void    showhostmap __P((natstat_t *nsp));
86 void    natstat_dead __P((natstat_t *, char *));
87
88 int     opts;
89
90 void usage(name)
91 char *name;
92 {
93         fprintf(stderr, "Usage: %s [-CFhlnrRsv] [-f filename]\n", name);
94         exit(1);
95 }
96
97
98 int main(argc, argv)
99 int argc;
100 char *argv[];
101 {
102         char *file, *core, *kernel;
103         natstat_t ns, *nsp;
104         int fd, c, mode;
105         ipfobj_t obj;
106
107         fd = -1;
108         opts = 0;
109         nsp = &ns;
110         file = NULL;
111         core = NULL;
112         kernel = NULL;
113         mode = O_RDWR;
114
115         while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsv")) != -1)
116                 switch (c)
117                 {
118                 case 'C' :
119                         opts |= OPT_CLEAR;
120                         break;
121                 case 'd' :
122                         opts |= OPT_DEBUG;
123                         break;
124                 case 'f' :
125                         file = optarg;
126                         break;
127                 case 'F' :
128                         opts |= OPT_FLUSH;
129                         break;
130                 case 'h' :
131                         opts |=OPT_HITS;
132                         break;
133                 case 'l' :
134                         opts |= OPT_LIST;
135                         mode = O_RDONLY;
136                         break;
137                 case 'M' :
138                         core = optarg;
139                         break;
140                 case 'N' :
141                         kernel = optarg;
142                         break;
143                 case 'n' :
144                         opts |= OPT_DONOTHING;
145                         mode = O_RDONLY;
146                         break;
147                 case 'R' :
148                         opts |= OPT_NORESOLVE;
149                         break;
150                 case 'r' :
151                         opts |= OPT_REMOVE;
152                         break;
153                 case 's' :
154                         opts |= OPT_STAT;
155                         mode = O_RDONLY;
156                         break;
157                 case 'v' :
158                         opts |= OPT_VERBOSE;
159                         break;
160                 default :
161                         usage(argv[0]);
162                 }
163
164         initparse();
165
166         if ((kernel != NULL) || (core != NULL)) {
167                 (void) setgid(getgid());
168                 (void) setuid(getuid());
169         }
170
171         bzero((char *)&ns, sizeof(ns));
172
173         if ((opts & OPT_DONOTHING) == 0) {
174                 if (checkrev(IPL_NAME) == -1) {
175                         fprintf(stderr, "User/kernel version check failed\n");
176                         exit(1);
177                 }
178         }
179
180
181         if (!(opts & OPT_DONOTHING) && (kernel == NULL) && (core == NULL)) {
182                 if (openkmem(kernel, core) == -1)
183                         exit(1);
184
185                 if (((fd = open(IPNAT_NAME, mode)) == -1) &&
186                     ((fd = open(IPNAT_NAME, O_RDONLY)) == -1)) {
187                         (void) fprintf(stderr, "%s: open: %s\n", IPNAT_NAME,
188                                 STRERROR(errno));
189                         exit(1);
190                 }
191
192                 bzero((char *)&obj, sizeof(obj));
193                 obj.ipfo_rev = IPFILTER_VERSION;
194                 obj.ipfo_size = sizeof(*nsp);
195                 obj.ipfo_type = IPFOBJ_NATSTAT;
196                 obj.ipfo_ptr = (void *)nsp;
197                 if (ioctl(fd, SIOCGNATS, &obj) == -1) {
198                         perror("ioctl(SIOCGNATS)");
199                         exit(1);
200                 }
201                 (void) setgid(getgid());
202                 (void) setuid(getuid());
203         } else if ((kernel != NULL) || (core != NULL)) {
204                 if (openkmem(kernel, core) == -1)
205                         exit(1);
206
207                 natstat_dead(nsp, kernel);
208                 if (opts & (OPT_LIST|OPT_STAT))
209                         dostats(nsp, opts);
210                 exit(0);
211         }
212
213         if (opts & (OPT_FLUSH|OPT_CLEAR))
214                 flushtable(fd, opts);
215         if (file) {
216                 ipnat_parsefile(fd, ipnat_addrule, ioctl, file);
217         }
218         if (opts & (OPT_LIST|OPT_STAT))
219                 dostats(nsp, opts);
220         return 0;
221 }
222
223
224 /*
225  * Read NAT statistic information in using a symbol table and memory file
226  * rather than doing ioctl's.
227  */
228 void natstat_dead(nsp, kernel)
229 natstat_t *nsp;
230 char *kernel;
231 {
232         struct nlist nat_nlist[10] = {
233                 { "nat_table" },                /* 0 */
234                 { "nat_list" },
235                 { "maptable" },
236                 { "ipf_nattable_sz" },
237                 { "ipf_natrules_sz" },
238                 { "ipf_rdrrules_sz" },          /* 5 */
239                 { "ipf_hostmap_sz" },
240                 { "nat_instances" },
241                 { "ap_sess_list" },
242                 { NULL }
243         };
244         void *tables[2];
245
246         if (nlist(kernel, nat_nlist) == -1) {
247                 fprintf(stderr, "nlist error\n");
248                 return;
249         }
250
251         /*
252          * Normally the ioctl copies all of these values into the structure
253          * for us, before returning it to userland, so here we must copy each
254          * one in individually.
255          */
256         kmemcpy((char *)&tables, nat_nlist[0].n_value, sizeof(tables));
257         nsp->ns_table[0] = tables[0];
258         nsp->ns_table[1] = tables[1];
259
260         kmemcpy((char *)&nsp->ns_list, nat_nlist[1].n_value,
261                 sizeof(nsp->ns_list));
262         kmemcpy((char *)&nsp->ns_maptable, nat_nlist[2].n_value,
263                 sizeof(nsp->ns_maptable));
264         kmemcpy((char *)&nsp->ns_nattab_sz, nat_nlist[3].n_value,
265                 sizeof(nsp->ns_nattab_sz));
266         kmemcpy((char *)&nsp->ns_rultab_sz, nat_nlist[4].n_value,
267                 sizeof(nsp->ns_rultab_sz));
268         kmemcpy((char *)&nsp->ns_rdrtab_sz, nat_nlist[5].n_value,
269                 sizeof(nsp->ns_rdrtab_sz));
270         kmemcpy((char *)&nsp->ns_hostmap_sz, nat_nlist[6].n_value,
271                 sizeof(nsp->ns_hostmap_sz));
272         kmemcpy((char *)&nsp->ns_instances, nat_nlist[7].n_value,
273                 sizeof(nsp->ns_instances));
274         kmemcpy((char *)&nsp->ns_apslist, nat_nlist[8].n_value,
275                 sizeof(nsp->ns_apslist));
276 }
277
278
279 /*
280  * Display NAT statistics.
281  */
282 void dostats(nsp, opts)
283 natstat_t *nsp;
284 int opts;
285 {
286         nat_t *np, nat;
287         ipnat_t ipn;
288
289         /*
290          * Show statistics ?
291          */
292         if (opts & OPT_STAT) {
293                 printf("mapped\tin\t%lu\tout\t%lu\n",
294                         nsp->ns_mapped[0], nsp->ns_mapped[1]);
295                 printf("added\t%lu\texpired\t%lu\n",
296                         nsp->ns_added, nsp->ns_expire);
297                 printf("no memory\t%lu\tbad nat\t%lu\n",
298                         nsp->ns_memfail, nsp->ns_badnat);
299                 printf("inuse\t%lu\nrules\t%lu\n",
300                         nsp->ns_inuse, nsp->ns_rules);
301                 printf("wilds\t%u\n", nsp->ns_wilds);
302                 if (opts & OPT_VERBOSE)
303                         printf("table %p list %p\n",
304                                 nsp->ns_table, nsp->ns_list);
305         }
306
307         /*
308          * Show list of NAT rules and NAT sessions ?
309          */
310         if (opts & OPT_LIST) {
311                 printf("List of active MAP/Redirect filters:\n");
312                 while (nsp->ns_list) {
313                         if (kmemcpy((char *)&ipn, (long)nsp->ns_list,
314                                     sizeof(ipn))) {
315                                 perror("kmemcpy");
316                                 break;
317                         }
318                         if (opts & OPT_HITS)
319                                 printf("%lu ", ipn.in_hits);
320                         printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
321                         nsp->ns_list = ipn.in_next;
322                 }
323
324                 printf("\nList of active sessions:\n");
325
326                 for (np = nsp->ns_instances; np; np = nat.nat_next) {
327                         if (kmemcpy((char *)&nat, (long)np, sizeof(nat)))
328                                 break;
329                         printactivenat(&nat, opts);
330                         if (nat.nat_aps)
331                                 printaps(nat.nat_aps, opts);
332                 }
333
334                 if (opts & OPT_VERBOSE)
335                         showhostmap(nsp);
336         }
337 }
338
339
340 /*
341  * Display the active host mapping table.
342  */
343 void showhostmap(nsp)
344 natstat_t *nsp;
345 {
346         hostmap_t hm, *hmp, **maptable;
347         u_int hv;
348
349         printf("\nList of active host mappings:\n");
350
351         maptable = (hostmap_t **)malloc(sizeof(hostmap_t *) *
352                                         nsp->ns_hostmap_sz);
353         if (kmemcpy((char *)maptable, (u_long)nsp->ns_maptable,
354                     sizeof(hostmap_t *) * nsp->ns_hostmap_sz)) {
355                 perror("kmemcpy (maptable)");
356                 return;
357         }
358
359         for (hv = 0; hv < nsp->ns_hostmap_sz; hv++) {
360                 hmp = maptable[hv];
361
362                 while (hmp) {
363                         if (kmemcpy((char *)&hm, (u_long)hmp, sizeof(hm))) {
364                                 perror("kmemcpy (hostmap)");
365                                 return;
366                         }
367
368                         printhostmap(&hm, hv);
369                         hmp = hm.hm_next;
370                 }
371         }
372         free(maptable);
373 }
374
375
376 /*
377  * Issue an ioctl to flush either the NAT rules table or the active mapping
378  * table or both.
379  */
380 void flushtable(fd, opts)
381 int fd, opts;
382 {
383         int n = 0;
384
385         if (opts & OPT_FLUSH) {
386                 n = 0;
387                 if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1)
388                         perror("ioctl(SIOCFLNAT)");
389                 else
390                         printf("%d entries flushed from NAT table\n", n);
391         }
392
393         if (opts & OPT_CLEAR) {
394                 n = 1;
395                 if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1)
396                         perror("ioctl(SIOCCNATL)");
397                 else
398                         printf("%d entries flushed from NAT list\n", n);
399         }
400 }