Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mctp-netlink: Add helpers to add or remove addrs and neighs #36

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
143 changes: 143 additions & 0 deletions src/mctp-netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,77 @@ static int linkmap_add_entry(mctp_nl *nl, struct ifinfomsg *info,
return 0;
}

/* Common parts of RTM_NEWADDR and RTM_DELADDR */
struct mctp_ifaddralter_msg {
struct nlmsghdr nh;
struct ifaddrmsg ifmsg;
struct rtattr rta;
uint8_t data[4];
};

static int fill_ifaddralter_args(struct mctp_nl *nl,
struct mctp_ifaddralter_msg *msg,
struct rtattr **prta, size_t *prta_len,
mctp_eid_t eid, const char *linkstr)
{
int ifindex;

ifindex = mctp_nl_ifindex_byname(nl, linkstr);
if (!ifindex) {
warnx("invalid device %s", linkstr);
return -1;
}

memset(msg, 0x0, sizeof(*msg));

msg->nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;

msg->ifmsg.ifa_index = ifindex;
msg->ifmsg.ifa_family = AF_MCTP;

msg->rta.rta_type = IFA_LOCAL;
msg->rta.rta_len = RTA_LENGTH(sizeof(eid));
memcpy(RTA_DATA(&msg->rta), &eid, sizeof(eid));

msg->nh.nlmsg_len =
NLMSG_LENGTH(sizeof(msg->ifmsg)) + RTA_SPACE(sizeof(eid));

if (prta)
*prta = &msg->rta;
if (prta_len)
*prta_len = msg->rta.rta_len;

return 0;
}

int mctp_nl_addr_add(struct mctp_nl *nl, mctp_eid_t eid, const char *linkstr)
{
struct mctp_ifaddralter_msg msg;
int rc;

rc = fill_ifaddralter_args(nl, &msg, NULL, NULL, eid, linkstr);
if (rc)
return -1;

msg.nh.nlmsg_type = RTM_NEWADDR;

return mctp_nl_send(nl, &msg.nh);
}

int mctp_nl_addr_del(struct mctp_nl *nl, mctp_eid_t eid, const char *linkstr)
{
struct mctp_ifaddralter_msg msg;
int rc;

rc = fill_ifaddralter_args(nl, &msg, NULL, NULL, eid, linkstr);
if (rc)
return -1;

msg.nh.nlmsg_type = RTM_DELADDR;

return mctp_nl_send(nl, &msg.nh);
}

/* Common parts of RTM_NEWROUTE and RTM_DELROUTE */
struct mctp_rtalter_msg {
struct nlmsghdr nh;
Expand Down Expand Up @@ -1163,3 +1234,75 @@ int mctp_nl_route_del(struct mctp_nl *nl, uint8_t eid, const char* ifname)
return mctp_nl_send(nl, &msg.nh);
}

/* Common parts of RTM_NEWNEIGH and RTM_DELNEIGH */
struct mctp_ndalter_msg {
struct nlmsghdr nh;
struct ndmsg ndmsg;
uint8_t rta_buff[RTA_SPACE(1) + RTA_SPACE(MAX_ADDR_LEN)];
};

static int fill_ndalter_args(struct mctp_nl *nl, struct mctp_ndalter_msg *msg,
struct rtattr **prta, size_t *prta_len,
mctp_eid_t eid, const char *ifname)
{
struct rtattr *rta;
size_t rta_len;
int ifindex;

ifindex = mctp_nl_ifindex_byname(nl, ifname);
if (!ifindex) {
warnx("invalid device %s", ifname);
return -1;
}

msg->nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
msg->ndmsg.ndm_ifindex = ifindex;
msg->ndmsg.ndm_family = AF_MCTP;
msg->nh.nlmsg_len = NLMSG_LENGTH(sizeof(msg->ndmsg));

rta_len = sizeof(msg->rta_buff);
rta = (void *)msg->rta_buff;

msg->nh.nlmsg_len += mctp_put_rtnlmsg_attr(&rta, &rta_len, NDA_DST,
&eid, sizeof(eid));

if (prta)
*prta = rta;
if (prta_len)
*prta_len = rta_len;

return 0;
}

