Programming


If you want to debug why your C/C++ application segfaults once in a while (daemon that segfaults once in few days) under Linux the obvious way is to tell your program to create core dump files on segfault. It took me few hours to make my program coredump - by default under Linux setuid programs do not dump core. To force a program to do so, you should execute this after setuid:


prctl(PR_SET_DUMPABLE, 1);

and include:


#include <sys/prctl.h>

Of course you should also enable core dump with setrlimit:


setrlimit(RLIMIT_CORE, &limit);

To tune where your core dumps are stored, search google for core_pattern or /proc/sys/kernel/core_pattern, I don’t feel like copy-pasting.

Hope this helps somebody.

Ever wanted to be able to create site screenshots, just like alexa? Want to do it on your server with a script? Than read this article.

The idea is simple: install xvnc on your server, so you’ll have a virtual X display, than install Opera browser (Firefox does not support -geometry parameter) and finally install ImageMagick (the chances are that you already have it) so you can screenshot your virtual display. On Gentoo Linux I’ve done this by typing:


USE='X qt server png jpeg -kde' emerge vnc opera imagemagick

Create a user, under which xvnc/Opera will run and switch to it. Start vncserver with:


vncserver :1 -depth 24 -geometry 1024x768

it will ask for a password, you will need it if you want to connect to this display from a desktop computer. Of course you can change resolution, which is 1024×768 in this case (do not raise -depth, at least without reading “man vncserver”). Now start opera browser with:


/usr/bin/opera -display :1

Of course you will se nothing. Connect from your computer to the remote vnc server with:

vncviewer xx.xx.xx.xx:1

where xx.xx.xx.xx of course is the IP address of your server. You should see Opera window. Remove all the tollbars, so you have only meny on top. SECURE YOUR BROWSER - you may want to completely disable JavaScript or at least disable all popups. Close the browser. Now is a good time to decide if you want to install Macromedia Flash (installation is trivial).

So now you should be able to make screenshot from the console - run opera with URL as a parameter, also specifying -geometry and screenshot the site with import (part of ImageMagick package). This simple shell script runs Opera, waits 25 seconds for the site to load (unfortunately I didn’t find a good way to check if site is loaded) and screenshots it:


#!/bin/bash

export DISPLAY=":1"
/usr/bin/opera -display :1 -geometry 1024x768+0+0 -nomail -nosession "$1" > /dev/null 2> /dev/null &
/usr/bin/sleep 25
/usr/bin/import -window root -display :1 -crop 1024x768+7+50 "$2"
/usr/bin/killall opera

Usage is:
./screenshot http://www.google.com/ google.png

where screenshot is the name of the script. After executing it you will have google.png with screenshot of google’s website. If you see browser’s menus or frames, play with -crop parameter of import. Do not pass unchecked/unescaped parameters to the script, somebody will be able to execute a program on your server! Also have in mind that running browser on your server is not the most secure thing in the world. Actually it is as secure as browsing with Opera browser, so the choice is yours. Just don’t blame me if something wrong happens.

You can also use this sample Perl webserver. It will site screenshot when called as:
http://xx.xx.xx.xx/shot?http://www.google.com/

The server is single process, so you are limited to a single user at a time, also have in mind that you will have to wait 25+ sec for your screenshot. Before starting it, make sure you have installed: HTTP::Daemon and HTTP::Status. Also have in mind that this is only a TEST server that IS VULNERABLE, but it’s OK for testing and use in trusted environment.


#!/usr/bin/perl

$SIG{PIPE} = 'IGNORE';

use HTTP::Daemon;
use HTTP::Status;

my $d = HTTP::Daemon->new(
'LocalPort' => 8899
) || die;
print "Please contact me at: url, “>\n”;
while (my $c = $d->accept) {
if (my $r = $c->get_request) {
if ($r->method eq ‘GET’ and $r->url->path eq “/shot”) {
$site=urlDecode($r->url->query);
`/path/to/screenshot $site /path/to/writable/area/site.png`;
$c->send_file_response(”/path/to/writable/area/site.png”);
}
else {
$c->send_error(RC_FORBIDDEN)
}
}
$c->close;
undef($c);
}

sub urlDecode {
my ($string) = @_;
$string =~ tr/+/ /;
$string =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(”C”, hex($1))/eg;

return $string;
}

This webserver should be run like:

nohup perl ws.pl &

as the same user as which vncserver is running (root is not a good choice, really).

