Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to use the incoming IP address for sending outgoing packets #967

Merged
merged 1 commit into from
Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions quinn-proto/src/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ where
contents: buf,
ecn: None,
segment_size: None,
src_ip: self.local_ip,
});
}
}
Expand Down Expand Up @@ -554,6 +555,7 @@ where
None
},
segment_size: None,
src_ip: self.local_ip,
})
}

Expand Down
15 changes: 12 additions & 3 deletions quinn-proto/src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ where
ecn: None,
contents: buf,
segment_size: None,
src_ip: local_ip,
});
return None;
}
Expand Down Expand Up @@ -253,7 +254,7 @@ where

if !self.is_server() {
debug!("packet for unrecognized connection {}", dst_cid);
self.stateless_reset(datagram_len, remote, &dst_cid);
self.stateless_reset(datagram_len, remote, local_ip, &dst_cid);
return None;
}

Expand Down Expand Up @@ -288,7 +289,7 @@ where
//

if !dst_cid.is_empty() {
self.stateless_reset(datagram_len, remote, &dst_cid);
self.stateless_reset(datagram_len, remote, local_ip, &dst_cid);
} else {
trace!("dropping unrecognized short packet without ID");
}
Expand All @@ -299,6 +300,7 @@ where
&mut self,
inciting_dgram_len: usize,
remote: SocketAddr,
local_ip: Option<IpAddr>,
dst_cid: &ConnectionId,
) {
/// Minimum amount of padding for the stateless reset to look like a short-header packet
Expand Down Expand Up @@ -336,6 +338,7 @@ where
ecn: None,
contents: buf,
segment_size: None,
src_ip: local_ip,
});
}

Expand Down Expand Up @@ -535,6 +538,7 @@ where
debug!("refusing connection");
self.initial_close(
remote,
local_ip,
crypto,
&src_cid,
&temp_loc_cid,
Expand All @@ -553,6 +557,7 @@ where
);
self.initial_close(
remote,
local_ip,
crypto,
&src_cid,
&temp_loc_cid,
Expand Down Expand Up @@ -590,6 +595,7 @@ where
ecn: None,
contents: buf,
segment_size: None,
src_ip: local_ip,
});
return None;
}
Expand All @@ -608,6 +614,7 @@ where
debug!("rejecting invalid stateless retry token");
self.initial_close(
remote,
local_ip,
crypto,
&src_cid,
&temp_loc_cid,
Expand Down Expand Up @@ -645,7 +652,7 @@ where
debug!("handshake failed: {}", e);
self.handle_event(ch, EndpointEvent(EndpointEventInner::Drained));
if let ConnectionError::TransportError(e) = e {
self.initial_close(remote, crypto, &src_cid, &temp_loc_cid, e);
self.initial_close(remote, local_ip, crypto, &src_cid, &temp_loc_cid, e);
}
None
}
Expand All @@ -655,6 +662,7 @@ where
fn initial_close(
&mut self,
destination: SocketAddr,
local_ip: Option<IpAddr>,
crypto: &Keys<S>,
remote_id: &ConnectionId,
local_id: &ConnectionId,
Expand Down Expand Up @@ -683,6 +691,7 @@ where
ecn: None,
contents: buf,
segment_size: None,
src_ip: local_ip,
})
}

Expand Down
10 changes: 9 additions & 1 deletion quinn-proto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
#![allow(clippy::cognitive_complexity)]
#![allow(clippy::too_many_arguments)]

use std::{convert::TryInto, fmt, net::SocketAddr, ops, time::Duration};
use std::{
convert::TryInto,
fmt,
net::{IpAddr, SocketAddr},
ops,
time::Duration,
};

mod cid_queue;
#[doc(hidden)]
Expand Down Expand Up @@ -277,6 +283,8 @@ pub struct Transmit {
/// The segment size if this transmission contains multiple datagrams.
/// This is `None` if the transmit only contains a single datagram
pub segment_size: Option<usize>,
/// Optional source IP address for the datagram
pub src_ip: Option<IpAddr>,
}

//
Expand Down
30 changes: 28 additions & 2 deletions quinn/src/platform/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{
io,
io::IoSliceMut,
mem::{self, MaybeUninit},
net::{IpAddr, SocketAddr, SocketAddrV4, SocketAddrV6},
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
os::unix::io::AsRawFd,
ptr,
};
Expand Down Expand Up @@ -273,7 +273,7 @@ pub fn caps() -> UdpCapabilities {
*CAPABILITIES
}

const CMSG_LEN: usize = 64;
const CMSG_LEN: usize = 80;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was updated to account for GSO + src-ip setting


fn prepare_msg(
transmit: &Transmit,
Expand Down Expand Up @@ -312,6 +312,32 @@ fn prepare_msg(
gso::set_segment_size(&mut encoder, segment_size as u16);
}

if let Some(ip) = &transmit.src_ip {
if cfg!(target_os = "linux") {
match ip {
IpAddr::V4(v4) => {
let pktinfo = libc::in_pktinfo {
ipi_ifindex: 0,
ipi_spec_dst: unsafe {
*(v4 as *const Ipv4Addr as *const () as *const libc::in_addr)
djc marked this conversation as resolved.
Show resolved Hide resolved
djc marked this conversation as resolved.
Show resolved Hide resolved
},
ipi_addr: libc::in_addr { s_addr: 0 },
};
encoder.push(libc::IPPROTO_IP, libc::IP_PKTINFO, pktinfo);
}
IpAddr::V6(v6) => {
let pktinfo = libc::in6_pktinfo {
ipi6_ifindex: 0,
ipi6_addr: unsafe {
*(v6 as *const Ipv6Addr as *const () as *const libc::in6_addr)
},
};
encoder.push(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO, pktinfo);
}
}
}
}

encoder.finish();
}

Expand Down