]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/ipnat.c
This commit was generated by cvs2svn to compensate for changes in r53568,
[FreeBSD/FreeBSD.git] / contrib / ipfilter / ipnat.c
1 /*
2  * Copyright (C) 1993-1998 by Darren Reed.
3  *
4  * Redistribution and use in source and binary forms are permitted
5  * provided that this notice is preserved and due credit is given
6  * to the original author and the contributors.
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/socket.h>
26 #include <sys/ioctl.h>
27 #if defined(sun) && (defined(__svr4__) || defined(__SVR4))
28 # include <sys/ioccom.h>
29 # include <sys/sysmacros.h>
30 #endif
31 #include <netinet/in.h>
32 #include <netinet/in_systm.h>
33 #include <netinet/ip.h>
34 #include <netinet/tcp.h>
35 #include <net/if.h>
36 #if __FreeBSD_version >= 300000
37 # include <net/if_var.h>
38 #endif
39 #include <netdb.h>
40 #include <arpa/nameser.h>
41 #include <arpa/inet.h>
42 #include <resolv.h>
43 #include <ctype.h>
44 #include "netinet/ip_compat.h"
45 #include "netinet/ip_fil.h"
46 #include "netinet/ip_proxy.h"
47 #include "netinet/ip_nat.h"
48 #include "kmem.h"
49
50 #if     defined(sun) && !SOLARIS2
51 # define        STRERROR(x)     sys_errlist[x]
52 extern  char    *sys_errlist[];
53 #else
54 # define        STRERROR(x)     strerror(x)
55 #endif
56
57 #if !defined(lint)
58 static const char sccsid[] ="@(#)ipnat.c        1.9 6/5/96 (C) 1993 Darren Reed";
59 static const char rcsid[] = "@(#)$Id: ipnat.c,v 2.1 1999/08/04 17:30:07 darrenr Exp $";
60 #endif
61
62
63 #if     SOLARIS
64 #define bzero(a,b)      memset(a,0,b)
65 #endif
66
67 extern  char    *optarg;
68 extern  ipnat_t *natparse __P((char *, int));
69 extern  void    natparsefile __P((int, char *, int));
70 extern  void    printnat __P((ipnat_t *, int, void *));
71
72 u_32_t  hostnum __P((char *, int *, int));
73 u_32_t  hostmask __P((char *));
74 void    dostats __P((int, int)), flushtable __P((int, int));
75 void    usage __P((char *));
76 int     countbits __P((u_32_t));
77 char    *getnattype __P((ipnat_t *));
78 int     main __P((int, char*[]));
79 void    printaps __P((ap_session_t *, int));
80
81 #define OPT_REM         1
82 #define OPT_NODO        2
83 #define OPT_STAT        4
84 #define OPT_LIST        8
85 #define OPT_VERBOSE     16
86 #define OPT_FLUSH       32
87 #define OPT_CLEAR       64
88 #define OPT_HITS        128
89
90
91 void usage(name)
92 char *name;
93 {
94         fprintf(stderr, "%s: [-CFhlnrsv] [-f filename]\n", name);
95         exit(1);
96 }
97
98
99 int main(argc, argv)
100 int argc;
101 char *argv[];
102 {
103         char    *file = NULL;
104         int     fd = -1, opts = 0, c;
105
106         while ((c = getopt(argc, argv, "CFf:hlnrsv")) != -1)
107                 switch (c)
108                 {
109                 case 'C' :
110                         opts |= OPT_CLEAR;
111                         break;
112                 case 'f' :
113                         file = optarg;
114                         break;
115                 case 'F' :
116                         opts |= OPT_FLUSH;
117                         break;
118                 case 'h' :
119                         opts |=OPT_HITS;
120                         break;
121                 case 'l' :
122                         opts |= OPT_LIST;
123                         break;
124                 case 'n' :
125                         opts |= OPT_NODO;
126                         break;
127                 case 'r' :
128                         opts |= OPT_REM;
129                         break;
130                 case 's' :
131                         opts |= OPT_STAT;
132                         break;
133                 case 'v' :
134                         opts |= OPT_VERBOSE;
135                         break;
136                 default :
137                         usage(argv[0]);
138                 }
139
140         if (!(opts & OPT_NODO) && ((fd = open(IPL_NAT, O_RDWR)) == -1) &&
141             ((fd = open(IPL_NAT, O_RDONLY)) == -1)) {
142                 (void) fprintf(stderr, "%s: open: %s\n", IPL_NAT,
143                         STRERROR(errno));
144                 exit(-1);
145         }
146
147         if (opts & (OPT_FLUSH|OPT_CLEAR))
148                 flushtable(fd, opts);
149         if (file)
150                 natparsefile(fd, file, opts);
151         if (opts & (OPT_LIST|OPT_STAT))
152                 dostats(fd, opts);
153         return 0;
154 }
155
156
157 /*
158  * count consecutive 1's in bit mask.  If the mask generated by counting
159  * consecutive 1's is different to that passed, return -1, else return #
160  * of bits.
161  */
162 int     countbits(ip)
163 u_32_t  ip;
164 {
165         u_32_t  ipn;
166         int     cnt = 0, i, j;
167
168         ip = ipn = ntohl(ip);
169         for (i = 32; i; i--, ipn *= 2)
170                 if (ipn & 0x80000000)
171                         cnt++;
172                 else
173                         break;
174         ipn = 0;
175         for (i = 32, j = cnt; i; i--, j--) {
176                 ipn *= 2;
177                 if (j > 0)
178                         ipn++;
179         }
180         if (ipn == ip)
181                 return cnt;
182         return -1;
183 }
184
185
186 void printaps(aps, opts)
187 ap_session_t *aps;
188 int opts;
189 {
190         ap_session_t ap;
191         aproxy_t apr;
192         raudio_t ra;
193
194         if (kmemcpy((char *)&ap, (long)aps, sizeof(ap)))
195                 return;
196         if (kmemcpy((char *)&apr, (long)ap.aps_apr, sizeof(apr)))
197                 return;
198         printf("\tproxy %s/%d use %d flags %x\n", apr.apr_label,
199                 apr.apr_p, apr.apr_ref, apr.apr_flags);
200         printf("\t\tproto %d flags %#x bytes ", ap.aps_p, ap.aps_flags);
201 #ifdef  USE_QUAD_T
202         printf("%qu pkts %qu", ap.aps_bytes, ap.aps_pkts);
203 #else
204         printf("%lu pkts %lu", ap.aps_bytes, ap.aps_pkts);
205 #endif
206         printf(" data %p psiz %d\n", ap.aps_data, ap.aps_psiz);
207         if ((ap.aps_p == IPPROTO_TCP) && (opts & OPT_VERBOSE)) {
208                 printf("\t\tstate[%u,%u], sel[%d,%d]\n",
209                         ap.aps_state[0], ap.aps_state[1],
210                         ap.aps_sel[0], ap.aps_sel[1]);
211 #if (defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011)) || \
212     (__FreeBSD_version >= 300000) || defined(OpenBSD)
213                 printf("\t\tseq: off %hd/%hd min %x/%x\n",
214                         ap.aps_seqoff[0], ap.aps_seqoff[1],
215                         ap.aps_seqmin[0], ap.aps_seqmin[1]);
216                 printf("\t\tack: off %hd/%hd min %x/%x\n",
217                         ap.aps_ackoff[0], ap.aps_ackoff[1],
218                         ap.aps_ackmin[0], ap.aps_ackmin[1]);
219 #else
220                 printf("\t\tseq: off %hd/%hd min %lx/%lx\n",
221                         ap.aps_seqoff[0], ap.aps_seqoff[1],
222                         ap.aps_seqmin[0], ap.aps_seqmin[1]);
223                 printf("\t\tack: off %hd/%hd min %lx/%lx\n",
224                         ap.aps_ackoff[0], ap.aps_ackoff[1],
225                         ap.aps_ackmin[0], ap.aps_ackmin[1]);
226 #endif
227         }
228
229         if (!strcmp(apr.apr_label, "raudio") && ap.aps_psiz == sizeof(ra)) {
230                 if (kmemcpy((char *)&ra, (long)ap.aps_data, sizeof(ra)))
231                         return;
232                 printf("\tReal Audio Proxy:\n");
233                 printf("\t\tSeen PNA: %d\tVersion: %d\tEOS: %d\n",
234                         ra.rap_seenpna, ra.rap_version, ra.rap_eos);
235                 printf("\t\tMode: %#x\tSBF: %#x\n", ra.rap_mode, ra.rap_sbf);
236                 printf("\t\tPorts:pl %hu, pr %hu, sr %hu\n",
237                         ra.rap_plport, ra.rap_prport, ra.rap_srport);
238         }
239 }
240
241
242 /*
243  * Get a nat filter type given its kernel address.
244  */
245 char *getnattype(ipnat)
246 ipnat_t *ipnat;
247 {
248         char *which;
249         ipnat_t ipnatbuff;
250
251         if (!ipnat || (ipnat && kmemcpy((char *)&ipnatbuff, (long)ipnat,
252                                         sizeof(ipnatbuff))))
253                 return "???";
254
255         switch (ipnatbuff.in_redir)
256         {
257         case NAT_MAP :
258                 which = "MAP";
259                 break;
260         case NAT_MAPBLK :
261                 which = "MAP-BLOCK";
262                 break;
263         case NAT_REDIRECT :
264                 which = "RDR";
265                 break;
266         case NAT_BIMAP :
267                 which = "BIMAP";
268                 break;
269         default :
270                 which = "unknown";
271                 break;
272         }
273         return which;
274 }
275
276
277 void dostats(fd, opts)
278 int fd, opts;
279 {
280         natstat_t ns;
281         ipnat_t ipn;
282         nat_t   **nt[2], *np, nat;
283         int     i = 0;
284
285         bzero((char *)&ns, sizeof(ns));
286
287         if (!(opts & OPT_NODO) && ioctl(fd, SIOCGNATS, &ns) == -1) {
288                 perror("ioctl(SIOCGNATS)");
289                 return;
290         }
291
292         if (opts & OPT_STAT) {
293                 printf("mapped\tin\t%lu\tout\t%lu\n",
294                         ns.ns_mapped[0], ns.ns_mapped[1]);
295                 printf("added\t%lu\texpired\t%lu\n",
296                         ns.ns_added, ns.ns_expire);
297                 printf("inuse\t%lu\nrules\t%lu\n", ns.ns_inuse, ns.ns_rules);
298                 if (opts & OPT_VERBOSE)
299                         printf("table %p list %p\n", ns.ns_table, ns.ns_list);
300         }
301         if (opts & OPT_LIST) {
302                 printf("List of active MAP/Redirect filters:\n");
303                 while (ns.ns_list) {
304                         if (kmemcpy((char *)&ipn, (long)ns.ns_list,
305                                     sizeof(ipn))) {
306                                 perror("kmemcpy");
307                                 break;
308                         }
309                         if (opts & OPT_HITS)
310                                 printf("%d ", ipn.in_hits);
311                         printnat(&ipn, opts & OPT_VERBOSE, (void *)ns.ns_list);
312                         ns.ns_list = ipn.in_next;
313                 }
314
315                 nt[0] = (nat_t **)malloc(sizeof(*nt) * NAT_SIZE);
316                 if (kmemcpy((char *)nt[0], (long)ns.ns_table[0],
317                             sizeof(**nt) * NAT_SIZE)) {
318                         perror("kmemcpy");
319                         return;
320                 }
321
322                 printf("\nList of active sessions:\n");
323
324                 for (np = ns.ns_instances; np; np = nat.nat_next) {
325                         if (kmemcpy((char *)&nat, (long)np, sizeof(nat)))
326                                 break;
327
328                         printf("%s %-15s %-5hu <- ->", getnattype(nat.nat_ptr),
329                                inet_ntoa(nat.nat_inip), ntohs(nat.nat_inport));
330                         printf(" %-15s %-5hu", inet_ntoa(nat.nat_outip),
331                                 ntohs(nat.nat_outport));
332                         printf(" [%s %hu]", inet_ntoa(nat.nat_oip),
333                                 ntohs(nat.nat_oport));
334                         if (opts & OPT_VERBOSE) {
335                                 printf("\n\tage %lu use %hu sumd %x pr %u",
336                                         nat.nat_age, nat.nat_use, nat.nat_sumd,
337                                         nat.nat_p);
338                                 printf(" bkt %d flags %x ", i, nat.nat_flags);
339 #ifdef  USE_QUAD_T
340                                 printf("bytes %qu pkts %qu",
341                                         nat.nat_bytes, nat.nat_pkts);
342 #else
343                                 printf("bytes %lu pkts %lu",
344                                         nat.nat_bytes, nat.nat_pkts);
345 #endif
346 #if SOLARIS
347                                 printf(" %lx", nat.nat_ipsumd);
348 #endif
349                         }
350                         putchar('\n');
351                         if (nat.nat_aps)
352                                 printaps(nat.nat_aps, opts);
353                 }
354
355                 free(nt[0]);
356         }
357 }
358
359
360 u_32_t  hostmask(msk)
361 char    *msk;
362 {
363         int     bits = -1;
364         u_32_t  mask;
365
366         if (!isdigit(*msk))
367                 return (u_32_t)-1;
368         if (strchr(msk, '.'))
369                 return inet_addr(msk);
370         if (strchr(msk, 'x'))
371                 return (u_32_t)strtol(msk, NULL, 0);
372         /*
373          * set x most significant bits
374          */
375         for (mask = 0, bits = atoi(msk); bits; bits--) {
376                 mask /= 2;
377                 mask |= ntohl(inet_addr("128.0.0.0"));
378         }
379         mask = htonl(mask);
380         return mask;
381 }
382
383
384 /*
385  * returns an ip address as a long var as a result of either a DNS lookup or
386  * straight inet_addr() call
387  */
388 u_32_t  hostnum(host, resolved, linenum)
389 char    *host;
390 int     *resolved;
391 int     linenum;
392 {
393         struct  hostent *hp;
394         struct  netent  *np;
395
396         *resolved = 0;
397         if (!strcasecmp("any", host))
398                 return 0L;
399         if (isdigit(*host))
400                 return inet_addr(host);
401
402         if (!(hp = gethostbyname(host))) {
403                 if (!(np = getnetbyname(host))) {
404                         *resolved = -1;
405                         fprintf(stderr, "Line %d: can't resolve hostname: %s\n", linenum, host);
406                         return 0;
407                 }
408                 return htonl(np->n_net);
409         }
410         return *(u_32_t *)hp->h_addr;
411 }
412
413
414 void flushtable(fd, opts)
415 int fd, opts;
416 {
417         int n = 0;
418
419         if (opts & OPT_FLUSH) {
420                 n = 0;
421                 if (!(opts & OPT_NODO) && ioctl(fd, SIOCFLNAT, &n) == -1)
422                         perror("ioctl(SIOCFLNAT)");
423                 else
424                         printf("%d entries flushed from NAT table\n", n);
425         }
426
427         if (opts & OPT_CLEAR) {
428                 n = 0;
429                 if (!(opts & OPT_NODO) && ioctl(fd, SIOCCNATL, &n) == -1)
430                         perror("ioctl(SIOCCNATL)");
431                 else
432                         printf("%d entries flushed from NAT list\n", n);
433         }
434 }