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);
}


sábado, 22 de outubro de 2011

Character device Hello World

This is a little character device hello World, more
information on code.

/*
 * file: gkos_char_device.c
 *
 * Desc: A simple device that
 *      echos a message when read,
 *      write method not implemented
 *
 *      This was made on top of 
 *      LDD and LKMPG examples 
 *      
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>

#define DEVICE_NAME "gkos_char_device"


/*
 * Prototypes 
 */
int init_module(void);
void cleanup_module(void);
static int dev_open(struct inode *inode, struct file *);
static int dev_release(struct inode *inode, struct file *);
static ssize_t dev_read(struct file *fp, char *buf, size_t len, loff_t *off);
static ssize_t dev_write(struct file *, const char *buf, size_t len, 
                loff_t *off);
static int dev_init(void);

/*
 * Our variables, @use_counter
 * will block concurrenty opens.
 * @buffer is the message and
 * @buffer_len the lenght of @buffer (duh)
 */
static char use_counter = 0;
static char buffer[] = "Hello character device world\n";
static int buffer_len = sizeof(buffer);

static dev_t dev;
static struct cdev *cdevp;


static struct file_operations fops = {
        .owner = THIS_MODULE,
        .read = dev_read,
        .write = dev_write,
        .open = dev_open,
        .release = dev_release
};

/*
 * Any device specific initialization
 * goes here. Its called at bottom of init_module()
 */
static int dev_init(void)
{
        return 0;
}

/*
 * Called when device is opened
 */
static int dev_open(struct inode *inode, struct file *fp)
{
        if (use_counter)
                return -EBUSY;
        use_counter++;
        try_module_get(THIS_MODULE);
        return 0;
}

/* 
 * Called when device is released. The device is
 * released when there is no process using it.
 */
static int dev_release(struct inode *inode, struct file *fp)
{
        use_counter--;
        module_put(THIS_MODULE);
        return 0;
}


/*
 * @off controls
 * the "walk" through our buffer, is whith @off
 * that we say to user where is stoped.
 * @len is how much bytes to read. I almost ignore it.
 * I just check if is greater than 0.
 *
 * Called when device is read. 
 * This method will read one, and only one byte per call,
 * If @off is longer than my buffer size or len is not
 * greater than 0 it returns 0, otherwise I copy one byte
 * to user buffer and returns the bytes readed, so 1.
 */
static ssize_t dev_read(struct file *fp, char *buf, size_t len, loff_t *off)
{
        if (*off >= buffer_len || len <= 0)
                return 0;

        if (copy_to_user(buf, &buffer[*off], 1u))
                        return -EFAULT;

        (*off)++;
        return 1;
}


/*
 * Not implemented at all
 */
static ssize_t dev_write(struct file *fp, const char *buf, size_t len, 
                loff_t *off)
{
        return -ENOSYS;
}

/*
 * Called when module is load
 */
int init_module(void)
{
        int error;

        /* Alloc a device region */
        error = alloc_chrdev_region(&dev, 1, 1, DEVICE_NAME);
        if (error) 
                goto error_out;

        /* Registring */
        cdevp = cdev_alloc();
        if (!cdevp) 
                return -ENOMEM; 

        /* Init it! */
        cdev_init(cdevp, &fops); 

        /* Tell the kernel "hey, I'm exist" */
        error = cdev_add(cdevp, dev, 1);
        if (error < 0) 
                goto error_out;

        printk(KERN_INFO DEVICE_NAME " registred with major %d\n", MAJOR(dev));
        printk(KERN_INFO DEVICE_NAME " do: `mknod /dev/%s c %d %d' to create "
                        "the device file\n", 
                        DEVICE_NAME, MAJOR(dev), MINOR(dev)); 

        /* Device initialization isn't needed yet */
        if (dev_init())
                goto error_out;

        return 0;

error_out:
        return -EFAULT;
}

void cleanup_module(void)
{
        cdev_del(cdevp);
}

MODULE_LICENSE("GPL");

Makefile:
obj-m += gkos_char_device.o

all:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 
 
clean:
 rm *.ko *.o *.mod.c *.mod.o

Building and Running:

sexta-feira, 21 de outubro de 2011

Perl assembly generator

I wrote a little perl script that receives input and creates an x86 assembly program. This program put all data on stack and then print it using printf c function. Useless but cool
#!/usr/bin/perl

use warnings;
use strict;

undef $/;
my $input = <>

$input = unpack("H*", $input);
my @integers;

while (length($input) > 8) {
 my $str = substr($input, 0, 8);
 $str =~ s/(.{2})(.{2})(.{2})(.{2})/$4$3$2$1/;
 push(@integers, ("0x".$str));
 $input = substr($input, 8);
}

my $buf = "";
while (length($input) > 0) {
 $buf .= substr($input, -2);
 $input = substr($input, 0, -2);
}

