Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164913502
D57666.id183026.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D57666.id183026.diff
View Options
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -90,6 +90,12 @@
#include <net/if_bridgevar.h>
#include <net/if_gif.h>
+#include <netlink/netlink.h>
+#include <netlink/netlink_ctl.h>
+#include <netlink/netlink_var.h>
+#include <netlink/netlink_route.h>
+#include <netlink/route/route_var.h>
+
#include <security/mac/mac_framework.h>
static const char gifname[] = "gif";
@@ -97,6 +103,7 @@
MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
static struct sx gif_ioctl_sx;
SX_SYSINIT(gif_ioctl_sx, &gif_ioctl_sx, "gif_ioctl");
+#define GIF_LOCK_ASSERT() sx_assert(&gif_ioctl_sx, SA_XLOCKED);
void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
@@ -110,8 +117,18 @@
static int gif_ioctl(struct ifnet *, u_long, caddr_t);
static int gif_transmit(struct ifnet *, struct mbuf *);
static void gif_qflush(struct ifnet *);
-static int gif_clone_create(struct if_clone *, int, caddr_t);
-static void gif_clone_destroy(struct ifnet *);
+static int gif_clone_create(struct if_clone *, char *, size_t,
+ struct ifc_data *, struct ifnet **);
+static int gif_clone_destroy(struct if_clone *, struct ifnet *, uint32_t);
+static int gif_clone_create_nl(struct if_clone *, char *, size_t,
+ struct ifc_data_nl *);
+static int gif_clone_modify_nl(struct ifnet *, struct ifc_data_nl *);
+static void gif_clone_dump_nl(struct ifnet *, struct nl_writer *);
+
+static int gif_set_addr_nl(struct gif_softc *, struct nl_pstate *,
+ struct sockaddr *, struct sockaddr *);
+static int gif_set_flags_nl(struct gif_softc *, struct nl_pstate *,
+ uint32_t);
VNET_DEFINE_STATIC(struct if_clone *, gif_cloner);
#define V_gif_cloner VNET(gif_cloner)
@@ -134,8 +151,145 @@
SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(max_gif_nesting), 0, "Max nested tunnels");
+struct nl_parsed_gif {
+ struct sockaddr *ifla_local;
+ struct sockaddr *ifla_remote;
+ uint32_t ifla_flags;
+};
+
+#define _OUT(_field) offsetof(struct nl_parsed_gif, _field)
+static const struct nlattr_parser nla_p_gif[] = {
+ { .type = IFLA_IPTUN_LOCAL, .off = _OUT(ifla_local), .cb = nlattr_get_ip },
+ { .type = IFLA_IPTUN_REMOTE, .off = _OUT(ifla_remote), .cb = nlattr_get_ip },
+ { .type = IFLA_IPTUN_FLAGS, .off = _OUT(ifla_flags), .cb = nlattr_get_uint32 },
+};
+#undef _OUT
+NL_DECLARE_ATTR_PARSER(gif_modify_parser, nla_p_gif);
+
+static const struct nlhdr_parser *all_parsers[] = {
+ &gif_modify_parser,
+};
+
static int
-gif_clone_create(struct if_clone *ifc, int unit, caddr_t params)
+gif_clone_create_nl(struct if_clone *ifc, char *name, size_t len,
+ struct ifc_data_nl *ifd)
+{
+ struct ifc_data ifd_new = {
+ .flags = IFC_F_SYSSPACE,
+ .unit = ifd->unit,
+ };
+
+ return (gif_clone_create(ifc, name, len, &ifd_new, &ifd->ifp));
+}
+
+static int
+gif_clone_modify_nl(struct ifnet *ifp, struct ifc_data_nl *ifd)
+{
+ struct gif_softc *sc;
+ struct nl_parsed_link *lattrs = ifd->lattrs;
+ struct nl_pstate *npt = ifd->npt;
+ struct nl_parsed_gif params = {};
+ struct nlattr *attrs = lattrs->ifla_idata;
+ struct nlattr_bmask bm;
+ int error;
+
+ if ((attrs == NULL) ||
+ (nl_has_attr(ifd->bm, IFLA_LINKINFO) == 0)) {
+ error = nl_modify_ifp_generic(ifp, lattrs, ifd->bm, npt);
+ return (error);
+ }
+
+ error = priv_check(curthread, PRIV_NET_GIF);
+ if (error)
+ return (error);
+
+ nl_get_attrs_bmask_raw(NLA_DATA(attrs), NLA_DATA_LEN(attrs), &bm);
+ if ((error = nl_parse_nested(attrs, &gif_modify_parser, npt, ¶ms)) != 0)
+ return (error);
+
+ sx_xlock(&gif_ioctl_sx);
+ sc = ifp->if_softc;
+ if (sc == NULL)
+ goto generic;
+
+ if (nl_has_attr(&bm, IFLA_IPTUN_LOCAL) && nl_has_attr(&bm, IFLA_IPTUN_REMOTE))
+ error = gif_set_addr_nl(sc, npt, params.ifla_local, params.ifla_remote);
+ else if (nl_has_attr(&bm, IFLA_IPTUN_LOCAL) || nl_has_attr(&bm, IFLA_IPTUN_REMOTE)) {
+ error = EINVAL;
+ nlmsg_report_err_msg(npt, "Specify both remote and local address together");
+ }
+
+ if (error == 0 && nl_has_attr(&bm, IFLA_IPTUN_FLAGS))
+ error = gif_set_flags_nl(sc, npt, params.ifla_flags);
+
+generic:
+ sx_xunlock(&gif_ioctl_sx);
+
+ if (error == 0)
+ error = nl_modify_ifp_generic(ifp, ifd->lattrs, ifd->bm, ifd->npt);
+
+ return (error);
+}
+
+static void
+gif_clone_dump_nl(struct ifnet *ifp, struct nl_writer *nw)
+{
+ struct gif_softc *sc;
+ int off, off2;
+
+ nlattr_add_u32(nw, IFLA_LINK, ifp->if_index);
+ nlattr_add_string(nw, IFLA_IFNAME, ifp->if_xname);
+
+ off = nlattr_add_nested(nw, IFLA_LINKINFO);
+ if (off == 0)
+ return;
+
+ nlattr_add_string(nw, IFLA_INFO_KIND, gifname);
+ off2 = nlattr_add_nested(nw, IFLA_INFO_DATA);
+ if (off2 == 0) {
+ nlattr_set_len(nw, off);
+ return;
+ }
+
+ sx_slock(&gif_ioctl_sx);
+ sc = ifp->if_softc;
+ if (sc == NULL)
+ goto ret;
+
+ if (sc->gif_family == AF_INET) {
+#ifdef INET
+ struct in_aliasreq in;
+ if (in_gif_ioctl(sc, SIOCGIFPSRCADDR, (caddr_t)&in) == 0)
+ nlattr_add_in_addr(nw, IFLA_IPTUN_LOCAL,
+ &in.ifra_addr.sin_addr);
+ if (in_gif_ioctl(sc, SIOCGIFPDSTADDR, (caddr_t)&in) == 0)
+ nlattr_add_in_addr(nw, IFLA_IPTUN_REMOTE,
+ &in.ifra_addr.sin_addr);
+#endif
+ } else if (sc->gif_family == AF_INET6) {
+#ifdef INET6
+ struct in6_aliasreq in6;
+ if (in6_gif_ioctl(sc, SIOCGIFPSRCADDR_IN6, (caddr_t)&in6) == 0)
+ nlattr_add_in6_addr(nw, IFLA_IPTUN_LOCAL,
+ &in6.ifra_addr.sin6_addr);
+ if (in6_gif_ioctl(sc, SIOCGIFPDSTADDR_IN6, (caddr_t)&in6) == 0)
+ nlattr_add_in6_addr(nw, IFLA_IPTUN_REMOTE,
+ &in6.ifra_addr.sin6_addr);
+#endif
+ }
+
+ nlattr_add_u32(nw, IFLA_IPTUN_FLAGS, sc->gif_options);
+
+ret:
+ nlattr_set_len(nw, off2);
+ nlattr_set_len(nw, off);
+
+ sx_sunlock(&gif_ioctl_sx);
+}
+
+static int
+gif_clone_create(struct if_clone *ifc, char *name, size_t len,
+ struct ifc_data *ifd, struct ifnet **ifpp)
{
struct gif_softc *sc;
@@ -143,7 +297,7 @@
sc->gif_fibnum = curthread->td_proc->p_fibnum;
GIF2IFP(sc) = if_alloc(IFT_GIF);
GIF2IFP(sc)->if_softc = sc;
- if_initname(GIF2IFP(sc), gifname, unit);
+ if_initname(GIF2IFP(sc), gifname, ifd->unit);
GIF2IFP(sc)->if_addrlen = 0;
GIF2IFP(sc)->if_mtu = GIF_MTU;
@@ -161,6 +315,7 @@
bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int32_t));
if (ng_gif_attach_p != NULL)
(*ng_gif_attach_p)(GIF2IFP(sc));
+ *ifpp = GIF2IFP(sc);
return (0);
}
@@ -177,35 +332,47 @@
if (sc != NULL)
gif_delete_tunnel(sc);
sx_xunlock(&gif_ioctl_sx);
+ if_link_state_change(ifp, LINK_STATE_DOWN);
}
#endif /* VIMAGE */
-static void
-gif_clone_destroy(struct ifnet *ifp)
+static int
+gif_clone_destroy(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags)
{
struct gif_softc *sc;
sx_xlock(&gif_ioctl_sx);
sc = ifp->if_softc;
gif_delete_tunnel(sc);
+ ifp->if_softc = NULL;
+ sx_xunlock(&gif_ioctl_sx);
+ if_link_state_change(GIF2IFP(sc), LINK_STATE_DOWN);
if (ng_gif_detach_p != NULL)
(*ng_gif_detach_p)(ifp);
bpfdetach(ifp);
if_detach(ifp);
- ifp->if_softc = NULL;
- sx_xunlock(&gif_ioctl_sx);
GIF_WAIT();
if_free(ifp);
free(sc, M_GIF);
+
+ return (0);
}
static void
vnet_gif_init(const void *unused __unused)
{
-
- V_gif_cloner = if_clone_simple(gifname, gif_clone_create,
- gif_clone_destroy, 0);
+ struct if_clone_addreq_v2 req = {
+ .version = 2,
+ .flags = IFC_F_AUTOUNIT,
+ .match_f = NULL,
+ .create_f = gif_clone_create,
+ .destroy_f = gif_clone_destroy,
+ .create_nl_f = gif_clone_create_nl,
+ .modify_nl_f = gif_clone_modify_nl,
+ .dump_nl_f = gif_clone_dump_nl,
+ };
+ V_gif_cloner = ifc_attach_cloner(gifname, (struct if_clone_addreq *)&req);
#ifdef INET
in_gif_init();
#endif
@@ -220,7 +387,7 @@
vnet_gif_uninit(const void *unused __unused)
{
- if_clone_detach(V_gif_cloner);
+ ifc_detach_cloner(V_gif_cloner);
#ifdef INET
in_gif_uninit();
#endif
@@ -237,6 +404,8 @@
switch (type) {
case MOD_LOAD:
+ NL_VERIFY_PARSERS(all_parsers);
+ break;
case MOD_UNLOAD:
break;
default:
@@ -566,6 +735,37 @@
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
}
+static int
+gif_set_flags(struct gif_softc *sc, u_int opt)
+{
+ int error = 0;
+
+ GIF_LOCK_ASSERT();
+
+ if (opt & ~GIF_OPTMASK)
+ return (EINVAL);
+ if (sc->gif_options == opt)
+ return (0);
+
+ switch (sc->gif_family) {
+#ifdef INET
+ case AF_INET:
+ error = in_gif_setopts(sc, opt);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ error = in6_gif_setopts(sc, opt);
+ break;
+#endif
+ default:
+ /* No need to invoke AF-handler */
+ sc->gif_options = opt;
+ }
+
+ return (error);
+}
+
static int
gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
@@ -640,27 +840,7 @@
sizeof(options));
if (error)
break;
- if (options & ~GIF_OPTMASK) {
- error = EINVAL;
- break;
- }
- if (sc->gif_options != options) {
- switch (sc->gif_family) {
-#ifdef INET
- case AF_INET:
- error = in_gif_setopts(sc, options);
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- error = in6_gif_setopts(sc, options);
- break;
-#endif
- default:
- /* No need to invoke AF-handler */
- sc->gif_options = options;
- }
- }
+ error = gif_set_flags(sc, options);
break;
default:
error = EINVAL;
@@ -687,7 +867,7 @@
gif_delete_tunnel(struct gif_softc *sc)
{
- sx_assert(&gif_ioctl_sx, SA_XLOCKED);
+ GIF_LOCK_ASSERT();
if (sc->gif_family != 0) {
CK_LIST_REMOVE(sc, srchash);
CK_LIST_REMOVE(sc, chain);
@@ -697,5 +877,62 @@
}
sc->gif_family = 0;
GIF2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
- if_link_state_change(GIF2IFP(sc), LINK_STATE_DOWN);
+}
+
+static int
+gif_set_addr_nl(struct gif_softc *sc, struct nl_pstate *npt,
+ struct sockaddr *src, struct sockaddr *dst)
+{
+#if defined(INET) || defined(INET6)
+ union {
+#ifdef INET
+ struct in_aliasreq in;
+#endif
+#ifdef INET6
+ struct in6_aliasreq in6;
+#endif
+ } aliasreq;
+#endif
+ int error;
+
+ /* XXX: this sanity check runs again in in[6]_gif_ioctl */
+ if (src->sa_family != dst->sa_family)
+ error = EADDRNOTAVAIL;
+#ifdef INET
+ else if (src->sa_family == AF_INET) {
+ memcpy(&aliasreq.in.ifra_addr, src, sizeof(struct sockaddr_in));
+ memcpy(&aliasreq.in.ifra_dstaddr, dst, sizeof(struct sockaddr_in));
+ error = in_gif_ioctl(sc, SIOCSIFPHYADDR, (caddr_t)&aliasreq.in);
+ }
+#endif
+#ifdef INET6
+ else if (src->sa_family == AF_INET6) {
+ memcpy(&aliasreq.in6.ifra_addr, src, sizeof(struct sockaddr_in6));
+ memcpy(&aliasreq.in6.ifra_dstaddr, dst, sizeof(struct sockaddr_in6));
+ error = in6_gif_ioctl(sc, SIOCSIFPHYADDR_IN6, (caddr_t)&aliasreq.in6);
+ }
+#endif
+ else
+ error = EAFNOSUPPORT;
+
+ if (error == EADDRNOTAVAIL)
+ nlmsg_report_err_msg(npt, "address is invalid");
+ if (error == EEXIST)
+ nlmsg_report_err_msg(npt, "remote and local addresses are the same");
+ if (error == EAFNOSUPPORT)
+ nlmsg_report_err_msg(npt, "address family is not supported");
+
+ return (error);
+}
+
+static int
+gif_set_flags_nl(struct gif_softc *sc, struct nl_pstate *npt, uint32_t opt)
+{
+ int error;
+
+ error = gif_set_flags(sc, opt);
+ if (error == EINVAL)
+ nlmsg_report_err_msg(npt, "gif flags are invalid");
+
+ return (error);
}
diff --git a/sys/netlink/route/interface.h b/sys/netlink/route/interface.h
--- a/sys/netlink/route/interface.h
+++ b/sys/netlink/route/interface.h
@@ -272,6 +272,16 @@
uint32_t mask;
};
+/* IFLA_INFO_DATA gif attributes */
+enum {
+ IFLA_IPTUN_UNSPEC,
+ IFLA_IPTUN_LOCAL,
+ IFLA_IPTUN_REMOTE,
+ IFLA_IPTUN_FLAGS,
+ __IFLA_IPTUN_MAX,
+};
+#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
+
/* IFLA_INFO_DATA gre attributes */
enum {
IFLA_GRE_UNSPEC,
diff --git a/tests/sys/netlink/Makefile b/tests/sys/netlink/Makefile
--- a/tests/sys/netlink/Makefile
+++ b/tests/sys/netlink/Makefile
@@ -6,6 +6,7 @@
ATF_TESTS_C+= netlink_socket
ATF_TESTS_C+= test_snl test_snl_generic
ATF_TESTS_C+= test_rtnl_gre
+ATF_TESTS_C+= test_rtnl_gif
ATF_TESTS_C+= test_rtnl_route
ATF_TESTS_PYTEST += test_nl_core.py
ATF_TESTS_PYTEST += test_rtnl_iface.py
diff --git a/tests/sys/netlink/test_rtnl_gif.c b/tests/sys/netlink/test_rtnl_gif.c
new file mode 100644
--- /dev/null
+++ b/tests/sys/netlink/test_rtnl_gif.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2026 Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/module.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if_gif.h>
+
+#include <netlink/netlink.h>
+#include <netlink/netlink_route.h>
+#include <netlink/netlink_snl.h>
+#include <netlink/netlink_snl_route.h>
+#include <netlink/netlink_snl_route_compat.h>
+#include <netlink/netlink_snl_route_parsers.h>
+
+#include <atf-c.h>
+
+struct nl_parsed_gif {
+ struct sockaddr *ifla_local;
+ struct sockaddr *ifla_remote;
+ uint32_t ifla_flags;
+};
+
+struct nla_gif_info {
+ const char *kind;
+ struct nl_parsed_gif data;
+};
+
+struct nla_gif_link {
+ uint32_t ifi_index;
+ struct nla_gif_info linkinfo;
+};
+
+#define _OUT(_field) offsetof(struct nl_parsed_gif, _field)
+static const struct snl_attr_parser nla_p_gif[] = {
+ { .type = IFLA_IPTUN_LOCAL, .off = _OUT(ifla_local), .cb = snl_attr_get_ip },
+ { .type = IFLA_IPTUN_REMOTE, .off = _OUT(ifla_remote), .cb = snl_attr_get_ip },
+ { .type = IFLA_IPTUN_FLAGS, .off = _OUT(ifla_flags), .cb = snl_attr_get_uint32 },
+};
+#undef _OUT
+SNL_DECLARE_ATTR_PARSER(gif_linkinfo_data_parser, nla_p_gif);
+
+#define _OUT(_field) offsetof(struct nla_gif_info, _field)
+static const struct snl_attr_parser ap_gif_linkinfo[] = {
+ { .type = IFLA_INFO_KIND, .off = _OUT(kind), .cb = snl_attr_get_string },
+ { .type = IFLA_INFO_DATA, .off = _OUT(data),
+ .arg = &gif_linkinfo_data_parser, .cb = snl_attr_get_nested },
+};
+#undef _OUT
+SNL_DECLARE_ATTR_PARSER(gif_linkinfo_parser, ap_gif_linkinfo);
+
+#define _IN(_field) offsetof(struct ifinfomsg, _field)
+#define _OUT(_field) offsetof(struct nla_gif_link, _field)
+static const struct snl_attr_parser ap_gif_link[] = {
+ { .type = IFLA_LINKINFO, .off = _OUT(linkinfo),
+ .arg = &gif_linkinfo_parser, .cb = snl_attr_get_nested },
+};
+
+static const struct snl_field_parser fp_gif_link[] = {
+ { .off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 },
+};
+#undef _IN
+#undef _OUT
+SNL_DECLARE_PARSER(gif_parser, struct ifinfomsg, fp_gif_link, ap_gif_link);
+
+ATF_TC(test_rtnl_gif);
+ATF_TC_HEAD(test_rtnl_gif, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "test gif interface using netlink");
+ atf_tc_set_md_var(tc, "require.user", "root");
+ atf_tc_set_md_var(tc, "require.kmods", "netlink if_gif");
+}
+
+ATF_TC_BODY(test_rtnl_gif, tc)
+{
+ struct snl_state ss;
+ struct snl_writer nw;
+ struct nlmsghdr *hdr, *rx_hdr;
+ struct in_addr src, dst;
+ struct nla_gif_link lattrs = {};
+ struct nl_parsed_gif attrs = {};
+ struct snl_errmsg_data e = {};
+ struct ifinfomsg *ifmsg;
+ int off, off2;
+
+ ATF_REQUIRE_MSG(snl_init(&ss, NETLINK_ROUTE), "snl_init() failed");
+
+ /* Create gif interface */
+ snl_init_writer(&ss, &nw);
+ ATF_REQUIRE((hdr = snl_create_msg_request(&nw, RTM_NEWLINK)) != NULL);
+ hdr->nlmsg_flags |= (NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST | NLM_F_ACK);
+ snl_reserve_msg_object(&nw, struct ifinfomsg);
+
+ /* Create parameters */
+ snl_add_msg_attr_string(&nw, IFLA_IFNAME, "gif10");
+ off = snl_add_msg_attr_nested(&nw, IFLA_LINKINFO);
+ snl_add_msg_attr_string(&nw, IFLA_INFO_KIND, "gif");
+ off2 = snl_add_msg_attr_nested(&nw, IFLA_INFO_DATA);
+
+ inet_pton(AF_INET, "127.0.0.1", &src);
+ inet_pton(AF_INET, "127.0.0.2", &dst);
+ snl_add_msg_attr_ip4(&nw, IFLA_IPTUN_LOCAL, &src);
+ snl_add_msg_attr_ip4(&nw, IFLA_IPTUN_REMOTE, &dst);
+ snl_add_msg_attr_u32(&nw, IFLA_IPTUN_FLAGS, (GIF_NOCLAMP | GIF_IGNORE_SOURCE));
+
+ snl_end_attr_nested(&nw, off2);
+ snl_end_attr_nested(&nw, off);
+
+ ATF_REQUIRE((hdr = snl_finalize_msg(&nw)) != NULL);
+ ATF_REQUIRE(snl_send_message(&ss, hdr));
+ ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL);
+ ATF_REQUIRE(snl_parse_errmsg(&ss, rx_hdr, &e));
+ ATF_REQUIRE_INTEQ(e.error, 0);
+
+ /* Dump gif interface */
+ snl_init_writer(&ss, &nw);
+ ATF_REQUIRE((hdr = snl_create_msg_request(&nw, RTM_GETLINK)) != NULL);
+ hdr->nlmsg_flags |= NLM_F_DUMP;
+ snl_reserve_msg_object(&nw, struct ifinfomsg);
+ snl_add_msg_attr_string(&nw, IFLA_IFNAME, "gif10");
+ off = snl_add_msg_attr_nested(&nw, IFLA_LINKINFO);
+ snl_add_msg_attr_string(&nw, IFLA_INFO_KIND, "gif");
+ snl_end_attr_nested(&nw, off);
+
+ ATF_REQUIRE((hdr = snl_finalize_msg(&nw)) != NULL);
+ ATF_REQUIRE(snl_send_message(&ss, hdr));
+
+ /* Check parameters */
+ ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL);
+ ATF_CHECK(snl_parse_nlmsg(&ss, rx_hdr, &gif_parser, &lattrs));
+ attrs = lattrs.linkinfo.data;
+ ATF_CHECK_STREQ(lattrs.linkinfo.kind, "gif");
+ ATF_CHECK_INTEQ(attrs.ifla_flags, (GIF_NOCLAMP | GIF_IGNORE_SOURCE));
+
+ /* Delete gif interface */
+ snl_init_writer(&ss, &nw);
+ ATF_REQUIRE((hdr = snl_create_msg_request(&nw, RTM_DELLINK)) != NULL);
+ hdr->nlmsg_flags |= (NLM_F_ACK | NLM_F_REQUEST);
+ ATF_REQUIRE((ifmsg = snl_reserve_msg_object(&nw, struct ifinfomsg)) != NULL);
+ ifmsg->ifi_index = lattrs.ifi_index;
+ ATF_REQUIRE((hdr = snl_finalize_msg(&nw)) != NULL);
+ ATF_REQUIRE(snl_send_message(&ss, hdr));
+ ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL);
+ ATF_REQUIRE(snl_parse_errmsg(&ss, rx_hdr, &e));
+ ATF_REQUIRE_INTEQ(e.error, 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, test_rtnl_gif);
+
+ return (atf_no_error());
+}
+
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Aug 5, 7:03 PM (17 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35971396
Default Alt Text
D57666.id183026.diff (17 KB)
Attached To
Mode
D57666: if_gif: Add netlink support with tests
Attached
Detach File
Event Timeline
Log In to Comment