aboutsummaryrefslogtreecommitdiff
path: root/sys/netlink
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netlink')
-rw-r--r--sys/netlink/netlink_io.c13
-rw-r--r--sys/netlink/netlink_linux.h2
-rw-r--r--sys/netlink/netlink_message_writer.h6
-rw-r--r--sys/netlink/netlink_snl.h11
-rw-r--r--sys/netlink/route/iface.c1
-rw-r--r--sys/netlink/route/iface_drivers.c37
-rw-r--r--sys/netlink/route/route_var.h1
7 files changed, 58 insertions, 13 deletions
diff --git a/sys/netlink/netlink_io.c b/sys/netlink/netlink_io.c
index e7908d6f3a44..2391d8ea752c 100644
--- a/sys/netlink/netlink_io.c
+++ b/sys/netlink/netlink_io.c
@@ -216,16 +216,17 @@ nl_send(struct nl_writer *nw, struct nlpcb *nlp)
hdr->nlmsg_len);
}
- if (nlp->nl_linux && linux_netlink_p != NULL &&
- __predict_false(!linux_netlink_p->msgs_to_linux(nw, nlp))) {
+ if (nlp->nl_linux && linux_netlink_p != NULL) {
+ nb = linux_netlink_p->msgs_to_linux(nw->buf, nlp);
nl_buf_free(nw->buf);
nw->buf = NULL;
- return (false);
+ if (nb == NULL)
+ return (false);
+ } else {
+ nb = nw->buf;
+ nw->buf = NULL;
}
- nb = nw->buf;
- nw->buf = NULL;
-
SOCK_RECVBUF_LOCK(so);
if (!nw->ignore_limit && __predict_false(sb->sb_hiwat <= sb->sb_ccc)) {
SOCK_RECVBUF_UNLOCK(so);
diff --git a/sys/netlink/netlink_linux.h b/sys/netlink/netlink_linux.h
index d4c451d470b2..794065692901 100644
--- a/sys/netlink/netlink_linux.h
+++ b/sys/netlink/netlink_linux.h
@@ -37,7 +37,7 @@ struct nlpcb;
struct nl_pstate;
struct nl_writer;
-typedef bool msgs_to_linux_cb_t(struct nl_writer *nw, struct nlpcb *nlp);
+typedef struct nl_buf * msgs_to_linux_cb_t(struct nl_buf *, struct nlpcb *);
typedef int msg_from_linux_cb_t(int netlink_family, struct nlmsghdr **hdr,
struct nl_pstate *npt);
diff --git a/sys/netlink/netlink_message_writer.h b/sys/netlink/netlink_message_writer.h
index 83f925e8d93d..ad2099a4d636 100644
--- a/sys/netlink/netlink_message_writer.h
+++ b/sys/netlink/netlink_message_writer.h
@@ -284,6 +284,12 @@ nlattr_add_s64(struct nl_writer *nw, uint16_t attrtype, int64_t value)
}
static inline bool
+nlattr_add_time_t(struct nl_writer *nw, uint16_t attrtype, time_t value)
+{
+ return (nlattr_add(nw, attrtype, sizeof(time_t), &value));
+}
+
+static inline bool
nlattr_add_flag(struct nl_writer *nw, uint16_t attrtype)
{
return (nlattr_add(nw, attrtype, 0, NULL));
diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h
index 586716776bc5..6dd8a9cbdb35 100644
--- a/sys/netlink/netlink_snl.h
+++ b/sys/netlink/netlink_snl.h
@@ -631,6 +631,17 @@ snl_attr_get_int64(struct snl_state *ss, struct nlattr *nla, const void *arg,
}
static inline bool
+snl_attr_get_time_t(struct snl_state *ss __unused, struct nlattr *nla,
+ const void *arg __unused, void *target)
+{
+ if (NLA_DATA_LEN(nla) == sizeof(time_t)) {
+ memcpy(target, NLA_DATA_CONST(nla), sizeof(time_t));
+ return (true);
+ }
+ return (false);
+}
+
+static inline bool
snl_attr_get_string(struct snl_state *ss __unused, struct nlattr *nla,
const void *arg __unused, void *target)
{
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
index 8b871576d0b2..9beb80792af4 100644
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -403,6 +403,7 @@ static const struct nlattr_parser nla_p_linfo[] = {
NL_DECLARE_ATTR_PARSER(linfo_parser, nla_p_linfo);
static const struct nlattr_parser nla_p_if[] = {
+ { .type = IFLA_ADDRESS, .off = _OUT(ifla_address), .cb = nlattr_get_nla },
{ .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = nlattr_get_string },
{ .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = nlattr_get_uint32 },
{ .type = IFLA_LINK, .off = _OUT(ifla_link), .cb = nlattr_get_uint32 },
diff --git a/sys/netlink/route/iface_drivers.c b/sys/netlink/route/iface_drivers.c
index 5f605b05f7b8..4f1540740ead 100644
--- a/sys/netlink/route/iface_drivers.c
+++ b/sys/netlink/route/iface_drivers.c
@@ -93,7 +93,12 @@ _nl_modify_ifp_generic(struct ifnet *ifp, struct nl_parsed_link *lattrs,
if (lattrs->ifla_mtu > 0) {
if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFMTU)) {
struct ifreq ifr = { .ifr_mtu = lattrs->ifla_mtu };
- error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr, curthread);
+ error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr,
+ curthread);
+ if (error != 0) {
+ nlmsg_report_err_msg(npt, "Failed to set mtu");
+ return (error);
+ }
} else {
nlmsg_report_err_msg(npt, "Not enough privileges to set mtu");
return (EPERM);
@@ -101,11 +106,31 @@ _nl_modify_ifp_generic(struct ifnet *ifp, struct nl_parsed_link *lattrs,
}
if ((lattrs->ifi_change & IFF_PROMISC) != 0 ||
- lattrs->ifi_change == 0) {
- error = ifpromisc(ifp, lattrs->ifi_flags & IFF_PROMISC);
- if (error != 0) {
- nlmsg_report_err_msg(npt, "unable to set promisc");
- return (error);
+ lattrs->ifi_change == 0)
+ /*
+ * When asking for IFF_PROMISC, set permanent flag instead
+ * (IFF_PPROMISC) as we have no way of doing promiscuity
+ * reference counting through ifpromisc(). Every call to this
+ * function either sets or unsets IFF_PROMISC, and ifi_change
+ * is usually set to 0xFFFFFFFF.
+ */
+ if_setppromisc(ifp, (lattrs->ifi_flags & IFF_PROMISC) != 0);
+
+ if (lattrs->ifla_address != NULL) {
+ if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFMAC)) {
+ error = if_setlladdr(ifp,
+ NLA_DATA(lattrs->ifla_address),
+ NLA_DATA_LEN(lattrs->ifla_address));
+ if (error != 0) {
+ nlmsg_report_err_msg(npt,
+ "setting IFLA_ADDRESS failed with error code: %d",
+ error);
+ return (error);
+ }
+ } else {
+ nlmsg_report_err_msg(npt,
+ "Not enough privileges to set IFLA_ADDRESS");
+ return (EPERM);
}
}
diff --git a/sys/netlink/route/route_var.h b/sys/netlink/route/route_var.h
index b84b34461e35..41f110038b54 100644
--- a/sys/netlink/route/route_var.h
+++ b/sys/netlink/route/route_var.h
@@ -69,6 +69,7 @@ struct nl_parsed_link {
char *ifla_cloner;
char *ifla_ifalias;
struct nlattr *ifla_idata;
+ struct nlattr *ifla_address;
unsigned short ifi_type;
int ifi_index;
uint32_t ifla_link;