push(@integers, sprintf("0x%08x", hex($buf)));
my $stck_deep = ($#integers + 1) * 4;

print <<EOS
        .section        .text.startup,"ax",\@progbits
        .globl  main
        .type   main, \@function
main:
        pushl   %ebp
        movl    %esp, %ebp

 subl \$$stck_deep, %esp

 movl \$$integers[0], (%esp)
EOS
;

for my $i (1 .. $#integers) {
 printf("\tmovl \$%s, %d(%%esp)\n", $integers[$i], $i * 4); 
} 

print <<EOS
 movl \$0x0, $stck_deep(%esp)
 
 pushl %esp
 call printf
 popl %eax

 addl \$$stck_deep, %esp


 xorl %eax, %eax
 leave
 ret
EOS

;

Here is a try:
https://ideone.com/cuvXe
https://ideone.com/2oA9q
[]'s

terça-feira, 11 de outubro de 2011

Pickshit game ported to autotools

I have made just a exercise of applying autotools to my Pick stick game


Here is the "autotool'ed" source

[]'s

Procfs hello world

Fuck you world... I will learn kernel, getting payed or not!!


Here is a simple procfs hello world


The source (proc2.c)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>

static struct proc_dir_entry *proc_file;

int procfile_read(char *buf, char **buf_location, off_t offset,
 int buf_len, int *eof, void *data)
{
 return sprintf(buf, "Hello Word\n"); 
}

#define PROC_FILE_NAME "hello"
int init_module()
{
 proc_file = create_proc_entry(PROC_FILE_NAME, 0644, NULL);
 if (!proc_file) { 
  remove_proc_entry(PROC_FILE_NAME, NULL);
  return -ENOMEM;
 } 
 proc_file->read_proc = procfile_read;
 proc_file->mode = 0644;
 proc_file->uid = 0;
 proc_file->gid = 0;
 proc_file->size = 37;
 return 0;
}


void cleanup_module()
{
 remove_proc_entry(PROC_FILE_NAME, NULL);
}

The Makefile
obj-m += proc2.o

all:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

Compiling and running


Cheers :-P

quinta-feira, 16 de junho de 2011

Java script

This is real life?

Yeah it is, so I get tired to run toward my dreams
and try to get a dev job. I choose php + javascript. I don't
really like php, but JavaScript can be really fun!!! Better than
live with support stress.

Here is my latest betting:


and
 The O'Reilly books are really the best ever! They come from
basic to advanced in a book that promises only the basic and
in a easy, clearly and deep speak.

So, web, there I go!

segunda-feira, 4 de abril de 2011

Pickshit game

Pickshit is a pointless game where you need to clean the shits that apear
around. Isn't actually game because there is no objective to complete. It's just an exercise in games developing know as pick stick.

The "game" was develop using allegro library so you need to have it installed to compile the game. I'm working on a better prototype.

You can download the game code/files here, and compile using this:
$ gcc -o pickshit pickshit.c -lalleg

Controls:
Arrows to move
ESC to exit

screenshot:




See you...

Cheers

terça-feira, 8 de março de 2011

Boot hello world

; Tell the compiler that this is the 0 address
[ORG 0] 
    jmp 07C0h:start   ; Jump to start

    msg db "Hello boot world ", 2, 0 ; My string
         ; the 2 byte should provide some fun

start: 

    ; Setting up the segment registers
    
    mov ax, cs
    mov ds, ax
    mov es, ax
    
    
    ; Writing the string 

    mov si, msg
print:    lodsb
    cmp al, 0
    je hang
    mov ah, 0Eh
    mov bx, 7
    int 010h    ; BIOS video service interrupt
    
    jmp print
    

hang:     
    jmp hang


    times 510-($-$$) db 0
    dw 0AA55h

.

I saw this here, so is not my merit..

to run:
copy this to a .asm file, e.g. b.asm, then assemble it with
$ nasm -o b.bin b.asm
and finaly write it to some pendrive with
dd if=b.bin of=/dev/YOURPENDRIVE
e.g $ dd if=b.bin of=/dev/sdc
Boot the pendrive and you should get a funny message on screen =)
if you have qemu installed you can boot directly the binary
$ qemu -hda b.bin

domingo, 9 de janeiro de 2011

Revised tree

I have to make some changes in tree.c and tree.h, so del_branch
can be implemented easily!

Code:

tree.h
#ifndef GKO_TREE_H
#define GKO_TREE_H

#include "stack.h"
#include "common.h"

struct branch {
    char *name;
    char *data;
    struct branch *cont;
    struct branch *next;
} branch;
    

void init_tree (struct branch *,  char *,  char *) ;
void set_branch (struct branch *,  char *,  char *);
struct branch * get_branch (struct branch *,  char *);
void del_branch (struct branch *);

#endif


tree.c
#include "tree.h"

/* Initialize a Tree, set the root node */
void
init_tree (struct branch *t, char *name, char *data) 
{
    cpystr (&t->name, name);
    cpystr (&t->data, data);
    t->cont = NULL;
    t->next = NULL;
}

