]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/pfctl/pfctl_radix.c
Remove spurious newline
[FreeBSD/FreeBSD.git] / sbin / pfctl / pfctl_radix.c
1 /*      $OpenBSD: pfctl_radix.c,v 1.27 2005/05/21 21:03:58 henning Exp $ */
2
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause
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
57 extern int dev;
58
59 static int       pfr_next_token(char buf[], FILE *);
60
61
62 int
63 pfr_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
78 int
79 pfr_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
99 int
100 pfr_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
120 int
121 pfr_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
143 int
144 pfr_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
166 int
167 pfr_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
185 int
186 pfr_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
208 int
209 pfr_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
231 int
232 pfr_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
261 int
262 pfr_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
284 int
285 pfr_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
307 int
308 pfr_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
328 int
329 pfr_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
351 int
352 pfr_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
379 int
380 pfi_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
406 const size_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  */
415 int
416 pfr_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  */
438 void *
439 pfr_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  */
460 int
461 pfr_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  */
501 void
502 pfr_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
512 int
513 pfr_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
539 int
540 pfr_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
576 char *
577 pfr_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 }