1 /*
2 * This file is part of the Sofia-SIP package
3 *
4 * Copyright (C) 2006 Nokia Corporation.
5 *
6 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25 /**@CFILE nua_register.c
26 * @brief REGISTER and registrations
27 *
28 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
29 *
30 * @date Created: Wed Mar 8 11:48:49 EET 2006 ppessi
31 */
32
33 #include "config.h"
34
35 #include <sofia-sip/su_string.h>
36 #include <sofia-sip/su_strlst.h>
37 #include <sofia-sip/token64.h>
38 #include <sofia-sip/su_tagarg.h>
39 #include <sofia-sip/su_tag_inline.h>
40
41 #include <sofia-sip/bnf.h>
42
43 #include <sofia-sip/sip_protos.h>
44 #include <sofia-sip/sip_util.h>
45 #include <sofia-sip/sip_status.h>
46 #include <sofia-sip/msg_parser.h>
47
48 #include "nua_stack.h"
49
50 #include <stddef.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <limits.h>
54
55 #include <assert.h>
56
57 /* ====================================================================== */
58 /* Helper macros and functions for handling #nua_handle_preferences_t. */
59
60 #define NHP_IS_ANY_SET(nhp) nhp_is_any_set((nhp))
61
62 /** Check if any preference is set in @a nhp. */
nhp_is_any_set(nua_handle_preferences_t const * nhp)63 su_inline int nhp_is_any_set(nua_handle_preferences_t const *nhp)
64 {
65 char nhp_zero[sizeof nhp->nhp_set] = { 0 };
66 return memcmp(&nhp->nhp_set, nhp_zero, sizeof nhp->nhp_set) != 0;
67 }
68
69 /** Copy set parameters from @a b to @a a.
70 *
71 * If preference is set in @a b, mark it set also in @a a.
72 */
nhp_or_set(nua_handle_preferences_t * a,nua_handle_preferences_t const * b)73 su_inline void nhp_or_set(nua_handle_preferences_t *a,
74 nua_handle_preferences_t const *b)
75 {
76 memcpy(a, b, offsetof(nua_handle_preferences_t, nhp_set));
77
78 /* Bitwise or of bitfields, casted to unsigned */
79 a->nhp_set_.set_unsigned[0] |= b->nhp_set_.set_unsigned[0];
80 a->nhp_set_.set_unsigned[1] |= b->nhp_set_.set_unsigned[1];
81 }
82
83 static int nhp_set_tags(su_home_t *home,
84 nua_handle_preferences_t *nhp,
85 nua_global_preferences_t *ngp,
86 tagi_t const *tags);
87
88 static int nhp_merge_lists(su_home_t *home,
89 msg_hclass_t *hc,
90 msg_list_t **return_new_list,
91 msg_list_t const *old_list,
92 int already_set,
93 int already_parsed,
94 int always_merge,
95 tag_value_t value);
96
97 static int nhp_save_params(nua_handle_t *nh,
98 su_home_t *tmphome,
99 nua_global_preferences_t *gsrc,
100 nua_handle_preferences_t *src);
101
102 /* ====================================================================== */
103 /* Magical NUTAG_USER_AGENT() - add NHP_USER_AGENT there if it is not there */
104
105 #define NHP_USER_AGENT PACKAGE_NAME "/" PACKAGE_VERSION
106
already_contains_package_name(char const * s)107 static int already_contains_package_name(char const *s)
108 {
109 char const pn[] = " " PACKAGE_NAME "/";
110 size_t pnlen = strlen(pn + 1);
111
112 return su_casenmatch(s, pn + 1, pnlen) || su_strcasestr(s, pn);
113 }
114
115 /* ====================================================================== */
116 /* Stack and handle parameters */
117
118 static int nua_stack_set_smime_params(nua_t *nua, tagi_t const *tags);
119
120 /** @internal Methods allowed by default. */
121 static char const nua_allow_str[] =
122 "INVITE, ACK, BYE, CANCEL, OPTIONS, PRACK, "
123 "MESSAGE, SUBSCRIBE, NOTIFY, REFER, UPDATE";
124
125 /** @internal Set default parameters */
nua_stack_set_defaults(nua_handle_t * nh,nua_handle_preferences_t * nhp)126 int nua_stack_set_defaults(nua_handle_t *nh,
127 nua_handle_preferences_t *nhp)
128 {
129 su_home_t *home = (su_home_t *)nh;
130
131 /* Set some defaults */
132 NHP_SET(nhp, retry_count, 3);
133 NHP_SET(nhp, max_subscriptions, 20);
134
135 NHP_SET(nhp, media_enable, 1);
136 NHP_SET(nhp, invite_enable, 1);
137 NHP_SET(nhp, auto_alert, 0);
138 NHP_SET(nhp, early_media, 0);
139 NHP_SET(nhp, only183_100rel, 0);
140 NHP_SET(nhp, auto_answer, 0);
141 NHP_SET(nhp, auto_ack, 1);
142 NHP_SET(nhp, timer_autorequire, 1);
143 NHP_SET(nhp, invite_timeout, 120);
144
145 nhp->nhp_session_timer = 1800;
146 nhp->nhp_refresher = nua_no_refresher;
147
148 NHP_SET(nhp, min_se, 120);
149 NHP_SET(nhp, update_refresh, 0);
150
151 NHP_SET(nhp, message_enable, 1);
152 NHP_SET(nhp, win_messenger_enable, 0);
153 if (getenv("PIMIW_HACK") != 0)
154 NHP_SET(nhp, message_auto_respond, 1);
155
156 NHP_SET(nhp, media_features, 0);
157 NHP_SET(nhp, callee_caps, 0);
158 NHP_SET(nhp, service_route_enable, 1);
159 NHP_SET(nhp, path_enable, 1);
160 NHP_SET(nhp, retry_after_enable, 1);
161
162 NHP_SET(nhp, refer_expires, 300);
163 NHP_SET(nhp, refer_with_id, 1);
164
165 NHP_SET(nhp, substate, nua_substate_active);
166 NHP_SET(nhp, sub_expires, 3600);
167
168 NHP_SET(nhp, allow, sip_allow_make(home, nua_allow_str));
169 NHP_SET(nhp, supported, sip_supported_make(home, "timer, 100rel"));
170 NHP_SET(nhp, user_agent, su_strdup(home, NHP_USER_AGENT));
171
172 NHP_SET(nhp, outbound, su_strdup(home, "natify"));
173
174 NHP_SET(nhp, keepalive, 120000);
175
176 NHP_SET(nhp, auto_invite_100, 1);
177
178 NHP_SET(nhp, appl_method,
179 sip_allow_make(home, "INVITE, REGISTER, PUBLISH, SUBSCRIBE"));
180
181 if (!nhp->nhp_allow ||
182 !nhp->nhp_supported ||
183 !nhp->nhp_user_agent ||
184 !nhp->nhp_outbound)
185 return -1;
186
187 return 0;
188 }
189
190 /** @internal Set the default from field */
nua_stack_set_from(nua_t * nua,int initial,tagi_t const * tags)191 int nua_stack_set_from(nua_t *nua, int initial, tagi_t const *tags)
192 {
193 sip_from_t const *from = NONE;
194 char const *str = NONE;
195 sip_from_t *f = NULL, f0[1];
196 int set;
197
198 tl_gets(tags,
199 /* By nua_stack_set_from() */
200 SIPTAG_FROM_REF(from),
201 SIPTAG_FROM_STR_REF(str),
202 TAG_END());
203
204 if (!initial && from == NONE && str == NONE)
205 return 0;
206
207 sip_from_init(f0);
208
209 if (from && from != NONE) {
210 f0->a_display = from->a_display;
211 *f0->a_url = *from->a_url;
212 f = sip_from_dup(nua->nua_home, f0);
213 set = 1;
214 }
215 else if (str && str != NONE) {
216 f = sip_from_make(nua->nua_home, str);
217 if (f)
218 *f0 = *f, f = f0, f->a_params = NULL;
219 set = 1;
220 }
221 else {
222 sip_contact_t const *m;
223
224 m = nua_stack_get_contact(nua->nua_registrations);
225
226 if (m) {
227 f0->a_display = m->m_display;
228 *f0->a_url = *m->m_url;
229 f = sip_from_dup(nua->nua_home, f0);
230 }
231 set = 0;
232 }
233
234 if (!f)
235 return -1;
236
237 nua->nua_from_is_set = set;
238 *nua->nua_from = *f;
239 return 0;
240 }
241
242 /** @internal Initialize instance ID. */
nua_stack_init_instance(nua_handle_t * nh,tagi_t const * tags)243 int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags)
244 {
245 nua_handle_preferences_t *nhp = nh->nh_prefs;
246
247 char const *instance = NONE;
248
249 tl_gets(tags, NUTAG_INSTANCE_REF(instance), TAG_END());
250
251 if (instance != NONE) {
252 NHP_SET(nhp, instance, su_strdup(nh->nh_home, instance));
253 if (instance && !nhp->nhp_instance)
254 return -1;
255 }
256
257 return 0;
258 }
259
260 /**@fn void nua_set_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...)
261 *
262 * Set @nua parameters, shared by all handles.
263 *
264 * @param nua Pointer to NUA stack object
265 * @param tag, value, ... List of tagged parameters
266 *
267 * @return
268 * nothing
269 *
270 * @par Related tags:
271 * NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() \n
272 * NUTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS(), and
273 * SIPTAG_ALLOW_EVENTS_STR() \n
274 * NUTAG_AUTOACK() \n
275 * NUTAG_AUTOALERT() \n
276 * NUTAG_AUTOANSWER() \n
277 * NUTAG_CALLEE_CAPS() \n
278 * NUTAG_DETECT_NETWORK_UPDATES() \n
279 * NUTAG_EARLY_ANSWER() \n
280 * NUTAG_EARLY_MEDIA() \n
281 * NUTAG_ENABLEINVITE() \n
282 * NUTAG_ENABLEMESSAGE() \n
283 * NUTAG_ENABLEMESSENGER() \n
284 * NUTAG_INITIAL_ROUTE() \n
285 * NUTAG_INITIAL_ROUTE_STR() \n
286 * NUTAG_INSTANCE() \n
287 * NUTAG_INVITE_TIMER() \n
288 * NUTAG_KEEPALIVE() \n
289 * NUTAG_KEEPALIVE_STREAM() \n
290 * NUTAG_MAX_SUBSCRIPTIONS() \n
291 * NUTAG_MEDIA_ENABLE() \n
292 * NUTAG_MEDIA_FEATURES() \n
293 * NUTAG_MIN_SE() \n
294 * NUTAG_M_DISPLAY() \n
295 * NUTAG_M_FEATURES() \n
296 * NUTAG_M_PARAMS() \n
297 * NUTAG_M_USERNAME() \n
298 * NUTAG_ONLY183_100REL() \n
299 * NUTAG_OUTBOUND() \n
300 * NUTAG_PATH_ENABLE() \n
301 * NUTAG_RETRY_AFTER_ENABLE() \n
302 * NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n
303 * NUTAG_REFER_EXPIRES() \n
304 * NUTAG_REFER_WITH_ID() \n
305 * NUTAG_REFRESH_WITHOUT_SDP() \n
306 * NUTAG_REGISTRAR() \n
307 * NUTAG_RETRY_COUNT() \n
308 * NUTAG_SERVICE_ROUTE_ENABLE() \n
309 * NUTAG_SESSION_REFRESHER() \n
310 * NUTAG_SESSION_TIMER() \n
311 * NUTAG_SMIME_ENABLE() \n
312 * NUTAG_SMIME_KEY_ENCRYPTION() \n
313 * NUTAG_SMIME_MESSAGE_DIGEST() \n
314 * NUTAG_SMIME_MESSAGE_ENCRYPTION() \n
315 * NUTAG_SMIME_OPT() \n
316 * NUTAG_SMIME_PROTECTION_MODE() \n
317 * NUTAG_SMIME_SIGNATURE() \n
318 * NUTAG_SOA_NAME() \n
319 * NUTAG_SUBSTATE() \n
320 * NUTAG_SUB_EXPIRES() \n
321 * NUTAG_SUPPORTED(), SIPTAG_SUPPORTED(), and SIPTAG_SUPPORTED_STR() \n
322 * NUTAG_UPDATE_REFRESH() \n
323 * NUTAG_USER_AGENT(), SIPTAG_USER_AGENT() and SIPTAG_USER_AGENT_STR() \n
324 * SIPTAG_ORGANIZATION() and SIPTAG_ORGANIZATION_STR() \n
325 *
326 * nua_set_params() also accepts any soa tags, defined in
327 * <sofia-sip/soa_tag.h>, and nta tags, defined in <sofia-sip/nta_tag.h>.
328 *
329 * @par Events:
330 * #nua_r_set_params
331 *
332 * @par SIP Header as NUA Parameters
333 * The @nua parameters include SIP headers @Allow, @Supported, @Organization,
334 * @UserAgent and @From. They are included in most of the SIP messages sent
335 * by @nua. They are set in the same way as the tagged arguments are
336 * used to populate a SIP message.
337 * @par
338 * When multiple tags for the same header are specified, the behaviour
339 * depends on the header type. If only a single header field can be included
340 * in a SIP message, the latest non-NULL value is used, e.g., @Organization.
341 * However, if the SIP header can consist of multiple lines or header fields
342 * separated by comma, in this case, @Allow and @Supported, all the tagged
343 * values are concatenated.
344 * @par
345 * However, if the tag value is #SIP_NONE (-1 casted as a void pointer), the
346 * values from previous tags are ignored.
347 *
348 * For example, the nua_set_params() call like this:
349 * @code
350 * nua_set_params(nua,
351 * SIPTAG_USER_AGENT_STR("tester/1.0"),
352 * SIPTAG_ALLOW_STR("INVITE,CANCEL,BYE,ACK"),
353 * SIPTAG_ORGANIZATION(NULL),
354 * SIPTAG_USER_AGENT(NULL),
355 * SIPTAG_ALLOW(SIP_NONE),
356 * TAG_END());
357 * @endcode
358 * will leave @Allow and @Organization headers empty. The @UserAgent header
359 * will contain value "tester/1.0".
360 * @code
361 * nua_set_params(nua,
362 * SIPTAG_ORGANIZATION_STR("Malevolent Microwavers"),
363 * SIPTAG_ALLOW_STR("OPTIONS"),
364 * SIPTAG_ALLOW(SIP_NONE),
365 * SIPTAG_ORGANIZATION_STR("The Phone Company"),
366 * SIPTAG_ALLOW_STR("SUBSCRIBE"),
367 * SIPTAG_ALLOW(NULL),
368 * SIPTAG_ORGANIZATION_STR(NULL),
369 * TAG_END());
370 * @endcode
371 * sets the header @Allow with value <code>SUBSCRIBE</code> and the
372 * header @Organization will have value <code>The Phone Company</code>.
373 *
374 */
375
376 /**@fn void nua_set_hparams(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...);
377 *
378 * Set the handle-specific parameters.
379 *
380 * The handle-specific parameters override default or global parameters set
381 * by nua_set_params(). The handle-specific parameters are set by several
382 * other operations: nua_invite(), nua_respond(), nua_ack(),
383 * nua_prack(), nua_update(), nua_info(), nua_bye(), nua_options(),
384 * nua_message(), nua_register(), nua_publish(), nua_refer(),
385 * nua_subscribe(), nua_notify(), nua_refer(), and nua_notifier().
386 *
387 * @param nh Pointer to a NUA handle
388 * @param tag, value, ... List of tagged parameters
389 *
390 * @return
391 * nothing
392 *
393 * @par Tags Used to Set Handle-Specific Parameters:
394 * NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() \n
395 * NUTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS(), and
396 * SIPTAG_ALLOW_EVENTS_STR() \n
397 * NUTAG_AUTH_CACHE() \n
398 * NUTAG_AUTOACK() \n
399 * NUTAG_AUTOALERT() \n
400 * NUTAG_AUTOANSWER() \n
401 * NUTAG_CALLEE_CAPS() \n
402 * NUTAG_EARLY_ANSWER() \n
403 * NUTAG_EARLY_MEDIA() \n
404 * NUTAG_ENABLEINVITE() \n
405 * NUTAG_ENABLEMESSAGE() \n
406 * NUTAG_ENABLEMESSENGER() \n
407 * NUTAG_INITIAL_ROUTE() \n
408 * NUTAG_INITIAL_ROUTE_STR() \n
409 * NUTAG_INSTANCE() \n
410 * NUTAG_INVITE_TIMER() \n
411 * NUTAG_KEEPALIVE() \n
412 * NUTAG_KEEPALIVE_STREAM() \n
413 * NUTAG_MAX_SUBSCRIPTIONS() \n
414 * NUTAG_MEDIA_ENABLE() \n
415 * NUTAG_MEDIA_FEATURES() \n
416 * NUTAG_MIN_SE() \n
417 * NUTAG_M_DISPLAY() \n
418 * NUTAG_M_FEATURES() \n
419 * NUTAG_M_PARAMS() \n
420 * NUTAG_M_USERNAME() \n
421 * NUTAG_ONLY183_100REL() \n
422 * NUTAG_OUTBOUND() \n
423 * NUTAG_PATH_ENABLE() \n
424 * NUTAG_RETRY_AFTER_ENABLE() \n
425 * NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n
426 * NUTAG_REFER_EXPIRES() \n
427 * NUTAG_REFER_WITH_ID() \n
428 * NUTAG_REFRESH_WITHOUT_SDP() \n
429 * NUTAG_REGISTRAR() \n
430 * NUTAG_RETRY_COUNT() \n
431 * NUTAG_SERVICE_ROUTE_ENABLE() \n
432 * NUTAG_SESSION_REFRESHER() \n
433 * NUTAG_SESSION_TIMER() \n
434 * NUTAG_SOA_NAME() \n
435 * NUTAG_SUBSTATE() \n
436 * NUTAG_SUB_EXPIRES() \n
437 * NUTAG_SUPPORTED(), SIPTAG_SUPPORTED(), and SIPTAG_SUPPORTED_STR() \n
438 * NUTAG_UPDATE_REFRESH() \n
439 * NUTAG_USER_AGENT(), SIPTAG_USER_AGENT() and SIPTAG_USER_AGENT_STR() \n
440 * SIPTAG_ORGANIZATION() and SIPTAG_ORGANIZATION_STR() \n
441 * Any soa tags are also considered as handle-specific parameters. They are
442 * defined in <sofia-sip/soa_tag.h>.
443 *
444 * The global parameters that can not be set by nua_set_hparams() include
445 * NUTAG_DETECT_NETWORK_UPDATES(), NUTAG_SMIME_* tags, and all NTA tags.
446 *
447 * @par Events:
448 * #nua_r_set_params
449 */
450
451 /** @NUA_EVENT nua_r_set_params
452 *
453 * Response to nua_set_params() or nua_set_hparams().
454 *
455 * @param status 200 when successful, error code otherwise
456 * @param phrase a short textual description of @a status code
457 * @param nh NULL when responding to nua_set_params(),
458 * operation handle when responding to nua_set_hparams()
459 * @param hmagic NULL when responding to nua_set_params(),
460 * application contact associated with the operation handle
461 * when responding to nua_set_hparams()
462 * @param sip NULL
463 * @param tags None
464 *
465 * @sa nua_set_params(), nua_set_hparams(),
466 * #nua_r_get_params, nua_get_params(), nua_get_hparams()
467 *
468 * @END_NUA_EVENT
469 */
470
nua_stack_set_params(nua_t * nua,nua_handle_t * nh,nua_event_t e,tagi_t const * tags)471 int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
472 tagi_t const *tags)
473 {
474 nua_handle_t *dnh = nua->nua_dhandle;
475
476 int status;
477 char const *phrase;
478
479 nua_handle_preferences_t tmp[1];
480 int any_changes = 0;
481
482 enter;
483
484 {
485 su_home_t tmphome[1] = { SU_HOME_INIT(tmphome) };
486 nua_handle_preferences_t *nhp = nh->nh_prefs;
487 nua_handle_preferences_t const *dnhp = dnh->nh_prefs;
488 nua_global_preferences_t gtmp[1], *ngp = NULL;
489
490 *tmp = *nhp; NHP_UNSET_ALL(tmp);
491
492 /*
493 * Supported features, allowed methods and events are merged
494 * with previous or default settings.
495 *
496 * Here we just copy pointers from default settings. However when saving
497 * settings we have to be extra careful so that we
498 * 1) zero the pointers if the setting has not been modified
499 * 2) do not free pointer if the setting has been modified
500 * See NHP_ZAP_OVERRIDEN() below for gorier details.
501 */
502 if (!NHP_ISSET(nhp, supported))
503 tmp->nhp_supported = dnhp->nhp_supported;
504 if (!NHP_ISSET(nhp, allow))
505 tmp->nhp_allow = dnhp->nhp_allow;
506 if (!NHP_ISSET(nhp, allow_events))
507 tmp->nhp_allow_events = dnhp->nhp_allow_events;
508 if (!NHP_ISSET(nhp, appl_method))
509 tmp->nhp_appl_method = dnhp->nhp_appl_method;
510
511 if (nh == dnh) /* nua_set_params() call, save stack-wide params, too */
512 ngp = gtmp, *gtmp = *nua->nua_prefs;
513
514 /* Set and save parameters to tmp */
515 if (!nh->nh_used_ptags &&
516 nhp_set_tags(tmphome, tmp, NULL, nh->nh_ptags) < 0)
517 status = 900, phrase = "Error storing default handle parameters";
518 else if (nhp_set_tags(tmphome, tmp, ngp, tags) < 0)
519 status = 900, phrase = "Error storing parameters";
520 else if ((any_changes = nhp_save_params(nh, tmphome, ngp, tmp)) < 0)
521 status = 900, phrase = su_strerror(ENOMEM);
522 else
523 status = 200, phrase = "OK", nh->nh_used_ptags = 1;
524
525 su_home_deinit(tmphome);
526 }
527
528 if (status == 200) {
529 nua_handle_preferences_t const *nhp = nh->nh_prefs;
530 nua_handle_preferences_t const *dnhp = dnh->nh_prefs;
531
532 if (!nh->nh_soa && NHP_GET(nhp, dnhp, media_enable)) {
533 /* Create soa when needed */
534 char const *soa_name = NHP_GET(nhp, dnhp, soa_name);
535
536 if (dnh->nh_soa)
537 nh->nh_soa = soa_clone(dnh->nh_soa, nua->nua_root, nh);
538 else
539 nh->nh_soa = soa_create(soa_name, nua->nua_root, nh);
540
541 if (!nh->nh_soa)
542 status = 900, phrase = "Error Creating SOA Object";
543 else if (soa_set_params(nh->nh_soa, TAG_NEXT(nh->nh_ptags)) < 0)
544 status = 900, phrase = "Error Setting SOA Parameters";
545 }
546 else if (nh->nh_soa && !NHP_GET(nhp, dnhp, media_enable)) {
547 /* ... destroy soa when not needed */
548 soa_destroy(nh->nh_soa), nh->nh_soa = NULL;
549 }
550
551 if (status == 200 && tags && nh->nh_soa &&
552 soa_set_params(nh->nh_soa, TAG_NEXT(tags)) < 0)
553 status = 900, phrase = "Error Setting SOA Parameters";
554 }
555
556 if (status == 200 && nh == dnh) {
557 /* Set stack-specific things below */
558 if (nua_stack_set_smime_params(nua, tags) < 0) {
559 status = 900, phrase = "Error setting S/MIME parameters";
560 }
561 else if (nua->nua_nta &&
562 nta_agent_set_params(nua->nua_nta, TAG_NEXT(tags)) < 0) {
563 status = 900, phrase = "Error setting NTA parameters";
564 }
565 else {
566 nua_stack_set_from(nua, 0, tags);
567
568 if (nua->nua_prefs->ngp_detect_network_updates)
569 nua_stack_launch_network_change_detector(nua);
570 }
571 }
572
573 if (status != 200) {
574 if (e == nua_i_none)
575 SU_DEBUG_1(("nua_set_params(): failed: %s\n", phrase));
576 return UA_EVENT2(e, status, phrase), -1;
577 }
578 else {
579 if (e == nua_r_set_params)
580 UA_EVENT2(e, status, phrase);
581
582 if (any_changes) {
583 nua_handle_preferences_t changed[1];
584
585 *changed = *nh->nh_prefs;
586 memcpy(&changed->nhp_set_, &tmp->nhp_set_, sizeof changed->nhp_set_);
587
588 nua_dialog_update_params(nh->nh_ds,
589 changed,
590 nh->nh_prefs,
591 dnh->nh_prefs);
592 }
593 return 0;
594 }
595 }
596
597
598 /** Parse parameters from tags to @a nhp or @a ngp.
599 *
600 * @param home allocate new values from @a home
601 * @param nhp structure to store handle preferences
602 * @param ngp structure to store global preferences
603 * @param tags list of tags to parse
604 */
nhp_set_tags(su_home_t * home,nua_handle_preferences_t * nhp,nua_global_preferences_t * ngp,tagi_t const * tags)605 static int nhp_set_tags(su_home_t *home,
606 nua_handle_preferences_t *nhp,
607 nua_global_preferences_t *ngp,
608 tagi_t const *tags)
609 {
610
611 /* Set copy of string to handle pref structure */
612 #define NHP_SET_STR(nhp, name, v) \
613 if ((v) != (tag_value_t)0) { \
614 char const *_value = (char const *)v; \
615 char *_new = _value ? su_strdup(home, _value) : NULL; \
616 if (NHP_ISSET(nhp, name)) \
617 su_free(home, (void *)nhp->nhp_##name); \
618 NHP_SET(nhp, name, _new); \
619 if (_new == NULL && _value != NULL) \
620 return -1; \
621 }
622
623 /* Set copy of string from url to handle pref structure */
624 #define NHP_SET_STR_BY_URL(nhp, type, name, v) \
625 if ((v) != (tag_value_t)-1) { \
626 url_t const *_value = (url_t const *)(v); \
627 type *_new = (type *)url_as_string(home, (void *)_value); \
628 if (NHP_ISSET(nhp, name)) \
629 su_free(home, (void *)nhp->nhp_##name); \
630 NHP_SET(nhp, name, _new); \
631 if (_new == NULL && _value != NULL) \
632 return -1; \
633 }
634
635 /* Set copy of header to handle pref structure */
636 #define NHP_SET_HEADER(nhp, name, hdr, v) \
637 if ((v) != 0) { \
638 sip_##hdr##_t const *_value = (sip_##hdr##_t const *)(v); \
639 sip_##hdr##_t *_new = NULL; \
640 if (_value != SIP_NONE) \
641 _new = sip_##name##_dup(home, _value); \
642 if (NHP_ISSET(nhp, name)) \
643 msg_header_free_all(home, (void *)nhp->nhp_##name); \
644 NHP_SET(nhp, name, _new); \
645 if (_new == NULL && _value != SIP_NONE) \
646 return -1; \
647 }
648
649 /* Set header made of string to handle pref structure */
650 #define NHP_SET_HEADER_STR(nhp, name, hdr, v) \
651 if ((v) != 0) { \
652 char const *_value = (char const *)(v); \
653 sip_##hdr##_t *_new = NULL; \
654 if (_value != SIP_NONE) \
655 _new = sip_##name##_make(home, _value); \
656 if (NHP_ISSET(nhp, name)) \
657 msg_header_free_all(home, (void *)nhp->nhp_##name); \
658 NHP_SET(nhp, name, _new); \
659 if (_new == NULL && _value != SIP_NONE) \
660 return -1; \
661 }
662
663 /* Append copy of header to handle pref structure */
664 #define NHP_APPEND_HEADER(nhp, name, hdr, is_str, next, v) \
665 { \
666 sip_##hdr##_t const *_value = (sip_##hdr##_t const *)(v); \
667 char const *_str = (char const *)(v); \
668 sip_##hdr##_t *_new = NULL; \
669 sip_##hdr##_t **_end = &nhp->nhp_##name; \
670 if (_value != SIP_NONE && _value != NULL) { \
671 _new = (is_str) \
672 ? sip_##hdr##_make(home, _str) \
673 : sip_##hdr##_dup(home, _value); \
674 if (_new == NULL) return -1; \
675 } \
676 if (NHP_ISSET(nhp, name)) \
677 while(*_end) \
678 _end = next(*_end); \
679 nhp->nhp_set.nhb_##name = 1; \
680 *_end = _new; \
681 }
682
683 /* Set copy of string from header to handle pref structure */
684 #define NHP_SET_STR_BY_HEADER(nhp, name, v) \
685 if ((v) != 0) { \
686 sip_##name##_t const *_value = (sip_##name##_t const *)(v); \
687 char *_new = NULL; \
688 if (_value != SIP_NONE) \
689 _new = sip_header_as_string(home, (void *)_value); \
690 if (NHP_ISSET(nhp, name)) \
691 su_free(home, (void *)nhp->nhp_##name); \
692 NHP_SET(nhp, name, _new); \
693 if (_new == NULL && _value != SIP_NONE) \
694 return -1; \
695 }
696
697
698 tagi_t const *t;
699
700 for (t = tags; t; t = tl_next(t)) {
701 tag_type_t tag = t->t_tag;
702 tag_value_t value = t->t_value;
703
704 if (tag == NULL)
705 break;
706 /* NUTAG_RETRY_COUNT(retry_count) */
707 else if (tag == nutag_retry_count) {
708 NHP_SET(nhp, retry_count, (unsigned)value);
709 }
710 /* NUTAG_MAX_SUBSCRIPTIONS(max_subscriptions) */
711 else if (tag == nutag_max_subscriptions) {
712 NHP_SET(nhp, max_subscriptions, (unsigned)value);
713 }
714 /* NUTAG_SOA_NAME(soa_name) */
715 else if (tag == nutag_soa_name) {
716 NHP_SET_STR(nhp, soa_name, value);
717 }
718 /* NUTAG_MEDIA_ENABLE(media_enable) */
719 else if (tag == nutag_media_enable) {
720 NHP_SET(nhp, media_enable, value != 0);
721 }
722 /* NUTAG_ENABLEINVITE(invite_enable) */
723 else if (tag == nutag_enableinvite) {
724 NHP_SET(nhp, invite_enable, value != 0);
725 }
726 /* NUTAG_AUTOALERT(auto_alert) */
727 else if (tag == nutag_autoalert) {
728 NHP_SET(nhp, auto_alert, value != 0);
729 }
730 /* NUTAG_EARLY_ANSWER(early_answer) */
731 else if (tag == nutag_early_answer) {
732 NHP_SET(nhp, early_answer, value != 0);
733 }
734 /* NUTAG_EARLY_MEDIA(early_media) */
735 else if (tag == nutag_early_media) {
736 NHP_SET(nhp, early_media, value != 0);
737 }
738 /* NUTAG_ONLY183_100REL(only183_100rel) */
739 else if (tag == nutag_only183_100rel) {
740 NHP_SET(nhp, only183_100rel, value != 0);
741 }
742 /* NUTAG_AUTOANSWER(auto_answer) */
743 else if (tag == nutag_autoanswer) {
744 NHP_SET(nhp, auto_answer, value != 0);
745 }
746 /* NUTAG_AUTOACK(auto_ack) */
747 else if (tag == nutag_autoack) {
748 NHP_SET(nhp, auto_ack, value != 0);
749 }
750 /* NUTAG_TIMER_AUTOREQUIRE(timer_autorequire) */
751 else if (tag == nutag_timer_autorequire) {
752 NHP_SET(nhp, timer_autorequire, value != 0);
753 }
754 /* NUTAG_INVITE_TIMER(invite_timeout) */
755 else if (tag == nutag_invite_timer) {
756 NHP_SET(nhp, invite_timeout, (unsigned)value);
757 }
758 /* NUTAG_SESSION_TIMER(session_timer) */
759 else if (tag == nutag_session_timer) {
760 NHP_SET(nhp, session_timer, (unsigned)value);
761 }
762 /* NUTAG_MIN_SE(min_se) */
763 else if (tag == nutag_min_se) {
764 NHP_SET(nhp, min_se, (unsigned)value);
765 }
766 /* NUTAG_SESSION_REFRESHER(refresher) */
767 else if (tag == nutag_session_refresher) {
768 int refresher = value;
769
770 if (refresher >= nua_remote_refresher)
771 refresher = nua_remote_refresher;
772 else if (refresher <= nua_no_refresher)
773 refresher = nua_no_refresher;
774
775 NHP_SET(nhp, refresher, (enum nua_session_refresher)refresher);
776 }
777 /* NUTAG_UPDATE_REFRESH(update_refresh) */
778 else if (tag == nutag_update_refresh) {
779 NHP_SET(nhp, update_refresh, value != 0);
780 }
781 /* NUTAG_REFRESH_WITHOUT_SDP(refresh_without_sdp) */
782 else if (tag == nutag_refresh_without_sdp) {
783 NHP_SET(nhp, refresh_without_sdp, value != 0);
784 }
785 /* NUTAG_ENABLEMESSAGE(message_enable) */
786 else if (tag == nutag_enablemessage) {
787 NHP_SET(nhp, message_enable, value != 0);
788 }
789 /* NUTAG_ENABLEMESSENGER(win_messenger_enable) */
790 else if (tag == nutag_enablemessenger) {
791 NHP_SET(nhp, win_messenger_enable, value != 0);
792 }
793 /* NUTAG_CALLEE_CAPS(callee_caps) */
794 else if (tag == nutag_callee_caps) {
795 NHP_SET(nhp, callee_caps, value != 0);
796 }
797 /* NUTAG_MEDIA_FEATURES(media_features) */
798 else if (tag == nutag_media_features) {
799 NHP_SET(nhp, media_features, value != 0);
800 }
801 /* NUTAG_SERVICE_ROUTE_ENABLE(service_route_enable) */
802 else if (tag == nutag_service_route_enable) {
803 NHP_SET(nhp, service_route_enable, value != 0);
804 }
805 /* NUTAG_PATH_ENABLE(path_enable) */
806 else if (tag == nutag_path_enable) {
807 NHP_SET(nhp, path_enable, value != 0);
808 }
809 /* NUTAG_RETRY_AFTER_ENABLE(retry_after_enable) */
810 else if (tag == nutag_retry_after_enable) {
811 NHP_SET(nhp, retry_after_enable, value != 0);
812 }
813 /* NUTAG_AUTH_CACHE(auth_cache) */
814 else if (tag == nutag_auth_cache) {
815 if (value >= 0 && value < (tag_value_t)_nua_auth_cache_invalid)
816 NHP_SET(nhp, auth_cache, (int)value);
817 }
818 /* NUTAG_REFER_EXPIRES(refer_expires) */
819 else if (tag == nutag_refer_expires) {
820 NHP_SET(nhp, refer_expires, value);
821 }
822 /* NUTAG_REFER_WITH_ID(refer_with_id) */
823 else if (tag == nutag_refer_with_id) {
824 NHP_SET(nhp, refer_with_id, value != 0);
825 }
826 /* NUTAG_SUBSTATE(substate) */
827 else if (tag == nutag_substate) {
828 NHP_SET(nhp, substate, (int)value);
829 }
830 /* NUTAG_SUB_EXPIRES(sub_expires) */
831 else if (tag == nutag_sub_expires) {
832 NHP_SET(nhp, sub_expires, value);
833 }
834 /* NUTAG_KEEPALIVE(keepalive) */
835 else if (tag == nutag_keepalive) {
836 NHP_SET(nhp, keepalive, (unsigned)value);
837 }
838 /* NUTAG_KEEPALIVE_STREAM(keepalive_stream) */
839 else if (tag == nutag_keepalive_stream) {
840 NHP_SET(nhp, keepalive_stream, (unsigned)value);
841 }
842
843 /* NUTAG_SUPPORTED(feature) */
844 /* SIPTAG_SUPPORTED_STR(supported_str) */
845 /* SIPTAG_SUPPORTED(supported) */
846 else if (tag == nutag_supported ||
847 tag == siptag_supported ||
848 tag == siptag_supported_str) {
849 int ok;
850 sip_supported_t *supported = NULL;
851
852 ok = nhp_merge_lists(home,
853 sip_supported_class, &supported, nhp->nhp_supported,
854 NHP_ISSET(nhp, supported), /* already set by tags */
855 tag == siptag_supported, /* dup it, don't make */
856 tag == nutag_supported, /* merge with old value */
857 t->t_value);
858 if (ok < 0)
859 return -1;
860 else if (ok)
861 NHP_SET(nhp, supported, supported);
862 }
863 /* NUTAG_ALLOW(allowing) */
864 /* SIPTAG_ALLOW_STR(allow_str) */
865 /* SIPTAG_ALLOW(allow) */
866 else if (tag == nutag_allow ||
867 tag == siptag_allow_str ||
868 tag == siptag_allow) {
869 int ok;
870 msg_list_t *allow = NULL;
871
872 ok = nhp_merge_lists(home,
873 sip_allow_class,
874 &allow,
875 (msg_list_t const *)nhp->nhp_allow,
876 NHP_ISSET(nhp, allow), /* already set by tags */
877 tag == siptag_allow, /* dup it, don't make */
878 tag == nutag_allow, /* merge with old value */
879 t->t_value);
880 if (ok < 0)
881 return -1;
882 else if (ok)
883 NHP_SET(nhp, allow, (sip_allow_t *)allow);
884 }
885 /* NUTAG_ALLOW_EVENTS(allow_events) */
886 /* SIPTAG_ALLOW_EVENTS_STR(allow_events) */
887 /* SIPTAG_ALLOW_EVENTS(allow_events) */
888 else if (tag == nutag_allow_events ||
889 tag == siptag_allow_events_str ||
890 tag == siptag_allow_events) {
891 int ok;
892 sip_allow_events_t *allow_events = NULL;
893
894 ok = nhp_merge_lists(home,
895 sip_allow_events_class,
896 &allow_events,
897 nhp->nhp_allow_events,
898 NHP_ISSET(nhp, allow_events), /* already set */
899 tag == siptag_allow_events, /* dup it, don't make */
900 tag == nutag_allow_events, /* merge with old value */
901 t->t_value);
902 if (ok < 0)
903 return -1;
904 else if (ok)
905 NHP_SET(nhp, allow_events, allow_events);
906 }
907 /* NUTAG_APPL_METHOD(appl_method) */
908 else if (tag == nutag_appl_method) {
909 if (t->t_value == 0) {
910 NHP_SET(nhp, appl_method, NULL);
911 }
912 else {
913 int ok;
914 msg_list_t *appl_method = NULL;
915
916 ok = nhp_merge_lists(home,
917 sip_allow_class,
918 &appl_method,
919 (msg_list_t const *)nhp->nhp_appl_method,
920 /* already set by tags? */
921 NHP_ISSET(nhp, appl_method),
922 0, /* dup it, don't make */
923 1, /* merge with old value */
924 t->t_value);
925 if (ok < 0)
926 return -1;
927 else if (ok)
928 NHP_SET(nhp, appl_method, (sip_allow_t *)appl_method);
929 }
930 }
931 else if (tag == nutag_initial_route ||
932 tag == nutag_initial_route_str) {
933 #define next_route(r) (&(r)->r_next)
934 NHP_APPEND_HEADER(nhp, initial_route, route,
935 (tag == nutag_initial_route_str),
936 next_route,
937 t->t_value);
938 sip_route_fix(nhp->nhp_initial_route);
939 }
940 /* SIPTAG_USER_AGENT(user_agent) */
941 else if (tag == siptag_user_agent) {
942 NHP_SET_STR_BY_HEADER(nhp, user_agent, value);
943 }
944 /* SIPTAG_USER_AGENT_STR(user_agent_str) */
945 else if (tag == siptag_user_agent_str && value != 0) {
946 if (value == -1)
947 value = 0;
948 NHP_SET_STR(nhp, user_agent, value);
949 }
950 /* NUTAG_USER_AGENT(ua_name) */
951 else if (tag == nutag_user_agent) {
952 /* Add contents of NUTAG_USER_AGENT() to our distribution name */
953 char const *str = (void *)value, *ua;
954
955 if (str && !already_contains_package_name(str))
956 ua = su_sprintf(home, "%s %s", str, NHP_USER_AGENT);
957 else if (str)
958 ua = su_strdup(home, str);
959 else
960 ua = su_strdup(home, NHP_USER_AGENT);
961
962 NHP_SET(nhp, user_agent, ua);
963 }
964 /* SIPTAG_ORGANIZATION(organization) */
965 else if (tag == siptag_organization) {
966 NHP_SET_STR_BY_HEADER(nhp, organization, value);
967 }
968 /* SIPTAG_ORGANIZATION_STR(organization_str) */
969 else if (tag == siptag_organization_str) {
970 if (value == -1)
971 value = 0;
972 NHP_SET_STR(nhp, organization, value);
973 }
974 /* SIPTAG_VIA(via) */
975 else if (tag == siptag_via) {
976 NHP_SET_STR_BY_HEADER(nhp, via, value);
977 }
978 /* SIPTAG_VIA_STR(via_str) */
979 else if (tag == siptag_via_str) {
980 if (value == -1)
981 value = 0;
982 NHP_SET_STR(nhp, via, value);
983 }
984 /* NUTAG_REGISTRAR(registrar) */
985 else if (tag == nutag_registrar) {
986 NHP_SET_STR_BY_URL(nhp, char, registrar, value);
987 if (NHP_ISSET(nhp, registrar) && su_strmatch(nhp->nhp_registrar, "*"))
988 NHP_SET_STR(nhp, registrar, 0);
989 }
990 /* NUTAG_INSTANCE(instance) */
991 else if (tag == nutag_instance) {
992 NHP_SET_STR(nhp, instance, value);
993 }
994 /* NUTAG_M_DISPLAY(m_display) */
995 else if (tag == nutag_m_display) {
996 NHP_SET_STR(nhp, m_display, value);
997 }
998 /* NUTAG_M_USERNAME(m_username) */
999 else if (tag == nutag_m_username) {
1000 NHP_SET_STR(nhp, m_username, value);
1001 }
1002 /* NUTAG_M_PARAMS(m_params) */
1003 else if (tag == nutag_m_params) {
1004 NHP_SET_STR(nhp, m_params, value);
1005 }
1006 /* NUTAG_M_FEATURES(m_features) */
1007 else if (tag == nutag_m_features) {
1008 NHP_SET_STR(nhp, m_features, value);
1009 }
1010 /* NUTAG_OUTBOUND(outbound) */
1011 else if (tag == nutag_outbound) {
1012 NHP_SET_STR(nhp, outbound, value);
1013 }
1014 /* NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) */
1015 else if (tag == ntatag_default_proxy) {
1016 NHP_SET_STR_BY_URL(nhp, url_string_t, proxy, value);
1017 }
1018 /* NUTAG_AUTO_INVITE_100() */
1019 else if (tag == nutag_auto_invite_100) {
1020 NHP_SET(nhp, auto_invite_100, value != 0);
1021 }
1022 /* NUTAG_DETECT_NETWORK_UPDATES(detect_network_updates) */
1023 else if (ngp && tag == nutag_detect_network_updates) {
1024 int detector = (int)value;
1025
1026 if (detector < NUA_NW_DETECT_NOTHING)
1027 detector = NUA_NW_DETECT_NOTHING;
1028 else if (detector > NUA_NW_DETECT_TRY_FULL)
1029 detector = NUA_NW_DETECT_TRY_FULL;
1030
1031 ngp->ngp_detect_network_updates = detector;
1032 ngp->ngp_set.ngp_detect_network_updates = 1;
1033 }
1034 /* NUTAG_SHUTDOWN_EVENTS() */
1035 else if (ngp && tag == nutag_shutdown_events) {
1036 ngp->ngp_shutdown_events = value != 0;
1037 ngp->ngp_set.ngp_shutdown_events = 1;
1038 }
1039 }
1040
1041 return 0;
1042 }
1043
1044 /** Merge (when needed) new values with old values. */
nhp_merge_lists(su_home_t * home,msg_hclass_t * hc,msg_list_t ** return_new_list,msg_list_t const * old_list,int already_set,int already_parsed,int always_merge,tag_value_t value)1045 static int nhp_merge_lists(su_home_t *home,
1046 msg_hclass_t *hc,
1047 msg_list_t **return_new_list,
1048 msg_list_t const *old_list,
1049 int already_set,
1050 int already_parsed,
1051 int always_merge,
1052 tag_value_t value)
1053 {
1054 msg_list_t *list, *elems;
1055
1056 if (value == -1) {
1057 *return_new_list = NULL;
1058 return 1;
1059 }
1060
1061 if (value == 0) {
1062 if (!already_set && !always_merge) {
1063 *return_new_list = NULL;
1064 return 1;
1065 }
1066 return 0;
1067 }
1068
1069 if (already_parsed)
1070 elems = (void *)msg_header_dup_as(home, hc, (msg_header_t *)value);
1071 else
1072 elems = (void *)msg_header_make(home, hc, (char const *)value);
1073
1074 if (!elems)
1075 return -1;
1076
1077 list = (msg_list_t *)old_list;
1078
1079 if (!already_set) {
1080 if (always_merge && list) {
1081 list = (void *)msg_header_dup_as(home, hc, (void *)old_list);
1082 if (!list)
1083 return -1;
1084 }
1085 else
1086 list = NULL;
1087 }
1088
1089 if (!list) {
1090 *return_new_list = elems;
1091 return 1;
1092 }
1093
1094 /* Add contents to the new list to the old list */
1095 if (msg_params_join(home, (msg_param_t **)&list->k_items, elems->k_items,
1096 2 /* prune */, 0 /* don't dup */) < 0)
1097 return -1;
1098
1099 *return_new_list =
1100 (msg_list_t *)msg_header_dup_as(home, hc, (msg_header_t *)list);
1101 if (!*return_new_list)
1102 return -1;
1103
1104 msg_header_free(home, (msg_header_t *)list);
1105 msg_header_free(home, (msg_header_t *)elems);
1106
1107 return 1;
1108 }
1109
1110 /** Save parameters in @a gtmp and @a tmp.
1111 *
1112 * @retval 1 - parameters were changed
1113 * @retval 0 - no changes in parameters
1114 * @retval -1 - an error
1115 */
1116 static
nhp_save_params(nua_handle_t * nh,su_home_t * tmphome,nua_global_preferences_t * gsrc,nua_handle_preferences_t * src)1117 int nhp_save_params(nua_handle_t *nh,
1118 su_home_t *tmphome,
1119 nua_global_preferences_t *gsrc,
1120 nua_handle_preferences_t *src)
1121 {
1122 su_home_t *home = nh->nh_home;
1123 nua_t *nua = nh->nh_nua;
1124 nua_handle_t *dnh = nua->nua_dhandle;
1125 nua_handle_preferences_t *dst, old[1];
1126
1127 if (gsrc) {
1128 *nua->nua_prefs = *gsrc; /* No pointers this far */
1129 }
1130
1131 if (!NHP_IS_ANY_SET(src))
1132 return 0;
1133
1134 if (nh == dnh || nh->nh_prefs != dnh->nh_prefs) {
1135 dst = nh->nh_prefs, *old = *dst;
1136 }
1137 else {
1138 dst = su_zalloc(home, sizeof *dst), memset(old, 0, sizeof *old);
1139 if (!dst)
1140 return -1;
1141 }
1142
1143 /* Move allocations from tmphome to home */
1144 su_home_move(nh->nh_home, tmphome);
1145
1146 /* Copy parameters that are set from src to dst */
1147 nhp_or_set(dst, src);
1148
1149 /* Handle pointer items. Free changed ones and zap unset ones. */
1150 /* Note that pointer items where !NHP_ISSET(old, pref) are not freed
1151 (because they were just on loan from the default preference set) */
1152 #define NHP_ZAP_OVERRIDEN(old, dst, free, pref) \
1153 (((NHP_ISSET(old, pref) && \
1154 (old)->nhp_##pref && (old)->nhp_##pref != (dst)->nhp_##pref) \
1155 ? (free)(home, (void *)(old)->nhp_##pref) : (void)0), \
1156 (void)(!(dst)->nhp_set.nhb_##pref ? (dst)->nhp_##pref = NULL : NULL))
1157
1158 NHP_ZAP_OVERRIDEN(old, dst, su_free, soa_name);
1159 NHP_ZAP_OVERRIDEN(old, dst, su_free, registrar);
1160 NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, allow);
1161 NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, supported);
1162 NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, allow_events);
1163 NHP_ZAP_OVERRIDEN(old, dst, su_free, user_agent);
1164 NHP_ZAP_OVERRIDEN(old, dst, su_free, organization);
1165 NHP_ZAP_OVERRIDEN(old, dst, su_free, via);
1166 NHP_ZAP_OVERRIDEN(old, dst, su_free, m_display);
1167 NHP_ZAP_OVERRIDEN(old, dst, su_free, m_username);
1168 NHP_ZAP_OVERRIDEN(old, dst, su_free, m_params);
1169 NHP_ZAP_OVERRIDEN(old, dst, su_free, m_features);
1170 NHP_ZAP_OVERRIDEN(old, dst, su_free, instance);
1171 NHP_ZAP_OVERRIDEN(old, dst, su_free, outbound);
1172 NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, appl_method);
1173 NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, initial_route);
1174
1175 nh->nh_prefs = dst;
1176
1177 return memcmp(dst, old, sizeof *dst) != 0;
1178 }
1179
1180 static int nua_handle_tags_filter(tagi_t const *f, tagi_t const *t);
1181 static int nua_handle_param_filter(tagi_t const *f, tagi_t const *t);
1182
1183 /** Save taglist to a handle */
nua_handle_save_tags(nua_handle_t * nh,tagi_t * tags)1184 int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags)
1185 {
1186 /* Initialization parameters */
1187 url_string_t const *url = NULL;
1188 sip_to_t const *p_to = NULL;
1189 char const *to_str = NULL;
1190 sip_from_t const *p_from = NULL;
1191 char const *from_str = NULL;
1192 nua_handle_t *identity = NULL;
1193
1194 tagi_t const *t;
1195
1196 su_home_t tmphome[SU_HOME_AUTO_SIZE(1024)];
1197
1198 int error;
1199
1200 #if HAVE_OPEN_C
1201 /* Nice. An old symbian compiler */
1202 tagi_t tagfilter[2];
1203 tagi_t paramfilter[2];
1204
1205 tagfilter[0].t_tag = tag_filter;
1206 tagfilter[0].t_value = tag_filter_v(nua_handle_tags_filter);
1207 tagfilter[1].t_tag = (tag_type_t)0;
1208 tagfilter[1].t_value = (tag_value_t)0;
1209
1210 paramfilter[0].t_tag = tag_filter;
1211 paramfilter[0].t_value = tag_filter_v(nua_handle_param_filter);
1212 paramfilter[1].t_tag = (tag_type_t)0;
1213 paramfilter[1].t_value = (tag_value_t)0;
1214
1215 #else
1216 tagi_t const tagfilter[] = {
1217 { TAG_FILTER(nua_handle_tags_filter) },
1218 { TAG_NULL() }
1219 };
1220 tagi_t const paramfilter[] = {
1221 { TAG_FILTER(nua_handle_param_filter) },
1222 { TAG_NULL() }
1223 };
1224 #endif
1225
1226 for (t = tags; t; t = tl_next(t)) {
1227 if (t->t_tag == NULL)
1228 break;
1229 /* SIPTAG_FROM_REF(p_from) */
1230 else if (t->t_tag == siptag_from) {
1231 p_from = (sip_from_t *)t->t_value, from_str = NULL;
1232 }
1233 /* SIPTAG_FROM_STR_REF(from_str) */
1234 else if (t->t_tag == siptag_from_str) {
1235 from_str = (char const *)t->t_value, p_from = NULL;
1236 }
1237 /* SIPTAG_TO_REF(p_to) */
1238 else if (t->t_tag == siptag_to) {
1239 p_to = (sip_to_t *)t->t_value, to_str = NULL;
1240 }
1241 /* SIPTAG_TO_STR_REF(to_str) */
1242 else if (t->t_tag == siptag_to_str) {
1243 to_str = (char const *)t->t_value, p_to = NULL;
1244 }
1245 /* NUTAG_IDENTITY_REF(identity) */
1246 else if (t->t_tag == nutag_identity) {
1247 identity = (nua_handle_t *)t->t_value;
1248 }
1249 /* NUTAG_URL_REF(url) */
1250 else if (t->t_tag == nutag_url) {
1251 url = (url_string_t *)t->t_value;
1252 }
1253 /* NUTAG_SIPS_URL_REF(url) */
1254 else if (t->t_tag == nutag_sips_url) {
1255 url = (url_string_t *)t->t_value;
1256 }
1257 /* NUTAG_WS_URL_REF(url) */
1258 else if (t->t_tag == nutag_ws_url) {
1259 url = (url_string_t *)t->t_value;
1260 }
1261 /* NUTAG_WSS_URL_REF(url) */
1262 else if (t->t_tag == nutag_wss_url) {
1263 url = (url_string_t *)t->t_value;
1264 }
1265 }
1266
1267 su_home_auto(tmphome, sizeof tmphome);
1268
1269 if (p_from)
1270 ;
1271 else if (from_str)
1272 p_from = sip_from_make(tmphome, from_str);
1273 else
1274 p_from = SIP_NONE;
1275
1276 if (p_to)
1277 ;
1278 else if (to_str)
1279 p_to = sip_to_make(tmphome, to_str);
1280 else if (url)
1281 p_to = sip_to_create(tmphome, url),
1282 p_to ? sip_aor_strip((url_t*)p_to->a_url) : 0;
1283 else
1284 p_to = SIP_NONE;
1285
1286 if (p_to == NULL || p_from == NULL) {
1287 su_home_deinit(tmphome);
1288 return -1;
1289 }
1290
1291 nh->nh_tags =
1292 tl_filtered_tlist(nh->nh_home, tagfilter,
1293 TAG_IF(p_from != SIP_NONE, SIPTAG_FROM(p_from)),
1294 TAG_IF(p_from != SIP_NONE, TAG_FILTER(nua_handle_tags_filter)),
1295 TAG_IF(p_to != SIP_NONE, SIPTAG_TO(p_to)),
1296 TAG_IF(p_to != SIP_NONE, TAG_FILTER(nua_handle_tags_filter)),
1297 TAG_NEXT(tags));
1298
1299 nh->nh_ptags =
1300 tl_filtered_tlist(nh->nh_home, paramfilter, TAG_NEXT(tags));
1301
1302 error = nh->nh_tags == NULL || nh->nh_ptags == NULL;
1303
1304 if (!error)
1305 tl_gets(nh->nh_tags, /* These does not change while nh lives */
1306 SIPTAG_FROM_REF(nh->nh_ds->ds_local),
1307 SIPTAG_TO_REF(nh->nh_ds->ds_remote),
1308 TAG_END());
1309
1310 if (nh->nh_ptags && nh->nh_ptags->t_tag == NULL)
1311 su_free(nh->nh_home, nh->nh_ptags), nh->nh_ptags = NULL;
1312
1313 if (identity)
1314 nh->nh_identity = nua_handle_ref(identity);
1315
1316 su_home_deinit(tmphome);
1317
1318 return -error;
1319 }
1320
1321 /** Filter tags used for settings. */
nua_handle_param_filter(tagi_t const * f,tagi_t const * t)1322 static int nua_handle_param_filter(tagi_t const *f, tagi_t const *t)
1323 {
1324 char const *ns;
1325
1326 if (!t || !t->t_tag)
1327 return 0;
1328
1329 if (t->t_tag == nutag_url ||
1330 t->t_tag == nutag_sips_url ||
1331 t->t_tag == nutag_ws_url ||
1332 t->t_tag == nutag_wss_url ||
1333 t->t_tag == nutag_identity)
1334 return 0;
1335
1336 ns = t->t_tag->tt_ns;
1337 if (!ns)
1338 return 0;
1339
1340 return strcmp(ns, "nua") == 0 || strcmp(ns, "soa") == 0;
1341 }
1342
1343 /** Filter tags stored permanently as taglist. */
nua_handle_tags_filter(tagi_t const * f,tagi_t const * t)1344 static int nua_handle_tags_filter(tagi_t const *f, tagi_t const *t)
1345 {
1346 tag_type_t tag;
1347
1348 if (!t || !t->t_tag)
1349 return 0;
1350
1351 tag = t->t_tag;
1352
1353 if (tag == tag_filter)
1354 return 0;
1355
1356 /* Accept @From or @To only when they are followed by
1357 TAG_FILTER(nua_handle_tags_filter) */
1358 if (tag == siptag_from || tag == siptag_to) {
1359 t = tl_next(t);
1360 return t && t->t_tag == tag_filter &&
1361 t->t_value == (tag_value_t)nua_handle_tags_filter;
1362 }
1363
1364 if (tag == nutag_identity)
1365 return 0;
1366 if (tag == siptag_from_str)
1367 return 0;
1368 if (tag == siptag_to_str)
1369 return 0;
1370
1371 /** Ignore @CSeq, @RSeq, @RAck, @Timestamp, and @ContentLength */
1372 if (tag == siptag_cseq || tag == siptag_cseq_str)
1373 return 0;
1374 if (tag == siptag_rseq || tag == siptag_rseq_str)
1375 return 0;
1376 if (tag == siptag_rack || tag == siptag_rack_str)
1377 return 0;
1378 if (tag == siptag_timestamp || tag == siptag_timestamp_str)
1379 return 0;
1380 if (tag == siptag_content_length || tag == siptag_content_length_str)
1381 return 0;
1382
1383 return ! nua_handle_param_filter(f, t);
1384 }
1385
1386 static
nua_stack_set_smime_params(nua_t * nua,tagi_t const * tags)1387 int nua_stack_set_smime_params(nua_t *nua, tagi_t const *tags)
1388 {
1389 #if HAVE_SOFIA_SMIME
1390 int smime_enable = nua->sm->sm_enable;
1391 int smime_opt = nua->sm->sm_opt;
1392 int smime_protection_mode = nua->sm->sm_protection_mode;
1393 char const *smime_message_digest = NONE;
1394 char const *smime_signature = NONE;
1395 char const *smime_key_encryption = NONE;
1396 char const *smime_message_encryption = NONE;
1397 char const *smime_path = NONE;
1398
1399 int n;
1400
1401 n = tl_gets(tags,
1402 NUTAG_SMIME_ENABLE_REF(smime_enable),
1403 NUTAG_SMIME_OPT_REF(smime_opt),
1404 NUTAG_SMIME_PROTECTION_MODE_REF(smime_protection_mode),
1405 NUTAG_SMIME_MESSAGE_DIGEST_REF(smime_message_digest),
1406 NUTAG_SMIME_SIGNATURE_REF(smime_signature),
1407 NUTAG_SMIME_KEY_ENCRYPTION_REF(smime_key_encryption),
1408 NUTAG_SMIME_MESSAGE_ENCRYPTION_REF(smime_message_encryption),
1409 NUTAG_CERTIFICATE_DIR_REF(smime_path),
1410 TAG_NULL());
1411 if (n <= 0)
1412 return n;
1413
1414 /* XXX - all other S/MIME parameters? */
1415 return sm_set_params(nua->sm, smime_enable, smime_opt,
1416 smime_protection_mode, smime_path);
1417 #endif
1418
1419 return 0;
1420 }
1421
1422 /**@fn void nua_get_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...)
1423 *
1424 * Get NUA parameters matching with the given filter.
1425 * The values of NUA parameters is returned in #nua_r_get_params event.
1426 *
1427 * @param nua Pointer to NUA stack object
1428 * @param tag, value, ... List of tagged parameters
1429 *
1430 * @return
1431 * nothing
1432 *
1433 * @par Related tags:
1434 * TAG_ANY() \n
1435 * otherwise same tags as nua_set_params()
1436 *
1437 * @par Events:
1438 * #nua_r_get_params
1439 *
1440 * @par Examples
1441 * Find out default values of all parameters:
1442 * @code
1443 * nua_get_params(nua, TAG_ANY(), TAG_END());
1444 * @endcode
1445 */
1446
1447 /**@fn void nua_get_hparams(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
1448 *
1449 * Get values of handle-specific parameters in #nua_r_get_params event.
1450 *
1451 * Application will specify either expilicit list of tags it is interested
1452 * in, or a filter (at the moment, TAG_ANY()). The values are returned as a
1453 * list of tags in the #nua_r_get_params event.
1454 *
1455 * @param nh Pointer to operation handle
1456 * @param tag, value, ... List of tagged parameters
1457 *
1458 * The handle-specific parameters will contain only the parameters actually
1459 * modified by application, either by nua_set_hparams() or some other
1460 * handle-specific call. Currently, no NTA parameters are returned. They are
1461 * returned only when application asks for user-agent-level parameters using
1462 * either nua_get_params() or using default handle, eg.
1463 * @code
1464 * nua_get_hparams(nua_default(nua), TAG_ANY())
1465 * @endcode
1466 *
1467 * @return
1468 * nothing
1469 *
1470 * @par Related tags:
1471 * #TAG_ANY \n
1472 * othervise same tags as nua_set_hparams()
1473 *
1474 * @par Events:
1475 * #nua_r_get_params
1476 */
1477
1478 /** @NUA_EVENT nua_r_get_params
1479 *
1480 * Answer to nua_get_params() or nua_get_hparams().
1481 *
1482 * @param status 200 when succesful, error code otherwise
1483 * @param phrase a short textual description of @a status code
1484 * @param nh NULL when responding to nua_get_params(),
1485 * operation handle when responding to nua_get_hparams()
1486 * @param hmagic NULL when responding to nua_get_params(),
1487 * application contact associated with the operation handle
1488 * when responding to nua_get_hparams()
1489 * @param sip NULL
1490 * @param tags
1491 * NUTAG_APPL_METHOD() \n
1492 * NUTAG_AUTH_CACHE() \n
1493 * NUTAG_AUTOACK() \n
1494 * NUTAG_AUTOALERT() \n
1495 * NUTAG_AUTOANSWER() \n
1496 * NUTAG_CALLEE_CAPS() \n
1497 * NUTAG_DETECT_NETWORK_UPDATES() \n
1498 * NUTAG_EARLY_ANSWER() \n
1499 * NUTAG_EARLY_MEDIA() \n
1500 * NUTAG_ENABLEINVITE() \n
1501 * NUTAG_ENABLEMESSAGE() \n
1502 * NUTAG_ENABLEMESSENGER() \n
1503 * NUTAG_INITIAL_ROUTE() \n
1504 * NUTAG_INITIAL_ROUTE_STR() \n
1505 * NUTAG_INSTANCE() \n
1506 * NUTAG_INVITE_TIMER() \n
1507 * NUTAG_KEEPALIVE() \n
1508 * NUTAG_KEEPALIVE_STREAM() \n
1509 * NUTAG_MAX_SUBSCRIPTIONS() \n
1510 * NUTAG_MEDIA_ENABLE() \n
1511 * NUTAG_MEDIA_FEATURES() \n
1512 * NUTAG_MIN_SE() \n
1513 * NUTAG_M_DISPLAY() \n
1514 * NUTAG_M_FEATURES() \n
1515 * NUTAG_M_PARAMS() \n
1516 * NUTAG_M_USERNAME() \n
1517 * NUTAG_ONLY183_100REL() \n
1518 * NUTAG_OUTBOUND() \n
1519 * NUTAG_PATH_ENABLE() \n
1520 * NUTAG_RETRY_AFTER_ENABLE() \n
1521 * NUTAG_REFER_EXPIRES() \n
1522 * NUTAG_REFER_WITH_ID() \n
1523 * NUTAG_REFRESH_WITHOUT_SDP() \n
1524 * NUTAG_REGISTRAR() \n
1525 * NUTAG_RETRY_COUNT() \n
1526 * NUTAG_SERVICE_ROUTE_ENABLE() \n
1527 * NUTAG_SESSION_REFRESHER() \n
1528 * NUTAG_SESSION_TIMER() \n
1529 * NUTAG_SMIME_ENABLE() \n
1530 * NUTAG_SMIME_KEY_ENCRYPTION() \n
1531 * NUTAG_SMIME_MESSAGE_DIGEST() \n
1532 * NUTAG_SMIME_MESSAGE_ENCRYPTION() \n
1533 * NUTAG_SMIME_OPT() \n
1534 * NUTAG_SMIME_PROTECTION_MODE() \n
1535 * NUTAG_SMIME_SIGNATURE() \n
1536 * NUTAG_SOA_NAME() \n
1537 * NUTAG_SUBSTATE() \n
1538 * NUTAG_SUB_EXPIRES() \n
1539 * NUTAG_UPDATE_REFRESH() \n
1540 * NUTAG_USER_AGENT() \n
1541 * SIPTAG_ALLOW() \n
1542 * SIPTAG_ALLOW_STR() \n
1543 * SIPTAG_ALLOW_EVENTS() \n
1544 * SIPTAG_ALLOW_EVENTS_STR() \n
1545 * SIPTAG_FROM() \n
1546 * SIPTAG_FROM_STR() \n
1547 * SIPTAG_ORGANIZATION() \n
1548 * SIPTAG_ORGANIZATION_STR() \n
1549 * SIPTAG_SUPPORTED() \n
1550 * SIPTAG_SUPPORTED_STR() \n
1551 * SIPTAG_USER_AGENT() \n
1552 * SIPTAG_USER_AGENT_STR() \n
1553 *
1554 * @sa nua_get_params(), nua_get_hparams(),
1555 * nua_set_params(), nua_set_hparams(), #nua_r_set_params
1556 *
1557 * @END_NUA_EVENT
1558 */
1559
1560 /**@internal
1561 * Send a list of NUA parameters to the application.
1562 *
1563 * This function gets invoked when application calls either nua_get_params()
1564 * or nua_get_hparams().
1565 *
1566 * The parameter tag list will initially contain all the relevant parameter
1567 * tags, and it will be filtered down to parameters asked by application.
1568 *
1569 * The handle-specific parameters will contain only the parameters actually
1570 * modified by application, either by nua_set_hparams() or some other
1571 * handle-specific call. NTA parameters are returned only when application
1572 * asks for user-agent-level parameters using nua_get_params().
1573 *
1574 */
nua_stack_get_params(nua_t * nua,nua_handle_t * nh,nua_event_t e,tagi_t const * tags)1575 int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
1576 tagi_t const *tags)
1577 {
1578 nua_handle_t *dnh = nua->nua_dhandle;
1579 nua_global_preferences_t const *ngp = nua->nua_prefs;
1580 nua_handle_preferences_t const *nhp = nh->nh_prefs;
1581 nua_handle_preferences_t const nhp_zero[1] = {{ 0 }};
1582 tagi_t *lst;
1583
1584 int has_from;
1585 sip_from_t from[1];
1586
1587 sip_contact_t const *m;
1588
1589 /* nta */
1590 unsigned udp_mtu = 0;
1591 usize_t max_proceeding = 0;
1592 unsigned sip_t1 = 0, sip_t2 = 0, sip_t4 = 0, sip_t1x64 = 0;
1593 unsigned debug_drop_prob = 0;
1594 url_string_t const *proxy = NULL;
1595 sip_contact_t const *aliases = NULL;
1596 unsigned flags = 0;
1597
1598 /* soa */
1599 tagi_t *media_params = NULL;
1600
1601 su_home_t tmphome[SU_HOME_AUTO_SIZE(16536)];
1602
1603 enter;
1604
1605 if (nh == dnh)
1606 nta_agent_get_params(nua->nua_nta,
1607 NTATAG_UDP_MTU_REF(udp_mtu),
1608 NTATAG_MAX_PROCEEDING_REF(max_proceeding),
1609 NTATAG_SIP_T1_REF(sip_t1),
1610 NTATAG_SIP_T2_REF(sip_t2),
1611 NTATAG_SIP_T4_REF(sip_t4),
1612 NTATAG_SIP_T1X64_REF(sip_t1x64),
1613 NTATAG_DEBUG_DROP_PROB_REF(debug_drop_prob),
1614 NTATAG_DEFAULT_PROXY_REF(proxy),
1615 NTATAG_ALIASES_REF(aliases),
1616 NTATAG_SIPFLAGS_REF(flags),
1617 TAG_END());
1618
1619 if (nh->nh_ds->ds_local)
1620 has_from = 1, *from = *nh->nh_ds->ds_local, from->a_params = NULL;
1621 else /* if (nua->nua_from_is_set) */
1622 has_from = 1, *from = *nua->nua_from;
1623
1624 media_params = soa_get_paramlist(nh->nh_soa, TAG_END());
1625
1626 m = nua_stack_get_contact(nua->nua_registrations);
1627
1628 /* Include tag in the list returned to user
1629 * if it has been earlier set (by user) */
1630 #define TIF(TAG, pref) \
1631 TAG_IF(nhp->nhp_set.nhb_##pref, TAG(nhp->nhp_##pref))
1632
1633 /* Include tag in the list returned to user
1634 * if it has been earlier set (by user)
1635 * but always include in the default parameters */
1636 #define TIFD(TAG, pref) \
1637 TAG_IF(nh == dnh || nhp->nhp_set.nhb_##pref, TAG(nhp->nhp_##pref))
1638
1639 /* Include string tag made out of SIP header
1640 * if it has been earlier set (by user) */
1641 #define TIF_STR(TAG, pref) \
1642 TAG_IF(nhp->nhp_set.nhb_##pref, \
1643 TAG(nhp->nhp_set.nhb_##pref && nhp->nhp_##pref \
1644 ? sip_header_as_string(tmphome, (void *)nhp->nhp_##pref) : NULL))
1645
1646 /* Include header tag made out of string
1647 * if it has been earlier set (by user) */
1648 #define TIF_SIP(TAG, pref) \
1649 TAG_IF(nhp->nhp_set.nhb_##pref, \
1650 TAG(nhp->nhp_set.nhb_##pref && nhp->nhp_##pref \
1651 ? sip_##pref##_make(tmphome, (char *)nhp->nhp_##pref) \
1652 : NULL))
1653
1654 if (nh != dnh && nhp == dnh->nh_prefs)
1655 nhp = nhp_zero;
1656
1657 su_home_auto(tmphome, sizeof(tmphome));
1658
1659 lst = tl_filtered_tlist
1660 (tmphome, tags,
1661 TAG_IF(has_from, SIPTAG_FROM(from)),
1662 TAG_IF(has_from,
1663 SIPTAG_FROM_STR(has_from
1664 ? sip_header_as_string(tmphome, (void *)from)
1665 : NULL)),
1666
1667 TIF(NUTAG_RETRY_COUNT, retry_count),
1668 TIF(NUTAG_MAX_SUBSCRIPTIONS, max_subscriptions),
1669
1670 TIF(NUTAG_SOA_NAME, soa_name),
1671 TIF(NUTAG_MEDIA_ENABLE, media_enable),
1672 TIF(NUTAG_ENABLEINVITE, invite_enable),
1673 TIF(NUTAG_AUTOALERT, auto_alert),
1674 TIF(NUTAG_EARLY_ANSWER, early_answer),
1675 TIF(NUTAG_EARLY_MEDIA, early_media),
1676 TIF(NUTAG_ONLY183_100REL, only183_100rel),
1677 TIF(NUTAG_AUTOANSWER, auto_answer),
1678 TIF(NUTAG_AUTOACK, auto_ack),
1679 TIF(NUTAG_TIMER_AUTOREQUIRE, timer_autorequire),
1680 TIF(NUTAG_INVITE_TIMER, invite_timeout),
1681
1682 TIFD(NUTAG_SESSION_TIMER, session_timer),
1683 TIF(NUTAG_MIN_SE, min_se),
1684 TIFD(NUTAG_SESSION_REFRESHER, refresher),
1685 TIF(NUTAG_UPDATE_REFRESH, update_refresh),
1686 TIF(NUTAG_REFRESH_WITHOUT_SDP, refresh_without_sdp),
1687
1688 TIF(NUTAG_ENABLEMESSAGE, message_enable),
1689 TIF(NUTAG_ENABLEMESSENGER, win_messenger_enable),
1690 /* TIF(NUTAG_AUTORESPOND, autorespond), */
1691
1692 TIF(NUTAG_CALLEE_CAPS, callee_caps),
1693 TIF(NUTAG_MEDIA_FEATURES, media_features),
1694 TIF(NUTAG_SERVICE_ROUTE_ENABLE, service_route_enable),
1695 TIF(NUTAG_PATH_ENABLE, path_enable),
1696 TIF(NUTAG_RETRY_AFTER_ENABLE, retry_after_enable),
1697 TIF(NUTAG_AUTH_CACHE, auth_cache),
1698 TIF(NUTAG_REFER_EXPIRES, refer_expires),
1699 TIF(NUTAG_REFER_WITH_ID, refer_with_id),
1700
1701 TIF(NUTAG_SUBSTATE, substate),
1702 TIF(NUTAG_SUB_EXPIRES, sub_expires),
1703
1704 TIF(SIPTAG_SUPPORTED, supported),
1705 TIF_STR(SIPTAG_SUPPORTED_STR, supported),
1706 TIF(SIPTAG_ALLOW, allow),
1707 TIF_STR(SIPTAG_ALLOW_STR, allow),
1708 TIF_STR(NUTAG_APPL_METHOD, appl_method),
1709 TIF(SIPTAG_ALLOW_EVENTS, allow_events),
1710 TIF_STR(SIPTAG_ALLOW_EVENTS_STR, allow_events),
1711 TIF_SIP(SIPTAG_USER_AGENT, user_agent),
1712 TIF(SIPTAG_USER_AGENT_STR, user_agent),
1713 TIF(NUTAG_USER_AGENT, user_agent),
1714
1715 TIF_SIP(SIPTAG_ORGANIZATION, organization),
1716 TIF(SIPTAG_ORGANIZATION_STR, organization),
1717
1718 TIF_SIP(SIPTAG_VIA, via),
1719 TIF(SIPTAG_VIA_STR, via),
1720
1721 TIF(NUTAG_INITIAL_ROUTE, initial_route),
1722 TIF_STR(NUTAG_INITIAL_ROUTE_STR, initial_route),
1723
1724 TIF(NUTAG_REGISTRAR, registrar),
1725 TIF(NUTAG_KEEPALIVE, keepalive),
1726 TIF(NUTAG_KEEPALIVE_STREAM, keepalive_stream),
1727
1728 TIF(NUTAG_INSTANCE, instance),
1729 TIF(NUTAG_M_DISPLAY, m_display),
1730 TIF(NUTAG_M_USERNAME, m_username),
1731 TIF(NUTAG_M_PARAMS, m_params),
1732 TIF(NUTAG_M_FEATURES, m_features),
1733 TIF(NUTAG_OUTBOUND, outbound),
1734
1735 /* Handle-specific proxy */
1736 TAG_IF(nh != dnh && nhp->nhp_set.nhb_proxy,
1737 NUTAG_PROXY(nhp->nhp_proxy)),
1738
1739 /* Skip user-agent-level parameters if parameters are for handle only */
1740 TAG_IF(nh != dnh, TAG_NEXT(media_params)),
1741
1742 /* Include tag in the list returned to user
1743 * if it has been earlier set (by user) */
1744 #define GIF(TAG, pref) \
1745 TAG_IF(ngp->ngp_set.ngp_##pref, TAG(ngp->ngp_##pref))
1746
1747 GIF(NUTAG_DETECT_NETWORK_UPDATES, detect_network_updates),
1748 GIF(NUTAG_SHUTDOWN_EVENTS, shutdown_events),
1749
1750 NTATAG_CONTACT(m),
1751
1752 #if HAVE_SOFIA_SMIME
1753 NUTAG_SMIME_ENABLE(nua->sm->sm_enable),
1754 NUTAG_SMIME_OPT(nua->sm->sm_opt),
1755 NUTAG_SMIME_PROTECTION_MODE(nua->sm->sm_protection_mode),
1756 NUTAG_SMIME_MESSAGE_DIGEST(nua->sm->sm_message_digest),
1757 NUTAG_SMIME_SIGNATURE(nua->sm->sm_signature),
1758 NUTAG_SMIME_KEY_ENCRYPTION(nua->sm->sm_key_encryption),
1759 NUTAG_SMIME_MESSAGE_ENCRYPTION(nua->sm->sm_message_encryption),
1760 #endif
1761
1762 NTATAG_UDP_MTU(udp_mtu),
1763 NTATAG_MAX_PROCEEDING(max_proceeding),
1764 NTATAG_SIP_T1(sip_t1),
1765 NTATAG_SIP_T2(sip_t2),
1766 NTATAG_SIP_T4(sip_t4),
1767 NTATAG_SIP_T1X64(sip_t1x64),
1768 NTATAG_DEBUG_DROP_PROB(debug_drop_prob),
1769 /* Stack-wide proxy */
1770 NTATAG_DEFAULT_PROXY(proxy),
1771 NTATAG_ALIASES(aliases),
1772 NTATAG_SIPFLAGS(flags),
1773
1774 TAG_NEXT(media_params));
1775
1776 nua_stack_event(nua, nh, NULL, nua_r_get_params, SIP_200_OK, lst);
1777
1778 su_home_deinit(tmphome);
1779
1780 tl_vfree(media_params);
1781
1782 return 0;
1783 }
1784