diff options
| author | Noriaki TAKAMIYA <takamiya@po.ntts.co.jp> | 2006-07-28 05:12:10 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-08-02 16:38:09 -0400 |
| commit | 0778769d392b5b80410673f53e4f946574ebacf7 (patch) | |
| tree | a045eb932e17e8bc8d963d1555a5f37701c8a770 | |
| parent | 643162258e57180a33e0ef7f08f0d986fbb5b4b9 (diff) | |
[IPV6] ADDRCONF: Allow user-space to specify address lifetime
Based on MIPL2 kernel patch.
Signed-off-by: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
| -rw-r--r-- | net/ipv6/addrconf.c | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 81702b9ba5be..c0641887bdeb 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -1869,15 +1869,21 @@ err_exit: | |||
| 1869 | /* | 1869 | /* |
| 1870 | * Manual configuration of address on an interface | 1870 | * Manual configuration of address on an interface |
| 1871 | */ | 1871 | */ |
| 1872 | static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen) | 1872 | static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, |
| 1873 | __u32 prefered_lft, __u32 valid_lft) | ||
| 1873 | { | 1874 | { |
| 1874 | struct inet6_ifaddr *ifp; | 1875 | struct inet6_ifaddr *ifp; |
| 1875 | struct inet6_dev *idev; | 1876 | struct inet6_dev *idev; |
| 1876 | struct net_device *dev; | 1877 | struct net_device *dev; |
| 1878 | __u8 ifa_flags = 0; | ||
| 1877 | int scope; | 1879 | int scope; |
| 1878 | 1880 | ||
| 1879 | ASSERT_RTNL(); | 1881 | ASSERT_RTNL(); |
| 1880 | 1882 | ||
| 1883 | /* check the lifetime */ | ||
| 1884 | if (!valid_lft || prefered_lft > valid_lft) | ||
| 1885 | return -EINVAL; | ||
| 1886 | |||
| 1881 | if ((dev = __dev_get_by_index(ifindex)) == NULL) | 1887 | if ((dev = __dev_get_by_index(ifindex)) == NULL) |
| 1882 | return -ENODEV; | 1888 | return -ENODEV; |
| 1883 | 1889 | ||
| @@ -1889,10 +1895,29 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen) | |||
| 1889 | 1895 | ||
| 1890 | scope = ipv6_addr_scope(pfx); | 1896 | scope = ipv6_addr_scope(pfx); |
| 1891 | 1897 | ||
| 1892 | ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT); | 1898 | if (valid_lft == INFINITY_LIFE_TIME) |
| 1899 | ifa_flags |= IFA_F_PERMANENT; | ||
| 1900 | else if (valid_lft >= 0x7FFFFFFF/HZ) | ||
| 1901 | valid_lft = 0x7FFFFFFF/HZ; | ||
| 1902 | |||
| 1903 | if (prefered_lft == 0) | ||
| 1904 | ifa_flags |= IFA_F_DEPRECATED; | ||
| 1905 | else if ((prefered_lft >= 0x7FFFFFFF/HZ) && | ||
| 1906 | (prefered_lft != INFINITY_LIFE_TIME)) | ||
| 1907 | prefered_lft = 0x7FFFFFFF/HZ; | ||
| 1908 | |||
| 1909 | ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); | ||
| 1910 | |||
| 1893 | if (!IS_ERR(ifp)) { | 1911 | if (!IS_ERR(ifp)) { |
| 1912 | spin_lock(&ifp->lock); | ||
| 1913 | ifp->valid_lft = valid_lft; | ||
| 1914 | ifp->prefered_lft = prefered_lft; | ||
| 1915 | ifp->tstamp = jiffies; | ||
| 1916 | spin_unlock(&ifp->lock); | ||
| 1917 | |||
| 1894 | addrconf_dad_start(ifp, 0); | 1918 | addrconf_dad_start(ifp, 0); |
| 1895 | in6_ifa_put(ifp); | 1919 | in6_ifa_put(ifp); |
| 1920 | addrconf_verify(0); | ||
| 1896 | return 0; | 1921 | return 0; |
| 1897 | } | 1922 | } |
| 1898 | 1923 | ||
| @@ -1945,7 +1970,8 @@ int addrconf_add_ifaddr(void __user *arg) | |||
| 1945 | return -EFAULT; | 1970 | return -EFAULT; |
| 1946 | 1971 | ||
| 1947 | rtnl_lock(); | 1972 | rtnl_lock(); |
| 1948 | err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); | 1973 | err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen, |
| 1974 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | ||
| 1949 | rtnl_unlock(); | 1975 | rtnl_unlock(); |
| 1950 | return err; | 1976 | return err; |
| 1951 | } | 1977 | } |
| @@ -2870,6 +2896,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 2870 | struct rtattr **rta = arg; | 2896 | struct rtattr **rta = arg; |
| 2871 | struct ifaddrmsg *ifm = NLMSG_DATA(nlh); | 2897 | struct ifaddrmsg *ifm = NLMSG_DATA(nlh); |
| 2872 | struct in6_addr *pfx; | 2898 | struct in6_addr *pfx; |
| 2899 | __u32 valid_lft = INFINITY_LIFE_TIME, prefered_lft = INFINITY_LIFE_TIME; | ||
| 2873 | 2900 | ||
| 2874 | pfx = NULL; | 2901 | pfx = NULL; |
| 2875 | if (rta[IFA_ADDRESS-1]) { | 2902 | if (rta[IFA_ADDRESS-1]) { |
| @@ -2886,7 +2913,18 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 2886 | if (pfx == NULL) | 2913 | if (pfx == NULL) |
| 2887 | return -EINVAL; | 2914 | return -EINVAL; |
| 2888 | 2915 | ||
| 2889 | return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen); | 2916 | if (rta[IFA_CACHEINFO-1]) { |
| 2917 | struct ifa_cacheinfo *ci; | ||
| 2918 | if (RTA_PAYLOAD(rta[IFA_CACHEINFO-1]) < sizeof(*ci)) | ||
| 2919 | return -EINVAL; | ||
| 2920 | ci = RTA_DATA(rta[IFA_CACHEINFO-1]); | ||
| 2921 | valid_lft = ci->ifa_valid; | ||
| 2922 | prefered_lft = ci->ifa_prefered; | ||
| 2923 | } | ||
| 2924 | |||
| 2925 | return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, | ||
| 2926 | prefered_lft, valid_lft); | ||
| 2927 | |||
| 2890 | } | 2928 | } |
| 2891 | 2929 | ||
| 2892 | /* Maximum length of ifa_cacheinfo attributes */ | 2930 | /* Maximum length of ifa_cacheinfo attributes */ |
