iriap.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  1. /*********************************************************************
  2. *
  3. * Filename: iriap.c
  4. * Version: 0.8
  5. * Description: Information Access Protocol (IAP)
  6. * Status: Experimental.
  7. * Author: Dag Brattli <dagb@cs.uit.no>
  8. * Created at: Thu Aug 21 00:02:07 1997
  9. * Modified at: Sat Dec 25 16:42:42 1999
  10. * Modified by: Dag Brattli <dagb@cs.uit.no>
  11. *
  12. * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
  13. * All Rights Reserved.
  14. * Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  15. *
  16. * This program is free software; you can redistribute it and/or
  17. * modify it under the terms of the GNU General Public License as
  18. * published by the Free Software Foundation; either version 2 of
  19. * the License, or (at your option) any later version.
  20. *
  21. * Neither Dag Brattli nor University of Tromsø admit liability nor
  22. * provide warranty for any of this software. This material is
  23. * provided "AS-IS" and at no charge.
  24. *
  25. ********************************************************************/
  26. #include <linux/module.h>
  27. #include <linux/types.h>
  28. #include <linux/skbuff.h>
  29. #include <linux/fs.h>
  30. #include <linux/string.h>
  31. #include <linux/init.h>
  32. #include <linux/seq_file.h>
  33. #include <linux/slab.h>
  34. #include <asm/byteorder.h>
  35. #include <asm/unaligned.h>
  36. #include <net/irda/irda.h>
  37. #include <net/irda/irttp.h>
  38. #include <net/irda/irlmp.h>
  39. #include <net/irda/irias_object.h>
  40. #include <net/irda/iriap_event.h>
  41. #include <net/irda/iriap.h>
  42. /* FIXME: This one should go in irlmp.c */
  43. static const char *const ias_charset_types[] __maybe_unused = {
  44. "CS_ASCII",
  45. "CS_ISO_8859_1",
  46. "CS_ISO_8859_2",
  47. "CS_ISO_8859_3",
  48. "CS_ISO_8859_4",
  49. "CS_ISO_8859_5",
  50. "CS_ISO_8859_6",
  51. "CS_ISO_8859_7",
  52. "CS_ISO_8859_8",
  53. "CS_ISO_8859_9",
  54. "CS_UNICODE"
  55. };
  56. static hashbin_t *iriap = NULL;
  57. static void *service_handle;
  58. static void __iriap_close(struct iriap_cb *self);
  59. static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode);
  60. static void iriap_disconnect_indication(void *instance, void *sap,
  61. LM_REASON reason, struct sk_buff *skb);
  62. static void iriap_connect_indication(void *instance, void *sap,
  63. struct qos_info *qos, __u32 max_sdu_size,
  64. __u8 max_header_size,
  65. struct sk_buff *skb);
  66. static void iriap_connect_confirm(void *instance, void *sap,
  67. struct qos_info *qos,
  68. __u32 max_sdu_size, __u8 max_header_size,
  69. struct sk_buff *skb);
  70. static int iriap_data_indication(void *instance, void *sap,
  71. struct sk_buff *skb);
  72. static void iriap_watchdog_timer_expired(void *data);
  73. static inline void iriap_start_watchdog_timer(struct iriap_cb *self,
  74. int timeout)
  75. {
  76. irda_start_timer(&self->watchdog_timer, timeout, self,
  77. iriap_watchdog_timer_expired);
  78. }
  79. static struct lock_class_key irias_objects_key;
  80. /*
  81. * Function iriap_init (void)
  82. *
  83. * Initializes the IrIAP layer, called by the module initialization code
  84. * in irmod.c
  85. */
  86. int __init iriap_init(void)
  87. {
  88. struct ias_object *obj;
  89. struct iriap_cb *server;
  90. __u8 oct_seq[6];
  91. __u16 hints;
  92. /* Allocate master array */
  93. iriap = hashbin_new(HB_LOCK);
  94. if (!iriap)
  95. return -ENOMEM;
  96. /* Object repository - defined in irias_object.c */
  97. irias_objects = hashbin_new(HB_LOCK);
  98. if (!irias_objects) {
  99. net_warn_ratelimited("%s: Can't allocate irias_objects hashbin!\n",
  100. __func__);
  101. hashbin_delete(iriap, NULL);
  102. return -ENOMEM;
  103. }
  104. lockdep_set_class_and_name(&irias_objects->hb_spinlock, &irias_objects_key,
  105. "irias_objects");
  106. /*
  107. * Register some default services for IrLMP
  108. */
  109. hints = irlmp_service_to_hint(S_COMPUTER);
  110. service_handle = irlmp_register_service(hints);
  111. /* Register the Device object with LM-IAS */
  112. obj = irias_new_object("Device", IAS_DEVICE_ID);
  113. irias_add_string_attrib(obj, "DeviceName", "Linux", IAS_KERNEL_ATTR);
  114. oct_seq[0] = 0x01; /* Version 1 */
  115. oct_seq[1] = 0x00; /* IAS support bits */
  116. oct_seq[2] = 0x00; /* LM-MUX support bits */
  117. #ifdef CONFIG_IRDA_ULTRA
  118. oct_seq[2] |= 0x04; /* Connectionless Data support */
  119. #endif
  120. irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3,
  121. IAS_KERNEL_ATTR);
  122. irias_insert_object(obj);
  123. /*
  124. * Register server support with IrLMP so we can accept incoming
  125. * connections
  126. */
  127. server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
  128. if (!server) {
  129. pr_debug("%s(), unable to open server\n", __func__);
  130. return -1;
  131. }
  132. iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
  133. return 0;
  134. }
  135. /*
  136. * Function iriap_cleanup (void)
  137. *
  138. * Initializes the IrIAP layer, called by the module cleanup code in
  139. * irmod.c
  140. */
  141. void iriap_cleanup(void)
  142. {
  143. irlmp_unregister_service(service_handle);
  144. hashbin_delete(iriap, (FREE_FUNC) __iriap_close);
  145. hashbin_delete(irias_objects, (FREE_FUNC) __irias_delete_object);
  146. }
  147. /*
  148. * Function iriap_open (void)
  149. *
  150. * Opens an instance of the IrIAP layer, and registers with IrLMP
  151. */
  152. struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
  153. CONFIRM_CALLBACK callback)
  154. {
  155. struct iriap_cb *self;
  156. self = kzalloc(sizeof(*self), GFP_ATOMIC);
  157. if (!self)
  158. return NULL;
  159. /*
  160. * Initialize instance
  161. */
  162. self->magic = IAS_MAGIC;
  163. self->mode = mode;
  164. if (mode == IAS_CLIENT)
  165. iriap_register_lsap(self, slsap_sel, mode);
  166. self->confirm = callback;
  167. self->priv = priv;
  168. /* iriap_getvaluebyclass_request() will construct packets before
  169. * we connect, so this must have a sane value... Jean II */
  170. self->max_header_size = LMP_MAX_HEADER;
  171. init_timer(&self->watchdog_timer);
  172. hashbin_insert(iriap, (irda_queue_t *) self, (long) self, NULL);
  173. /* Initialize state machines */
  174. iriap_next_client_state(self, S_DISCONNECT);
  175. iriap_next_call_state(self, S_MAKE_CALL);
  176. iriap_next_server_state(self, R_DISCONNECT);
  177. iriap_next_r_connect_state(self, R_WAITING);
  178. return self;
  179. }
  180. EXPORT_SYMBOL(iriap_open);
  181. /*
  182. * Function __iriap_close (self)
  183. *
  184. * Removes (deallocates) the IrIAP instance
  185. *
  186. */
  187. static void __iriap_close(struct iriap_cb *self)
  188. {
  189. IRDA_ASSERT(self != NULL, return;);
  190. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  191. del_timer(&self->watchdog_timer);
  192. if (self->request_skb)
  193. dev_kfree_skb(self->request_skb);
  194. self->magic = 0;
  195. kfree(self);
  196. }
  197. /*
  198. * Function iriap_close (void)
  199. *
  200. * Closes IrIAP and deregisters with IrLMP
  201. */
  202. void iriap_close(struct iriap_cb *self)
  203. {
  204. struct iriap_cb *entry;
  205. IRDA_ASSERT(self != NULL, return;);
  206. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  207. if (self->lsap) {
  208. irlmp_close_lsap(self->lsap);
  209. self->lsap = NULL;
  210. }
  211. entry = (struct iriap_cb *) hashbin_remove(iriap, (long) self, NULL);
  212. IRDA_ASSERT(entry == self, return;);
  213. __iriap_close(self);
  214. }
  215. EXPORT_SYMBOL(iriap_close);
  216. static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
  217. {
  218. notify_t notify;
  219. irda_notify_init(&notify);
  220. notify.connect_confirm = iriap_connect_confirm;
  221. notify.connect_indication = iriap_connect_indication;
  222. notify.disconnect_indication = iriap_disconnect_indication;
  223. notify.data_indication = iriap_data_indication;
  224. notify.instance = self;
  225. if (mode == IAS_CLIENT)
  226. strcpy(notify.name, "IrIAS cli");
  227. else
  228. strcpy(notify.name, "IrIAS srv");
  229. self->lsap = irlmp_open_lsap(slsap_sel, &notify, 0);
  230. if (self->lsap == NULL) {
  231. net_err_ratelimited("%s: Unable to allocated LSAP!\n",
  232. __func__);
  233. return -1;
  234. }
  235. self->slsap_sel = self->lsap->slsap_sel;
  236. return 0;
  237. }
  238. /*
  239. * Function iriap_disconnect_indication (handle, reason)
  240. *
  241. * Got disconnect, so clean up everything associated with this connection
  242. *
  243. */
  244. static void iriap_disconnect_indication(void *instance, void *sap,
  245. LM_REASON reason,
  246. struct sk_buff *skb)
  247. {
  248. struct iriap_cb *self;
  249. pr_debug("%s(), reason=%s [%d]\n", __func__,
  250. irlmp_reason_str(reason), reason);
  251. self = instance;
  252. IRDA_ASSERT(self != NULL, return;);
  253. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  254. IRDA_ASSERT(iriap != NULL, return;);
  255. del_timer(&self->watchdog_timer);
  256. /* Not needed */
  257. if (skb)
  258. dev_kfree_skb(skb);
  259. if (self->mode == IAS_CLIENT) {
  260. pr_debug("%s(), disconnect as client\n", __func__);
  261. iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION,
  262. NULL);
  263. /*
  264. * Inform service user that the request failed by sending
  265. * it a NULL value. Warning, the client might close us, so
  266. * remember no to use self anymore after calling confirm
  267. */
  268. if (self->confirm)
  269. self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
  270. } else {
  271. pr_debug("%s(), disconnect as server\n", __func__);
  272. iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION,
  273. NULL);
  274. iriap_close(self);
  275. }
  276. }
  277. /*
  278. * Function iriap_disconnect_request (handle)
  279. */
  280. static void iriap_disconnect_request(struct iriap_cb *self)
  281. {
  282. struct sk_buff *tx_skb;
  283. IRDA_ASSERT(self != NULL, return;);
  284. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  285. tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
  286. if (tx_skb == NULL) {
  287. pr_debug("%s(), Could not allocate an sk_buff of length %d\n",
  288. __func__, LMP_MAX_HEADER);
  289. return;
  290. }
  291. /*
  292. * Reserve space for MUX control and LAP header
  293. */
  294. skb_reserve(tx_skb, LMP_MAX_HEADER);
  295. irlmp_disconnect_request(self->lsap, tx_skb);
  296. }
  297. /*
  298. * Function iriap_getvaluebyclass (addr, name, attr)
  299. *
  300. * Retrieve all values from attribute in all objects with given class
  301. * name
  302. */
  303. int iriap_getvaluebyclass_request(struct iriap_cb *self,
  304. __u32 saddr, __u32 daddr,
  305. char *name, char *attr)
  306. {
  307. struct sk_buff *tx_skb;
  308. int name_len, attr_len, skb_len;
  309. __u8 *frame;
  310. IRDA_ASSERT(self != NULL, return -1;);
  311. IRDA_ASSERT(self->magic == IAS_MAGIC, return -1;);
  312. /* Client must supply the destination device address */
  313. if (!daddr)
  314. return -1;
  315. self->daddr = daddr;
  316. self->saddr = saddr;
  317. /*
  318. * Save operation, so we know what the later indication is about
  319. */
  320. self->operation = GET_VALUE_BY_CLASS;
  321. /* Give ourselves 10 secs to finish this operation */
  322. iriap_start_watchdog_timer(self, 10*HZ);
  323. name_len = strlen(name); /* Up to IAS_MAX_CLASSNAME = 60 */
  324. attr_len = strlen(attr); /* Up to IAS_MAX_ATTRIBNAME = 60 */
  325. skb_len = self->max_header_size+2+name_len+1+attr_len+4;
  326. tx_skb = alloc_skb(skb_len, GFP_ATOMIC);
  327. if (!tx_skb)
  328. return -ENOMEM;
  329. /* Reserve space for MUX and LAP header */
  330. skb_reserve(tx_skb, self->max_header_size);
  331. skb_put(tx_skb, 3+name_len+attr_len);
  332. frame = tx_skb->data;
  333. /* Build frame */
  334. frame[0] = IAP_LST | GET_VALUE_BY_CLASS;
  335. frame[1] = name_len; /* Insert length of name */
  336. memcpy(frame+2, name, name_len); /* Insert name */
  337. frame[2+name_len] = attr_len; /* Insert length of attr */
  338. memcpy(frame+3+name_len, attr, attr_len); /* Insert attr */
  339. iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, tx_skb);
  340. /* Drop reference count - see state_s_disconnect(). */
  341. dev_kfree_skb(tx_skb);
  342. return 0;
  343. }
  344. EXPORT_SYMBOL(iriap_getvaluebyclass_request);
  345. /*
  346. * Function iriap_getvaluebyclass_confirm (self, skb)
  347. *
  348. * Got result from GetValueByClass command. Parse it and return result
  349. * to service user.
  350. *
  351. */
  352. static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
  353. struct sk_buff *skb)
  354. {
  355. struct ias_value *value;
  356. int charset;
  357. __u32 value_len;
  358. __u32 tmp_cpu32;
  359. __u16 obj_id;
  360. __u16 len;
  361. __u8 type;
  362. __u8 *fp;
  363. int n;
  364. IRDA_ASSERT(self != NULL, return;);
  365. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  366. IRDA_ASSERT(skb != NULL, return;);
  367. /* Initialize variables */
  368. fp = skb->data;
  369. n = 2;
  370. /* Get length, MSB first */
  371. len = get_unaligned_be16(fp + n);
  372. n += 2;
  373. pr_debug("%s(), len=%d\n", __func__, len);
  374. /* Get object ID, MSB first */
  375. obj_id = get_unaligned_be16(fp + n);
  376. n += 2;
  377. type = fp[n++];
  378. pr_debug("%s(), Value type = %d\n", __func__, type);
  379. switch (type) {
  380. case IAS_INTEGER:
  381. memcpy(&tmp_cpu32, fp+n, 4); n += 4;
  382. be32_to_cpus(&tmp_cpu32);
  383. value = irias_new_integer_value(tmp_cpu32);
  384. /* Legal values restricted to 0x01-0x6f, page 15 irttp */
  385. pr_debug("%s(), lsap=%d\n", __func__, value->t.integer);
  386. break;
  387. case IAS_STRING:
  388. charset = fp[n++];
  389. switch (charset) {
  390. case CS_ASCII:
  391. break;
  392. /* case CS_ISO_8859_1: */
  393. /* case CS_ISO_8859_2: */
  394. /* case CS_ISO_8859_3: */
  395. /* case CS_ISO_8859_4: */
  396. /* case CS_ISO_8859_5: */
  397. /* case CS_ISO_8859_6: */
  398. /* case CS_ISO_8859_7: */
  399. /* case CS_ISO_8859_8: */
  400. /* case CS_ISO_8859_9: */
  401. /* case CS_UNICODE: */
  402. default:
  403. pr_debug("%s(), charset [%d] %s, not supported\n",
  404. __func__, charset,
  405. charset < ARRAY_SIZE(ias_charset_types) ?
  406. ias_charset_types[charset] :
  407. "(unknown)");
  408. /* Aborting, close connection! */
  409. iriap_disconnect_request(self);
  410. return;
  411. /* break; */
  412. }
  413. value_len = fp[n++];
  414. pr_debug("%s(), strlen=%d\n", __func__, value_len);
  415. /* Make sure the string is null-terminated */
  416. if (n + value_len < skb->len)
  417. fp[n + value_len] = 0x00;
  418. pr_debug("Got string %s\n", fp+n);
  419. /* Will truncate to IAS_MAX_STRING bytes */
  420. value = irias_new_string_value(fp+n);
  421. break;
  422. case IAS_OCT_SEQ:
  423. value_len = get_unaligned_be16(fp + n);
  424. n += 2;
  425. /* Will truncate to IAS_MAX_OCTET_STRING bytes */
  426. value = irias_new_octseq_value(fp+n, value_len);
  427. break;
  428. default:
  429. value = irias_new_missing_value();
  430. break;
  431. }
  432. /* Finished, close connection! */
  433. iriap_disconnect_request(self);
  434. /* Warning, the client might close us, so remember no to use self
  435. * anymore after calling confirm
  436. */
  437. if (self->confirm)
  438. self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
  439. else {
  440. pr_debug("%s(), missing handler!\n", __func__);
  441. irias_delete_value(value);
  442. }
  443. }
  444. /*
  445. * Function iriap_getvaluebyclass_response ()
  446. *
  447. * Send answer back to remote LM-IAS
  448. *
  449. */
  450. static void iriap_getvaluebyclass_response(struct iriap_cb *self,
  451. __u16 obj_id,
  452. __u8 ret_code,
  453. struct ias_value *value)
  454. {
  455. struct sk_buff *tx_skb;
  456. int n;
  457. __be32 tmp_be32;
  458. __be16 tmp_be16;
  459. __u8 *fp;
  460. IRDA_ASSERT(self != NULL, return;);
  461. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  462. IRDA_ASSERT(value != NULL, return;);
  463. IRDA_ASSERT(value->len <= 1024, return;);
  464. /* Initialize variables */
  465. n = 0;
  466. /*
  467. * We must adjust the size of the response after the length of the
  468. * value. We add 32 bytes because of the 6 bytes for the frame and
  469. * max 5 bytes for the value coding.
  470. */
  471. tx_skb = alloc_skb(value->len + self->max_header_size + 32,
  472. GFP_ATOMIC);
  473. if (!tx_skb)
  474. return;
  475. /* Reserve space for MUX and LAP header */
  476. skb_reserve(tx_skb, self->max_header_size);
  477. skb_put(tx_skb, 6);
  478. fp = tx_skb->data;
  479. /* Build frame */
  480. fp[n++] = GET_VALUE_BY_CLASS | IAP_LST;
  481. fp[n++] = ret_code;
  482. /* Insert list length (MSB first) */
  483. tmp_be16 = htons(0x0001);
  484. memcpy(fp+n, &tmp_be16, 2); n += 2;
  485. /* Insert object identifier ( MSB first) */
  486. tmp_be16 = cpu_to_be16(obj_id);
  487. memcpy(fp+n, &tmp_be16, 2); n += 2;
  488. switch (value->type) {
  489. case IAS_STRING:
  490. skb_put(tx_skb, 3 + value->len);
  491. fp[n++] = value->type;
  492. fp[n++] = 0; /* ASCII */
  493. fp[n++] = (__u8) value->len;
  494. memcpy(fp+n, value->t.string, value->len); n+=value->len;
  495. break;
  496. case IAS_INTEGER:
  497. skb_put(tx_skb, 5);
  498. fp[n++] = value->type;
  499. tmp_be32 = cpu_to_be32(value->t.integer);
  500. memcpy(fp+n, &tmp_be32, 4); n += 4;
  501. break;
  502. case IAS_OCT_SEQ:
  503. skb_put(tx_skb, 3 + value->len);
  504. fp[n++] = value->type;
  505. tmp_be16 = cpu_to_be16(value->len);
  506. memcpy(fp+n, &tmp_be16, 2); n += 2;
  507. memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
  508. break;
  509. case IAS_MISSING:
  510. pr_debug("%s: sending IAS_MISSING\n", __func__);
  511. skb_put(tx_skb, 1);
  512. fp[n++] = value->type;
  513. break;
  514. default:
  515. pr_debug("%s(), type not implemented!\n", __func__);
  516. break;
  517. }
  518. iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, tx_skb);
  519. /* Drop reference count - see state_r_execute(). */
  520. dev_kfree_skb(tx_skb);
  521. }
  522. /*
  523. * Function iriap_getvaluebyclass_indication (self, skb)
  524. *
  525. * getvaluebyclass is requested from peer LM-IAS
  526. *
  527. */
  528. static void iriap_getvaluebyclass_indication(struct iriap_cb *self,
  529. struct sk_buff *skb)
  530. {
  531. struct ias_object *obj;
  532. struct ias_attrib *attrib;
  533. int name_len;
  534. int attr_len;
  535. char name[IAS_MAX_CLASSNAME + 1]; /* 60 bytes */
  536. char attr[IAS_MAX_ATTRIBNAME + 1]; /* 60 bytes */
  537. __u8 *fp;
  538. int n;
  539. IRDA_ASSERT(self != NULL, return;);
  540. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  541. IRDA_ASSERT(skb != NULL, return;);
  542. fp = skb->data;
  543. n = 1;
  544. name_len = fp[n++];
  545. IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;);
  546. memcpy(name, fp+n, name_len); n+=name_len;
  547. name[name_len] = '\0';
  548. attr_len = fp[n++];
  549. IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;);
  550. memcpy(attr, fp+n, attr_len); n+=attr_len;
  551. attr[attr_len] = '\0';
  552. pr_debug("LM-IAS: Looking up %s: %s\n", name, attr);
  553. obj = irias_find_object(name);
  554. if (obj == NULL) {
  555. pr_debug("LM-IAS: Object %s not found\n", name);
  556. iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
  557. &irias_missing);
  558. return;
  559. }
  560. pr_debug("LM-IAS: found %s, id=%d\n", obj->name, obj->id);
  561. attrib = irias_find_attrib(obj, attr);
  562. if (attrib == NULL) {
  563. pr_debug("LM-IAS: Attribute %s not found\n", attr);
  564. iriap_getvaluebyclass_response(self, obj->id,
  565. IAS_ATTRIB_UNKNOWN,
  566. &irias_missing);
  567. return;
  568. }
  569. /* We have a match; send the value. */
  570. iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS,
  571. attrib->value);
  572. }
  573. /*
  574. * Function iriap_send_ack (void)
  575. *
  576. * Currently not used
  577. *
  578. */
  579. void iriap_send_ack(struct iriap_cb *self)
  580. {
  581. struct sk_buff *tx_skb;
  582. __u8 *frame;
  583. IRDA_ASSERT(self != NULL, return;);
  584. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  585. tx_skb = alloc_skb(LMP_MAX_HEADER + 1, GFP_ATOMIC);
  586. if (!tx_skb)
  587. return;
  588. /* Reserve space for MUX and LAP header */
  589. skb_reserve(tx_skb, self->max_header_size);
  590. skb_put(tx_skb, 1);
  591. frame = tx_skb->data;
  592. /* Build frame */
  593. frame[0] = IAP_LST | IAP_ACK | self->operation;
  594. irlmp_data_request(self->lsap, tx_skb);
  595. }
  596. void iriap_connect_request(struct iriap_cb *self)
  597. {
  598. int ret;
  599. IRDA_ASSERT(self != NULL, return;);
  600. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  601. ret = irlmp_connect_request(self->lsap, LSAP_IAS,
  602. self->saddr, self->daddr,
  603. NULL, NULL);
  604. if (ret < 0) {
  605. pr_debug("%s(), connect failed!\n", __func__);
  606. self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
  607. }
  608. }
  609. /*
  610. * Function iriap_connect_confirm (handle, skb)
  611. *
  612. * LSAP connection confirmed!
  613. *
  614. */
  615. static void iriap_connect_confirm(void *instance, void *sap,
  616. struct qos_info *qos, __u32 max_seg_size,
  617. __u8 max_header_size,
  618. struct sk_buff *skb)
  619. {
  620. struct iriap_cb *self;
  621. self = instance;
  622. IRDA_ASSERT(self != NULL, return;);
  623. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  624. IRDA_ASSERT(skb != NULL, return;);
  625. self->max_data_size = max_seg_size;
  626. self->max_header_size = max_header_size;
  627. del_timer(&self->watchdog_timer);
  628. iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, skb);
  629. /* Drop reference count - see state_s_make_call(). */
  630. dev_kfree_skb(skb);
  631. }
  632. /*
  633. * Function iriap_connect_indication ( handle, skb)
  634. *
  635. * Remote LM-IAS is requesting connection
  636. *
  637. */
  638. static void iriap_connect_indication(void *instance, void *sap,
  639. struct qos_info *qos, __u32 max_seg_size,
  640. __u8 max_header_size,
  641. struct sk_buff *skb)
  642. {
  643. struct iriap_cb *self, *new;
  644. self = instance;
  645. IRDA_ASSERT(skb != NULL, return;);
  646. IRDA_ASSERT(self != NULL, goto out;);
  647. IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;);
  648. /* Start new server */
  649. new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
  650. if (!new) {
  651. pr_debug("%s(), open failed\n", __func__);
  652. goto out;
  653. }
  654. /* Now attach up the new "socket" */
  655. new->lsap = irlmp_dup(self->lsap, new);
  656. if (!new->lsap) {
  657. pr_debug("%s(), dup failed!\n", __func__);
  658. goto out;
  659. }
  660. new->max_data_size = max_seg_size;
  661. new->max_header_size = max_header_size;
  662. /* Clean up the original one to keep it in listen state */
  663. irlmp_listen(self->lsap);
  664. iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, skb);
  665. out:
  666. /* Drop reference count - see state_r_disconnect(). */
  667. dev_kfree_skb(skb);
  668. }
  669. /*
  670. * Function iriap_data_indication (handle, skb)
  671. *
  672. * Receives data from connection identified by handle from IrLMP
  673. *
  674. */
  675. static int iriap_data_indication(void *instance, void *sap,
  676. struct sk_buff *skb)
  677. {
  678. struct iriap_cb *self;
  679. __u8 *frame;
  680. __u8 opcode;
  681. self = instance;
  682. IRDA_ASSERT(skb != NULL, return 0;);
  683. IRDA_ASSERT(self != NULL, goto out;);
  684. IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;);
  685. frame = skb->data;
  686. if (self->mode == IAS_SERVER) {
  687. /* Call server */
  688. pr_debug("%s(), Calling server!\n", __func__);
  689. iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
  690. goto out;
  691. }
  692. opcode = frame[0];
  693. if (~opcode & IAP_LST) {
  694. net_warn_ratelimited("%s:, IrIAS multiframe commands or results is not implemented yet!\n",
  695. __func__);
  696. goto out;
  697. }
  698. /* Check for ack frames since they don't contain any data */
  699. if (opcode & IAP_ACK) {
  700. pr_debug("%s() Got ack frame!\n", __func__);
  701. goto out;
  702. }
  703. opcode &= ~IAP_LST; /* Mask away LST bit */
  704. switch (opcode) {
  705. case GET_INFO_BASE:
  706. pr_debug("IrLMP GetInfoBaseDetails not implemented!\n");
  707. break;
  708. case GET_VALUE_BY_CLASS:
  709. iriap_do_call_event(self, IAP_RECV_F_LST, NULL);
  710. switch (frame[1]) {
  711. case IAS_SUCCESS:
  712. iriap_getvaluebyclass_confirm(self, skb);
  713. break;
  714. case IAS_CLASS_UNKNOWN:
  715. pr_debug("%s(), No such class!\n", __func__);
  716. /* Finished, close connection! */
  717. iriap_disconnect_request(self);
  718. /*
  719. * Warning, the client might close us, so remember
  720. * no to use self anymore after calling confirm
  721. */
  722. if (self->confirm)
  723. self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
  724. self->priv);
  725. break;
  726. case IAS_ATTRIB_UNKNOWN:
  727. pr_debug("%s(), No such attribute!\n", __func__);
  728. /* Finished, close connection! */
  729. iriap_disconnect_request(self);
  730. /*
  731. * Warning, the client might close us, so remember
  732. * no to use self anymore after calling confirm
  733. */
  734. if (self->confirm)
  735. self->confirm(IAS_ATTRIB_UNKNOWN, 0, NULL,
  736. self->priv);
  737. break;
  738. }
  739. break;
  740. default:
  741. pr_debug("%s(), Unknown op-code: %02x\n", __func__,
  742. opcode);
  743. break;
  744. }
  745. out:
  746. /* Cleanup - sub-calls will have done skb_get() as needed. */
  747. dev_kfree_skb(skb);
  748. return 0;
  749. }
  750. /*
  751. * Function iriap_call_indication (self, skb)
  752. *
  753. * Received call to server from peer LM-IAS
  754. *
  755. */
  756. void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
  757. {
  758. __u8 *fp;
  759. __u8 opcode;
  760. IRDA_ASSERT(self != NULL, return;);
  761. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  762. IRDA_ASSERT(skb != NULL, return;);
  763. fp = skb->data;
  764. opcode = fp[0];
  765. if (~opcode & 0x80) {
  766. net_warn_ratelimited("%s: IrIAS multiframe commands or results is not implemented yet!\n",
  767. __func__);
  768. return;
  769. }
  770. opcode &= 0x7f; /* Mask away LST bit */
  771. switch (opcode) {
  772. case GET_INFO_BASE:
  773. net_warn_ratelimited("%s: GetInfoBaseDetails not implemented yet!\n",
  774. __func__);
  775. break;
  776. case GET_VALUE_BY_CLASS:
  777. iriap_getvaluebyclass_indication(self, skb);
  778. break;
  779. }
  780. /* skb will be cleaned up in iriap_data_indication */
  781. }
  782. /*
  783. * Function iriap_watchdog_timer_expired (data)
  784. *
  785. * Query has taken too long time, so abort
  786. *
  787. */
  788. static void iriap_watchdog_timer_expired(void *data)
  789. {
  790. struct iriap_cb *self = (struct iriap_cb *) data;
  791. IRDA_ASSERT(self != NULL, return;);
  792. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  793. /* iriap_close(self); */
  794. }
  795. #ifdef CONFIG_PROC_FS
  796. static const char *const ias_value_types[] = {
  797. "IAS_MISSING",
  798. "IAS_INTEGER",
  799. "IAS_OCT_SEQ",
  800. "IAS_STRING"
  801. };
  802. static inline struct ias_object *irias_seq_idx(loff_t pos)
  803. {
  804. struct ias_object *obj;
  805. for (obj = (struct ias_object *) hashbin_get_first(irias_objects);
  806. obj; obj = (struct ias_object *) hashbin_get_next(irias_objects)) {
  807. if (pos-- == 0)
  808. break;
  809. }
  810. return obj;
  811. }
  812. static void *irias_seq_start(struct seq_file *seq, loff_t *pos)
  813. {
  814. spin_lock_irq(&irias_objects->hb_spinlock);
  815. return *pos ? irias_seq_idx(*pos - 1) : SEQ_START_TOKEN;
  816. }
  817. static void *irias_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  818. {
  819. ++*pos;
  820. return (v == SEQ_START_TOKEN)
  821. ? (void *) hashbin_get_first(irias_objects)
  822. : (void *) hashbin_get_next(irias_objects);
  823. }
  824. static void irias_seq_stop(struct seq_file *seq, void *v)
  825. {
  826. spin_unlock_irq(&irias_objects->hb_spinlock);
  827. }
  828. static int irias_seq_show(struct seq_file *seq, void *v)
  829. {
  830. if (v == SEQ_START_TOKEN)
  831. seq_puts(seq, "LM-IAS Objects:\n");
  832. else {
  833. struct ias_object *obj = v;
  834. struct ias_attrib *attrib;
  835. IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -EINVAL;);
  836. seq_printf(seq, "name: %s, id=%d\n",
  837. obj->name, obj->id);
  838. /* Careful for priority inversions here !
  839. * All other uses of attrib spinlock are independent of
  840. * the object spinlock, so we are safe. Jean II */
  841. spin_lock(&obj->attribs->hb_spinlock);
  842. /* List all attributes for this object */
  843. for (attrib = (struct ias_attrib *) hashbin_get_first(obj->attribs);
  844. attrib != NULL;
  845. attrib = (struct ias_attrib *) hashbin_get_next(obj->attribs)) {
  846. IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC,
  847. goto outloop; );
  848. seq_printf(seq, " - Attribute name: \"%s\", ",
  849. attrib->name);
  850. seq_printf(seq, "value[%s]: ",
  851. ias_value_types[attrib->value->type]);
  852. switch (attrib->value->type) {
  853. case IAS_INTEGER:
  854. seq_printf(seq, "%d\n",
  855. attrib->value->t.integer);
  856. break;
  857. case IAS_STRING:
  858. seq_printf(seq, "\"%s\"\n",
  859. attrib->value->t.string);
  860. break;
  861. case IAS_OCT_SEQ:
  862. seq_printf(seq, "octet sequence (%d bytes)\n",
  863. attrib->value->len);
  864. break;
  865. case IAS_MISSING:
  866. seq_puts(seq, "missing\n");
  867. break;
  868. default:
  869. seq_printf(seq, "type %d?\n",
  870. attrib->value->type);
  871. }
  872. seq_putc(seq, '\n');
  873. }
  874. IRDA_ASSERT_LABEL(outloop:)
  875. spin_unlock(&obj->attribs->hb_spinlock);
  876. }
  877. return 0;
  878. }
  879. static const struct seq_operations irias_seq_ops = {
  880. .start = irias_seq_start,
  881. .next = irias_seq_next,
  882. .stop = irias_seq_stop,
  883. .show = irias_seq_show,
  884. };
  885. static int irias_seq_open(struct inode *inode, struct file *file)
  886. {
  887. IRDA_ASSERT( irias_objects != NULL, return -EINVAL;);
  888. return seq_open(file, &irias_seq_ops);
  889. }
  890. const struct file_operations irias_seq_fops = {
  891. .owner = THIS_MODULE,
  892. .open = irias_seq_open,
  893. .read = seq_read,
  894. .llseek = seq_lseek,
  895. .release = seq_release,
  896. };
  897. #endif /* PROC_FS */