timod.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  1. /* $Id: timod.c,v 1.19 2002/02/08 03:57:14 davem Exp $
  2. * timod.c: timod emulation.
  3. *
  4. * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
  5. *
  6. * Streams & timod emulation based on code
  7. * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
  8. *
  9. */
  10. #include <linux/types.h>
  11. #include <linux/kernel.h>
  12. #include <linux/sched.h>
  13. #include <linux/smp.h>
  14. #include <linux/smp_lock.h>
  15. #include <linux/ioctl.h>
  16. #include <linux/fs.h>
  17. #include <linux/file.h>
  18. #include <linux/netdevice.h>
  19. #include <linux/poll.h>
  20. #include <net/sock.h>
  21. #include <asm/uaccess.h>
  22. #include <asm/termios.h>
  23. #include "conv.h"
  24. #include "socksys.h"
  25. asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
  26. static DEFINE_SPINLOCK(timod_pagelock);
  27. static char * page = NULL ;
  28. #ifndef DEBUG_SOLARIS_KMALLOC
  29. #define mykmalloc kmalloc
  30. #define mykfree kfree
  31. #else
  32. void * mykmalloc(size_t s, gfp_t gfp)
  33. {
  34. static char * page;
  35. static size_t free;
  36. void * r;
  37. s = ((s + 63) & ~63);
  38. if( s > PAGE_SIZE ) {
  39. SOLD("too big size, calling real kmalloc");
  40. return kmalloc(s, gfp);
  41. }
  42. if( s > free ) {
  43. /* we are wasting memory, but we don't care */
  44. page = (char *)__get_free_page(gfp);
  45. free = PAGE_SIZE;
  46. }
  47. r = page;
  48. page += s;
  49. free -= s;
  50. return r;
  51. }
  52. void mykfree(void *p)
  53. {
  54. }
  55. #endif
  56. #ifndef DEBUG_SOLARIS
  57. #define BUF_SIZE PAGE_SIZE
  58. #define PUT_MAGIC(a,m)
  59. #define SCHECK_MAGIC(a,m)
  60. #define BUF_OFFSET 0
  61. #define MKCTL_TRAILER 0
  62. #else
  63. #define BUF_SIZE (PAGE_SIZE-2*sizeof(u64))
  64. #define BUFPAGE_MAGIC 0xBADC0DEDDEADBABEL
  65. #define MKCTL_MAGIC 0xDEADBABEBADC0DEDL
  66. #define PUT_MAGIC(a,m) do{(*(u64*)(a))=(m);}while(0)
  67. #define SCHECK_MAGIC(a,m) do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\
  68. __FILE__,__LINE__,__FUNCTION__,(m),(a));}while(0)
  69. #define BUF_OFFSET sizeof(u64)
  70. #define MKCTL_TRAILER sizeof(u64)
  71. #endif
  72. static char *getpage( void )
  73. {
  74. char *r;
  75. SOLD("getting page");
  76. spin_lock(&timod_pagelock);
  77. if (page) {
  78. r = page;
  79. page = NULL;
  80. spin_unlock(&timod_pagelock);
  81. SOLD("got cached");
  82. return r + BUF_OFFSET;
  83. }
  84. spin_unlock(&timod_pagelock);
  85. SOLD("getting new");
  86. r = (char *)__get_free_page(GFP_KERNEL);
  87. PUT_MAGIC(r,BUFPAGE_MAGIC);
  88. PUT_MAGIC(r+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
  89. return r + BUF_OFFSET;
  90. }
  91. static void putpage(char *p)
  92. {
  93. SOLD("putting page");
  94. p = p - BUF_OFFSET;
  95. SCHECK_MAGIC(p,BUFPAGE_MAGIC);
  96. SCHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
  97. spin_lock(&timod_pagelock);
  98. if (page) {
  99. spin_unlock(&timod_pagelock);
  100. free_page((unsigned long)p);
  101. SOLD("freed it");
  102. } else {
  103. page = p;
  104. spin_unlock(&timod_pagelock);
  105. SOLD("cached it");
  106. }
  107. }
  108. static struct T_primsg *timod_mkctl(int size)
  109. {
  110. struct T_primsg *it;
  111. SOLD("creating primsg");
  112. it = (struct T_primsg *)mykmalloc(size+sizeof(*it)-sizeof(s32)+2*MKCTL_TRAILER, GFP_KERNEL);
  113. if (it) {
  114. SOLD("got it");
  115. it->pri = MSG_HIPRI;
  116. it->length = size;
  117. PUT_MAGIC((char*)((u64)(((char *)&it->type)+size+7)&~7),MKCTL_MAGIC);
  118. }
  119. return it;
  120. }
  121. static void timod_wake_socket(unsigned int fd)
  122. {
  123. struct socket *sock;
  124. struct fdtable *fdt;
  125. SOLD("wakeing socket");
  126. fdt = files_fdtable(current->files);
  127. sock = SOCKET_I(fdt->fd[fd]->f_path.dentry->d_inode);
  128. wake_up_interruptible(&sock->wait);
  129. read_lock(&sock->sk->sk_callback_lock);
  130. if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
  131. __kill_fasync(sock->fasync_list, SIGIO, POLL_IN);
  132. read_unlock(&sock->sk->sk_callback_lock);
  133. SOLD("done");
  134. }
  135. static void timod_queue(unsigned int fd, struct T_primsg *it)
  136. {
  137. struct sol_socket_struct *sock;
  138. struct fdtable *fdt;
  139. SOLD("queuing primsg");
  140. fdt = files_fdtable(current->files);
  141. sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data;
  142. it->next = sock->pfirst;
  143. sock->pfirst = it;
  144. if (!sock->plast)
  145. sock->plast = it;
  146. timod_wake_socket(fd);
  147. SOLD("done");
  148. }
  149. static void timod_queue_end(unsigned int fd, struct T_primsg *it)
  150. {
  151. struct sol_socket_struct *sock;
  152. struct fdtable *fdt;
  153. SOLD("queuing primsg at end");
  154. fdt = files_fdtable(current->files);
  155. sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data;
  156. it->next = NULL;
  157. if (sock->plast)
  158. sock->plast->next = it;
  159. else
  160. sock->pfirst = it;
  161. sock->plast = it;
  162. SOLD("done");
  163. }
  164. static void timod_error(unsigned int fd, int prim, int terr, int uerr)
  165. {
  166. struct T_primsg *it;
  167. SOLD("making error");
  168. it = timod_mkctl(sizeof(struct T_error_ack));
  169. if (it) {
  170. struct T_error_ack *err = (struct T_error_ack *)&it->type;
  171. SOLD("got it");
  172. err->PRIM_type = T_ERROR_ACK;
  173. err->ERROR_prim = prim;
  174. err->TLI_error = terr;
  175. err->UNIX_error = uerr; /* FIXME: convert this */
  176. timod_queue(fd, it);
  177. }
  178. SOLD("done");
  179. }
  180. static void timod_ok(unsigned int fd, int prim)
  181. {
  182. struct T_primsg *it;
  183. struct T_ok_ack *ok;
  184. SOLD("creating ok ack");
  185. it = timod_mkctl(sizeof(*ok));
  186. if (it) {
  187. SOLD("got it");
  188. ok = (struct T_ok_ack *)&it->type;
  189. ok->PRIM_type = T_OK_ACK;
  190. ok->CORRECT_prim = prim;
  191. timod_queue(fd, it);
  192. }
  193. SOLD("done");
  194. }
  195. static int timod_optmgmt(unsigned int fd, int flag, char __user *opt_buf, int opt_len, int do_ret)
  196. {
  197. int error, failed;
  198. int ret_space, ret_len;
  199. long args[5];
  200. char *ret_pos,*ret_buf;
  201. int (*sys_socketcall)(int, unsigned long *) =
  202. (int (*)(int, unsigned long *))SYS(socketcall);
  203. mm_segment_t old_fs = get_fs();
  204. SOLD("entry");
  205. SOLDD(("fd %u flg %u buf %p len %u doret %u",fd,flag,opt_buf,opt_len,do_ret));
  206. if (!do_ret && (!opt_buf || opt_len <= 0))
  207. return 0;
  208. SOLD("getting page");
  209. ret_pos = ret_buf = getpage();
  210. ret_space = BUF_SIZE;
  211. ret_len = 0;
  212. error = failed = 0;
  213. SOLD("looping");
  214. while(opt_len >= sizeof(struct opthdr)) {
  215. struct opthdr *opt;
  216. int orig_opt_len;
  217. SOLD("loop start");
  218. opt = (struct opthdr *)ret_pos;
  219. if (ret_space < sizeof(struct opthdr)) {
  220. failed = TSYSERR;
  221. break;
  222. }
  223. SOLD("getting opthdr");
  224. if (copy_from_user(opt, opt_buf, sizeof(struct opthdr)) ||
  225. opt->len > opt_len) {
  226. failed = TBADOPT;
  227. break;
  228. }
  229. SOLD("got opthdr");
  230. if (flag == T_NEGOTIATE) {
  231. char *buf;
  232. SOLD("handling T_NEGOTIATE");
  233. buf = ret_pos + sizeof(struct opthdr);
  234. if (ret_space < opt->len + sizeof(struct opthdr) ||
  235. copy_from_user(buf, opt_buf+sizeof(struct opthdr), opt->len)) {
  236. failed = TSYSERR;
  237. break;
  238. }
  239. SOLD("got optdata");
  240. args[0] = fd;
  241. args[1] = opt->level;
  242. args[2] = opt->name;
  243. args[3] = (long)buf;
  244. args[4] = opt->len;
  245. SOLD("calling SETSOCKOPT");
  246. set_fs(KERNEL_DS);
  247. error = sys_socketcall(SYS_SETSOCKOPT, args);
  248. set_fs(old_fs);
  249. if (error) {
  250. failed = TBADOPT;
  251. break;
  252. }
  253. SOLD("SETSOCKOPT ok");
  254. }
  255. orig_opt_len = opt->len;
  256. opt->len = ret_space - sizeof(struct opthdr);
  257. if (opt->len < 0) {
  258. failed = TSYSERR;
  259. break;
  260. }
  261. args[0] = fd;
  262. args[1] = opt->level;
  263. args[2] = opt->name;
  264. args[3] = (long)(ret_pos+sizeof(struct opthdr));
  265. args[4] = (long)&opt->len;
  266. SOLD("calling GETSOCKOPT");
  267. set_fs(KERNEL_DS);
  268. error = sys_socketcall(SYS_GETSOCKOPT, args);
  269. set_fs(old_fs);
  270. if (error) {
  271. failed = TBADOPT;
  272. break;
  273. }
  274. SOLD("GETSOCKOPT ok");
  275. ret_space -= sizeof(struct opthdr) + opt->len;
  276. ret_len += sizeof(struct opthdr) + opt->len;
  277. ret_pos += sizeof(struct opthdr) + opt->len;
  278. opt_len -= sizeof(struct opthdr) + orig_opt_len;
  279. opt_buf += sizeof(struct opthdr) + orig_opt_len;
  280. SOLD("loop end");
  281. }
  282. SOLD("loop done");
  283. if (do_ret) {
  284. SOLD("generating ret msg");
  285. if (failed)
  286. timod_error(fd, T_OPTMGMT_REQ, failed, -error);
  287. else {
  288. struct T_primsg *it;
  289. it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len);
  290. if (it) {
  291. struct T_optmgmt_ack *ack =
  292. (struct T_optmgmt_ack *)&it->type;
  293. SOLD("got primsg");
  294. ack->PRIM_type = T_OPTMGMT_ACK;
  295. ack->OPT_length = ret_len;
  296. ack->OPT_offset = sizeof(struct T_optmgmt_ack);
  297. ack->MGMT_flags = (failed ? T_FAILURE : flag);
  298. memcpy(((char*)ack)+sizeof(struct T_optmgmt_ack),
  299. ret_buf, ret_len);
  300. timod_queue(fd, it);
  301. }
  302. }
  303. }
  304. SOLDD(("put_page %p\n", ret_buf));
  305. putpage(ret_buf);
  306. SOLD("done");
  307. return 0;
  308. }
  309. int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
  310. char __user *data_buf, int data_len, int flags)
  311. {
  312. int ret, error, terror;
  313. char *buf;
  314. struct file *filp;
  315. struct inode *ino;
  316. struct fdtable *fdt;
  317. struct sol_socket_struct *sock;
  318. mm_segment_t old_fs = get_fs();
  319. long args[6];
  320. int (*sys_socketcall)(int, unsigned long __user *) =
  321. (int (*)(int, unsigned long __user *))SYS(socketcall);
  322. int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int) =
  323. (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int))SYS(sendto);
  324. fdt = files_fdtable(current->files);
  325. filp = fdt->fd[fd];
  326. ino = filp->f_path.dentry->d_inode;
  327. sock = (struct sol_socket_struct *)filp->private_data;
  328. SOLD("entry");
  329. if (get_user(ret, (int __user *)A(ctl_buf)))
  330. return -EFAULT;
  331. switch (ret) {
  332. case T_BIND_REQ:
  333. {
  334. struct T_bind_req req;
  335. SOLDD(("bind %016lx(%016lx)\n", sock, filp));
  336. SOLD("T_BIND_REQ");
  337. if (sock->state != TS_UNBND) {
  338. timod_error(fd, T_BIND_REQ, TOUTSTATE, 0);
  339. return 0;
  340. }
  341. SOLD("state ok");
  342. if (copy_from_user(&req, ctl_buf, sizeof(req))) {
  343. timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
  344. return 0;
  345. }
  346. SOLD("got ctl req");
  347. if (req.ADDR_offset && req.ADDR_length) {
  348. if (req.ADDR_length > BUF_SIZE) {
  349. timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
  350. return 0;
  351. }
  352. SOLD("req size ok");
  353. buf = getpage();
  354. if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) {
  355. timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
  356. putpage(buf);
  357. return 0;
  358. }
  359. SOLD("got ctl data");
  360. args[0] = fd;
  361. args[1] = (long)buf;
  362. args[2] = req.ADDR_length;
  363. SOLD("calling BIND");
  364. set_fs(KERNEL_DS);
  365. error = sys_socketcall(SYS_BIND, args);
  366. set_fs(old_fs);
  367. putpage(buf);
  368. SOLD("BIND returned");
  369. } else
  370. error = 0;
  371. if (!error) {
  372. struct T_primsg *it;
  373. if (req.CONIND_number) {
  374. args[0] = fd;
  375. args[1] = req.CONIND_number;
  376. SOLD("calling LISTEN");
  377. set_fs(KERNEL_DS);
  378. error = sys_socketcall(SYS_LISTEN, args);
  379. set_fs(old_fs);
  380. SOLD("LISTEN done");
  381. }
  382. it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr));
  383. if (it) {
  384. struct T_bind_ack *ack;
  385. ack = (struct T_bind_ack *)&it->type;
  386. ack->PRIM_type = T_BIND_ACK;
  387. ack->ADDR_offset = sizeof(*ack);
  388. ack->ADDR_length = sizeof(struct sockaddr);
  389. ack->CONIND_number = req.CONIND_number;
  390. args[0] = fd;
  391. args[1] = (long)(ack+sizeof(*ack));
  392. args[2] = (long)&ack->ADDR_length;
  393. set_fs(KERNEL_DS);
  394. sys_socketcall(SYS_GETSOCKNAME,args);
  395. set_fs(old_fs);
  396. sock->state = TS_IDLE;
  397. timod_ok(fd, T_BIND_REQ);
  398. timod_queue_end(fd, it);
  399. SOLD("BIND done");
  400. return 0;
  401. }
  402. }
  403. SOLD("some error");
  404. switch (error) {
  405. case -EINVAL:
  406. terror = TOUTSTATE;
  407. error = 0;
  408. break;
  409. case -EACCES:
  410. terror = TACCES;
  411. error = 0;
  412. break;
  413. case -EADDRNOTAVAIL:
  414. case -EADDRINUSE:
  415. terror = TNOADDR;
  416. error = 0;
  417. break;
  418. default:
  419. terror = TSYSERR;
  420. break;
  421. }
  422. timod_error(fd, T_BIND_REQ, terror, -error);
  423. SOLD("BIND done");
  424. return 0;
  425. }
  426. case T_CONN_REQ:
  427. {
  428. struct T_conn_req req;
  429. unsigned short oldflags;
  430. struct T_primsg *it;
  431. SOLD("T_CONN_REQ");
  432. if (sock->state != TS_UNBND && sock->state != TS_IDLE) {
  433. timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
  434. return 0;
  435. }
  436. SOLD("state ok");
  437. if (copy_from_user(&req, ctl_buf, sizeof(req))) {
  438. timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
  439. return 0;
  440. }
  441. SOLD("got ctl req");
  442. if (ctl_len > BUF_SIZE) {
  443. timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
  444. return 0;
  445. }
  446. SOLD("req size ok");
  447. buf = getpage();
  448. if (copy_from_user(buf, ctl_buf, ctl_len)) {
  449. timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
  450. putpage(buf);
  451. return 0;
  452. }
  453. #ifdef DEBUG_SOLARIS
  454. {
  455. char * ptr = buf;
  456. int len = ctl_len;
  457. printk("returned data (%d bytes): ",len);
  458. while( len-- ) {
  459. if (!(len & 7))
  460. printk(" ");
  461. printk("%02x",(unsigned char)*ptr++);
  462. }
  463. printk("\n");
  464. }
  465. #endif
  466. SOLD("got ctl data");
  467. args[0] = fd;
  468. args[1] = (long)buf+req.DEST_offset;
  469. args[2] = req.DEST_length;
  470. oldflags = filp->f_flags;
  471. filp->f_flags &= ~O_NONBLOCK;
  472. SOLD("calling CONNECT");
  473. set_fs(KERNEL_DS);
  474. error = sys_socketcall(SYS_CONNECT, args);
  475. set_fs(old_fs);
  476. filp->f_flags = oldflags;
  477. SOLD("CONNECT done");
  478. if (!error) {
  479. struct T_conn_con *con;
  480. SOLD("no error");
  481. it = timod_mkctl(ctl_len);
  482. if (!it) {
  483. putpage(buf);
  484. return -ENOMEM;
  485. }
  486. con = (struct T_conn_con *)&it->type;
  487. #ifdef DEBUG_SOLARIS
  488. {
  489. char * ptr = buf;
  490. int len = ctl_len;
  491. printk("returned data (%d bytes): ",len);
  492. while( len-- ) {
  493. if (!(len & 7))
  494. printk(" ");
  495. printk("%02x",(unsigned char)*ptr++);
  496. }
  497. printk("\n");
  498. }
  499. #endif
  500. memcpy(con, buf, ctl_len);
  501. SOLD("copied ctl_buf");
  502. con->PRIM_type = T_CONN_CON;
  503. sock->state = TS_DATA_XFER;
  504. } else {
  505. struct T_discon_ind *dis;
  506. SOLD("some error");
  507. it = timod_mkctl(sizeof(*dis));
  508. if (!it) {
  509. putpage(buf);
  510. return -ENOMEM;
  511. }
  512. SOLD("got primsg");
  513. dis = (struct T_discon_ind *)&it->type;
  514. dis->PRIM_type = T_DISCON_IND;
  515. dis->DISCON_reason = -error; /* FIXME: convert this as in iABI_errors() */
  516. dis->SEQ_number = 0;
  517. }
  518. putpage(buf);
  519. timod_ok(fd, T_CONN_REQ);
  520. it->pri = 0;
  521. timod_queue_end(fd, it);
  522. SOLD("CONNECT done");
  523. return 0;
  524. }
  525. case T_OPTMGMT_REQ:
  526. {
  527. struct T_optmgmt_req req;
  528. SOLD("OPTMGMT_REQ");
  529. if (copy_from_user(&req, ctl_buf, sizeof(req)))
  530. return -EFAULT;
  531. SOLD("got req");
  532. return timod_optmgmt(fd, req.MGMT_flags,
  533. req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL,
  534. req.OPT_length, 1);
  535. }
  536. case T_UNITDATA_REQ:
  537. {
  538. struct T_unitdata_req req;
  539. int err;
  540. SOLD("T_UNITDATA_REQ");
  541. if (sock->state != TS_IDLE && sock->state != TS_DATA_XFER) {
  542. timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
  543. return 0;
  544. }
  545. SOLD("state ok");
  546. if (copy_from_user(&req, ctl_buf, sizeof(req))) {
  547. timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
  548. return 0;
  549. }
  550. SOLD("got ctl req");
  551. #ifdef DEBUG_SOLARIS
  552. {
  553. char * ptr = ctl_buf+req.DEST_offset;
  554. int len = req.DEST_length;
  555. printk("socket address (%d bytes): ",len);
  556. while( len-- ) {
  557. char c;
  558. if (get_user(c,ptr))
  559. printk("??");
  560. else
  561. printk("%02x",(unsigned char)c);
  562. ptr++;
  563. }
  564. printk("\n");
  565. }
  566. #endif
  567. err = sys_sendto(fd, data_buf, data_len, 0, req.DEST_length > 0 ? (struct sockaddr __user *)(ctl_buf+req.DEST_offset) : NULL, req.DEST_length);
  568. if (err == data_len)
  569. return 0;
  570. if(err >= 0) {
  571. printk("timod: sendto failed to send all the data\n");
  572. return 0;
  573. }
  574. timod_error(fd, T_CONN_REQ, TSYSERR, -err);
  575. return 0;
  576. }
  577. default:
  578. printk(KERN_INFO "timod_putmsg: unsupported command %u.\n", ret);
  579. break;
  580. }
  581. return -EINVAL;
  582. }
  583. int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __user *ctl_len,
  584. char __user *data_buf, int data_maxlen, s32 __user *data_len, int *flags_p)
  585. {
  586. int error;
  587. int oldflags;
  588. struct file *filp;
  589. struct inode *ino;
  590. struct fdtable *fdt;
  591. struct sol_socket_struct *sock;
  592. struct T_unitdata_ind udi;
  593. mm_segment_t old_fs = get_fs();
  594. long args[6];
  595. char __user *tmpbuf;
  596. int tmplen;
  597. int (*sys_socketcall)(int, unsigned long __user *) =
  598. (int (*)(int, unsigned long __user *))SYS(socketcall);
  599. int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *);
  600. SOLD("entry");
  601. SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p));
  602. fdt = files_fdtable(current->files);
  603. filp = fdt->fd[fd];
  604. ino = filp->f_path.dentry->d_inode;
  605. sock = (struct sol_socket_struct *)filp->private_data;
  606. SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
  607. if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM
  608. && sock->state == TS_IDLE) {
  609. SOLD("calling LISTEN");
  610. args[0] = fd;
  611. args[1] = -1;
  612. set_fs(KERNEL_DS);
  613. sys_socketcall(SYS_LISTEN, args);
  614. set_fs(old_fs);
  615. SOLD("LISTEN done");
  616. }
  617. if (!(filp->f_flags & O_NONBLOCK)) {
  618. struct poll_wqueues wait_table;
  619. poll_table *wait;
  620. poll_initwait(&wait_table);
  621. wait = &wait_table.pt;
  622. for(;;) {
  623. SOLD("loop");
  624. set_current_state(TASK_INTERRUPTIBLE);
  625. /* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
  626. /* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
  627. /* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
  628. /* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */
  629. /* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */
  630. /* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */
  631. if (ctl_maxlen >= 0 && sock->pfirst && (*flags_p != MSG_HIPRI || sock->pfirst->pri == MSG_HIPRI))
  632. break;
  633. SOLD("cond 1 passed");
  634. if (
  635. #if 1
  636. *flags_p != MSG_HIPRI &&
  637. #endif
  638. ((filp->f_op->poll(filp, wait) & POLLIN) ||
  639. (filp->f_op->poll(filp, NULL) & POLLIN) ||
  640. signal_pending(current))
  641. ) {
  642. break;
  643. }
  644. if( *flags_p == MSG_HIPRI ) {
  645. SOLD("avoiding lockup");
  646. break ;
  647. }
  648. if(wait_table.error) {
  649. SOLD("wait-table error");
  650. poll_freewait(&wait_table);
  651. return wait_table.error;
  652. }
  653. SOLD("scheduling");
  654. schedule();
  655. }
  656. SOLD("loop done");
  657. current->state = TASK_RUNNING;
  658. poll_freewait(&wait_table);
  659. if (signal_pending(current)) {
  660. SOLD("signal pending");
  661. return -EINTR;
  662. }
  663. }
  664. if (ctl_maxlen >= 0 && sock->pfirst) {
  665. struct T_primsg *it = sock->pfirst;
  666. int l = min_t(int, ctl_maxlen, it->length);
  667. SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC);
  668. SOLD("purting ctl data");
  669. if(copy_to_user(ctl_buf,
  670. (char*)&it->type + sock->offset, l))
  671. return -EFAULT;
  672. SOLD("pur it");
  673. if(put_user(l, ctl_len))
  674. return -EFAULT;
  675. SOLD("set ctl_len");
  676. *flags_p = it->pri;
  677. it->length -= l;
  678. if (it->length) {
  679. SOLD("more ctl");
  680. sock->offset += l;
  681. return MORECTL;
  682. } else {
  683. SOLD("removing message");
  684. sock->pfirst = it->next;
  685. if (!sock->pfirst)
  686. sock->plast = NULL;
  687. SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst));
  688. mykfree(it);
  689. sock->offset = 0;
  690. SOLD("ctl done");
  691. return 0;
  692. }
  693. }
  694. *flags_p = 0;
  695. if (ctl_maxlen >= 0) {
  696. SOLD("ACCEPT perhaps?");
  697. if (SOCKET_I(ino)->type == SOCK_STREAM && sock->state == TS_IDLE) {
  698. struct T_conn_ind ind;
  699. char *buf = getpage();
  700. int len = BUF_SIZE;
  701. SOLD("trying ACCEPT");
  702. if (put_user(ctl_maxlen - sizeof(ind), ctl_len))
  703. return -EFAULT;
  704. args[0] = fd;
  705. args[1] = (long)buf;
  706. args[2] = (long)&len;
  707. oldflags = filp->f_flags;
  708. filp->f_flags |= O_NONBLOCK;
  709. SOLD("calling ACCEPT");
  710. set_fs(KERNEL_DS);
  711. error = sys_socketcall(SYS_ACCEPT, args);
  712. set_fs(old_fs);
  713. filp->f_flags = oldflags;
  714. if (error < 0) {
  715. SOLD("some error");
  716. putpage(buf);
  717. return error;
  718. }
  719. if (error) {
  720. SOLD("connect");
  721. putpage(buf);
  722. if (sizeof(ind) > ctl_maxlen) {
  723. SOLD("generating CONN_IND");
  724. ind.PRIM_type = T_CONN_IND;
  725. ind.SRC_length = len;
  726. ind.SRC_offset = sizeof(ind);
  727. ind.OPT_length = ind.OPT_offset = 0;
  728. ind.SEQ_number = error;
  729. if(copy_to_user(ctl_buf, &ind, sizeof(ind))||
  730. put_user(sizeof(ind)+ind.SRC_length,ctl_len))
  731. return -EFAULT;
  732. SOLD("CONN_IND created");
  733. }
  734. if (data_maxlen >= 0)
  735. put_user(0, data_len);
  736. SOLD("CONN_IND done");
  737. return 0;
  738. }
  739. if (len>ctl_maxlen) {
  740. SOLD("data don't fit");
  741. putpage(buf);
  742. return -EFAULT; /* XXX - is this ok ? */
  743. }
  744. if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){
  745. SOLD("can't copy data");
  746. putpage(buf);
  747. return -EFAULT;
  748. }
  749. SOLD("ACCEPT done");
  750. putpage(buf);
  751. }
  752. }
  753. SOLD("checking data req");
  754. if (data_maxlen <= 0) {
  755. if (data_maxlen == 0)
  756. put_user(0, data_len);
  757. if (ctl_maxlen >= 0)
  758. put_user(0, ctl_len);
  759. return -EAGAIN;
  760. }
  761. SOLD("wants data");
  762. if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
  763. SOLD("udi fits");
  764. tmpbuf = ctl_buf + sizeof(udi);
  765. tmplen = ctl_maxlen - sizeof(udi);
  766. } else {
  767. SOLD("udi does not fit");
  768. tmpbuf = NULL;
  769. tmplen = 0;
  770. }
  771. if (put_user(tmplen, ctl_len))
  772. return -EFAULT;
  773. SOLD("set ctl_len");
  774. oldflags = filp->f_flags;
  775. filp->f_flags |= O_NONBLOCK;
  776. SOLD("calling recvfrom");
  777. sys_recvfrom = (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom);
  778. error = sys_recvfrom(fd, data_buf, data_maxlen, 0, (struct sockaddr __user *)tmpbuf, ctl_len);
  779. filp->f_flags = oldflags;
  780. if (error < 0)
  781. return error;
  782. SOLD("error >= 0" ) ;
  783. if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
  784. SOLD("generating udi");
  785. udi.PRIM_type = T_UNITDATA_IND;
  786. if (get_user(udi.SRC_length, ctl_len))
  787. return -EFAULT;
  788. udi.SRC_offset = sizeof(udi);
  789. udi.OPT_length = udi.OPT_offset = 0;
  790. if (copy_to_user(ctl_buf, &udi, sizeof(udi)) ||
  791. put_user(sizeof(udi)+udi.SRC_length, ctl_len))
  792. return -EFAULT;
  793. SOLD("udi done");
  794. } else {
  795. if (put_user(0, ctl_len))
  796. return -EFAULT;
  797. }
  798. put_user(error, data_len);
  799. SOLD("done");
  800. return 0;
  801. }
  802. asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
  803. {
  804. struct file *filp;
  805. struct inode *ino;
  806. struct strbuf __user *ctlptr;
  807. struct strbuf __user *datptr;
  808. struct strbuf ctl, dat;
  809. int __user *flgptr;
  810. int flags;
  811. int error = -EBADF;
  812. struct fdtable *fdt;
  813. SOLD("entry");
  814. lock_kernel();
  815. if(fd >= NR_OPEN) goto out;
  816. fdt = files_fdtable(current->files);
  817. filp = fdt->fd[fd];
  818. if(!filp) goto out;
  819. ino = filp->f_path.dentry->d_inode;
  820. if (!ino || !S_ISSOCK(ino->i_mode))
  821. goto out;
  822. ctlptr = (struct strbuf __user *)A(arg1);
  823. datptr = (struct strbuf __user *)A(arg2);
  824. flgptr = (int __user *)A(arg3);
  825. error = -EFAULT;
  826. if (ctlptr) {
  827. if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) ||
  828. put_user(-1,&ctlptr->len))
  829. goto out;
  830. } else
  831. ctl.maxlen = -1;
  832. if (datptr) {
  833. if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) ||
  834. put_user(-1,&datptr->len))
  835. goto out;
  836. } else
  837. dat.maxlen = -1;
  838. if (get_user(flags,flgptr))
  839. goto out;
  840. switch (flags) {
  841. case 0:
  842. case MSG_HIPRI:
  843. case MSG_ANY:
  844. case MSG_BAND:
  845. break;
  846. default:
  847. error = -EINVAL;
  848. goto out;
  849. }
  850. error = timod_getmsg(fd,A(ctl.buf),ctl.maxlen,&ctlptr->len,
  851. A(dat.buf),dat.maxlen,&datptr->len,&flags);
  852. if (!error && put_user(flags,flgptr))
  853. error = -EFAULT;
  854. out:
  855. unlock_kernel();
  856. SOLD("done");
  857. return error;
  858. }
  859. asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
  860. {
  861. struct file *filp;
  862. struct inode *ino;
  863. struct strbuf __user *ctlptr;
  864. struct strbuf __user *datptr;
  865. struct strbuf ctl, dat;
  866. int flags = (int) arg3;
  867. int error = -EBADF;
  868. struct fdtable *fdt;
  869. SOLD("entry");
  870. lock_kernel();
  871. if(fd >= NR_OPEN) goto out;
  872. fdt = files_fdtable(current->files);
  873. filp = fdt->fd[fd];
  874. if(!filp) goto out;
  875. ino = filp->f_path.dentry->d_inode;
  876. if (!ino) goto out;
  877. if (!S_ISSOCK(ino->i_mode) &&
  878. (imajor(ino) != 30 || iminor(ino) != 1))
  879. goto out;
  880. ctlptr = A(arg1);
  881. datptr = A(arg2);
  882. error = -EFAULT;
  883. if (ctlptr) {
  884. if (copy_from_user(&ctl,ctlptr,sizeof(ctl)))
  885. goto out;
  886. if (ctl.len < 0 && flags) {
  887. error = -EINVAL;
  888. goto out;
  889. }
  890. } else {
  891. ctl.len = 0;
  892. ctl.buf = 0;
  893. }
  894. if (datptr) {
  895. if (copy_from_user(&dat,datptr,sizeof(dat)))
  896. goto out;
  897. } else {
  898. dat.len = 0;
  899. dat.buf = 0;
  900. }
  901. error = timod_putmsg(fd,A(ctl.buf),ctl.len,
  902. A(dat.buf),dat.len,flags);
  903. out:
  904. unlock_kernel();
  905. SOLD("done");
  906. return error;
  907. }