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

Support abritrary socket adresses #918

Open
niklaswimmer opened this issue Nov 3, 2023 · 5 comments
Open

Support abritrary socket adresses #918

niklaswimmer opened this issue Nov 3, 2023 · 5 comments

Comments

@niklaswimmer
Copy link

Rustix can currently not be used to bind sockets which are not unix or ip. The only real requirement on a socket address is that it starts with an u16 (the address family) - judging from the types used in the definition of the bind syscall.

My specific use case is binding bluetooth sockets and my current workaround is to just call libc::bind instead (using the fd returned by rustix's socket_with).

I am unsure what a good API would look like, but ideally it would not require me to construct a [u8] array myself and instead work with structs which are then automatically converted into byte arrays when it comes to invoking the syscall. For my use case I wrote a helper module that uses unions to convert some struct into a libc::sockaddr if you want to take a look.

This issue also blocks usage of eyra for any programs that need to work with some non-well-known sockets.

I would be happy to help implementing this API, but as noted above I am not sure about the design and would require some input.

@sunfishcode
Copy link
Member

Interesting question.

I think my preference here is to add a Bluetooth arm to SocketAddrAny for bluetooth, containing a SocketAddrBluetooth, similar to the Unix arm, which encapsulates a bluetooth address, and then teach the encode/decode logic to handle it.

That said, at a quick search, I found about 40 sockaddr_* types in Linux's headers. I don't have any idea how commonly used they all are. If rustix is going to end up supporting a lot of them, it may make sense to switch over to just exposing arbitrary bytes and letting users or other crates sort it out.

However, my guess is, for now, it makes sense to stick with typed interfaces and adding address families such as SocketAddrBluetooth when people have a need for them, and we'll see how far we get.

Does that make sense?

@nbdd0121
Copy link
Contributor

nbdd0121 commented Dec 3, 2023

I tried to add SocketAddrNetlink to rustix but it involves an incredible amount of code duplication. Currently there's a copy of connect, bind, sendmsg, sendto for every single type of sockaddr and I don't think that'll be sustainable if more types of addresses are to be added.

@sunfishcode
Copy link
Member

The purpose of having connect_v4/connect_v6/connect_unix instead of just connect/connect_any is just to avoid the construction of a SocketAddr/SocketAddrAny in common cases. Compared to V4/V6/Unix, I assume all other socket address types are far less commonly used, so it seems ok to just add entries to SocketAddrAny and use connect_any, and not add new specialized connect_* etc. routines. Does that sound feasible?

@nbdd0121
Copy link
Contributor

nbdd0121 commented Dec 9, 2023

For clarification, I am talking about the syscall side. connect_v4/connect_v6/connect_unix all just encode the sockaddr and perform a syscall.

@nbdd0121
Copy link
Contributor

nbdd0121 commented Dec 9, 2023

Would it make sense to have a SocketAddr trait, that just does encode and decode to sockaddr_*?

trait SocketAddr {
    fn encode(&self) -> SocketAddrStorage;
    fn decode(storage: &SocketAddrStorage) -> Result<Self>;
}

I am not sure why we currently have two methods of encoding/decoding, and duplicate for both backends for each sockaddr (4 redundant copies!).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants