parameters.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*********************************************************************
  2. *
  3. * Filename: parameters.c
  4. * Version: 1.0
  5. * Description: A more general way to handle (pi,pl,pv) parameters
  6. * Status: Experimental.
  7. * Author: Dag Brattli <dagb@cs.uit.no>
  8. * Created at: Mon Jun 7 10:25:11 1999
  9. * Modified at: Sun Jan 30 14:08:39 2000
  10. * Modified by: Dag Brattli <dagb@cs.uit.no>
  11. *
  12. * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License as
  16. * published by the Free Software Foundation; either version 2 of
  17. * the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  26. *
  27. ********************************************************************/
  28. #include <linux/types.h>
  29. #include <linux/module.h>
  30. #include <asm/unaligned.h>
  31. #include <asm/byteorder.h>
  32. #include <net/irda/irda.h>
  33. #include <net/irda/parameters.h>
  34. static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
  35. PV_TYPE type, PI_HANDLER func);
  36. static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi,
  37. PV_TYPE type, PI_HANDLER func);
  38. static int irda_extract_octseq(void *self, __u8 *buf, int len, __u8 pi,
  39. PV_TYPE type, PI_HANDLER func);
  40. static int irda_extract_no_value(void *self, __u8 *buf, int len, __u8 pi,
  41. PV_TYPE type, PI_HANDLER func);
  42. static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi,
  43. PV_TYPE type, PI_HANDLER func);
  44. static int irda_insert_no_value(void *self, __u8 *buf, int len, __u8 pi,
  45. PV_TYPE type, PI_HANDLER func);
  46. static int irda_param_unpack(__u8 *buf, char *fmt, ...);
  47. /* Parameter value call table. Must match PV_TYPE */
  48. static const PV_HANDLER pv_extract_table[] = {
  49. irda_extract_integer, /* Handler for any length integers */
  50. irda_extract_integer, /* Handler for 8 bits integers */
  51. irda_extract_integer, /* Handler for 16 bits integers */
  52. irda_extract_string, /* Handler for strings */
  53. irda_extract_integer, /* Handler for 32 bits integers */
  54. irda_extract_octseq, /* Handler for octet sequences */
  55. irda_extract_no_value /* Handler for no value parameters */
  56. };
  57. static const PV_HANDLER pv_insert_table[] = {
  58. irda_insert_integer, /* Handler for any length integers */
  59. irda_insert_integer, /* Handler for 8 bits integers */
  60. irda_insert_integer, /* Handler for 16 bits integers */
  61. NULL, /* Handler for strings */
  62. irda_insert_integer, /* Handler for 32 bits integers */
  63. NULL, /* Handler for octet sequences */
  64. irda_insert_no_value /* Handler for no value parameters */
  65. };
  66. /*
  67. * Function irda_insert_no_value (self, buf, len, pi, type, func)
  68. */
  69. static int irda_insert_no_value(void *self, __u8 *buf, int len, __u8 pi,
  70. PV_TYPE type, PI_HANDLER func)
  71. {
  72. irda_param_t p;
  73. int ret;
  74. p.pi = pi;
  75. p.pl = 0;
  76. /* Call handler for this parameter */
  77. ret = (*func)(self, &p, PV_GET);
  78. /* Extract values anyway, since handler may need them */
  79. irda_param_pack(buf, "bb", p.pi, p.pl);
  80. if (ret < 0)
  81. return ret;
  82. return 2; /* Inserted pl+2 bytes */
  83. }
  84. /*
  85. * Function irda_extract_no_value (self, buf, len, type, func)
  86. *
  87. * Extracts a parameter without a pv field (pl=0)
  88. *
  89. */
  90. static int irda_extract_no_value(void *self, __u8 *buf, int len, __u8 pi,
  91. PV_TYPE type, PI_HANDLER func)
  92. {
  93. irda_param_t p;
  94. int ret;
  95. /* Extract values anyway, since handler may need them */
  96. irda_param_unpack(buf, "bb", &p.pi, &p.pl);
  97. /* Call handler for this parameter */
  98. ret = (*func)(self, &p, PV_PUT);
  99. if (ret < 0)
  100. return ret;
  101. return 2; /* Extracted pl+2 bytes */
  102. }
  103. /*
  104. * Function irda_insert_integer (self, buf, len, pi, type, func)
  105. */
  106. static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi,
  107. PV_TYPE type, PI_HANDLER func)
  108. {
  109. irda_param_t p;
  110. int n = 0;
  111. int err;
  112. p.pi = pi; /* In case handler needs to know */
  113. p.pl = type & PV_MASK; /* The integer type codes the length as well */
  114. p.pv.i = 0; /* Clear value */
  115. /* Call handler for this parameter */
  116. err = (*func)(self, &p, PV_GET);
  117. if (err < 0)
  118. return err;
  119. /*
  120. * If parameter length is still 0, then (1) this is an any length
  121. * integer, and (2) the handler function does not care which length
  122. * we choose to use, so we pick the one the gives the fewest bytes.
  123. */
  124. if (p.pl == 0) {
  125. if (p.pv.i < 0xff) {
  126. pr_debug("%s(), using 1 byte\n", __func__);
  127. p.pl = 1;
  128. } else if (p.pv.i < 0xffff) {
  129. pr_debug("%s(), using 2 bytes\n", __func__);
  130. p.pl = 2;
  131. } else {
  132. pr_debug("%s(), using 4 bytes\n", __func__);
  133. p.pl = 4; /* Default length */
  134. }
  135. }
  136. /* Check if buffer is long enough for insertion */
  137. if (len < (2+p.pl)) {
  138. net_warn_ratelimited("%s: buffer too short for insertion!\n",
  139. __func__);
  140. return -1;
  141. }
  142. pr_debug("%s(), pi=%#x, pl=%d, pi=%d\n", __func__,
  143. p.pi, p.pl, p.pv.i);
  144. switch (p.pl) {
  145. case 1:
  146. n += irda_param_pack(buf, "bbb", p.pi, p.pl, (__u8) p.pv.i);
  147. break;
  148. case 2:
  149. if (type & PV_BIG_ENDIAN)
  150. p.pv.i = cpu_to_be16((__u16) p.pv.i);
  151. else
  152. p.pv.i = cpu_to_le16((__u16) p.pv.i);
  153. n += irda_param_pack(buf, "bbs", p.pi, p.pl, (__u16) p.pv.i);
  154. break;
  155. case 4:
  156. if (type & PV_BIG_ENDIAN)
  157. cpu_to_be32s(&p.pv.i);
  158. else
  159. cpu_to_le32s(&p.pv.i);
  160. n += irda_param_pack(buf, "bbi", p.pi, p.pl, p.pv.i);
  161. break;
  162. default:
  163. net_warn_ratelimited("%s: length %d not supported\n",
  164. __func__, p.pl);
  165. /* Skip parameter */
  166. return -1;
  167. }
  168. return p.pl+2; /* Inserted pl+2 bytes */
  169. }
  170. /*
  171. * Function irda_extract integer (self, buf, len, pi, type, func)
  172. *
  173. * Extract a possibly variable length integer from buffer, and call
  174. * handler for processing of the parameter
  175. */
  176. static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
  177. PV_TYPE type, PI_HANDLER func)
  178. {
  179. irda_param_t p;
  180. int n = 0;
  181. int extract_len; /* Real length we extract */
  182. int err;
  183. p.pi = pi; /* In case handler needs to know */
  184. p.pl = buf[1]; /* Extract length of value */
  185. p.pv.i = 0; /* Clear value */
  186. extract_len = p.pl; /* Default : extract all */
  187. /* Check if buffer is long enough for parsing */
  188. if (len < (2+p.pl)) {
  189. net_warn_ratelimited("%s: buffer too short for parsing! Need %d bytes, but len is only %d\n",
  190. __func__, p.pl, len);
  191. return -1;
  192. }
  193. /*
  194. * Check that the integer length is what we expect it to be. If the
  195. * handler want a 16 bits integer then a 32 bits is not good enough
  196. * PV_INTEGER means that the handler is flexible.
  197. */
  198. if (((type & PV_MASK) != PV_INTEGER) && ((type & PV_MASK) != p.pl)) {
  199. net_err_ratelimited("%s: invalid parameter length! Expected %d bytes, but value had %d bytes!\n",
  200. __func__, type & PV_MASK, p.pl);
  201. /* Most parameters are bit/byte fields or little endian,
  202. * so it's ok to only extract a subset of it (the subset
  203. * that the handler expect). This is necessary, as some
  204. * broken implementations seems to add extra undefined bits.
  205. * If the parameter is shorter than we expect or is big
  206. * endian, we can't play those tricks. Jean II */
  207. if((p.pl < (type & PV_MASK)) || (type & PV_BIG_ENDIAN)) {
  208. /* Skip parameter */
  209. return p.pl+2;
  210. } else {
  211. /* Extract subset of it, fallthrough */
  212. extract_len = type & PV_MASK;
  213. }
  214. }
  215. switch (extract_len) {
  216. case 1:
  217. n += irda_param_unpack(buf+2, "b", &p.pv.i);
  218. break;
  219. case 2:
  220. n += irda_param_unpack(buf+2, "s", &p.pv.i);
  221. if (type & PV_BIG_ENDIAN)
  222. p.pv.i = be16_to_cpu((__u16) p.pv.i);
  223. else
  224. p.pv.i = le16_to_cpu((__u16) p.pv.i);
  225. break;
  226. case 4:
  227. n += irda_param_unpack(buf+2, "i", &p.pv.i);
  228. if (type & PV_BIG_ENDIAN)
  229. be32_to_cpus(&p.pv.i);
  230. else
  231. le32_to_cpus(&p.pv.i);
  232. break;
  233. default:
  234. net_warn_ratelimited("%s: length %d not supported\n",
  235. __func__, p.pl);
  236. /* Skip parameter */
  237. return p.pl+2;
  238. }
  239. pr_debug("%s(), pi=%#x, pl=%d, pi=%d\n", __func__,
  240. p.pi, p.pl, p.pv.i);
  241. /* Call handler for this parameter */
  242. err = (*func)(self, &p, PV_PUT);
  243. if (err < 0)
  244. return err;
  245. return p.pl+2; /* Extracted pl+2 bytes */
  246. }
  247. /*
  248. * Function irda_extract_string (self, buf, len, type, func)
  249. */
  250. static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi,
  251. PV_TYPE type, PI_HANDLER func)
  252. {
  253. char str[33];
  254. irda_param_t p;
  255. int err;
  256. p.pi = pi; /* In case handler needs to know */
  257. p.pl = buf[1]; /* Extract length of value */
  258. if (p.pl > 32)
  259. p.pl = 32;
  260. pr_debug("%s(), pi=%#x, pl=%d\n", __func__,
  261. p.pi, p.pl);
  262. /* Check if buffer is long enough for parsing */
  263. if (len < (2+p.pl)) {
  264. net_warn_ratelimited("%s: buffer too short for parsing! Need %d bytes, but len is only %d\n",
  265. __func__, p.pl, len);
  266. return -1;
  267. }
  268. /* Should be safe to copy string like this since we have already
  269. * checked that the buffer is long enough */
  270. strncpy(str, buf+2, p.pl);
  271. pr_debug("%s(), str=0x%02x 0x%02x\n",
  272. __func__, (__u8)str[0], (__u8)str[1]);
  273. /* Null terminate string */
  274. str[p.pl] = '\0';
  275. p.pv.c = str; /* Handler will need to take a copy */
  276. /* Call handler for this parameter */
  277. err = (*func)(self, &p, PV_PUT);
  278. if (err < 0)
  279. return err;
  280. return p.pl+2; /* Extracted pl+2 bytes */
  281. }
  282. /*
  283. * Function irda_extract_octseq (self, buf, len, type, func)
  284. */
  285. static int irda_extract_octseq(void *self, __u8 *buf, int len, __u8 pi,
  286. PV_TYPE type, PI_HANDLER func)
  287. {
  288. irda_param_t p;
  289. p.pi = pi; /* In case handler needs to know */
  290. p.pl = buf[1]; /* Extract length of value */
  291. /* Check if buffer is long enough for parsing */
  292. if (len < (2+p.pl)) {
  293. net_warn_ratelimited("%s: buffer too short for parsing! Need %d bytes, but len is only %d\n",
  294. __func__, p.pl, len);
  295. return -1;
  296. }
  297. pr_debug("%s(), not impl\n", __func__);
  298. return p.pl+2; /* Extracted pl+2 bytes */
  299. }
  300. /*
  301. * Function irda_param_pack (skb, fmt, ...)
  302. *
  303. * Format:
  304. * 'i' = 32 bits integer
  305. * 's' = string
  306. *
  307. */
  308. int irda_param_pack(__u8 *buf, char *fmt, ...)
  309. {
  310. irda_pv_t arg;
  311. va_list args;
  312. char *p;
  313. int n = 0;
  314. va_start(args, fmt);
  315. for (p = fmt; *p != '\0'; p++) {
  316. switch (*p) {
  317. case 'b': /* 8 bits unsigned byte */
  318. buf[n++] = (__u8)va_arg(args, int);
  319. break;
  320. case 's': /* 16 bits unsigned short */
  321. arg.i = (__u16)va_arg(args, int);
  322. put_unaligned((__u16)arg.i, (__u16 *)(buf+n)); n+=2;
  323. break;
  324. case 'i': /* 32 bits unsigned integer */
  325. arg.i = va_arg(args, __u32);
  326. put_unaligned(arg.i, (__u32 *)(buf+n)); n+=4;
  327. break;
  328. #if 0
  329. case 'c': /* \0 terminated string */
  330. arg.c = va_arg(args, char *);
  331. strcpy(buf+n, arg.c);
  332. n += strlen(arg.c) + 1;
  333. break;
  334. #endif
  335. default:
  336. va_end(args);
  337. return -1;
  338. }
  339. }
  340. va_end(args);
  341. return 0;
  342. }
  343. EXPORT_SYMBOL(irda_param_pack);
  344. /*
  345. * Function irda_param_unpack (skb, fmt, ...)
  346. */
  347. static int irda_param_unpack(__u8 *buf, char *fmt, ...)
  348. {
  349. irda_pv_t arg;
  350. va_list args;
  351. char *p;
  352. int n = 0;
  353. va_start(args, fmt);
  354. for (p = fmt; *p != '\0'; p++) {
  355. switch (*p) {
  356. case 'b': /* 8 bits byte */
  357. arg.ip = va_arg(args, __u32 *);
  358. *arg.ip = buf[n++];
  359. break;
  360. case 's': /* 16 bits short */
  361. arg.ip = va_arg(args, __u32 *);
  362. *arg.ip = get_unaligned((__u16 *)(buf+n)); n+=2;
  363. break;
  364. case 'i': /* 32 bits unsigned integer */
  365. arg.ip = va_arg(args, __u32 *);
  366. *arg.ip = get_unaligned((__u32 *)(buf+n)); n+=4;
  367. break;
  368. #if 0
  369. case 'c': /* \0 terminated string */
  370. arg.c = va_arg(args, char *);
  371. strcpy(arg.c, buf+n);
  372. n += strlen(arg.c) + 1;
  373. break;
  374. #endif
  375. default:
  376. va_end(args);
  377. return -1;
  378. }
  379. }
  380. va_end(args);
  381. return 0;
  382. }
  383. /*
  384. * Function irda_param_insert (self, pi, buf, len, info)
  385. *
  386. * Insert the specified parameter (pi) into buffer. Returns number of
  387. * bytes inserted
  388. */
  389. int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len,
  390. pi_param_info_t *info)
  391. {
  392. const pi_minor_info_t *pi_minor_info;
  393. __u8 pi_minor;
  394. __u8 pi_major;
  395. int type;
  396. int ret = -1;
  397. int n = 0;
  398. IRDA_ASSERT(buf != NULL, return ret;);
  399. IRDA_ASSERT(info != NULL, return ret;);
  400. pi_minor = pi & info->pi_mask;
  401. pi_major = pi >> info->pi_major_offset;
  402. /* Check if the identifier value (pi) is valid */
  403. if ((pi_major > info->len-1) ||
  404. (pi_minor > info->tables[pi_major].len-1))
  405. {
  406. pr_debug("%s(), no handler for parameter=0x%02x\n",
  407. __func__, pi);
  408. /* Skip this parameter */
  409. return -1;
  410. }
  411. /* Lookup the info on how to parse this parameter */
  412. pi_minor_info = &info->tables[pi_major].pi_minor_call_table[pi_minor];
  413. /* Find expected data type for this parameter identifier (pi)*/
  414. type = pi_minor_info->type;
  415. /* Check if handler has been implemented */
  416. if (!pi_minor_info->func) {
  417. net_info_ratelimited("%s: no handler for pi=%#x\n",
  418. __func__, pi);
  419. /* Skip this parameter */
  420. return -1;
  421. }
  422. /* Insert parameter value */
  423. ret = (*pv_insert_table[type & PV_MASK])(self, buf+n, len, pi, type,
  424. pi_minor_info->func);
  425. return ret;
  426. }
  427. EXPORT_SYMBOL(irda_param_insert);
  428. /*
  429. * Function irda_param_extract (self, buf, len, info)
  430. *
  431. * Parse all parameters. If len is correct, then everything should be
  432. * safe. Returns the number of bytes that was parsed
  433. *
  434. */
  435. static int irda_param_extract(void *self, __u8 *buf, int len,
  436. pi_param_info_t *info)
  437. {
  438. const pi_minor_info_t *pi_minor_info;
  439. __u8 pi_minor;
  440. __u8 pi_major;
  441. int type;
  442. int ret = -1;
  443. int n = 0;
  444. IRDA_ASSERT(buf != NULL, return ret;);
  445. IRDA_ASSERT(info != NULL, return ret;);
  446. pi_minor = buf[n] & info->pi_mask;
  447. pi_major = buf[n] >> info->pi_major_offset;
  448. /* Check if the identifier value (pi) is valid */
  449. if ((pi_major > info->len-1) ||
  450. (pi_minor > info->tables[pi_major].len-1))
  451. {
  452. pr_debug("%s(), no handler for parameter=0x%02x\n",
  453. __func__, buf[0]);
  454. /* Skip this parameter */
  455. return 2 + buf[n + 1]; /* Continue */
  456. }
  457. /* Lookup the info on how to parse this parameter */
  458. pi_minor_info = &info->tables[pi_major].pi_minor_call_table[pi_minor];
  459. /* Find expected data type for this parameter identifier (pi)*/
  460. type = pi_minor_info->type;
  461. pr_debug("%s(), pi=[%d,%d], type=%d\n", __func__,
  462. pi_major, pi_minor, type);
  463. /* Check if handler has been implemented */
  464. if (!pi_minor_info->func) {
  465. net_info_ratelimited("%s: no handler for pi=%#x\n",
  466. __func__, buf[n]);
  467. /* Skip this parameter */
  468. return 2 + buf[n + 1]; /* Continue */
  469. }
  470. /* Parse parameter value */
  471. ret = (*pv_extract_table[type & PV_MASK])(self, buf+n, len, buf[n],
  472. type, pi_minor_info->func);
  473. return ret;
  474. }
  475. /*
  476. * Function irda_param_extract_all (self, buf, len, info)
  477. *
  478. * Parse all parameters. If len is correct, then everything should be
  479. * safe. Returns the number of bytes that was parsed
  480. *
  481. */
  482. int irda_param_extract_all(void *self, __u8 *buf, int len,
  483. pi_param_info_t *info)
  484. {
  485. int ret = -1;
  486. int n = 0;
  487. IRDA_ASSERT(buf != NULL, return ret;);
  488. IRDA_ASSERT(info != NULL, return ret;);
  489. /*
  490. * Parse all parameters. Each parameter must be at least two bytes
  491. * long or else there is no point in trying to parse it
  492. */
  493. while (len > 2) {
  494. ret = irda_param_extract(self, buf+n, len, info);
  495. if (ret < 0)
  496. return ret;
  497. n += ret;
  498. len -= ret;
  499. }
  500. return n;
  501. }
  502. EXPORT_SYMBOL(irda_param_extract_all);