diff options
| author | Thomas Graf <tgraf@suug.ch> | 2006-09-18 03:09:49 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:18:55 -0400 |
| commit | 461d8837faac141f4676bf451b3339d0e48656d1 (patch) | |
| tree | 6bd4a0d5aa2859b5e4c9c97971d992f71b94566e /net/ipv6 | |
| parent | 94aec08ea426903a3fb3cafd4d8b900cd50df702 (diff) | |
[IPV6] address: Convert address addition to new netlink api
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/addrconf.c | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index fc9cff3426c4..52ba96a64a1f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -2868,6 +2868,29 @@ restart: | |||
| 2868 | spin_unlock_bh(&addrconf_verify_lock); | 2868 | spin_unlock_bh(&addrconf_verify_lock); |
| 2869 | } | 2869 | } |
| 2870 | 2870 | ||
| 2871 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) | ||
| 2872 | { | ||
| 2873 | struct in6_addr *pfx = NULL; | ||
| 2874 | |||
| 2875 | if (addr) | ||
| 2876 | pfx = nla_data(addr); | ||
| 2877 | |||
| 2878 | if (local) { | ||
| 2879 | if (pfx && nla_memcmp(local, pfx, sizeof(*pfx))) | ||
| 2880 | pfx = NULL; | ||
| 2881 | else | ||
| 2882 | pfx = nla_data(local); | ||
| 2883 | } | ||
| 2884 | |||
| 2885 | return pfx; | ||
| 2886 | } | ||
| 2887 | |||
| 2888 | static struct nla_policy ifa_ipv6_policy[IFA_MAX+1] __read_mostly = { | ||
| 2889 | [IFA_ADDRESS] = { .len = sizeof(struct in6_addr) }, | ||
| 2890 | [IFA_LOCAL] = { .len = sizeof(struct in6_addr) }, | ||
| 2891 | [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, | ||
| 2892 | }; | ||
| 2893 | |||
| 2871 | static int | 2894 | static int |
| 2872 | inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 2895 | inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
| 2873 | { | 2896 | { |
| @@ -2945,46 +2968,41 @@ inet6_addr_modify(int ifindex, struct in6_addr *pfx, | |||
| 2945 | static int | 2968 | static int |
| 2946 | inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 2969 | inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
| 2947 | { | 2970 | { |
| 2948 | struct rtattr **rta = arg; | 2971 | struct ifaddrmsg *ifm; |
| 2949 | struct ifaddrmsg *ifm = NLMSG_DATA(nlh); | 2972 | struct nlattr *tb[IFA_MAX+1]; |
| 2950 | struct in6_addr *pfx; | 2973 | struct in6_addr *pfx; |
| 2951 | __u32 valid_lft = INFINITY_LIFE_TIME, prefered_lft = INFINITY_LIFE_TIME; | 2974 | u32 valid_lft, preferred_lft; |
| 2975 | int err; | ||
| 2952 | 2976 | ||
| 2953 | pfx = NULL; | 2977 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
| 2954 | if (rta[IFA_ADDRESS-1]) { | 2978 | if (err < 0) |
| 2955 | if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx)) | 2979 | return err; |
| 2956 | return -EINVAL; | 2980 | |
| 2957 | pfx = RTA_DATA(rta[IFA_ADDRESS-1]); | 2981 | ifm = nlmsg_data(nlh); |
| 2958 | } | 2982 | pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); |
| 2959 | if (rta[IFA_LOCAL-1]) { | ||
| 2960 | if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) || | ||
| 2961 | (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))) | ||
| 2962 | return -EINVAL; | ||
| 2963 | pfx = RTA_DATA(rta[IFA_LOCAL-1]); | ||
| 2964 | } | ||
| 2965 | if (pfx == NULL) | 2983 | if (pfx == NULL) |
| 2966 | return -EINVAL; | 2984 | return -EINVAL; |
| 2967 | 2985 | ||
| 2968 | if (rta[IFA_CACHEINFO-1]) { | 2986 | if (tb[IFA_CACHEINFO]) { |
| 2969 | struct ifa_cacheinfo *ci; | 2987 | struct ifa_cacheinfo *ci; |
| 2970 | if (RTA_PAYLOAD(rta[IFA_CACHEINFO-1]) < sizeof(*ci)) | 2988 | |
| 2971 | return -EINVAL; | 2989 | ci = nla_data(tb[IFA_CACHEINFO]); |
| 2972 | ci = RTA_DATA(rta[IFA_CACHEINFO-1]); | ||
| 2973 | valid_lft = ci->ifa_valid; | 2990 | valid_lft = ci->ifa_valid; |
| 2974 | prefered_lft = ci->ifa_prefered; | 2991 | preferred_lft = ci->ifa_prefered; |
| 2992 | } else { | ||
| 2993 | preferred_lft = INFINITY_LIFE_TIME; | ||
| 2994 | valid_lft = INFINITY_LIFE_TIME; | ||
| 2975 | } | 2995 | } |
| 2976 | 2996 | ||
| 2977 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { | 2997 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { |
| 2978 | int ret; | 2998 | err = inet6_addr_modify(ifm->ifa_index, pfx, |
| 2979 | ret = inet6_addr_modify(ifm->ifa_index, pfx, | 2999 | preferred_lft, valid_lft); |
| 2980 | prefered_lft, valid_lft); | 3000 | if (err == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE)) |
| 2981 | if (ret == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE)) | 3001 | return err; |
| 2982 | return ret; | ||
| 2983 | } | 3002 | } |
| 2984 | 3003 | ||
| 2985 | return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, | 3004 | return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, |
| 2986 | prefered_lft, valid_lft); | 3005 | preferred_lft, valid_lft); |
| 2987 | |||
| 2988 | } | 3006 | } |
| 2989 | 3007 | ||
| 2990 | /* Maximum length of ifa_cacheinfo attributes */ | 3008 | /* Maximum length of ifa_cacheinfo attributes */ |
