source: rtems-libbsd/freebsd/contrib/pf/pfctl/pfctl_radix.c @ 6e9a8ea

5-freebsd-12freebsd-9.3
Last change on this file since 6e9a8ea was 6e9a8ea, checked in by Christian Mauderer <Christian.Mauderer@…>, on Jul 5, 2016 at 2:07:37 PM

pfctl: Import sources from FreeBSD.

  • Property mode set to 100644
File size: 12.4 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*      $OpenBSD: pfctl_radix.c,v 1.27 2005/05/21 21:03:58 henning Exp $ */
4
5/*
6 * Copyright (c) 2002 Cedric Berger
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 *    - Redistributions of source code must retain the above copyright
14 *      notice, this list of conditions and the following disclaimer.
15 *    - Redistributions in binary form must reproduce the above
16 *      copyright notice, this list of conditions and the following
17 *      disclaimer in the documentation and/or other materials provided
18 *      with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD$");
37
38#include <sys/types.h>
39#include <sys/ioctl.h>
40#include <sys/socket.h>
41
42#include <net/if.h>
43#include <net/pfvar.h>
44
45#include <errno.h>
46#include <string.h>
47#include <ctype.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <limits.h>
51#include <err.h>
52
53#include "pfctl.h"
54
55#define BUF_SIZE 256
56
57extern int dev;
58
59static int       pfr_next_token(char buf[], FILE *);
60
61
62int
63pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
64{
65        struct pfioc_table io;
66
67        bzero(&io, sizeof io);
68        io.pfrio_flags = flags;
69        if (filter != NULL)
70                io.pfrio_table = *filter;
71        if (ioctl(dev, DIOCRCLRTABLES, &io))
72                return (-1);
73        if (ndel != NULL)
74                *ndel = io.pfrio_ndel;
75        return (0);
76}
77
78int
79pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
80{
81        struct pfioc_table io;
82
83        if (size < 0 || (size && tbl == NULL)) {
84                errno = EINVAL;
85                return (-1);
86        }
87        bzero(&io, sizeof io);
88        io.pfrio_flags = flags;
89        io.pfrio_buffer = tbl;
90        io.pfrio_esize = sizeof(*tbl);
91        io.pfrio_size = size;
92        if (ioctl(dev, DIOCRADDTABLES, &io))
93                return (-1);
94        if (nadd != NULL)
95                *nadd = io.pfrio_nadd;
96        return (0);
97}
98
99int
100pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
101{
102        struct pfioc_table io;
103
104        if (size < 0 || (size && tbl == NULL)) {
105                errno = EINVAL;
106                return (-1);
107        }
108        bzero(&io, sizeof io);
109        io.pfrio_flags = flags;
110        io.pfrio_buffer = tbl;
111        io.pfrio_esize = sizeof(*tbl);
112        io.pfrio_size = size;
113        if (ioctl(dev, DIOCRDELTABLES, &io))
114                return (-1);
115        if (ndel != NULL)
116                *ndel = io.pfrio_ndel;
117        return (0);
118}
119
120int
121pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
122        int flags)
123{
124        struct pfioc_table io;
125
126        if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
127                errno = EINVAL;
128                return (-1);
129        }
130        bzero(&io, sizeof io);
131        io.pfrio_flags = flags;
132        if (filter != NULL)
133                io.pfrio_table = *filter;
134        io.pfrio_buffer = tbl;
135        io.pfrio_esize = sizeof(*tbl);
136        io.pfrio_size = *size;
137        if (ioctl(dev, DIOCRGETTABLES, &io))
138                return (-1);
139        *size = io.pfrio_size;
140        return (0);
141}
142
143int
144pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
145        int flags)
146{
147        struct pfioc_table io;
148
149        if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
150                errno = EINVAL;
151                return (-1);
152        }
153        bzero(&io, sizeof io);
154        io.pfrio_flags = flags;
155        if (filter != NULL)
156                io.pfrio_table = *filter;
157        io.pfrio_buffer = tbl;
158        io.pfrio_esize = sizeof(*tbl);
159        io.pfrio_size = *size;
160        if (ioctl(dev, DIOCRGETTSTATS, &io))
161                return (-1);
162        *size = io.pfrio_size;
163        return (0);
164}
165
166int
167pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
168{
169        struct pfioc_table io;
170
171        if (tbl == NULL) {
172                errno = EINVAL;
173                return (-1);
174        }
175        bzero(&io, sizeof io);
176        io.pfrio_flags = flags;
177        io.pfrio_table = *tbl;
178        if (ioctl(dev, DIOCRCLRADDRS, &io))
179                return (-1);
180        if (ndel != NULL)
181                *ndel = io.pfrio_ndel;
182        return (0);
183}
184
185int
186pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
187    int *nadd, int flags)
188{
189        struct pfioc_table io;
190
191        if (tbl == NULL || size < 0 || (size && addr == NULL)) {
192                errno = EINVAL;
193                return (-1);
194        }
195        bzero(&io, sizeof io);
196        io.pfrio_flags = flags;
197        io.pfrio_table = *tbl;
198        io.pfrio_buffer = addr;
199        io.pfrio_esize = sizeof(*addr);
200        io.pfrio_size = size;
201        if (ioctl(dev, DIOCRADDADDRS, &io))
202                return (-1);
203        if (nadd != NULL)
204                *nadd = io.pfrio_nadd;
205        return (0);
206}
207
208int
209pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
210    int *ndel, int flags)
211{
212        struct pfioc_table io;
213
214        if (tbl == NULL || size < 0 || (size && addr == NULL)) {
215                errno = EINVAL;
216                return (-1);
217        }
218        bzero(&io, sizeof io);
219        io.pfrio_flags = flags;
220        io.pfrio_table = *tbl;
221        io.pfrio_buffer = addr;
222        io.pfrio_esize = sizeof(*addr);
223        io.pfrio_size = size;
224        if (ioctl(dev, DIOCRDELADDRS, &io))
225                return (-1);
226        if (ndel != NULL)
227                *ndel = io.pfrio_ndel;
228        return (0);
229}
230
231int
232pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
233    int *size2, int *nadd, int *ndel, int *nchange, int flags)
234{
235        struct pfioc_table io;
236
237        if (tbl == NULL || size < 0 || (size && addr == NULL)) {
238                errno = EINVAL;
239                return (-1);
240        }
241        bzero(&io, sizeof io);
242        io.pfrio_flags = flags;
243        io.pfrio_table = *tbl;
244        io.pfrio_buffer = addr;
245        io.pfrio_esize = sizeof(*addr);
246        io.pfrio_size = size;
247        io.pfrio_size2 = (size2 != NULL) ? *size2 : 0;
248        if (ioctl(dev, DIOCRSETADDRS, &io))
249                return (-1);
250        if (nadd != NULL)
251                *nadd = io.pfrio_nadd;
252        if (ndel != NULL)
253                *ndel = io.pfrio_ndel;
254        if (nchange != NULL)
255                *nchange = io.pfrio_nchange;
256        if (size2 != NULL)
257                *size2 = io.pfrio_size2;
258        return (0);
259}
260
261int
262pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
263    int flags)
264{
265        struct pfioc_table io;
266
267        if (tbl == NULL || size == NULL || *size < 0 ||
268            (*size && addr == NULL)) {
269                errno = EINVAL;
270                return (-1);
271        }
272        bzero(&io, sizeof io);
273        io.pfrio_flags = flags;
274        io.pfrio_table = *tbl;
275        io.pfrio_buffer = addr;
276        io.pfrio_esize = sizeof(*addr);
277        io.pfrio_size = *size;
278        if (ioctl(dev, DIOCRGETADDRS, &io))
279                return (-1);
280        *size = io.pfrio_size;
281        return (0);
282}
283
284int
285pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
286    int flags)
287{
288        struct pfioc_table io;
289
290        if (tbl == NULL || size == NULL || *size < 0 ||
291            (*size && addr == NULL)) {
292                errno = EINVAL;
293                return (-1);
294        }
295        bzero(&io, sizeof io);
296        io.pfrio_flags = flags;
297        io.pfrio_table = *tbl;
298        io.pfrio_buffer = addr;
299        io.pfrio_esize = sizeof(*addr);
300        io.pfrio_size = *size;
301        if (ioctl(dev, DIOCRGETASTATS, &io))
302                return (-1);
303        *size = io.pfrio_size;
304        return (0);
305}
306
307int
308pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
309{
310        struct pfioc_table io;
311
312        if (size < 0 || (size && !tbl)) {
313                errno = EINVAL;
314                return (-1);
315        }
316        bzero(&io, sizeof io);
317        io.pfrio_flags = flags;
318        io.pfrio_buffer = tbl;
319        io.pfrio_esize = sizeof(*tbl);
320        io.pfrio_size = size;
321        if (ioctl(dev, DIOCRCLRTSTATS, &io))
322                return (-1);
323        if (nzero)
324                *nzero = io.pfrio_nzero;
325        return (0);
326}
327
328int
329pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
330    int *nmatch, int flags)
331{
332        struct pfioc_table io;
333
334        if (tbl == NULL || size < 0 || (size && addr == NULL)) {
335                errno = EINVAL;
336                return (-1);
337        }
338        bzero(&io, sizeof io);
339        io.pfrio_flags = flags;
340        io.pfrio_table = *tbl;
341        io.pfrio_buffer = addr;
342        io.pfrio_esize = sizeof(*addr);
343        io.pfrio_size = size;
344        if (ioctl(dev, DIOCRTSTADDRS, &io))
345                return (-1);
346        if (nmatch)
347                *nmatch = io.pfrio_nmatch;
348        return (0);
349}
350
351int
352pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
353    int *nadd, int *naddr, int ticket, int flags)
354{
355        struct pfioc_table io;
356
357        if (tbl == NULL || size < 0 || (size && addr == NULL)) {
358                errno = EINVAL;
359                return (-1);
360        }
361        bzero(&io, sizeof io);
362        io.pfrio_flags = flags;
363        io.pfrio_table = *tbl;
364        io.pfrio_buffer = addr;
365        io.pfrio_esize = sizeof(*addr);
366        io.pfrio_size = size;
367        io.pfrio_ticket = ticket;
368        if (ioctl(dev, DIOCRINADEFINE, &io))
369                return (-1);
370        if (nadd != NULL)
371                *nadd = io.pfrio_nadd;
372        if (naddr != NULL)
373                *naddr = io.pfrio_naddr;
374        return (0);
375}
376
377/* interface management code */
378
379int
380pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
381{
382        struct pfioc_iface io;
383
384        if (size == NULL || *size < 0 || (*size && buf == NULL)) {
385                errno = EINVAL;
386                return (-1);
387        }
388        bzero(&io, sizeof io);
389        if (filter != NULL)
390                if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
391                    sizeof(io.pfiio_name)) {
392                        errno = EINVAL;
393                        return (-1);
394                }
395        io.pfiio_buffer = buf;
396        io.pfiio_esize = sizeof(*buf);
397        io.pfiio_size = *size;
398        if (ioctl(dev, DIOCIGETIFACES, &io))
399                return (-1);
400        *size = io.pfiio_size;
401        return (0);
402}
403
404/* buffer management code */
405
406size_t buf_esize[PFRB_MAX] = { 0,
407        sizeof(struct pfr_table), sizeof(struct pfr_tstats),
408        sizeof(struct pfr_addr), sizeof(struct pfr_astats),
409        sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
410};
411
412/*
413 * add one element to the buffer
414 */
415int
416pfr_buf_add(struct pfr_buffer *b, const void *e)
417{
418        size_t bs;
419
420        if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
421            e == NULL) {
422                errno = EINVAL;
423                return (-1);
424        }
425        bs = buf_esize[b->pfrb_type];
426        if (b->pfrb_size == b->pfrb_msize)
427                if (pfr_buf_grow(b, 0))
428                        return (-1);
429        memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
430        b->pfrb_size++;
431        return (0);
432}
433
434/*
435 * return next element of the buffer (or first one if prev is NULL)
436 * see PFRB_FOREACH macro
437 */
438void *
439pfr_buf_next(struct pfr_buffer *b, const void *prev)
440{
441        size_t bs;
442
443        if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
444                return (NULL);
445        if (b->pfrb_size == 0)
446                return (NULL);
447        if (prev == NULL)
448                return (b->pfrb_caddr);
449        bs = buf_esize[b->pfrb_type];
450        if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
451                return (NULL);
452        return (((caddr_t)prev) + bs);
453}
454
455/*
456 * minsize:
457 *    0: make the buffer somewhat bigger
458 *    n: make room for "n" entries in the buffer
459 */
460int
461pfr_buf_grow(struct pfr_buffer *b, int minsize)
462{
463        caddr_t p;
464        size_t bs;
465
466        if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
467                errno = EINVAL;
468                return (-1);
469        }
470        if (minsize != 0 && minsize <= b->pfrb_msize)
471                return (0);
472        bs = buf_esize[b->pfrb_type];
473        if (!b->pfrb_msize) {
474                if (minsize < 64)
475                        minsize = 64;
476                b->pfrb_caddr = calloc(bs, minsize);
477                if (b->pfrb_caddr == NULL)
478                        return (-1);
479                b->pfrb_msize = minsize;
480        } else {
481                if (minsize == 0)
482                        minsize = b->pfrb_msize * 2;
483                if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
484                        /* msize overflow */
485                        errno = ENOMEM;
486                        return (-1);
487                }
488                p = realloc(b->pfrb_caddr, minsize * bs);
489                if (p == NULL)
490                        return (-1);
491                bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
492                b->pfrb_caddr = p;
493                b->pfrb_msize = minsize;
494        }
495        return (0);
496}
497
498/*
499 * reset buffer and free memory.
500 */
501void
502pfr_buf_clear(struct pfr_buffer *b)
503{
504        if (b == NULL)
505                return;
506        if (b->pfrb_caddr != NULL)
507                free(b->pfrb_caddr);
508        b->pfrb_caddr = NULL;
509        b->pfrb_size = b->pfrb_msize = 0;
510}
511
512int
513pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
514    int (*append_addr)(struct pfr_buffer *, char *, int))
515{
516        FILE    *fp;
517        char     buf[BUF_SIZE];
518        int      rv;
519
520        if (file == NULL)
521                return (0);
522        if (!strcmp(file, "-"))
523                fp = stdin;
524        else {
525                fp = pfctl_fopen(file, "r");
526                if (fp == NULL)
527                        return (-1);
528        }
529        while ((rv = pfr_next_token(buf, fp)) == 1)
530                if (append_addr(b, buf, nonetwork)) {
531                        rv = -1;
532                        break;
533                }
534        if (fp != stdin)
535                fclose(fp);
536        return (rv);
537}
538
539int
540pfr_next_token(char buf[BUF_SIZE], FILE *fp)
541{
542        static char     next_ch = ' ';
543        int             i = 0;
544
545        for (;;) {
546                /* skip spaces */
547                while (isspace(next_ch) && !feof(fp))
548                        next_ch = fgetc(fp);
549                /* remove from '#' until end of line */
550                if (next_ch == '#')
551                        while (!feof(fp)) {
552                                next_ch = fgetc(fp);
553                                if (next_ch == '\n')
554                                        break;
555                        }
556                else
557                        break;
558        }
559        if (feof(fp)) {
560                next_ch = ' ';
561                return (0);
562        }
563        do {
564                if (i < BUF_SIZE)
565                        buf[i++] = next_ch;
566                next_ch = fgetc(fp);
567        } while (!feof(fp) && !isspace(next_ch));
568        if (i >= BUF_SIZE) {
569                errno = EINVAL;
570                return (-1);
571        }
572        buf[i] = '\0';
573        return (1);
574}
575
576char *
577pfr_strerror(int errnum)
578{
579        switch (errnum) {
580        case ESRCH:
581                return "Table does not exist";
582        case ENOENT:
583                return "Anchor or Ruleset does not exist";
584        default:
585                return strerror(errnum);
586        }
587}
Note: See TracBrowser for help on using the repository browser.