diff options
Diffstat (limited to 'sys/netlink')
-rw-r--r-- | sys/netlink/netlink_io.c | 13 | ||||
-rw-r--r-- | sys/netlink/netlink_linux.h | 2 | ||||
-rw-r--r-- | sys/netlink/netlink_message_writer.h | 6 | ||||
-rw-r--r-- | sys/netlink/netlink_snl.h | 11 | ||||
-rw-r--r-- | sys/netlink/route/iface.c | 1 | ||||
-rw-r--r-- | sys/netlink/route/iface_drivers.c | 37 | ||||
-rw-r--r-- | sys/netlink/route/route_var.h | 1 |
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; |