struct inet_opt *inet = inet_sk(sk);
struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
struct rtable *rt;
+ u32 saddr;
+ int oif;
int err;
sk_dst_reset(sk);
- err = ip_route_connect(&rt, usin->sin_addr.s_addr, inet->saddr,
- RT_CONN_FLAGS(sk), sk->bound_dev_if);
+ oif = sk->bound_dev_if;
+ saddr = inet->saddr;
+ if (MULTICAST(usin->sin_addr.s_addr)) {
+ if (!oif)
+ oif = inet->mc_index;
+ if (!saddr)
+ saddr = inet->mc_addr;
+ }
+ err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
+ RT_CONN_FLAGS(sk), oif);
if (err)
return err;
if ((rt->rt_flags&RTCF_BROADCAST) && !sk->broadcast) {
return -EINVAL;
}
sk->bound_dev_if = usin->sin6_scope_id;
+ if (!sk->bound_dev_if && (addr_type&IPV6_ADDR_MULTICAST))
+ fl.oif = np->mcast_oif;
}
/* Connect to link-local address requires an interface */
fl.uli_u.ports.dport = inet->dport;
fl.uli_u.ports.sport = inet->sport;
+ if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST))
+ fl.oif = np->mcast_oif;
+
if (flowlabel) {
if (flowlabel->opt && flowlabel->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;