diff -ur linux-2.6.25.7/include/linux/mroute.h linux-2.6.25.7-mc/include/linux/mroute.h --- linux-2.6.25.7/include/linux/mroute.h 2008-06-16 22:24:36.000000000 +0200 +++ linux-2.6.25.7-mc/include/linux/mroute.h 2008-07-13 22:57:13.393350391 +0200 @@ -60,6 +60,16 @@ struct in_addr vifc_rmt_addr; /* IPIP tunnel addr */ }; +struct vifctln { + vifi_t vifc_vifi; /* Index of VIF */ + unsigned char vifc_flags; /* VIFF_ flags */ + unsigned char vifc_threshold; /* ttl limit */ + unsigned int vifc_rate_limit; /* Rate limiter values (NI) */ + struct in_addr vifc_lcl_addr; /* Our address */ + struct in_addr vifc_rmt_addr; /* IPIP tunnel addr */ + int vifc_ifindex; /* Index of real Interface */ +}; + #define VIFF_TUNNEL 0x1 /* IPIP tunnel */ #define VIFF_SRCRT 0x2 /* NI */ #define VIFF_REGISTER 0x4 /* register vif */ diff -ur linux-2.6.25.7/net/ipv4/ipmr.c linux-2.6.25.7-mc/net/ipv4/ipmr.c --- linux-2.6.25.7/net/ipv4/ipmr.c 2008-06-16 22:24:36.000000000 +0200 +++ linux-2.6.25.7-mc/net/ipv4/ipmr.c 2008-07-13 23:00:09.688053825 +0200 @@ -121,7 +121,7 @@ /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ static -struct net_device *ipmr_new_tunnel(struct vifctl *v) +struct net_device *ipmr_new_tunnel(struct vifctln *v) { struct net_device *dev; @@ -135,6 +135,7 @@ struct in_device *in_dev; memset(&p, 0, sizeof(p)); + p.link = v->vifc_ifindex; p.iph.daddr = v->vifc_rmt_addr.s_addr; p.iph.saddr = v->vifc_lcl_addr.s_addr; p.iph.version = 4; @@ -392,7 +393,7 @@ } } -static int vif_add(struct vifctl *vifc, int mrtsock) +static int vif_add(struct vifctln *vifc, int mrtsock) { int vifi = vifc->vifc_vifi; struct vif_device *v = &vif_table[vifi]; @@ -423,7 +424,10 @@ return -ENOBUFS; break; case 0: - dev = ip_dev_find(&init_net, vifc->vifc_lcl_addr.s_addr); + if (vifc->vifc_ifindex) + dev = dev_get_by_index(&init_net, vifc->vifc_ifindex); + else + dev = ip_dev_find(&init_net, vifc->vifc_lcl_addr.s_addr); if (!dev) return -EADDRNOTAVAIL; dev_put(dev); @@ -870,7 +874,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int optlen) { int ret; - struct vifctl vif; + struct vifctln vif; struct mfcctl mfc; if (optname != MRT_INIT) { @@ -908,9 +912,10 @@ return ip_ra_control(sk, 0, NULL); case MRT_ADD_VIF: case MRT_DEL_VIF: - if (optlen!=sizeof(vif)) + if (optlen != sizeof(vif) && optlen != sizeof(struct vifctl)) return -EINVAL; - if (copy_from_user(&vif,optval,sizeof(vif))) + vif.vifc_ifindex = 0; + if (copy_from_user(&vif, optval, optlen)) return -EFAULT; if (vif.vifc_vifi >= MAXVIFS) return -ENFILE;