diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 77 |
1 files changed, 43 insertions, 34 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d546f0e74530..ca7ecf2f3e82 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3000,6 +3000,19 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3000 | preferred_lft, valid_lft); | 3000 | preferred_lft, valid_lft); |
3001 | } | 3001 | } |
3002 | 3002 | ||
3003 | static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags, | ||
3004 | u8 scope, int ifindex) | ||
3005 | { | ||
3006 | struct ifaddrmsg *ifm; | ||
3007 | |||
3008 | ifm = nlmsg_data(nlh); | ||
3009 | ifm->ifa_family = AF_INET6; | ||
3010 | ifm->ifa_prefixlen = prefixlen; | ||
3011 | ifm->ifa_flags = flags; | ||
3012 | ifm->ifa_scope = scope; | ||
3013 | ifm->ifa_index = ifindex; | ||
3014 | } | ||
3015 | |||
3003 | static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp, | 3016 | static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp, |
3004 | unsigned long tstamp, u32 preferred, u32 valid) | 3017 | unsigned long tstamp, u32 preferred, u32 valid) |
3005 | { | 3018 | { |
@@ -3015,6 +3028,18 @@ static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp, | |||
3015 | return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci); | 3028 | return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci); |
3016 | } | 3029 | } |
3017 | 3030 | ||
3031 | static inline int rt_scope(int ifa_scope) | ||
3032 | { | ||
3033 | if (ifa_scope & IFA_HOST) | ||
3034 | return RT_SCOPE_HOST; | ||
3035 | else if (ifa_scope & IFA_LINK) | ||
3036 | return RT_SCOPE_LINK; | ||
3037 | else if (ifa_scope & IFA_SITE) | ||
3038 | return RT_SCOPE_SITE; | ||
3039 | else | ||
3040 | return RT_SCOPE_UNIVERSE; | ||
3041 | } | ||
3042 | |||
3018 | /* Maximum length of ifa_cacheinfo attributes */ | 3043 | /* Maximum length of ifa_cacheinfo attributes */ |
3019 | #define INET6_IFADDR_RTA_SPACE \ | 3044 | #define INET6_IFADDR_RTA_SPACE \ |
3020 | RTA_SPACE(16) /* IFA_ADDRESS */ + \ | 3045 | RTA_SPACE(16) /* IFA_ADDRESS */ + \ |
@@ -3023,24 +3048,14 @@ static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp, | |||
3023 | static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | 3048 | static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, |
3024 | u32 pid, u32 seq, int event, unsigned int flags) | 3049 | u32 pid, u32 seq, int event, unsigned int flags) |
3025 | { | 3050 | { |
3026 | struct ifaddrmsg *ifm; | ||
3027 | struct nlmsghdr *nlh; | 3051 | struct nlmsghdr *nlh; |
3028 | unsigned char *b = skb->tail; | 3052 | unsigned char *b = skb->tail; |
3029 | u32 preferred, valid; | 3053 | u32 preferred, valid; |
3030 | 3054 | ||
3031 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); | 3055 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); |
3032 | ifm = NLMSG_DATA(nlh); | 3056 | put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope), |
3033 | ifm->ifa_family = AF_INET6; | 3057 | ifa->idev->dev->ifindex); |
3034 | ifm->ifa_prefixlen = ifa->prefix_len; | 3058 | |
3035 | ifm->ifa_flags = ifa->flags; | ||
3036 | ifm->ifa_scope = RT_SCOPE_UNIVERSE; | ||
3037 | if (ifa->scope&IFA_HOST) | ||
3038 | ifm->ifa_scope = RT_SCOPE_HOST; | ||
3039 | else if (ifa->scope&IFA_LINK) | ||
3040 | ifm->ifa_scope = RT_SCOPE_LINK; | ||
3041 | else if (ifa->scope&IFA_SITE) | ||
3042 | ifm->ifa_scope = RT_SCOPE_SITE; | ||
3043 | ifm->ifa_index = ifa->idev->dev->ifindex; | ||
3044 | RTA_PUT(skb, IFA_ADDRESS, 16, &ifa->addr); | 3059 | RTA_PUT(skb, IFA_ADDRESS, 16, &ifa->addr); |
3045 | if (!(ifa->flags&IFA_F_PERMANENT)) { | 3060 | if (!(ifa->flags&IFA_F_PERMANENT)) { |
3046 | preferred = ifa->prefered_lft; | 3061 | preferred = ifa->prefered_lft; |
@@ -3071,19 +3086,16 @@ rtattr_failure: | |||
3071 | static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, | 3086 | static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, |
3072 | u32 pid, u32 seq, int event, u16 flags) | 3087 | u32 pid, u32 seq, int event, u16 flags) |
3073 | { | 3088 | { |
3074 | struct ifaddrmsg *ifm; | ||
3075 | struct nlmsghdr *nlh; | 3089 | struct nlmsghdr *nlh; |
3076 | unsigned char *b = skb->tail; | 3090 | unsigned char *b = skb->tail; |
3091 | u8 scope = RT_SCOPE_UNIVERSE; | ||
3092 | int ifindex = ifmca->idev->dev->ifindex; | ||
3093 | |||
3094 | if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE) | ||
3095 | scope = RT_SCOPE_SITE; | ||
3077 | 3096 | ||
3078 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); | 3097 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); |
3079 | ifm = NLMSG_DATA(nlh); | 3098 | put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); |
3080 | ifm->ifa_family = AF_INET6; | ||
3081 | ifm->ifa_prefixlen = 128; | ||
3082 | ifm->ifa_flags = IFA_F_PERMANENT; | ||
3083 | ifm->ifa_scope = RT_SCOPE_UNIVERSE; | ||
3084 | if (ipv6_addr_scope(&ifmca->mca_addr)&IFA_SITE) | ||
3085 | ifm->ifa_scope = RT_SCOPE_SITE; | ||
3086 | ifm->ifa_index = ifmca->idev->dev->ifindex; | ||
3087 | RTA_PUT(skb, IFA_MULTICAST, 16, &ifmca->mca_addr); | 3099 | RTA_PUT(skb, IFA_MULTICAST, 16, &ifmca->mca_addr); |
3088 | 3100 | ||
3089 | if (put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp, | 3101 | if (put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp, |
@@ -3102,19 +3114,16 @@ rtattr_failure: | |||
3102 | static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, | 3114 | static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, |
3103 | u32 pid, u32 seq, int event, unsigned int flags) | 3115 | u32 pid, u32 seq, int event, unsigned int flags) |
3104 | { | 3116 | { |
3105 | struct ifaddrmsg *ifm; | ||
3106 | struct nlmsghdr *nlh; | 3117 | struct nlmsghdr *nlh; |
3107 | unsigned char *b = skb->tail; | 3118 | unsigned char *b = skb->tail; |
3119 | u8 scope = RT_SCOPE_UNIVERSE; | ||
3120 | int ifindex = ifaca->aca_idev->dev->ifindex; | ||
3121 | |||
3122 | if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE) | ||
3123 | scope = RT_SCOPE_SITE; | ||
3108 | 3124 | ||
3109 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); | 3125 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); |
3110 | ifm = NLMSG_DATA(nlh); | 3126 | put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); |
3111 | ifm->ifa_family = AF_INET6; | ||
3112 | ifm->ifa_prefixlen = 128; | ||
3113 | ifm->ifa_flags = IFA_F_PERMANENT; | ||
3114 | ifm->ifa_scope = RT_SCOPE_UNIVERSE; | ||
3115 | if (ipv6_addr_scope(&ifaca->aca_addr)&IFA_SITE) | ||
3116 | ifm->ifa_scope = RT_SCOPE_SITE; | ||
3117 | ifm->ifa_index = ifaca->aca_idev->dev->ifindex; | ||
3118 | RTA_PUT(skb, IFA_ANYCAST, 16, &ifaca->aca_addr); | 3127 | RTA_PUT(skb, IFA_ANYCAST, 16, &ifaca->aca_addr); |
3119 | 3128 | ||
3120 | if (put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp, | 3129 | if (put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp, |