diff options
Diffstat (limited to 'src/ip6-manager/nm-ip6-manager.c')
| -rw-r--r-- | src/ip6-manager/nm-ip6-manager.c | 56 |
1 files changed, 24 insertions, 32 deletions
diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c index 490e9574..c2871e4a 100644 --- a/src/ip6-manager/nm-ip6-manager.c +++ b/src/ip6-manager/nm-ip6-manager.c @@ -93,6 +93,11 @@ typedef struct { NMIP6Manager *manager; char *iface; int ifindex; + /* +7 since this field is used directly by stuff that expects + * padding to multiples of 8 bytes. + */ + guint8 hwaddr[NM_UTILS_HWADDR_LEN_MAX + 7]; + guint hwaddr_len; gboolean has_linklocal; gboolean has_nonlinklocal; @@ -164,12 +169,18 @@ nm_ip6_device_destroy (NMIP6Device *device) } static NMIP6Device * -nm_ip6_device_new (NMIP6Manager *manager, int ifindex) +nm_ip6_device_new (NMIP6Manager *manager, + int ifindex, + const guint8 *hwaddr, + guint hwaddr_len) { NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); NMIP6Device *device; g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail (hwaddr != NULL, NULL); + g_return_val_if_fail (hwaddr_len > 0, NULL); + g_return_val_if_fail (hwaddr_len <= NM_UTILS_HWADDR_LEN_MAX, NULL); device = g_slice_new0 (NMIP6Device); if (!device) { @@ -186,6 +197,9 @@ nm_ip6_device_new (NMIP6Manager *manager, int ifindex) goto error; } + memcpy (device->hwaddr, hwaddr, hwaddr_len); + device->hwaddr_len = hwaddr_len; + device->manager = manager; device->rdnss_servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS)); @@ -222,28 +236,6 @@ nm_ip6_manager_get_device (NMIP6Manager *manager, int ifindex) return g_hash_table_lookup (priv->devices, GINT_TO_POINTER (ifindex)); } -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; -} - static void device_send_router_solicitation (NMIP6Device *device, const char *why) { @@ -251,8 +243,6 @@ device_send_router_solicitation (NMIP6Device *device, const char *why) struct sockaddr_in6 sin6; struct nd_router_solicit rs; struct nd_opt_hdr lladdr_hdr; - guint8 hwaddr[NM_UTILS_HWADDR_LEN_MAX + 7]; - int hwaddr_len; static const guint8 local_routers_addr[] = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; @@ -301,18 +291,15 @@ device_send_router_solicitation (NMIP6Device *device, const char *why) iov[0].iov_len = sizeof (rs); iov[0].iov_base = &rs; - memset (hwaddr, 0, sizeof (hwaddr)); - hwaddr_len = get_hwaddr (device->ifindex, hwaddr); - - if (hwaddr_len > 0) { + if (device->hwaddr_len > 0) { memset (&lladdr_hdr, 0, sizeof (lladdr_hdr)); lladdr_hdr.nd_opt_type = ND_OPT_SOURCE_LINKADDR; - lladdr_hdr.nd_opt_len = (sizeof (lladdr_hdr) + hwaddr_len + 7) % 8; + lladdr_hdr.nd_opt_len = (sizeof (lladdr_hdr) + device->hwaddr_len + 7) % 8; iov[1].iov_len = sizeof (lladdr_hdr); iov[1].iov_base = &lladdr_hdr; iov[2].iov_len = (lladdr_hdr.nd_opt_len * 8) - 2; - iov[2].iov_base = hwaddr; + iov[2].iov_base = device->hwaddr; mhdr.msg_iovlen = 3; } else @@ -1372,6 +1359,8 @@ netlink_notification (NMNetlinkMonitor *monitor, struct nl_msg *msg, gpointer us gboolean nm_ip6_manager_prepare_interface (NMIP6Manager *manager, int ifindex, + const guint8 *hwaddr, + guint hwaddr_len, NMSettingIP6Config *s_ip6, const char *accept_ra_path) { @@ -1381,10 +1370,13 @@ nm_ip6_manager_prepare_interface (NMIP6Manager *manager, g_return_val_if_fail (NM_IS_IP6_MANAGER (manager), FALSE); g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (hwaddr != NULL, FALSE); + g_return_val_if_fail (hwaddr_len > 0, FALSE); + g_return_val_if_fail (hwaddr_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE); priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - device = nm_ip6_device_new (manager, ifindex); + device = nm_ip6_device_new (manager, ifindex, hwaddr, hwaddr_len); g_return_val_if_fail (device != NULL, FALSE); g_return_val_if_fail ( strchr (device->iface, '/') == NULL && strcmp (device->iface, "all") != 0 |