/* multicast groups */ enum batadv_netlink_multicast_groups {
BATADV_NL_MCGRP_CONFIG,
BATADV_NL_MCGRP_TPMETER,
};
/** * enum batadv_genl_ops_flags - flags for genl_ops's internal_flags
*/ enum batadv_genl_ops_flags { /** * @BATADV_FLAG_NEED_MESH: request requires valid mesh interface in * attribute BATADV_ATTR_MESH_IFINDEX and expects a pointer to it to be * saved in info->user_ptr[0]
*/
BATADV_FLAG_NEED_MESH = BIT(0),
/** * @BATADV_FLAG_NEED_HARDIF: request requires valid hard interface in * attribute BATADV_ATTR_HARD_IFINDEX and expects a pointer to it to be * saved in info->user_ptr[1]
*/
BATADV_FLAG_NEED_HARDIF = BIT(1),
/** * @BATADV_FLAG_NEED_VLAN: request requires valid vlan in * attribute BATADV_ATTR_VLANID and expects a pointer to it to be * saved in info->user_ptr[1]
*/
BATADV_FLAG_NEED_VLAN = BIT(2),
};
/** * batadv_netlink_get_ifindex() - Extract an interface index from a message * @nlh: Message header * @attrtype: Attribute which holds an interface index * * Return: interface index, or 0.
*/ staticint batadv_netlink_get_ifindex(conststruct nlmsghdr *nlh, int attrtype)
{ struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype);
/** * batadv_netlink_mesh_fill_ap_isolation() - Add ap_isolation meshif attribute * @msg: Netlink message to dump into * @bat_priv: the bat priv with all the mesh interface information * * Return: 0 on success or negative error number in case of failure
*/ staticint batadv_netlink_mesh_fill_ap_isolation(struct sk_buff *msg, struct batadv_priv *bat_priv)
{ struct batadv_meshif_vlan *vlan;
u8 ap_isolation;
vlan = batadv_meshif_vlan_get(bat_priv, BATADV_NO_FLAGS); if (!vlan) return 0;
/** * batadv_netlink_set_mesh_ap_isolation() - Set ap_isolation from genl msg * @attr: parsed BATADV_ATTR_AP_ISOLATION_ENABLED attribute * @bat_priv: the bat priv with all the mesh interface information * * Return: 0 on success or negative error number in case of failure
*/ staticint batadv_netlink_set_mesh_ap_isolation(struct nlattr *attr, struct batadv_priv *bat_priv)
{ struct batadv_meshif_vlan *vlan;
vlan = batadv_meshif_vlan_get(bat_priv, BATADV_NO_FLAGS); if (!vlan) return -ENOENT;
/** * batadv_netlink_mesh_fill() - Fill message with mesh attributes * @msg: Netlink message to dump into * @bat_priv: the bat priv with all the mesh interface information * @cmd: type of message to generate * @portid: Port making netlink request * @seq: sequence number for message * @flags: Additional flags for message * * Return: 0 on success or negative error number in case of failure
*/ staticint batadv_netlink_mesh_fill(struct sk_buff *msg, struct batadv_priv *bat_priv, enum batadv_nl_commands cmd,
u32 portid, u32 seq, int flags)
{ struct net_device *mesh_iface = bat_priv->mesh_iface; struct batadv_hard_iface *primary_if = NULL; struct net_device *hard_iface; void *hdr;
if (nla_put_u8(msg, BATADV_ATTR_FRAGMENTATION_ENABLED,
!!atomic_read(&bat_priv->fragmentation))) goto nla_put_failure;
if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_DOWN,
atomic_read(&bat_priv->gw.bandwidth_down))) goto nla_put_failure;
if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_UP,
atomic_read(&bat_priv->gw.bandwidth_up))) goto nla_put_failure;
if (nla_put_u8(msg, BATADV_ATTR_GW_MODE,
atomic_read(&bat_priv->gw.mode))) goto nla_put_failure;
if (bat_priv->algo_ops->gw.get_best_gw_node &&
bat_priv->algo_ops->gw.is_eligible) { /* GW selection class is not available if the routing algorithm * in use does not implement the GW API
*/ if (nla_put_u32(msg, BATADV_ATTR_GW_SEL_CLASS,
atomic_read(&bat_priv->gw.sel_class))) goto nla_put_failure;
}
if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY,
atomic_read(&bat_priv->hop_penalty))) goto nla_put_failure;
if (nla_put_u32(msg, BATADV_ATTR_ORIG_INTERVAL,
atomic_read(&bat_priv->orig_interval))) goto nla_put_failure;
batadv_hardif_put(primary_if);
genlmsg_end(msg, hdr); return 0;
nla_put_failure:
batadv_hardif_put(primary_if);
genlmsg_cancel(msg, hdr); return -EMSGSIZE;
}
/** * batadv_netlink_notify_mesh() - send meshif attributes to listener * @bat_priv: the bat priv with all the mesh interface information * * Return: 0 on success, < 0 on error
*/ staticint batadv_netlink_notify_mesh(struct batadv_priv *bat_priv)
{ struct sk_buff *msg; int ret;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM;
ret = batadv_netlink_mesh_fill(msg, bat_priv, BATADV_CMD_SET_MESH,
0, 0, 0); if (ret < 0) {
nlmsg_free(msg); return ret;
}
/** * batadv_netlink_get_mesh() - Get meshif attributes * @skb: Netlink message with request data * @info: receiver information * * Return: 0 on success or negative error number in case of failure
*/ staticint batadv_netlink_get_mesh(struct sk_buff *skb, struct genl_info *info)
{ struct batadv_priv *bat_priv = info->user_ptr[0]; struct sk_buff *msg; int ret;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM;
ret = batadv_netlink_mesh_fill(msg, bat_priv, BATADV_CMD_GET_MESH,
info->snd_portid, info->snd_seq, 0); if (ret < 0) {
nlmsg_free(msg); return ret;
}
ret = genlmsg_reply(msg, info);
return ret;
}
/** * batadv_netlink_set_mesh() - Set meshif attributes * @skb: Netlink message with request data * @info: receiver information * * Return: 0 on success or negative error number in case of failure
*/ staticint batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
{ struct batadv_priv *bat_priv = info->user_ptr[0]; struct nlattr *attr;
if (info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED]) {
attr = info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED];
if (gw_mode <= BATADV_GW_MODE_SERVER) { /* Invoking batadv_gw_reselect() is not enough to really * de-select the current GW. It will only instruct the * gateway client code to perform a re-election the next * time that this is needed. * * When gw client mode is being switched off the current * GW must be de-selected explicitly otherwise no GW_ADD * uevent is thrown on client mode re-activation. This * is operation is performed in * batadv_gw_check_client_stop().
*/
batadv_gw_reselect(bat_priv);
/* always call batadv_gw_check_client_stop() before * changing the gateway state
*/
batadv_gw_check_client_stop(bat_priv);
atomic_set(&bat_priv->gw.mode, gw_mode);
batadv_gw_tvlv_container_update(bat_priv);
}
}
if (info->attrs[BATADV_ATTR_GW_SEL_CLASS] &&
bat_priv->algo_ops->gw.get_best_gw_node &&
bat_priv->algo_ops->gw.is_eligible) { /* setting the GW selection class is allowed only if the routing * algorithm in use implements the GW API
*/
/** * batadv_netlink_tp_meter_put() - Fill information of started tp_meter session * @msg: netlink message to be sent back * @cookie: tp meter session cookie * * Return: 0 on success, < 0 on error
*/ staticint
batadv_netlink_tp_meter_put(struct sk_buff *msg, u32 cookie)
{ if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie)) return -ENOBUFS;
return 0;
}
/** * batadv_netlink_tpmeter_notify() - send tp_meter result via netlink to client * @bat_priv: the bat priv with all the mesh interface information * @dst: destination of tp_meter session * @result: reason for tp meter session stop * @test_time: total time of the tp_meter session * @total_bytes: bytes acked to the receiver * @cookie: cookie of tp_meter session * * Return: 0 on success, < 0 on error
*/ int batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst,
u8 result, u32 test_time, u64 total_bytes,
u32 cookie)
{ struct sk_buff *msg; void *hdr; int ret;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM;
hdr = genlmsg_put(msg, 0, 0, &batadv_netlink_family, 0,
BATADV_CMD_TP_METER); if (!hdr) {
ret = -ENOBUFS; goto err_genlmsg;
}
if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie)) goto nla_put_failure;
if (nla_put_u32(msg, BATADV_ATTR_TPMETER_TEST_TIME, test_time)) goto nla_put_failure;
if (nla_put_u64_64bit(msg, BATADV_ATTR_TPMETER_BYTES, total_bytes,
BATADV_ATTR_PAD)) goto nla_put_failure;
if (nla_put_u8(msg, BATADV_ATTR_TPMETER_RESULT, result)) goto nla_put_failure;
if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, dst)) goto nla_put_failure;
/** * batadv_netlink_hardif_fill() - Fill message with hardif attributes * @msg: Netlink message to dump into * @bat_priv: the bat priv with all the mesh interface information * @hard_iface: hard interface which was modified * @cmd: type of message to generate * @portid: Port making netlink request * @seq: sequence number for message * @flags: Additional flags for message * @cb: Control block containing additional options * * Return: 0 on success or negative error number in case of failure
*/ staticint batadv_netlink_hardif_fill(struct sk_buff *msg, struct batadv_priv *bat_priv, struct batadv_hard_iface *hard_iface, enum batadv_nl_commands cmd,
u32 portid, u32 seq, int flags, struct netlink_callback *cb)
{ struct net_device *net_dev = hard_iface->net_dev; void *hdr;
/** * batadv_netlink_notify_hardif() - send hardif attributes to listener * @bat_priv: the bat priv with all the mesh interface information * @hard_iface: hard interface which was modified * * Return: 0 on success, < 0 on error
*/ staticint batadv_netlink_notify_hardif(struct batadv_priv *bat_priv, struct batadv_hard_iface *hard_iface)
{ struct sk_buff *msg; int ret;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM;
ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface,
BATADV_CMD_SET_HARDIF, 0, 0, 0, NULL); if (ret < 0) {
nlmsg_free(msg); return ret;
}
/** * batadv_netlink_dump_hardif() - Dump all hard interface into a messages * @msg: Netlink message to dump into * @cb: Parameters from query * * Return: error code, or length of reply message on success
*/ staticint
batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb)
{ struct net_device *mesh_iface; struct batadv_hard_iface *hard_iface; struct batadv_priv *bat_priv; int portid = NETLINK_CB(cb->skb).portid; int skip = cb->args[0]; struct list_head *iter; int i = 0;
mesh_iface = batadv_netlink_get_meshif(cb); if (IS_ERR(mesh_iface)) return PTR_ERR(mesh_iface);
/** * batadv_netlink_vlan_fill() - Fill message with vlan attributes * @msg: Netlink message to dump into * @bat_priv: the bat priv with all the mesh interface information * @vlan: vlan which was modified * @cmd: type of message to generate * @portid: Port making netlink request * @seq: sequence number for message * @flags: Additional flags for message * * Return: 0 on success or negative error number in case of failure
*/ staticint batadv_netlink_vlan_fill(struct sk_buff *msg, struct batadv_priv *bat_priv, struct batadv_meshif_vlan *vlan, enum batadv_nl_commands cmd,
u32 portid, u32 seq, int flags)
{ void *hdr;
/** * batadv_netlink_notify_vlan() - send vlan attributes to listener * @bat_priv: the bat priv with all the mesh interface information * @vlan: vlan which was modified * * Return: 0 on success, < 0 on error
*/ staticint batadv_netlink_notify_vlan(struct batadv_priv *bat_priv, struct batadv_meshif_vlan *vlan)
{ struct sk_buff *msg; int ret;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM;
ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan,
BATADV_CMD_SET_VLAN, 0, 0, 0); if (ret < 0) {
nlmsg_free(msg); return ret;
}
/** * batadv_netlink_get_meshif_from_ifindex() - Get mesh-iface from ifindex * @net: the applicable net namespace * @ifindex: index of the mesh interface * * Return: Pointer to mesh interface (with increased refcnt) on success, error * pointer on error
*/ staticstruct net_device *
batadv_netlink_get_meshif_from_ifindex(struct net *net, int ifindex)
{ struct net_device *mesh_iface;
mesh_iface = dev_get_by_index(net, ifindex); if (!mesh_iface) return ERR_PTR(-ENODEV);
if (!batadv_meshif_is_valid(mesh_iface)) goto err_put_meshif;
return mesh_iface;
err_put_meshif:
dev_put(mesh_iface);
return ERR_PTR(-EINVAL);
}
/** * batadv_netlink_get_meshif_from_info() - Get mesh-iface from genl attributes * @net: the applicable net namespace * @info: receiver information * * Return: Pointer to mesh interface (with increased refcnt) on success, error * pointer on error
*/ staticstruct net_device *
batadv_netlink_get_meshif_from_info(struct net *net, struct genl_info *info)
{ int ifindex;
if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) return ERR_PTR(-EINVAL);
/** * batadv_netlink_get_hardif_from_ifindex() - Get hard-iface from ifindex * @bat_priv: the bat priv with all the mesh interface information * @net: the applicable net namespace * @ifindex: index of the hard interface * * Return: Pointer to hard interface (with increased refcnt) on success, error * pointer on error
*/ staticstruct batadv_hard_iface *
batadv_netlink_get_hardif_from_ifindex(struct batadv_priv *bat_priv, struct net *net, int ifindex)
{ struct batadv_hard_iface *hard_iface; struct net_device *hard_dev;
hard_dev = dev_get_by_index(net, ifindex); if (!hard_dev) return ERR_PTR(-ENODEV);
hard_iface = batadv_hardif_get_by_netdev(hard_dev); if (!hard_iface) goto err_put_harddev;
if (hard_iface->mesh_iface != bat_priv->mesh_iface) goto err_put_hardif;
/* hard_dev is referenced by hard_iface and not needed here */
dev_put(hard_dev);
/** * batadv_netlink_get_hardif_from_info() - Get hard-iface from genl attributes * @bat_priv: the bat priv with all the mesh interface information * @net: the applicable net namespace * @info: receiver information * * Return: Pointer to hard interface (with increased refcnt) on success, error * pointer on error
*/ staticstruct batadv_hard_iface *
batadv_netlink_get_hardif_from_info(struct batadv_priv *bat_priv, struct net *net, struct genl_info *info)
{ int ifindex;
if (!info->attrs[BATADV_ATTR_HARD_IFINDEX]) return ERR_PTR(-EINVAL);
/** * batadv_netlink_get_hardif() - Retrieve hard interface from netlink callback * @bat_priv: the bat priv with all the mesh interface information * @cb: callback structure containing arguments * * Return: Pointer to hard interface (with increased refcnt) on success, error * pointer on error
*/ struct batadv_hard_iface *
batadv_netlink_get_hardif(struct batadv_priv *bat_priv, struct netlink_callback *cb)
{ int ifindex = batadv_netlink_get_ifindex(cb->nlh,
BATADV_ATTR_HARD_IFINDEX); if (!ifindex) return ERR_PTR(-ENONET);
/** * batadv_get_vlan_from_info() - Retrieve vlan from genl attributes * @bat_priv: the bat priv with all the mesh interface information * @net: the applicable net namespace * @info: receiver information * * Return: Pointer to vlan on success (with increased refcnt), error pointer * on error
*/ staticstruct batadv_meshif_vlan *
batadv_get_vlan_from_info(struct batadv_priv *bat_priv, struct net *net, struct genl_info *info)
{ struct batadv_meshif_vlan *vlan;
u16 vid;
if (!info->attrs[BATADV_ATTR_VLANID]) return ERR_PTR(-EINVAL);
vid = nla_get_u16(info->attrs[BATADV_ATTR_VLANID]);
vlan = batadv_meshif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG); if (!vlan) return ERR_PTR(-ENOENT);
return vlan;
}
/** * batadv_pre_doit() - Prepare batman-adv genl doit request * @ops: requested netlink operation * @skb: Netlink message with request data * @info: receiver information * * Return: 0 on success or negative error number in case of failure
*/ staticint batadv_pre_doit(conststruct genl_split_ops *ops, struct sk_buff *skb, struct genl_info *info)
{ struct net *net = genl_info_net(info); struct batadv_hard_iface *hard_iface; struct batadv_priv *bat_priv = NULL; struct batadv_meshif_vlan *vlan; struct net_device *mesh_iface;
u8 user_ptr1_flags;
u8 mesh_dep_flags; int ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.