Yesterday, Topher asked the plug mailing list how to get your IP address from C. He got the answer on the mailing list, but I wanted to add a little bit about how to find answers to questions like this.
When I want to figure out how to get or set some bit of system information programmatically it always helps to try to rephrase the question. Instead of asking “How do I do foo programmatically?” I like to ask “Is there a program that does foo?” If there is a program that has similar functionality, here are three helps to find out how it works, in order of increasing difficulty.
strace
- browse manual pages in section 2
- use the source
strace
strace will show all the system calls a program makes, along with many of the arguments passed to them.
If I wanted to programmatically find the target of a symbolic link and didn’t know the system call to use, here is how I would use strace to find out.
byron@thinktank:~$ touch foo
byron@thinktank:~$ ln -s foo bar
byron@thinktank:~$ ls -l bar
lrwxrwxrwx 1 byron byron 3 2007-01-17 21:56 bar -> foo
byron@thinktank:~$ strace -o ls.strace ls -l bar
lrwxrwxrwx 1 byron byron 3 2007-01-17 21:56 bar -> foo
I start by creating a symbolic link bar that points to foo. I then find a utility that has the functionality I want, in this case ls finds the target of a symbolic link and prints it. The next step is to run strace, the -o option sends the output to a file instead of stderr. The next step is to examine the ls.strace file created by strace. The file is a little long, 204 lines on my system so I won’t post it all here. The first part of most strace output is a series of calls to access, open, and some form of mmap; this is dynamic linking in action and, unless this is the part of the trace you cared about, can be skipped. Because we told ls to only list file bar we can search for that filename to see if it is ever used; it is, and only on the following lines:
lstat64("bar", {st_mode=S_IFLNK|0777, st_size=3, ...}) = 0
readlink("bar", "foo", 4) = 3
Checking the man pages, it would appear that readlink(2) is the system call we need to use to find the target of a symbolic link.
That’s a simple example, but the same principles apply for any application, just be prepared to wade through a lot of system calls.
Manual pages in section 2
You can greatly reduce the time spent reading strace dumps if you are familiar with the system calls in manual page section 2. All it takes is ‘ls /usr/share/man/man2‘ and some reading. Of particular interest is the ioctl_list(2) manual page. Operations that don’t map cleanly to a read or write are often implemented using ioctl(2). While ioctl_list(2) doesn’t document how to use all of the ioctls it does at least list the codes and the arguments they expect. For real documentation your best bet is to grab the Linux kernel source and search for the ioctl you want to use. Of special note are the network ioctls, they are always performed on a socket and are of the form SIOCG.* for getting information and SIOCS.* for setting information.
Use the source
If the other methods fail and you have the source to the application, don’t be afraid to use it. I list this method last because I can usually find what I need with a quick strace and sometimes it takes quite a bit longer to get into the source for an application. Still, the source is the ultimate reference and isn’t hard to read.
A better example
If you have a better example for me to strace and dissect, let me know.