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