Tuesday, April 29, 2014

Using ipset

Finally got it to work. Nobody seems to have a complete and accurate solution for my case... So here it is.
 #include <iostream>  
 #include <thread>     // std::thread  
 #include <mutex>     // std::mutex  
 #include <assert.h>  
 extern "C" {  

 // Debian libipset libary is a C library. All the headers  
 // have to be enclosed in extern "C" brackets to have  
 // proper linkage  
 #include <libipset/session.h>      /* ipset_session_* */  
 #include <libipset/data.h>       /* enum ipset_data */  
 #include <libipset/parse.h>       /* ipset_parse_* */  
 #include <libipset/types.h>       /* struct ipset_type */  
 #include <libipset/ui.h>        /* core options, commands */  
 #include <libipset/utils.h>       /* STREQ */  
 }  
 // debian-ipset is not thread-safe. We're using  
 // a mutex to serialize the ipset calls.  
 std::mutex s_ipsetMutex;  
 // We're only adding a command/an element to the set,  
 // so the restore line no. remains 0  
 #define IPSET_SESSION_LINE_NO 0  
 int  
 ipsetAdd(std::string table, std::string set_type, uint32_t interval)  
 {  
  int32_t ret = 0;  
  const struct ipset_type *type = NULL;  
  enum ipset_cmd cmd = IPSET_CMD_ADD;  
  struct ipset_session *session;  
  // debian-ipset calls are not thread-safe. We're adding  
  // a mutex to serialize the calls.  
  s_ipsetMutex.lock();  
  ipset_load_types();  
  // Initialize an ipset session by allocating a session structure  
  // and filling out with the initialization data.  
  session = ipset_session_init(printf);  
  if (session == NULL)  
  {  
   printf("ipsetAdd: Cannot initialize ipset session for "  
     "set_type %s. aborting.\n", set_type.c_str());  
   ret = 1;  
  }  
  else  
  {  
   // Set session lineno to report parser errors correctly   
   ipset_session_lineno(session, IPSET_SESSION_LINE_NO);  
   // Parse string as a setname.  
   // The value is stored in the data blob of the session.  
   ret = ipset_parse_setname(session, IPSET_SETNAME, table.c_str());  
   if (ret == 0)  
   {  
    type = ipset_type_get(session, cmd);  
    if (!type)  
    {  
     printf("ipsetAdd: Failed to get the set type from Kernel "  
       "set_type=%s table=%s sess=%p cmd=%d\n", set_type.c_str(), table.c_str(),  
       session, cmd);  
     ret = 1;  
    }  
    else  
    {  
     // Parse string as a (multipart) element according to the settype.  
     // The value is stored in the data blob of the session.  
     ret = ipset_parse_elem(session, (ipset_opt)type->last_elem_optional,  
                 set_type.c_str());  
     if (ret == 0)  
     {  
      // Put a given kind of data into the data blob and mark the  
      // option kind as already set in the blob.  
      ret = ipset_data_set(ipset_session_data(session), IPSET_OPT_TIMEOUT, &interval);  
      if (!ret)  
      {  
       // Execute a command  
       ret = ipset_cmd(session, cmd, IPSET_SESSION_LINE_NO);  
       if (ret)  
       {  
        printf("ipsetAdd: WARNING: Failed to execute "  
          "IPSET_CMD_ADD command. ipset exists? ret=%d set_type=%s table=%s\n",  
          ret, set_type.c_str(), table.c_str());  
        // Not an error condition  
        ret = 0;  
       }  
      }  
      else  
      {  
       printf("ipsetAdd: Failed to set timeout option. "  
         "ret=%d set_type=%s table=%s\n", ret, set_type.c_str(), table.c_str());  
      }  
     }  
     else  
     {  
      printf("ipsetAdd: Failed to parse element. "  
        "ret=%d set_type=%s table=%s\n", ret, set_type.c_str(), table.c_str());  
     }  
    }  
   }  
   else  
   {  
    printf("ipsetAdd: Failed to parse setname. "  
      "ret=%d set_type=%s table=%s\n", ret, set_type.c_str(), table.c_str());  
   }  
   // Finish the ipset session  
   if (ipset_session_fini(session) != 0)  
   {  
    printf("ipsetAdd: Failed to destroy ipset "  
      "session. ret=%d set_type=%s table=%s\n", ret, set_type.c_str(),  
      table.c_str());  
   }  
  } // else of if (session == NULL)  
  s_ipsetMutex.unlock();  
  return ret;  
 }  
 int main()  
 {  
  ipsetAdd("my_ipset_table", "127.0.0.1,62142,127.0.0.1", 600);  
  return 0;  
 }  


To build it:
$ g++ myipset.cpp -std=c++0x  -lipset -o myipset

Create your ipset first:
$ sudo ipset create my_ipset_table hash:ip,port,ip family inet maxelem 600000

Due to the fact that some of the ipset commands need special
capability to call or get valid return (e.g. ipset_type_get & ipset_cmd), you have to run it as root.
$ sudo myipset

To check it:
$ sudo ipset -l

