quarta-feira, 22 de junho de 2016

I migrated to http://gkos.github.io, see you there :)

sexta-feira, 18 de janeiro de 2013

The end?

So many things happening..

I'm contributing to collectd
I'm contributing to riemann writing a client library in C
I'm contributing to emacs writing an interactive pastebin interface 

And I never made any effort to get more views on this blog. This was me and my self, documentating my learning. From the first post, when I was pĺaying with C pointers.. to now, that I can contribute to real opensource projects.. was a beatiful walk. 3 long years.. Maybe I create something like this with kernel stuff, starting from proc files playing to accepted kernel patches, who knows...

So I think is time to change and get more views, spread the knowledge I get everyday, and do some nicer posts, about linux, programming and offtopics too.. I'll try to migrate the archive from this blog to other platform. I really love markup languages, so I will try something with it .. and this is it!

Time to spread! Time to do real bloging! Time to change!

Cheers!

quinta-feira, 12 de julho de 2012

hex-to-ascii elisp function to fast decode protected donwload urls

Is really common to face download urls being "protected" but some annoying ringtone site. Some of then are so stupid that just encode the url as an hexadecimal string. Here is an example http://www.baixedetudo.net/id/?url=687474703a2f2f756c2e746f2f6f7977366b667732. Is easy to see the url here. I used perl to decode this, simple as in
print pack("H*", "687474703a2f2f756c2e746f2f6f7977366b667732"), "\n";
But as much I become an "emacs guy" more I do to easy my life.
Here is what I use from now to translate urls from hex to ascii The function usage is simple, just select the hex text and run it, you should get the translated text on clipboard.. You should be running emacs in its graphical form.
(defun hex-to-ascii (b e)
  "Translate the region from hex to ascii and copy it to clipboard.
I use that to translate urls in hex and paste it to url bar on my
browser."
  (interactive "r")
  (save-excursion
    (let ((i e)
           (x-select-enable-clipboard t)
           s)
      (while (> i b)
        (setq s (concat (format "%c" (read (concat "#x" (buffer-substring-no-properties (- i 2) i)))) s))
        (setq i (- i 2)))
      (kill-new s t)
      (message (format "%s copied to clip board" s)))))

I just keep this on my init.el.

Also I have done the opposite, a function that takes ascii string and returns its hex representation 
(defun ascii-to-hex (b e)
  "Translate an ascii string to a hex string and copy it to clipboard"
  (interactive "r")
  (save-excursion
    (let ((i b)
          (x-select-enable-clipboard t)
          s)
      (while (< i e)
        (setq s (concat s (format "%x" (get-byte i))))
        (setq i (+ i 1)))
      (kill-new s t)
      (message s))))

Nice and Easy :-)

quarta-feira, 11 de julho de 2012

elisp - get lines of text to a list

Here is an example of how get lines of text on a list.. I think I will use this on future for process text... Also I'm exercising my elisp skills since I want to be able to process text programmatically.
;; This text will be obtained 
;; by the function get-lines
;; It takes two parameters
;; The first being the start line (inclusive)
;; from with the text will be gathered 
;; The second being the end line (exclusive)
;; Nice and easy!! :-)

(defun get-beginning-of-line ()
  "Get the point at the beginning of line"
  (save-excursion
    (beginning-of-line)
    (point)))

(defun get-end-of-line ()
  "Get the point at the end of line"
  (save-excursion
    (end-of-line)
    (point)))

(defun programmatic-goto-line (line)
  "As goto-line but better for programming stuff"
  (goto-char (point-min))
  (forward-line (- line 1)))


(defun get-lines (start-line end-line)
  "Return a list with the lines between START-LINE (inclusive) and END-LINE (exclusive)"
  (save-excursion
    (programmatic-goto-line end-line)
    (let (lines)
      (while (< start-line (line-number-at-pos))
        (forward-line -1)
        (setq lines (cons (buffer-substring-no-properties (get-beginning-of-line) (get-end-of-line)) lines)))
      lines)))
      
               
;; Example
(let (v)
  (dolist (v (get-lines 1 7))
    (princ (format "%s\n" v))))

;; This text will be obtained 
;; by the function get-lines
;; It takes two parameters
;; The first being the start line (inclusive)
;; from with the text will be gathered 
;; The second being the end line (exclusive)
nil


sexta-feira, 6 de julho de 2012

My two "just arrived" new kernel books

Understading the Linux Kernel 

amd Linux Device Drivers

terça-feira, 3 de julho de 2012

Resolving names and IPs

Here is two examples of name resolving in linux.. I use getaddrinfo() and getnameinfo() respectively..


