Hello,

this is the first patch in series of three. All patches modify PF radix
table API such the ioctl() functions accept one IP address per call.
The idea has been proposed by Claudio at Varazdin.

I still have to untangle pfr_commit_ktable() and DIOCRSETADDRS ioctl.  Both
seem to be more complicated than DIOCRADDADDRS and DIOCRDELADDRS (subject of
next patch).

Patch changes DIOCRADDADDRS ioctl to DIOCRADDADDRS, which accepts one IP
address only per ioctl(2) call. Patch updates kernel and pfctl(8) only. Other
components, which happen to use DIOCRADDADDRS will be updated by extra patch.

thanks and
regards
sasha

P.S. I still need to update pf(4) manpage, I'll do it as soon as there we
will reach agreement on proposed patches.

--------8<---------------8<---------------8<------------------8<--------

Index: sbin/pfctl/pfctl_radix.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_radix.c,v
retrieving revision 1.32
diff -u -p -r1.32 pfctl_radix.c
--- sbin/pfctl/pfctl_radix.c    21 Jan 2015 21:50:33 -0000      1.32
+++ sbin/pfctl/pfctl_radix.c    27 Oct 2015 23:24:59 -0000
@@ -184,6 +184,7 @@ pfr_add_addrs(struct pfr_table *tbl, str
     int *nadd, int flags)
 {
        struct pfioc_table io;
+       int     i, rv, add = 0;
 
        if (tbl == NULL || size < 0 || (size && addr == NULL)) {
                errno = EINVAL;
@@ -192,14 +193,18 @@ pfr_add_addrs(struct pfr_table *tbl, str
        bzero(&io, sizeof io);
        io.pfrio_flags = flags;
        io.pfrio_table = *tbl;
-       io.pfrio_buffer = addr;
        io.pfrio_esize = sizeof(*addr);
-       io.pfrio_size = size;
-       if (ioctl(dev, DIOCRADDADDRS, &io))
-               return (-1);
-       if (nadd != NULL)
-               *nadd = io.pfrio_nadd;
-       return (0);
+       io.pfrio_size = 1;      /* TODO: check .pfrio_size is needed */
+       for (i = 0; (i < size) && (rv == 0); i++) {
+               io.pfrio_buffer = addr++;
+               rv = ioctl(dev, DIOCRADDADDR, &io);
+               add++;
+       }
+
+       if ((rv == 0) && (nadd != NULL))
+               *nadd = add;
+
+       return (rv);
 }
 
 int
Index: sys/net/pf_ioctl.c
===================================================================
RCS file: /cvs/src/sys/net/pf_ioctl.c,v
retrieving revision 1.291
diff -u -p -r1.291 pf_ioctl.c
--- sys/net/pf_ioctl.c  13 Oct 2015 19:32:31 -0000      1.291
+++ sys/net/pf_ioctl.c  27 Oct 2015 23:25:23 -0000
@@ -834,7 +834,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
                case DIOCRGETTSTATS:
                case DIOCRCLRTSTATS:
                case DIOCRCLRADDRS:
-               case DIOCRADDADDRS:
+               case DIOCRADDADDR:
                case DIOCRDELADDRS:
                case DIOCRSETADDRS:
                case DIOCRGETASTATS:
@@ -887,7 +887,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
                case DIOCRDELTABLES:
                case DIOCRCLRTSTATS:
                case DIOCRCLRADDRS:
-               case DIOCRADDADDRS:
+               case DIOCRADDADDR:
                case DIOCRDELADDRS:
                case DIOCRSETADDRS:
                case DIOCRSETTFLAGS:
@@ -1816,16 +1816,15 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
                break;
        }
 
-       case DIOCRADDADDRS: {
+       case DIOCRADDADDR: {
                struct pfioc_table *io = (struct pfioc_table *)addr;
 
                if (io->pfrio_esize != sizeof(struct pfr_addr)) {
                        error = ENODEV;
                        break;
                }
-               error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
-                   io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
-                   PFR_FLAG_USERIOCTL);
+               error = pfr_add_addr(&io->pfrio_table, io->pfrio_buffer,
+                   io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                break;
        }
 
Index: sys/net/pf_table.c
===================================================================
RCS file: /cvs/src/sys/net/pf_table.c,v
retrieving revision 1.115
diff -u -p -r1.115 pf_table.c
--- sys/net/pf_table.c  7 Oct 2015 11:57:44 -0000       1.115
+++ sys/net/pf_table.c  27 Oct 2015 23:25:26 -0000
@@ -266,6 +266,54 @@ pfr_clr_addrs(struct pfr_table *tbl, int
 }
 
 int
+pfr_add_addr(struct pfr_table *tbl, struct pfr_addr *addr, int size, int flags)
+{
+       struct pfr_ktable       *kt;
+       struct pfr_kentry       *p;
+       struct pfr_addr          ad;
+       int                      rv;
+       time_t                   tzero = time_second;
+
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK);
+       if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
+               return (EINVAL);
+       kt = pfr_lookup_table(tbl);
+       if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+               return (ESRCH);
+       if (kt->pfrkt_flags & PFR_TFLAG_CONST)
+               return (EPERM);
+       if (COPYIN(addr, &ad, sizeof(ad), flags))
+               senderr(EFAULT);
+       if (pfr_validate_addr(&ad))
+               senderr(EINVAL);
+       p = pfr_lookup_addr(kt, &ad, 1);
+       if (p == NULL) {
+               rv = pfr_insert_kentry(kt, &ad, tzero);
+       }
+
+       if (flags & PFR_FLAG_FEEDBACK) {
+               if (p != NULL) {
+                       if ((p->pfrke_flags & PFRKE_FLAG_NOT) != ad.pfra_not)
+                               ad.pfra_fback = PFR_FB_CONFLICT;
+                       else
+                               ad.pfra_fback = PFR_FB_DUPLICATE;
+               } else if (rv != 0) {
+                       ad.pfra_fback = PFR_FB_NONE;
+               } else {
+                       ad.pfra_fback = PFR_FB_ADDED;
+               }
+               if (COPYOUT(&ad, addr, sizeof(ad), flags))
+                       senderr(EFAULT);
+       }
+
+       return (0);
+_bad:
+       if (flags & PFR_FLAG_FEEDBACK)
+               pfr_reset_feedback(addr, size, flags);
+       return (rv);
+}
+
+int
 pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
     int *nadd, int flags)
 {
Index: sys/net/pfvar.h
===================================================================
RCS file: /cvs/src/sys/net/pfvar.h,v
retrieving revision 1.421
diff -u -p -r1.421 pfvar.h
--- sys/net/pfvar.h     13 Oct 2015 19:32:32 -0000      1.421
+++ sys/net/pfvar.h     27 Oct 2015 23:25:29 -0000
@@ -1613,7 +1613,7 @@ struct pfioc_iface {
 #define        DIOCRGETTSTATS  _IOWR('D', 64, struct pfioc_table)
 #define DIOCRCLRTSTATS  _IOWR('D', 65, struct pfioc_table)
 #define        DIOCRCLRADDRS   _IOWR('D', 66, struct pfioc_table)
-#define        DIOCRADDADDRS   _IOWR('D', 67, struct pfioc_table)
+#define        DIOCRADDADDR    _IOWR('D', 67, struct pfioc_table)
 #define        DIOCRDELADDRS   _IOWR('D', 68, struct pfioc_table)
 #define        DIOCRSETADDRS   _IOWR('D', 69, struct pfioc_table)
 #define        DIOCRGETADDRS   _IOWR('D', 70, struct pfioc_table)
@@ -1789,8 +1789,7 @@ int       pfr_clr_tstats(struct pfr_table *, i
 int    pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int);
 int    pfr_clr_addrs(struct pfr_table *, int *, int);
 int    pfr_insert_kentry(struct pfr_ktable *, struct pfr_addr *, time_t);
-int    pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
-           int);
+int    pfr_add_addr(struct pfr_table *, struct pfr_addr *, int, int);
 int    pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
            int);
 int    pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
