/* Allow a vserver running on a master connecting to dstport to connect to another vserver running on a master using another dstport */ struct CONNECT_RULE_FROM{ string master; string vserver; string target; // ip0, ip1 or an actual IP. string dstport; string keys[6]; void initkey(){ for (unsigned i=0; i<6; i++) keys[i] = ""; const char *pt = vserver.c_str(); unsigned pos = 0; while (*pt != '\0'){ const char *start = pt; while (*pt != '\0' && *pt != ',') pt++; //printf ("start=%s:%s\n",start,pt); keys[pos++] = string(start,pt-start); if (*pt == ',') pt++; } } CONNECT_RULE_FROM (const char *_master, const char *_vserver, const char *_target, const char *_dstport){ master = _master; vserver = _vserver; target = _target; dstport = _dstport; initkey(); } CONNECT_RULE_FROM (const string &_master, const string &_vserver, const string &_target, const string &_dstport){ master = _master; vserver = _vserver; target = _target; dstport = _dstport; initkey(); } CONNECT_RULE_FROM(){} CONNECT_RULE_FROM (const CONNECT_RULE_FROM &t){ master = t.master; vserver = t.vserver; target = t.target; dstport = t.dstport; for (unsigned i=0; i != 6; i++) keys[i] = t.keys[i]; } CONNECT_RULE_FROM & operator = (const CONNECT_RULE_FROM &t){ master = t.master; vserver = t.vserver; target = t.target; dstport = t.dstport; for (unsigned i=0; i != 6; i++) keys[i] = t.keys[i]; return *this; } int match (const CONNECT_RULE_FROM &t) const { int ret = 0; if (master == t.master && keys[0] == t.keys[0] && target == t.target && dstport == t.dstport){ ret = 1; for (unsigned i=1; i<6; i++){ if (keys[i].size() != 0){ if (keys[i] == t.keys[i]){ ret ++; }else{ ret = 0; break; } } } } return ret; } bool operator < (const CONNECT_RULE_FROM &r) const{ bool ret = false; int cmp = strcmp(master.c_str(),r.master.c_str()); if (cmp < 0){ ret = true; }else if (cmp == 0){ cmp = strcmp(vserver.c_str(),r.vserver.c_str()); if (cmp < 0){ ret = true; }else if (cmp == 0){ cmp = strcmp(target.c_str(),r.target.c_str()); if (cmp < 0){ ret = true; }else if (cmp == 0){ if (dstport < r.dstport) ret = true; } } } return ret; } }; struct CONNECT_RULE_TO{ string master; string vserver; string dstport; time_t end; // This rule is valid until int nbcon; // Number of connection made using this rule time_t lastcon; // Last connection made string last_source; // Latest match of the rules, containing the full request vserver,program,user,group string last_target; // Target IP of the latest match string check; // Protocol checker void reset(){ end = 0; // Forever lastcon = (time_t)0; nbcon = 0; } CONNECT_RULE_TO (const char *_master, const char *_vserver, const char *_dstport){ const char *pt = strchr(_master,':'); if (pt != NULL){ check = string(_master,pt-_master); master = pt+1; }else{ master = _master; } vserver = _vserver; dstport = _dstport; reset(); } CONNECT_RULE_TO (const char *_master, const char *_vserver, const char *_dstport, time_t _end){ reset(); master = _master; vserver = _vserver; dstport = _dstport; end = _end; } CONNECT_RULE_TO(){ reset(); } bool operator == (CONNECT_RULE_TO &r) const { return master == r.master && vserver == r.vserver && dstport == r.dstport; } bool operator != (CONNECT_RULE_TO &r) const { return !(*this == r); } bool operator < (const CONNECT_RULE_TO &r) const{ bool ret = false; int cmp = strcmp(master.c_str(),r.master.c_str()); if (cmp < 0){ ret = true; }else if (cmp == 0){ cmp = strcmp(vserver.c_str(),r.vserver.c_str()); if (cmp < 0){ ret = true; }else if (cmp == 0){ if (dstport < r.dstport) ret = true; } } return ret; } }; struct RULES_TO{ bool logging; vector tos; RULES_TO(){ logging = false; } RULES_TO(const RULES_TO &r){ logging = r.logging; tos = r.tos; } }; /* Find the best rule matching a connection request. Return rules.end() if not found. */ static map::iterator blackhole_findmatch ( const CONNECT_RULE_FROM &tst, map &rules) { int best = 0; debug_printf (D_MATCH,"Match %s %s %s %s\n",tst.master.c_str(),tst.vserver.c_str(),tst.target.c_str(),tst.dstport.c_str()); map::iterator found = rules.end(); CONNECT_RULE_FROM base(tst.master,tst.keys[0],tst.target,tst.dstport); for (map::iterator it=rules.lower_bound(base); it != rules.end(); it++){ int match = it->first.match(tst); debug_printf (D_MATCH,"Test match=%d %s %s %s %s\n",match,it->first.master.c_str(),it->first.vserver.c_str() ,it->first.target.c_str(),it->first.dstport.c_str()); if (match == 0){ if (tst < it->first){ //printf ("\tEnd %s %s %s %s\n",it->first.master.c_str(),it->first.vserver.c_str() // ,it->first.target.c_str(),it->first.dstport.c_str()); break; } }else if (match > best){ best = match; found = it; }else if (match == best && best != 0){ tlmp_error ("Ambiguous rule selection %s <> %s\n",found->first.vserver.c_str(),it->first.vserver.c_str()); found = rules.end(); break; } } return found; }