Monday, March 20, 2017

OpenWRT Modules (UBOX, UBUS, etc.)

OpenWRT system relies on these projects to bind and integrate userspace applications with centralized configuration.  So, basically OpenWRT = GNU/Linux + network apps + OpenWRT libraries (U- modules)
  • U-BOX
  • U-BUS
  • UCI
  • J-UCI

The foundation is the U-BOX framework. U-BUS depends on it.  While UCI depends on U-BUS, and J-UCI depends on UCI.
The dependency:

J-UCI
 |
 |
 +---> UCI
        |
        |
        +---> UBUS
               |
               |
               +---> UBOX



UBOX


UBox (Micro Box) is a collection of utilities intensively used by OpenWrt project.  It provides facilities, such as polling, event handling, socket helper functions, logging, MD5 hashing, generating/parsing tagged binary data, AVL binary-tree  balancing, JSON handling, task queueing/completion tracking, and others. The RPC module for inter-process communication is called ubus (http://git.openwrt.org/project/ubus.git).






Modules:
  • ULoop
  • UBus



  • BLOB (Binary Large Object)
  • BLOBMSG (based on BLOB)


  • GIT repos: 


    ULoop

    Most used functions in this subsystem are:
    int uloop_init(void);
    void uloop_run(void);
    void uloop_done(void);

    Routine
    Description
    int uloop_init(void)
    Must be called before we can use uloop_run()
    void uloop_run(void)
    This routine does the main loop:
    • Execute scheduled one-shot tasks, if any
    • Execute queued tasks, if any
    • Execute signal handlers, if any
    • Execute event handlers, if any
    The routine runs continuously until we set the global variable uloop_cancelled to true.
    void uloop_done(void)
    Finally, we can this routine before quit to cleanup uloop's internal spaces used before.

    Compilation

    Basically, we just need to tell GCC the path to libubox.so and the headers needed.
    For example:

    Basic Compilation Command
    gcc -o myprog -I. -I/usr/local/include myprog.c -L/usr/local/lib -lubox

    One-shot Timer Task

    A one-time scheduled task is added via uloop_timout_add().
    Routine Name
    Description
    int uloop_timeout_add(struct uloop_timeout *timeout)Add our timeout task into queue
    int uloop_timeout_cancel(struct uloop_timeout *timeout)Delete our timeout task from queue
    int uloop_timeout_set(struct uloop_timeout *timeout, int msec)Set milliseconds from now (e.g, to be executed later after mSecs elapsed)
    int uloop_timeout_remaining(struct uloop_timeout *timeout)How many mSecs remained for the task to be executed
    int uloop_clear_timeouts(void)Empty the one-shot queue completely

    To add an one-time shot event timer, we call uloop_timeout_set(struct uloop_timeout uto*, msecs) (as defined in libubox).   In uloop_timeout, we set a member variable cb for callback, for example:
    Event Callback
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    static struct uloop_timeout my_event_timer;
    static void my_event_handler(struct uloop_timeout *timeout)
    {
        // if we want to make a repeatable event, set the timer again by calling uloop_timeout(timeout, <timeout val in msec)
    }
    void set_event(void)
    {
        my_event_timer.cb = my_event_handler;
        uloop_timeout_set(&my_event_timer, 1000); // timeout in 1 sec
    }
    int main(void)
    {
        uloop_init();
        set_event();
        uloop_run();
        uloop_done();
        return 0;
    }

    Another example:
    Delayed single-shot Task
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdint.h>
    #include <time.h>
    #include "uloop.h"
    void oneshot_cbhandler(struct uloop_timeout *t)
    {
        printf("Executed!\n");
    }
    struct uloop_timeout timeout = {
        .cb = oneshot_cbhandler
    };
    void add_oneshot_timer(struct uloop_timeout *t, unsigned int delay)
    {
        uloop_timeout_set(t, delay);
        uloop_timeout_add(t);
    }
    // set the delay to 1 Second
    add_oneshot_timer(&timeout, 1000);
    // oneshot_cbhandler will be executed 1 second later by uloop_run()

    To make a periodic task, in the callback we re-add our task:

    Periodic Task
    void oneshot_cbhandler(struct uloop_timeout *t)
    {
        printf("Executed!\n");
        add_oneshot_timer(t, 1000);
    }

    The following example shows how to create a periodic task but only executed for limited time, then the uloop is finished:
    Periodic Task For a limited Time
    /*
     * timer.c
     * Lutfi Muhammad
     */
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdint.h>
    #include "uloop.h"
    // 0.25 secs
    TIME_INTERVAL       250
    //forward declaration
    void oneshot_timer(struct uloop_timeout *t);
    static unsigned long ticks = 0;
    struct uloop_timeout timeout = { .cb = oneshot_timer };
    void add_oneshot_timer(struct uloop_timeout *t, unsigned int delay)
    {
        uloop_timeout_set(t, delay);
        uloop_timeout_add(t);
    }
    void oneshot_timer(struct uloop_timeout *t)
    {
        ticks++;
        printf("%s: ticks=%lu\n", __FUNCTION__, ticks);
        if (ticks == 50)
            uloop_cancelled = true;
        else
            add_oneshot_timer(t, TIME_INTERVAL);
    }
    int main(int argc, char **argv)
    {
        uloop_init();
        add_oneshot_timer(&timeout, TIME_INTERVAL);
        uloop_run();
        uloop_done();
        return 0;
    }

    External Processes

    ULoop supports to queue up external processes to be executed in later time.  The execution is one-time (once the process has been executed, it is not repeated unless we re-enter the entry into process queue).
    To queue a process to be executed by uloop_run above, we need to call uloop_process_add() as shows below.  Subsequent calls to uloop_process_add() will queue the processes and would be executed FIFO way.  Once the process/task has been called, it is removed from the queue.

    Routine Name
    Description
    int uloop_process_add(struct uloop_process *p)Insert our task into process queue
    int uloop_process_delete(struct uloop_process *p)Delete our task from process queue

    Example:
    Adding process into queue
    char *init[] = { "/bin/sh""/etc/preinit", NULL };
    struct uloop_process preinit_proc;
    spawn_procd(struct uloop_process *proc, int ret)
    {
        char *argv[] = {"/sbin/procd", NULL};
        execvp(argv[0], argv);
    }
    preinit_proc.cb = spawn_procd;
    preinit_proc.pid = fork();
    if (preinit_proc.pid == 0)
    {
        // we're a child already, so simply execute "init" directly
        execvp(init[0], init);
        exit(-1);
    }
    // add to queue of processes to be executed
    uloop_process_add(&preinit_proc);
    //.... sometime later,spawn_procd() would be called by uloop_run() ....


    uloop_init() is used to do main loop. A typical construct is as follow:

    Server using U-Loop
    const char *port = "8080";
    void server_cb(int param)
    {
        // yadi..yada
    }
    struct uloop_fd server = {
        .cb = server_cb,
        .fd = usock(USOCK_TCP | USOCK_SERVER | USOCK_IPV4ONLY | USOCK_NUMERIC, "127.0.0.1", port);
    }'
    int main()
    {
        uloop_init();
         
        uloop_fd_add(&server, ULOOP_READ);  // add server_cb as the TCP listener at port 8080
        uloop_run();  // this will run forever
    }


    Generic Example of ULoop app
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    int main(int argc, char **argv)
    {
        const char *ubus_socket = NULL;
        bool client = false;
        int ch;
        while ((ch = getopt(argc, argv, "cs:")) != -1) {
            switch (ch) {
            case 's':
                ubus_socket = optarg;
                break;
            case 'c':
                client = true;
                break;
            default:
                break;
            }
        }
        argc -= optind;
        argv += optind;
        uloop_init();
        ctx = ubus_connect(ubus_socket);
        if (!ctx) {
            fprintf(stderr, "Failed to connect to ubus\n");
            return -1;
        }
        ubus_add_uloop(ctx);
        if (client)
            client_main();
        else
            server_main();
        ubus_free(ctx);
        uloop_done();
        return 0;
    }

    Client version  (when client_main() routine above is executed):
    ULoop Client
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    static void client_main(void)
    {
        uint32_t id;
        int ret;
        ret = ubus_add_object(ctx, &test_client_object);
        if (ret) {
            fprintf(stderr, "Failed to add_object object: %s\n", ubus_strerror(ret));
            return;
        }
        if (ubus_lookup_id(ctx, test_object.name, &id)) {
            fprintf(stderr, "Failed to look up test object\n");
            return;
        }
        blob_buf_init(&b, 0);
        blobmsg_add_u32(&b, "id", test_client_object.id);
        ubus_invoke(ctx, id, "watch", b.head, NULL, 0, 3000);
        uloop_run();
    }
    All routines prepended with "ubus_" provided by ubus  library.
    To prepare ubus for RPC communication, first we create a context by calling: ctx = ubus_connect(path), where path is the path to pipe (e.g: "/tmp/compipe").  Once we have the context, we call ubus_add_uloop() to let uloop to handle ubus-related default events.

    Task Queue

    As described in libubox/runqueue.h:
    Task and Process Queue APIs
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    struct runqueue;
    struct runqueue_task;
    struct runqueue_task_type;
    struct runqueue {
        struct safe_list tasks_active;
        struct safe_list tasks_inactive;
        struct uloop_timeout timeout;
        int running_tasks;
        int max_running_tasks;
        bool stopped;
        bool empty;
        /* called when the runqueue is emptied */
        void (*empty_cb)(struct runqueue *q);
    };
    struct runqueue_task_type {
        const char *name;
        /*
         * called when a task is requested to run
         *
         * The task is removed from the list before this callback is run. It
         * can re-arm itself using runqueue_task_add.
         */
        void (*run)(struct runqueue *q, struct runqueue_task *t);
        /*
         * called to request cancelling a task
         *
         * int type is used as an optional hint for the method to be used when
         * cancelling the task, e.g. a signal number for processes. Calls
         * runqueue_task_complete when done.
         */
        void (*cancel)(struct runqueue *q, struct runqueue_task *t, int type);
        /*
         * called to kill a task. must not make any calls to runqueue_task_complete,
         * it has already been removed from the list.
         */
        void (*kill)(struct runqueue *q, struct runqueue_task *t);
    };
    struct runqueue_task {
        struct safe_list list;
        const struct runqueue_task_type *type;
        struct runqueue *q;
        void (*complete)(struct runqueue *q, struct runqueue_task *t);
        struct uloop_timeout timeout;
        int run_timeout;
        int cancel_timeout;
        int cancel_type;
        bool queued;
        bool running;
        bool cancelled;
    };
    struct runqueue_process {
        struct runqueue_task task;
        struct uloop_process proc;
    };
    #define RUNQUEUE_INIT(_name, _max_running) { \
            .tasks_active = SAFE_LIST_INIT(_name.tasks_active), \
            .tasks_inactive = SAFE_LIST_INIT(_name.tasks_inactive), \
            .max_running_tasks = _max_running \
        }
    #define RUNQUEUE(_name, _max_running) \
        struct runqueue _name = RUNQUEUE_INIT(_name, _max_running)
    void runqueue_init(struct runqueue *q);
    void runqueue_cancel(struct runqueue *q);
    void runqueue_cancel_active(struct runqueue *q);
    void runqueue_cancel_pending(struct runqueue *q);
    void runqueue_kill(struct runqueue *q);
    void runqueue_stop(struct runqueue *q);
    void runqueue_resume(struct runqueue *q);
    void runqueue_task_add(struct runqueue *q, struct runqueue_task *t, bool running);
    void runqueue_task_add_first(struct runqueue *q, struct runqueue_task *t, bool running);
    void runqueue_task_complete(struct runqueue_task *t);
    void runqueue_task_cancel(struct runqueue_task *t, int type);
    void runqueue_task_kill(struct runqueue_task *t);
    void runqueue_process_add(struct runqueue *q, struct runqueue_process *p, pid_t pid);
    /* to be used only from runqueue_process callbacks */
    void runqueue_process_cancel_cb(struct runqueue *q, struct runqueue_task *t, int type);
    void runqueue_process_kill_cb(struct runqueue *q, struct runqueue_task *t);

    Normally, we first call runqueue_init first.  Later we can add a task or process to the queue (which will be executed by uloop_run).  To add a task, we call runqueue_task_add() and to add a process to the queue is runqueue_process_add().  The difference between task and process in this context is that process is an external job/program to be executed (similar to at or cron), while task is simply a routine to be called later.
    For Example:
    Task Queue Example
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    static struct runqueue my_queue;
    ...
    runqueue_init(&my_queue);
    ...
    static void handle_run_script(struct job *j, struct blob_attr *exec, struct blob_attr *env)
    {
        pid_t pid;
        pid = fork();
        if (pid < 0)
           return;
        if (pid > 0) {
            runqueue_process_add(&q, &j->proc, pid);
            return;
        }
        // after this line, it applies only to a child process
         // ---- DO SOMETHING HERE -----
    }
    static struct cmd handlers[] = {
        {
            .name = "run_script",
            .handler = handle_run_script,
        },
    };
    static void rule_handle_command(struct trigger *t, const char *name, struct blob_attr *exec, struct blob_attr *vars)
    {
        struct trigger *t = container_of(ctx, struct trigger);
        int i;
        if (t->pending)
            return;
        for (i = 0; i < ARRAY_SIZE(handlers); i++) {
            if (!strcmp(handlers[i].name, name)) {
                add_job(t, &handlers[i], exec, vars);
                break;
            }
        }
    }
    (&my_queue)

    BLOB (Binary Large OBject)

    BLOB submodule is used for message formatting, packaging and handling.  There are several supported datatypes, and it creates blobs that could be sent over any socket, as endianess is taken care in the library itself.
    The method is to create a type-value chained data, supporting nested data. This part basically covers putting and getting datatypes. Further functionality is implemented in blobmsg.h.
    Blobmsg sits on top of blob.h, providing tables and arrays, providing it's own but parallel datatypes.

    Some important routines:
    BLOB API
    bool              blob_attr_equal(const struct blob_attr *a1, const struct blob_attr *a2);
    int               blob_buf_init(struct blob_buf *buf, int id);
    void              blob_buf_free(struct blob_buf *buf);
    bool              blob_buf_grow(struct blob_buf *buf, int required);
    void              blob_fill_pad(struct blob_attr *attr);
    struct blob_attr* blob_new(struct blob_buf *buf, int id, int payload);
    void*             blob_nest_start(struct blob_buf *buf, int id);
    void              blob_nest_end(struct blob_buf *buf, void *cookie);
    struct blob_attr* blob_put(struct blob_buf *buf, int id, const void *ptr, unsigned int len);
    struct blob_attr* blob_put_raw(struct blob_buf *buf, const void *ptr, unsigned int len);
    bool              blob_check_type(const void *ptr, unsigned int len, int type);
    int               blob_parse(struct blob_attr *attr, struct blob_attr **data, const struct blob_attr_info *info, int max);
    struct blob_attr* blob_memdup(struct blob_attr *attr);
    void              blob_set_raw_len(struct blob_attr *attr, unsigned int len);
    static <type> inline blob_get_<type>(blob_attr *);
    static <type> inline blob_put_<type>(blob_attr *);

    Example:
    BLOB Example
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #include "blob.h"
    #define BUF_ID    0
    enum {
         BUF_U8,
         BUF_U16,
         BUF_U32,
         BUF_U64,
         BUF_STR
    };
    int main()
    {
        static struct blob_buf buf;
        // initiate
        blob_buf_init(&buf, BUF_ID);
        // put some values in sequence
        blob_put_string(&buf, BUF_STR, Hello, World!");
        uint32_t val = 300;
        blob_put_U32(&buf, BUF_U32, (uint32_t)val);
         
        // free it
        blob_buf_free(&buf);
    }

    BLOBMSG

    Function Name
    Description
    int blobmsg_hdrlen(unsigned int namelen)

    void blobmsg_clear_name(struct blob_attr *attr)

    const char *blobmsg_name(const struct blob_attr *attr)

    int blobmsg_type(const struct blob_attr *attr)

    void *blobmsg_data(const struct blob_attr *attr)

    int blobmsg_data_len(const struct blob_attr *attr)

    bool blobmsg_check_attr(const struct blob_attr *attr, bool name)

    bool blobmsg_check_attr_list(const struct blob_attr *attr, int type)

    int blobmsg_check_array(const struct blob_attr *attr, int type)
    int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len,
    struct blob_attr **tb, void *data, unsigned int len)

    int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len,
    struct blob_attr **tb, void *data, unsigned int len)

    int blobmsg_add_field(struct blob_buf *buf, int type, const char *name,
    const void *data, unsigned int len)

    int blobmsg_add_u8(struct blob_buf *buf, const char *name, uint8_t val)

    int blobmsg_add_u16(struct blob_buf *buf, const char *name, uint16_t val)

    int blobmsg_add_u32(struct blob_buf *buf, const char *name, uint32_t val)

    int blobmsg_add_u64(struct blob_buf *buf, const char *name, uint64_t val)

    int blobmsg_add_string(struct blob_buf *buf, const char *name, const char *string)

    int blobmsg_add_blob(struct blob_buf *buf, struct blob_attr *attr)

    void *blobmsg_open_nested(struct blob_buf *buf, const char *name, bool array);

    void *blobmsg_open_array(struct blob_buf *buf, const char *name)

    void *blobmsg_open_table(struct blob_buf *buf, const char *name)

    void
    blobmsg_close_array(struct blob_buf *buf, void *cookie)

    void
    blobmsg_close_table(struct blob_buf *buf, void *cookie)

    int blobmsg_buf_init(struct blob_buf *buf)

    uint8_t blobmsg_get_u8(struct blob_attr *attr)





    ULOG

    The APIs provided are:
    ULOG API
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    enum {
        ULOG_KMSG   = (1 << 0),
        ULOG_SYSLOG = (1 << 1),
        ULOG_STDIO  = (1 << 2)
    }; // for channels
    /* as defined in /usr/include/sys/syslog.h, facility can be one of these:
    LOG_KERN
    LOG_USER
    LOG_MAIL
    LOG_DAEMON
    LOG_AUTH
    LOG_SYSLOG
    LOG_LPR
    LOG_NEWS
    LOG_UUCP
    LOG_CRON
    LOG_AUTHPRIV
    LOG_FTP
    LOG_LOCAL[0-7]
    ident: a string to identify our string, so the log will be prepended with "<ident>: "
    */
    void ulog_open(int channels, int facility, const char *ident);
    void ulog_close(void);
    void ulog_threshold(int threshold);
    void ulog(int priority, const char *fmt, ...);
    #define ULOG_INFO(fmt, ...) ulog(LOG_INFO, fmt, ## __VA_ARGS__)
    #define ULOG_NOTE(fmt, ...) ulog(LOG_NOTICE, fmt, ## __VA_ARGS__)
    #define ULOG_WARN(fmt, ...) ulog(LOG_WARNING, fmt, ## __VA_ARGS__)
    #define ULOG_ERR(fmt, ...) ulog(LOG_ERR, fmt, ## __VA_ARGS__)
    void ulog_threshold(int threshold);
    void ulog(int priority, const char *fmt, ...);
    #define ULOG_INFO(fmt, ...) ulog(LOG_INFO, fmt, ## __VA_ARGS__)
    #define ULOG_NOTE(fmt, ...) ulog(LOG_NOTICE, fmt, ## __VA_ARGS__)
    #define ULOG_WARN(fmt, ...) ulog(LOG_WARNING, fmt, ## __VA_ARGS__)
    #define ULOG_ERR(fmt, ...) ulog(LOG_ERR, fmt, ## __VA_ARGS__)

    (...to be continued...)

    Friday, March 17, 2017

    Raspberry-pi update without IPv6 checking


    To prevent Raspberry-Pi to use IPv6 when updating:

    Edit file /etc/apt/apt.conf.d/99force-ipv4,  and in it add:

    Acquire::ForceIPv4 "true";

    Thursday, October 20, 2016

    Denial of Service on detection of Intrusion event

    The following iptables rules should be adequate to lower the change an intruder to continuously try to login to our server.

    #!/bin/bash
    
    ### BLOCKING INTRUDERS TO OUR SSH SERVICE ####
    
    VERBOSE=1
    
    execandprint() {
     cmd="${1}"
     [[ $VERBOSE -eq 1 ]] && echo "$cmd"
     ${cmd}
    }
    
    # create properREJECT chain that does different rejects for tcp/udp
    rjchain="properREJECT"
    echo "Creating chain $rjchain in filter table..."
    iptables -N $rjchain
    iptables -A $rjchain -m limit --limit 2/min -j LOG --log-prefix "REJECTED: " --log-level 4
    iptables -A $rjchain -p tcp -j REJECT --reject-with tcp-reset
    iptables -A $rjchain -j REJECT --reject-with icmp-port-unreachable
    
    #
    blchain="blacklistdrop"
    echo "Creating chain $blchain in filter table..."
    iptables -N $blchain
    iptables -A $blchain -m limit --limit 2/second -j LOG --log-prefix "adding to BLACKLIST: " --log-level 6
    iptables -A $blchain -m recent --name BLACKLIST --set -j DROP
    
    # block this baukdeh in Shenzhen, China
    iptables -A INPUT -s 221.229.172.71 -j $rjchain
    
    #
    # if the src address of packet is currently in the list BLACKLIST within the last 120 seconds, drop it
    # see /proc/net/xt_recent/BLACKLIST
    execandprint "iptables -A INPUT -m recent --name BLACKLIST --update --seconds 120 -j DROP"
    #
    # all *established* ssh connections simply continue
    # see /proc/net/nf_conntrack and /proc/net/xt_recent/sshconn
    execandprint "iptables -A INPUT  -p tcp --dport 22 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT"
    #
    # *new* ssh connections are all put into a list 'sshconn', and if there are 3 such packets in 30 seconds
    # we send the package to chain 'blacklistdrop' which puts the IP in the blacklist
    execandprint "iptables -A INPUT  -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --name sshconn --rcheck --seconds 30 --hitcount 3 -j $blchain"
    
    #
    # if we have seen less then 3 such packets in the last 30 seconds we accept
    execandprint "iptables -A INPUT  -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --name sshconn --set -j ACCEPT"
    
    #
    # if the destination address is in the blacklist, we REJECT *any* packet
    execandprint "iptables -A OUTPUT -m recent --name BLACKLIST --rdest --rcheck --seconds 30 -j $rjchain"
    
    #
    # outgoing we accept all ssh traffic, with connection tracking
    execandprint "iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED,NEW,RELATED -j ACCEPT"
    
    



    Friday, September 30, 2016

    ZMODEM file transfer between Windows VM on VirtualBox and Linux

    This is to show an alternative to transfer a file between host (Linux) and Windows XP running over VirtualBox on the same machine.


    1. On VirtualBox configuration, enable serial communication on port COM1, select "Host Pipe"  for Port Mode, and in "Path/Address" input box type "/tmp/WINCOM1".
    2. Start Windows VM
    3. From Windows VM, start Hyper Terminal, set speed to 115200 and no Flow control
    4. On Linux, open a terminal and type: sudo socat unix-connect /tmp/WINCOM1 TCP4-LISTEN:telnet
    5. To transfer file using ZMODEM, open another terminal and type: sz --tcp-client localhost:23 <file to transfer>


    To connect to Windows' serial terminal, we simply telnet to localhost: telnet localhost, and amything we type on the telnet terminal will echo back on Windows' HyperTerminal and vice versa.

    Thursday, September 22, 2016

    Some VirtualBox Interesting internal features

    As documented:

    Usage: VBoxManage internalcommands <command> [command arguments]

    Commands:

      loadmap <vmname|uuid> <symfile> <address> [module] [subtrahend] [segment]
          This will instruct DBGF to load the given map file
          during initialization.  (See also loadmap in the debugger.)

      loadsyms <vmname|uuid> <symfile> [delta] [module] [module address]
          This will instruct DBGF to load the given symbol file
          during initialization.

      sethduuid <filepath> [<uuid>]
           Assigns a new UUID to the given image file. This way, multiple copies
           of a container can be registered.

      sethdparentuuid <filepath> <uuid>
           Assigns a new parent UUID to the given image file.

      dumphdinfo <filepath>
           Prints information about the image at the given location.

      listpartitions -rawdisk <diskname>
           Lists all partitions on <diskname>.

      createrawvmdk -filename <filename> -rawdisk <diskname>
                    [-partitions <list of partition numbers> [-mbr <filename>] ]
                    [-relative]
           Creates a new VMDK image which gives access to an entire host disk (if
           the parameter -partitions is not specified) or some partitions of a
           host disk. If access to individual partitions is granted, then the
           parameter -mbr can be used to specify an alternative MBR to be used
           (the partitioning information in the MBR file is ignored).
           The diskname is on Linux e.g. /dev/sda, and on Windows e.g.
           \\.\PhysicalDrive0).
           On Linux or FreeBSD host the parameter -relative causes a VMDK file to
           be created which refers to individual partitions instead to the entire
           disk.
           The necessary partition numbers can be queried with
             VBoxManage internalcommands listpartitions

      renamevmdk -from <filename> -to <filename>
           Renames an existing VMDK image, including the base file and all its extents.

      converttoraw [-format <fileformat>] <filename> <outputfile>
           Convert image to raw, writing to file.

      converthd [-srcformat VDI|VMDK|VHD|RAW]
                [-dstformat VDI|VMDK|VHD|RAW]
                <inputfile> <outputfile>
           converts hard disk images between formats

      repairhd [-dry-run]
               [-format VDI|VMDK|VHD|...]
               <filename>
           Tries to repair corrupted disk images

      debuglog <vmname|uuid> [--enable|--disable] [--flags todo]
               [--groups todo] [--destinations todo]
           Controls debug logging.

      passwordhash <passsword>
           Generates a password hash.

      gueststats <vmname|uuid> [--interval <seconds>]
           Obtains and prints internal guest statistics.
           Sets the update interval if specified.

    WARNING: This is a development tool and shall only be used to analyse
             problems. It is completely unsupported and will change in
             incompatible ways without warning.

    I think some of the most useful ones are:
    repairhd
    converthd

    So, if we want to convert Qemu's virtual-disk format (QCow) to VDI/VMDK/VHD, the steps are as follow (assume the qemu' image file is called home.qcow):

    qemu-img convert -f qcow home.qcow -O raw home_raw.img
    vboxmanage internalcommands converthd -srcformat RAW -dstformat VDI home_raw.img home.vdi

    or
    VBoxManage convertfromraw --format VDI home_raw.img home.vdi

    Another interesting one, if we want to create and boot a virtual machine from a USB device.  Steps are:


    1. Verify which device the usb drive is attached to (e.g, /dev/sdd)
    2. Do:  VBoxManage internalcommands createrawvmdk -filename usb.vmdk  -rawdisk /dev/sdd
    3. Start VirtualBox and mount the file usb.vmdk in the storage (or, create a new Virtual Machine and attach the file usb.vmdk as the first storage)



    Monday, September 19, 2016

    Xamarin: The best way to develop Multi-platform Apps


    Xamarin is a framework made by Microsoft to let developers to develop apps running natively on multiple platforms (Windows, iOS, Android).

    The beauty about this framework SDK is enabling us to make apps running natively.  Our code is developed in C# (so for Windows we need to have Ms. Visual Stdio).  It uses native UI for its apps, so once we develop an app for Windows, for example, it's also compilable on Mac OS without code changes.  The same for Android.

    The framework can be downloaded freely for Windows and MacOS:

    https://www.xamarin.com/platform