/* Create a new struct branch or edit an existent one */
void
set_branch (struct branch *t, char *name, char *data)
{
    struct branch *b;
    struct branch *prior;

    if (!t || !name || !data)
        pexit ("set_branch: NULL argument call\n");

    for (b = t->cont, prior = NULL; b; prior = b, b = b->next) {
        if (! strcmp (b->name, name)) {
            free (b->data);
            cpystr (&b->data, data);
            return;
        }
    }

    b = xmalloc (sizeof (struct branch));
    init_tree (b, name, data);
    if (!prior) /* if there is no content in branch *t, the prior remains NULL */
        t->cont = b;
    else
        prior->next = b;
}

/* Return the address of a struct branch */
struct branch *
get_branch (struct branch *t, char *name)
{
    struct branch *b;
    
    if (!t || !name)
        pexit ("get_brach: NULL argument call\n");

    for (b = t->cont; b; b = b->next)
        if (! strcmp (b->name, name))
            return b;
    
    return NULL;
}


/* Delete a struct branch an everything below that node */
void
del_branch (struct branch *t)
{
    if (t->cont) 
        del_branch (t->cont);

    if  (t->next)
        del_branch (t->next);
    
    free (t->name);
    free (t->data);
    free (t);
}


common.c
#include "common.h"

void
pexit (const char *msg)
{
    perror (msg);
    exit (EXIT_FAILURE);
} 
    
void *
xmalloc (size_t siz)
{
    void *n = malloc (siz);
    if (!n) 
        pexit ("malloc");
    return n;
}

void
cpystr (char **dst, char *src)
{
    int len = strlen (src) + 1;
    *dst = xmalloc (len);
    strncpy (*dst, src, len); 
}


test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "tree.h"

main ()
{
    struct branch *myt = xmalloc (sizeof (struct branch));
    struct branch *buf;

    init_tree (myt, "root", "root_data");
    set_branch (myt, "etc", "etc_data");
    set_branch (myt, "usr", "usr_data");
    buf = get_branch (myt, "etc");
    set_branch (buf, "rc.conf", "rc.conf data");
    set_branch (myt, "etc", "etc_edited_data");

    del_branch (myt);
    return 0;
}

sexta-feira, 7 de janeiro de 2011

Middleware manager..

Yeap, I got a job. Intern on middleware management area.. I really like it.. I have
close contact with commercial aplications and linux/unix environments... and the warm/pressure of the businesses.. There are nice guys there.. some times looks like an arena.. but with little fat funny guys instead of big muscle losers.. :-) 

by the way.. an tree prototype...


tree.h
#ifndef GKO_TREE_H
#define GKO_TREE_H

#include "stack.h"
#include "ll.h"
#include "common.h"

typedef struct branch {
    char *name;
    char *data;
    ll cont;
    struct branch *next;
} branch;
    
void init_tree (branch *,  char *,  char *) ;
void set_branch (branch *,  char *,  char *);
branch *get_branch (branch *, char *);

#endif


tree.c
#include "tree.h"

/* Initialize a Tree, set the root node */
void
init_tree (branch *t, char *name, char *data) 
{
    cpystr (&t->name, name);
    cpystr (&t->data, data);
    init_ll (&t->cont);
    t->next = NULL;
}

/* Create a new branch or edit an existent one */
void
set_branch (branch *t, char *name, char *data)
{
    lln **node = search_lln (&t->cont, name);
    branch *b;

    if (node) { /* edit branch */
        b = node[0]->data; /* the address of found branch */
        free (b->data);
        cpystr (&b->data, data);
    } else { /* create a brand new branch */
        b = xmalloc (sizeof (branch));
        init_tree (b, name, data);
    }
    
    add_lln (&t->cont, name, b); /* tree contains branch */
}

/* Return the address of a branch */
branch *
get_branch (branch *t, char *name)
{
    lln **node = search_lln (&t->cont, name);
    if (node)
        return node[0]->data; /* return void * don't need casts */
    return NULL;
}

/* Delete a branch an everything below that node */
/* @TODO */
void
del_branch ()
{
}



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

#include "tree.h"

main ()
{
    branch myt;
    branch *buf;

    init_tree (&myt, "root", "root_data");
    set_branch (&myt, "etc", "etc_data");
    set_branch (&myt, "usr", "usr_data");

    buf = get_branch (&myt, "etc");
    printf ("Searched %s\n", buf->data);
    
    set_branch (buf, "rc.conf", "rc.conf data");
    buf = get_branch (buf, "rc.conf");
    printf ("Searched %s\n", buf->data);

    buf = get_branch (&myt, "usr");
    printf ("User data? %s\n", buf->data); 

    set_branch (&myt, "etc", "etc_edited_data");
    buf = get_branch (&myt, "etc");
    printf ("Searched %s\n", buf->data);

    return 0;
}


MAYBE I work more on this..