addrconf.c (6ecf4c37eb3e89b0832c9616089a5cdca3747da7) | addrconf.c (203651b665f72ba765fc4721842a471f8e9e5739) |
---|---|
1/* 2 * IPv6 Address [auto]configuration 3 * Linux INET6 implementation 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 8 * --- 4780 unchanged lines hidden (view full) --- 4789 return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) 4790 + nla_total_size(16) /* IFA_LOCAL */ 4791 + nla_total_size(16) /* IFA_ADDRESS */ 4792 + nla_total_size(sizeof(struct ifa_cacheinfo)) 4793 + nla_total_size(4) /* IFA_FLAGS */ 4794 + nla_total_size(4) /* IFA_RT_PRIORITY */; 4795} 4796 | 1/* 2 * IPv6 Address [auto]configuration 3 * Linux INET6 implementation 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 8 * --- 4780 unchanged lines hidden (view full) --- 4789 return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) 4790 + nla_total_size(16) /* IFA_LOCAL */ 4791 + nla_total_size(16) /* IFA_ADDRESS */ 4792 + nla_total_size(sizeof(struct ifa_cacheinfo)) 4793 + nla_total_size(4) /* IFA_FLAGS */ 4794 + nla_total_size(4) /* IFA_RT_PRIORITY */; 4795} 4796 |
4797struct inet6_fill_args { 4798 u32 portid; 4799 u32 seq; 4800 int event; 4801 unsigned int flags; 4802 int netnsid; 4803}; 4804 |
|
4797static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | 4805static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, |
4798 u32 portid, u32 seq, int event, unsigned int flags, 4799 int netnsid) | 4806 struct inet6_fill_args *args) |
4800{ 4801 struct nlmsghdr *nlh; 4802 u32 preferred, valid; 4803 | 4807{ 4808 struct nlmsghdr *nlh; 4809 u32 preferred, valid; 4810 |
4804 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags); | 4811 nlh = nlmsg_put(skb, args->portid, args->seq, args->event, 4812 sizeof(struct ifaddrmsg), args->flags); |
4805 if (!nlh) 4806 return -EMSGSIZE; 4807 4808 put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope), 4809 ifa->idev->dev->ifindex); 4810 | 4813 if (!nlh) 4814 return -EMSGSIZE; 4815 4816 put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope), 4817 ifa->idev->dev->ifindex); 4818 |
4811 if (netnsid >= 0 && nla_put_s32(skb, IFA_TARGET_NETNSID, netnsid)) | 4819 if (args->netnsid >= 0 && 4820 nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid)) |
4812 goto error; 4813 4814 if (!((ifa->flags&IFA_F_PERMANENT) && 4815 (ifa->prefered_lft == INFINITY_LIFE_TIME))) { 4816 preferred = ifa->prefered_lft; 4817 valid = ifa->valid_lft; 4818 if (preferred != INFINITY_LIFE_TIME) { 4819 long tval = (jiffies - ifa->tstamp)/HZ; --- 35 unchanged lines hidden (view full) --- 4855 return 0; 4856 4857error: 4858 nlmsg_cancel(skb, nlh); 4859 return -EMSGSIZE; 4860} 4861 4862static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, | 4821 goto error; 4822 4823 if (!((ifa->flags&IFA_F_PERMANENT) && 4824 (ifa->prefered_lft == INFINITY_LIFE_TIME))) { 4825 preferred = ifa->prefered_lft; 4826 valid = ifa->valid_lft; 4827 if (preferred != INFINITY_LIFE_TIME) { 4828 long tval = (jiffies - ifa->tstamp)/HZ; --- 35 unchanged lines hidden (view full) --- 4864 return 0; 4865 4866error: 4867 nlmsg_cancel(skb, nlh); 4868 return -EMSGSIZE; 4869} 4870 4871static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, |
4863 u32 portid, u32 seq, int event, u16 flags, 4864 int netnsid) | 4872 struct inet6_fill_args *args) |
4865{ 4866 struct nlmsghdr *nlh; 4867 u8 scope = RT_SCOPE_UNIVERSE; 4868 int ifindex = ifmca->idev->dev->ifindex; 4869 4870 if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE) 4871 scope = RT_SCOPE_SITE; 4872 | 4873{ 4874 struct nlmsghdr *nlh; 4875 u8 scope = RT_SCOPE_UNIVERSE; 4876 int ifindex = ifmca->idev->dev->ifindex; 4877 4878 if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE) 4879 scope = RT_SCOPE_SITE; 4880 |
4873 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags); | 4881 nlh = nlmsg_put(skb, args->portid, args->seq, args->event, 4882 sizeof(struct ifaddrmsg), args->flags); |
4874 if (!nlh) 4875 return -EMSGSIZE; 4876 | 4883 if (!nlh) 4884 return -EMSGSIZE; 4885 |
4877 if (netnsid >= 0 && nla_put_s32(skb, IFA_TARGET_NETNSID, netnsid)) | 4886 if (args->netnsid >= 0 && 4887 nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid)) |
4878 return -EMSGSIZE; 4879 4880 put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); 4881 if (nla_put_in6_addr(skb, IFA_MULTICAST, &ifmca->mca_addr) < 0 || 4882 put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp, 4883 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) { 4884 nlmsg_cancel(skb, nlh); 4885 return -EMSGSIZE; 4886 } 4887 4888 nlmsg_end(skb, nlh); 4889 return 0; 4890} 4891 4892static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, | 4888 return -EMSGSIZE; 4889 4890 put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); 4891 if (nla_put_in6_addr(skb, IFA_MULTICAST, &ifmca->mca_addr) < 0 || 4892 put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp, 4893 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) { 4894 nlmsg_cancel(skb, nlh); 4895 return -EMSGSIZE; 4896 } 4897 4898 nlmsg_end(skb, nlh); 4899 return 0; 4900} 4901 4902static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, |
4893 u32 portid, u32 seq, int event, 4894 unsigned int flags, int netnsid) | 4903 struct inet6_fill_args *args) |
4895{ 4896 struct net_device *dev = fib6_info_nh_dev(ifaca->aca_rt); 4897 int ifindex = dev ? dev->ifindex : 1; 4898 struct nlmsghdr *nlh; 4899 u8 scope = RT_SCOPE_UNIVERSE; 4900 4901 if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE) 4902 scope = RT_SCOPE_SITE; 4903 | 4904{ 4905 struct net_device *dev = fib6_info_nh_dev(ifaca->aca_rt); 4906 int ifindex = dev ? dev->ifindex : 1; 4907 struct nlmsghdr *nlh; 4908 u8 scope = RT_SCOPE_UNIVERSE; 4909 4910 if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE) 4911 scope = RT_SCOPE_SITE; 4912 |
4904 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct ifaddrmsg), flags); | 4913 nlh = nlmsg_put(skb, args->portid, args->seq, args->event, 4914 sizeof(struct ifaddrmsg), args->flags); |
4905 if (!nlh) 4906 return -EMSGSIZE; 4907 | 4915 if (!nlh) 4916 return -EMSGSIZE; 4917 |
4908 if (netnsid >= 0 && nla_put_s32(skb, IFA_TARGET_NETNSID, netnsid)) | 4918 if (args->netnsid >= 0 && 4919 nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid)) |
4909 return -EMSGSIZE; 4910 4911 put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); 4912 if (nla_put_in6_addr(skb, IFA_ANYCAST, &ifaca->aca_addr) < 0 || 4913 put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp, 4914 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) { 4915 nlmsg_cancel(skb, nlh); 4916 return -EMSGSIZE; --- 9 unchanged lines hidden (view full) --- 4926 ANYCAST_ADDR, 4927}; 4928 4929/* called with rcu_read_lock() */ 4930static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, 4931 struct netlink_callback *cb, enum addr_type_t type, 4932 int s_ip_idx, int *p_ip_idx, int netnsid) 4933{ | 4920 return -EMSGSIZE; 4921 4922 put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); 4923 if (nla_put_in6_addr(skb, IFA_ANYCAST, &ifaca->aca_addr) < 0 || 4924 put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp, 4925 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) { 4926 nlmsg_cancel(skb, nlh); 4927 return -EMSGSIZE; --- 9 unchanged lines hidden (view full) --- 4937 ANYCAST_ADDR, 4938}; 4939 4940/* called with rcu_read_lock() */ 4941static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, 4942 struct netlink_callback *cb, enum addr_type_t type, 4943 int s_ip_idx, int *p_ip_idx, int netnsid) 4944{ |
4945 struct inet6_fill_args fillargs = { 4946 .portid = NETLINK_CB(cb->skb).portid, 4947 .seq = cb->nlh->nlmsg_seq, 4948 .flags = NLM_F_MULTI, 4949 .netnsid = netnsid, 4950 }; |
|
4934 struct ifmcaddr6 *ifmca; 4935 struct ifacaddr6 *ifaca; 4936 int err = 1; 4937 int ip_idx = *p_ip_idx; 4938 4939 read_lock_bh(&idev->lock); 4940 switch (type) { 4941 case UNICAST_ADDR: { 4942 struct inet6_ifaddr *ifa; | 4951 struct ifmcaddr6 *ifmca; 4952 struct ifacaddr6 *ifaca; 4953 int err = 1; 4954 int ip_idx = *p_ip_idx; 4955 4956 read_lock_bh(&idev->lock); 4957 switch (type) { 4958 case UNICAST_ADDR: { 4959 struct inet6_ifaddr *ifa; |
4960 fillargs.event = RTM_NEWADDR; |
|
4943 4944 /* unicast address incl. temp addr */ 4945 list_for_each_entry(ifa, &idev->addr_list, if_list) { 4946 if (++ip_idx < s_ip_idx) 4947 continue; | 4961 4962 /* unicast address incl. temp addr */ 4963 list_for_each_entry(ifa, &idev->addr_list, if_list) { 4964 if (++ip_idx < s_ip_idx) 4965 continue; |
4948 err = inet6_fill_ifaddr(skb, ifa, 4949 NETLINK_CB(cb->skb).portid, 4950 cb->nlh->nlmsg_seq, 4951 RTM_NEWADDR, 4952 NLM_F_MULTI, netnsid); | 4966 err = inet6_fill_ifaddr(skb, ifa, &fillargs); |
4953 if (err < 0) 4954 break; 4955 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 4956 } 4957 break; 4958 } 4959 case MULTICAST_ADDR: | 4967 if (err < 0) 4968 break; 4969 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 4970 } 4971 break; 4972 } 4973 case MULTICAST_ADDR: |
4974 fillargs.event = RTM_GETMULTICAST; 4975 |
|
4960 /* multicast address */ 4961 for (ifmca = idev->mc_list; ifmca; 4962 ifmca = ifmca->next, ip_idx++) { 4963 if (ip_idx < s_ip_idx) 4964 continue; | 4976 /* multicast address */ 4977 for (ifmca = idev->mc_list; ifmca; 4978 ifmca = ifmca->next, ip_idx++) { 4979 if (ip_idx < s_ip_idx) 4980 continue; |
4965 err = inet6_fill_ifmcaddr(skb, ifmca, 4966 NETLINK_CB(cb->skb).portid, 4967 cb->nlh->nlmsg_seq, 4968 RTM_GETMULTICAST, 4969 NLM_F_MULTI, netnsid); | 4981 err = inet6_fill_ifmcaddr(skb, ifmca, &fillargs); |
4970 if (err < 0) 4971 break; 4972 } 4973 break; 4974 case ANYCAST_ADDR: | 4982 if (err < 0) 4983 break; 4984 } 4985 break; 4986 case ANYCAST_ADDR: |
4987 fillargs.event = RTM_GETANYCAST; |
|
4975 /* anycast address */ 4976 for (ifaca = idev->ac_list; ifaca; 4977 ifaca = ifaca->aca_next, ip_idx++) { 4978 if (ip_idx < s_ip_idx) 4979 continue; | 4988 /* anycast address */ 4989 for (ifaca = idev->ac_list; ifaca; 4990 ifaca = ifaca->aca_next, ip_idx++) { 4991 if (ip_idx < s_ip_idx) 4992 continue; |
4980 err = inet6_fill_ifacaddr(skb, ifaca, 4981 NETLINK_CB(cb->skb).portid, 4982 cb->nlh->nlmsg_seq, 4983 RTM_GETANYCAST, 4984 NLM_F_MULTI, netnsid); | 4993 err = inet6_fill_ifacaddr(skb, ifaca, &fillargs); |
4985 if (err < 0) 4986 break; 4987 } 4988 break; 4989 default: 4990 break; 4991 } 4992 read_unlock_bh(&idev->lock); --- 84 unchanged lines hidden (view full) --- 5077 5078 return inet6_dump_addr(skb, cb, type); 5079} 5080 5081static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh, 5082 struct netlink_ext_ack *extack) 5083{ 5084 struct net *net = sock_net(in_skb->sk); | 4994 if (err < 0) 4995 break; 4996 } 4997 break; 4998 default: 4999 break; 5000 } 5001 read_unlock_bh(&idev->lock); --- 84 unchanged lines hidden (view full) --- 5086 5087 return inet6_dump_addr(skb, cb, type); 5088} 5089 5090static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh, 5091 struct netlink_ext_ack *extack) 5092{ 5093 struct net *net = sock_net(in_skb->sk); |
5094 struct inet6_fill_args fillargs = { 5095 .portid = NETLINK_CB(in_skb).portid, 5096 .seq = nlh->nlmsg_seq, 5097 .event = RTM_NEWADDR, 5098 .flags = 0, 5099 .netnsid = -1, 5100 }; |
|
5085 struct net *tgt_net = net; 5086 struct ifaddrmsg *ifm; 5087 struct nlattr *tb[IFA_MAX+1]; 5088 struct in6_addr *addr = NULL, *peer; 5089 struct net_device *dev = NULL; 5090 struct inet6_ifaddr *ifa; 5091 struct sk_buff *skb; | 5101 struct net *tgt_net = net; 5102 struct ifaddrmsg *ifm; 5103 struct nlattr *tb[IFA_MAX+1]; 5104 struct in6_addr *addr = NULL, *peer; 5105 struct net_device *dev = NULL; 5106 struct inet6_ifaddr *ifa; 5107 struct sk_buff *skb; |
5092 int netnsid = -1; | |
5093 int err; 5094 5095 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy, 5096 extack); 5097 if (err < 0) 5098 return err; 5099 5100 if (tb[IFA_TARGET_NETNSID]) { | 5108 int err; 5109 5110 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy, 5111 extack); 5112 if (err < 0) 5113 return err; 5114 5115 if (tb[IFA_TARGET_NETNSID]) { |
5101 netnsid = nla_get_s32(tb[IFA_TARGET_NETNSID]); | 5116 fillargs.netnsid = nla_get_s32(tb[IFA_TARGET_NETNSID]); |
5102 5103 tgt_net = rtnl_get_net_ns_capable(NETLINK_CB(in_skb).sk, | 5117 5118 tgt_net = rtnl_get_net_ns_capable(NETLINK_CB(in_skb).sk, |
5104 netnsid); | 5119 fillargs.netnsid); |
5105 if (IS_ERR(tgt_net)) 5106 return PTR_ERR(tgt_net); 5107 } 5108 5109 addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer); 5110 if (!addr) 5111 return -EINVAL; 5112 --- 8 unchanged lines hidden (view full) --- 5121 } 5122 5123 skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL); 5124 if (!skb) { 5125 err = -ENOBUFS; 5126 goto errout_ifa; 5127 } 5128 | 5120 if (IS_ERR(tgt_net)) 5121 return PTR_ERR(tgt_net); 5122 } 5123 5124 addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer); 5125 if (!addr) 5126 return -EINVAL; 5127 --- 8 unchanged lines hidden (view full) --- 5136 } 5137 5138 skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL); 5139 if (!skb) { 5140 err = -ENOBUFS; 5141 goto errout_ifa; 5142 } 5143 |
5129 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).portid, 5130 nlh->nlmsg_seq, RTM_NEWADDR, 0, netnsid); | 5144 err = inet6_fill_ifaddr(skb, ifa, &fillargs); |
5131 if (err < 0) { 5132 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */ 5133 WARN_ON(err == -EMSGSIZE); 5134 kfree_skb(skb); 5135 goto errout_ifa; 5136 } 5137 err = rtnl_unicast(skb, tgt_net, NETLINK_CB(in_skb).portid); 5138errout_ifa: 5139 in6_ifa_put(ifa); 5140errout: 5141 if (dev) 5142 dev_put(dev); | 5145 if (err < 0) { 5146 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */ 5147 WARN_ON(err == -EMSGSIZE); 5148 kfree_skb(skb); 5149 goto errout_ifa; 5150 } 5151 err = rtnl_unicast(skb, tgt_net, NETLINK_CB(in_skb).portid); 5152errout_ifa: 5153 in6_ifa_put(ifa); 5154errout: 5155 if (dev) 5156 dev_put(dev); |
5143 if (netnsid >= 0) | 5157 if (fillargs.netnsid >= 0) |
5144 put_net(tgt_net); 5145 5146 return err; 5147} 5148 5149static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) 5150{ 5151 struct sk_buff *skb; 5152 struct net *net = dev_net(ifa->idev->dev); | 5158 put_net(tgt_net); 5159 5160 return err; 5161} 5162 5163static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) 5164{ 5165 struct sk_buff *skb; 5166 struct net *net = dev_net(ifa->idev->dev); |
5167 struct inet6_fill_args fillargs = { 5168 .portid = 0, 5169 .seq = 0, 5170 .event = event, 5171 .flags = 0, 5172 .netnsid = -1, 5173 }; |
|
5153 int err = -ENOBUFS; 5154 5155 skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC); 5156 if (!skb) 5157 goto errout; 5158 | 5174 int err = -ENOBUFS; 5175 5176 skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC); 5177 if (!skb) 5178 goto errout; 5179 |
5159 err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0, -1); | 5180 err = inet6_fill_ifaddr(skb, ifa, &fillargs); |
5160 if (err < 0) { 5161 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */ 5162 WARN_ON(err == -EMSGSIZE); 5163 kfree_skb(skb); 5164 goto errout; 5165 } 5166 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); 5167 return; --- 1714 unchanged lines hidden --- | 5181 if (err < 0) { 5182 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */ 5183 WARN_ON(err == -EMSGSIZE); 5184 kfree_skb(skb); 5185 goto errout; 5186 } 5187 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); 5188 return; --- 1714 unchanged lines hidden --- |