parameters.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  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 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 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. IRDA_DEBUG(2, "%s(), using 1 byte\n", __func__);
  127. p.pl = 1;
  128. } else if (p.pv.i < 0xffff) {
  129. IRDA_DEBUG(2, "%s(), using 2 bytes\n", __func__);
  130. p.pl = 2;
  131. } else {
  132. IRDA_DEBUG(2, "%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. IRDA_DEBUG(2, "%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. IRDA_DEBUG(2, "%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. IRDA_DEBUG(2, "%s()\n", __func__);
  257. p.pi = pi; /* In case handler needs to know */
  258. p.pl = buf[1]; /* Extract length of value */
  259. if (p.pl > 32)
  260. p.pl = 32;
  261. IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d\n", __func__,
  262. p.pi, p.pl);
  263. /* Check if buffer is long enough for parsing */
  264. if (len < (2+p.pl)) {
  265. net_warn_ratelimited("%s: buffer too short for parsing! Need %d bytes, but len is only %d\n",
  266. __func__, p.pl, len);
  267. return -1;
  268. }
  269. /* Should be safe to copy string like this since we have already
  270. * checked that the buffer is long enough */
  271. strncpy(str, buf+2, p.pl);
  272. IRDA_DEBUG(2, "%s(), str=0x%02x 0x%02x\n", __func__,
  273. (__u8) str[0], (__u8) str[1]);
  274. /* Null terminate string */
  275. str[p.pl] = '\0';
  276. p.pv.c = str; /* Handler will need to take a copy */
  277. /* Call handler for this parameter */
  278. err = (*func)(self, &p, PV_PUT);
  279. if (err < 0)
  280. return err;
  281. return p.pl+2; /* Extracted pl+2 bytes */
  282. }
  283. /*
  284. * Function irda_extract_octseq (self, buf, len, type, func)
  285. */
  286. static int irda_extract_octseq(void *self, __u8 *buf, int len, __u8 pi,
  287. PV_TYPE type, PI_HANDLER func)
  288. {
  289. irda_param_t p;
  290. p.pi = pi; /* In case handler needs to know */
  291. p.pl = buf[1]; /* Extract length of value */
  292. /* Check if buffer is long enough for parsing */
  293. if (len < (2+p.pl)) {
  294. net_warn_ratelimited("%s: buffer too short for parsing! Need %d bytes, but len is only %d\n",
  295. __func__, p.pl, len);
  296. return -1;
  297. }
  298. IRDA_DEBUG(0, "%s(), not impl\n", __func__);
  299. return p.pl+2; /* Extracted pl+2 bytes */
  300. }
  301. /*
  302. * Function irda_param_pack (skb, fmt, ...)
  303. *
  304. * Format:
  305. * 'i' = 32 bits integer
  306. * 's' = string
  307. *
  308. */
  309. int irda_param_pack(__u8 *buf, char *fmt, ...)
  310. {
  311. irda_pv_t arg;
  312. va_list args;
  313. char *p;
  314. int n = 0;
  315. va_start(args, fmt);
  316. for (p = fmt; *p != '\0'; p++) {
  317. switch (*p) {
  318. case 'b': /* 8 bits unsigned byte */
  319. buf[n++] = (__u8)va_arg(args, int);
  320. break;
  321. case 's': /* 16 bits unsigned short */
  322. arg.i = (__u16)va_arg(args, int);
  323. put_unaligned((__u16)arg.i, (__u16 *)(buf+n)); n+=2;
  324. break;
  325. case 'i': /* 32 bits unsigned integer */
  326. arg.i = va_arg(args, __u32);
  327. put_unaligned(arg.i, (__u32 *)(buf+n)); n+=4;
  328. break;
  329. #if 0
  330. case 'c': /* \0 terminated string */
  331. arg.c = va_arg(args, char *);
  332. strcpy(buf+n, arg.c);
  333. n += strlen(arg.c) + 1;
  334. break;
  335. #endif
  336. default:
  337. va_end(args);
  338. return -1;
  339. }
  340. }
  341. va_end(args);
  342. return 0;
  343. }
  344. EXPORT_SYMBOL(irda_param_pack);
  345. /*
  346. * Function irda_param_unpack (skb, fmt, ...)
  347. */
  348. static int irda_param_unpack(__u8 *buf, char *fmt, ...)
  349. {
  350. irda_pv_t arg;
  351. va_list args;
  352. char *p;
  353. int n = 0;
  354. va_start(args, fmt);
  355. for (p = fmt; *p != '\0'; p++) {
  356. switch (*p) {
  357. case 'b': /* 8 bits byte */
  358. arg.ip = va_arg(args, __u32 *);
  359. *arg.ip = buf[n++];
  360. break;
  361. case 's': /* 16 bits short */
  362. arg.ip = va_arg(args, __u32 *);
  363. *arg.ip = get_unaligned((__u16 *)(buf+n)); n+=2;
  364. break;
  365. case 'i': /* 32 bits unsigned integer */
  366. arg.ip = va_arg(args, __u32 *);
  367. *arg.ip = get_unaligned((__u32 *)(buf+n)); n+=4;
  368. break;
  369. #if 0
  370. case 'c': /* \0 terminated string */
  371. arg.c = va_arg(args, char *);
  372. strcpy(arg.c, buf+n);
  373. n += strlen(arg.c) + 1;
  374. break;
  375. #endif
  376. default:
  377. va_end(args);
  378. return -1;
  379. }
  380. }
  381. va_end(args);
  382. return 0;
  383. }
  384. /*
  385. * Function irda_param_insert (self, pi, buf, len, info)
  386. *
  387. * Insert the specified parameter (pi) into buffer. Returns number of
  388. * bytes inserted
  389. */
  390. int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len,
  391. pi_param_info_t *info)
  392. {
  393. pi_minor_info_t *pi_minor_info;
  394. __u8 pi_minor;
  395. __u8 pi_major;
  396. int type;
  397. int ret = -1;
  398. int n = 0;
  399. IRDA_ASSERT(buf != NULL, return ret;);
  400. IRDA_ASSERT(info != NULL, return ret;);
  401. pi_minor = pi & info->pi_mask;
  402. pi_major = pi >> info->pi_major_offset;
  403. /* Check if the identifier value (pi) is valid */
  404. if ((pi_major > info->len-1) ||
  405. (pi_minor > info->tables[pi_major].len-1))
  406. {
  407. IRDA_DEBUG(0, "%s(), no handler for parameter=0x%02x\n",
  408. __func__, pi);
  409. /* Skip this parameter */
  410. return -1;
  411. }
  412. /* Lookup the info on how to parse this parameter */
  413. pi_minor_info = &info->tables[pi_major].pi_minor_call_table[pi_minor];
  414. /* Find expected data type for this parameter identifier (pi)*/
  415. type = pi_minor_info->type;
  416. /* Check if handler has been implemented */
  417. if (!pi_minor_info->func) {
  418. net_info_ratelimited("%s: no handler for pi=%#x\n",
  419. __func__, pi);
  420. /* Skip this parameter */
  421. return -1;
  422. }
  423. /* Insert parameter value */
  424. ret = (*pv_insert_table[type & PV_MASK])(self, buf+n, len, pi, type,
  425. pi_minor_info->func);
  426. return ret;
  427. }
  428. EXPORT_SYMBOL(irda_param_insert);
  429. /*
  430. * Function irda_param_extract (self, buf, len, info)
  431. *
  432. * Parse all parameters. If len is correct, then everything should be
  433. * safe. Returns the number of bytes that was parsed
  434. *
  435. */
  436. static int irda_param_extract(void *self, __u8 *buf, int len,
  437. pi_param_info_t *info)
  438. {
  439. pi_minor_info_t *pi_minor_info;
  440. __u8 pi_minor;
  441. __u8 pi_major;
  442. int type;
  443. int ret = -1;
  444. int n = 0;
  445. IRDA_ASSERT(buf != NULL, return ret;);
  446. IRDA_ASSERT(info != NULL, return ret;);
  447. pi_minor = buf[n] & info->pi_mask;
  448. pi_major = buf[n] >> info->pi_major_offset;
  449. /* Check if the identifier value (pi) is valid */
  450. if ((pi_major > info->len-1) ||
  451. (pi_minor > info->tables[pi_major].len-1))
  452. {
  453. IRDA_DEBUG(0, "%s(), no handler for parameter=0x%02x\n",
  454. __func__, buf[0]);
  455. /* Skip this parameter */
  456. return 2 + buf[n + 1]; /* Continue */
  457. }
  458. /* Lookup the info on how to parse this parameter */
  459. pi_minor_info = &info->tables[pi_major].pi_minor_call_table[pi_minor];
  460. /* Find expected data type for this parameter identifier (pi)*/
  461. type = pi_minor_info->type;
  462. IRDA_DEBUG(3, "%s(), pi=[%d,%d], type=%d\n", __func__,
  463. pi_major, pi_minor, type);
  464. /* Check if handler has been implemented */
  465. if (!pi_minor_info->func) {
  466. net_info_ratelimited("%s: no handler for pi=%#x\n",
  467. __func__, buf[n]);
  468. /* Skip this parameter */
  469. return 2 + buf[n + 1]; /* Continue */
  470. }
  471. /* Parse parameter value */
  472. ret = (*pv_extract_table[type & PV_MASK])(self, buf+n, len, buf[n],
  473. type, pi_minor_info->func);
  474. return ret;
  475. }
  476. /*
  477. * Function irda_param_extract_all (self, buf, len, info)
  478. *
  479. * Parse all parameters. If len is correct, then everything should be
  480. * safe. Returns the number of bytes that was parsed
  481. *
  482. */
  483. int irda_param_extract_all(void *self, __u8 *buf, int len,
  484. pi_param_info_t *info)
  485. {
  486. int ret = -1;
  487. int n = 0;
  488. IRDA_ASSERT(buf != NULL, return ret;);
  489. IRDA_ASSERT(info != NULL, return ret;);
  490. /*
  491. * Parse all parameters. Each parameter must be at least two bytes
  492. * long or else there is no point in trying to parse it
  493. */
  494. while (len > 2) {
  495. ret = irda_param_extract(self, buf+n, len, info);
  496. if (ret < 0)
  497. return ret;
  498. n += ret;
  499. len -= ret;
  500. }
  501. return n;
  502. }
  503. EXPORT_SYMBOL(irda_param_extract_all);