sensors.cpp \
        handlers.cpp \
        utils.cpp \
+       types.cpp \
        asn1/DisplayString.c \
        asn1/PhysAddress.c \
        asn1/IfEntry.c \
 
     {
     VarBind_t * vb = getRequest->variable_bindings.list.array[i];
     Sensors::iterator it;
-    it = sensors.find(OI2String(&vb->name));
+    it = sensors.find(OID(&vb->name));
     if (it == sensors.end())
         {
         SendGetResponseErrorPDU(sock, getRequest,
     {
     VarBind_t * vb = getRequest->variable_bindings.list.array[i];
     Sensors::iterator it;
-    it = sensors.upper_bound(OI2String(&vb->name));
+    it = sensors.upper_bound(OID(&vb->name));
     if (it == sensors.end())
         {
         SendGetResponseErrorPDU(sock, getRequest,
 
 #ifndef __SENSORS_H__
 #define __SENSORS_H__
 
-#include <string>
 #include <map>
 
 #include "stg/users.h"
 #include "asn1/ObjectSyntax.h"
 
 #include "value2os.h"
+#include "types.h"
 
 class Sensor {
     public:
         virtual bool GetValue(ObjectSyntax_t * objectSyntax) const = 0;
 };
 
-typedef std::map<std::string, Sensor *> Sensors;
+typedef std::map<OID, Sensor *> Sensors;
 
 class TableSensor {
     public:
 
 #include "smux.h"
 #include "utils.h"
 
-PLUGIN_CREATOR<SMUX> sac;
+PLUGIN_CREATOR<SMUX> smc;
 
 PLUGIN * GetPlugin()
 {
-return sac.GetPlugin();
+return smc.GetPlugin();
 }
 
 SMUX_SETTINGS::SMUX_SETTINGS()
 PARAM_VALUE pv;
 std::vector<PARAM_VALUE>::const_iterator pvi;
 int p;
-///////////////////////////
+
 pv.param = "Port";
 pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
 if (pvi == s.moduleParams.end())
     return -1;
 
 // Users
-sensors[".1.3.6.1.4.1.38313.1.1.1"] = new TotalUsersSensor(*users);
-sensors[".1.3.6.1.4.1.38313.1.1.2"] = new ConnectedUsersSensor(*users);
-sensors[".1.3.6.1.4.1.38313.1.1.3"] = new AuthorizedUsersSensor(*users);
-sensors[".1.3.6.1.4.1.38313.1.1.4"] = new AlwaysOnlineUsersSensor(*users);
-sensors[".1.3.6.1.4.1.38313.1.1.5"] = new NoCashUsersSensor(*users);
-sensors[".1.3.6.1.4.1.38313.1.1.7"] = new DisabledDetailStatsUsersSensor(*users);
-sensors[".1.3.6.1.4.1.38313.1.1.8"] = new DisabledUsersSensor(*users);
-sensors[".1.3.6.1.4.1.38313.1.1.9"] = new PassiveUsersSensor(*users);
-sensors[".1.3.6.1.4.1.38313.1.1.10"] = new CreditUsersSensor(*users);
-sensors[".1.3.6.1.4.1.38313.1.1.11"] = new FreeMbUsersSensor(*users);
-sensors[".1.3.6.1.4.1.38313.1.1.12"] = new TariffChangeUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.1")] = new TotalUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.2")] = new ConnectedUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.3")] = new AuthorizedUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.4")] = new AlwaysOnlineUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.5")] = new NoCashUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.7")] = new DisabledDetailStatsUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.8")] = new DisabledUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.9")] = new PassiveUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.10")] = new CreditUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.11")] = new FreeMbUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.12")] = new TariffChangeUsersSensor(*users);
 // Tariffs
