Sendmsg(UDP) with ancillary message to set source port - c

I have a UDP socket on which i have specified the IP_PKTINFO flag
to pass a ancillary message containing a pktinfo struct to set a custom source address
struct in_pktinfo {
unsigned int ipi_ifindex;
struct in_addr ipi_spec_dst;
struct in_addr ipi_addr;
};
struct in_addr is just wrapping struct around a unsigned long
struct in_addr {
unsigned long s_addr; // load with inet_aton()
};
On my implementation:
Datagrams arriving on a transparent UDP socket(tproxy), analyzed, processed
and then forwarded to a specific destination(Port Address Translation).
So it is crucial for me to set the source IP as well as source port.
I can realize setting a specific source port if i open new socket and bind to it,
because of the large amount of datagrams it is very inefficient.
Questions:
is there anyway to set the source port without multiple sockets/binds or using a raw socket.

Related

How to read sk_buff data if we have have sock structure of specific process?

I have written a program where I can access the sock struct of the specific process but want to read sport and dport by reading sk_buff. But, I am unable to access sk_buff from the sock struct. Is it possible to do it?
If buf is a struct sk_buff*, then its source and destination ports are
buf->sk->sk_num
buf->sk->sk_dport
respectively.
This works since struct sk_buff contains a pointer to a struct sock, which defines a few macros to allow easy access to the port numbers you're looking for.

eBPF: how to get the socket associated to a sock from a `struct __sk_buff`

I am currently writing an eBPF program in C to track egress network packets using tc-bpf. The program has its definition as follows:
SEC("classifier")
int bpf_tc_sample(struct __sk_buff *skb) {
[...]
return TC_ACT_OK;
}
In my program, I need to get the socket associated with the sock of the socket buffer.
If the type of the socket buffer would have been struct sk_buff this could have been done by accessing skb->sk->sk_socket. In this case, the type of skb->sk is struct bpf_sock and not struct sock which does not contain an entry for sk_socket.
Could anyone please let me know whether there is a way to access the struct socket field from a struct __sk_buff entry in an eBPF program, either through a BPF helper or via using a kprobe.
Any insight will be appreciated.

How can I get the address and port of a client in C sockets (sys/socket.h)?

I am currently messing around with sockets (on a UNIX based system) and would like to get the address and port of a client when they connect. How can I do this?
You can extract it from a struct sockaddr_in (or sockaddr_in6).
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
See the man page: http://man7.org/linux/man-pages/man7/ip.7.html
Also, you can see my DNS-server code as a practical example (there is extracted IPV6 address sin6.sin6_addr).

Be confused with msg_name field in msghdr structure

In user space, I encapsulated a L3 packet using sock_raw (including IP header) and send to kernel space using sock_sendmsg() using msghdr structure
struct msghdr {
void *msg_name; /* optional address */
struct iovec *msg_iov; /* scatter/gather array */
...
};
I cannot understand clearly the roles of msg_name. I already specified the source IP and dest IP in L3 header. Why do I need msg_name?
The msg_name and msg_namelen fields of struct msghdr have the same function as the dest_addr and addrlen arguments to sendto: they specify the destination address. They are intended to be used with normal unconnected datagram sockets. For instance, when sending UDP packets with sendmsg on an AF_INET/SOCK_DGRAM socket, you supply only the payload, not the headers, in the iovec, and the destination address goes in msg_name + msg_namelen.
raw(7), the manpage describing SOCK_RAW sockets, indicates that you are allowed to put the header into the iovec when using raw sockets (note in particular the discussion of IP_HDRINCL) but does not make clear what you should set msg_name and msg_namelen to in that case. I would recommend you try setting both of them to 0 and see if that works.

sockaddr structure - (sys/socket.h)

Ive been reading the sys/socket.h all day and finally starting to understand it, and now starting to use it, however, I'm not sure why I can't assign a value to sa_family member of the sockaddr struct.
Specification sockaddr Structure:
struct sockaddr{
sa_family_t sa_family address family
char sa_data[] socket address (variable-length data)
};
Data Type: sa_family_t - Unsigned integral type (2-4 bytes)
Values:
Name Purpose Man page
AF_UNIX, AF_LOCAL Local communication unix(7)
AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_IPX IPX - Novell protocols
AF_NETLINK Kernel user interface device netlink(7)
AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7)
AF_AX25 Amateur radio AX.25 protocol
AF_ATMPVC Access to raw ATM PVCs
AF_APPLETALK AppleTalk ddp(7)
AF_PACKET Low level packet interface packet(7)
AF_ALG Interface to kernel crypto API
Which is a bit confusing since these values are char data types not an unsigned int.
Simple Test:
#include<stdio.h>
#include<sys/socket.h>
int main(void){
struct sockaddr_in address;
address.sin_family = AF_INET;
printf("Socket Address Family: %s\n", address.sin_family);
return 0;
}
Error:
storage size of ‘address’ isn’t known
It should be printing out Socket Address Family: AF_INET... what am I missing here?
It is because you don't include the definition of that structure. The structure sockaddr_in is defined in <netinet/in.h>. For more details, see: sockaddr_in undeclared identifier

Resources