-
-
Notifications
You must be signed in to change notification settings - Fork 621
Open
Labels
Description
Hi,
I would be nice to gain access to the SO_ORIGINAL_DST option using the socket.
I wrote a transparent proxy to be used on a linux machine, and therefore need the destination address.
I patched fs2 to get this option, but I think it would be useful for other projects.
There are two possible solutions:
- Grant access to the native FD in Socket. (should return an UnsupportedException on the JVM)
- Include the SO_ORIGINAL_DST option in the getOption method (only in scala-native...)
The code would be something like:
def getOptOriginalDest[F[_]](fd: CInt)(implicit F: Sync[F]): F[Option[SocketAddress[IpAddress]]] = {
F.delay {
val SOL_IP = 0
val SO_ORIGINAL_DST = 80
val size = sizeOf[sockaddr_storage]
val ptr = stackalloc[Byte](size)
val szPtr = stackalloc[UInt]()
!szPtr = size.toUInt
val ret = guardMask(
getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, ptr, szPtr)
)(_ == ENOPROTOOPT)
if (ret == ENOPROTOOPT) None else {
val sockaddr = ptr.asInstanceOf[Ptr[sockaddr_storage]]
if(sockaddr._1 == AF_INET) {
val dstStr = stackalloc[Byte](INET_ADDRSTRLEN)
val addr = ptr.asInstanceOf[Ptr[sockaddr_in]]
val addr_in = addr.sin_addr
val port = htons(addr.sin_port).toInt
inet_ntop(AF_INET, addr_in.toPtr.asInstanceOf[CVoidPtr], dstStr, INET_ADDRSTRLEN.toUInt)
SocketAddress.fromString4(s"${fromCString(dstStr)}:$port")
} else if(sockaddr._1 == AF_INET6) {
val dstStr = stackalloc[Byte](INET6_ADDRSTRLEN)
val addr = ptr.asInstanceOf[Ptr[sockaddr_in6]]
val addr_in = addr.sin6_addr
val port = htons(addr.sin6_port).toInt
inet_ntop(AF_INET6, addr_in.toPtr.asInstanceOf[CVoidPtr], dstStr, INET6_ADDRSTRLEN.toUInt)
SocketAddress.fromString6(s"${fromCString(dstStr)}:$port")
} else {
println("Something went wrong during getsockopt")
None
}
}
}
}
What do you think?
I could help making a PR if needed
Thanks for this great library