void netlink_neigh_info::fill(struct rtnl_neigh* neigh) { if (!neigh) return; nl_addr* addr; char addr_str[ADDR_MAX_STR_LEN + 1]; addr = rtnl_neigh_get_dst(neigh); if (addr) { dst_addr_str = nl_addr2str(addr, addr_str, ADDR_MAX_STR_LEN); dst_addr = (unsigned char*)nl_addr_get_binary_addr(addr); dst_addr_len = nl_addr_get_len(addr); } addr = rtnl_neigh_get_lladdr(neigh); if (addr) { lladdr_str = nl_addr2str(addr, addr_str, ADDR_MAX_STR_LEN); lladdr = (unsigned char*)nl_addr_get_binary_addr(addr); lladdr_len = nl_addr_get_len(addr); } //addr_family = rtnl_neigh_get_family(neigh); flags = rtnl_neigh_get_flags(neigh); ifindex = rtnl_neigh_get_ifindex(neigh); state = rtnl_neigh_get_state(neigh); type = rtnl_neigh_get_type(neigh); }
static void find_one_address (struct nl_object *object, void *user_data) { FindAddrInfo *info = user_data; struct rtnl_addr *addr = (struct rtnl_addr *) object; struct nl_addr *local; void *binaddr; if (info->found) return; if (rtnl_addr_get_ifindex (addr) != info->ifindex) return; if (rtnl_addr_get_family (addr) != info->family) return; if (rtnl_addr_get_prefixlen (addr) != info->prefix) return; local = rtnl_addr_get_local (addr); if (nl_addr_get_family (local) != info->family) return; if (nl_addr_get_len (local) != info->addrlen) return; binaddr = nl_addr_get_binary_addr (local); if (binaddr) { if (memcmp (binaddr, info->addr, info->addrlen) == 0) info->found = TRUE; /* Yay, found it */ } }
void nl_bridge::add_neigh_to_fdb(rtnl_neigh *neigh) { assert(sw); assert(neigh); uint32_t port = nl->get_port_id(rtnl_neigh_get_ifindex(neigh)); if (port == 0) { VLOG(1) << __FUNCTION__ << ": unknown port for neigh " << OBJ_CAST(neigh); return; } nl_addr *mac = rtnl_neigh_get_lladdr(neigh); int vlan = rtnl_neigh_get_vlan(neigh); bool permanent = true; // for sure this is master (sw bridged) if (rtnl_neigh_get_master(neigh) && !(rtnl_neigh_get_flags(neigh) & NTF_MASTER)) { rtnl_neigh_set_flags(neigh, NTF_MASTER); } // check if entry already exists in cache if (is_mac_in_l2_cache(neigh)) { permanent = false; } rofl::caddress_ll _mac((uint8_t *)nl_addr_get_binary_addr(mac), nl_addr_get_len(mac)); LOG(INFO) << __FUNCTION__ << ": add mac=" << _mac << " to bridge " << rtnl_link_get_name(bridge) << " on port=" << port << " vlan=" << (unsigned)vlan << ", permanent=" << permanent; LOG(INFO) << __FUNCTION__ << ": object: " << OBJ_CAST(neigh); sw->l2_addr_add(port, vlan, _mac, true, permanent); }
static Option<net::IP> IP(nl_addr* _ip) { Option<net::IP> result; if (_ip != NULL && nl_addr_get_len(_ip) != 0) { struct in_addr* addr = (struct in_addr*) nl_addr_get_binary_addr(_ip); result = net::IP(*addr); } return result; }
static void update_hw_address (NMDevice *dev) { NMDeviceWired *self = NM_DEVICE_WIRED (dev); NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self); struct rtnl_link *rtnl; struct nl_addr *addr; rtnl = nm_netlink_index_to_rtnl_link (nm_device_get_ip_ifindex (dev)); if (!rtnl) { nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev), "(%s) failed to read hardware address (error %d)", nm_device_get_iface (dev), errno); return; } addr = rtnl_link_get_addr (rtnl); if (!addr) { nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev), "(%s) no hardware address?", nm_device_get_iface (dev)); rtnl_link_put (rtnl); return; } if (nl_addr_get_len (addr) != priv->hw_addr_len) { nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev), "(%s) hardware address is wrong length (expected %d got %d)", nm_device_get_iface (dev), priv->hw_addr_len, nl_addr_get_len (addr)); } else { memcpy (&priv->hw_addr, nl_addr_get_binary_addr (addr), priv->hw_addr_len); } rtnl_link_put (rtnl); }
/** * Set IPv6 tokenized interface identifier * @arg link Link object * @arg token Tokenized interface identifier * * Sets the link's IPv6 tokenized interface identifier. * * @return 0 on success * @return -NLE_NOMEM could not allocate inet6 data * @return -NLE_INVAL addr is not a valid inet6 address */ int rtnl_link_inet6_set_token(struct rtnl_link *link, struct nl_addr *addr) { struct inet6_data *id; if ((nl_addr_get_family(addr) != AF_INET6) || (nl_addr_get_len(addr) != sizeof(id->i6_token))) return -NLE_INVAL; if (!(id = rtnl_link_af_alloc(link, &inet6_ops))) return -NLE_NOMEM; memcpy(&id->i6_token, nl_addr_get_binary_addr(addr), sizeof(id->i6_token)); return 0; }
static int get_hwaddr (int ifindex, guint8 *buf) { struct rtnl_link *lk; struct nl_addr *addr; int len; lk = nm_netlink_index_to_rtnl_link (ifindex); if (!lk) return -1; addr = rtnl_link_get_addr (lk); len = nl_addr_get_len (addr); if (len > NM_UTILS_HWADDR_LEN_MAX) len = -1; else memcpy (buf, nl_addr_get_binary_addr (addr), len); rtnl_link_put (lk); return len; }
int xfrmnl_ae_build_get_request(struct nl_addr* daddr, unsigned int spi, unsigned int protocol, unsigned int mark_mask, unsigned int mark_value, struct nl_msg **result) { struct nl_msg *msg; struct xfrm_aevent_id ae_id; struct xfrmnl_mark mark; if (!daddr || !spi) { fprintf(stderr, "APPLICATION BUG: %s:%d:%s: A valid destination address, spi must be specified\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); assert(0); return -NLE_MISSING_ATTR; } memset(&ae_id, 0, sizeof(ae_id)); memcpy (&ae_id.sa_id.daddr, nl_addr_get_binary_addr (daddr), sizeof (uint8_t) * nl_addr_get_len (daddr)); ae_id.sa_id.spi = htonl(spi); ae_id.sa_id.family = nl_addr_get_family (daddr); ae_id.sa_id.proto = protocol; if (!(msg = nlmsg_alloc_simple(XFRM_MSG_GETAE, 0))) return -NLE_NOMEM; if (nlmsg_append(msg, &ae_id, sizeof(ae_id), NLMSG_ALIGNTO) < 0) goto nla_put_failure; mark.m = mark_mask; mark.v = mark_value; NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrmnl_mark), &mark); *result = msg; return 0; nla_put_failure: nlmsg_free(msg); return -NLE_MSGSIZE; }
void nl_bridge::remove_neigh_from_fdb(rtnl_neigh *neigh) { assert(sw); nl_addr *addr = rtnl_neigh_get_lladdr(neigh); if (nl_addr_cmp(rtnl_link_get_addr(bridge), addr) == 0) { // ignore ll addr of bridge on slave return; } // lookup l2_cache as well std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> n_lookup( NEIGH_CAST(nl_cache_search(l2_cache.get(), OBJ_CAST(neigh))), rtnl_neigh_put); if (n_lookup) { nl_cache_remove(OBJ_CAST(n_lookup.get())); } const uint32_t port = nl->get_port_id(rtnl_neigh_get_ifindex(neigh)); rofl::caddress_ll mac((uint8_t *)nl_addr_get_binary_addr(addr), nl_addr_get_len(addr)); sw->l2_addr_remove(port, rtnl_neigh_get_vlan(neigh), mac); }
bool TNlAddr::IsHost() const { return Addr && nl_addr_get_prefixlen(Addr) == nl_addr_get_len(Addr) * 8; }
TError TNlLink::AddXVlan(const std::string &vlantype, const std::string &master, uint32_t type, const std::string &hw, int mtu) { TError error = TError::Success(); int ret; uint32_t masterIdx; struct nl_msg *msg; struct nlattr *linkinfo, *infodata; struct ifinfomsg ifi = { 0 }; struct ether_addr *ea = nullptr; auto Name = GetName(); if (hw.length()) { // FIXME THREADS ea = ether_aton(hw.c_str()); if (!ea) return TError(EError::Unknown, "Invalid " + vlantype + " mac address " + hw); } TNlLink masterLink(Nl, master); error = masterLink.Load(); if (error) return error; masterIdx = masterLink.GetIndex(); msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_CREATE); if (!msg) return TError(EError::Unknown, "Unable to add " + vlantype + ": no memory"); ret = nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO); if (ret < 0) { error = TError(EError::Unknown, "Unable to add " + vlantype + ": " + nl_geterror(ret)); goto free_msg; } /* link configuration */ ret = nla_put(msg, IFLA_LINK, sizeof(uint32_t), &masterIdx); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_LINK: ") + nl_geterror(ret)); goto free_msg; } ret = nla_put(msg, IFLA_IFNAME, Name.length() + 1, Name.c_str()); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_IFNAME: ") + nl_geterror(ret)); goto free_msg; } if (mtu > 0) { ret = nla_put(msg, IFLA_MTU, sizeof(int), &mtu); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_MTU: ") + nl_geterror(ret)); goto free_msg; } } if (ea) { struct nl_addr *addr = nl_addr_build(AF_LLC, ea, ETH_ALEN); ret = nla_put(msg, IFLA_ADDRESS, nl_addr_get_len(addr), nl_addr_get_binary_addr(addr)); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_ADDRESS: ") + nl_geterror(ret)); goto free_msg; } nl_addr_put(addr); } /* link type */ linkinfo = nla_nest_start(msg, IFLA_LINKINFO); if (!linkinfo) { error = TError(EError::Unknown, "Unable to add " + vlantype + ": can't nest IFLA_LINKINFO"); goto free_msg; } ret = nla_put(msg, IFLA_INFO_KIND, vlantype.length() + 1, vlantype.c_str()); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_INFO_KIND: ") + nl_geterror(ret)); goto free_msg; } /* xvlan specific */ infodata = nla_nest_start(msg, IFLA_INFO_DATA); if (!infodata) { error = TError(EError::Unknown, "Unable to add " + vlantype + ": can't nest IFLA_INFO_DATA"); goto free_msg; } if (vlantype == "macvlan") { ret = nla_put(msg, IFLA_MACVLAN_MODE, sizeof(uint32_t), &type); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_MACVLAN_MODE: ") + nl_geterror(ret)); goto free_msg; } #ifdef IFLA_IPVLAN_MAX } else if (vlantype == "ipvlan") { uint16_t mode = type; ret = nla_put(msg, IFLA_IPVLAN_MODE, sizeof(uint16_t), &mode); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_IPVLAN_MODE: ") + nl_geterror(ret)); goto free_msg; } #endif } nla_nest_end(msg, infodata); nla_nest_end(msg, linkinfo); L() << "netlink: add " << vlantype << " " << Name << " master " << master << " type " << type << " hw " << hw << " mtu " << mtu << std::endl; ret = nl_send_sync(GetSock(), msg); if (ret) return Error(ret, "Cannot add " + vlantype); return Load(); free_msg: nlmsg_free(msg); return error; }
static int build_xfrm_ae_message(struct xfrmnl_ae *tmpl, int cmd, int flags, struct nl_msg **result) { struct nl_msg* msg; struct xfrm_aevent_id ae_id; if (!(tmpl->ce_mask & XFRM_AE_ATTR_DADDR) || !(tmpl->ce_mask & XFRM_AE_ATTR_SPI) || !(tmpl->ce_mask & XFRM_AE_ATTR_PROTO)) return -NLE_MISSING_ATTR; memcpy (&ae_id.sa_id.daddr, nl_addr_get_binary_addr (tmpl->sa_id.daddr), sizeof (uint8_t) * nl_addr_get_len (tmpl->sa_id.daddr)); ae_id.sa_id.spi = htonl(tmpl->sa_id.spi); ae_id.sa_id.family = tmpl->sa_id.family; ae_id.sa_id.proto = tmpl->sa_id.proto; if (tmpl->ce_mask & XFRM_AE_ATTR_SADDR) memcpy (&ae_id.saddr, nl_addr_get_binary_addr (tmpl->saddr), sizeof (uint8_t) * nl_addr_get_len (tmpl->saddr)); if (tmpl->ce_mask & XFRM_AE_ATTR_FLAGS) ae_id.flags = tmpl->flags; if (tmpl->ce_mask & XFRM_AE_ATTR_REQID) ae_id.reqid = tmpl->reqid; msg = nlmsg_alloc_simple(cmd, flags); if (!msg) return -NLE_NOMEM; if (nlmsg_append(msg, &ae_id, sizeof(ae_id), NLMSG_ALIGNTO) < 0) goto nla_put_failure; if (tmpl->ce_mask & XFRM_AE_ATTR_MARK) NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrmnl_mark), &tmpl->mark); if (tmpl->ce_mask & XFRM_AE_ATTR_LIFETIME) NLA_PUT (msg, XFRMA_LTIME_VAL, sizeof (struct xfrmnl_lifetime_cur), &tmpl->lifetime_cur); if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_MAXAGE) NLA_PUT_U32 (msg, XFRMA_ETIMER_THRESH, tmpl->replay_maxage); if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_MAXDIFF) NLA_PUT_U32 (msg, XFRMA_REPLAY_THRESH, tmpl->replay_maxdiff); if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_STATE) { if (tmpl->replay_state_esn) { uint32_t len = sizeof (struct xfrm_replay_state_esn) + (sizeof (uint32_t) * tmpl->replay_state_esn->bmp_len); NLA_PUT (msg, XFRMA_REPLAY_ESN_VAL, len, tmpl->replay_state_esn); } else { NLA_PUT (msg, XFRMA_REPLAY_VAL, sizeof (struct xfrmnl_replay_state), &tmpl->replay_state); } } *result = msg; return 0; nla_put_failure: nlmsg_free(msg); return -NLE_MSGSIZE; }