~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sparc64/solaris/timod.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.14 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.57 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.138 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.193 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp