简体   繁体   中英

Linux UDP in kernel space get sockaddr_in

I use UDP in kernel space. When some packet is incoming, I store it on workqueue_struct and then I process it. Everything working. Now I would like send answer to client. So, I need IPv4 address from struct sock .

I found out function kernel_getsockname() but this function not return sockaddr_in which I need to sock_sendmsg() .

My question is: How can I get sockaddr_in from struct sock ?

The client address is in is a struct sockaddr_in then you can get the ip address from client_addr.sin_addr.s_addr. It will be a 32 bit unsigned integer.

for eg.

struct sockaddr_in* clientAddr = (struct sockaddr_in*)&client_addr; int ip = clientAddr->sin_addr.s_addr;

According to linux kernel documentation, ( https://www.kernel.org/doc/htmldocs/networking/API-struct-sock.html ) struct sock has a member named sk_rcv_saddr which can be equated to struct cnic_sockaddr *saddr

cnic_sockaddr has local and remote sockaddr_in structure members and you can get ip address from it. For exemple, Im not sure, but...

struct cnic_sockaddr saddr = sk.sk_rcv_saddr;

where sk is sock structure variable. so your sockaddr_in is

saddr.remote.v4

and you can parse it like that:

char* parse_sinaddr(const struct in_addr saddr)
{ 
    static char ip_str[16];
    bzero(ip_str, sizeof(ip_str));
    int printed_bytes = 0;

    printed_bytes = snprintf(ip_str, sizeof(ip_str), "%d.%d.%d.%d", 
        (saddr.s_addr&0xFF), 
        ((saddr.s_addr&0xFF00)>>8), 
        ((saddr.s_addr&0xFF0000)>>16), 
        ((saddr.s_addr&0xFF000000)>>24));

    if (printed_bytes > sizeof(ip_str)) return NULL;

    return ip_str;
}


char *ip_str = parse_sinaddr(saddr.remote.v4.sin_addr.in_addr);

You need to get the source IP from the received packet because an UDP socket in itself doesn't contain the remote end point (because UDP is 1-to-many).

Your packet is essentially contained in the sk_buff . You could try do do that to get the remote IP :

struct iphdr *ip_header = ip_hdr(skb);
to.sin_addr.s_addr = ip_header->saddr;

ip_hdr() is in linux/ip.h .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM