Changeset 356:e203fc0c95e3 in freeDiameter for extensions/app_radgw/rgw_msg.c
- Timestamp:
- Jul 1, 2010, 3:47:34 PM (13 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/app_radgw/rgw_msg.c
r278 r356 137 137 } 138 138 139 static struct dict_object * cache_sess_id = NULL;140 static struct dict_object * cache_dest_host = NULL;141 static struct dict_object * cache_dest_realm = NULL;142 139 static struct dict_object * cache_orig_host = NULL; 143 140 static struct dict_object * cache_orig_realm = NULL; … … 146 143 { 147 144 TRACE_ENTRY(); 148 CHECK_FCT( fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &cache_sess_id, ENOENT) );149 CHECK_FCT( fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &cache_dest_host, ENOENT) );150 CHECK_FCT( fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &cache_dest_realm, ENOENT) );151 145 CHECK_FCT( fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &cache_orig_host, ENOENT) ); 152 146 CHECK_FCT( fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm", &cache_orig_realm, ENOENT) ); … … 154 148 } 155 149 156 /* Create a msg with origin-host & realm, and session-id, and a session object from a RADIUS request message*/157 int rgw_msg_create_base(struct rgw_ radius_msg_meta * msg, struct rgw_client * cli, struct session ** session, struct msg ** diam)150 /* Create a new Diameter msg with origin-host & realm */ 151 int rgw_msg_create_base(struct rgw_client * cli, struct msg ** diam) 158 152 { 159 int idx, i;160 const char * prefix = "Diameter/";161 size_t pref_len;162 char * dh = NULL;163 size_t dh_len = 0;164 char * dr = NULL;165 size_t dr_len = 0;166 char * si = NULL;167 size_t si_len = 0;168 char * un = NULL;169 size_t un_len = 0;170 171 153 char * fqdn; 172 154 char * realm; 173 char * sess_str = NULL;174 155 175 156 struct avp *avp = NULL; 176 157 union avp_value avp_val; 177 158 178 TRACE_ENTRY("%p %p %p %p", msg, cli, session, diam); 179 CHECK_PARAMS( msg && cli && session && (*session == NULL) && diam && (*diam == NULL) ); 180 181 pref_len = strlen(prefix); 182 183 /* Is there a State attribute with prefix "Diameter/" in the message? (in that case: Diameter/Destination-Host/Destination-Realm/Session-Id) */ 184 /* NOTE: RFC4005 says "Origin-Host" here, but it's not coherent with the rules for answers. Destination-Host makes more sense */ 185 /* Is there a Class attribute with prefix "Diameter/" in the message? (in that case: Diameter/Session-Id) */ 186 for (idx = 0; idx < msg->radius.attr_used; idx++) { 187 struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(msg->radius.buf + msg->radius.attr_pos[idx]); 188 char * attr_val = (char *)(attr + 1); 189 size_t attr_len = attr->length - sizeof(struct radius_attr_hdr); 190 191 if ((attr->type == RADIUS_ATTR_USER_NAME) 192 && attr_len) { 193 TRACE_DEBUG(ANNOYING, "Found a User-Name attribute: '%.*s'", attr_len, attr_val); 194 un = attr_val; 195 un_len = attr_len; 196 continue; 197 } 198 199 if ((attr->type == RADIUS_ATTR_STATE) 200 && (attr_len > pref_len + 5 /* for the '/'s and non empty strings */ ) 201 && ! strncmp(attr_val, prefix, pref_len)) { /* should we make it strncasecmp? */ 202 int i, start; 203 204 TRACE_DEBUG(ANNOYING, "Found a State attribute with '%s' prefix (attr #%d).", prefix, idx); 205 206 /* Now parse the value and check its content is valid. Unfortunately we cannot use strchr here since strings are not \0-terminated */ 207 208 i = start = pref_len; 209 dh = attr_val + i; 210 for (; (i < attr_len - 2) && (attr_val[i] != '/'); i++) /* loop */; 211 if ( i >= attr_len - 2 ) continue; /* the attribute format is not good */ 212 dh_len = i - start; 213 214 start = ++i; 215 dr = attr_val + i; 216 for (; (i < attr_len - 1) && (attr_val[i] != '/'); i++) /* loop */; 217 if ( i >= attr_len - 1 ) continue; /* the attribute format is not good */ 218 dr_len = i - start; 219 220 i++; 221 si = attr_val + i; 222 si_len = attr_len - i; 223 224 TRACE_DEBUG(ANNOYING, "Attribute parsed successfully: DH:'%.*s' DR:'%.*s' SI:'%.*s'.", dh_len, dh, dr_len, dr, si_len, si); 225 /* Remove from the message */ 226 for (i = idx + 1; i < msg->radius.attr_used; i++) 227 msg->radius.attr_pos[i - 1] = msg->radius.attr_pos[i]; 228 msg->radius.attr_used -= 1; 229 break; 230 } 231 232 if ((attr->type == RADIUS_ATTR_CLASS) 233 && (attr_len > pref_len ) 234 && ! strncmp(attr_val, prefix, pref_len)) { 235 si = attr_val + pref_len; 236 si_len = attr_len - pref_len; 237 TRACE_DEBUG(ANNOYING, "Found Class attribute with '%s' prefix (attr #%d), SI:'%.*s'.", prefix, idx, si_len, si); 238 /* Remove from the message */ 239 for (i = idx + 1; i < msg->radius.attr_used; i++) 240 msg->radius.attr_pos[i - 1] = msg->radius.attr_pos[i]; 241 msg->radius.attr_used -= 1; 242 break; 243 } 244 245 } 159 TRACE_ENTRY("%p %p", cli, diam); 160 CHECK_PARAMS( cli && diam && (*diam == NULL) ); 246 161 247 162 /* Get information on this peer */ 248 163 CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &realm) ); 249 164 250 /* Create the session object */251 if (si_len) {252 CHECK_FCT( fd_sess_fromsid ( si, si_len, session, &idx) );253 } else {254 if (un) {255 int len;256 /* If not found, create a new Session-Id. The format is: {fqdn;hi32;lo32;username;diamid} */257 CHECK_MALLOC( sess_str = malloc(un_len + 1 /* ';' */ + fd_g_config->cnf_diamid_len + 1 /* '\0' */) );258 len = sprintf(sess_str, "%.*s;%s", un_len, un, fd_g_config->cnf_diamid);259 CHECK_FCT( fd_sess_new(session, fqdn, sess_str, len) );260 free(sess_str);261 idx = 1;262 }263 }264 265 165 /* Create an empty Diameter message so that extensions can store their AVPs */ 266 166 CHECK_FCT( fd_msg_new ( NULL, MSGFL_ALLOC_ETEID, diam ) ); 267 268 if (*session) {269 CHECK_FCT( fd_sess_getsid(*session, &sess_str) );270 if (idx == 0) {271 TRACE_DEBUG(INFO, "Another message was translated for this session ('%s') and not answered yet, discarding the new RADIUS request.", sess_str);272 *session = NULL;273 return EALREADY;274 }275 276 TRACE_DEBUG(FULL, "Translating new message for session '%s'...", sess_str);277 278 /* Add the Session-Id AVP as first AVP */279 CHECK_FCT( fd_msg_avp_new ( cache_sess_id, 0, &avp ) );280 memset(&avp_val, 0, sizeof(avp_val));281 avp_val.os.data = (unsigned char *)sess_str;282 avp_val.os.len = strlen(sess_str);283 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );284 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_FIRST_CHILD, avp) );285 286 } else {287 TRACE_DEBUG(FULL, "No session has been created for this message");288 }289 290 /* Add the Destination-Realm as next AVP */291 CHECK_FCT( fd_msg_avp_new ( cache_dest_realm, 0, &avp ) );292 memset(&avp_val, 0, sizeof(avp_val));293 if (dr) {294 avp_val.os.data = (unsigned char *)dr;295 avp_val.os.len = dr_len;296 } else {297 int i = 0;298 if (un) {299 /* Is there an '@' in the user name? We don't care for decorated NAI here */300 for (i = un_len - 2; i > 0; i--) {301 if (un[i] == '@') {302 i++;303 break;304 }305 }306 }307 if (i == 0) {308 /* Not found in the User-Name => we use the local domain of this gateway */309 avp_val.os.data = fd_g_config->cnf_diamrlm;310 avp_val.os.len = fd_g_config->cnf_diamrlm_len;311 } else {312 avp_val.os.data = un + i;313 avp_val.os.len = un_len - i;314 }315 }316 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );317 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );318 319 /* Add the Destination-Host as next AVP */320 if (dh) {321 CHECK_FCT( fd_msg_avp_new ( cache_dest_host, 0, &avp ) );322 memset(&avp_val, 0, sizeof(avp_val));323 avp_val.os.data = (unsigned char *)dh;324 avp_val.os.len = dh_len;325 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );326 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );327 }328 167 329 168 /* Add the Origin-Host as next AVP */
Note: See TracChangeset
for help on using the changeset viewer.