Querying system memory usage from c in linux

My task was to write a program which creates memory load and fragmentation stress on linux. Before I can start on that, I had to know how much ram is present in total and how much is available. First idea that comes to our mind is,

cat /proc/meminfo

Other alternatives are,

free -b
vmstat

But I wanted a way to get this info from a c program. My first trial was using get_phys_pages and get_avphys_pages.

printf("total memory    : %10lin", get_phys_pages() * getpagesize());
printf("free memory     : %10lin", get_avphys_pages() * getpagesize());

The problem with this method is, get_avphys_pages returns the free memory excluding cached and buffered memory. So I tried sysinfo system call.

struct sysinfo si;
if(sysinfo(&si) < 0) {
  printf("error! couldn't get sin");
}
printf("total memory    : %10lin", si.totalram);
printf("free memory     : %10lin", si.freeram);
printf("shared memory   : %10lin", si.sharedram);
printf("buffer memory   : %10lin", si.bufferram);

Unfortunately, sysinfo also returned the same free memory as get_avphys_pages. If we add buffer memory and cache memory to free memory returned, we will get the actual free memory available. Unfortunately, sysinfo only provides buffer memory size. So at the end i had to parse /proc/meminfo file to get memory size used as cache pages.

FILE *fp;
char buf[MAXLEN];
fp = fopen("/proc/meminfo", "r");
for(int i = 0; i <= 3; i++) {
  fgets(buf, MAXLEN, fp);
}
char *p1 = strchr(buf, ":");
printf("%st%in", p1, strtoull(p1, NULL, 10));

witnessing ip fragmentation using ping

My friend was testing ip fragmentation attacks on linux. So we had to witness ip fragmentation effect first. As we know, an IP packet can carry a total packet length of 65535(2^16 – 1) bytes. But since, data link layer(ethernet) frames can only carry maximum data size of 1500(MTU) bytes, IP has to fragment the packet if its length is greater than MTU. Out of 1500 bytes, IP’s header will itself occupy 20 bytes. We are left with 1480 bytes of data. Since we are using ping(which internally uses ICMP), 8 bytes are used by ICMP for its header. ¬†We are left with 1472 bytes, which is the maximum data size that can be sent using ping.


Fig1 Ethernet frame format

ip packet format
Fig2 IP packet format


Fig3 ICMP frame format

Note: To check MTU of interface eth0, type

ifconfig eth0

This is the ip we will be using throughout this test,

EXIP="192.168.1.10"

Run tcpdump in another terminal to keep track of transmission,

tcpdump -i wlan0 icmp -vvv

Now let us test the connection,

ping $EXIP -s 1472 -c 1

tcpdump reports that the packet has been sent,

01:58:05.960968 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 1500)
teja-laptop.local > vinit-PC.local: ICMP echo request, id 15530, seq 1, length 1480

When we try to send a packet with packet size greater than MTU and don’t fragment flag set,

ping $EXIP -s 1473 -M do -c 1

tcpdump remains silent because no packets are being sent. Lets see the output of ping and infer what has happened,

PING 192.168.1.10 (192.168.1.10) 1473(1501) bytes of data.
From 192.168.1.7 icmp_seq=1 Frag needed and DF set (mtu = 1500)

— 192.168.1.10 ping statistics —
0 packets transmitted, 0 received, +1 errors

This shows that if we try to send a packet with size greater than MTU and don’t fragment bit set, ping replies that it can’t send the packet. Now let us try to send the same packet with don’t fragment bit unset,

ping $EXIP -s 1473 -c 1

02:02:33.141005 IP (tos 0x0, ttl 64, id 31043, offset 0, flags [+], proto ICMP (1), length 1500)
teja-laptop.local > vinit-PC.local: ICMP echo request, id 15540, seq 1, length 1480
02:02:33.141134 IP (tos 0x0, ttl 64, id 31043, offset 1480, flags [none], proto ICMP (1), length 21)
teja-laptop.local > vinit-PC.local: icmp

Voila! The packet has been fragmented. As you can see, IP layer has fragmented the packet into two fragments. The first fragment has offset 0, id 31043 and length 1500. The second packet has the same id as the first but the offset shows where exactly this fragment fits into in the original packet. The data length of second packet is only 21(IP header + remaining 1 byte). Finally “flags [+]” in first packet means that there are more fragments yet to arrive while “flags [none]” in second packet means this is the last fragment.

viewing hardware spec in linux

There are various commands in linux that provide us with neccesary info about our hardware. Here we are going to use a few of them,
lshw
lshw shows a comprehensive list of devices connected to our system and their info.

sudo lshw

Thats too much to have a look at. You can get a simpler but readable info,

lshw -short

The third column of output from lshw command is class. If you want to view information about a specific class(example: disaply),

lshw -class display

lspci
lspci command lists details about various devices connected to pci card.

lspci -v

Again thats too much information when you want to know about just a specific device. Lets look for display device information,

lspci | grep -i display

In my case, It displayed the following info,
output:

00:02.1 Display controller: Intel Corporation Mobile GM965/GL960 Integrated Graphics Controller (rev 03)

If you observe, there is a number(00:02.1) at the begining of previous command’s output. You can use this number to make lspci show info about specific device.

lspci -v -s 00:02.1

output:

00:02.1 Display controller: Intel Corporation Mobile GM965/GL960 Integrated Graphics Controller (rev 03)
Subsystem: Lenovo Device 383e
Flags: bus master, fast devsel, latency 0
Memory at f8100000 (64-bit, non-prefetchable) [size=1M]
Capabilities: [d0] Power Management version 3

This can be made easy by using a single command,

lspci -v -s `lspci | grep -i display | awk '{print $1}'`

lsusb
If you want to know about various devices connected to your usb port,

lsusb -v

Asusual, There is a method to produce more cuter output,

lsusb -v -d `lsusb | grep -i camera | awk '{print $6}'`