int mctp_nl_neigh_add(struct mctp_nl *nl, uint8_t eid, const char *ifname,
uint8_t *haddr, uint8_t halen)
{
struct mctp_ndalter_msg msg;
struct rtattr *rta;
size_t rta_len;
int rc;

rc = fill_ndalter_args(nl, &msg, &rta, &rta_len, eid, ifname);
if (rc) {
return rc;
}
msg.nh.nlmsg_type = RTM_NEWNEIGH;
msg.nh.nlmsg_len +=
mctp_put_rtnlmsg_attr(&rta, &rta_len, NDA_LLADDR, haddr, halen);

return mctp_nl_send(nl, &msg.nh);
}

int mctp_nl_neigh_del(struct mctp_nl *nl, uint8_t eid, const char *ifname)
{
struct mctp_ndalter_msg msg;
int rc;

rc = fill_ndalter_args(nl, &msg, NULL, NULL, eid, ifname);
if (rc) {
return rc;
}
msg.nh.nlmsg_type = RTM_DELNEIGH;

return mctp_nl_send(nl, &msg.nh);
}
9 changes: 9 additions & 0 deletions src/mctp-netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,20 @@ int *mctp_nl_net_list(const mctp_nl *nl, size_t *ret_num_nets);
/* Returns an allocated list of ifindex, caller to free */
int *mctp_nl_if_list(const mctp_nl *nl, size_t *ret_num_if);

/* MCTP addr helper */
int mctp_nl_addr_add(struct mctp_nl *nl, uint8_t eid, const char *ifname);
int mctp_nl_addr_del(struct mctp_nl *nl, uint8_t eid, const char *ifname);

/* MCTP route helper */
int mctp_nl_route_add(struct mctp_nl *nl, uint8_t eid, const char* ifname,
uint32_t mtu);
int mctp_nl_route_del(struct mctp_nl *nl, uint8_t eid, const char* ifname);

/* MCTP neigh helper */
int mctp_nl_neigh_add(struct mctp_nl *nl, uint8_t eid, const char *ifname,
uint8_t *haddr, uint8_t halen);
int mctp_nl_neigh_del(struct mctp_nl *nl, uint8_t eid, const char *ifname);

/* Helpers */

void* mctp_get_rtnlmsg_attr(int rta_type, struct rtattr *rta, size_t len,
Expand Down
79 changes: 14 additions & 65 deletions src/mctp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1023,62 +1023,14 @@ static int cmd_neigh_show(struct ctx *ctx, int argc, const char **argv)
return 0;
}

struct mctp_neighalter_msg {
struct nlmsghdr nh;
struct ndmsg ndmsg;
uint8_t rta_buff[RTA_SPACE(1) + RTA_SPACE(MAX_ADDR_LEN)];
};

static int fill_neighalter_args(struct ctx *ctx,
struct mctp_neighalter_msg *msg,
struct rtattr **prta, size_t *prta_len,
const char *eidstr, const char *linkstr) {
struct rtattr *rta;
uint32_t tmp;
uint8_t eid;
int ifindex;
size_t rta_len;

ifindex = mctp_nl_ifindex_byname(ctx->nl, linkstr);
if (!ifindex) {
warnx("invalid device %s", linkstr);
return -1;
}

if (parse_uint32(eidstr, &tmp) < 0 || tmp > 0xff) {
warnx("invalid address %s", eidstr);
return -1;
}
eid = tmp & 0xff;

memset(msg, 0x0, sizeof(*msg));
msg->nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
msg->ndmsg.ndm_ifindex = ifindex;
msg->ndmsg.ndm_family = AF_MCTP;

msg->nh.nlmsg_len = NLMSG_LENGTH(sizeof(msg->ndmsg));
rta_len = sizeof(msg->rta_buff);
rta = (void*)msg->rta_buff;

msg->nh.nlmsg_len += mctp_put_rtnlmsg_attr(&rta, &rta_len,
NDA_DST, &eid, sizeof(eid));


if (prta)
*prta = rta;
if (prta_len)
*prta_len = rta_len;
return 0;
}

