/* * Used when converting values to be used in a DB query */ int db_mysql_val2str(const db_con_t* _c, const db_val_t* _v, char* _s, int* _len) { int l; char* old_s; if (!_c || !_v || !_s || !_len || !*_len) { LM_ERR("invalid parameter value\n"); return -1; } if (VAL_NULL(_v)) { if (*_len < sizeof("NULL")) { LM_ERR("buffer too small\n"); return -1; } *_len = snprintf(_s, *_len, "NULL"); return 0; } switch(VAL_TYPE(_v)) { case DB_INT: if (db_int2str(VAL_INT(_v), _s, _len) < 0) { LM_ERR("error while converting string to int\n"); return -2; } else { return 0; } break; case DB_BIGINT: if (db_bigint2str(VAL_BIGINT(_v), _s, _len) < 0) { LM_ERR("error while converting bigint to string\n"); return -2; } else { return 0; } break; case DB_BITMAP: if (db_int2str(VAL_BITMAP(_v), _s, _len) < 0) { LM_ERR("error while converting string to int\n"); return -3; } else { return 0; } break; case DB_DOUBLE: if (db_double2str(VAL_DOUBLE(_v), _s, _len) < 0) { LM_ERR("error while converting string to double\n"); return -4; } else { return 0; } break; case DB_STRING: l = strlen(VAL_STRING(_v)); if (*_len < (l * 2 + 3)) { LM_ERR("destination buffer too short\n"); return -5; } else { old_s = _s; *_s++ = '\''; _s += mysql_real_escape_string(CON_CONNECTION(_c), _s, VAL_STRING(_v), l); *_s++ = '\''; *_s = '\0'; /* FIXME */ *_len = _s - old_s; return 0; } break; case DB_STR: if (*_len < (VAL_STR(_v).len * 2 + 3)) { LM_ERR("destination buffer too short\n"); return -6; } else { old_s = _s; *_s++ = '\''; _s += mysql_real_escape_string(CON_CONNECTION(_c), _s, VAL_STR(_v).s, VAL_STR(_v).len); *_s++ = '\''; *_s = '\0'; *_len = _s - old_s; return 0; } break; case DB_DATETIME: if (db_time2str(VAL_TIME(_v), _s, _len) < 0) { LM_ERR("error while converting string to time_t\n"); return -7; } else { return 0; } break; case DB_BLOB: l = VAL_BLOB(_v).len; if (*_len < (l * 2 + 3)) { LM_ERR("destination buffer too short\n"); return -8; } else { old_s = _s; *_s++ = '\''; _s += mysql_real_escape_string(CON_CONNECTION(_c), _s, VAL_STR(_v).s, l); *_s++ = '\''; *_s = '\0'; *_len = _s - old_s; return 0; } break; default: LM_DBG("unknown data type\n"); return -9; } /*return -8; --not reached*/ }
/* * Used when converting result from a query */ int db_postgres_val2str(const db_con_t* _con, const db_val_t* _v, char* _s, int* _len) { int l, ret; int pgret; char *tmp_s; size_t tmp_len; char* old_s; if ((!_v) || (!_s) || (!_len) || (!*_len)) { LM_ERR("invalid parameter value\n"); return -1; } if (VAL_NULL(_v)) { if ( *_len < (l=(int)sizeof("NULL")-1)) { LM_ERR("buffer too short to print NULL\n"); return -1; } memcpy(_s, "NULL", l); *_len = l; return 0; } switch(VAL_TYPE(_v)) { case DB_INT: if (db_int2str(VAL_INT(_v), _s, _len) < 0) { LM_ERR("failed to convert string to int\n"); return -2; } else { return 0; } break; case DB_BIGINT: if (db_bigint2str(VAL_BIGINT(_v), _s, _len) < 0) { LM_ERR("failed to convert string to big int\n"); return -2; } else { return 0; } break; case DB_BITMAP: if (db_int2str(VAL_BITMAP(_v), _s, _len) < 0) { LM_ERR("failed to convert string to int\n"); return -3; } else { return 0; } break; case DB_DOUBLE: if (db_double2str(VAL_DOUBLE(_v), _s, _len) < 0) { LM_ERR("failed to convert string to double\n"); return -3; } else { return 0; } break; case DB_STRING: l = strlen(VAL_STRING(_v)); if (*_len < (l * 2 + 3)) { LM_ERR("destination STRING buffer too short (have %d, need %d)\n", *_len, l * 2 + 3); return -4; } else { old_s = _s; *_s++ = '\''; ret = PQescapeStringConn(CON_CONNECTION(_con), _s, VAL_STRING(_v), l, &pgret); if(pgret!=0) { LM_ERR("PQescapeStringConn failed\n"); return -4; } LM_DBG("PQescapeStringConn: in: %d chars," " out: %d chars\n", l, ret); _s += ret; *_s++ = '\''; *_s = '\0'; /* FIXME */ *_len = _s - old_s; return 0; } break; case DB_STR: l = VAL_STR(_v).len; if (*_len < (l * 2 + 3)) { LM_ERR("destination STR buffer too short (have %d, need %d)\n", *_len, l * 2 + 3); return -5; } else { old_s = _s; *_s++ = '\''; ret = PQescapeStringConn(CON_CONNECTION(_con), _s, VAL_STRING(_v), l, &pgret); if(pgret!=0) { LM_ERR("PQescapeStringConn failed \n"); return -5; } LM_DBG("PQescapeStringConn: in: %d chars, out: %d chars\n", l, ret); _s += ret; *_s++ = '\''; *_s = '\0'; /* FIXME */ *_len = _s - old_s; return 0; } break; case DB_DATETIME: if (db_time2str(VAL_TIME(_v), _s, _len) < 0) { LM_ERR("failed to convert string to time_t\n"); return -6; } else { return 0; } break; case DB_BLOB: l = VAL_BLOB(_v).len; /* this estimation is not always correct, thus we need to check later again */ if (*_len < (l * 2 + 3)) { LM_ERR("destination BLOB buffer too short (have %d, need %d)\n", *_len, l * 2 + 3); return -7; } else { *_s++ = '\''; tmp_s = (char*)PQescapeByteaConn(CON_CONNECTION(_con), (unsigned char*)VAL_STRING(_v), (size_t)l, (size_t*)&tmp_len); if(tmp_s==NULL) { LM_ERR("PQescapeBytea failed\n"); return -7; } if (tmp_len > *_len) { LM_ERR("escaped result too long\n"); return -7; } memcpy(_s, tmp_s, tmp_len); PQfreemem(tmp_s); tmp_len = strlen(_s); *(_s + tmp_len) = '\''; *(_s + tmp_len + 1) = '\0'; *_len = tmp_len + 2; return 0; } break; default: LM_DBG("unknown data type\n"); return -7; } }
/*! * \brief Get all contacts from the database, in partitions if wanted * \see get_all_ucontacts * \param buf target buffer * \param len length of buffer * \param flags contact flags * \param part_idx part index * \param part_max maximal part * \param GAU options * \return 0 on success, positive if buffer size was not sufficient, negative on failure */ static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags, unsigned int part_idx, unsigned int part_max, int options) { struct socket_info *sock; unsigned int dbflags; db1_res_t* res = NULL; db_row_t *row; dlist_t *dom; str now; char now_s[25]; int port, proto; char *p; str addr; str recv; str path; str ruid; str host; unsigned int aorhash; int i; void *cp; int shortage, needed; db_key_t keys1[4]; /* where */ db_val_t vals1[4]; db_op_t ops1[4]; db_key_t keys2[6]; /* select */ int n[2] = {2,6}; /* number of dynamic values used on key1/key2 */ cp = buf; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof(addr.len); /* get the current time in DB format */ now.len = 25; now.s = now_s; if (db_time2str( time(0), now.s, &now.len)!=0) { LM_ERR("failed to print now time\n"); return -1; } aorhash = 0; /* select fields */ keys2[0] = &received_col; keys2[1] = &contact_col; keys2[2] = &sock_col; keys2[3] = &cflags_col; keys2[4] = &path_col; keys2[5] = &ruid_col; /* where fields */ keys1[0] = &expires_col; ops1[0] = OP_GT; vals1[0].type = DB1_STR; vals1[0].nul = 0; vals1[0].val.str_val = now; keys1[1] = &partition_col; ops1[1] = OP_EQ; vals1[1].type = DB1_INT; vals1[1].nul = 0; if(_ul_max_partition>0) vals1[1].val.int_val = part_idx; else vals1[1].val.int_val = 0; if (flags & nat_bflag) { keys1[n[0]] = &keepalive_col; ops1[n[0]] = OP_EQ; vals1[n[0]].type = DB1_INT; vals1[n[0]].nul = 0; vals1[n[0]].val.int_val = 1; n[0]++; } if(options&GAU_OPT_SERVER_ID) { keys1[n[0]] = &srv_id_col; ops1[n[0]] = OP_EQ; vals1[n[0]].type = DB1_INT; vals1[n[0]].nul = 0; vals1[n[0]].val.int_val = server_id; n[0]++; } /* TODO: use part_idx and part_max on keys1 */ for (dom = root; dom!=NULL ; dom=dom->next) { if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) { LM_ERR("sql use_table failed\n"); return -1; } if (ul_dbf.query(ul_dbh, keys1, ops1, vals1, keys2, n[0], n[1], NULL, &res) <0 ) { LM_ERR("query error\n"); return -1; } if( RES_ROW_N(res)==0 ) { ul_dbf.free_result(ul_dbh, res); continue; } for(i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; /* received */ recv.s = (char*)VAL_STRING(ROW_VALUES(row)); if ( VAL_NULL(ROW_VALUES(row)) || recv.s==0 || recv.s[0]==0 ) { recv.s = NULL; recv.len = 0; } else { recv.len = strlen(recv.s); } /* contact */ addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1); if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) { LM_ERR("empty contact -> skipping\n"); continue; } else { addr.len = strlen(addr.s); } /* path */ path.s = (char*)VAL_STRING(ROW_VALUES(row)+4); if (VAL_NULL(ROW_VALUES(row)+4) || path.s==0 || path.s[0]==0){ path.s = NULL; path.len = 0; } else { path.len = strlen(path.s); } /* ruid */ ruid.s = (char*)VAL_STRING(ROW_VALUES(row)+5); if (VAL_NULL(ROW_VALUES(row)+5) || ruid.s==0 || ruid.s[0]==0){ ruid.s = NULL; ruid.len = 0; } else { ruid.len = strlen(ruid.s); } needed = (int)(sizeof(addr.len) + addr.len + sizeof(recv.len) + recv.len + sizeof(sock) + sizeof(dbflags) + sizeof(path.len) + path.len + sizeof(ruid.len) + ruid.len + sizeof(aorhash)); if (len < needed) { shortage += needed ; continue; } /* write contact */ memcpy(cp, &addr.len, sizeof(addr.len)); cp = (char*)cp + sizeof(addr.len); memcpy(cp, addr.s, addr.len); cp = (char*)cp + addr.len; /* write received */ memcpy(cp, &recv.len, sizeof(recv.len)); cp = (char*)cp + sizeof(recv.len); /* copy received only if exist */ if(recv.len){ memcpy(cp, recv.s, recv.len); cp = (char*)cp + recv.len; } /* sock */ p = (char*)VAL_STRING(ROW_VALUES(row) + 2); if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){ sock = 0; } else { if (parse_phostport( p, &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%s>...set to 0\n", p); sock = 0; } else { sock = grep_sock_info( &host, (unsigned short)port, proto); if (sock==0) { LM_DBG("non-local socket <%s>...set to 0\n", p); } } } /* flags */ dbflags = VAL_BITMAP(ROW_VALUES(row) + 3); /* write sock and flags */ memcpy(cp, &sock, sizeof(sock)); cp = (char*)cp + sizeof(sock); memcpy(cp, &dbflags, sizeof(dbflags)); cp = (char*)cp + sizeof(dbflags); /* write path */ memcpy(cp, &path.len, sizeof(path.len)); cp = (char*)cp + sizeof(path.len); /* copy path only if exist */ if(path.len){ memcpy(cp, path.s, path.len); cp = (char*)cp + path.len; } /* write ruid */ memcpy(cp, &ruid.len, sizeof(ruid.len)); cp = (char*)cp + sizeof(ruid.len); /* copy ruid only if exist */ if(ruid.len){ memcpy(cp, ruid.s, ruid.len); cp = (char*)cp + ruid.len; } /* aorhash not used for db-only records, but it is added * (as 0) to match the struct used for mem records */ memcpy(cp, &aorhash, sizeof(aorhash)); cp = (char*)cp + sizeof(aorhash); len -= needed; } /* row cycle */ ul_dbf.free_result(ul_dbh, res); } /* domain cycle */ /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */ if (len >= 0) memset(cp, 0, sizeof(addr.len)); /* Shouldn't happen */ if (shortage > 0 && len > shortage) { abort(); } shortage -= len; return shortage > 0 ? shortage : 0; }
/* * Used when converting values to be used in a DB query */ int db_sqlite_val2str(const db_con_t* _c, const db_val_t* _v, char* _s, int* _len) { int l; if (!_c || !_v || !_s || !_len || !*_len) { LM_ERR("invalid parameter value\n"); return -1; } if (VAL_NULL(_v)) { if (*_len < sizeof("NULL")) { LM_ERR("buffer too small\n"); return -1; } *_len = snprintf(_s, *_len, "NULL"); return 0; } switch(VAL_TYPE(_v)) { case DB_INT: if (db_int2str(VAL_INT(_v), _s, _len) < 0) { LM_ERR("error while converting string to int\n"); return -2; } else { return 0; } break; case DB_BIGINT: if (db_bigint2str(VAL_BIGINT(_v), _s, _len) < 0) { LM_ERR("error while converting bigint to string\n"); return -2; } else { return 0; } break; case DB_BITMAP: if (db_int2str(VAL_BITMAP(_v), _s, _len) < 0) { LM_ERR("error while converting string to int\n"); return -3; } else { return 0; } break; case DB_DOUBLE: if (db_double2str(VAL_DOUBLE(_v), _s, _len) < 0) { LM_ERR("error while converting string to double\n"); return -4; } else { return 0; } break; case DB_STRING: /* TODO check escpaing */ l = strlen(VAL_STRING(_v)); if (*_len < l ) { LM_ERR("Destination buffer too short for string\n"); return -4; } else { LM_DBG("Converted string to string\n"); strncpy(_s, VAL_STRING(_v) , l); _s[l] = 0; *_len = l+1; /* count the 0 also */ return 0; } break; case DB_STR: /* TODO check escpaing */ l = VAL_STR(_v).len; if (*_len < l) { LM_ERR("Destination buffer too short for str\n"); return -5; } else { LM_DBG("Converted str to string\n"); strncpy(_s, VAL_STR(_v).s , l); *_len = l; return 0; } break; break; case DB_DATETIME: if (db_time2str(VAL_TIME(_v), _s, _len) < 0) { LM_ERR("error while converting string to time_t\n"); return -7; } else { return 0; } break; case DB_BLOB: /* TODO check escpaing */ l = VAL_BLOB(_v).len; if (*_len < l) { LM_ERR("Destination buffer too short for blob\n"); return -7; } else { strncpy(_s, VAL_BLOB(_v).s , l); LM_DBG("Converting BLOB [%.*s]\n", l,_s); *_len = l; return 0; } break; default: LM_DBG("unknown data type\n"); return -9; } }
/*! * \brief Get all contacts from the database, in partitions if wanted * \see get_all_ucontacts * \param buf target buffer * \param len length of buffer * \param flags contact flags * \param part_idx part index * \param part_max maximal part * \return 0 on success, positive if buffer size was not sufficient, negative on failure */ static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags, unsigned int part_idx, unsigned int part_max) { static char query_buf[512]; static str query_str; struct socket_info *sock; unsigned int dbflags; db1_res_t* res = NULL; db_row_t *row; dlist_t *dom; char now_s[25]; int now_len; int port, proto; char *p; str addr; str path; str ruid; str host; unsigned int aorhash; int i; void *cp; int shortage, needed; if(ul_dbf.raw_query==NULL) { LM_WARN("DB raw query support is required, but not implemented\n"); return -1; } cp = buf; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof(addr.len); /* get the current time in DB format */ now_len = 25; if (db_time2str( time(0), now_s, &now_len)!=0) { LM_ERR("failed to print now time\n"); return -1; } aorhash = 0; for (dom = root; dom!=NULL ; dom=dom->next) { /* build query */ i = snprintf( query_buf, sizeof(query_buf), "select %.*s, %.*s, %.*s," " %.*s, %.*s, %.*s from %s where %.*s > %.*s and" #ifdef ORACLE_USRLOC " bitand(%.*s, %d) = %d and mod(id, %u) = %u", #else " %.*s & %d = %d and id %% %u = %u", #endif received_col.len, received_col.s, contact_col.len, contact_col.s, sock_col.len, sock_col.s, cflags_col.len, cflags_col.s, path_col.len, path_col.s, ruid_col.len, ruid_col.s, dom->d->name->s, expires_col.len, expires_col.s, now_len, now_s, cflags_col.len, cflags_col.s, flags, flags, part_max, part_idx); if ( i>=sizeof(query_buf) ) { LM_ERR("DB query too long\n"); return -1; } query_str.s = query_buf; query_str.len = i; if ( ul_dbf.raw_query( ul_dbh, &query_str, &res)<0 ) { LM_ERR("raw_query failed\n"); return -1; } if( RES_ROW_N(res)==0 ) { ul_dbf.free_result(ul_dbh, res); continue; } for(i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; /* received */ addr.s = (char*)VAL_STRING(ROW_VALUES(row)); if ( VAL_NULL(ROW_VALUES(row)) || addr.s==0 || addr.s[0]==0 ) { /* contact */ addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1); if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) { LM_ERR("empty contact -> skipping\n"); continue; } } addr.len = strlen(addr.s); /* path */ path.s = (char*)VAL_STRING(ROW_VALUES(row)+4); if (VAL_NULL(ROW_VALUES(row)+4) || path.s==0 || path.s[0]==0){ path.s = NULL; path.len = 0; } else { path.len = strlen(path.s); } /* ruid */ ruid.s = (char*)VAL_STRING(ROW_VALUES(row)+5); if (VAL_NULL(ROW_VALUES(row)+5) || ruid.s==0 || ruid.s[0]==0){ ruid.s = NULL; ruid.len = 0; } else { ruid.len = strlen(ruid.s); } needed = (int)(sizeof(addr.len) + addr.len + sizeof(sock) + sizeof(dbflags) + sizeof(path.len) + path.len + sizeof(ruid.len) + ruid.len + sizeof(aorhash)); if (len < needed) { shortage += needed ; continue; } /* write received/contact */ memcpy(cp, &addr.len, sizeof(addr.len)); cp = (char*)cp + sizeof(addr.len); memcpy(cp, addr.s, addr.len); cp = (char*)cp + addr.len; /* sock */ p = (char*)VAL_STRING(ROW_VALUES(row) + 2); if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){ sock = 0; } else { if (parse_phostport( p, &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%s>...set to 0\n", p); sock = 0; } else { sock = grep_sock_info( &host, (unsigned short)port, proto); if (sock==0) { LM_DBG("non-local socket <%s>...set to 0\n", p); } } } /* flags */ dbflags = VAL_BITMAP(ROW_VALUES(row) + 3); /* write sock and flags */ memcpy(cp, &sock, sizeof(sock)); cp = (char*)cp + sizeof(sock); memcpy(cp, &dbflags, sizeof(dbflags)); cp = (char*)cp + sizeof(dbflags); /* write path */ memcpy(cp, &path.len, sizeof(path.len)); cp = (char*)cp + sizeof(path.len); /* copy path only if exist */ if(path.len){ memcpy(cp, path.s, path.len); cp = (char*)cp + path.len; } /* write ruid */ memcpy(cp, &ruid.len, sizeof(ruid.len)); cp = (char*)cp + sizeof(ruid.len); /* copy ruid only if exist */ if(ruid.len){ memcpy(cp, ruid.s, ruid.len); cp = (char*)cp + ruid.len; } /* aorhash not used for db-only records, but it is added * (as 0) to match the struct used for mem records */ memcpy(cp, &aorhash, sizeof(aorhash)); cp = (char*)cp + sizeof(aorhash); len -= needed; } /* row cycle */ ul_dbf.free_result(ul_dbh, res); } /* domain cycle */ /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */ if (len >= 0) memset(cp, 0, sizeof(addr.len)); /* Shouldn't happen */ if (shortage > 0 && len > shortage) { abort(); } shortage -= len; return shortage > 0 ? shortage : 0; }
static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags, unsigned int part_idx, unsigned int part_max) { static char query_buf[512]; static str query_str; struct socket_info *sock; unsigned int dbflags; db_res_t* res = NULL; db_row_t *row; dlist_t *dom; char *p, *p1; char now_s[25]; int now_len; int port, proto, p_len, p1_len; str host; int i; void *cp; int shortage, needed; cp = buf; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof(p_len); /* get the current time in DB format */ now_len = 25; if (db_time2str( time(0), now_s, &now_len)!=0) { LM_ERR("failed to print now time\n"); return -1; } for (dom = root; dom!=NULL ; dom=dom->next) { /* build query */ i = snprintf( query_buf, sizeof(query_buf), "select %.*s, %.*s, %.*s," #ifdef ORACLE_USRLOC " %.*s, %.*s from %s where %.*s > %.*s and " "bitand(%.*s, %d) = %d and mod(id, %u) = %u", #else " %.*s, %.*s from %s where %.*s > %.*s and %.*s & %d = %d and " "id %% %u = %u", #endif received_col.len, received_col.s, contact_col.len, contact_col.s, sock_col.len, sock_col.s, cflags_col.len, cflags_col.s, path_col.len, path_col.s, dom->d->name->s, expires_col.len, expires_col.s, now_len, now_s, cflags_col.len, cflags_col.s, flags, flags, part_max, part_idx); if ( i>=sizeof(query_buf) ) { LM_ERR("DB query too long\n"); return -1; } query_str.s = query_buf; query_str.len = i; if ( ul_dbf.raw_query( ul_dbh, &query_str, &res)<0 ) { LM_ERR("raw_query failed\n"); return -1; } if( RES_ROW_N(res)==0 ) { ul_dbf.free_result(ul_dbh, res); continue; } for(i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; /* received */ p = (char*)VAL_STRING(ROW_VALUES(row)); if ( VAL_NULL(ROW_VALUES(row)) || p==0 || p[0]==0 ) { /* contact */ p = (char*)VAL_STRING(ROW_VALUES(row)+1); if (VAL_NULL(ROW_VALUES(row)+1) || p==0 || p[0]==0) { LM_ERR("empty contact -> skipping\n"); continue; } } p_len = strlen(p); /* path */ p1 = (char*)VAL_STRING(ROW_VALUES(row)+4); if (VAL_NULL(ROW_VALUES(row)+4) || p1==0 || p1[0]==0){ p1 = NULL; p1_len = 0; } else { p1_len = strlen(p1); } needed = (int)(sizeof(p_len)+p_len+sizeof(sock)+sizeof(dbflags)+ sizeof(p1_len)+p1_len); if (len < needed) { shortage += needed ; continue; } /* write received/contact */ memcpy(cp, &p_len, sizeof(p_len)); cp = (char*)cp + sizeof(p_len); memcpy(cp, p, p_len); cp = (char*)cp + p_len; /* sock */ p = (char*)VAL_STRING(ROW_VALUES(row) + 2); if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){ sock = 0; } else { if (parse_phostport( p, strlen(p), &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%s>...ignoring\n", p); sock = 0; } else { sock = grep_sock_info( &host, (unsigned short)port, proto); if (sock==0) { LM_DBG("non-local socket <%s>...ignoring\n", p); } } } /* flags */ dbflags = VAL_BITMAP(ROW_VALUES(row) + 3); /* write sock and flags */ memcpy(cp, &sock, sizeof(sock)); cp = (char*)cp + sizeof(sock); memcpy(cp, &dbflags, sizeof(dbflags)); cp = (char*)cp + sizeof(dbflags); /* write path */ memcpy(cp, &p1_len, sizeof(p1_len)); cp = (char*)cp + sizeof(p1_len); memcpy(cp, p1, p1_len); cp = (char*)cp + p1_len; len -= needed; } /* row cycle */ ul_dbf.free_result(ul_dbh, res); } /* domain cycle */ /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */ if (len >= 0) memset(cp, 0, sizeof(p_len)); /* Shouldn't happen */ if (shortage > 0 && len > shortage) { abort(); } shortage -= len; return shortage > 0 ? shortage : 0; }
static int get_all_db_ucontacts(void *buf, int len, unsigned int flags, unsigned int part_idx, unsigned int part_max) { static char query_buf[512]; static str query_str; static struct sip_uri puri; struct socket_info *sock; struct proxy_l next_hop; db_res_t *res = NULL; db_row_t *row; db_val_t *val; dlist_t *dom; str uri, host, flag_list; int i, no_rows = 10; int now_len; char now_s[25]; char *p, *p1; int port, proto, p_len, p1_len; unsigned int dbflags; int needed; int shortage = 0; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof p_len; /* get the current time in DB format */ now_len = 25; if (db_time2str(time(NULL), now_s, &now_len) != 0) { LM_ERR("failed to print now time\n"); return -1; } LM_DBG("buf: %p. flags: %d\n", buf, flags); /* for each table */ for (dom = root; dom; dom = dom->next) { if (db_check_table_version(&ul_dbf, ul_dbh, dom->d->name, UL_TABLE_VERSION)) goto error; /* read the destinations */ if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) { LM_ERR("cannot select table \"%.*s\"\n", dom->d->name->len, dom->d->name->s); goto error; } i = snprintf(query_buf, sizeof query_buf, "select %.*s, %.*s, %.*s," #ifdef ORACLE_USRLOC " %.*s, %.*s from %s where %.*s > %.*s and mod(id, %u) = %u", #else " %.*s, %.*s from %s where %.*s > %.*s and id %% %u = %u", #endif received_col.len, received_col.s, contact_col.len, contact_col.s, sock_col.len, sock_col.s, cflags_col.len, cflags_col.s, path_col.len, path_col.s, dom->d->name->s, expires_col.len, expires_col.s, now_len, now_s, part_max, part_idx); LM_DBG("query: %.*s\n", (int)(sizeof query_buf), query_buf); if (i >= sizeof query_buf) { LM_ERR("DB query too long\n"); goto error; } query_str.s = query_buf; query_str.len = i; if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) { if (ul_dbf.raw_query(ul_dbh, &query_str, 0) < 0) { LM_ERR("raw_query failed\n"); goto error; } no_rows = estimate_available_rows(20+128+20+128+64, 5); if (no_rows == 0) no_rows = 10; LM_DBG("fetching %d rows\n", no_rows); if (ul_dbf.fetch_result(ul_dbh, &res, no_rows) < 0) { LM_ERR("Error fetching rows\n"); goto error; } } else if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) { LM_ERR("raw_query failed\n"); goto error; } do { for (i = 0; i < RES_ROW_N(res); i++) { row = RES_ROWS(res) + i; val = ROW_VALUES(row) + 3; /* cflags */ flag_list.s = (char *)VAL_STRING(val); flag_list.len = strlen(flag_list.s); LM_DBG("contact cflags: '%.*s'\n", flag_list.len, flag_list.s); /* contact is not flagged at all */ if (flags && (val->nul || !flag_list.s)) continue; dbflags = flag_list_to_bitmask(&flag_list, FLAG_TYPE_BRANCH, FLAG_DELIM); LM_DBG("masks: param: %d --- %d :db\n", flags, dbflags); /* check if contact flags match the given bitmask */ if ((dbflags & flags) != flags) continue; /* received */ p = (char*)VAL_STRING(ROW_VALUES(row)); if (VAL_NULL(ROW_VALUES(row)) || !p || !p[0]) { /* contact */ p = (char*)VAL_STRING(ROW_VALUES(row) + 1); if (VAL_NULL(ROW_VALUES(row) + 1) || !p || *p == '\0') { LM_ERR("empty contact -> skipping\n"); continue; } } p_len = strlen(p); /* path */ p1 = (char*)VAL_STRING(ROW_VALUES(row) + 4); if (VAL_NULL(ROW_VALUES(row) + 4) || !p1 || *p1 == '\0') { p1 = NULL; p1_len = 0; } else p1_len = strlen(p1); needed = (int)(p_len + sizeof p_len + p1_len + sizeof p1_len + sizeof sock + sizeof dbflags + sizeof next_hop); LM_DBG("len: %d, needed: %d\n", len, needed); if (len < needed) { shortage += needed; continue; } /* determine and parse the URI of this contact's next hop */ if (p1_len > 0) { /* send to first URI in path */ host.s = p1; host.len = p1_len; if (get_path_dst_uri(&host, &uri) < 0) { LM_ERR("failed to get dst_uri for Path\n"); continue; } if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse path URI of next hop: '%*.s'\n", p1_len, p1); return -1; } } else { if (parse_uri(p, p_len, &puri) < 0) { LM_ERR("failed to parse contact of next hop: '%*.s'\n", p_len, p); return -1; } } /* write received/contact */ memcpy(buf, &p_len, sizeof p_len); buf += sizeof p_len; memcpy(buf, p, p_len); buf += p_len; /* write path */ memcpy(buf, &p1_len, sizeof p1_len); buf += sizeof p1_len; memcpy(buf, p1, p1_len); buf += p1_len; /* sock */ p = (char*)VAL_STRING(ROW_VALUES(row) + 2); if (VAL_NULL(ROW_VALUES(row)+2) || !p || *p == '\0') { sock = NULL; } else { if (parse_phostport(p, strlen(p), &host.s, &host.len, &port, &proto) != 0) { LM_ERR("bad socket <%s>...ignoring\n", p); sock = NULL; } else { sock = grep_sock_info(&host, (unsigned short)port, proto); if (!sock) LM_DBG("non-local socket <%s>...ignoring\n", p); } } /* write sock and flags */ memcpy(buf, &sock, sizeof sock); buf += sizeof sock; memcpy(buf, &dbflags, sizeof dbflags); buf += sizeof dbflags; memset(&next_hop, 0, sizeof next_hop); next_hop.port = puri.port_no; next_hop.proto = puri.proto; next_hop.name = puri.host; /* write the next hop */ memcpy(buf, &next_hop, sizeof next_hop); buf += sizeof next_hop; len -= needed; } if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) { if (ul_dbf.fetch_result(ul_dbh, &res, no_rows) < 0) { LM_ERR("fetching rows (1)\n"); goto error; } } else break; } while (RES_ROW_N(res) > 0); ul_dbf.free_result(ul_dbh, res); } /* len < 0 is possible, if size of the buffer < sizeof c->c.len */ if (len >= 0) memset(buf, 0, sizeof p_len); /* Shouldn't happen */ if (shortage > 0 && len > shortage) abort(); shortage -= len; return shortage > 0 ? shortage : 0; error: if (res) ul_dbf.free_result(ul_dbh, res); return -1; }