How to use socket_t (socket reference) to get ip and port in Network Kernel Extension of Mac OS - kernel-extension

I am writing the Socket filter in which most of call back functions for socket filtering(struct sflt_filter) have input parameter socket_t so as shown below:
errno_t ( *sf_bind_func)(
void *cookie,
socket_t so,
const struct sockaddr *to);
Need to get Port and IP from socket_t so.
Is anyone have the idea how to do this?

Got the solution in OSx and iOS Kernel programming Book.
function sock_getsockname() do the job. Find following code snippet:
unsigned char addrStr[256];
struct sockaddr_in addrLcl;
sock_getsockname(so, (struct sockaddr *)&addrLcl, sizeof(addrLcl));
inet_ntop(AF_INET, &addrLcl.sin_addr, (char *)addrStr, sizeof(addrStr));
printf("SFWebSecBind() : <%s> Hex:<%X>", addrStr, ntohs(addrLcl.sin_port));

Related

How to know through which network interface ip address is pinged?

I am progrmmatically pininging ip address using c++ in windows.
I used the code from this link for pinging https://www.codeproject.com/Articles/647/Ping-for-Windows
I am receiving reply from this function
WSAAPI
recvfrom(
SOCKET s,
char FAR * buf,
int len,
int flags,
struct sockaddr FAR * from,
int FAR * fromlen
);
From this function, How to know through which local network interface I am receiving the reply or able to ping?
Thanks.

How do I replicate a C++ cast of Windows SOCKADDR_BTH to a SOCKADDR in Rust?