getaddrinfo: given a name retuns all translated IPs, one per line
/*
 * File: getaddrinfo.c
 * Compile: gcc getaddrinfo.c -o getaddrinfo
 * Usage: ./getaddrinfo FQN
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char **argv)
{
        int error;

        struct addrinfo saddr, *psaddr, *ptr;

        memset(&saddr, '\0', sizeof(saddr));
        saddr.ai_family = AF_INET;


        saddr.ai_socktype = SOCK_STREAM;

        error = getaddrinfo(argv[1], NULL, &saddr, &psaddr);
        if (error) {
                fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
                exit(EXIT_FAILURE);
        }

        for (ptr = psaddr; ptr; ptr = ptr->ai_next) {
                puts(inet_ntoa(((struct sockaddr_in *)    
                               ptr->ai_addr)->sin_addr));
        }

        return 0;
}

getnameinfo: Given an IP returns the name that first resolves to it. 
/*
 * File: getnameinfo.c
 * Compile: gcc getnameinfo.c -o getnameinfo
 * Usage: ./getnameinfo IP
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

static char hostname[255];

int main(int argc, char **argv)
{
        int error;
        struct sockaddr_in saddr_in;



        memset(&saddr_in, '\0', sizeof(saddr_in));
        saddr_in.sin_family = AF_INET;
        error = inet_aton(argv[1], &saddr_in.sin_addr);
        if (error == 0) {
                perror("inet_aton");
                exit(EXIT_FAILURE);
        }

        error = getnameinfo((struct sockaddr *)&saddr_in, sizeof(saddr_in),
                            hostname, sizeof(hostname),
                            NULL, 0, NI_NAMEREQD);
        if (error) {
                fprintf(stderr, "getnameinfo: %s\n", gai_strerror(error));
                exit(EXIT_FAILURE);
        }

        puts(hostname);
        return 0;
}


Cheers

terça-feira, 17 de abril de 2012

My first shellcode :)

/*
 * File: shello.c
 *
 * Generated from this assembly code:
 *      pushl   %ebp
 *      movl    %esp, %ebp
 *      
 *      subl    $12, %esp
 *      movl    $0x6c6c6548, -12(%ebp)
 *      movl    $0x6f57206f, -8(%ebp)
 *      movl    $0x0a646c72, -4(%ebp)
 *      
 *      movl    $4, %eax        
 *      movl    $1, %ebx
 *      leal    -12(%ebp), %ecx 
 *      movl    $12, %edx 
 *      
 *      int     $0x80
 *      addl     $12, %esp
 *      
 *      leave
 *      ret
 * 
 */

/*
 * Tested on Linux hilstdsk 3.2.7-1-ARCH #1 SMP PREEMPT Tue Feb 21
 * 16:59:04 UTC 2012 i686 AMD Athlon(tm) 64 X2 Dual Core Processor
 * 4400+ AuthenticAMD GNU/Linux
 * Archlinux
 */

/*
 * Compile: gcc -o shello shello.c
 * Run: ./shello
 * Output: Hello World
 */
 
/*
 * Thats pretty cool!
 */
#include 

static char shellcode[] = "\x55"
        "\x89\xe5"
        "\x83\xec\x0c"
        "\xc7\x45\xf4\x48\x65\x6c\x6c"
        "\xc7\x45\xf8\x6f\x20\x57\x6f"
        "\xc7\x45\xfc\x72\x6c\x64\x0a"
        "\xb8\x04\x00\x00\x00"
        "\xbb\x01\x00\x00\x00"
        "\x8d\x4d\xf4"
        "\xba\x0c\x00\x00\x00"
        "\xcd\x80"
        "\x83\xc4\x0c"
        "\xc9"
        "\xc3";

int main(void)
{
        void (*p)(void);
        p = shellcode;
        p();
        return 0;
}

segunda-feira, 19 de março de 2012

My first elisp function

;; This is my first elisp function, it helps me to write functions
;; that surround text by HTML tags.
(defun surround-by-tag (begin end topen tclose)
  "Surround selected text by HTML tags"
  (goto-char begin)
  (insert topen)
  (goto-char (+ end (length topen)))
  (insert tclose))


;; Here is how to use it. I define a function and calls
;; surround-by-tag passing the begin and end of my selection
;; as the open and close tags. 
(defun p (b e)
  "Surround text by <p></p>"
  (interactive "r")
  (surround-by-tag b e "<p>" "</p>"))

(defun pre (b e)
  "Surround text by <pre></pre>"
  (interactive "r")
  (surround-by-tag b e "<pre>" "</pre>"))


;; Then I select my text and use the defined interactive function
;; <p>Hello elisp world</p>

sábado, 10 de março de 2012

regex example

/*
 * File: regex.c
 * 
 * This is a sample regex usage, gets three arguments. It is a grep
 * like tool.  
 * -f <FILE> -> A file to be read if omited or - stdin is read 
 * -p <PATTERN> -> The pattern to be matched agains every line on FILE 
 * -v -> Invert the match, as like grep -v.
 *
 * Compiling: gcc -o preg regex.c 
 */
 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <regex.h>
#include <unistd.h>
#include <getopt.h>



