Page MenuHomeFreeBSD

D52130.diff
No OneTemporary

D52130.diff

diff --git a/lib/libifconfig/Makefile b/lib/libifconfig/Makefile
--- a/lib/libifconfig/Makefile
+++ b/lib/libifconfig/Makefile
@@ -18,6 +18,7 @@
libifconfig_internal.c \
libifconfig_lagg.c \
libifconfig_media.c \
+ libifconfig_nl.c \
libifconfig_sfp.c
GEN= libifconfig_sfp_tables.h \
diff --git a/lib/libifconfig/libifconfig.h b/lib/libifconfig/libifconfig.h
--- a/lib/libifconfig/libifconfig.h
+++ b/lib/libifconfig/libifconfig.h
@@ -382,3 +382,23 @@
* length of *lenp * IFNAMSIZ bytes.
*/
int ifconfig_list_cloners(ifconfig_handle_t *h, char **bufp, size_t *lenp);
+
+/** Get MAC address of an interface
+ * @param h An open ifconfig state object
+ * @param ifname The interface name
+ * @param addr Return argument. It will be filled with the MAC address
+ * @return 0 on success, nonzero on failure.
+ * On failure, the error info on the handle is set.
+ */
+int ifconfig_get_mac(ifconfig_handle_t *h, const char *ifname,
+ struct ether_addr *addr);
+
+/** Set MAC address on an interface
+ * @param h An open ifconfig state object
+ * @param ifname The interface name
+ * @param addr The MAC address
+ * @return 0 on success, nonzero on failure.
+ * On failure, the error info on the handle is set.
+ */
+int ifconfig_set_mac(ifconfig_handle_t *h, const char *ifname,
+ const struct ether_addr *addr);
diff --git a/lib/libifconfig/libifconfig_nl.c b/lib/libifconfig/libifconfig_nl.c
new file mode 100644
--- /dev/null
+++ b/lib/libifconfig/libifconfig_nl.c
@@ -0,0 +1,186 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025, Muhammad Saheed <saheed@FreeBSD.org>
+ */
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netlink/netlink.h>
+#include <netlink/netlink_snl.h>
+#include <netlink/netlink_snl_route_parsers.h>
+#include <netlink/route/common.h>
+#include <netlink/route/interface.h>
+
+#include <errno.h>
+
+#include "libifconfig.h"
+#include "libifconfig_internal.h"
+
+static int ifconfig_get_link(ifconfig_handle_t *h, struct snl_state *ss,
+ const char *ifname, struct snl_parsed_link_simple *link);
+
+int
+ifconfig_get_mac(ifconfig_handle_t *h, const char *ifname,
+ struct ether_addr *addr)
+{
+ int ret = 0;
+ uint32_t nlmsg_seq = 0;
+ struct snl_state ss;
+ struct snl_writer nw = { 0 };
+ struct nlmsghdr *hdr;
+ struct snl_parsed_link link = { 0 };
+ struct snl_errmsg_data e = { 0 };
+
+ assert(addr != NULL);
+
+ if (!snl_init(&ss, NETLINK_ROUTE)) {
+ ifconfig_error(h, NETLINK, ENOTSUP);
+ return (-1);
+ }
+
+ snl_init_writer(&ss, &nw);
+ hdr = snl_create_msg_request(&nw, RTM_GETLINK);
+ (void)snl_reserve_msg_object(&nw, struct ifinfomsg);
+
+ snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname);
+
+ if ((hdr = snl_finalize_msg(&nw)) == NULL) {
+ ifconfig_error(h, NETLINK, ENOMEM);
+ ret = -1;
+ goto out;
+ }
+
+ if (!snl_send_message(&ss, hdr)) {
+ ifconfig_error(h, NETLINK, EIO);
+ ret = -1;
+ goto out;
+ }
+
+ nlmsg_seq = hdr->nlmsg_seq;
+ while ((hdr = snl_read_reply_multi(&ss, nlmsg_seq, &e)) != NULL) {
+ if (!snl_parse_nlmsg(&ss, hdr, &snl_rtm_link_parser, &link))
+ continue;
+
+ if (link.ifla_address != NULL &&
+ NLA_DATA_LEN(link.ifla_address) == ETHER_ADDR_LEN) {
+ memcpy(addr, NLA_DATA(link.ifla_address),
+ ETHER_ADDR_LEN);
+ goto out;
+ }
+ }
+ ifconfig_error(h, NETLINK, ENOENT);
+ ret = -1;
+
+out:
+ snl_free(&ss);
+ return (ret);
+}
+
+static int
+ifconfig_get_link(ifconfig_handle_t *h, struct snl_state *ss,
+ const char *ifname, struct snl_parsed_link_simple *link)
+{
+ struct snl_writer nw = { 0 };
+ struct nlmsghdr *hdr;
+ struct snl_errmsg_data e = { 0 };
+
+ snl_init_writer(ss, &nw);
+ hdr = snl_create_msg_request(&nw, RTM_GETLINK);
+ (void)snl_reserve_msg_object(&nw, struct ifinfomsg);
+ snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname);
+
+ if ((hdr = snl_finalize_msg(&nw)) == NULL) {
+ ifconfig_error(h, NETLINK, ENOMEM);
+ return (-1);
+ }
+
+ if (!snl_send_message(ss, hdr)) {
+ ifconfig_error(h, NETLINK, EIO);
+ return (-1);
+ }
+
+ hdr = snl_read_reply(ss, hdr->nlmsg_seq);
+ if (hdr->nlmsg_type == NLMSG_ERROR) {
+ int error = snl_parse_errmsg(ss, hdr, &e) ? e.error : EINVAL;
+
+ ifconfig_error(h, NETLINK, error);
+ return (-1);
+ }
+
+ if (hdr->nlmsg_type != RTM_NEWLINK) {
+ ifconfig_error(h, NETLINK, EINVAL);
+ return (1);
+ }
+
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser_simple, link)) {
+ ifconfig_error(h, NETLINK, EINVAL);
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+ifconfig_set_mac(ifconfig_handle_t *h, const char *ifname,
+ const struct ether_addr *addr)
+{
+ int ret = 0;
+ struct snl_state ss;
+ struct snl_writer nw = { 0 };
+ struct nlmsghdr *hdr;
+ struct ifinfomsg *ifi;
+ struct snl_errmsg_data e = { 0 };
+ struct snl_parsed_link_simple link = { 0 };
+
+ assert(addr != NULL);
+
+ if (!snl_init(&ss, NETLINK_ROUTE)) {
+ ifconfig_error(h, NETLINK, ENOTSUP);
+ return (-1);
+ }
+
+ snl_init_writer(&ss, &nw);
+ hdr = snl_create_msg_request(&nw, RTM_NEWLINK);
+ ifi = snl_reserve_msg_object(&nw, struct ifinfomsg);
+
+ if (ifconfig_get_link(h, &ss, ifname, &link) != 0) {
+ ret = -1;
+ goto out;
+ }
+
+ ifi->ifi_family = AF_UNSPEC;
+ ifi->ifi_type = link.ifi_type;
+ ifi->ifi_index = link.ifi_index;
+
+ /*
+ * Preserve interface flags
+ */
+ ifi->ifi_flags = link.ifi_flags;
+ ifi->ifi_change = 0xFFFFFFFF;
+
+ snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname);
+ snl_add_msg_attr(&nw, IFLA_ADDRESS, ETHER_ADDR_LEN, addr);
+
+ if ((hdr = snl_finalize_msg(&nw)) == NULL) {
+ ifconfig_error(h, NETLINK, ENOMEM);
+ ret = -1;
+ goto out;
+ }
+
+ if (!snl_send_message(&ss, hdr)) {
+ ifconfig_error(h, NETLINK, EIO);
+ ret = -1;
+ goto out;
+ }
+
+ if (!snl_read_reply_code(&ss, hdr->nlmsg_seq, &e)) {
+ ifconfig_error(h, NETLINK, e.error);
+ ret = -1;
+ goto out;
+ }
+
+out:
+ snl_free(&ss);
+ return (ret);
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 5, 9:50 AM (20 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29259408
Default Alt Text
D52130.diff (5 KB)

Event Timeline