I am writing a Bluetooth utility on Windows in Rust, using winsock2 (but happy to use any other libraries) and have hit a roadblock. The following C++ sample from the Windows Bluetooth Connection Sample is what I am using as a reference:.
SOCKADDR_BTH SockAddrBthServer;
# code to set SockAddrBthServer vals in here
connect(LocalSocket, (struct sockaddr *) &SockAddrBthServer, sizeof(SOCKADDR_BTH));
The structs are defined like so:
typedef struct _SOCKADDR_BTH
{
USHORT addressFamily; // Always AF_BTH
BTH_ADDR btAddr; // Bluetooth device address
GUID serviceClassId; // [OPTIONAL] system will query SDP for port
ULONG port; // RFCOMM channel or L2CAP PSM
} SOCKADDR_BTH, *PSOCKADDR_BTH;
typedef struct sockaddr {
#if (_WIN32_WINNT < 0x0600)
u_short sa_family;
#else
ADDRESS_FAMILY sa_family; // Address family.
#endif //(_WIN32_WINNT < 0x0600)
CHAR sa_data[14]; // Up to 14 bytes of direct address.
} SOCKADDR, *PSOCKADDR, FAR *LPSOCKADDR;
How do I replicate the (struct sockaddr *) &SockAddrBthServer cast from the connect line above in Rust? So far, I'm making use of the winapi, user32 and ws2_32 crates.
Here is the Rust version of the connect function from the ws2_32 crate.
pub unsafe extern "system" fn connect(s: SOCKET, name: *const SOCKADDR, namelen: c_int) -> c_int
You are overthinking the problem. If Windows says it's cool to cast a SOCKADDR_BTH pointer to a SOCKADDR pointer, then just do that. In Rust, you have to add one extra cast to leave the safe world of references and get to a raw pointer, then you can cast that to whatever you want:
use std::mem;
struct SomeErrorType;
fn example(LocalSocket: SOCKET) -> Result<SOCKADDR_BTH, SomeErrorType> {
unsafe {
let SockAddrBthServer: SOCKADDR_BTH = mem::uninitialized();
let retval = connect(
LocalSocket,
&SockAddrBthServer as *const SOCKADDR_BTH as *const SOCKADDR,
mem::size_of::<SOCKADDR_BTH>() as i32,
);
// PERFORM REAL ERROR CHECKING HERE
if retval == 42 {
Ok(SockAddrBthServer)
} else {
Err(SomeErrorType)
}
}
}
(Untested because I don't have a Windows machine handy)
Under the hood, this will only work as long as the initial members of SOCKADDR_BTH exactly match the members of SOCKADDR.

Why is the addr variable type-converted?

While surfing on the internet I've found a c++ example that sends GET-requests. The part of this code I couldn't grasp is why (see the section that's bold) the variable addr is type converted. I understand that the function only accepts a certain type. But why using a type and then converting it to another one?
#include <iostream>
#include <sys/socket.h>
#include <resolv.h>
#include <arpa/inet.h>
using namespace std;
int main()
{
int s, error;
struct sockaddr_in addr;
if((s = socket(AF_INET,SOCK_STREAM,0))<0)
{
cout<<"Error 01: creating socket failed!\n";
close(s);
return 1;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
inet_aton("204.27.61.92",&addr.sin_addr);
error = connect(s,(sockaddr*)&addr,sizeof(addr));
if(error!=0)
{
cout<<"Error 02: conecting to server failed!\n";
close(s);
return 1;
}
char msg[] = "GET /beej/inet_ntoaman.html http/1.1\nHOST: retran.com\n\n";
char answ[1024];
//cin.getline(&msg[0],256);
send(s,msg,sizeof(msg),0);
while(recv(s,answ,1024,0)!=0)
cout<<answ<<endl;
close(s);
cin.getline(&msg[0],1);
return 0;
}
This is runtime polymorphism, C style.
sockaddr is effectively an abstract base class - it isn't specific to any concrete type of socket. However, each socket type requires type-specific information.
Since C doesn't have language support for polymorphism, the technique is to write a "derived" type which has the "base" type as it's first data member. This way they have the same address, and you can cast between them.
So, (sockaddr*)&addr is an upcast, yielding a pointer to a valid base-class subobject. When you pass this to an AF_INET socket, it will cast the pointer back to (sockaddr_in*) and recover your inet-specific data.
Equivalent C++ for reference, since it's slightly more expressive:
class SockAddr {
public:
virtual ~SockAddr();
enum Family { INET, UNIX, ... };
Family get_family() const { return family; }
protected:
explicit SockAddr(Family f) : family(f) {}
Family family;
};
class SockAddrInet: public SockAddr {
uint16_t port;
uint32_t addr;
public:
SockAddrInet(uint16_t port, uint32_t addr)
: SockAddr(SockAddr::INET), port(htons(port)), addr(addr)
{}
};
class SockAddrUnix: public SockAddr {
std::string path;
public:
explicit SockAddrInet(std::string path)
: SockAddr(SockAddr::UNIX), path(path) {}
};
void connect(Socket &s, SockAddr const &addr) {
switch (addr.get_family()) {
case SockAddr::INET:
connect_inet(s, dynamic_cast<SockAddrInet const&>(addr));
break;
case SockAddr::UNIX:
connect_unix(s, dynamic_cast<SockAddrUnix const&>(addr));
break;
}
}
It's a technique to have "subtypes" in C. There are various other sockaddr types (e.g. sockaddr_in6 for IPv6). The called function inspects the sin_family field to determine which kind of struct was passed in and handle it accordingly.
struct sockaddr {
u_short sa_family;
char sa_data[14];
};
We have to remember that the socket APIs can work with many different network protocols. Each protocol has a completely different format for how addresses work. This sockaddr structure is, therefore, a generic structure. It contains a place to put the identifying address family, along with a generic "data" field that the address can be placed in, regardless of the format of the address.
There is however the sockaddr_in structure:
struct sockaddr_in { /* socket address (internet) */
short sin_family; /* address family (AF_INET) */
u_short sin_port; /* port number */
struct in_addr sin_addr; /* IP address */
char sin_zero[8]; /* reserved - must be 0x00's */
};
which is designed specially for networking, IP address. This type can be safely type casted to sockaddr* because it is aligned to it.
This is what Richard Stevens says about it in his "UNIX Network Programming":
Generic Socket Address Structure
A socket address structures is always passed by reference when passed as an argument to
any socket functions. But any socket function that takes one of these pointers as an
argument must deal with socket address structures from any of the supported protocol
families.
A problem arises in how to declare the type of pointer that is passed. With ANSI C, the
solution is simple: void * is the generic pointer type. But, the socket functions predate ANSI C and the solution chosen in 1982 was to define a generic socket address structure in the <sys/socket.h> header (...)
struct sockaddr {
uint8_t sa_len;
sa_family_t sa_family; /* address family: AF_xxx value */
char sa_data[14]; /* protocol-specific address */
};
The socket functions are then defined as taking a pointer to the generic socket address
structure, as shown here in the ANSI C function prototype for the bind function:
int bind(int, struct sockaddr *, socklen_t);
This requires that any calls to these functions must cast the pointer to the protocol-specific socket address structure to be a pointer to a generic socket address structure. (...)
From the kernel's perspective, another reason for using pointers to generic socket address
structures as arguments is that the kernel must take the caller's pointer, cast it to a struct sockaddr *, and then look at the value of sa_family to determine the type of the structure.
But from an application programmer's perspective, it would be simpler if the pointer type was void *, omitting the need for the explicit cast.
Returning to the windows's connect function ::connect
http://msdn.microsoft.com/en-us/library/windows/desktop/ms737625%28v=vs.85%29.aspx
It requires sockaddr as a parameter type

WSAEFAULT error when use getsockname function

I have a problem using getsockname function. I have this code:
struct sockaddr sa;
int sa_len;
sa_len = sizeof(sa);
if (getsockname(socketfd, &sa, &sa_len) != SOCKET_ERROR)
{
///
}
else
{
int error = WSAGetLastError();
//error here WSAEFAULT always
}
As you can see, i always have error when use getsockname function. Error - WSAEFAULT. But why? structure and structure size are right, why this happens?
WSAEFAULT desc:
The name or the namelen parameter is not a valid part of the user
address space, or the namelen parameter is too small.
p.s. Application is 64 bit
Thanks!
Your struct sockaddr is too small to accept the socket address. Either use an appropriately sized struct, such as struct sockaddr_in, or better yet, use a struct sockaddr_storage, which is guaranteed to be large enough to contain the address. Using a sockaddr_storage also allows you to easily support both IPv4 and IPv6 with minimal adjustments.
Edited code:
struct sockaddr_storage sa;
int sa_len;
sa_len = sizeof(sa);
if (getsockname(socketfd, (struct sockaddr *)&sa, &sa_len) != SOCKET_ERROR)
Instead of general struct sockaddr use the one specified for your protocol i.e. *struct sockaddr_in* for IPv4 address. See here for a complete example.

Programmatically verify if a UDP port is bound in C/C++

Without attempting to bind it
This should do the trick...
int getsockname(int socket, struct sockaddr *restrict address,
socklen_t *restrict address_len);