sockaddr structure - (sys/socket.h) - c

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

Related

Send Raw arp reply packet in windows

I am currently learning how to use the windows raw sockets.
I created a raw arp reply frame(includes all headers (ethernet+arp headers)), and when I send it using sendto function,
It fails and return SOCKET_ERROR with error code 10047.
The parameters I used to create the socket are as follows:
socket s = socket(AF_INET,SOCK_RAW,IPPROTO_RAW);
and also I changed the socket options as follows:
int on=1;
setsockopt(s,IPPROTO_IP, 2,(char*)&on,sizeof(on));
(By the way, '2' is equal to IP_HDRINCL, for some reason, visual studio didn't recognize it..)
I try to send the packet as follows:
socketaddr sa = { 0 };
int SentBytesCount = sendto(s, (char*)&arp_raw_msg,sizeof(Arp_Frame),0,&sa,sizeof(sa));
Where Arp_Frame is a struct that includes ethernet header+arp header+18 Bytes for padding.
After this call I get that SentBytesCount is equal to SOCKET_ERROR(-1), and no packet is sent.
Thank you for your help!
Winsock error 10047 is WSAEAFNOSUPPORT:
Address family not supported by protocol family.
An address incompatible with the requested protocol was used. All sockets are created with an associated address family (that is, AF_INET for Internet Protocols) and a generic protocol type (that is, SOCK_STREAM). This error is returned if an incorrect protocol is explicitly requested in the socket call, or if an address of the wrong family is used for a socket, for example, in sendto.
You created an AF_INET (IPv4) socket, but you are not passing sendto() a valid sockaddr_in containing an IPv4 address and port, hence the error. You are passing it an empty socketaddr (what is that?) instead.
Any sockaddr_... struct you use with a socket must match what the socket's address family expects, as set by the socket() call (in your case, AF_INET, which uses sockaddr_in addresses).
sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr("destination IP address");
sa.sin_port = htons(Destination port number);
int SentBytesCount = sendto(s, (char*)&arp_raw_msg, sizeof(Arp_Frame), 0, (struct sockaddr*)&sa, sizeof(sa));
As for IP_HDRINCL, it is defined in ws2tcpip.h.

What is the socket address family defined by 30?

I am writing a simple FTP server program in C. I am mostly following Beej's Guide to Network Programming. In order to complete the pasv mode functionality, I have to create another socket and send its ip and port to the client.
Since gethostbyname() is deprecated, I am using getsockname() to get my current network IP address. My plan is that I separate two cases (ipv4 and ipv6) and send info to the client accordingly. But, whenever I try to get the address family it always 30. I am not sure if I am printing this correctly though.
I am doing something simple like this (which might include mistakes), and it prints 30.
struct sockaddr_storage my_addr;
int result;
socklen_t len = sizeof(my_addr);
result = getsockname(current_fd, (struct sockaddr *) &my_addr, &len);
if (my_addr.ss_family == AF_INET) { // ipv4
struct sockaddr_in * ipv4 = (struct sockaddr_in *) &my_addr;
addr = &(ipv4->sin_addr);
} else { // ipv6
struct sockaddr_in6 * ipv6 = (struct sockaddr_in6 *) &my_addr;
addr = &(ipv6->sin6_addr);
}
printf(" family: %u\n", (unsigned short) my_addr.ss_family);
When I searched this online, I got:
#define AF_ATM 30 /* ATM */
What is this exactly? Is this expected? If not, where am I doing something wrong?
Thank you.
Edit:
Apparently what it was printing was something different.
It is not defined as:
#define AF_ATM 30 /* ATM */
but it is defines as:
MT IPv6: Multi-Topology IP version 6 [RFC7307]

"UDP datagrams only" socket in C

In Linux, Ubuntu 14.04:
I'm writing a code that implements socket to send pure UDP datagrams which includes UDP header+payload, without any part of IP header.
I have created the socket
sokt_fd=socket(AF_INET, SOCK_RAW, IPPROTO_UDP)
Also, I have prepared the UDP header.
I want to leave the IP encapsulation process to the kernel.
I want to send the datagram over any available IP interface. (I do not want to specify the source IP, and also leave this task to the kernel).
Do I need to specify the destination IP address before sending the datagram.
I must use "sendto()" command to send the datagram; how I must fill the "sockaddr" data structure?
#include <netinet/in.h>
struct sockaddr
{
unsigned short sa_family;// address family, AF_xxx
char sa_data[14];// 14 bytes of protocol address
};
Don't use the sockaddr structure. Use sockaddr_in instead and cast it when you have to pass a sockaddr* to a function.
struct sockaddr_in myaddr;
int s;
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(3490);
inet_aton("63.161.169.137", &myaddr.sin_addr.s_addr);
s = socket(PF_INET, SOCK_STREAM, 0);
bind(s, (struct sockaddr*)myaddr, sizeof(myaddr));
The socket API is designed for different addressing families, others are Infrared and Bluetooth. Since AF_INET is only one of the families the API functions use the general sockaddr type in the parameters.
There is a nice explanation of this in Chapter 3, "Sockets Introduction" in the well-known book Unix Network Programming, The Sockets Networking API (Volume 1) by Richard Stevens et. al. Let me quote:
Most socket functions require a pointer to a socket address structure
as an argument. Each supported protocol suite defines its own socket
address structure. The names of these structures begin with
sockaddr_ and end with a unique suffix for each protocol suite.
For the IP (Internet protocol) suite, the structure is sockaddr_in so it follows that since your example is specifying the AF_INET address family when you created the socket that you would use the more specific sockaddr_in structure instead of the more generic sockaddr. The socket API, as a matter of efficiency uses the more generic sockaddr pointer in the signature prototype.
With regard to using send() versus sendto(), I have found that sendto() is used more commonly with UDP and send() with TCP sockets. Therefore, to answer your question in #3 above, with UDP you don't have to specify the destination address up front, but instead it is supplied as an argument to sendto().
For a given udp_datagram and datagram_length, your code might look something like this:
uint32_t address = inet_addr("1.2.3.4"); // can also provide hostname here
uint16_t port = 27890;
sockaddr_in_t dest_addr;
memset(*dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
dest_addr.sin_addr.s_addr = htonl(address);
sendto(socket_fd,
(const char*)upd_datagram,
datagram_length,
0,
reinterpret_cast<sockaddr_t*>(&dest_addr),
sizeof(dest_addr));
The address API really wanted to be object-oriented, but had to deal with the fact that C isn't an OO language. sockaddr can be seen as the "base class" and the parameter type that bind, connect, sendto, recvfrom, etc. use when they need an address. However, you must provide a "subclassed" address matching the socket domain that you're using. This is because Berkeley sockets can be used for a wide and extensible range of protocols. IPv4 and IPv6 are the most typical, but UNIX-based installs also support sockets as filesystem objects ("addressed" by path), and, for instance, a hypervisor driver can install support for special inter-VM or guest-to-host sockets. See man 7 socket for an overview.
If you use IPv4, you need to use sockaddr_in. If you use IPv6, you need to use sockaddr_in6. In both cases, you need to cast your pointer to a sockaddr*.
To fill in a sockaddr_in, you need to do something like this:
struct sockaddr_in inet_addr;
inet_addr.sin_family = AF_INET;
inet_addr.sin_port = htons(port);
inet_addr.sin_addr.s_addr = htonl(ip_address_as_number);
struct sockaddr* addr = (struct sockaddr*)&inet_addr;
htons and htonl stand for "host to network (short)" and "host to network (long)", respectively. You need this because there was a time at which network drivers were too dumb to abstract away the machine's endianness and we can't go back in time to fix them. (The network byte order is big endian.)

how to find clients ip address using tcp socket programming in c

I am trying to develop a TCP server, in that server clients are connecting with the server after the set up the connection. But how do i find the ip address from that connection. Sample codes are given here.
int connfd;
int listenfd;
struct sockaddr_in cliaddr;
socklen_t clilen;
connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
this is not the exact code. But now i need to find the client address as a string.
accept() gives you the client's remote IP address and port number in the sockaddr_in struct that it fills in, in the sin_addr and sin_port struct members, respectively. Both values are numeric values in network byte order. You can use a function like inet_ntoa() to convert the IP into a human-readible string, and ntohs() to convert the port number into an integer whose byte order matches the calling machine so you can work with it more naturally.
Also look at the getpeername() and getsockname() functions.
cliaddr is the structure variable for of structure sockaddr_in for the client.
cliaddr.sin_addr.s_addr contains the client's IP address.
inet_ntop(AF_INET, &(cliaddr.sin_addr), clientAddr, CLADDR_LEN); Retrieves the IP address of the client into a string clientAddr.

why we still have the sun_family in the struct sockaddr_un?

I'm a newbie in UNIX programming. Normally, when we use local socket to communicate, the domain is always AF_UNIX or AF_LOCAL. So in this case, struct sockaddr_un serves always for the local communication. Why there is still "short sun_family"? For a historical reason?
struct sockaddr_un{
short sun_family; /*AF_UNIX*/
char sun_PATH[108]; /*path name */
};
You pass a sockaddr * to several socket functions (e.g. connect, bind, sendto) - these will look at the family variable before casting to e.g. sockaddr_un * or sockaddr_in *

Resources