diff --git a/src/mctp-netlink.c b/src/mctp-netlink.c index 56f620d..74a84af 100644 --- a/src/mctp-netlink.c +++ b/src/mctp-netlink.c @@ -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; @@ -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); +} diff --git a/src/mctp-netlink.h b/src/mctp-netlink.h index 31ee6b6..1d02c75 100644 --- a/src/mctp-netlink.h +++ b/src/mctp-netlink.h @@ -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, diff --git a/src/mctp.c b/src/mctp.c index c136e21..6bee883 100644 --- a/src/mctp.c +++ b/src/mctp.c @@ -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) { @@ -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; @@ -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) { diff --git a/src/mctpd.c b/src/mctpd.c index db6f4f2..1abf133 100644 --- a/src/mctpd.c +++ b/src/mctpd.c @@ -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