Zero is usually right for a protocol? - c

I have been going through the GNU, libc manual on using the sockets. As per to the documentation here
Exact wording from the documentation is,
zero is usually right for protocol.
I have seen several examples of code where engineers have put 0 for the protocol when implementing a socket regardless of the protocol in use!
int socket (int namespace, int style, int protocol)
May I know, What does the author mean by above statement ? I could sense that there are situations in which 0 might not be the correct answer as per to the author's statement, If so, would it be possible for someone to elaborate on such scenarios ? Most importantly where do we get the value for protocol ? Is there any standard to refer to for protocol numbers ?

The valid values for protocol is dependent on the namespace used and the kernel the program is running on.
I assume, since the question is tagged gnu, that you are running under linux. You may then find a list of valid namespaces, and links to documentation of those namespaces with man 'socket(2)'. For instance, you may find documentation for the internet namespaces AM_INET and AM_INET6 under man 'ip(7)' and man 'ipv6(7)'
Reading the ip(7) manpage you may then see that AM_INET supports protocols IPPROTO_TCP and IPPROTO_SCTP for stream sockets, and IPPROTO_UDP and IPPROTO_UDPLITE for datagram sockets.
If you want to dig further, the different protocols also have their own manpages

Related

meaning of 'CG' in SIOCGIF* in netdevice(7)?

Linux netdevice(7) interface introduces a number of SIOCGIF* constants, for example, SIOCGIFNAME.
I suppose the latter reads as "socket i/o ?? interface name", where ?? stands for "CG".
So what is "CG" then? Shall be something simple, but I'm a little stuck here. ( And I'm in a habit of knowing of what my identifiers mean, hence the question )
Probably Socket I/O Control - Get InterFace NAME.
It seems obvious that ioctl stands for "I/O Control" (but if not then just consider that IOC stands for IOCTL)
We can see the TIOC prefix used on some older Terminal I/O Controls. T for Terminal and S for Socket - makes sense.
You can also notice the Get functions have G and the Set functions have S.
And IFNAME seems clear enough.

What are the equivalents of IP_RECVOPTS and IP_RECVRETOPTS in Windows

