Changeset View
Changeset View
Standalone View
Standalone View
sys/netlink/route/iface.c
Show First 20 Lines • Show All 297 Lines • ▼ Show 20 Lines | */ | ||||
if (ifp->if_description != NULL) | if (ifp->if_description != NULL) | ||||
nlattr_add_string(nw, IFLA_IFALIAS, ifp->if_description); | nlattr_add_string(nw, IFLA_IFALIAS, ifp->if_description); | ||||
get_stats(nw, ifp); | get_stats(nw, ifp); | ||||
uint32_t val = (ifp->if_flags & IFF_PROMISC) != 0; | uint32_t val = (ifp->if_flags & IFF_PROMISC) != 0; | ||||
nlattr_add_u32(nw, IFLA_PROMISCUITY, val); | nlattr_add_u32(nw, IFLA_PROMISCUITY, val); | ||||
sx_slock(&rtnl_cloner_lock); | ifc_dump_ifp_nl(ifp, nw); | ||||
struct nl_cloner *cloner = rtnl_iface_find_cloner_locked(ifp->if_dname); | |||||
if (cloner != NULL && cloner->dump_f != NULL) { | |||||
/* Ignore any dump error */ | |||||
cloner->dump_f(ifp, nw); | |||||
} | |||||
sx_sunlock(&rtnl_cloner_lock); | |||||
if (nlmsg_end(nw)) | if (nlmsg_end(nw)) | ||||
return (true); | return (true); | ||||
enomem: | enomem: | ||||
NL_LOG(LOG_DEBUG, "unable to dump interface %s state (ENOMEM)", if_name(ifp)); | NL_LOG(LOG_DEBUG, "unable to dump interface %s state (ENOMEM)", if_name(ifp)); | ||||
nlmsg_abort(nw); | nlmsg_abort(nw); | ||||
return (false); | return (false); | ||||
Show All 27 Lines | static const struct nlattr_parser nla_p_linfo[] = { | ||||
{ .type = IFLA_INFO_KIND, .off = _OUT(ifla_cloner), .cb = nlattr_get_stringn }, | { .type = IFLA_INFO_KIND, .off = _OUT(ifla_cloner), .cb = nlattr_get_stringn }, | ||||
{ .type = IFLA_INFO_DATA, .off = _OUT(ifla_idata), .cb = nlattr_get_nla }, | { .type = IFLA_INFO_DATA, .off = _OUT(ifla_idata), .cb = nlattr_get_nla }, | ||||
}; | }; | ||||
NL_DECLARE_ATTR_PARSER(linfo_parser, nla_p_linfo); | NL_DECLARE_ATTR_PARSER(linfo_parser, nla_p_linfo); | ||||
static const struct nlattr_parser nla_p_if[] = { | static const struct nlattr_parser nla_p_if[] = { | ||||
{ .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = nlattr_get_string }, | { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = nlattr_get_string }, | ||||
{ .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = nlattr_get_uint32 }, | { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = nlattr_get_uint32 }, | ||||
{ .type = IFLA_LINK, .off = _OUT(ifi_index), .cb = nlattr_get_uint32 }, | { .type = IFLA_LINK, .off = _OUT(ifla_link), .cb = nlattr_get_uint32 }, | ||||
{ .type = IFLA_LINKINFO, .arg = &linfo_parser, .cb = nlattr_get_nested }, | { .type = IFLA_LINKINFO, .arg = &linfo_parser, .cb = nlattr_get_nested }, | ||||
{ .type = IFLA_IFALIAS, .off = _OUT(ifla_ifalias), .cb = nlattr_get_string }, | { .type = IFLA_IFALIAS, .off = _OUT(ifla_ifalias), .cb = nlattr_get_string }, | ||||
{ .type = IFLA_GROUP, .off = _OUT(ifla_group), .cb = nlattr_get_string }, | { .type = IFLA_GROUP, .off = _OUT(ifla_group), .cb = nlattr_get_string }, | ||||
{ .type = IFLA_ALT_IFNAME, .off = _OUT(ifla_ifname), .cb = nlattr_get_string }, | { .type = IFLA_ALT_IFNAME, .off = _OUT(ifla_ifname), .cb = nlattr_get_string }, | ||||
}; | }; | ||||
#undef _IN | #undef _IN | ||||
#undef _OUT | #undef _OUT | ||||
NL_DECLARE_STRICT_PARSER(ifmsg_parser, struct ifinfomsg, check_ifmsg, nlf_p_if, nla_p_if); | NL_DECLARE_STRICT_PARSER(ifmsg_parser, struct ifinfomsg, check_ifmsg, nlf_p_if, nla_p_if); | ||||
▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | if (lattrs->ifla_ifname == NULL || strlen(lattrs->ifla_ifname) == 0) { | ||||
NLMSG_REPORT_ERR_MSG(npt, "empty IFLA_IFNAME attribute"); | NLMSG_REPORT_ERR_MSG(npt, "empty IFLA_IFNAME attribute"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (lattrs->ifla_cloner == NULL || strlen(lattrs->ifla_cloner) == 0) { | if (lattrs->ifla_cloner == NULL || strlen(lattrs->ifla_cloner) == 0) { | ||||
NLMSG_REPORT_ERR_MSG(npt, "empty IFLA_INFO_KIND attribute"); | NLMSG_REPORT_ERR_MSG(npt, "empty IFLA_INFO_KIND attribute"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
bool found = false; | struct ifc_data_nl ifd = { | ||||
int error = 0; | .flags = IFC_F_CREATE, | ||||
.lattrs = lattrs, | |||||
.bm = bm, | |||||
.npt = npt, | |||||
}; | |||||
if (ifc_create_ifp_nl(lattrs->ifla_ifname, &ifd) && ifd.error == 0) | |||||
nl_store_ifp_cookie(npt, ifd.ifp); | |||||
sx_slock(&rtnl_cloner_lock); | return (ifd.error); | ||||
struct nl_cloner *cloner = rtnl_iface_find_cloner_locked(lattrs->ifla_cloner); | |||||
if (cloner != NULL) { | |||||
found = true; | |||||
error = cloner->create_f(lattrs, bm, nlp, npt); | |||||
} | } | ||||
sx_sunlock(&rtnl_cloner_lock); | |||||
if (!found) | |||||
error = generic_cloner.create_f(lattrs, bm, nlp, npt); | |||||
return (error); | |||||
} | |||||
static int | static int | ||||
modify_link(struct nlmsghdr *hdr, struct nl_parsed_link *lattrs, | modify_link(struct nlmsghdr *hdr, struct nl_parsed_link *lattrs, | ||||
struct nlattr_bmask *bm, struct nlpcb *nlp, struct nl_pstate *npt) | struct nlattr_bmask *bm, struct nlpcb *nlp, struct nl_pstate *npt) | ||||
{ | { | ||||
struct ifnet *ifp = NULL; | struct ifnet *ifp = NULL; | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
if (lattrs->ifi_index == 0 && lattrs->ifla_ifname == NULL) { | if (lattrs->ifi_index == 0 && lattrs->ifla_ifname == NULL) { | ||||
Show All 24 Lines | if (ifp == NULL) { | ||||
lattrs->ifla_ifname); | lattrs->ifla_ifname); | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
} | } | ||||
MPASS(ifp != NULL); | MPASS(ifp != NULL); | ||||
/* | /* | ||||
* There can be multiple kinds of interfaces: | * Modification request can address either | ||||
* 1) cloned, with additional options | * 1) cloned interface, in which case we call the cloner-specific | ||||
* 2) cloned, but w/o additional options | * modification routine | ||||
* 3) non-cloned (e.g. "physical). | * or | ||||
* | * 2) non-cloned (e.g. "physical") interface, in which case we call | ||||
* Thus, try to find cloner-specific callback and fallback to the | * generic modification routine | ||||
* "default" handler if not found. | |||||
*/ | */ | ||||
bool found = false; | struct ifc_data_nl ifd = { .lattrs = lattrs, .bm = bm, .npt = npt }; | ||||
int error = 0; | if (!ifc_modify_ifp_nl(ifp, &ifd)) | ||||
ifd.error = nl_modify_ifp_generic(ifp, lattrs, bm, npt); | |||||
sx_slock(&rtnl_cloner_lock); | |||||
struct nl_cloner *cloner = rtnl_iface_find_cloner_locked(ifp->if_dname); | |||||
if (cloner != NULL) { | |||||
found = true; | |||||
error = cloner->modify_f(ifp, lattrs, bm, nlp, npt); | |||||
} | |||||
sx_sunlock(&rtnl_cloner_lock); | |||||
if (!found) | |||||
error = generic_cloner.modify_f(ifp, lattrs, bm, nlp, npt); | |||||
if_rele(ifp); | if_rele(ifp); | ||||
return (error); | return (ifd.error); | ||||
} | } | ||||
static int | static int | ||||
rtnl_handle_newlink(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *npt) | rtnl_handle_newlink(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *npt) | ||||
{ | { | ||||
struct nlattr_bmask bm; | struct nlattr_bmask bm; | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 424 Lines • ▼ Show 20 Lines | ifdetach_event = EVENTHANDLER_REGISTER( | ||||
EVENTHANDLER_PRI_ANY); | EVENTHANDLER_PRI_ANY); | ||||
ifaddr_event = EVENTHANDLER_REGISTER( | ifaddr_event = EVENTHANDLER_REGISTER( | ||||
rt_addrmsg, rtnl_handle_ifaddr, NULL, | rt_addrmsg, rtnl_handle_ifaddr, NULL, | ||||
EVENTHANDLER_PRI_ANY); | EVENTHANDLER_PRI_ANY); | ||||
iflink_event = EVENTHANDLER_REGISTER( | iflink_event = EVENTHANDLER_REGISTER( | ||||
ifnet_link_event, rtnl_handle_iflink, NULL, | ifnet_link_event, rtnl_handle_iflink, NULL, | ||||
EVENTHANDLER_PRI_ANY); | EVENTHANDLER_PRI_ANY); | ||||
NL_VERIFY_PARSERS(all_parsers); | NL_VERIFY_PARSERS(all_parsers); | ||||
rtnl_iface_drivers_register(); | |||||
rtnl_register_messages(cmd_handlers, NL_ARRAY_LEN(cmd_handlers)); | rtnl_register_messages(cmd_handlers, NL_ARRAY_LEN(cmd_handlers)); | ||||
} | } | ||||
void | void | ||||
rtnl_ifaces_destroy(void) | rtnl_ifaces_destroy(void) | ||||
{ | { | ||||
EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ifattach_event); | EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ifattach_event); | ||||
EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_event); | EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_event); | ||||
EVENTHANDLER_DEREGISTER(rt_addrmsg, ifaddr_event); | EVENTHANDLER_DEREGISTER(rt_addrmsg, ifaddr_event); | ||||
EVENTHANDLER_DEREGISTER(ifnet_link_event, iflink_event); | EVENTHANDLER_DEREGISTER(ifnet_link_event, iflink_event); | ||||
} | } |