timod.c 23 KB

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