1.1 --- a/opensips/modules/lcr/lcr_mod.c Wed Feb 10 21:14:04 2010 +0100 1.2 +++ b/opensips/modules/lcr/lcr_mod.c Wed Feb 10 21:21:24 2010 +0100 1.3 @@ -114,9 +114,18 @@ 1.4 1.5 #define PRIORITY_COL "priority" 1.6 1.7 +#define USER_COL "user" 1.8 + 1.9 +#define REALM_COL "realm" 1.10 + 1.11 +#define PASSWD_COL "passwd" 1.12 + 1.13 #define MAX_NO_OF_GWS 32 1.14 #define MAX_NO_OF_LCRS 256 1.15 #define MAX_PREFIX_LEN 256 1.16 +#define MAX_USER_LEN 64 1.17 +#define MAX_REALM_LEN 64 1.18 +#define MAX_PASSWD_LEN 64 1.19 #define MAX_TAG_LEN 16 1.20 #define MAX_FROM_URI_LEN 256 1.21 1.22 @@ -141,6 +150,12 @@ 1.23 char tag[MAX_TAG_LEN + 1]; 1.24 unsigned short tag_len; 1.25 unsigned int flags; 1.26 + char user[MAX_USER_LEN]; 1.27 + unsigned short user_len; 1.28 + char realm[MAX_REALM_LEN]; 1.29 + unsigned short realm_len; 1.30 + char passwd[MAX_PASSWD_LEN]; 1.31 + unsigned short passwd_len; 1.32 }; 1.33 1.34 struct lcr_info { 1.35 @@ -196,6 +211,9 @@ 1.36 static str prefix_col = str_init(PREFIX_COL); 1.37 static str from_uri_col = str_init(FROM_URI_COL); 1.38 static str priority_col = str_init(PRIORITY_COL); 1.39 +static str user_col = str_init(USER_COL); 1.40 +static str realm_col = str_init(REALM_COL); 1.41 +static str passwd_col = str_init(PASSWD_COL); 1.42 1.43 /* timer */ 1.44 int fr_inv_timer = DEF_FR_INV_TIMER; 1.45 @@ -208,6 +226,9 @@ 1.46 static char *contact_avp_param = NULL; 1.47 static char *rpid_avp_param = NULL; 1.48 static char *flags_avp_param = NULL; 1.49 +static char *user_avp_param = NULL; 1.50 +static char *realm_avp_param = NULL; 1.51 +static char *passwd_avp_param = NULL; 1.52 1.53 /* prefix mode */ 1.54 int prefix_mode_param = DEF_PREFIX_MODE; 1.55 @@ -239,6 +260,12 @@ 1.56 static int_str rpid_avp; 1.57 static int flags_avp_type; 1.58 static int_str flags_avp; 1.59 +static int user_avp_type; 1.60 +static int_str user_avp; 1.61 +static int realm_avp_type; 1.62 +static int_str realm_avp; 1.63 +static int passwd_avp_type; 1.64 +static int_str passwd_avp; 1.65 1.66 struct gw_info **gws; /* Pointer to current gw table pointer */ 1.67 struct gw_info *gws_1; /* Pointer to gw table 1 */ 1.68 @@ -327,6 +354,12 @@ 1.69 {"fr_inv_timer", INT_PARAM, &fr_inv_timer }, 1.70 {"fr_inv_timer_next", INT_PARAM, &fr_inv_timer_next }, 1.71 {"prefix_mode", INT_PARAM, &prefix_mode_param }, 1.72 + {"user_column", STR_PARAM, &user_col.s }, 1.73 + {"realm_column", STR_PARAM, &realm_col.s }, 1.74 + {"passwd_column", STR_PARAM, &passwd_col.s }, 1.75 + {"auth_username_avp", STR_PARAM, &user_avp_param }, 1.76 + {"auth_realm_avp", STR_PARAM, &realm_avp_param }, 1.77 + {"auth_password_avp", STR_PARAM, &passwd_avp_param }, 1.78 {0, 0, 0} 1.79 }; 1.80 1.81 @@ -438,6 +471,9 @@ 1.82 prefix_col.len = strlen(prefix_col.s); 1.83 from_uri_col.len = strlen(from_uri_col.s); 1.84 priority_col.len = strlen(priority_col.s); 1.85 + user_col.len = strlen(user_col.s); 1.86 + realm_col.len = strlen(realm_col.s); 1.87 + passwd_col.len = strlen(passwd_col.s); 1.88 1.89 /* Bind database */ 1.90 if (lcr_db_bind(&db_url)) { 1.91 @@ -563,6 +599,60 @@ 1.92 return -1; 1.93 } 1.94 1.95 + if (user_avp_param && *user_avp_param) { 1.96 + s.s = user_avp_param; s.len = strlen(s.s); 1.97 + if (pv_parse_spec(&s, &avp_spec)==0 1.98 + || avp_spec.type!=PVT_AVP) { 1.99 + LM_ERR("Malformed or non AVP definition <%s>\n", user_avp_param); 1.100 + return -1; 1.101 + } 1.102 + 1.103 + if(pv_get_avp_name(0, &(avp_spec.pvp), &user_avp, &avp_flags)!=0) { 1.104 + LM_ERR("Invalid AVP definition <%s>\n", user_avp_param); 1.105 + return -1; 1.106 + } 1.107 + user_avp_type = avp_flags; 1.108 + } else { 1.109 + LM_ERR("AVP user_avp has not been defined\n"); 1.110 + return -1; 1.111 + } 1.112 + 1.113 + if (realm_avp_param && *realm_avp_param) { 1.114 + s.s = realm_avp_param; s.len = strlen(s.s); 1.115 + if (pv_parse_spec(&s, &avp_spec)==0 1.116 + || avp_spec.type!=PVT_AVP) { 1.117 + LM_ERR("Malformed or non AVP definition <%s>\n", realm_avp_param); 1.118 + return -1; 1.119 + } 1.120 + 1.121 + if(pv_get_avp_name(0, &(avp_spec.pvp), &realm_avp, &avp_flags)!=0) { 1.122 + LM_ERR("Invalid AVP definition <%s>\n", realm_avp_param); 1.123 + return -1; 1.124 + } 1.125 + realm_avp_type = avp_flags; 1.126 + } else { 1.127 + LM_ERR("AVP realm_avp has not been defined\n"); 1.128 + return -1; 1.129 + } 1.130 + 1.131 + if (passwd_avp_param && *passwd_avp_param) { 1.132 + s.s = passwd_avp_param; s.len = strlen(s.s); 1.133 + if (pv_parse_spec(&s, &avp_spec)==0 1.134 + || avp_spec.type!=PVT_AVP) { 1.135 + LM_ERR("Malformed or non AVP definition <%s>\n", passwd_avp_param); 1.136 + return -1; 1.137 + } 1.138 + 1.139 + if(pv_get_avp_name(0, &(avp_spec.pvp), &passwd_avp, &avp_flags)!=0) { 1.140 + LM_ERR("Invalid AVP definition <%s>\n", passwd_avp_param); 1.141 + return -1; 1.142 + } 1.143 + passwd_avp_type = avp_flags; 1.144 + } else { 1.145 + LM_ERR("AVP passwd_avp has not been defined\n"); 1.146 + return -1; 1.147 + } 1.148 + 1.149 /* Check table version */ 1.150 db_con_t* dbh; 1.151 if (lcr_dbf.init==0){ 1.152 @@ -801,16 +891,17 @@ 1.153 int reload_gws(void) 1.154 { 1.155 unsigned int i, port, strip, tag_len, prefix_len, from_uri_len, 1.156 - grp_id, priority; 1.157 + user_len, realm_len, passwd_len, grp_id, priority; 1.158 struct in_addr ip_addr; 1.159 unsigned int flags; 1.160 uri_type scheme; 1.161 uri_transport transport; 1.162 db_con_t* dbh; 1.163 char *tag, *prefix, *from_uri; 1.164 + char *user, *realm, *passwd; 1.165 db_res_t* res = NULL; 1.166 db_row_t* row; 1.167 - db_key_t gw_cols[8]; 1.168 + db_key_t gw_cols[11]; 1.169 db_key_t lcr_cols[4]; 1.170 1.171 gw_cols[0] = &ip_addr_col; 1.172 @@ -823,6 +914,9 @@ 1.173 in the two tables? (ge vw lcr) */ 1.174 gw_cols[6] = &grp_id_col; 1.175 gw_cols[7] = &flags_col; 1.176 + gw_cols[8] = &user_col; 1.177 + gw_cols[9] = &realm_col; 1.178 + gw_cols[10] = &passwd_col; 1.179 1.180 lcr_cols[0] = &prefix_col; 1.181 lcr_cols[1] = &from_uri_col; 1.182 @@ -846,7 +940,7 @@ 1.183 return -1; 1.184 } 1.185 1.186 - if (lcr_dbf.query(dbh, NULL, 0, NULL, gw_cols, 0, 8, 0, &res) < 0) { 1.187 + if (lcr_dbf.query(dbh, NULL, 0, NULL, gw_cols, 0, 11, 0, &res) < 0) { 1.188 LM_ERR("Failed to query gw data\n"); 1.189 lcr_dbf.close(dbh); 1.190 return -1; 1.191 @@ -938,6 +1032,45 @@ 1.192 lcr_dbf.close(dbh); 1.193 return -1; 1.194 } 1.195 + if (VAL_NULL(ROW_VALUES(row) + 8) == 1) { 1.196 + user_len = 0; 1.197 + user = (char *)0; 1.198 + } else { 1.199 + user = (char *)VAL_STRING(ROW_VALUES(row) + 8); 1.200 + user_len = strlen(user); 1.201 + if (user_len > MAX_USER_LEN) { 1.202 + LM_ERR("Too long gw user <%u>\n", user_len); 1.203 + lcr_dbf.free_result(dbh, res); 1.204 + lcr_dbf.close(dbh); 1.205 + return -1; 1.206 + } 1.207 + } 1.208 + if (VAL_NULL(ROW_VALUES(row) + 9) == 1) { 1.209 + realm_len = 0; 1.210 + realm = (char *)0; 1.211 + } else { 1.212 + realm = (char *)VAL_STRING(ROW_VALUES(row) + 9); 1.213 + realm_len = strlen(realm); 1.214 + if (realm_len > MAX_REALM_LEN) { 1.215 + LM_ERR("Too long gw realm <%u>\n", realm_len); 1.216 + lcr_dbf.free_result(dbh, res); 1.217 + lcr_dbf.close(dbh); 1.218 + return -1; 1.219 + } 1.220 + } 1.221 + if (VAL_NULL(ROW_VALUES(row) + 10) == 1) { 1.222 + passwd_len = 0; 1.223 + passwd = (char *)0; 1.224 + } else { 1.225 + passwd = (char *)VAL_STRING(ROW_VALUES(row) + 10); 1.226 + passwd_len = strlen(passwd); 1.227 + if (passwd_len > MAX_PASSWD_LEN) { 1.228 + LM_ERR("Too long gw passwd <%u>\n", passwd_len); 1.229 + lcr_dbf.free_result(dbh, res); 1.230 + lcr_dbf.close(dbh); 1.231 + return -1; 1.232 + } 1.233 + } 1.234 if (*gws == gws_1) { 1.235 gws_2[i].ip_addr = (unsigned int)ip_addr.s_addr; 1.236 gws_2[i].port = port; 1.237 @@ -949,6 +1082,15 @@ 1.238 gws_2[i].tag_len = tag_len; 1.239 if (tag_len) 1.240 memcpy(&(gws_2[i].tag[0]), tag, tag_len); 1.241 + gws_2[i].user_len = user_len; 1.242 + if (user_len) 1.243 + memcpy(&(gws_2[i].user[0]), user, user_len); 1.244 + gws_2[i].realm_len = realm_len; 1.245 + if (realm_len) 1.246 + memcpy(&(gws_2[i].realm[0]), realm, realm_len); 1.247 + gws_2[i].passwd_len = passwd_len; 1.248 + if (passwd_len) 1.249 + memcpy(&(gws_2[i].passwd[0]), passwd, passwd_len); 1.250 } else { 1.251 gws_1[i].ip_addr = (unsigned int)ip_addr.s_addr; 1.252 gws_1[i].port = port; 1.253 @@ -960,6 +1102,15 @@ 1.254 gws_1[i].tag_len = tag_len; 1.255 if (tag_len) 1.256 memcpy(&(gws_1[i].tag[0]), tag, tag_len); 1.257 + gws_1[i].user_len = user_len; 1.258 + if (user_len) 1.259 + memcpy(&(gws_1[i].user[0]), user, user_len); 1.260 + gws_1[i].realm_len = realm_len; 1.261 + if (realm_len) 1.262 + memcpy(&(gws_1[i].realm[0]), realm, realm_len); 1.263 + gws_1[i].passwd_len = passwd_len; 1.264 + if (passwd_len) 1.265 + memcpy(&(gws_1[i].passwd[0]), passwd, passwd_len); 1.266 } 1.267 } 1.268 1.269 @@ -1141,6 +1292,21 @@ 1.270 attr = add_mi_attr(node, MI_DUP_VALUE, "FLAGS", 5, p, len); 1.271 if(attr == NULL) 1.272 return -1; 1.273 + 1.274 + attr = add_mi_attr(node, MI_DUP_VALUE, "USER", 6, 1.275 + (*gws)[i].user, (*gws)[i].user_len ); 1.276 + if(attr == NULL) 1.277 + return -1; 1.278 + 1.279 + attr = add_mi_attr(node, MI_DUP_VALUE, "REALM", 6, 1.280 + (*gws)[i].realm, (*gws)[i].realm_len ); 1.281 + if(attr == NULL) 1.282 + return -1; 1.283 + 1.284 + attr = add_mi_attr(node, MI_DUP_VALUE, "PASSWD", 6, 1.285 + (*gws)[i].passwd, (*gws)[i].passwd_len ); 1.286 + if(attr == NULL) 1.287 + return -1; 1.288 } 1.289 1.290 for (i = 0; i < MAX_NO_OF_LCRS; i++) { 1.291 @@ -1184,6 +1350,9 @@ 1.292 char ruri[MAX_URI_SIZE]; 1.293 unsigned int i, j, k, index, addr, port, strip, gw_index, 1.294 duplicated_gw, flags, have_rpid_avp; 1.295 + char *user; 1.296 + char *realm; 1.297 + char *passwd; 1.298 uri_type scheme; 1.299 uri_transport transport; 1.300 struct ip_addr address; 1.301 @@ -1407,6 +1576,9 @@ 1.302 transport = (*gws)[index].transport; 1.303 flags = (*gws)[index].flags; 1.304 strip = (*gws)[index].strip; 1.305 + user = (*gws)[index].user; 1.306 + realm = (*gws)[index].realm; 1.307 + passwd = (*gws)[index].passwd; 1.308 if (strip > ruri_user.len) { 1.309 LM_ERR("Strip count of gw is too large <%u>\n", strip); 1.310 goto skip; 1.311 @@ -1476,6 +1648,25 @@ 1.312 val.s = value; 1.313 add_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp, val); 1.314 LM_DBG("Added gw_uri_avp <%.*s>\n", value.len, value.s); 1.315 + 1.316 + value.s = user; 1.317 + value.len = strlen(value.s); 1.318 + val.s = value; 1.319 + add_avp(user_avp_type|AVP_VAL_STR, user_avp, val); 1.320 + LM_DBG("Added user_avp <%.*s>\n", value.len, value.s); 1.321 + 1.322 + value.s = realm; 1.323 + value.len = strlen(value.s); 1.324 + val.s = value; 1.325 + add_avp(realm_avp_type|AVP_VAL_STR, realm_avp, val); 1.326 + LM_DBG("Added realm_avp <%.*s>\n", value.len, value.s); 1.327 + 1.328 + value.s = passwd; 1.329 + value.len = strlen(value.s); 1.330 + val.s = value; 1.331 + add_avp(passwd_avp_type|AVP_VAL_STR, passwd_avp, val); 1.332 + LM_DBG("Added passwd_avp <%.*s>\n", value.len, value.s); 1.333 + 1.334 skip: 1.335 continue; 1.336 } 1.337 @@ -1558,7 +1749,8 @@ 1.338 static int next_gw(struct sip_msg* _m, char* _s1, char* _s2) 1.339 { 1.340 int_str gw_uri_val, ruri_user_val, val; 1.341 - struct usr_avp *gu_avp, *ru_avp; 1.342 + int_str user_val, realm_val, passwd_val; 1.343 + struct usr_avp *gu_avp, *ru_avp, *usr_avp, *rlm_avp, *pwd_avp; 1.344 int rval; 1.345 str new_ruri; 1.346 char *at, *at_char, *strip_char, *endptr; 1.347 @@ -1575,6 +1767,35 @@ 1.348 gw_uri_val.s.len = gw_uri_val.s.len - (at - gw_uri_val.s.s); 1.349 gw_uri_val.s.s = at; 1.350 1.351 + /* Save gateway AVPs for use in script */ 1.352 + usr_avp = search_first_avp(user_avp_type, user_avp, &user_val, 0); 1.353 + rlm_avp = search_first_avp(realm_avp_type, realm_avp, &realm_val, 0); 1.354 + pwd_avp = search_first_avp(passwd_avp_type, passwd_avp, &passwd_val, 0); 1.355 + if (!usr_avp) { 1.356 + LM_DBG("User AVP no set\n"); 1.357 + return -1; 1.358 + } 1.359 + else { 1.360 + add_avp(user_avp_type|AVP_VAL_STR, user_avp, user_val); 1.361 + LM_DBG("Added user_avp <%.*s>\n", user_val.s.len, user_val.s.s); 1.362 + } 1.363 + if (!rlm_avp) { 1.364 + LM_DBG("Realm AVP no set\n"); 1.365 + return -1; 1.366 + } 1.367 + else { 1.368 + add_avp(realm_avp_type|AVP_VAL_STR, realm_avp, realm_val); 1.369 + LM_DBG("Added realm_avp <%.*s>\n", realm_val.s.len, realm_val.s.s); 1.370 + } 1.371 + if (!pwd_avp) { 1.372 + LM_DBG("Passwd AVP no set\n"); 1.373 + return -1; 1.374 + } 1.375 + else { 1.376 + add_avp(passwd_avp_type|AVP_VAL_STR, passwd_avp, passwd_val); 1.377 + LM_DBG("Added passwd_avp <%.*s>\n", passwd_val.s.len, passwd_val.s.s); 1.378 + } 1.379 + 1.380 /* Create new Request-URI taking URI user from ruri_user AVP 1.381 and other parts of from gateway URI AVP. */ 1.382 ru_avp = search_first_avp(ruri_user_avp_type, ruri_user_avp,