int main(int argc, char **argv)
{
        regex_t reg;
        char pattern[256];
        int status;
        char buf[256];
        FILE *fp = NULL;
        int opt;
        int inverted = 0;
        
        while ((opt = getopt(argc, argv, "vp:f:")) != -1) {
                switch (opt) {
                case 'v':
                        inverted = 1;
                        break;
                case 'p':
                        strncpy(pattern, optarg, 256);
                        break;
                case 'f':
                        if (optarg[0] == '-') {
                                fp = stdin;
                        } else {
                                fp = fopen(optarg, "r");
                                if (!fp) {
                                        perror("fopen");
                                        exit(EXIT_FAILURE);
                                }
                        }
                        break;
                }
                /* printf("%c\n", opt); */
        }

        if (!fp)
                fp = stdin;

        status = regcomp(&reg, pattern, REG_EXTENDED | REG_NOSUB);
        if (status != 0)
        {
                fprintf(stderr, "Compiling the regular expression \"%s\" failed.\n", pattern);
                exit(EXIT_FAILURE);
        }


        while (fgets(buf, 256, fp)) {
                status = regexec(&reg, buf,
                                 /* nmatch = */ 0,
                                 /* pmatch = */ NULL,
                                 /* eflags = */ 0);

                if (inverted ? status : !status) {
                        printf("%s", buf);
                }
        }

        return 0;
}

quarta-feira, 15 de fevereiro de 2012

Capture idle "percentage" in C

This program will read /proc/stat an calculum the amount of time that computer was idle...


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define BUFLEN 256
static char buf[BUFLEN];


int strsplit (char *string, char **fields, size_t size);

int main(void)
{
        FILE *stat;
        char *fields[9];        
        int numfields;

        unsigned int ncores;

        unsigned int idle;
        unsigned int old_idle = 0;

        
        while (1) {
                /*
                 * The cpu sum line SHOULD be the first line
                 * on /proc/stat, or things will get wrong.
                 */
                if ((stat = fopen("/proc/stat", "r")) == NULL) {
                        perror("fopen");
                        exit(EXIT_FAILURE);
                }

                fgets(buf, BUFLEN, stat);

                numfields = strsplit (buf, fields, 9);
                if (numfields < 5) {
                        fprintf(stderr, "To few fields\n");
                        exit(EXIT_FAILURE);
                }
                
                ncores = sysconf(_SC_NPROCESSORS_ONLN); /* number of cores */
                idle = atoi(fields[4]);
                printf("idle %d%%\n", (idle - old_idle) / ncores);
                old_idle = idle;
                
                fclose(stat);
                sleep(1);
        }                        

        return 0;
}

int strsplit (char *string, char **fields, size_t size)
{
        size_t i;
        char *ptr;
        char *saveptr;

        i = 0;
        ptr = string;
        saveptr = NULL;
        while ((fields[i] = strtok_r (ptr, " \t\r\n", &saveptr)) != NULL)
        {
                ptr = NULL;
                i++;

                if (i >= size)
                        break;
        }

        return ((int) i);
}

quarta-feira, 25 de janeiro de 2012

Creating C libraries/extensions/binds to Lua

I'm training the C API of lua.. planning to create extensions to awesome window manager (the one I use) -> http://awesome.naquadah.org/. Here is a "Lua calling C" hello world.


/*
 * File: hellolib.c
 *
 * Compile: 
 * gcc -Wall -fPIC -c hellolib.c && gcc -shared -Wl -o libhellolib.so hellolib.o
 *
 * Calling from lua:
 *
 * > hello_lib = package.loadlib("/home/geckos/programming/lua/libhellolib.so", "lua_open_hellolib")()
 * > 
 * > 
 * > hello_lib.hello_from_c()
 * Hello from C world to lua
 * > 
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>


static int hello_from_c(lua_State *L)
{
 puts("Hello from C world to lua");
 return 0;
}

static const struct luaL_reg hello_lib[] = {
 { "hello_from_c", hello_from_c },
 { NULL, NULL },
};

int lua_open_hellolib(lua_State *L)
{
 luaL_openlib(L, "hello_lib", hello_lib, 0);
 return 1;
}


quinta-feira, 5 de janeiro de 2012

TCP Flooder with pthreads

/**
 * This code creates N threads. Each threads does one GET to an address. The
 * GET, the address and the number of threads are passed as argument. An "\r\n"
 * is appended to the GET string. 
 */
/* headers *//*{{{*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <pthread.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netdb.h>/*}}}*/

/* declarations and prototypes */ /*{{{*/
#define pexit(s) ({perror(s); exit(exit_failure);})
static struct cstats { 
        int socket_errors;
        int send_errors;
        int recv_errors;
        int connect_errors;
        int avg_respt; /* average response time */
        pthread_mutex_t mutex;
} cstats;
        

struct sockaddr_in addr;

#define buflen 1024
static char buf[buflen];
static int buf_len;

void *get_get_thread(void *);/*}}}*/

int main(int argc, char **argv)
{
        /* main declarations *//*{{{*/
        int i;
        int fail = 0;
        int ngets;
 int addr_len;
 int error;
 struct hostent *host;
        pthread_t *threadv;
        pthread_attr_t attr;/*}}}*/
  
        /* error checking *//*{{{*/
 if (argc <= 4) { 
  printf("usage: %s address port number_of_gets get_string\n", argv[0]);
  exit(exit_failure);
 }


        ngets = atoi(argv[3]);
        if (ngets <= 0) {
                printf("number_of_gets\n");
                errno = einval;
                exit(exit_failure);
        }
/*}}}*/

        bzero(&cstats, sizeof(struct cstats));

        /* pthread initialization *//*{{{*/
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, pthread_create_joinable);
        pthread_mutex_init(&cstats.mutex, null);
        threadv = malloc(sizeof(pthread_t) * ngets);
        if (!threadv) 
                pexit("malloc");/*}}}*/

        /* address initialization *//*{{{*/
        strncpy(buf, argv[4], buflen);
        strncat(buf, "\r\n", buflen);

 host = gethostbyname(argv[1]);
 if (!host)
  pexit("gethostbyname");

 memcpy(&addr.sin_addr.s_addr, host->h_addr_list[0], sizeof(struct
    sockaddr_in)); 
 addr.sin_family = pf_inet;
 addr.sin_port = htons(atoi(argv[2]));
