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