This source file includes following definitions.
- dprintf
- min
- sockaddr_un_printk
- unix_lock
- unix_unlock
- unix_proto_listen
- unix_proto_setsockopt
- unix_proto_getsockopt
- unix_proto_sendto
- unix_proto_recvfrom
- unix_proto_shutdown
- unix_proto_send
- unix_proto_recv
- unix_data_lookup
- unix_data_alloc
- unix_data_ref
- unix_data_deref
- unix_proto_create
- unix_proto_dup
- unix_proto_release
- unix_proto_bind
- unix_proto_connect
- unix_proto_socketpair
- unix_proto_accept
- unix_proto_getname
- unix_proto_read
- unix_proto_write
- unix_proto_select
- unix_proto_ioctl
- unix_open
- unix_close
- unix_ioctl
- unix_proto_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <linux/config.h>
30 #include <linux/kernel.h>
31 #include <linux/major.h>
32 #include <linux/signal.h>
33 #include <linux/sched.h>
34 #include <linux/errno.h>
35 #include <linux/string.h>
36 #include <linux/stat.h>
37 #include <linux/socket.h>
38 #include <linux/un.h>
39 #include <linux/fcntl.h>
40 #include <linux/termios.h>
41 #include <linux/sockios.h>
42 #include <linux/net.h>
43 #include <linux/fs.h>
44 #include <linux/ddi.h>
45 #include <linux/malloc.h>
46
47 #include <asm/system.h>
48 #include <asm/segment.h>
49
50 #include <stdarg.h>
51
52 #include "unix.h"
53
54 struct unix_proto_data unix_datas[NSOCKETS];
55 static int unix_debug = 0;
56
57
58 static int unix_proto_create(struct socket *sock, int protocol);
59 static int unix_proto_dup(struct socket *newsock, struct socket *oldsock);
60 static int unix_proto_release(struct socket *sock, struct socket *peer);
61 static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
62 int sockaddr_len);
63 static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
64 int sockaddr_len, int flags);
65 static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2);
66 static int unix_proto_accept(struct socket *sock, struct socket *newsock,
67 int flags);
68 static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
69 int *usockaddr_len, int peer);
70 static int unix_proto_read(struct socket *sock, char *ubuf, int size,
71 int nonblock);
72 static int unix_proto_write(struct socket *sock, char *ubuf, int size,
73 int nonblock);
74 static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait);
75 static int unix_proto_ioctl(struct socket *sock, unsigned int cmd,
76 unsigned long arg);
77 static int unix_proto_listen(struct socket *sock, int backlog);
78 static int unix_proto_send(struct socket *sock, void *buff, int len,
79 int nonblock, unsigned flags);
80 static int unix_proto_recv(struct socket *sock, void *buff, int len,
81 int nonblock, unsigned flags);
82 static int unix_proto_sendto(struct socket *sock, void *buff, int len,
83 int nonblock, unsigned flags,
84 struct sockaddr *addr, int addr_len);
85 static int unix_proto_recvfrom(struct socket *sock, void *buff, int len,
86 int nonblock, unsigned flags,
87 struct sockaddr *addr, int *addr_len);
88
89 static int unix_proto_shutdown(struct socket *sock, int how);
90
91 static int unix_proto_setsockopt(struct socket *sock, int level, int optname,
92 char *optval, int optlen);
93 static int unix_proto_getsockopt(struct socket *sock, int level, int optname,
94 char *optval, int *optlen);
95
96
97 static void
98 dprintf(int level, char *fmt, ...)
99 {
100 va_list args;
101 char *buff;
102 extern int vsprintf(char * buf, const char * fmt, va_list args);
103
104 if (level != unix_debug) return;
105
106 buff = (char *) kmalloc(256, GFP_KERNEL);
107 if (buff != NULL) {
108 va_start(args, fmt);
109 vsprintf(buff, fmt, args);
110 va_end(args);
111 printk(buff);
112 kfree(buff);
113 }
114 }
115
116
117 static inline int
118 min(int a, int b)
119 {
120 if (a < b) return(a);
121 return(b);
122 }
123
124
125 void
126 sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
127 {
128 char buf[sizeof(sockun->sun_path) + 1];
129
130 if (unix_debug == 0) return;
131
132 sockaddr_len -= UN_PATH_OFFSET;
133 if (sockun->sun_family != AF_UNIX)
134 printk("UNIX: Badd addr family %d>\n", sockun->sun_family);
135 else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf))
136 printk("UNIX: Bad addr len %d>\n", sockaddr_len);
137 else {
138 memcpy(buf, sockun->sun_path, sockaddr_len);
139 buf[sockaddr_len] = '\0';
140 printk("\"%s\"[%lu]\n", buf, sockaddr_len + UN_PATH_OFFSET);
141 }
142 }
143
144
145
146
147
148
149
150
151
152
153
154 void unix_lock(struct unix_proto_data *upd)
155 {
156 while (upd->lock_flag)
157 sleep_on(&upd->wait);
158 upd->lock_flag = 1;
159 }
160
161
162 void unix_unlock(struct unix_proto_data *upd)
163 {
164 upd->lock_flag = 0;
165 wake_up(&upd->wait);
166 }
167
168
169 static int
170 unix_proto_listen(struct socket *sock, int backlog)
171 {
172 return(0);
173 }
174
175
176 static int
177 unix_proto_setsockopt(struct socket *sock, int level, int optname,
178 char *optval, int optlen)
179 {
180 return(-EOPNOTSUPP);
181 }
182
183
184 static int
185 unix_proto_getsockopt(struct socket *sock, int level, int optname,
186 char *optval, int *optlen)
187 {
188 return(-EOPNOTSUPP);
189 }
190
191 static int
192 unix_proto_sendto(struct socket *sock, void *buff, int len, int nonblock,
193 unsigned flags, struct sockaddr *addr, int addr_len)
194 {
195 return(-EOPNOTSUPP);
196 }
197
198 static int
199 unix_proto_recvfrom(struct socket *sock, void *buff, int len, int nonblock,
200 unsigned flags, struct sockaddr *addr, int *addr_len)
201 {
202 return(-EOPNOTSUPP);
203 }
204
205
206 static int
207 unix_proto_shutdown(struct socket *sock, int how)
208 {
209 return(-EOPNOTSUPP);
210 }
211
212
213
214 static int
215 unix_proto_send(struct socket *sock, void *buff, int len, int nonblock,
216 unsigned flags)
217 {
218 if (flags != 0) return(-EINVAL);
219 return(unix_proto_write(sock, (char *) buff, len, nonblock));
220 }
221
222
223
224 static int
225 unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
226 unsigned flags)
227 {
228 if (flags != 0) return(-EINVAL);
229 return(unix_proto_read(sock, (char *) buff, len, nonblock));
230 }
231
232
233 static struct unix_proto_data *
234 unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len,
235 struct inode *inode)
236 {
237 struct unix_proto_data *upd;
238
239 for(upd = unix_datas; upd <= last_unix_data; ++upd) {
240 if (upd->refcnt && upd->socket &&
241 upd->socket->state == SS_UNCONNECTED &&
242 upd->sockaddr_un.sun_family == sockun->sun_family &&
243 upd->inode == inode) return(upd);
244 }
245 return(NULL);
246 }
247
248
249 static struct unix_proto_data *
250 unix_data_alloc(void)
251 {
252 struct unix_proto_data *upd;
253
254 cli();
255 for(upd = unix_datas; upd <= last_unix_data; ++upd) {
256 if (!upd->refcnt) {
257 upd->refcnt = 1;
258 sti();
259 upd->socket = NULL;
260 upd->sockaddr_len = 0;
261 upd->sockaddr_un.sun_family = 0;
262 upd->buf = NULL;
263 upd->bp_head = upd->bp_tail = 0;
264 upd->inode = NULL;
265 upd->peerupd = NULL;
266 return(upd);
267 }
268 }
269 sti();
270 return(NULL);
271 }
272
273
274 static inline void
275 unix_data_ref(struct unix_proto_data *upd)
276 {
277 if (!upd) {
278 dprintf(1, "UNIX: data_ref: upd = NULL\n");
279 return;
280 }
281 ++upd->refcnt;
282 dprintf(1, "UNIX: data_ref: refing data 0x%x(%d)\n", upd, upd->refcnt);
283 }
284
285
286 static void
287 unix_data_deref(struct unix_proto_data *upd)
288 {
289 if (!upd) {
290 dprintf(1, "UNIX: data_deref: upd = NULL\n");
291 return;
292 }
293 if (upd->refcnt == 1) {
294 dprintf(1, "UNIX: data_deref: releasing data 0x%x\n", upd);
295 if (upd->buf) {
296 free_page((unsigned long)upd->buf);
297 upd->buf = NULL;
298 upd->bp_head = upd->bp_tail = 0;
299 }
300 }
301 --upd->refcnt;
302 }
303
304
305
306
307
308
309 static int
310 unix_proto_create(struct socket *sock, int protocol)
311 {
312 struct unix_proto_data *upd;
313
314 dprintf(1, "UNIX: create: socket 0x%x, proto %d\n", sock, protocol);
315 if (protocol != 0) {
316 dprintf(1, "UNIX: create: protocol != 0\n");
317 return(-EINVAL);
318 }
319 if (!(upd = unix_data_alloc())) {
320 printk("UNIX: create: can't allocate buffer\n");
321 return(-ENOMEM);
322 }
323 if (!(upd->buf = (char*) get_free_page(GFP_USER))) {
324 printk("UNIX: create: can't get page!\n");
325 unix_data_deref(upd);
326 return(-ENOMEM);
327 }
328 upd->protocol = protocol;
329 upd->socket = sock;
330 UN_DATA(sock) = upd;
331 dprintf(1, "UNIX: create: allocated data 0x%x\n", upd);
332 return(0);
333 }
334
335
336 static int
337 unix_proto_dup(struct socket *newsock, struct socket *oldsock)
338 {
339 struct unix_proto_data *upd = UN_DATA(oldsock);
340
341 return(unix_proto_create(newsock, upd->protocol));
342 }
343
344
345 static int
346 unix_proto_release(struct socket *sock, struct socket *peer)
347 {
348 struct unix_proto_data *upd = UN_DATA(sock);
349
350 dprintf(1, "UNIX: release: socket 0x%x, unix_data 0x%x\n", sock, upd);
351 if (!upd) return(0);
352 if (upd->socket != sock) {
353 printk("UNIX: release: socket link mismatch!\n");
354 return(-EINVAL);
355 }
356 if (upd->inode) {
357 dprintf(1, "UNIX: release: releasing inode 0x%x\n", upd->inode);
358 iput(upd->inode);
359 upd->inode = NULL;
360 }
361 UN_DATA(sock) = NULL;
362 upd->socket = NULL;
363 if (upd->peerupd) unix_data_deref(upd->peerupd);
364 unix_data_deref(upd);
365 return(0);
366 }
367
368
369
370
371
372
373
374
375
376
377
378 static int
379 unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
380 int sockaddr_len)
381 {
382 char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
383 struct unix_proto_data *upd = UN_DATA(sock);
384 unsigned long old_fs;
385 int i;
386 int er;
387
388 dprintf(1, "UNIX: bind: socket 0x%x, len=%d\n", sock, sockaddr_len);
389 if (sockaddr_len <= UN_PATH_OFFSET ||
390 sockaddr_len > sizeof(struct sockaddr_un)) {
391 dprintf(1, "UNIX: bind: bad length %d\n", sockaddr_len);
392 return(-EINVAL);
393 }
394 if (upd->sockaddr_len || upd->inode) {
395 printk("UNIX: bind: already bound!\n");
396 return(-EINVAL);
397 }
398 er=verify_area(VERIFY_WRITE, umyaddr, sockaddr_len);
399 if(er)
400 return er;
401 memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len);
402 upd->sockaddr_un.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
403 if (upd->sockaddr_un.sun_family != AF_UNIX) {
404 dprintf(1, "UNIX: bind: family is %d, not AF_UNIX(%d)\n",
405 upd->sockaddr_un.sun_family, AF_UNIX);
406 return(-EINVAL);
407 }
408
409 memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
410 fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
411 old_fs = get_fs();
412 set_fs(get_ds());
413 i = do_mknod(fname, S_IFSOCK | S_IRWXUGO, 0);
414 if (i == 0) i = open_namei(fname, 0, S_IFSOCK, &upd->inode, NULL);
415 set_fs(old_fs);
416 if (i < 0) {
417 printk("UNIX: bind: can't open socket %s\n", fname);
418 return(i);
419 }
420 upd->sockaddr_len = sockaddr_len;
421
422 dprintf(1, "UNIX: bind: bound socket address: ");
423 sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
424 dprintf(1, "to inode 0x%x\n", upd->inode);
425 return(0);
426 }
427
428
429
430
431
432
433
434 static int
435 unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
436 int sockaddr_len, int flags)
437 {
438 char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
439 struct sockaddr_un sockun;
440 struct unix_proto_data *serv_upd;
441 struct inode *inode;
442 unsigned long old_fs;
443 int i;
444 int er;
445
446 dprintf(1, "UNIX: connect: socket 0x%x, servlen=%d\n", sock, sockaddr_len);
447
448 if (sockaddr_len <= UN_PATH_OFFSET ||
449 sockaddr_len > sizeof(struct sockaddr_un)) {
450 dprintf(1, "UNIX: connect: bad length %d\n", sockaddr_len);
451 return(-EINVAL);
452 }
453 if (sock->state == SS_CONNECTING) return(-EINPROGRESS);
454 if (sock->state == SS_CONNECTED) return(-EISCONN);
455
456 er=verify_area(VERIFY_READ, uservaddr, sockaddr_len);
457 if(er)
458 return er;
459 memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
460 sockun.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
461 if (sockun.sun_family != AF_UNIX) {
462 dprintf(1, "UNIX: connect: family is %d, not AF_UNIX(%d)\n",
463 sockun.sun_family, AF_UNIX);
464 return(-EINVAL);
465 }
466
467
468
469
470
471
472
473 memcpy(fname, sockun.sun_path, sockaddr_len-UN_PATH_OFFSET);
474 fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
475 old_fs = get_fs();
476 set_fs(get_ds());
477 i = open_namei(fname, 0, S_IFSOCK, &inode, NULL);
478 set_fs(old_fs);
479 if (i < 0) {
480 dprintf(1, "UNIX: connect: can't open socket %s\n", fname);
481 return(i);
482 }
483 serv_upd = unix_data_lookup(&sockun, sockaddr_len, inode);
484 iput(inode);
485 if (!serv_upd) {
486 dprintf(1, "UNIX: connect: can't locate peer %s at inode 0x%x\n",
487 fname, inode);
488 return(-EINVAL);
489 }
490 if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
491 dprintf(1, "UNIX: connect: can't await connection\n");
492 return(i);
493 }
494 if (sock->conn) {
495 unix_data_ref(UN_DATA(sock->conn));
496 UN_DATA(sock)->peerupd = UN_DATA(sock->conn);
497 }
498 return(0);
499 }
500
501
502
503
504
505
506
507
508 static int
509 unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
510 {
511 struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
512
513 unix_data_ref(upd1);
514 unix_data_ref(upd2);
515 upd1->peerupd = upd2;
516 upd2->peerupd = upd1;
517 return(0);
518 }
519
520
521
522 static int
523 unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
524 {
525 struct socket *clientsock;
526
527 dprintf(1, "UNIX: accept: socket 0x%x accepted via socket 0x%x\n",
528 sock, newsock);
529
530
531
532
533
534 while(!(clientsock = sock->iconn)) {
535 if (flags & O_NONBLOCK) return(-EAGAIN);
536 interruptible_sleep_on(sock->wait);
537 if (current->signal & ~current->blocked) {
538 dprintf(1, "UNIX: accept: sleep was interrupted\n");
539 return(-ERESTARTSYS);
540 }
541 }
542
543
544
545
546
547 sock->iconn = clientsock->next;
548 clientsock->next = NULL;
549 newsock->conn = clientsock;
550 clientsock->conn = newsock;
551 clientsock->state = SS_CONNECTED;
552 newsock->state = SS_CONNECTED;
553 unix_data_ref(UN_DATA(clientsock));
554 UN_DATA(newsock)->peerupd = UN_DATA(clientsock);
555 UN_DATA(newsock)->sockaddr_un = UN_DATA(sock)->sockaddr_un;
556 UN_DATA(newsock)->sockaddr_len = UN_DATA(sock)->sockaddr_len;
557 wake_up(clientsock->wait);
558 return(0);
559 }
560
561
562
563 static int
564 unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
565 int *usockaddr_len, int peer)
566 {
567 struct unix_proto_data *upd;
568 int len;
569 int er;
570
571 dprintf(1, "UNIX: getname: socket 0x%x for %s\n", sock, peer?"peer":"self");
572 if (peer) {
573 if (sock->state != SS_CONNECTED) {
574 dprintf(1, "UNIX: getname: socket not connected\n");
575 return(-EINVAL);
576 }
577 upd = UN_DATA(sock->conn);
578 } else
579 upd = UN_DATA(sock);
580
581 er=verify_area(VERIFY_WRITE, usockaddr_len, sizeof(*usockaddr_len));
582 if(er)
583 return er;
584 if ((len = get_fs_long(usockaddr_len)) <= 0) return(-EINVAL);
585 if (len > upd->sockaddr_len) len = upd->sockaddr_len;
586 if (len) {
587 er=verify_area(VERIFY_WRITE, usockaddr, len);
588 if(er)
589 return er;
590 memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
591 }
592 put_fs_long(len, usockaddr_len);
593 return(0);
594 }
595
596
597
598 static int
599 unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
600 {
601 struct unix_proto_data *upd;
602 int todo, avail;
603 int er;
604
605 if ((todo = size) <= 0) return(0);
606 upd = UN_DATA(sock);
607 while(!(avail = UN_BUF_AVAIL(upd))) {
608 if (sock->state != SS_CONNECTED) {
609 dprintf(1, "UNIX: read: socket not connected\n");
610 return((sock->state == SS_DISCONNECTING) ? 0 : -EINVAL);
611 }
612 dprintf(1, "UNIX: read: no data available...\n");
613 if (nonblock) return(-EAGAIN);
614 interruptible_sleep_on(sock->wait);
615 if (current->signal & ~current->blocked) {
616 dprintf(1, "UNIX: read: interrupted\n");
617 return(-ERESTARTSYS);
618 }
619 }
620
621
622
623
624
625
626 unix_lock(upd);
627 do {
628 int part, cando;
629
630 if (avail <= 0) {
631 printk("UNIX: read: AVAIL IS NEGATIVE!!!\n");
632 send_sig(SIGKILL, current, 1);
633 return(-EPIPE);
634 }
635
636 if ((cando = todo) > avail) cando = avail;
637 if (cando >(part = BUF_SIZE - upd->bp_tail)) cando = part;
638 dprintf(1, "UNIX: read: avail=%d, todo=%d, cando=%d\n",
639 avail, todo, cando);
640 if((er=verify_area(VERIFY_WRITE,ubuf,cando))<0)
641 {
642 unix_unlock(upd);
643 return er;
644 }
645 memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
646 upd->bp_tail =(upd->bp_tail + cando) &(BUF_SIZE-1);
647 ubuf += cando;
648 todo -= cando;
649 if (sock->state == SS_CONNECTED) wake_up(sock->conn->wait);
650 avail = UN_BUF_AVAIL(upd);
651 } while(todo && avail);
652 unix_unlock(upd);
653 return(size - todo);
654 }
655
656
657
658
659
660
661
662 static int
663 unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
664 {
665 struct unix_proto_data *pupd;
666 int todo, space;
667 int er;
668
669 if ((todo = size) <= 0) return(0);
670 if (sock->state != SS_CONNECTED) {
671 dprintf(1, "UNIX: write: socket not connected\n");
672 if (sock->state == SS_DISCONNECTING) {
673 send_sig(SIGPIPE, current, 1);
674 return(-EPIPE);
675 }
676 return(-EINVAL);
677 }
678 pupd = UN_DATA(sock)->peerupd;
679
680 while(!(space = UN_BUF_SPACE(pupd))) {
681 dprintf(1, "UNIX: write: no space left...\n");
682 if (nonblock) return(-EAGAIN);
683 interruptible_sleep_on(sock->wait);
684 if (current->signal & ~current->blocked) {
685 dprintf(1, "UNIX: write: interrupted\n");
686 return(-ERESTARTSYS);
687 }
688 if (sock->state == SS_DISCONNECTING) {
689 dprintf(1, "UNIX: write: disconnected(SIGPIPE)\n");
690 send_sig(SIGPIPE, current, 1);
691 return(-EPIPE);
692 }
693 }
694
695
696
697
698
699
700 unix_lock(pupd);
701
702 do {
703 int part, cando;
704
705 if (space <= 0) {
706 printk("UNIX: write: SPACE IS NEGATIVE!!!\n");
707 send_sig(SIGKILL, current, 1);
708 return(-EPIPE);
709 }
710
711
712
713
714
715 if (sock->state == SS_DISCONNECTING) {
716 send_sig(SIGPIPE, current, 1);
717 unix_unlock(pupd);
718 return(-EPIPE);
719 }
720 if ((cando = todo) > space) cando = space;
721 if (cando >(part = BUF_SIZE - pupd->bp_head)) cando = part;
722 dprintf(1, "UNIX: write: space=%d, todo=%d, cando=%d\n",
723 space, todo, cando);
724 er=verify_area(VERIFY_READ, ubuf, cando);
725 if(er)
726 {
727 unix_unlock(pupd);
728 return er;
729 }
730 memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
731 pupd->bp_head =(pupd->bp_head + cando) &(BUF_SIZE-1);
732 ubuf += cando;
733 todo -= cando;
734 if (sock->state == SS_CONNECTED) wake_up(sock->conn->wait);
735 space = UN_BUF_SPACE(pupd);
736 } while(todo && space);
737 unix_unlock(pupd);
738 return(size - todo);
739 }
740
741
742 static int
743 unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
744 {
745 struct unix_proto_data *upd, *peerupd;
746
747
748 if (sock->flags & SO_ACCEPTCON) {
749 if (sel_type == SEL_IN) {
750 dprintf(1, "UNIX: select: %sconnections pending\n",
751 sock->iconn ? "" : "no ");
752 if (sock->iconn) return(1);
753 select_wait(sock->wait, wait);
754 return(sock->iconn ? 1 : 0);
755 }
756 dprintf(1, "UNIX: select: nothing else for server socket\n");
757 select_wait(sock->wait, wait);
758 return(0);
759 }
760
761 if (sel_type == SEL_IN) {
762 upd = UN_DATA(sock);
763 dprintf(1, "UNIX: select: there is%s data available\n",
764 UN_BUF_AVAIL(upd) ? "" : " no");
765 if (UN_BUF_AVAIL(upd))
766 return(1);
767 else if (sock->state != SS_CONNECTED) {
768 dprintf(1, "UNIX: select: socket not connected(read EOF)\n");
769 return(1);
770 }
771 select_wait(sock->wait,wait);
772 return(0);
773 }
774 if (sel_type == SEL_OUT) {
775 if (sock->state != SS_CONNECTED) {
776 dprintf(1, "UNIX: select: socket not connected(write EOF)\n");
777 return(1);
778 }
779 peerupd = UN_DATA(sock->conn);
780 dprintf(1, "UNIX: select: there is%s space available\n",
781 UN_BUF_SPACE(peerupd) ? "" : " no");
782 if (UN_BUF_SPACE(peerupd) > 0) return(1);
783 select_wait(sock->wait,wait);
784 return(0);
785 }
786
787
788 dprintf(1, "UNIX: select: there are no exceptions here?!\n");
789 return(0);
790 }
791
792
793 static int
794 unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
795 {
796 struct unix_proto_data *upd, *peerupd;
797 int er;
798
799 upd = UN_DATA(sock);
800 peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
801
802 switch(cmd) {
803 case TIOCINQ:
804 if (sock->flags & SO_ACCEPTCON) return(-EINVAL);
805 er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
806 if(er)
807 return er;
808 if (UN_BUF_AVAIL(upd) || peerupd)
809 put_fs_long(UN_BUF_AVAIL(upd),(unsigned long *)arg);
810 else
811 put_fs_long(0,(unsigned long *)arg);
812 break;
813 case TIOCOUTQ:
814 if (sock->flags & SO_ACCEPTCON) return(-EINVAL);
815 er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
816 if(er)
817 return er;
818 if (peerupd) put_fs_long(UN_BUF_SPACE(peerupd),
819 (unsigned long *)arg);
820 else
821 put_fs_long(0,(unsigned long *)arg);
822 break;
823 default:
824 return(-EINVAL);
825 }
826 return(0);
827 }
828
829
830 static int
831 unix_open(struct inode * inode, struct file * file)
832 {
833 int minor;
834
835 dprintf(1, "UNIX: open\n");
836 minor = MINOR(inode->i_rdev);
837 if (minor != 0) return(-ENODEV);
838
839 return(0);
840 }
841
842
843 static void
844 unix_close(struct inode * inode, struct file * file)
845 {
846 dprintf(1, "UNIX: close\n");
847 }
848
849
850 static int
851 unix_ioctl(struct inode *inode, struct file *file,
852 unsigned int cmd, unsigned long arg)
853 {
854 int minor, ret;
855 int er;
856
857 dprintf(1, "UNIX: ioctl(0x%X, 0x%X)\n", cmd, arg);
858 minor = MINOR(inode->i_rdev);
859 if (minor != 0) return(-ENODEV);
860
861 ret = -EINVAL;
862 switch(cmd) {
863 case DDIOCSDBG:
864 er=verify_area(VERIFY_READ,(void *)arg, sizeof(int));
865 if(er)
866 return er;
867 unix_debug = get_fs_long((int *)arg);
868 if (unix_debug != 0 && unix_debug != 1) {
869 unix_debug = 0;
870 return(-EINVAL);
871 }
872 return(0);
873 case SIOCSIFLINK:
874 printk("UNIX: cannot link streams!\n");
875 break;
876 default:
877 break;
878 }
879 return(ret);
880 }
881
882
883
884
885 static struct file_operations unix_fops = {
886 NULL,
887 NULL,
888 NULL,
889 NULL,
890 NULL,
891 unix_ioctl,
892 NULL,
893 unix_open,
894 unix_close
895 };
896
897
898 static struct proto_ops unix_proto_ops = {
899 AF_UNIX,
900 unix_proto_create,
901 unix_proto_dup,
902 unix_proto_release,
903 unix_proto_bind,
904 unix_proto_connect,
905 unix_proto_socketpair,
906 unix_proto_accept,
907 unix_proto_getname,
908 unix_proto_read,
909 unix_proto_write,
910 unix_proto_select,
911 unix_proto_ioctl,
912 unix_proto_listen,
913 unix_proto_send,
914 unix_proto_recv,
915 unix_proto_sendto,
916 unix_proto_recvfrom,
917 unix_proto_shutdown,
918 unix_proto_setsockopt,
919 unix_proto_getsockopt,
920 NULL
921 };
922
923
924 void
925 unix_proto_init(struct ddi_proto *pro)
926 {
927 struct unix_proto_data *upd;
928
929 dprintf(1, "%s: init: initializing...\n", pro->name);
930 if (register_chrdev(AF_UNIX_MAJOR, "af_unix", &unix_fops) < 0) {
931 printk("%s: cannot register major device %d!\n",
932 pro->name, AF_UNIX_MAJOR);
933 return;
934 }
935
936
937 (void) sock_register(unix_proto_ops.family, &unix_proto_ops);
938
939 for(upd = unix_datas; upd <= last_unix_data; ++upd) {
940 upd->refcnt = 0;
941 }
942 }