Here is the C version of the same function:
 #include <stdio.h>  
 #include <pthread.h>       
 #include <assert.h>  
 #include <libipset/session.h>      /* ipset_session_* */  
 #include <libipset/data.h>       /* enum ipset_data */  
 #include <libipset/parse.h>       /* ipset_parse_* */  
 #include <libipset/types.h>       /* struct ipset_type */  
 #include <libipset/ui.h>        /* core options, commands */  
 #include <libipset/utils.h>       /* STREQ */  
 // debian-ipset is not thread-safe. We're using  
 // a mutex to serialize the ipset calls.  
 pthread_mutex_t s_ipsetMutex;  
 // We're only adding a command/an element to to the set,  
 // so the restore line no. remains 0  
 #define IPSET_SESSION_LINE_NO 0  
 int  
 ipsetAdd(char *table, char *set_type, uint32_t interval)  
 {  
  int32_t ret = 0;  
  const struct ipset_type *type = NULL;  
  enum ipset_cmd cmd = IPSET_CMD_ADD;  
  struct ipset_session *session;  
  // debian-ipset calls are not thread-safe. We're adding  
  // a mutex to serialize the calls.  
  pthread_mutex_lock(&s_ipsetMutex);  
  ipset_load_types();  
  // Initialize an ipset session by allocating a session structure  
  // and filling out with the initialization data.  
  session = ipset_session_init(printf);  
  if (session == NULL)  
  {  
   printf("ipsetAdd: Cannot initialize ipset session for "  
     "set_type %s. aborting.\n", set_type);  
   ret = 1;  
  }  
  else  
  {  
   // Set session lineno to report parser errors correctly   
   ipset_session_lineno(session, IPSET_SESSION_LINE_NO);  
   // Parse string as a setname.  
   // The value is stored in the data blob of the session.  
   ret = ipset_parse_setname(session, IPSET_SETNAME, table);  
   if (ret == 0)  
   {  
    type = ipset_type_get(session, cmd);  
    if (!type)  
    {  
     printf("ipsetAdd: Failed to get the set type from Kernel "  
       "set_type=%s table=%s sess=%p cmd=%d\n", set_type, table,  
       session, cmd);  
     ret = 1;  
    }  
    else  
    {  
     // Parse string as a (multipart) element according to the settype.  
     // The value is stored in the data blob of the session.  
     ret = ipset_parse_elem(session, (enum ipset_opt)type->last_elem_optional,  
                 set_type);  
     if (ret == 0)  
     {  
      // Put a given kind of data into the data blob and mark the  
      // option kind as already set in the blob.  
      ret = ipset_data_set(ipset_session_data(session), IPSET_OPT_TIMEOUT, &interval);  
      if (!ret)  
      {  
       // Execute a command  
       ret = ipset_cmd(session, cmd, IPSET_SESSION_LINE_NO);  
       if (ret)  
       {  
        printf("ipsetAdd: WARNING: Failed to execute "  
          "IPSET_CMD_ADD command. ipset exists? ret=%d set_type=%s table=%s\n",  
          ret, set_type, table);  
        // Not an error condition  
        ret = 0;  
       }  
      }  
      else  
      {  
       printf("ipsetAdd: Failed to set timeout option. "  
         "ret=%d set_type=%s table=%s\n", ret, set_type, table);  
      }  
     }  
     else  
     {  
      printf("ipsetAdd: Failed to parse element. "  
        "ret=%d set_type=%s table=%s\n", ret, set_type, table);  
     }  
    }  
   }  
   else  
   {  
    printf("ipsetAdd: Failed to parse setname. "  
      "ret=%d set_type=%s table=%s\n", ret, set_type, table);  
   }  
   // Finish the ipset session  
   if (ipset_session_fini(session) != 0)  
   {  
    printf("ipsetAdd: Failed to destroy ipset "  
      "session. ret=%d set_type=%s table=%s\n", ret, set_type,  
      table);  
   }  
  } // else of if (session == NULL)  
  pthread_mutex_unlock(&s_ipsetMutex);  
  return ret;  
 }  

Tuesday, April 15, 2014

Update Firefox on Ubuntu

For some strange reason, I couldn't open and see content of any of my yahoo mail using Firefox. I tried it on Chrome. It was working. So it must be something to do with Firefox + yahoo combination. Since I cannot fix yahoo from its setting (it doesn't even open), I in turn focused on fixing Firefox. Anyway I checked my add-ons and plug-ins and found nothing suspicious. So I decided to update my Firefox. I found the version from Help->About Firefox. The version was 20 and there was NO update button/link despite of all the articles on the net saying so. Next I ran

sudo apt-get update
sudo apt-get --purge --reinstall install firefox

Hoping the system will find the updates in the repositories and update Firefox for me. Nope. Firefox was not updated. So I had to do it manually. Here are the steps:

1. Get a Linux 64-bit copy from here and untar/uncompress it.

~/Downloads$ tar xvfj  firefox-28.0.tar.bz2
tar: Record size = 8 blocks
firefox/
firefox/libsoftokn3.so
firefox/chrome.manifest
firefox/mozilla-xremote-client
firefox/crashreporter.ini
firefox/libnspr4.so
firefox/updater
.
.
.

2. Backup your $HOME/.mozilla directory if you want to be careful.

$ cd; cp .mozilla .mozilla.bak
3. Close all Firefox instances.

4. Backup your firefox directory

$ sudo mv /usr/lib/firefox /usr/lib/firefox.bak
5. Move firefox directory you just uncompressed to /usr/lib

$ sudo mv ~/Downloads/firefox /usr/lib
6. Now give it a try by launching it from the launcher or command line.

$ /usr/bin/firefox &
7. One more step, the firefox.png file seems to be missing from the latest Firefox 28 package. You will see a big red cross if this is not done. So to properly show firefox icon in your launcher.

$ sudo cp /usr/lib/firefox.backup/icons/mozicon128.png \ 
/usr/lib/firefox/icons
8. Try yahoo mail again. It works!

9. Now you can delete all the backups if everything works as expected.

In a fairly good mode, so toss in a bonus tip - to open a file with the default application in command line:

xdg-open /usr/lib/firefox/mozicon128.png