sip_feature.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /*
  2. * This file is part of the Sofia-SIP package
  3. *
  4. * Copyright (C) 2005 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. /**@CFILE sip_feature.c
  25. *
  26. * @brief Feature-related SIP header handling
  27. *
  28. * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
  29. *
  30. * @date Created: Tue Jun 13 02:57:51 2000 ppessi
  31. */
  32. #include "config.h"
  33. /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */
  34. #define MSG_PUB_T struct sip_s
  35. #define MSG_HDR_T union sip_header_u
  36. #include "sofia-sip/sip_parser.h"
  37. #include <stdio.h>
  38. #include <stddef.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <assert.h>
  42. /* ====================================================================== */
  43. /**@SIP_HEADER sip_allow Allow Header
  44. *
  45. * The Allow header lists the set of methods supported by the user agent
  46. * generating the message. Its syntax is defined in @RFC3261 as
  47. * follows:
  48. *
  49. * @code
  50. * Allow = "Allow" HCOLON [Method *(COMMA Method)]
  51. * @endcode
  52. *
  53. * The parsed Allow header is stored in #sip_allow_t structure.
  54. *
  55. * Note that SIP methods are case-sensitive: "INVITE" method is different from
  56. * "Invite".
  57. *
  58. * @sa msg_header_find_item(), msg_header_replace_item(),
  59. * msg_header_remove_item()
  60. */
  61. /**@ingroup sip_allow
  62. * @typedef struct msg_list_s sip_allow_t;
  63. *
  64. * The structure #sip_allow_t contains representation of an @Allow header.
  65. *
  66. * The #sip_allow_t is defined as follows:
  67. * @code
  68. * typedef struct msg_allow_s
  69. * {
  70. * msg_common_t k_common[1]; // Common fragment info
  71. * msg_list_t *k_next; // Link to next header
  72. * msg_param_t *k_items; // List of items
  73. * uint32_t k_bitmap; // Bitmap of allowed methods
  74. * } sip_allow_t;
  75. * @endcode
  76. *
  77. * @note The field @a k_bitmap was added in @VERSION_1_12_5.
  78. */
  79. #define sip_allow_dup_xtra msg_list_dup_xtra
  80. #define sip_allow_dup_one msg_list_dup_one
  81. static msg_update_f sip_allow_update;
  82. msg_hclass_t sip_allow_class[] =
  83. SIP_HEADER_CLASS(allow, "Allow", "", k_items, list, allow);
  84. issize_t sip_allow_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  85. {
  86. sip_allow_t *k = (sip_allow_t *)h;
  87. issize_t retval = msg_commalist_d(home, &s, &k->k_items, msg_token_scan);
  88. msg_header_update_params(k->k_common, 0);
  89. return retval;
  90. }
  91. issize_t sip_allow_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  92. {
  93. assert(sip_is_allow(h));
  94. return msg_list_e(b, bsiz, h, f);
  95. }
  96. static int sip_allow_update(msg_common_t *h,
  97. char const *name, isize_t namelen,
  98. char const *value)
  99. {
  100. sip_allow_t *k = (sip_allow_t *)h;
  101. if (name == NULL) {
  102. k->k_bitmap = 0;
  103. }
  104. else {
  105. int method = (int)sip_method_code(name);
  106. if (method >= 0 && method < 32)
  107. k->k_bitmap |= 1 << method;
  108. }
  109. return 0;
  110. }
  111. /** Return true if the method is listed in @Allow header. */
  112. int sip_is_allowed(sip_allow_t const *allow,
  113. sip_method_t method,
  114. char const *name)
  115. {
  116. int meth = method;
  117. if (meth < sip_method_unknown || !allow)
  118. return 0;
  119. if (sip_method_unknown < meth && meth < 32)
  120. /* Well-known method */
  121. return (allow->k_bitmap & (1 << meth)) != 0;
  122. if (meth == sip_method_unknown &&
  123. (allow->k_bitmap & (1 << sip_method_unknown)) == 0)
  124. return 0;
  125. return msg_header_find_item(allow->k_common, name) != NULL;
  126. }
  127. /* ====================================================================== */
  128. /**@SIP_HEADER sip_proxy_require Proxy-Require Header
  129. *
  130. * The Proxy-Require header is used to indicate proxy-sensitive features
  131. * that @b MUST be supported by the proxy. Its syntax is defined in @RFC3261
  132. * as follows:
  133. *
  134. * @code
  135. * Proxy-Require = "Proxy-Require" HCOLON option-tag *(COMMA option-tag)
  136. * @endcode
  137. *
  138. *
  139. * The parsed Proxy-Require header is stored in #sip_proxy_require_t structure.
  140. */
  141. /**@ingroup sip_proxy_require
  142. * @typedef struct msg_list_s sip_proxy_require_t;
  143. *
  144. * The structure #sip_proxy_require_t contains representation of an
  145. * @ProxyRequire header.
  146. *
  147. * The #sip_proxy_require_t is defined as follows:
  148. * @code
  149. * typedef struct msg_list_s
  150. * {
  151. * msg_common_t k_common[1]; // Common fragment info
  152. * msg_list_t *k_next; // Dummy link
  153. * msg_param_t *k_items; // List of items
  154. * } sip_proxy_require_t;
  155. * @endcode
  156. */
  157. msg_hclass_t sip_proxy_require_class[] =
  158. SIP_HEADER_CLASS_LIST(proxy_require, "Proxy-Require", "", list);
  159. issize_t sip_proxy_require_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  160. {
  161. sip_proxy_require_t *k = (sip_proxy_require_t *)h;
  162. return msg_commalist_d(home, &s, &k->k_items, msg_token_scan);
  163. }
  164. issize_t sip_proxy_require_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  165. {
  166. assert(sip_is_proxy_require(h));
  167. return msg_list_e(b, bsiz, h, f);
  168. }
  169. /* ====================================================================== */
  170. /**@SIP_HEADER sip_require Require Header
  171. *
  172. * The Require header is used by clients to tell user agent servers about
  173. * options that the client expects the server to support in order to
  174. * properly process the request. Its syntax is defined in @RFC3261
  175. * as follows:
  176. *
  177. * @code
  178. * Require = "Require" HCOLON option-tag *(COMMA option-tag)
  179. * @endcode
  180. *
  181. * The parsed Require header is stored in #sip_require_t structure.
  182. */
  183. /**@ingroup sip_require
  184. * @typedef struct msg_list_s sip_require_t;
  185. *
  186. * The structure #sip_require_t contains representation of an
  187. * @Require header.
  188. *
  189. * The #sip_require_t is defined as follows:
  190. * @code
  191. * typedef struct msg_list_s
  192. * {
  193. * msg_common_t k_common[1]; // Common fragment info
  194. * msg_list_t *k_next; // Link to next header
  195. * msg_param_t *k_items; // List of items
  196. * } sip_require_t;
  197. * @endcode
  198. */
  199. msg_hclass_t sip_require_class[] =
  200. SIP_HEADER_CLASS_LIST(require, "Require", "", list);
  201. issize_t sip_require_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  202. {
  203. sip_require_t *k = (sip_require_t *)h;
  204. return msg_commalist_d(home, &s, &k->k_items, msg_token_scan);
  205. }
  206. issize_t sip_require_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  207. {
  208. assert(sip_is_require(h));
  209. return msg_list_e(b, bsiz, h, f);
  210. }
  211. /* ====================================================================== */
  212. /**@SIP_HEADER sip_supported Supported Header
  213. *
  214. * The Supported header enumerates all the capabilities of the client or
  215. * server. Its syntax is defined in @RFC3261 as follows:
  216. *
  217. * @code
  218. * Supported = ( "Supported" / "k" ) HCOLON
  219. * [option-tag *(COMMA option-tag)]
  220. * @endcode
  221. *
  222. * The parsed option-tags of Supported header
  223. * are stored in #sip_supported_t structure.
  224. */
  225. /**@ingroup sip_supported
  226. * @typedef struct msg_list_s sip_supported_t;
  227. *
  228. * The structure #sip_supported_t contains representation of an
  229. * @Supported header.
  230. *
  231. * The #sip_supported_t is defined as follows:
  232. * @code
  233. * typedef struct msg_list_s
  234. * {
  235. * msg_common_t k_common[1]; // Common fragment info
  236. * msg_list_t *k_next; // Link to next header
  237. * msg_param_t *k_items; // List of items
  238. * } sip_supported_t;
  239. * @endcode
  240. */
  241. msg_hclass_t sip_supported_class[] =
  242. SIP_HEADER_CLASS_LIST(supported, "Supported", "k", list);
  243. issize_t sip_supported_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  244. {
  245. sip_supported_t *k = (sip_supported_t *)h;
  246. return msg_commalist_d(home, &s, &k->k_items, msg_token_scan);
  247. }
  248. issize_t sip_supported_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  249. {
  250. assert(sip_is_supported(h));
  251. return msg_list_e(b, bsiz, h, f);
  252. }
  253. /* ====================================================================== */
  254. /**@SIP_HEADER sip_unsupported Unsupported Header
  255. *
  256. * The Unsupported header lists the features not supported by the server.
  257. * Its syntax is defined in @RFC3261 as follows:
  258. *
  259. * @code
  260. * Unsupported = "Unsupported" HCOLON [option-tag *(COMMA option-tag)]
  261. * @endcode
  262. *
  263. *
  264. * The parsed Unsupported header is stored in #sip_unsupported_t structure.
  265. */
  266. /**@ingroup sip_unsupported
  267. * @typedef struct msg_list_s sip_unsupported_t;
  268. *
  269. * The structure #sip_unsupported_t contains representation of an
  270. * @Unsupported header.
  271. *
  272. * The #sip_unsupported_t is defined as follows:
  273. * @code
  274. * typedef struct msg_list_s
  275. * {
  276. * msg_common_t k_common[1]; // Common fragment info
  277. * msg_list_t *k_next; // Link to next header
  278. * msg_param_t *k_items; // List of items
  279. * } sip_unsupported_t;
  280. * @endcode
  281. */
  282. msg_hclass_t sip_unsupported_class[] =
  283. SIP_HEADER_CLASS_LIST(unsupported, "Unsupported", "", list);
  284. issize_t sip_unsupported_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  285. {
  286. sip_unsupported_t *k = (sip_unsupported_t *)h;
  287. return msg_commalist_d(home, &s, &k->k_items, msg_token_scan);
  288. }
  289. issize_t sip_unsupported_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  290. {
  291. assert(sip_is_unsupported(h));
  292. return msg_list_e(b, bsiz, h, f);
  293. }
  294. /** Check if required feature is not supported.
  295. *
  296. * @retval NULL if all the required features are supported
  297. * @retval pointer to a @Unsupported header or
  298. * #SIP_NONE if @a home is NULL
  299. */
  300. sip_unsupported_t *sip_has_unsupported(su_home_t *home,
  301. sip_supported_t const *support,
  302. sip_require_t const *require)
  303. {
  304. return sip_has_unsupported_any(home, support, NULL, NULL,
  305. require, NULL, NULL);
  306. }
  307. /** Check if required feature is not supported.
  308. *
  309. * @retval NULL if all the required features are supported
  310. * @retval pointer to a @Unsupported header or
  311. * #SIP_NONE if @a home is NULL
  312. */
  313. sip_unsupported_t *
  314. sip_has_unsupported2(su_home_t *home,
  315. sip_supported_t const *support,
  316. sip_require_t const *support_by_require,
  317. sip_require_t const *require)
  318. {
  319. return
  320. sip_has_unsupported_any(home,
  321. support, support_by_require, NULL,
  322. require, NULL, NULL);
  323. }
  324. /** Check if required features are not supported.
  325. *
  326. * The supported features can be listed in @Supported, @Require or
  327. * @ProxyRequire headers (in @a supported, @a by_require, or @a
  328. * by_proxy_require parameters, respectively)
  329. *
  330. * @param home (optional) home pointer for allocating @Unsupported header
  331. * @param supported @Supported features (may be NULL) [IN]
  332. * @param by_require supported features listed by
  333. * @Require (may be NULL) [IN]
  334. * @param by_proxy_require supported features listed
  335. * by @ProxyRequire (may be NULL) [IN]
  336. *
  337. * @param require list of required features (may be NULL) [IN]
  338. * @param require2 2nd list of required features (may be NULL) [IN]
  339. * @param require3 3rd list of required features (may be NULL) [IN]
  340. *
  341. * @retval NULL if all the required features are supported
  342. * @retval pointer to a @Unsupported header or
  343. * #SIP_NONE if @a home is NULL
  344. */
  345. sip_unsupported_t *
  346. sip_has_unsupported_any(su_home_t *home,
  347. sip_supported_t const *supported,
  348. sip_require_t const *by_require,
  349. sip_proxy_require_t const *by_proxy_require,
  350. sip_require_t const *require,
  351. sip_require_t const *require2,
  352. sip_require_t const *require3)
  353. {
  354. size_t i, j;
  355. sip_unsupported_t *unsupported = NULL;
  356. msg_param_t const empty[1] = { NULL };
  357. msg_param_t const *slist = empty;
  358. msg_param_t const *rlist = empty;
  359. msg_param_t const *prlist = empty;
  360. if (require2 == NULL)
  361. require2 = require3, require3 = NULL;
  362. if (require == NULL)
  363. require = require2, require2 = NULL;
  364. if (require && require->k_items) {
  365. if (supported && supported->k_items)
  366. slist = supported->k_items;
  367. if (by_require && by_require->k_items)
  368. rlist = by_require->k_items;
  369. if (by_proxy_require && by_proxy_require->k_items)
  370. prlist = by_proxy_require->k_items;
  371. for (i = 0; require->k_items && require->k_items[i];) {
  372. msg_param_t feature = require->k_items[i++];
  373. for (j = 0; slist[j]; j++)
  374. if (su_casematch(feature, slist[j])) {
  375. feature = NULL;
  376. break;
  377. }
  378. if (feature)
  379. for (j = 0; rlist[j]; j++)
  380. if (su_casematch(feature, rlist[j])) {
  381. feature = NULL;
  382. break;
  383. }
  384. if (feature)
  385. for (j = 0; prlist[j]; j++)
  386. if (su_casematch(feature, prlist[j])) {
  387. feature = NULL;
  388. break;
  389. }
  390. if (feature) {
  391. if (home) {
  392. if (unsupported == NULL)
  393. unsupported = sip_unsupported_make(home, feature);
  394. else
  395. msg_params_add(home,
  396. (msg_param_t **)&unsupported->k_items,
  397. feature);
  398. }
  399. else {
  400. return (sip_unsupported_t *)SIP_NONE;
  401. }
  402. }
  403. if (require->k_items[i] == NULL && require2 && require2->k_items) {
  404. i = 0, require = require2, require2 = require3, require3 = NULL;
  405. }
  406. }
  407. }
  408. return unsupported;
  409. }
  410. int sip_has_feature(msg_list_t const *supported, char const *feature)
  411. {
  412. size_t i;
  413. if (!feature || !feature[0])
  414. return 1; /* Empty feature is always supported */
  415. for (; supported; supported = supported->k_next)
  416. if (supported->k_items)
  417. for (i = 0; supported->k_items[i]; i++)
  418. if (su_casematch(feature, supported->k_items[i]))
  419. return 1;
  420. return 0;
  421. }
  422. /** Check that a feature is supported. */
  423. int sip_has_supported(sip_supported_t const *supported, char const *feature)
  424. {
  425. return sip_has_feature(supported, feature);
  426. }
  427. /* ====================================================================== */
  428. /**@SIP_HEADER sip_path Path Header
  429. *
  430. * The Path header field is a SIP extension header field (@RFC3327) with
  431. * syntax very similar to the @RecordRoute header field. It is used in
  432. * conjunction with SIP REGISTER requests and with 200 class messages in
  433. * response to REGISTER (REGISTER responses).
  434. *
  435. * @code
  436. * Path = "Path" HCOLON path-value *(COMMA path-value)
  437. * path-value = name-addr *( SEMI rr-param )
  438. * @endcode
  439. *
  440. *
  441. * The parsed Path header is stored in #sip_path_t structure.
  442. */
  443. /**@ingroup sip_path
  444. * @typedef typedef struct sip_route_s sip_path_t;
  445. *
  446. * The structure #sip_path_t contains representation of SIP @Path header.
  447. *
  448. * The #sip_path_t is defined as follows:
  449. * @code
  450. * typedef struct sip_route_s {
  451. * sip_common_t r_common[1]; // Common fragment info
  452. * sip_path_t *r_next; // Link to next @Path
  453. * char const *r_display; // Display name
  454. * url_t r_url[1]; // @Path URL
  455. * msg_param_t const *r_params; // List of parameters
  456. * } sip_path_t;
  457. * @endcode
  458. */
  459. msg_hclass_t sip_path_class[] =
  460. SIP_HEADER_CLASS(path, "Path", "", r_params, prepend, any_route);
  461. issize_t sip_path_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  462. {
  463. return sip_any_route_d(home, h, s, slen);
  464. }
  465. issize_t sip_path_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
  466. {
  467. assert(sip_is_path(h));
  468. return sip_any_route_e(b, bsiz, h, flags);
  469. }
  470. /* ====================================================================== */
  471. /**@SIP_HEADER sip_service_route Service-Route Header
  472. *
  473. * The "Service-Route" is a SIP extension header field (@RFC3608), which can
  474. * contain a route vector that will direct requests through a specific
  475. * sequence of proxies. A registrar may use a Service-Route header field to
  476. * inform a UA of a service route that, if used by the UA, will provide
  477. * services from a proxy or set of proxies associated with that registrar.
  478. * The Service-Route header field may be included by a registrar in the
  479. * response to a REGISTER request. The syntax for the Service-Route header
  480. * field is:
  481. *
  482. * @code
  483. * Service-Route = "Service-Route" HCOLON sr-value *(COMMA sr-value)
  484. * sr-value = name-addr *( SEMI rr-param )
  485. * @endcode
  486. *
  487. * The parsed Service-Route header is stored in #sip_service_route_t structure.
  488. *
  489. * @sa @RFC3608, @Path, @Route, @RecordRoute
  490. */
  491. /**@ingroup sip_service_route
  492. * @typedef typedef struct sip_route_s sip_service_route_t;
  493. *
  494. * The structure #sip_service_route_t contains representation of SIP
  495. * @ServiceRoute header.
  496. *
  497. * The #sip_service_route_t is defined as follows:
  498. * @code
  499. * typedef struct sip_route_s {
  500. * sip_common_t r_common[1]; // Common fragment info
  501. * sip_service_route_t*r_next; // Link to next @ServiceRoute
  502. * char const *r_display; // Display name
  503. * url_t r_url[1]; // Service-Route URL
  504. * msg_param_t const *r_params; // List of parameters
  505. * } sip_service_route_t;
  506. * @endcode
  507. */
  508. msg_hclass_t sip_service_route_class[] =
  509. SIP_HEADER_CLASS(service_route, "Service-Route", "",
  510. r_params, append, any_route);
  511. issize_t sip_service_route_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  512. {
  513. return sip_any_route_d(home, h, s, slen);
  514. }
  515. issize_t sip_service_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
  516. {
  517. assert(sip_is_service_route(h));
  518. return sip_any_route_e(b, bsiz, h, flags);
  519. }