I'm doing some socket programming that I'm trying to make cross-platform compatible. For Windows systems, I'm including the following headers:
#include <winsock2.h>
#include <ws2tcpip.h>
When I tried to compile my application on Windows, I got errors about the following constants' being undefined:
IP_RECVOPTS
IP_RECVRETOPTS
I thought that odd, because I thought those were pretty common socket options, but perhaps I'm wrong. Either way, sure enough, they're not listed anywhere in the Windows socket documentation.
The documentation in a Linux distro's in.h says the following about these constants:
IP_RECVOPTS /* bool; Receive all IP options w/datagram. */
IP_RECVRETOPTS /* bool; Receive IP options for response. */
In that distro's in.h, the defined value of the first one appears to be 6, while the defined value of the second one appears to be 7.
So, my questions:
Are there equivalent constants in Windows sockets for replacing these two constants (or, perhaps, do I just need to include some other header)?
If not, is the receiving of IP options even possible in Windows sockets?
If so, is it safe for me to hard-code these values on Windows systems to 6 and 7, respectively, or should they be some other value?
UPDATE 1
I continued my Google research today. I found these two interesting tidbits. I don't know whether they help me. The first is the Windows Runtime (WinRT) Socket Address header (WinRTSockAddr.h) from the MixedRealityToolkit repository on Microsoft's official GitHub account. It contains the following:
#define IP_RECVOPTS 6
#define IP_RETOPTS 7
This aligns with *nix values I've seen elsewhere (I've commonly seen IP_RETOPTS aliased to IP_RECVRETOPTS). But then there's this alleged Windows Sockets helper header from the "Geek Research Lab"'s GitHub account. I've no idea if it has any credibility, but it has different values for these constants:
#define IP_RECVOPTS 5 /* bool; receive all IP opts w/dgram */
#define IP_RECVRETOPTS 6 /* bool; receive IP opts for response */
#define IP_RECVDSTADDR 7 /* bool; receive IP dst addr w/dgram */
#define IP_RETOPTS 8 /* ip_opts; set/get IP options */
That's contradictory on all fronts: values and the aliasing of IP_RETOPTS to IP_RECVRETOPTS. :-/
The only somewhat portable standard for accessing IP (as well as TCP and UDP) options is via the ancillary data parameters of sendmsg and recvmsg.
Unfortunately while having access is standardized, the exact details of what options are available can still vary between OSes.
On Linux, see the cmsg man page and note:
CONFORMING TO
This ancillary data model conforms to the POSIX.1g draft, 4.4BSD-
Lite, the IPv6 advanced API described in RFC 2292 and SUSv2.
CMSG_ALIGN() is a Linux extension.
By comparison, the man page describing IP_RECVOPTS has no "CONFORMING TO" section.
The similar Windows documentation page is "IPPROTO_IP Socket Options" on MSDN
In the Windows documentation for WSARecvMsg and WSASendMsg, there's the following note:
based on the Posix.1g specification for the msghdr structure
The documentation for _WSAMSG lists the ancillary data available from Winsock.
The POSIX documentation is here
Unfortunately for portability:
The system documentation shall specify the cmsg_type definitions for the supported protocols.
which is to say, the ancillary data actually available is not portable, because it's not specified by POSIX and/or Single Unix Specification.
Are there equivalent constants in Windows sockets for replacing these
two constants (or, perhaps, do I just need to include some other header)?
No. Unfortunately, this wouldn't be the first time that Windows is slow to implement parts of a particular standard or an RFC. Taking a look at socket options, for example, IP_RECVTTL was added only recently, for Windows 10. So maybe if you wait long enough, you may live to see the options you want supported on Windows? The code you have seen seems to be copy-pasted from some other, non-Windows code. In the case of RakNet, note that WinRTSockAddr.h is only used for WINDOWS_STORE_RT support, which is currently limited.
If not, is the receiving of IP options even possible in Windows
sockets?
No, it does not seem to be. At least I'm not aware of such capability.
If so, is it safe for me to hard-code these values on Windows systems
to 6 and 7, respectively, or should they be some other value?
No, it's probably not safe to hard-code the values. At best, such option values would be ignored, but they could be misinterpreted and result in unwanted behavior.
Since you indicated that you aim to make your code cross-platform, you will likely have to settle for the intersection of features that are supported on all the platforms that you want to support.

Find out MAC address on Linux&FreeBSD in C

I am trying to find out MAC address and I managed to create working solution using sysctl in Linux, problem is, that this solution is not working on FreeBSD version I am developing on. Is there any way I can find out mac address in C other than using sysctl?
Use the libpcap library. Its the most multi platform way you can find.
This library is used on network sniffers and intrusion detections, as well as dedicate measuring other network statistics. The nethogs utility to measure per process network usage, the iftop used to measure per machine/port bandwidth usage. Is very flexible in many roles.
Is written in C but there are some wrappers for other languages.
1: http://en.wikipedia.org/wiki/Pcap
[2]: http://www.tcpdump.org
[3]: http://sourceforge.net/projects/libpcap/
Edit:
here is a complete and exact and working example with the code and functions detailed:
http://coderrr.wordpress.com/2008/03/07/get-the-mac-address-of-a-local-ip/
There are plenty of tutorials and the source code is your best friend.
Edit 2: blaze pointed out getifaddrs(3) which seems to do the job, just a few caveats, its a non-posix function. Is a bsd function which glibc linux supports but do NOT documents. Is almost an undocumented featured :-)
All documentation are man pages and from the manual at kernel.org:
Not in POSIX.1-2001. This function first appeared in BSDi and is
present on
the BSD systems, but with slightly different semantics documented--returning
one entry per interface, not per address. This means ifa_addr and other
fields can actually be NULL if the interface has no address, and no link-level
address is returned if the interface has an IP address assigned. Also, the
way of choosing either ifa_broadaddr or ifa_dstaddr differs on various
systems.
and
The addresses returned on Linux will usually be the IPv4 and IPv6
addresses
assigned to the interface, but also one AF_PACKET address per interface
containing lower-level details about the interface and its physical layer. In
this case, the ifa_data field may contain a pointer to a struct
net_device_stats, defined in , which contains various
interface attributes and statistics.
So it may vary in behavior and you'll may have to #ifndef compile anyway.
The kernel.org man page at http://www.kernel.org/doc/man-pages/online/pages/man3/getifaddrs.3.html does provides example code in it, which may be helpful. My local linux man page is rather poor in comparison to the above linked.
I still think that libpcap is more portable if only because someone else had done all the portability work and all the extra features you gain by using it.
Hope this helps.
getifaddrs(3) returns IP addresses and MAC addresses on local interfaces. Portable between Linux and FreeBSD.

