aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/mroute.h4
-rw-r--r--include/uapi/linux/mroute6.h4
-rw-r--r--net/ipv4/ipmr.c119
-rw-r--r--net/ipv6/ip6mr.c126
4 files changed, 225 insertions, 28 deletions
diff --git a/include/uapi/linux/mroute.h b/include/uapi/linux/mroute.h
index 1c11004af5db..a382d2c04a42 100644
--- a/include/uapi/linux/mroute.h
+++ b/include/uapi/linux/mroute.h
@@ -26,7 +26,9 @@
26#define MRT_ASSERT (MRT_BASE+7) /* Activate PIM assert mode */ 26#define MRT_ASSERT (MRT_BASE+7) /* Activate PIM assert mode */
27#define MRT_PIM (MRT_BASE+8) /* enable PIM code */ 27#define MRT_PIM (MRT_BASE+8) /* enable PIM code */
28#define MRT_TABLE (MRT_BASE+9) /* Specify mroute table ID */ 28#define MRT_TABLE (MRT_BASE+9) /* Specify mroute table ID */
29#define MRT_MAX (MRT_BASE+9) 29#define MRT_ADD_MFC_PROXY (MRT_BASE+10) /* Add a (*,*|G) mfc entry */
30#define MRT_DEL_MFC_PROXY (MRT_BASE+11) /* Del a (*,*|G) mfc entry */
31#define MRT_MAX (MRT_BASE+11)
30 32
31#define SIOCGETVIFCNT SIOCPROTOPRIVATE /* IP protocol privates */ 33#define SIOCGETVIFCNT SIOCPROTOPRIVATE /* IP protocol privates */
32#define SIOCGETSGCNT (SIOCPROTOPRIVATE+1) 34#define SIOCGETSGCNT (SIOCPROTOPRIVATE+1)
diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h
index c206ae3a2327..ce91215cf7e6 100644
--- a/include/uapi/linux/mroute6.h
+++ b/include/uapi/linux/mroute6.h
@@ -26,7 +26,9 @@
26#define MRT6_ASSERT (MRT6_BASE+7) /* Activate PIM assert mode */ 26#define MRT6_ASSERT (MRT6_BASE+7) /* Activate PIM assert mode */
27#define MRT6_PIM (MRT6_BASE+8) /* enable PIM code */ 27#define MRT6_PIM (MRT6_BASE+8) /* enable PIM code */
28#define MRT6_TABLE (MRT6_BASE+9) /* Specify mroute table ID */ 28#define MRT6_TABLE (MRT6_BASE+9) /* Specify mroute table ID */
29#define MRT6_MAX (MRT6_BASE+9) 29#define MRT6_ADD_MFC_PROXY (MRT6_BASE+10) /* Add a (*,*|G) mfc entry */
30#define MRT6_DEL_MFC_PROXY (MRT6_BASE+11) /* Del a (*,*|G) mfc entry */
31#define MRT6_MAX (MRT6_BASE+11)
30 32
31#define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE /* IP protocol privates */ 33#define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE /* IP protocol privates */
32#define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1) 34#define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index a9454cbd953c..4b5e22670d44 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -828,6 +828,49 @@ static struct mfc_cache *ipmr_cache_find(struct mr_table *mrt,
828 return NULL; 828 return NULL;
829} 829}
830 830
831/* Look for a (*,*,oif) entry */
832static struct mfc_cache *ipmr_cache_find_any_parent(struct mr_table *mrt,
833 int vifi)
834{
835 int line = MFC_HASH(INADDR_ANY, INADDR_ANY);
836 struct mfc_cache *c;
837
838 list_for_each_entry_rcu(c, &mrt->mfc_cache_array[line], list)
839 if (c->mfc_origin == INADDR_ANY &&
840 c->mfc_mcastgrp == INADDR_ANY &&
841 c->mfc_un.res.ttls[vifi] < 255)
842 return c;
843
844 return NULL;
845}
846
847/* Look for a (*,G) entry */
848static struct mfc_cache *ipmr_cache_find_any(struct mr_table *mrt,
849 __be32 mcastgrp, int vifi)
850{
851 int line = MFC_HASH(mcastgrp, INADDR_ANY);
852 struct mfc_cache *c, *proxy;
853
854 if (mcastgrp == INADDR_ANY)
855 goto skip;
856
857 list_for_each_entry_rcu(c, &mrt->mfc_cache_array[line], list)
858 if (c->mfc_origin == INADDR_ANY &&
859 c->mfc_mcastgrp == mcastgrp) {
860 if (c->mfc_un.res.ttls[vifi] < 255)
861 return c;
862
863 /* It's ok if the vifi is part of the static tree */
864 proxy = ipmr_cache_find_any_parent(mrt,
865 c->mfc_parent);
866 if (proxy && proxy->mfc_un.res.ttls[vifi] < 255)
867 return c;
868 }
869
870skip:
871 return ipmr_cache_find_any_parent(mrt, vifi);
872}
873
831/* 874/*
832 * Allocate a multicast cache entry 875 * Allocate a multicast cache entry
833 */ 876 */
@@ -1053,7 +1096,7 @@ ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb)
1053 * MFC cache manipulation by user space mroute daemon 1096 * MFC cache manipulation by user space mroute daemon
1054 */ 1097 */
1055 1098
1056static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc) 1099static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc, int parent)
1057{ 1100{
1058 int line; 1101 int line;
1059 struct mfc_cache *c, *next; 1102 struct mfc_cache *c, *next;
@@ -1062,7 +1105,8 @@ static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc)
1062 1105
1063 list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[line], list) { 1106 list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[line], list) {
1064 if (c->mfc_origin == mfc->mfcc_origin.s_addr && 1107 if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
1065 c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { 1108 c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr &&
1109 (parent == -1 || parent == c->mfc_parent)) {
1066 list_del_rcu(&c->list); 1110 list_del_rcu(&c->list);
1067 mroute_netlink_event(mrt, c, RTM_DELROUTE); 1111 mroute_netlink_event(mrt, c, RTM_DELROUTE);
1068 ipmr_cache_free(c); 1112 ipmr_cache_free(c);
@@ -1073,7 +1117,7 @@ static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc)
1073} 1117}
1074 1118
1075static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, 1119static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
1076 struct mfcctl *mfc, int mrtsock) 1120 struct mfcctl *mfc, int mrtsock, int parent)
1077{ 1121{
1078 bool found = false; 1122 bool found = false;
1079 int line; 1123 int line;
@@ -1086,7 +1130,8 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
1086 1130
1087 list_for_each_entry(c, &mrt->mfc_cache_array[line], list) { 1131 list_for_each_entry(c, &mrt->mfc_cache_array[line], list) {
1088 if (c->mfc_origin == mfc->mfcc_origin.s_addr && 1132 if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
1089 c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { 1133 c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr &&
1134 (parent == -1 || parent == c->mfc_parent)) {
1090 found = true; 1135 found = true;
1091 break; 1136 break;
1092 } 1137 }
@@ -1103,7 +1148,8 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
1103 return 0; 1148 return 0;
1104 } 1149 }
1105 1150
1106 if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr)) 1151 if (mfc->mfcc_mcastgrp.s_addr != INADDR_ANY &&
1152 !ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr))
1107 return -EINVAL; 1153 return -EINVAL;
1108 1154
1109 c = ipmr_cache_alloc(); 1155 c = ipmr_cache_alloc();
@@ -1218,7 +1264,7 @@ static void mrtsock_destruct(struct sock *sk)
1218 1264
1219int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen) 1265int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
1220{ 1266{
1221 int ret; 1267 int ret, parent = 0;
1222 struct vifctl vif; 1268 struct vifctl vif;
1223 struct mfcctl mfc; 1269 struct mfcctl mfc;
1224 struct net *net = sock_net(sk); 1270 struct net *net = sock_net(sk);
@@ -1287,16 +1333,22 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
1287 */ 1333 */
1288 case MRT_ADD_MFC: 1334 case MRT_ADD_MFC:
1289 case MRT_DEL_MFC: 1335 case MRT_DEL_MFC:
1336 parent = -1;
1337 case MRT_ADD_MFC_PROXY:
1338 case MRT_DEL_MFC_PROXY:
1290 if (optlen != sizeof(mfc)) 1339 if (optlen != sizeof(mfc))
1291 return -EINVAL; 1340 return -EINVAL;
1292 if (copy_from_user(&mfc, optval, sizeof(mfc))) 1341 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1293 return -EFAULT; 1342 return -EFAULT;
1343 if (parent == 0)
1344 parent = mfc.mfcc_parent;
1294 rtnl_lock(); 1345 rtnl_lock();
1295 if (optname == MRT_DEL_MFC) 1346 if (optname == MRT_DEL_MFC || optname == MRT_DEL_MFC_PROXY)
1296 ret = ipmr_mfc_delete(mrt, &mfc); 1347 ret = ipmr_mfc_delete(mrt, &mfc, parent);
1297 else 1348 else
1298 ret = ipmr_mfc_add(net, mrt, &mfc, 1349 ret = ipmr_mfc_add(net, mrt, &mfc,
1299 sk == rtnl_dereference(mrt->mroute_sk)); 1350 sk == rtnl_dereference(mrt->mroute_sk),
1351 parent);
1300 rtnl_unlock(); 1352 rtnl_unlock();
1301 return ret; 1353 return ret;
1302 /* 1354 /*
@@ -1749,17 +1801,28 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
1749{ 1801{
1750 int psend = -1; 1802 int psend = -1;
1751 int vif, ct; 1803 int vif, ct;
1804 int true_vifi = ipmr_find_vif(mrt, skb->dev);
1752 1805
1753 vif = cache->mfc_parent; 1806 vif = cache->mfc_parent;
1754 cache->mfc_un.res.pkt++; 1807 cache->mfc_un.res.pkt++;
1755 cache->mfc_un.res.bytes += skb->len; 1808 cache->mfc_un.res.bytes += skb->len;
1756 1809
1810 if (cache->mfc_origin == INADDR_ANY && true_vifi >= 0) {
1811 struct mfc_cache *cache_proxy;
1812
1813 /* For an (*,G) entry, we only check that the incomming
1814 * interface is part of the static tree.
1815 */
1816 cache_proxy = ipmr_cache_find_any_parent(mrt, vif);
1817 if (cache_proxy &&
1818 cache_proxy->mfc_un.res.ttls[true_vifi] < 255)
1819 goto forward;
1820 }
1821
1757 /* 1822 /*
1758 * Wrong interface: drop packet and (maybe) send PIM assert. 1823 * Wrong interface: drop packet and (maybe) send PIM assert.
1759 */ 1824 */
1760 if (mrt->vif_table[vif].dev != skb->dev) { 1825 if (mrt->vif_table[vif].dev != skb->dev) {
1761 int true_vifi;
1762
1763 if (rt_is_output_route(skb_rtable(skb))) { 1826 if (rt_is_output_route(skb_rtable(skb))) {
1764 /* It is our own packet, looped back. 1827 /* It is our own packet, looped back.
1765 * Very complicated situation... 1828 * Very complicated situation...
@@ -1776,7 +1839,6 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
1776 } 1839 }
1777 1840
1778 cache->mfc_un.res.wrong_if++; 1841 cache->mfc_un.res.wrong_if++;
1779 true_vifi = ipmr_find_vif(mrt, skb->dev);
1780 1842
1781 if (true_vifi >= 0 && mrt->mroute_do_assert && 1843 if (true_vifi >= 0 && mrt->mroute_do_assert &&
1782 /* pimsm uses asserts, when switching from RPT to SPT, 1844 /* pimsm uses asserts, when switching from RPT to SPT,
@@ -1794,15 +1856,33 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
1794 goto dont_forward; 1856 goto dont_forward;
1795 } 1857 }
1796 1858
1859forward:
1797 mrt->vif_table[vif].pkt_in++; 1860 mrt->vif_table[vif].pkt_in++;
1798 mrt->vif_table[vif].bytes_in += skb->len; 1861 mrt->vif_table[vif].bytes_in += skb->len;
1799 1862
1800 /* 1863 /*
1801 * Forward the frame 1864 * Forward the frame
1802 */ 1865 */
1866 if (cache->mfc_origin == INADDR_ANY &&
1867 cache->mfc_mcastgrp == INADDR_ANY) {
1868 if (true_vifi >= 0 &&
1869 true_vifi != cache->mfc_parent &&
1870 ip_hdr(skb)->ttl >
1871 cache->mfc_un.res.ttls[cache->mfc_parent]) {
1872 /* It's an (*,*) entry and the packet is not coming from
1873 * the upstream: forward the packet to the upstream
1874 * only.
1875 */
1876 psend = cache->mfc_parent;
1877 goto last_forward;
1878 }
1879 goto dont_forward;
1880 }
1803 for (ct = cache->mfc_un.res.maxvif - 1; 1881 for (ct = cache->mfc_un.res.maxvif - 1;
1804 ct >= cache->mfc_un.res.minvif; ct--) { 1882 ct >= cache->mfc_un.res.minvif; ct--) {
1805 if (ip_hdr(skb)->ttl > cache->mfc_un.res.ttls[ct]) { 1883 /* For (*,G) entry, don't forward to the incoming interface */
1884 if ((cache->mfc_origin != INADDR_ANY || ct != true_vifi) &&
1885 ip_hdr(skb)->ttl > cache->mfc_un.res.ttls[ct]) {
1806 if (psend != -1) { 1886 if (psend != -1) {
1807 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); 1887 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
1808 1888
@@ -1813,6 +1893,7 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
1813 psend = ct; 1893 psend = ct;
1814 } 1894 }
1815 } 1895 }
1896last_forward:
1816 if (psend != -1) { 1897 if (psend != -1) {
1817 if (local) { 1898 if (local) {
1818 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); 1899 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
@@ -1902,6 +1983,13 @@ int ip_mr_input(struct sk_buff *skb)
1902 1983
1903 /* already under rcu_read_lock() */ 1984 /* already under rcu_read_lock() */
1904 cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); 1985 cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
1986 if (cache == NULL) {
1987 int vif = ipmr_find_vif(mrt, skb->dev);
1988
1989 if (vif >= 0)
1990 cache = ipmr_cache_find_any(mrt, ip_hdr(skb)->daddr,
1991 vif);
1992 }
1905 1993
1906 /* 1994 /*
1907 * No usable cache entry 1995 * No usable cache entry
@@ -2107,7 +2195,12 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
2107 2195
2108 rcu_read_lock(); 2196 rcu_read_lock();
2109 cache = ipmr_cache_find(mrt, saddr, daddr); 2197 cache = ipmr_cache_find(mrt, saddr, daddr);
2198 if (cache == NULL && skb->dev) {
2199 int vif = ipmr_find_vif(mrt, skb->dev);
2110 2200
2201 if (vif >= 0)
2202 cache = ipmr_cache_find_any(mrt, daddr, vif);
2203 }
2111 if (cache == NULL) { 2204 if (cache == NULL) {
2112 struct sk_buff *skb2; 2205 struct sk_buff *skb2;
2113 struct iphdr *iph; 2206 struct iphdr *iph;
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 26dcdec9e3a5..acc32494006a 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1017,6 +1017,50 @@ static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt,
1017 return NULL; 1017 return NULL;
1018} 1018}
1019 1019
1020/* Look for a (*,*,oif) entry */
1021static struct mfc6_cache *ip6mr_cache_find_any_parent(struct mr6_table *mrt,
1022 mifi_t mifi)
1023{
1024 int line = MFC6_HASH(&in6addr_any, &in6addr_any);
1025 struct mfc6_cache *c;
1026
1027 list_for_each_entry(c, &mrt->mfc6_cache_array[line], list)
1028 if (ipv6_addr_any(&c->mf6c_origin) &&
1029 ipv6_addr_any(&c->mf6c_mcastgrp) &&
1030 (c->mfc_un.res.ttls[mifi] < 255))
1031 return c;
1032
1033 return NULL;
1034}
1035
1036/* Look for a (*,G) entry */
1037static struct mfc6_cache *ip6mr_cache_find_any(struct mr6_table *mrt,
1038 struct in6_addr *mcastgrp,
1039 mifi_t mifi)
1040{
1041 int line = MFC6_HASH(mcastgrp, &in6addr_any);
1042 struct mfc6_cache *c, *proxy;
1043
1044 if (ipv6_addr_any(mcastgrp))
1045 goto skip;
1046
1047 list_for_each_entry(c, &mrt->mfc6_cache_array[line], list)
1048 if (ipv6_addr_any(&c->mf6c_origin) &&
1049 ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp)) {
1050 if (c->mfc_un.res.ttls[mifi] < 255)
1051 return c;
1052
1053 /* It's ok if the mifi is part of the static tree */
1054 proxy = ip6mr_cache_find_any_parent(mrt,
1055 c->mf6c_parent);
1056 if (proxy && proxy->mfc_un.res.ttls[mifi] < 255)
1057 return c;
1058 }
1059
1060skip:
1061 return ip6mr_cache_find_any_parent(mrt, mifi);
1062}
1063
1020/* 1064/*
1021 * Allocate a multicast cache entry 1065 * Allocate a multicast cache entry
1022 */ 1066 */
@@ -1247,7 +1291,8 @@ ip6mr_cache_unresolved(struct mr6_table *mrt, mifi_t mifi, struct sk_buff *skb)
1247 * MFC6 cache manipulation by user space 1291 * MFC6 cache manipulation by user space
1248 */ 1292 */
1249 1293
1250static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc) 1294static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc,
1295 int parent)
1251{ 1296{
1252 int line; 1297 int line;
1253 struct mfc6_cache *c, *next; 1298 struct mfc6_cache *c, *next;
@@ -1256,7 +1301,9 @@ static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc)
1256 1301
1257 list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) { 1302 list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) {
1258 if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && 1303 if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
1259 ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { 1304 ipv6_addr_equal(&c->mf6c_mcastgrp,
1305 &mfc->mf6cc_mcastgrp.sin6_addr) &&
1306 (parent == -1 || parent == c->mf6c_parent)) {
1260 write_lock_bh(&mrt_lock); 1307 write_lock_bh(&mrt_lock);
1261 list_del(&c->list); 1308 list_del(&c->list);
1262 write_unlock_bh(&mrt_lock); 1309 write_unlock_bh(&mrt_lock);
@@ -1391,7 +1438,7 @@ void ip6_mr_cleanup(void)
1391} 1438}
1392 1439
1393static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt, 1440static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
1394 struct mf6cctl *mfc, int mrtsock) 1441 struct mf6cctl *mfc, int mrtsock, int parent)
1395{ 1442{
1396 bool found = false; 1443 bool found = false;
1397 int line; 1444 int line;
@@ -1413,7 +1460,9 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
1413 1460
1414 list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) { 1461 list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) {
1415 if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && 1462 if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
1416 ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { 1463 ipv6_addr_equal(&c->mf6c_mcastgrp,
1464 &mfc->mf6cc_mcastgrp.sin6_addr) &&
1465 (parent == -1 || parent == mfc->mf6cc_parent)) {
1417 found = true; 1466 found = true;
1418 break; 1467 break;
1419 } 1468 }
@@ -1430,7 +1479,8 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
1430 return 0; 1479 return 0;
1431 } 1480 }
1432 1481
1433 if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr)) 1482 if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) &&
1483 !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
1434 return -EINVAL; 1484 return -EINVAL;
1435 1485
1436 c = ip6mr_cache_alloc(); 1486 c = ip6mr_cache_alloc();
@@ -1596,7 +1646,7 @@ struct sock *mroute6_socket(struct net *net, struct sk_buff *skb)
1596 1646
1597int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen) 1647int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
1598{ 1648{
1599 int ret; 1649 int ret, parent = 0;
1600 struct mif6ctl vif; 1650 struct mif6ctl vif;
1601 struct mf6cctl mfc; 1651 struct mf6cctl mfc;
1602 mifi_t mifi; 1652 mifi_t mifi;
@@ -1653,15 +1703,21 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
1653 */ 1703 */
1654 case MRT6_ADD_MFC: 1704 case MRT6_ADD_MFC:
1655 case MRT6_DEL_MFC: 1705 case MRT6_DEL_MFC:
1706 parent = -1;
1707 case MRT6_ADD_MFC_PROXY:
1708 case MRT6_DEL_MFC_PROXY:
1656 if (optlen < sizeof(mfc)) 1709 if (optlen < sizeof(mfc))
1657 return -EINVAL; 1710 return -EINVAL;
1658 if (copy_from_user(&mfc, optval, sizeof(mfc))) 1711 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1659 return -EFAULT; 1712 return -EFAULT;
1713 if (parent == 0)
1714 parent = mfc.mf6cc_parent;
1660 rtnl_lock(); 1715 rtnl_lock();
1661 if (optname == MRT6_DEL_MFC) 1716 if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
1662 ret = ip6mr_mfc_delete(mrt, &mfc); 1717 ret = ip6mr_mfc_delete(mrt, &mfc, parent);
1663 else 1718 else
1664 ret = ip6mr_mfc_add(net, mrt, &mfc, sk == mrt->mroute6_sk); 1719 ret = ip6mr_mfc_add(net, mrt, &mfc,
1720 sk == mrt->mroute6_sk, parent);
1665 rtnl_unlock(); 1721 rtnl_unlock();
1666 return ret; 1722 return ret;
1667 1723
@@ -2015,19 +2071,29 @@ static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
2015{ 2071{
2016 int psend = -1; 2072 int psend = -1;
2017 int vif, ct; 2073 int vif, ct;
2074 int true_vifi = ip6mr_find_vif(mrt, skb->dev);
2018 2075
2019 vif = cache->mf6c_parent; 2076 vif = cache->mf6c_parent;
2020 cache->mfc_un.res.pkt++; 2077 cache->mfc_un.res.pkt++;
2021 cache->mfc_un.res.bytes += skb->len; 2078 cache->mfc_un.res.bytes += skb->len;
2022 2079
2080 if (ipv6_addr_any(&cache->mf6c_origin) && true_vifi >= 0) {
2081 struct mfc6_cache *cache_proxy;
2082
2083 /* For an (*,G) entry, we only check that the incomming
2084 * interface is part of the static tree.
2085 */
2086 cache_proxy = ip6mr_cache_find_any_parent(mrt, vif);
2087 if (cache_proxy &&
2088 cache_proxy->mfc_un.res.ttls[true_vifi] < 255)
2089 goto forward;
2090 }
2091
2023 /* 2092 /*
2024 * Wrong interface: drop packet and (maybe) send PIM assert. 2093 * Wrong interface: drop packet and (maybe) send PIM assert.
2025 */ 2094 */
2026 if (mrt->vif6_table[vif].dev != skb->dev) { 2095 if (mrt->vif6_table[vif].dev != skb->dev) {
2027 int true_vifi;
2028
2029 cache->mfc_un.res.wrong_if++; 2096 cache->mfc_un.res.wrong_if++;
2030 true_vifi = ip6mr_find_vif(mrt, skb->dev);
2031 2097
2032 if (true_vifi >= 0 && mrt->mroute_do_assert && 2098 if (true_vifi >= 0 && mrt->mroute_do_assert &&
2033 /* pimsm uses asserts, when switching from RPT to SPT, 2099 /* pimsm uses asserts, when switching from RPT to SPT,
@@ -2045,14 +2111,32 @@ static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
2045 goto dont_forward; 2111 goto dont_forward;
2046 } 2112 }
2047 2113
2114forward:
2048 mrt->vif6_table[vif].pkt_in++; 2115 mrt->vif6_table[vif].pkt_in++;
2049 mrt->vif6_table[vif].bytes_in += skb->len; 2116 mrt->vif6_table[vif].bytes_in += skb->len;
2050 2117
2051 /* 2118 /*
2052 * Forward the frame 2119 * Forward the frame
2053 */ 2120 */
2121 if (ipv6_addr_any(&cache->mf6c_origin) &&
2122 ipv6_addr_any(&cache->mf6c_mcastgrp)) {
2123 if (true_vifi >= 0 &&
2124 true_vifi != cache->mf6c_parent &&
2125 ipv6_hdr(skb)->hop_limit >
2126 cache->mfc_un.res.ttls[cache->mf6c_parent]) {
2127 /* It's an (*,*) entry and the packet is not coming from
2128 * the upstream: forward the packet to the upstream
2129 * only.
2130 */
2131 psend = cache->mf6c_parent;
2132 goto last_forward;
2133 }
2134 goto dont_forward;
2135 }
2054 for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) { 2136 for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) {
2055 if (ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) { 2137 /* For (*,G) entry, don't forward to the incoming interface */
2138 if ((!ipv6_addr_any(&cache->mf6c_origin) || ct != true_vifi) &&
2139 ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) {
2056 if (psend != -1) { 2140 if (psend != -1) {
2057 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); 2141 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
2058 if (skb2) 2142 if (skb2)
@@ -2061,6 +2145,7 @@ static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
2061 psend = ct; 2145 psend = ct;
2062 } 2146 }
2063 } 2147 }
2148last_forward:
2064 if (psend != -1) { 2149 if (psend != -1) {
2065 ip6mr_forward2(net, mrt, skb, cache, psend); 2150 ip6mr_forward2(net, mrt, skb, cache, psend);
2066 return 0; 2151 return 0;
@@ -2096,6 +2181,14 @@ int ip6_mr_input(struct sk_buff *skb)
2096 read_lock(&mrt_lock); 2181 read_lock(&mrt_lock);
2097 cache = ip6mr_cache_find(mrt, 2182 cache = ip6mr_cache_find(mrt,
2098 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); 2183 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
2184 if (cache == NULL) {
2185 int vif = ip6mr_find_vif(mrt, skb->dev);
2186
2187 if (vif >= 0)
2188 cache = ip6mr_cache_find_any(mrt,
2189 &ipv6_hdr(skb)->daddr,
2190 vif);
2191 }
2099 2192
2100 /* 2193 /*
2101 * No usable cache entry 2194 * No usable cache entry
@@ -2183,6 +2276,13 @@ int ip6mr_get_route(struct net *net,
2183 2276
2184 read_lock(&mrt_lock); 2277 read_lock(&mrt_lock);
2185 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr); 2278 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
2279 if (!cache && skb->dev) {
2280 int vif = ip6mr_find_vif(mrt, skb->dev);
2281
2282 if (vif >= 0)
2283 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
2284 vif);
2285 }
2186 2286
2187 if (!cache) { 2287 if (!cache) {
2188 struct sk_buff *skb2; 2288 struct sk_buff *skb2;