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