pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/42443?usp=email )
Change subject: netdev: Add API osmo_netdev_del_addr() ......................................................................
netdev: Add API osmo_netdev_del_addr()
Change-Id: I75153eb59e96a6a2505dc5b29432c76e5c21ea24 --- M TODO-RELEASE M include/osmocom/core/netdev.h M src/core/libosmocore.map M src/core/netdev.c 4 files changed, 80 insertions(+), 0 deletions(-)
Approvals: Jenkins Builder: Verified fixeria: Looks good to me, but someone else must approve osmith: Looks good to me, approved
diff --git a/TODO-RELEASE b/TODO-RELEASE index 0ed7189..ee01c5b 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -7,3 +7,4 @@ # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line +core add osmo_netdev_del_addr() diff --git a/include/osmocom/core/netdev.h b/include/osmocom/core/netdev.h index 4d505fe..33dc4ec 100644 --- a/include/osmocom/core/netdev.h +++ b/include/osmocom/core/netdev.h @@ -42,6 +42,8 @@ void osmo_netdev_set_mtu_chg_cb(struct osmo_netdev *netdev, osmo_netdev_mtu_chg_cb_t mtu_chg_cb);
int osmo_netdev_add_addr(struct osmo_netdev *netdev, const struct osmo_sockaddr *addr, uint8_t prefixlen); +int osmo_netdev_del_addr(struct osmo_netdev *netdev, const struct osmo_sockaddr *addr, uint8_t prefixlen); + int osmo_netdev_add_route(struct osmo_netdev *netdev, const struct osmo_sockaddr *dst_addr, uint8_t dst_prefixlen, const struct osmo_sockaddr *gw_addr); int osmo_netdev_ifupdown(struct osmo_netdev *netdev, bool ifupdown); diff --git a/src/core/libosmocore.map b/src/core/libosmocore.map index 06a9009..0cb696b 100644 --- a/src/core/libosmocore.map +++ b/src/core/libosmocore.map @@ -323,6 +323,7 @@ osmo_netdev_add_addr; osmo_netdev_add_route; osmo_netdev_alloc; +osmo_netdev_del_addr; osmo_netdev_free; osmo_netdev_get_dev_name; osmo_netdev_get_ifindex; diff --git a/src/core/netdev.c b/src/core/netdev.c index be7ad2e..d9bc797 100644 --- a/src/core/netdev.c +++ b/src/core/netdev.c @@ -606,6 +606,50 @@ return 0; }
+static int netdev_mnl_del_addr(struct osmo_mnl *omnl, unsigned int if_index, const struct osmo_sockaddr *osa, uint8_t prefix) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); + struct ifaddrmsg *ifm; + + nlh->nlmsg_type = RTM_DELADDR; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE | NLM_F_ACK; + nlh->nlmsg_seq = (uint32_t)time(NULL); + + ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); + ifm->ifa_family = osa->u.sa.sa_family; + ifm->ifa_prefixlen = prefix; + ifm->ifa_flags = IFA_F_PERMANENT; + ifm->ifa_scope = RT_SCOPE_UNIVERSE; + ifm->ifa_index = if_index; + + /* + * The exact meaning of IFA_LOCAL and IFA_ADDRESS depend + * on the address family being used and the device type. + * For broadcast devices (like the interfaces we use), + * for IPv4 we specify both and they are used interchangeably. + * For IPv6, only IFA_ADDRESS needs to be set. + */ + switch (osa->u.sa.sa_family) { + case AF_INET: + mnl_attr_put_u32(nlh, IFA_LOCAL, osa->u.sin.sin_addr.s_addr); + mnl_attr_put_u32(nlh, IFA_ADDRESS, osa->u.sin.sin_addr.s_addr); + break; + case AF_INET6: + mnl_attr_put(nlh, IFA_ADDRESS, sizeof(struct in6_addr), &osa->u.sin6.sin6_addr); + break; + default: + return -EINVAL; + } + + if (mnl_socket_sendto(omnl->mnls, nlh, nlh->nlmsg_len) < 0) { + LOGP(DLGLOBAL, LOGL_ERROR, "mnl_socket_sendto\n"); + return -EIO; + } + + return 0; +} + static int netdev_mnl_add_route(struct osmo_mnl *omnl, unsigned int if_index, const struct osmo_sockaddr *dst_osa, @@ -983,6 +1027,38 @@ return rc; }
+/*! Remove IP address from netdev interface + * \param[in] netdev The netdev object managing the netdev interface + * \param[in] addr The local address to remove from the interface + * \param[in] prefixlen The network prefix of addr + * \returns 0 on succes; negative on error. + */ +int osmo_netdev_del_addr(struct osmo_netdev *netdev, const struct osmo_sockaddr *addr, uint8_t prefixlen) +{ + struct osmo_netns_switch_state switch_state; + char buf[INET6_ADDRSTRLEN]; + int rc; + + if (!netdev->registered) + return -ENODEV; + + LOGNETDEV(netdev, LOGL_NOTICE, "Deleting address %s/%u from dev %s\n", + osmo_sockaddr_ntop(&addr->u.sa, buf), prefixlen, netdev->dev_name); + + NETDEV_NETNS_ENTER(netdev, &switch_state, "Delete address"); + +#if ENABLE_LIBMNL + rc = netdev_mnl_del_addr(netdev->netns_ctx->omnl, netdev->ifindex, addr, prefixlen); +#else + LOGNETDEV(netdev, LOGL_ERROR, "%s: NOT SUPPORTED. Build libosmocore with --enable-libmnl.\n", __func__); + rc = -ENOTSUP; +#endif + + NETDEV_NETNS_EXIT(netdev, &switch_state, "Delete address"); + + return rc; +} + /*! Add IP route to netdev interface * \param[in] netdev The netdev object managing the netdev interface * \param[in] dst_addr The destination address of the route