Querying full DNS record

I do alot of programming in *nix using C gcc. I know how to do a basic gethostbyname(). BUt what if I wanted to pull down the entire DNS record. More to the point, is there a function that I'm missing that allows you to specify the specific record that you want to pull? Or will I need to do this manually through a UDP socket?
No, there is no such function in standard C or POSIX (and even the gethostbyname function, contrary to what you may think, is not a function for querying DNS - it can use any other way to get the address, like /etc/hosts or mDNS, whatever).
You might want to look at some DNS-specific libraries, like ldns, libbind or libdjbdns.
See also Code to do a direct DNS lookup.

Using the name resolver of resolv.h with IPv6

I write or modify programs which perform name resolution and need a
good control of the process. So I do not use getaddrinfo(), I go
deeper and use res_query() / res_send() / etc in resolv.h, documented
in resolver(3).
Although not documented, the common way to set the resolver used is to
update _res.nsaddr_list. But this array, defined in resolv.h, stores
struct sockaddr_in, that is IPv4 addresses only. (IPv6 addresses
are struct sockaddr_in6, a family-independant system would use struct sockaddr.)
I'm looking for a way (preferrably portable, at least among the
various Unix) to tell _res that I want also IPv6 addresses.
Apparently, a long time ago, there was in FreeBSD a _res_ext with this
ability but I cannot find it anymore in a recent FreeBSD 7 (grep
_res_ext /usr/include/resolv.h finds nothing). You can still find
code which uses it (try yourself with Google Codesearch).
Thanks to Alnitak, I noticed it is apparently now _res._ext and not .res_ext. I wonder where these sort of things are documented or announced... I have no idea how portable _res._ext is. I can find it on Debian and FreeBSD. It seems there are few programs which use it.
Stéphane - if your resolv.h doesn't include any support for sockaddr_in6 then that suggests that on your particular O/S the resolver does not itself support IPv6 transport.
I've checked some of my systems here:
MacOS X 10.5.6 - supports the BIND 9 library, which has a res_setservers() function which can take IPv6 addresses, no _res._ext extension.
CentOS 5.2 - has the _res._ext extension, although there's no mention of IPv6 in the man page for resolv.conf except that there's a setting to tell the resolver to return AAAA records before looking for A records for gethostbyname().
EDIT - also, the CVS repository for FreeBSD suggests that FreeBSD 7.0 (see tag FREEBSD_7_0_0_RELEASE) does also support res_setservers() from Bind 9.
glibc:
res_setservers: no
__res_state._u._ext.nsaddrs
__res_state._u._ext.nsmap
set the latter to MAXNS+1 according to:
http://sourceware.org/ml/libc-hacker/2002-05/msg00035.html
BSD-libc:
res_setservers: yes
__res_state._u._ext.__res_state_ext
Seems messy to me and you'll probably need autoconf.

Resources