-/* $OpenBSD: pf_if.c,v 1.100 2020/06/24 22:03:42 cheloha Exp $ */
+/* $OpenBSD: pf_if.c,v 1.101 2021/11/11 12:35:01 sashan Exp $ */
/*
* Copyright 2005 Henning Brauer <henning@openbsd.org>
#define PFI_BUFFER_MAX 0x10000
#define PFI_MTYPE M_IFADDR
+struct pfi_kif *
+pfi_kif_alloc(const char *kif_name, int mflags)
+{
+ struct pfi_kif *kif;
+
+ kif = malloc(sizeof(*pfi_all), PFI_MTYPE, mflags|M_ZERO);
+ strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name));
+ kif->pfik_tzero = gettime();
+ TAILQ_INIT(&kif->pfik_dynaddrs);
+
+ if (!strcmp(kif->pfik_name, "any")) {
+ /* both so it works in the ioctl and the regular case */
+ kif->pfik_flags |= PFI_IFLAG_ANY;
+ kif->pfik_flags_new |= PFI_IFLAG_ANY;
+ }
+
+ return (kif);
+}
+
+void
+pfi_kif_free(struct pfi_kif *kif)
+{
+ if (kif == NULL)
+ return;
+
+ if ((kif->pfik_rules != 0) || (kif->pfik_states != 0) ||
+ (kif->pfik_states != 0) || (kif->pfik_states != 0) ||
+ (kif->pfik_srcnodes != 0))
+ panic("kif is still alive");
+
+ free(kif, PFI_MTYPE, sizeof(*kif));
+}
+
void
pfi_initialize(void)
{
+ /*
+ * The first time we arrive here is during kernel boot,
+ * when if_attachsetup() for the first time. No locking
+ * is needed in this case, because it's granted there
+ * is a single thread, which sets pfi_all global var.
+ */
if (pfi_all != NULL) /* already initialized */
return;
pfi_buffer = mallocarray(pfi_buffer_max, sizeof(*pfi_buffer),
PFI_MTYPE, M_WAITOK);
- if ((pfi_all = pfi_kif_get(IFG_ALL)) == NULL)
- panic("pfi_kif_get for pfi_all failed");
+ pfi_all = pfi_kif_alloc(IFG_ALL, M_WAITOK);
+
+ if (RB_INSERT(pfi_ifhead, &pfi_ifs, pfi_all) != NULL)
+ panic("IFG_ALL kif found already");
}
struct pfi_kif *
}
struct pfi_kif *
-pfi_kif_get(const char *kif_name)
+pfi_kif_get(const char *kif_name, struct pfi_kif **prealloc)
{
struct pfi_kif *kif;
return (kif);
/* create new one */
- if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_NOWAIT|M_ZERO)) == NULL)
- return (NULL);
-
- strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name));
- kif->pfik_tzero = gettime();
- TAILQ_INIT(&kif->pfik_dynaddrs);
-
- if (!strcmp(kif->pfik_name, "any")) {
- /* both so it works in the ioctl and the regular case */
- kif->pfik_flags |= PFI_IFLAG_ANY;
- kif->pfik_flags_new |= PFI_IFLAG_ANY;
+ if ((prealloc == NULL) || (*prealloc == NULL)) {
+ kif = pfi_kif_alloc(kif_name, M_NOWAIT);
+ if (kif == NULL)
+ return (NULL);
+ } else {
+ kif = *prealloc;
+ *prealloc = NULL;
}
RB_INSERT(pfi_ifhead, &pfi_ifs, kif);
pfi_initialize();
pfi_update++;
- if ((kif = pfi_kif_get(ifp->if_xname)) == NULL)
+ if ((kif = pfi_kif_get(ifp->if_xname, NULL)) == NULL)
panic("%s: pfi_kif_get failed", __func__);
kif->pfik_ifp = ifp;
pfi_initialize();
pfi_update++;
- if ((kif = pfi_kif_get(ifg->ifg_group)) == NULL)
+ if ((kif = pfi_kif_get(ifg->ifg_group, NULL)) == NULL)
panic("%s: pfi_kif_get failed", __func__);
kif->pfik_group = ifg;
struct pfi_kif *kif;
pfi_update++;
- if ((kif = pfi_kif_get(group)) == NULL)
+ if ((kif = pfi_kif_get(group, NULL)) == NULL)
panic("%s: pfi_kif_get failed", __func__);
pfi_kif_update(kif);
{
struct pfi_kif *gkif, *ikif;
- if ((gkif = pfi_kif_get(group)) == NULL ||
- (ikif = pfi_kif_get(ifp->if_xname)) == NULL)
+ if ((gkif = pfi_kif_get(group, NULL)) == NULL ||
+ (ikif = pfi_kif_get(ifp->if_xname, NULL)) == NULL)
panic("%s: pfi_kif_get failed", __func__);
ikif->pfik_flags |= gkif->pfik_flags;
return (1);
if (!strcmp(aw->v.ifname, "self"))
- dyn->pfid_kif = pfi_kif_get(IFG_ALL);
+ dyn->pfid_kif = pfi_kif_get(IFG_ALL, NULL);
else
- dyn->pfid_kif = pfi_kif_get(aw->v.ifname);
+ dyn->pfid_kif = pfi_kif_get(aw->v.ifname, NULL);
if (dyn->pfid_kif == NULL) {
rv = 1;
goto _bad;
-/* $OpenBSD: pfvar.h,v 1.502 2021/06/23 06:53:52 dlg Exp $ */
+/* $OpenBSD: pfvar.h,v 1.503 2021/11/11 12:35:01 sashan Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
extern struct pfi_kif *pfi_all;
void pfi_initialize(void);
+struct pfi_kif *pfi_kif_alloc(const char *, int);
+void pfi_kif_free(struct pfi_kif *);
struct pfi_kif *pfi_kif_find(const char *);
-struct pfi_kif *pfi_kif_get(const char *);
+struct pfi_kif *pfi_kif_get(const char *, struct pfi_kif **);
void pfi_kif_ref(struct pfi_kif *, enum pfi_kif_refs);
void pfi_kif_unref(struct pfi_kif *, enum pfi_kif_refs);
int pfi_kif_match(struct pfi_kif *, struct pfi_kif *);