-sensors[".1.3.6.1.4.1.38313.1.2.1"] = new TotalTariffsSensor(*tariffs);
+sensors[OID(".1.3.6.1.4.1.38313.1.2.1")] = new TotalTariffsSensor(*tariffs);
 
 if (!running)
     {
 
 #include "stg/tariffs.h"
 
 #include "sensors.h"
+#include "types.h"
 
 extern "C" PLUGIN * GetPlugin();
 
 
--- /dev/null
+#include <stdexcept>
+#include <algorithm>
+#include <sstream>
+
+#include "types.h"
+
+bool StringToArcs(const char * str, size_t length, std::vector<unsigned> & arcs)
+{
+unsigned a[1024];
+if (length == 0)
+    return false;
+const char * left = str;
+if (*left == '.')
+    ++left;
+size_t arcPos = 0;
+while ((left - str) < length)
+    {
+    char * pos = NULL;
+    unsigned arc = strtoul(left, &pos, 10);
+    if (pos == left)
+        return false;
+    a[arcPos++] = arc;
+    if (arcPos >= 1024)
+        return false;
+    left = pos + 1;
+    }
+
+std::vector<unsigned> newArcs(a, a + arcPos);
+arcs.swap(newArcs);
+return true;
+}
+
+OID::OID(const std::string & str)
+{
+if (!StringToArcs(str.c_str(), str.length(), arcs))
+    throw std::runtime_error("Invalid oid");
+}
+
+OID::OID(const char * str, size_t length)
+{
+if (!StringToArcs(str, length, arcs))
+    throw std::runtime_error("Invalid oid");
+}
+
+OID::OID(const std::vector<unsigned> & a)
+    : arcs(a)
+{
+}
+
+OID::OID(const unsigned * a, size_t length)
+{
+std::vector<unsigned> newArcs(a, a + length);
+arcs.swap(newArcs);
+}
+
+OID::OID(OBJECT_IDENTIFIER_t * oid)
+{
+unsigned a[1024];
+int count = OBJECT_IDENTIFIER_get_arcs(oid, a, sizeof(a[0]), 1024);
+
+if (count > 1024)
+    throw std::runtime_error("OID is too long");
+
+std::vector<unsigned> newArcs(a, a + count);
+arcs.swap(newArcs);
+}
+
+OID::OID(const OID & rvalue)
+    : arcs(rvalue.arcs)
+{
+}
+
+OID::~OID()
+{
+}
+
+std::string OID::ToString() const
+{
+std::stringstream stream;
+for (size_t i = 0; i < arcs.size(); ++i)
+    stream << "." << arcs[i];
+return stream.str();
+}
+
+void OID::ToOID(OBJECT_IDENTIFIER_t * oid) const
+{
+OBJECT_IDENTIFIER_set_arcs(oid, &arcs.front(), sizeof(unsigned), arcs.size());
+}
+
+OID & OID::operator=(const OID & rvalue)
+{
+arcs = rvalue.arcs;
+return *this;
+}
+
+bool OID::operator==(const OID & rvalue) const
+{
+if (arcs.size() != rvalue.arcs.size())
+    return false;
+for (size_t i = 0; i < arcs.size(); ++i)
+    if (arcs[i] != rvalue.arcs[i])
+        return false;
+return true;
+}
+
+bool OID::operator<(const OID & rvalue) const
+{
+for (size_t i = 0; i < std::min(arcs.size(), rvalue.arcs.size()); ++i)
+    if (arcs[i] > rvalue.arcs[i])
+        return false;
+if (rvalue.arcs.size() < arcs.size())
+    return false;
+return true;
+}
+
+std::ostream & OID::operator<<(std::ostream & stream) const
+{
+for (size_t i = 0; i < arcs.size(); ++i)
+    stream << "." << arcs[i];
+return stream;
+}
 
--- /dev/null
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+#include <string>
+#include <vector>
+#include <istream>
+
+#include "asn1/OBJECT_IDENTIFIER.h"
+
+class OID {
+    public:
+        OID(const std::string & str);
+        OID(const char * str, size_t length);
+        OID(const std::vector<unsigned> & arcs);
+        OID(const unsigned * arcs, size_t length);
+        OID(OBJECT_IDENTIFIER_t * oid);
+        OID(const OID & rvalue);
+        ~OID();
+
+        std::string ToString() const;
+        const std::vector<unsigned> & ToVector() const { return arcs; }
+        void ToOID(OBJECT_IDENTIFIER_t * oid) const;
+
+        OID & operator=(const OID & rvalue);
+        bool operator==(const OID & rvalue) const;
+        bool operator<(const OID & rvalue) const;
+
+        std::ostream & operator<<(std::ostream & stream) const;
+
+    private:
+        std::vector<unsigned> arcs;
+};
+
+#endif
 
 return true;
 }
 
+std::string OI2String(OBJECT_IDENTIFIER_t * oi)
+{
+std::string res;
+
+int arcs[1024];
+int count = OBJECT_IDENTIFIER_get_arcs(oi, arcs, sizeof(arcs[0]), 1024);
+
+if (count > 1024)
+    return "";
+
+for (int i = 0; i < count; ++i)
+    {
+    res += ".";
+    std::string arc;
+    strprintf(&arc, "%d", arcs[i]);
+    res += arc;
+    }
+
+return res;
+}
+
 bool SendOpenPDU(int fd)
 {
 const char * description = "Stg SMUX Plugin";
 return pdus;
 }
 
-std::string OI2String(OBJECT_IDENTIFIER_t * oi)
-{
-std::string res;
-
-int arcs[1024];
-int count = OBJECT_IDENTIFIER_get_arcs(oi, arcs, sizeof(arcs[0]), 1024);
-
-if (count > 1024)
-    return "";
-
-for (int i = 0; i < count; ++i)
-    {
-    res += ".";
-    std::string arc;
-    strprintf(&arc, "%d", arcs[i]);
-    res += arc;
-    }
-
-return res;
-}
-
 int SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse)
 {
 asn_enc_rval_t error;