aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipmr.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r--net/ipv4/ipmr.c130
1 files changed, 112 insertions, 18 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index a9454cbd953c..5f95b3aa579e 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(htonl(INADDR_ANY), htonl(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 == htonl(INADDR_ANY) &&
840 c->mfc_mcastgrp == htonl(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, htonl(INADDR_ANY));
852 struct mfc_cache *c, *proxy;
853
854 if (mcastgrp == htonl(INADDR_ANY))
855 goto skip;
856
857 list_for_each_entry_rcu(c, &mrt->mfc_cache_array[line], list)
858 if (c->mfc_origin == htonl(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 != htonl(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 == htonl(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,34 @@ 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 == htonl(INADDR_ANY) &&
1867 cache->mfc_mcastgrp == htonl(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 != htonl(INADDR_ANY) ||
1885 ct != true_vifi) &&
1886 ip_hdr(skb)->ttl > cache->mfc_un.res.ttls[ct]) {
1806 if (psend != -1) { 1887 if (psend != -1) {
1807 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); 1888 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
1808 1889
@@ -1813,6 +1894,7 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
1813 psend = ct; 1894 psend = ct;
1814 } 1895 }
1815 } 1896 }
1897last_forward:
1816 if (psend != -1) { 1898 if (psend != -1) {
1817 if (local) { 1899 if (local) {
1818 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); 1900 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
@@ -1902,6 +1984,13 @@ int ip_mr_input(struct sk_buff *skb)
1902 1984
1903 /* already under rcu_read_lock() */ 1985 /* already under rcu_read_lock() */
1904 cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); 1986 cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
1987 if (cache == NULL) {
1988 int vif = ipmr_find_vif(mrt, skb->dev);
1989
1990 if (vif >= 0)
1991 cache = ipmr_cache_find_any(mrt, ip_hdr(skb)->daddr,
1992 vif);
1993 }
1905 1994
1906 /* 1995 /*
1907 * No usable cache entry 1996 * No usable cache entry
@@ -2107,7 +2196,12 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
2107 2196
2108 rcu_read_lock(); 2197 rcu_read_lock();
2109 cache = ipmr_cache_find(mrt, saddr, daddr); 2198 cache = ipmr_cache_find(mrt, saddr, daddr);
2199 if (cache == NULL && skb->dev) {
2200 int vif = ipmr_find_vif(mrt, skb->dev);
2110 2201
2202 if (vif >= 0)
2203 cache = ipmr_cache_find_any(mrt, daddr, vif);
2204 }
2111 if (cache == NULL) { 2205 if (cache == NULL) {
2112 struct sk_buff *skb2; 2206 struct sk_buff *skb2;
2113 struct iphdr *iph; 2207 struct iphdr *iph;
@@ -2609,16 +2703,16 @@ static int __net_init ipmr_net_init(struct net *net)
2609 2703
2610#ifdef CONFIG_PROC_FS 2704#ifdef CONFIG_PROC_FS
2611 err = -ENOMEM; 2705 err = -ENOMEM;
2612 if (!proc_net_fops_create(net, "ip_mr_vif", 0, &ipmr_vif_fops)) 2706 if (!proc_create("ip_mr_vif", 0, net->proc_net, &ipmr_vif_fops))
2613 goto proc_vif_fail; 2707 goto proc_vif_fail;
2614 if (!proc_net_fops_create(net, "ip_mr_cache", 0, &ipmr_mfc_fops)) 2708 if (!proc_create("ip_mr_cache", 0, net->proc_net, &ipmr_mfc_fops))
2615 goto proc_cache_fail; 2709 goto proc_cache_fail;
2616#endif 2710#endif
2617 return 0; 2711 return 0;
2618 2712
2619#ifdef CONFIG_PROC_FS 2713#ifdef CONFIG_PROC_FS
2620proc_cache_fail: 2714proc_cache_fail:
2621 proc_net_remove(net, "ip_mr_vif"); 2715 remove_proc_entry("ip_mr_vif", net->proc_net);
2622proc_vif_fail: 2716proc_vif_fail:
2623 ipmr_rules_exit(net); 2717 ipmr_rules_exit(net);
2624#endif 2718#endif
@@ -2629,8 +2723,8 @@ fail:
2629static void __net_exit ipmr_net_exit(struct net *net) 2723static void __net_exit ipmr_net_exit(struct net *net)
2630{ 2724{
2631#ifdef CONFIG_PROC_FS 2725#ifdef CONFIG_PROC_FS
2632 proc_net_remove(net, "ip_mr_cache"); 2726 remove_proc_entry("ip_mr_cache", net->proc_net);
2633 proc_net_remove(net, "ip_mr_vif"); 2727 remove_proc_entry("ip_mr_vif", net->proc_net);
2634#endif 2728#endif
2635 ipmr_rules_exit(net); 2729 ipmr_rules_exit(net);
2636} 2730}