-/* $OpenBSD: if.c,v 1.693 2023/04/26 00:14:21 jan Exp $ */
+/* $OpenBSD: if.c,v 1.694 2023/04/26 19:54:35 mvs Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
char ifrtlabelbuf[RTLABEL_LEN];
int error = 0;
size_t bytesdone;
- const char *label;
switch(cmd) {
case SIOCGIFCONF:
break;
case SIOCGIFRTLABEL:
- if (ifp->if_rtlabelid &&
- (label = rtlabel_id2name(ifp->if_rtlabelid)) != NULL) {
- strlcpy(ifrtlabelbuf, label, RTLABEL_LEN);
+ if (ifp->if_rtlabelid && rtlabel_id2name(ifp->if_rtlabelid,
+ ifrtlabelbuf, RTLABEL_LEN) != NULL) {
error = copyoutstr(ifrtlabelbuf, ifr->ifr_data,
RTLABEL_LEN, &bytesdone);
} else
-/* $OpenBSD: pf_ioctl.c,v 1.397 2023/01/06 17:44:34 sashan Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.398 2023/04/26 19:54:35 mvs Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
void
pf_rtlabel_copyout(struct pf_addr_wrap *a)
{
- const char *name;
-
if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel) {
- if ((name = rtlabel_id2name(a->v.rtlabel)) == NULL)
+ if (rtlabel_id2name(a->v.rtlabel, a->v.rtlabelname,
+ sizeof(a->v.rtlabelname)) == NULL)
strlcpy(a->v.rtlabelname, "?",
sizeof(a->v.rtlabelname));
- else
- strlcpy(a->v.rtlabelname, name,
- sizeof(a->v.rtlabelname));
}
}
-/* $OpenBSD: route.c,v 1.418 2023/04/26 16:09:44 kn Exp $ */
+/* $OpenBSD: route.c,v 1.419 2023/04/26 19:54:35 mvs Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
#include <sys/queue.h>
#include <sys/pool.h>
#include <sys/atomic.h>
+#include <sys/mutex.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/bfd.h>
#endif
+/*
+ * Locks used to protect struct members:
+ * I immutable after creation
+ * L rtlabel_mtx
+ */
+
#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
/* Give some jitter to hash, to avoid synchronization between routers. */
#define LABELID_MAX 50000
struct rt_label {
- TAILQ_ENTRY(rt_label) rtl_entry;
- char rtl_name[RTLABEL_LEN];
- u_int16_t rtl_id;
- int rtl_ref;
+ TAILQ_ENTRY(rt_label) rtl_entry; /* [L] */
+ char rtl_name[RTLABEL_LEN]; /* [I] */
+ u_int16_t rtl_id; /* [I] */
+ int rtl_ref; /* [L] */
};
-TAILQ_HEAD(rt_labels, rt_label) rt_labels = TAILQ_HEAD_INITIALIZER(rt_labels);
+TAILQ_HEAD(rt_labels, rt_label) rt_labels =
+ TAILQ_HEAD_INITIALIZER(rt_labels); /* [L] */
+struct mutex rtlabel_mtx = MUTEX_INITIALIZER(IPL_NET);
void
route_init(void)
rtlabel_name2id(char *name)
{
struct rt_label *label, *p;
- u_int16_t new_id = 1;
+ u_int16_t new_id = 1, id = 0;
if (!name[0])
return (0);
+ mtx_enter(&rtlabel_mtx);
TAILQ_FOREACH(label, &rt_labels, rtl_entry)
if (strcmp(name, label->rtl_name) == 0) {
label->rtl_ref++;
- return (label->rtl_id);
+ id = label->rtl_id;
+ goto out;
}
/*
new_id = p->rtl_id + 1;
}
if (new_id > LABELID_MAX)
- return (0);
+ goto out;
label = malloc(sizeof(*label), M_RTABLE, M_NOWAIT|M_ZERO);
if (label == NULL)
- return (0);
+ goto out;
strlcpy(label->rtl_name, name, sizeof(label->rtl_name));
label->rtl_id = new_id;
label->rtl_ref++;
else /* either list empty or no free slot in between */
TAILQ_INSERT_TAIL(&rt_labels, label, rtl_entry);
- return (label->rtl_id);
+ id = label->rtl_id;
+out:
+ mtx_leave(&rtlabel_mtx);
+
+ return (id);
}
const char *
-rtlabel_id2name(u_int16_t id)
+rtlabel_id2name_locked(u_int16_t id)
{
struct rt_label *label;
+ MUTEX_ASSERT_LOCKED(&rtlabel_mtx);
+
TAILQ_FOREACH(label, &rt_labels, rtl_entry)
if (label->rtl_id == id)
return (label->rtl_name);
return (NULL);
}
+const char *
+rtlabel_id2name(u_int16_t id, char *rtlabelbuf, size_t sz)
+{
+ const char *label;
+
+ if (id == 0)
+ return (NULL);
+
+ mtx_enter(&rtlabel_mtx);
+ if ((label = rtlabel_id2name_locked(id)) != NULL)
+ strlcpy(rtlabelbuf, label, sz);
+ mtx_leave(&rtlabel_mtx);
+
+ if (label == NULL)
+ return (NULL);
+
+ return (rtlabelbuf);
+}
+
struct sockaddr *
rtlabel_id2sa(u_int16_t labelid, struct sockaddr_rtlabel *sa_rl)
{
const char *label;
- if (labelid == 0 || (label = rtlabel_id2name(labelid)) == NULL)
+ if (labelid == 0)
return (NULL);
- bzero(sa_rl, sizeof(*sa_rl));
- sa_rl->sr_len = sizeof(*sa_rl);
- sa_rl->sr_family = AF_UNSPEC;
- strlcpy(sa_rl->sr_label, label, sizeof(sa_rl->sr_label));
+ mtx_enter(&rtlabel_mtx);
+ if ((label = rtlabel_id2name_locked(labelid)) != NULL) {
+ bzero(sa_rl, sizeof(*sa_rl));
+ sa_rl->sr_len = sizeof(*sa_rl);
+ sa_rl->sr_family = AF_UNSPEC;
+ strlcpy(sa_rl->sr_label, label, sizeof(sa_rl->sr_label));
+ }
+ mtx_leave(&rtlabel_mtx);
+
+ if (label == NULL)
+ return (NULL);
return ((struct sockaddr *)sa_rl);
}
if (id == 0)
return;
+ mtx_enter(&rtlabel_mtx);
TAILQ_FOREACH_SAFE(p, &rt_labels, rtl_entry, next) {
if (id == p->rtl_id) {
if (--p->rtl_ref == 0) {
break;
}
}
+ mtx_leave(&rtlabel_mtx);
}
int