Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions bp_socket/af_bp.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,8 @@ int bp_sendmsg(struct socket* sock, struct msghdr* msg, size_t size)
goto err_free;
}

ret = send_bundle_doit((uintptr_t)sock->sk->sk_socket, payload,
size, node_id, service_id, 8443);
ret = send_bundle_doit(
payload, size, node_id, service_id, 8443);
if (ret < 0) {
pr_err(
"bp_sendmsg: send_bundle_doit failed (%d)\n", ret);
Expand Down Expand Up @@ -335,6 +335,13 @@ int bp_recvmsg(struct socket* sock, struct msghdr* msg, size_t size, int flags)
goto out;
}

ret = destroy_bundle_doit(bp->bp_node_id, bp->bp_service_id, 8443);
if (ret < 0) {
pr_err(
"destroy_bundle_doit failed (%d), will retry later", ret);
// enqueue_retry(bp->bp_node_id, bp->bp_service_id);
}

ret = skb->len;

out:
Expand Down
73 changes: 61 additions & 12 deletions bp_socket/bp_genl.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ struct genl_family genl_fam = {
.n_mcgrps = ARRAY_SIZE(genl_mcgrps),
};

int send_bundle_doit(u64 sockid, void* payload, int payload_size,
u_int32_t node_id, u_int32_t service_id, int port_id)
int send_bundle_doit(void* payload, int payload_size, u_int32_t node_id,
u_int32_t service_id, int port_id)
{
void* msg_head;
struct sk_buff* msg;
Expand All @@ -62,12 +62,6 @@ int send_bundle_doit(u64 sockid, void* payload, int payload_size,
goto err_free;
}

ret = nla_put_u64_64bit(msg, BP_GENL_A_SOCKID, sockid, 0);
if (ret) {
pr_err("send_bundle: failed to put SOCKID (%d)\n", ret);
goto err_cancel;
}

ret = nla_put_u32(msg, BP_GENL_A_NODE_ID, node_id);
if (ret) {
pr_err("send_bundle: failed to put NODE_ID (%d)\n", ret);
Expand Down Expand Up @@ -104,7 +98,7 @@ int request_bundle_doit(u_int32_t node_id, u_int32_t service_id, int port_id)
size_t msg_size;
int ret;

msg_size = nla_total_size(sizeof(u32));
msg_size = 2 * nla_total_size(sizeof(u_int32_t));
msg = genlmsg_new(msg_size, GFP_KERNEL);
if (!msg) {
pr_err("request_bundle: failed to allocate message buffer\n");
Expand All @@ -120,6 +114,12 @@ int request_bundle_doit(u_int32_t node_id, u_int32_t service_id, int port_id)
goto err_free;
}

ret = nla_put_u32(msg, BP_GENL_A_NODE_ID, node_id);
if (ret) {
pr_err("request_bundle: failed to put NODE_ID (%d)\n", ret);
goto err_cancel;
}

ret = nla_put_u32(msg, BP_GENL_A_SERVICE_ID, service_id);
if (ret) {
pr_err("request_bundle: failed to put SERVICE_ID (%d)\n", ret);
Expand All @@ -143,17 +143,19 @@ int deliver_bundle_doit(struct sk_buff* skb, struct genl_info* info)
struct bp_sock* bp;
struct sk_buff* new_skb;
bool new_skb_queued = false;
u_int32_t service_id;
u_int32_t node_id, service_id;
void* payload;
size_t payload_len;
int ret;

if (!info->attrs[BP_GENL_A_SERVICE_ID]
if (!info->attrs[BP_GENL_A_NODE_ID]
|| !info->attrs[BP_GENL_A_SERVICE_ID]
|| !info->attrs[BP_GENL_A_PAYLOAD]) {
pr_err("deliver_bundle: missing required attributes\n");
ret = -EINVAL;
goto out;
}
node_id = nla_get_u32(info->attrs[BP_GENL_A_NODE_ID]);
service_id = nla_get_u32(info->attrs[BP_GENL_A_SERVICE_ID]);
payload = nla_data(info->attrs[BP_GENL_A_PAYLOAD]);
payload_len = nla_len(info->attrs[BP_GENL_A_PAYLOAD]);
Expand All @@ -172,7 +174,8 @@ int deliver_bundle_doit(struct sk_buff* skb, struct genl_info* info)
bh_lock_sock(sk);
bp = bp_sk(sk);

if (bp->bp_service_id == service_id) {
if (bp->bp_node_id == node_id
&& bp->bp_service_id == service_id) {

skb_queue_tail(&bp->queue, new_skb);
new_skb_queued = true;
Expand All @@ -199,3 +202,49 @@ int deliver_bundle_doit(struct sk_buff* skb, struct genl_info* info)
out:
return ret;
}

int destroy_bundle_doit(u_int32_t node_id, u_int32_t service_id, int port_id)
{
void* msg_head;
struct sk_buff* msg;
size_t msg_size;
int ret;

msg_size = 2 * nla_total_size(sizeof(u_int32_t));
msg = genlmsg_new(msg_size, GFP_KERNEL);
if (!msg) {
pr_err("destroy_bundle: failed to allocate message buffer\n");
ret = -ENOMEM;
goto out;
}

msg_head
= genlmsg_put(msg, 0, 0, &genl_fam, 0, BP_GENL_CMD_DESTROY_BUNDLE);
if (!msg_head) {
pr_err("destroy_bundle: failed to create genetlink header\n");
ret = -EMSGSIZE;
goto err_free;
}

ret = nla_put_u32(msg, BP_GENL_A_NODE_ID, node_id);
if (ret) {
pr_err("destroy_bundle: failed to put NODE_ID (%d)\n", ret);
goto err_cancel;
}

ret = nla_put_u32(msg, BP_GENL_A_SERVICE_ID, service_id);
if (ret) {
pr_err("destroy_bundle: failed to put SERVICE_ID (%d)\n", ret);
goto err_cancel;
}

genlmsg_end(msg, msg_head);
return genlmsg_unicast(&init_net, msg, port_id);

err_cancel:
genlmsg_cancel(msg, msg_head);
err_free:
nlmsg_free(msg);
out:
return ret;
}
6 changes: 3 additions & 3 deletions bp_socket/bp_genl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

extern struct genl_family genl_fam;

int fail_doit(struct sk_buff* skb, struct genl_info* info);
int send_bundle_doit(u64 sockid, void* payload, int payload_size,
u_int32_t node_id, u_int32_t service_id, int port_id);
int send_bundle_doit(void* payload, int payload_size, u_int32_t node_id,
u_int32_t service_id, int port_id);
int deliver_bundle_doit(struct sk_buff* skb, struct genl_info* info);
int request_bundle_doit(u_int32_t node_id, u_int32_t service_id, int port_id);
int destroy_bundle_doit(u_int32_t node_id, u_int32_t service_id, int port_id);

#endif
36 changes: 23 additions & 13 deletions daemon/bp_genl.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
#include "log.h"

struct nl_sock *genl_bp_sock_init(Daemon *daemon) {
struct nl_sock *sk = nl_socket_alloc();
struct nl_sock *sk;
int family_id;
int err;

sk = nl_socket_alloc();
if (!sk) {
log_error("Failed to allocate Netlink socket");
log_error("Failed to allocate Netlink socket: %s", nl_geterror(-ENOMEM));
return NULL;
}

Expand All @@ -24,16 +28,16 @@ struct nl_sock *genl_bp_sock_init(Daemon *daemon) {
nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, genl_bp_sock_recvmsg_cb, daemon);
nl_socket_set_peer_port(sk, 0); // Send to kernel

int err = genl_connect(sk);
err = genl_connect(sk);
if (err < 0) {
log_error("genl_connect() failed: %s", nl_geterror(err));
log_error("Failed to connect to Generic Netlink: %s", nl_geterror(err));
nl_socket_free(sk);
return NULL;
}

int family_id = genl_ctrl_resolve(sk, daemon->genl_bp_family_name);
family_id = genl_ctrl_resolve(sk, daemon->genl_bp_family_name);
if (family_id < 0) {
log_error("Failed to resolve family '%s': %s", daemon->genl_bp_family_name,
log_error("Failed to resolve Generic Netlink family '%s': %s", daemon->genl_bp_family_name,
nl_geterror(family_id));
nl_socket_free(sk);
return NULL;
Expand All @@ -47,21 +51,23 @@ void genl_bp_sock_close(Daemon *daemon) {
if (!daemon->genl_bp_sock) return;

nl_socket_free(daemon->genl_bp_sock);
log_info("Netlink socket closed");

daemon->genl_bp_sock = NULL;
daemon->genl_bp_family_id = -1;

log_info("Generic Netlink socket closed");
}

int genl_bp_sock_recvmsg_cb(struct nl_msg *msg, void *arg) {
Daemon *daemon = (Daemon *)arg;
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *genlhdr = nlmsg_data(nlh);
struct nlattr *attrs[BP_GENL_A_MAX + 1];
int err;

int err = nla_parse(attrs, BP_GENL_A_MAX, genlmsg_attrdata(genlhdr, 0),
genlmsg_attrlen(genlhdr, 0), NULL);
if (err) {
log_error("Failed to parse message: %s", strerror(-err));
err = nla_parse(attrs, BP_GENL_A_MAX, genlmsg_attrdata(genlhdr, 0), genlmsg_attrlen(genlhdr, 0),
NULL);
if (err < 0) {
log_error("Failed to parse Netlink attributes: %s", strerror(-err));
return NL_SKIP;
}

Expand All @@ -70,8 +76,12 @@ int genl_bp_sock_recvmsg_cb(struct nl_msg *msg, void *arg) {
return handle_send_bundle(daemon, attrs);
case BP_GENL_CMD_REQUEST_BUNDLE:
return handle_request_bundle(daemon, attrs);
// case BP_GENL_CMD_DELIVER_BUNDLE:
// return handle_deliver_bundle_reply(daemon, attrs);
case BP_GENL_CMD_DESTROY_BUNDLE:
return handle_destroy_bundle(daemon, attrs);
default:
log_error("Unknown GENL command: %d", genlhdr->cmd);
log_error("Unknown Generic Netlink command: %d", genlhdr->cmd);
return NL_SKIP;
}
}
Loading