/*}}}*/

        /* creating threads *//*{{{*/
 for (i = 0; i < ngets; i++) {
                error = pthread_create(&threadv[i], &attr,
                                        get_get_thread, null);
                if (error)
                        fail++; 
 }/*}}}*/


        printf("%d thread created. Running...\n", ngets -  fail);

        /* joing threads *//*{{{*/
        for (i = 0; i < ngets; i++) {
                error = pthread_join(threadv[i], null);
                if (error)
                        perror("pthread_join");
        }/*}}}*/

        /* output *//*{{{*/
        printf("errors:\n"
               "    socket() errors: %d\n"
               "    connect() errors: %d\n"
               "    send() errors: %d\n"
               "    recv() errors: %d\n", cstats.socket_errors,
               cstats.connect_errors, cstats.send_errors, cstats.recv_errors);/*}}}*/

 return 0;
}

void *get_get_thread(void *dummy)/*{{{*/
{
        int error;
        int nbytes;
        int sock;
#define RBUF_LEN 1024
        char rbuf[RBUF_LEN];

 sock = socket(PF_INET, SOCK_STREAM, 0);/*{{{*/
 if (sock < 0) {
                pthread_mutex_lock(&cstats.mutex);
                cstats.socket_errors++;
                pthread_mutex_unlock(&cstats.mutex);
        }/*}}}*/

 error = connect(sock, (struct sockaddr *)&addr, sizeof addr);/*{{{*/
 if (error) {
                pthread_mutex_lock(&cstats.mutex);
                cstats.connect_errors++;
                pthread_mutex_unlock(&cstats.mutex);
        }/*}}}*/

        nbytes = send(sock, buf, strlen(buf) , 0);/*{{{*/
        if (nbytes == -1) /* error */ {
                pthread_mutex_lock(&cstats.mutex);
                cstats.send_errors++;
                pthread_mutex_unlock(&cstats.mutex);
        }/*}}}*/

        nbytes = recv(sock, rbuf, RBUF_LEN, 0);/*{{{*/
        if (nbytes == -1) {
                pthread_mutex_lock(&cstats.mutex);
                cstats.recv_errors++;
                pthread_mutex_unlock(&cstats.mutex);
        }/*}}}*/

 close(sock);
        return (void *)0;
}/*}}}*/

/* vim: set fdm=marker: tw=80 : */

Collectd patch to collect cpu average on linux

I'm using collectd to collectd data at work -> http://www.collectd.org The cpu plugin don't collectd average cpu usage, I have create a patch to work this around. Here it is
diff -Nurp collectd-5.0.1/src/cpu.c collectd-5.0.1-new/src/cpu.c
--- collectd-5.0.1/src/cpu.c 2011-10-14 17:49:49.000000000 -0300
+++ collectd-5.0.1-new/src/cpu.c 2012-01-03 17:48:22.000000000 -0200
@@ -252,7 +252,11 @@ static void submit (int cpu_num, const c
  vl.values_len = 1;
  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
  sstrncpy (vl.plugin, "cpu", sizeof (vl.plugin));
- ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+        if (cpu_num < 0)
+                ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+   "avg");
+        else
+                ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
    "%i", cpu_num);
  sstrncpy (vl.type, "cpu", sizeof (vl.type));
  sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
@@ -359,6 +363,7 @@ static int cpu_read (void)
 
  char *fields[9];
  int numfields;