Have fun (and screenshots). This guide is intentionally not a total copy-paste solution, if you have hard time with missing steps - better outsource this task to somebody capable.

This works for me, you can click the counter button at the bottom of the page and you will see screenshot of my site on counter’s page (this is a free Bulgarian web counter written by me, only the high performance engine actually).

Today after some backups, generated from my C program generated few files exactly 2Gb in size I’ve remembered that there was some parameter to open for working with large files. I’ve opened man page for open and read that the option is O_LARGEFILE. I also liked the idea of using O_DIRECT. But when I tried to compile my program I got two errors:

hostbackupd.c: In function `somefunction':
somefile.c:102: error: `O_LARGEFILE' undeclared (first use in this function)
somefile.c:102: error: (Each undeclared identifier is reported only once
somefile.c:102: error: for each function it appears in.)

and

hostbackupd.c: In function `somefunction':
somefile.c:102: error: `O_DIRECT' undeclared (first use in this function)
somefile.c:102: error: (Each undeclared identifier is reported only once
somefile.c:102: error: for each function it appears in.)

After some googling I didn’t find something useful and looked at the .h files in /usr/include. I’ve found that header files are cheching if _GNU_SOURCE is defined and if it is, defines O_DIRECT and O_LARGEFILE. So to use this options you shoud compile your program with

gcc -D_GNU_SOURCE .....

or you shoud put

#define _GNU_SOURCE

before all your includes. Have in mind that this may make your program less portable.

And now some words about O_DIRECT. If you plan to use O_DIRECT your buffers should be aligned to pagesize (or sector size, depending on Linux version) and you should read/write in multiples of pagesize. To create buffer aligned at pagesize with size BUFFER_SIZE you can use code like this:


pagesize=getpagesize();
realbuff=malloc(BUFFER_SIZE+pagesize);
alignedbuff=((((int unsigned)realbuff+pagesize-1)/pagesize)*pagesize);

where pagesize is int and realbuff and alignedbuff are pointers. Realbuff is the pointer you should free() when you finished and alignedbuff is the buffer you shoud use with read/write.

You should also write only by multiples of pagesize. So if you want to create file that is not multiple of pagesize you should ftruncate the file when you finished writing.

If you need to check for instance if “ns1.titov.net” is a registered nameserver and can be filled as nameserver for a domain you can do it this way:

ask which nameservers are authoritative for zone “net” with:

dig ns net

in the answer section you will have:

net. 172800 IN NS l.gtld-servers.net.
net. 172800 IN NS m.gtld-servers.net.
net. 172800 IN NS a.gtld-servers.net.
net. 172800 IN NS b.gtld-servers.net.
net. 172800 IN NS c.gtld-servers.net.
net. 172800 IN NS d.gtld-servers.net.
net. 172800 IN NS e.gtld-servers.net.
net. 172800 IN NS f.gtld-servers.net.
net. 172800 IN NS g.gtld-servers.net.
net. 172800 IN NS h.gtld-servers.net.
net. 172800 IN NS i.gtld-servers.net.
net. 172800 IN NS j.gtld-servers.net.
net. 172800 IN NS k.gtld-servers.net.

than you should ask all of the nameservers for IP addres of the host in question:
host ns1.titov.net i.gtld-servers.net

if you got a respoce from any one of the servers, than you have a valid nameserver:
Using domain server:
Name: i.gtld-servers.net
Address: 192.43.172.30#53
Aliases:

ns1.titov.net has address 66.230.155.157

You can use this PHP code to accomplish this, I know it’s ugly, as it uses shell commands and regular expressions to parse their output, but I was not feeling like implementing the DNS protocol. Dig and host commands are part of bind package and should be installed on most servers:

function isValidNs($ns){
  $tld='com';
  if (preg_match('#\.([a-z]+)$#', $ns, $m))
    $tld=escapeshellarg($m[1]);
  $ns=escapeshellarg($ns);
  $dig=`/usr/bin/dig ns $tld`;
  preg_match_all(\"#[a-z\.]+\.\s+\d+\s+IN\s+NS\s+([a-z0-9\.\-]+).#\", $dig, $m);
  for ($i=0; $i<count($m[1]); $i++){
    $server=escapeshellarg($m[1][$i]);
    if (preg_match('#has address#', `/usr/bin/host $ns $server`))
      return true;
  }
  return false;
}

Note that you should as all of the nameservers, as for instance Bulgarian nameservers seem to be broken and only one of eight (maybe the master) nameservers responsible for “bg” zone replies to such requests.