static int cmd_neigh_add(struct ctx *ctx, int argc, const char **argv)
{
struct mctp_neighalter_msg msg;
struct rtattr *rta;
const char *linkstr, *eidstr, *lladdrstr;
int rc;
uint8_t llbuf[MAX_ADDR_LEN];
size_t llbuf_len, rta_len;
size_t llbuf_len;
mctp_eid_t eid;
uint32_t tmp;
int rc;

rc = 0;
if (argc != 6) {
Expand Down Expand Up @@ -1107,22 +1059,20 @@ static int cmd_neigh_add(struct ctx *ctx, int argc, const char **argv)
return rc;
}

rc = fill_neighalter_args(ctx, &msg, &rta, &rta_len,
eidstr, linkstr);
if (rc) {
if (parse_uint32(eidstr, &tmp) < 0 || tmp > 0xff) {
warnx("invalid address %s", eidstr);
return -1;
}
eid = tmp & 0xff;

msg.nh.nlmsg_type = RTM_NEWNEIGH;
msg.nh.nlmsg_len += mctp_put_rtnlmsg_attr(&rta, &rta_len,
NDA_LLADDR, llbuf, llbuf_len);
return mctp_nl_send(ctx->nl, &msg.nh);
return mctp_nl_neigh_add(ctx->nl, eid, linkstr, llbuf, llbuf_len);
}

static int cmd_neigh_del(struct ctx *ctx, int argc, const char **argv)
{
struct mctp_neighalter_msg msg;
const char *linkstr, *eidstr;
mctp_eid_t eid;
uint32_t tmp;
int rc;

rc = 0;
Expand All @@ -1141,14 +1091,13 @@ static int cmd_neigh_del(struct ctx *ctx, int argc, const char **argv)
eidstr = argv[1];
linkstr = argv[3];

rc = fill_neighalter_args(ctx, &msg, NULL, NULL,
eidstr, linkstr);
if (rc) {
if (parse_uint32(eidstr, &tmp) < 0 || tmp > 0xff) {
warnx("invalid address %s", eidstr);
return -1;
}
eid = tmp & 0xff;

msg.nh.nlmsg_type = RTM_DELNEIGH;
return mctp_nl_send(ctx->nl, &msg.nh);
return mctp_nl_neigh_del(ctx->nl, eid, linkstr);
}

static int cmd_neigh(struct ctx *ctx, int argc, const char **argv) {
Expand Down
38 changes: 20 additions & 18 deletions src/mctpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2033,26 +2033,28 @@ static int query_peer_properties(peer *peer)
return rc;
}

// type is RTM_NEWNEIGH or RTM_DELNEIGH
static int peer_neigh_update(peer *peer, uint16_t type)
{
struct {
struct nlmsghdr nh;
struct ndmsg ndmsg;
uint8_t rta_buff[RTA_SPACE(1) + RTA_SPACE(MAX_ADDR_LEN)];
} msg = {0};
size_t rta_len = sizeof(msg.rta_buff);
struct rtattr *rta = (void*)msg.rta_buff;

msg.nh.nlmsg_type = type;
msg.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
msg.ndmsg.ndm_ifindex = peer->phys.ifindex;
msg.ndmsg.ndm_family = AF_MCTP;
msg.nh.nlmsg_len = NLMSG_LENGTH(sizeof(msg.ndmsg));
msg.nh.nlmsg_len += mctp_put_rtnlmsg_attr(&rta, &rta_len,
NDA_DST, &peer->eid, sizeof(peer->eid));
msg.nh.nlmsg_len += mctp_put_rtnlmsg_attr(&rta, &rta_len,
NDA_LLADDR, peer->phys.hwaddr, peer->phys.hwaddr_len);
return mctp_nl_send(peer->ctx->nl_query, &msg.nh);
const char *link;

link = mctp_nl_if_byindex(peer->ctx->nl_query, peer->phys.ifindex);
if (!link) {
warnx("BUG %s: Unknown ifindex %d", __func__,
peer->phys.ifindex);
return -ENODEV;
}

if (type == RTM_NEWNEIGH) {
return mctp_nl_neigh_add(peer->ctx->nl_query, peer->eid, link,
peer->phys.hwaddr,
peer->phys.hwaddr_len);
} else if (type == RTM_DELNEIGH) {
return mctp_nl_neigh_del(peer->ctx->nl_query, peer->eid, link);
}

warnx("BUG %s: bad type %d", __func__, type);
return -EPROTO;
}

// type is RTM_NEWROUTE or RTM_DELROUTE
Expand Down