/** * i40iw_inetaddr_event - system notifier for ipv4 addr events * @notfier: not used * @event: event for notifier * @ptr: if address */ int i40iw_inetaddr_event(struct notifier_block *notifier, unsigned long event, void *ptr) { struct in_ifaddr *ifa = ptr; struct net_device *event_netdev = ifa->ifa_dev->dev; struct net_device *netdev; struct net_device *upper_dev; struct i40iw_device *iwdev; struct i40iw_handler *hdl; u32 local_ipaddr; u32 action = I40IW_ARP_ADD; hdl = i40iw_find_netdev(event_netdev); if (!hdl) return NOTIFY_DONE; iwdev = &hdl->device; if (iwdev->init_state < IP_ADDR_REGISTERED || iwdev->closing) return NOTIFY_DONE; netdev = iwdev->ldev->netdev; upper_dev = netdev_master_upper_dev_get(netdev); if (netdev != event_netdev) return NOTIFY_DONE; if (upper_dev) { struct in_device *in; rcu_read_lock(); in = __in_dev_get_rcu(upper_dev); local_ipaddr = ntohl(in->ifa_list->ifa_address); rcu_read_unlock(); } else { local_ipaddr = ntohl(ifa->ifa_address); } switch (event) { case NETDEV_DOWN: action = I40IW_ARP_DELETE; /* Fall through */ case NETDEV_UP: /* Fall through */ case NETDEV_CHANGEADDR: i40iw_manage_arp_cache(iwdev, netdev->dev_addr, &local_ipaddr, true, action); i40iw_if_notify(iwdev, netdev, &local_ipaddr, true, (action == I40IW_ARP_ADD) ? true : false); break; default: break; } return NOTIFY_DONE; }
/** * i40iw_inet6addr_event - system notifier for ipv6 addr events * @notfier: not used * @event: event for notifier * @ptr: if address */ int i40iw_inet6addr_event(struct notifier_block *notifier, unsigned long event, void *ptr) { struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; struct net_device *event_netdev = ifa->idev->dev; struct net_device *netdev; struct i40iw_device *iwdev; struct i40iw_handler *hdl; u32 local_ipaddr6[4]; u32 action = I40IW_ARP_ADD; hdl = i40iw_find_netdev(event_netdev); if (!hdl) return NOTIFY_DONE; iwdev = &hdl->device; if (iwdev->init_state < IP_ADDR_REGISTERED || iwdev->closing) return NOTIFY_DONE; netdev = iwdev->ldev->netdev; if (netdev != event_netdev) return NOTIFY_DONE; i40iw_copy_ip_ntohl(local_ipaddr6, ifa->addr.in6_u.u6_addr32); switch (event) { case NETDEV_DOWN: action = I40IW_ARP_DELETE; /* Fall through */ case NETDEV_UP: /* Fall through */ case NETDEV_CHANGEADDR: i40iw_manage_arp_cache(iwdev, netdev->dev_addr, local_ipaddr6, false, action); i40iw_if_notify(iwdev, netdev, local_ipaddr6, false, (action == I40IW_ARP_ADD) ? true : false); break; default: break; } return NOTIFY_DONE; }