+        int coren = sysconf(_SC_NPROCESSORS_ONLN); /* number of cores */
 
  if ((fh = fopen ("/proc/stat", "r")) == NULL)
  {
@@ -372,18 +377,24 @@ static int cpu_read (void)
  {
   if (strncmp (buf, "cpu", 3))
    continue;
-  if ((buf[3] < '0') || (buf[3] > '9'))
-   continue;
 
   numfields = strsplit (buf, fields, 9);
   if (numfields < 5)
    continue;
 
-  cpu = atoi (fields[0] + 3);
-  user = atoll (fields[1]);
-  nice = atoll (fields[2]);
-  syst = atoll (fields[3]);
-  idle = atoll (fields[4]);
+                if (!isdigit(fields[0][3])) {
+                        cpu = -1;
+                        user = atoll (fields[1]) / coren;
+                        nice = atoll (fields[2]) / coren;
+                        syst = atoll (fields[3]) / coren;
+                        idle = atoll (fields[4]) / coren;
+                } else { 
+          cpu = atoi (fields[0] + 3);
+                        user = atoll (fields[1]);
+                        nice = atoll (fields[2]);
+                        syst = atoll (fields[3]);
+                        idle = atoll (fields[4]);
+                }
 
   submit (cpu, "user", user);
   submit (cpu, "nice", nice);
@@ -392,9 +403,15 @@ static int cpu_read (void)
 
   if (numfields >= 8)
   {
-   wait = atoll (fields[5]);
-   intr = atoll (fields[6]);
-   sitr = atoll (fields[7]);
+                        if (cpu < 0) {
+                                wait = atoll (fields[5]) / coren;
+                                intr = atoll (fields[6]) / coren;
+                                sitr = atoll (fields[7]) / coren;
+                        } else {
+                                wait = atoll (fields[5]);
+                                intr = atoll (fields[6]);
+                                sitr = atoll (fields[7]);
+                        }
 
    submit (cpu, "wait", wait);
    submit (cpu, "interrupt", intr);


quarta-feira, 7 de dezembro de 2011

Ping/ICMP example

I have tried this on my archlinux i686 and works, on arch x86_64 segfaults and I don't no why, I need to work more on this.
/*
 * ping.c
 *
 * An ping example. I have used some iputils code
 * you can get the iputils source here: http://www.skbuff.net/iputils/
 *
 */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <netinet/ip_icmp.h>


#define pexit(s) ({perror(s); exit(EXIT_FAILURE);})

u_short in_cksum(const u_short *addr, register int len, u_short csum);
void print_icmphdr(struct icmphdr *);
void print_iphdr(struct iphdr *);

int main(int argc, char **argv)
{
        int sock;
        int len;
        int bytes;
        int count = -1;
        u_short cksum;
        u_int16_t seq; 

        struct sockaddr_in dst_addr;
        struct sockaddr_in rcv_addr;
        struct hostent *dst_host;

#define BUFLEN 1000000
        char outpack[BUFLEN];
        struct icmphdr *icp; 
        struct iphdr *ip;

        if (argc <= 1) {
                printf("Usage: %s HOST [COUNT]");
                exit(EXIT_FAILURE);
        }



        sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
        if (sock == -1)
                pexit("socket");
        
        dst_host = gethostbyname(argv[1]);
        if (!dst_host) {
                errno = h_errno;
                pexit("gethostbyname");
        }

        memcpy(&dst_addr.sin_addr.s_addr, dst_host->h_addr_list[0], 
                        sizeof(dst_addr));
        dst_addr.sin_family = PF_INET;
        dst_addr.sin_port = 0;

        if (argc > 2 )
                count = atoi(argv[2]);

        seq = 1;
        while (count--) {
                icp = (struct icmphdr *)outpack;
                icp->type = ICMP_ECHO;
                icp->code = 0;
                icp->un.echo.sequence = seq;
                icp->un.echo.id = getpid(); 
                icp->checksum = 0;
                icp->checksum = in_cksum((u_short *)icp, 
                                sizeof(struct icmphdr), 0);

                bytes = sendto(sock, outpack, sizeof(struct icmphdr),
                                MSG_DONTWAIT, (struct sockaddr *)&dst_addr,
                                sizeof(dst_addr));
                if (bytes < 0)
                        pexit("sendto");

                sleep(1);

                len = sizeof(struct sockaddr_in);
                bytes = recvfrom(sock, outpack, sizeof(struct iphdr) +
                                sizeof(struct icmphdr), MSG_DONTWAIT,
                                (struct sockaddr *)&rcv_addr, &len);
                if (bytes < 0) /* I'm ignoring incoming errors */
                        continue;

                ip = (struct iphdr *)outpack;
                icp = (struct icmphdr *)&outpack[sizeof(struct iphdr)];

                cksum = icp->checksum;
                icp->checksum = 0;
                icp->checksum = in_cksum((u_short *)icp, 
                                sizeof(struct icmphdr), 0);

                if (cksum != icp->checksum) /* and ignoring  */
                        continue;           /* corrupted packets */

                switch(icp->type) {
                case ICMP_ECHOREPLY: /* and repeateds */
                        if (icp->un.echo.sequence < seq)
                                continue;
                        print_iphdr(ip);
                        print_icmphdr(icp);
                        putchar('\n');
                        seq++;
                        break;
                case ICMP_DEST_UNREACH:
                        printf("Destination unreachable\n");
                        break;
                }

        } 

        return 0;
}


/*
 * Taken from iputils/ping.c, at http://www.skbuff.net/iputils/
 */
u_short in_cksum(const u_short *addr, register int len, u_short csum)
{
 register int nleft = len;
 const u_short *w = addr;
 register u_short answer;
 register int sum = csum;

 /*
  *  Our algorithm is simple, using a 32 bit accumulator (sum),
  *  we add sequential 16 bit words to it, and at the end, fold
  *  back all the carry bits from the top 16 bits into the lower
  *  16 bits.
  */
 while (nleft > 1)  {
  sum += *w++;
  nleft -= 2;
 }

 /* mop up an odd byte, if necessary */
 if (nleft == 1)
  sum += htons(*(u_char *)w << 8);

 /*
  * add back carry outs from top 16 bits to low 16 bits
  */
 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
 sum += (sum >> 16);   /* add carry */
 answer = ~sum;    /* truncate to 16 bits */
 return (answer);
}

void print_iphdr(struct iphdr *ip)
{
        printf("IP tos=%u id=%u ttl=%u saddr=%s daddr=%s ",
                       ip->tos, ip->id, ip->ttl, inet_ntoa(ip->saddr),
                       inet_ntoa(ip->daddr));
}
void print_icmphdr(struct icmphdr *icp)
{
        printf("ICMP seq=%d ", icp->un.echo.sequence);
}


terça-feira, 6 de dezembro de 2011

TCP Server Hello World example

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netdb.h>

#define pexit(s) ({perror(s); exit(EXIT_FAILURE);})

#define BUFLEN 0x400
static char buf[BUFLEN];

int main(int argc, char **argv)
{
 int srv_sock;
 int cli_sock;
 int srv_addr_len;
 int cli_addr_len;
 int error;
 int nbytes; 
 struct sockaddr_in srv_addr;
 struct sockaddr_in cli_addr;

  
 if (argc <= 1) { 
  printf("Usage: %s PORT\n", argv[0]);
  exit(EXIT_FAILURE);
 }

 srv_sock = socket(PF_INET, SOCK_STREAM, 0);
 if (srv_sock < 0)
  pexit("socket");


        srv_addr_len = sizeof(srv_addr);
        bzero(&srv_addr, srv_addr_len);
        srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 srv_addr.sin_family = PF_INET;
 srv_addr.sin_port = htons(atoi(argv[1]));

        error = bind(srv_sock, (struct sockaddr *)&srv_addr, srv_addr_len);
        if (error)
                pexit("bind");

        error = listen(srv_sock, 5);
        if (error)
                pexit("listen");

        cli_addr_len = sizeof(cli_addr);
        while ((cli_sock = accept(srv_sock, (struct sockaddr *)&cli_addr,
                                        &cli_addr_len)) != -1) 
        {
                printf("Received connection from %s\n",
                                inet_ntoa(cli_addr.sin_addr.s_addr));

                nbytes = send(cli_sock, "Hello World\n", strlen("Hello World\n"), 0);
                if (nbytes == -1)
                        perror("send");
                close(cli_sock);
 } 

 close(srv_sock);
 return 0;
}

segunda-feira, 5 de dezembro de 2011

UDP, Server and Client examples

/*
 * udpserver.c
 *
 * UDP Server example
 */
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define pexit(s) ({perror(s); exit(EXIT_FAILURE);})

int main(int argc, char **argv)
{
#define BUFLEN 1000
        char buf[BUFLEN];
        int sock, error, clilen, bytes;
        struct sockaddr_in srv, cli; 
        
        if (argc < 2) {
                printf("Usage: %s PORT\n", argv[0]);
                exit(EXIT_FAILURE);
        }

        sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock == -1)
                pexit("socket");


        memset(&srv, 0, sizeof(srv));
        srv.sin_family =  AF_INET;
        srv.sin_port = htons(atoi(argv[1]));
        srv.sin_addr.s_addr = htonl(INADDR_ANY);

        error = bind(sock, (struct sockaddr *)&srv, sizeof(srv));

        for (;;) {
               clilen = sizeof(cli);
               bytes = recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *)&cli,
                               &clilen);
               if (bytes == -1)
                       pexit("recvfrom");

               printf("received data from %s\n",
                               inet_ntoa(cli.sin_addr.s_addr));
               buf[bytes] = '\0';
               printf(">>%s<<\n", buf);
        }
        return 0;
} 