Index: sbin/pfctl/pfctl_radix.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_radix.c,v
retrieving revision 1.32
diff -u -p -r1.32 pfctl_radix.c
--- sbin/pfctl/pfctl_radix.c    21 Jan 2015 21:50:33 -0000      1.32
+++ sbin/pfctl/pfctl_radix.c    27 Oct 2015 23:27:32 -0000
@@ -184,6 +184,7 @@ pfr_add_addrs(struct pfr_table *tbl, str
     int *nadd, int flags)
 {
        struct pfioc_table io;
+       int     i, rv, add = 0;
 
        if (tbl == NULL || size < 0 || (size && addr == NULL)) {
                errno = EINVAL;
@@ -192,14 +193,18 @@ pfr_add_addrs(struct pfr_table *tbl, str
        bzero(&io, sizeof io);
        io.pfrio_flags = flags;
        io.pfrio_table = *tbl;
-       io.pfrio_buffer = addr;
        io.pfrio_esize = sizeof(*addr);
-       io.pfrio_size = size;
-       if (ioctl(dev, DIOCRADDADDRS, &io))
-               return (-1);
-       if (nadd != NULL)
-               *nadd = io.pfrio_nadd;
-       return (0);
+       io.pfrio_size = 1;      /* TODO: check .pfrio_size is needed */
+       for (i = 0; (i < size) && (rv == 0); i++) {
+               io.pfrio_buffer = addr++;
+               rv = ioctl(dev, DIOCRADDADDR, &io);
+               add++;
+       }
+
+       if ((rv == 0) && (nadd != NULL))
+               *nadd = add;
+
+       return (rv);
 }
 
 int

Reply via email to