/*
 * udpclient.c
 *
 * UDP client example
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define pexit(s) ({perror(s); exit(EXIT_FAILURE);})

int main(int argc, char **argv)
{
        int sock, error, srvlen, bytes;
        struct sockaddr_in srv;
        
        if (argc <= 2) {
                printf("Usage: %s IP PORT\n", argv[0]);
                exit(EXIT_FAILURE);
        }

        sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock == -1)
                pexit("socket");


        memset(&srv, 0, sizeof(srv));
        srv.sin_family =  AF_INET;
        srv.sin_port = htons(atoi(argv[2]));
        srv.sin_addr.s_addr = inet_addr(argv[1]);

        bytes = sendto(sock, "Hello World", strlen("Hello World"), 0,
                        (struct sockaddr *)&srv, sizeof(srv));
        if (bytes == -1)
                pexit("sendto");

        close(sock);

        return 0;
} 


terça-feira, 29 de novembro de 2011

Stress test in C !?

This code will create N threads that take B bytes of memory each and spin forever. Call it whihout arguments to see the usage.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define pexit(s) ({perror(s); exit(EXIT_FAILURE);})

static unsigned int sleepi = 0;
void *xmalloc(size_t);
void *tfunction(void *);

int main(int argc, char **argv)
{
        int nthreads;
        int nbytes;
        int i;
        pthread_t *threadv;

        if (argc <= 2) {
                printf("Usage: %s NUMBER_OF_THREADS NUMBER_OF_BYTES_PER_THREAD "
                                "[SLEEP_INTERVAL_IN_SECS]\n", argv[0]);
                exit(EXIT_FAILURE);
        }

        nthreads        = atoi(argv[1]);
        nbytes          = atoi(argv[2]);
        if (argc > 3) {
                sleepi          = atoi(argv[3]);
        }

        threadv = xmalloc(sizeof(pthread_t) * nthreads);
        for (i = 0; i < nthreads; i++) {
               pthread_create(&threadv[i], NULL, tfunction, (void *)&nbytes);
        }
        while (1) sleep(~0lu); /* MAX LONG POSSIBLE */
        return 0;
}

void *xmalloc(size_t siz)
{
        void *n = malloc(siz);
        if (!n)
                pexit("malloc"); 
        return n;
}

void *tfunction(void *num)
{
        int i = *(int *)num;
        while (i--) malloc(1);
        if (sleepi)
                while (1) sleep(sleepi);
        else
                while (1);
}

segunda-feira, 28 de novembro de 2011

Simple socket client

This sample application will connect to addres passed as first argument
and port passed as second argument. Then will send everything received from stdin
to that socket and send everything received as answer from socket to stdout. Simple!
Type quit to exit.

Is useful when you need to rember how to setup PF_INET sockects and when you need something simple
to talk with some socket.

Note: I have used `~' character as prompt.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netdb.h>

#define pexit(s) ({perror(s); exit(EXIT_FAILURE);})

#define BUFLEN 0x400
static char buf[BUFLEN];

int main(int argc, char **argv)
{
    int sock;
    int addr_len;
    int error;
    struct sockaddr_in addr;
    struct hostent *host;

        
    if (argc <= 2) { 
        printf("Usage: %s address port\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    sock = socket(PF_INET, SOCK_STREAM, 0);
    if (sock < 0)
        pexit("socket");


    host = gethostbyname(argv[1]);
    if (!host)
        pexit("gethostbyname");

    memcpy(&addr.sin_addr.s_addr, host->h_addr_list[0], sizeof(struct
                sockaddr_in));    
    addr.sin_family = PF_INET;
    addr.sin_port = htons(atoi(argv[2]));

    error = connect(sock, (struct sockaddr *)&addr, sizeof addr);
    if (error)
        pexit("connect");

    for (;;) {
        printf("~ "); /* my prompt */
        fgets(buf, BUFLEN, stdin);    
        if (!strcmp(buf, "quit\n"))
            break;

        error = send(sock, buf, strnlen(buf, BUFLEN), 0);        
        if (error == -1) /* error */
            pexit("send");

        error = recv(sock, buf, BUFLEN, 0);
        if (error == -1)
            pexit("recv");

        printf(buf);
    }    

    close(sock);
    return 0;
}

Testing:


sexta-feira, 11 de novembro de 2011

IP Fail over script writen in perl

This perl script provides an IP Fail Over enviroment, by testing the routes an jumping from one to another if the current route falls out of service.
More information on script comments.


#!/usr/bin/perl  
#
# (c) Daniel Hilst Selli, 2011, <danielhilst@gmail.com>
#
# IP FAIL OVER 
#
# Desc: Provides a IP FAIL OVER environment by testing the current routing and
#       changing it to next route if it fails. "ip" utility is used to change
#       the routes. 
#
# Usage: You need to configure the routes at @routes array. 
# /\_______update_the_comment_______________________/\
#
#       When ping fails on current route, the script searches for a new valid
#       route. That valid route will be the new default route.
#
#       The entry 0 is the standard route. You can request the script to go back
#       to standar route by sending a SIGUSR to it. The standard route will be
#       checked, if is not yet valid the script will not change the current
#       route.
#
#       $dest_host is the url that you will ping. I have setted it to
#       "www.google.com" but you can change it if needed.
#
#       This script goes to background as soon as possible. As a service should
#       do. You can define the log of it on $daemon_log variable. Its default is
#       the name of the script followed by ".log".
#


use strict;
use warnings; 
use Net::Ping; 
use POSIX qw(setsid);
use Time::localtime;
use Fcntl qw(:flock SEEK_END);


#
# START CONFIGURE HERE
#
my @routes = (
        {
#                iface =>  "ppp0",
                source => "200.171.87.72",
                gateway => "dev ppp0",
  init =>  sub {
      print ctime() .  " Rebooting ppp0\n";
      `ifdown ppp0`;
      `ifup ppp0`;
  },
        },
        {
                iface => "eth2",
                source => undef,
                gateway => "via 192.168.5.1",
        },
);
my $dest_host = "www.google.com";
my $standard_route = 1; # Used as index to @routes. So $routes[0] is the 
                        # standard route   
my $daemon_log = $0 . ".log"; 
#
# STOP CONFIGURE HERE
#



#
# Initialization 
# 
my $continue = 1;
my $pid;
my $indx = undef; 
my $current_route = undef;
my $pid_file = "$0.pid";
my $pid_fh = undef;
my $file_lock_fh = undef;
my $file_lock_fname = "$0.lck";
$| = 1; # unbuffered STDOUT

$SIG{TERM} = sub { $continue = 0 };

$SIG{USR1} = sub {
        print ctime() . " Standard route requested\n";
        if ($routes[$standard_route] == $current_route) {
                print ctime() . " the standard route is already".
                " being used, nothing to do\n";
        } elsif ($routes[$standard_route]->{ping}->ping($dest_host)) {
                print ctime() .  " Standard route is valid, ".
                "backing to it\n";
                $indx = $standard_route;
                set_route();
        } else {
                print ctime() . " Standard route offline, nothing to do\n";
        }
};

sub init_routes {
        for my $r (@routes) {
                if ($r->{source}) {
                        $r->{ping} = Net::Ping->new("icmp", 1);
                        $r->{ping}->bind($r->{source});
  } elsif ($r->{iface}) {
      $r->{ping} = Net::Ping->new("icmp", 1, 64, $r->{iface}); 
  } else {
      die "Route without source and iface member\n".
   "You need at least one of them\n";
  }
        } 

        die "\$standard_out setted to out of bounds of ". 
        "\@routes array\n" if $standard_route > $#routes;

        $indx = $standard_route;
        set_route();
}

sub do_flock {
        open($file_lock_fh, ">$file_lock_fname") or die "Can't open lock file".
 " $file_lock_fname";
        unless(flock($file_lock_fh, LOCK_EX | LOCK_NB)) {
                die "Cannot obtain lock. If there is another instance of".
                "this running kill it and try again";    
        }
}

sub do_funlock {
        my ($fname) = @_; 
        unless(flock($file_lock_fh, LOCK_UN)) {
                die "Cannot release lock, this shouldn't be happening";
        }
        close($file_lock_fh);
}

sub set_route {
        $current_route =  $routes[$indx];
        print ctime() . " Changing route to ".
        "$current_route->{gateway}\n";
 
 $current_route->{init}() if $current_route->{init};

        my $error = `ip route del default`; 
        print " Can't delete default route\n" if $error;

        $error = `ip route add default $current_route->{gateway}`;
        die " Can't add default route" if $error;

 print ctime() . " Route changed\n";
}

# Args
# 1 => Ref to global $indx variable
# 2 => The limmit 
sub next_indx {
        my ($indx, $limit) = @_;
        $$indx++;
        if ($$indx > $limit) {
                $$indx = 0;
        }
}


sub on_fail {
        my $error;
        
        print ctime() . " Ping failed\n";
        print ctime() . " Default route is $current_route->{gateway}. Adding new route\n";
        $error = `ip route del default via $current_route->{gateway}`; 
        die $! if $error;

        next_indx(\$indx, $#routes);
        set_route();

        print ctime() . " New route $current_route->{gateway} added\n";
}


sub daemonise {
        umask 0;
        open STDIN, '/dev/null'   or die "Can't read /dev/null: $!";
        open STDOUT, ">$daemon_log" or die "Can't write to log: $!";
        open STDERR, ">$daemon_log" or die "Can't write to log: $!";
        defined(my $pid = fork)   or die "Can't fork: $!";
        exit if $pid;
        setsid                    or die "Can't start a new session: $!"; }

#
# MAIN LOOP
#


do_flock();
daemonise();
init_routes();
while ($continue) {
        if ($current_route->{ping}->ping($dest_host)) {
#               print ctime();
#   if ($current_route->{source}) {
#       print " $current_route->{source} live\n";
#   } else {
#       print " $current_route->{iface} live\n";
#   }
                sleep(3);
        } else {
                on_fail();
        }
}
do_funlock();


# vim:ft=perl:tabstop=8:shiftwidth=4:smarttab:noexpandtab:softtabstop=4:ai:tw=80


container_of

/*
 * This example show how get sibling members of a struct. Suppose that you
 * have a struct foo with members A and B. With the macros provided here you can
 * get the address of B, having a pointer to A and knowing that B is the B member
 * of struct foo. This is not my work, is just based on macros provided by gcc
 * compiler __builtin_offsetof() and the container_of() macro found on linux
 * kernel sources. 
 */ 
#include <stdio.h> 

/*
 * You can get the offset of a member on a struct by dereferencing that member on
 * address 0 of such structure.
 */
#define offset_of(type, member) ((unsigned long) &((type *)0)->member)

/*
 * With the capability to get offsets, is possible to get the address of the
 * struct that contains some data. We just need a pointer to that data and the
 * offset of that data on the struct. With this informations we can calculate
 * the address of struct by subtracting the offset from the pointer to that data
 * contained on struct. In the macro above the @ptr is the data contained on
 * struct.
 */
#define container_of(ptr, type, member) \
        ((type *) ((char *)ptr - offset_of(type, member)))

struct foo {
        char *str;
        int len;
};

void print_sibling(int *ip);

int main(void)
{
        struct foo bar = {
                .str = "Hello World",
                .len= 11,
        }; 
        print_sibling(&bar.len);
        
        return 0;

}

/*
 * This function receives an int pointer (@ip) that is known to be the member "len" of
 * a "struct foo". With such information we can do the magic and take any
 * "sibling" member of that struct.
 */
void print_sibling(int *ip)
{
        struct foo *tmp = container_of(ip, struct foo, len);
        puts(tmp->str);
}