|
|
1.1.1.4 root 1: #include <linux/signal.h>
1.1 root 2: #include <linux/sched.h>
3: #include <linux/kernel.h>
1.1.1.4 root 4: #include <linux/errno.h>
5: #include <linux/string.h>
1.1.1.2 root 6: #include <linux/stat.h>
1.1.1.4 root 7: #include <linux/socket.h>
8: #include <linux/un.h>
9: #include <linux/fcntl.h>
10: #include <linux/termios.h>
11:
1.1 root 12: #include <asm/system.h>
13: #include <asm/segment.h>
1.1.1.4 root 14:
1.1 root 15: #include "kern_sock.h"
16:
17: static struct unix_proto_data {
18: int refcnt; /* cnt of reference 0=free */
19: struct socket *socket; /* socket we're bound to */
20: int protocol;
21: struct sockaddr_un sockaddr_un;
22: short sockaddr_len; /* >0 if name bound */
23: char *buf;
24: int bp_head, bp_tail;
25: struct inode *inode;
26: struct unix_proto_data *peerupd;
27: } unix_datas[NSOCKETS];
28: #define last_unix_data (unix_datas + NSOCKETS - 1)
29:
30: #define UN_DATA(SOCK) ((struct unix_proto_data *)(SOCK)->data)
31: #define UN_PATH_OFFSET ((unsigned long)((struct sockaddr_un *)0)->sun_path)
32:
33: /*
34: * buffer size must be power of 2. buffer mgmt inspired by pipe code.
35: * note that buffer contents can wraparound, and we can write one byte less
36: * than full size to discern full vs empty.
37: */
38: #define BUF_SIZE PAGE_SIZE
39: #define UN_BUF_AVAIL(UPD) (((UPD)->bp_head - (UPD)->bp_tail) & (BUF_SIZE-1))
40: #define UN_BUF_SPACE(UPD) ((BUF_SIZE-1) - UN_BUF_AVAIL(UPD))
41:
42: static int unix_proto_init(void);
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,
1.1.1.5 ! root 49: int sockaddr_len, int flags);
1.1 root 50: static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2);
1.1.1.5 ! root 51: static int unix_proto_accept(struct socket *sock, struct socket *newsock,
! 52: int flags);
1.1 root 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);
1.1.1.4 root 59: static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait);
1.1 root 60: static int unix_proto_ioctl(struct socket *sock, unsigned int cmd,
61: unsigned long arg);
1.1.1.5 ! root 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);
1.1 root 80:
81: struct proto_ops unix_proto_ops = {
82: unix_proto_init,
83: unix_proto_create,
84: unix_proto_dup,
85: unix_proto_release,
86: unix_proto_bind,
87: unix_proto_connect,
88: unix_proto_socketpair,
89: unix_proto_accept,
90: unix_proto_getname,
91: unix_proto_read,
92: unix_proto_write,
93: unix_proto_select,
1.1.1.5 ! root 94: unix_proto_ioctl,
! 95: unix_proto_listen,
! 96: unix_proto_send,
! 97: unix_proto_recv,
! 98: unix_proto_sendto,
! 99: unix_proto_recvfrom,
! 100: unix_proto_shutdown,
! 101: unix_proto_setsockopt,
! 102: unix_proto_getsockopt,
! 103: NULL /* unix_proto_fcntl. */
1.1 root 104: };
105:
106: #ifdef SOCK_DEBUG
107: void
108: sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
109: {
110: char buf[sizeof(sockun->sun_path) + 1];
111:
112: sockaddr_len -= UN_PATH_OFFSET;
113: if (sockun->sun_family != AF_UNIX)
114: printk("sockaddr_un: <BAD FAMILY: %d>\n", sockun->sun_family);
115: else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf)-1)
116: printk("sockaddr_un: <BAD LENGTH: %d>\n", sockaddr_len);
117: else {
118: memcpy(buf, sockun->sun_path, sockaddr_len);
119: buf[sockaddr_len] = '\0';
120: printk("sockaddr_un: '%s'[%d]\n", buf,
121: sockaddr_len + UN_PATH_OFFSET);
122: }
123: }
124: #endif
1.1.1.5 ! root 125:
! 126: /* don't have to do anything. */
! 127: static int
! 128: unix_proto_listen (struct socket *sock, int backlog)
! 129: {
! 130: return (0);
! 131: }
! 132:
! 133: static int
! 134: unix_proto_setsockopt(struct socket *sock, int level, int optname,
! 135: char *optval, int optlen)
! 136: {
! 137: return (-EOPNOTSUPP);
! 138: }
! 139:
! 140: static int
! 141: unix_proto_getsockopt(struct socket *sock, int level, int optname,
! 142: char *optval, int *optlen)
! 143: {
! 144: return (-EOPNOTSUPP);
! 145: }
! 146:
! 147: static int
! 148: unix_proto_sendto(struct socket *sock, void *buff, int len, int nonblock,
! 149: unsigned flags, struct sockaddr *addr, int addr_len)
! 150: {
! 151: return (-EOPNOTSUPP);
! 152: }
! 153:
! 154: static int
! 155: unix_proto_recvfrom(struct socket *sock, void *buff, int len, int nonblock,
! 156: unsigned flags, struct sockaddr *addr, int *addr_len)
! 157: {
! 158: return (-EOPNOTSUPP);
! 159: }
! 160:
! 161: static int
! 162: unix_proto_shutdown (struct socket *sock, int how)
! 163: {
! 164: return (-EOPNOTSUPP);
! 165: }
! 166:
! 167: static int
! 168: unix_proto_send(struct socket *sock, void *buff, int len, int nonblock,
! 169: unsigned flags)
! 170: {
! 171: /* this error needs to be checked. */
! 172: if (flags != 0)
! 173: return (-EINVAL);
! 174: return (unix_proto_write (sock, buff, len, nonblock));
! 175: }
! 176:
! 177: static int
! 178: unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
! 179: unsigned flags)
! 180: {
! 181: /* this error needs to be checked. */
! 182: if (flags != 0)
! 183: return (-EINVAL);
! 184: return (unix_proto_read (sock, buff, len, nonblock));
! 185: }
! 186:
1.1 root 187:
188: static struct unix_proto_data *
189: unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
190: {
191: struct unix_proto_data *upd;
192:
193: for (upd = unix_datas; upd <= last_unix_data; ++upd) {
194: if (upd->refcnt && upd->socket &&
195: upd->sockaddr_len == sockaddr_len &&
196: memcmp(&upd->sockaddr_un, sockun, sockaddr_len) == 0)
197: return upd;
198: }
199: return NULL;
200: }
201:
202: static struct unix_proto_data *
203: unix_data_alloc(void)
204: {
205: struct unix_proto_data *upd;
206:
207: cli();
208: for (upd = unix_datas; upd <= last_unix_data; ++upd) {
209: if (!upd->refcnt) {
210: upd->refcnt = 1;
211: sti();
212: upd->socket = NULL;
213: upd->sockaddr_len = 0;
214: upd->buf = NULL;
215: upd->bp_head = upd->bp_tail = 0;
216: upd->inode = NULL;
217: upd->peerupd = NULL;
218: return upd;
219: }
220: }
221: sti();
222: return NULL;
223: }
224:
225: static inline void
226: unix_data_ref(struct unix_proto_data *upd)
227: {
228: ++upd->refcnt;
229: PRINTK("unix_data_ref: refing data 0x%x (%d)\n", upd, upd->refcnt);
230: }
231:
232: static void
233: unix_data_deref(struct unix_proto_data *upd)
234: {
235: if (upd->refcnt == 1) {
236: PRINTK("unix_data_deref: releasing data 0x%x\n", upd);
237: if (upd->buf) {
238: free_page((unsigned long)upd->buf);
239: upd->buf = NULL;
240: upd->bp_head = upd->bp_tail = 0;
241: }
242: }
243: --upd->refcnt;
244: }
245:
246: /*
247: * upon a create, we allocate an empty protocol data, and grab a page to
248: * buffer writes
249: */
250: static int
251: unix_proto_create(struct socket *sock, int protocol)
252: {
253: struct unix_proto_data *upd;
254:
255: PRINTK("unix_proto_create: socket 0x%x, proto %d\n", sock, protocol);
256: if (protocol != 0) {
257: PRINTK("unix_proto_create: protocol != 0\n");
258: return -EINVAL;
259: }
260: if (!(upd = unix_data_alloc())) {
261: printk("unix_proto_create: can't allocate buffer\n");
262: return -ENOMEM;
263: }
1.1.1.4 root 264: if (!(upd->buf = (char *)get_free_page(GFP_USER))) {
1.1 root 265: printk("unix_proto_create: can't get page!\n");
266: unix_data_deref(upd);
267: return -ENOMEM;
268: }
269: upd->protocol = protocol;
270: upd->socket = sock;
271: UN_DATA(sock) = upd;
272: PRINTK("unix_proto_create: allocated data 0x%x\n", upd);
273: return 0;
274: }
275:
276: static int
277: unix_proto_dup(struct socket *newsock, struct socket *oldsock)
278: {
279: struct unix_proto_data *upd = UN_DATA(oldsock);
280:
281: return unix_proto_create(newsock, upd->protocol);
282: }
283:
284: static int
285: unix_proto_release(struct socket *sock, struct socket *peer)
286: {
287: struct unix_proto_data *upd = UN_DATA(sock);
288:
289: PRINTK("unix_proto_release: socket 0x%x, unix_data 0x%x\n",
290: sock, upd);
291: if (!upd)
292: return 0;
293: if (upd->socket != sock) {
294: printk("unix_proto_release: socket link mismatch!\n");
295: return -EINVAL;
296: }
297: if (upd->inode) {
298: PRINTK("unix_proto_release: releasing inode 0x%x\n",
299: upd->inode);
300: iput(upd->inode);
301: upd->inode = NULL;
302: }
303: UN_DATA(sock) = NULL;
304: upd->socket = NULL;
305: if (upd->peerupd)
306: unix_data_deref(upd->peerupd);
307: unix_data_deref(upd);
308: return 0;
309: }
310:
311: /*
312: * bind a name to a socket. this is where much of the work is done. we
313: * allocate a fresh page for the buffer, grab the appropriate inode and
314: * set things up.
315: *
316: * XXX what should we do if an address is already bound? here we return
317: * EINVAL, but it may be necessary to re-bind. i think thats what bsd does
318: * in the case of datagram sockets
319: */
320: static int
321: unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
322: int sockaddr_len)
323: {
324: struct unix_proto_data *upd = UN_DATA(sock);
325: char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
326: int i;
327: unsigned long old_fs;
328:
329: PRINTK("unix_proto_bind: socket 0x%x, len=%d\n", sock,
330: sockaddr_len);
331: if (sockaddr_len <= UN_PATH_OFFSET ||
332: sockaddr_len >= sizeof(struct sockaddr_un)) {
333: PRINTK("unix_proto_bind: bad length %d\n", sockaddr_len);
334: return -EINVAL;
335: }
336: if (upd->sockaddr_len || upd->inode) {
337: printk("unix_proto_bind: already bound!\n");
338: return -EINVAL;
339: }
340: verify_area(umyaddr, sockaddr_len);
341: memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len);
342: if (upd->sockaddr_un.sun_family != AF_UNIX) {
343: PRINTK("unix_proto_bind: family is %d, not AF_UNIX (%d)\n",
344: upd->sockaddr_un.sun_family, AF_UNIX);
345: return -EINVAL;
346: }
347:
348: memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
349: fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
350: old_fs = get_fs();
351: set_fs(get_ds());
1.1.1.2 root 352: i = do_mknod(fname, S_IFSOCK | 0777, 0);
1.1 root 353: if (i == 0)
1.1.1.5 ! root 354: i = open_namei(fname, 0, S_IFSOCK, &upd->inode, NULL);
1.1 root 355: set_fs(old_fs);
356: if (i < 0) {
357: printk("unix_proto_bind: can't open socket %s\n", fname);
358: return i;
359: }
360:
361: upd->sockaddr_len = sockaddr_len; /* now its legal */
362: PRINTK("unix_proto_bind: bound socket address: ");
363: #ifdef SOCK_DEBUG
364: sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
365: #endif
366: return 0;
367: }
368:
369: /*
370: * perform a connection. we can only connect to unix sockets (i can't for
371: * the life of me find an application where that wouldn't be the case!)
372: */
373: static int
374: unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
1.1.1.5 ! root 375: int sockaddr_len, int flags)
1.1 root 376: {
377: int i;
378: struct unix_proto_data *serv_upd;
379: struct sockaddr_un sockun;
380:
381: PRINTK("unix_proto_connect: socket 0x%x, servlen=%d\n", sock,
382: sockaddr_len);
383: if (sockaddr_len <= UN_PATH_OFFSET ||
384: sockaddr_len >= sizeof(struct sockaddr_un)) {
385: PRINTK("unix_proto_connect: bad length %d\n", sockaddr_len);
386: return -EINVAL;
387: }
388: verify_area(uservaddr, sockaddr_len);
389: memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
390: if (sockun.sun_family != AF_UNIX) {
391: PRINTK("unix_proto_connect: family is %d, not AF_UNIX (%d)\n",
392: sockun.sun_family, AF_UNIX);
393: return -EINVAL;
394: }
395: if (!(serv_upd = unix_data_lookup(&sockun, sockaddr_len))) {
396: PRINTK("unix_proto_connect: can't locate peer\n");
397: return -EINVAL;
398: }
399: if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
400: PRINTK("unix_proto_connect: can't await connection\n");
401: return i;
402: }
403: unix_data_ref(UN_DATA(sock->conn));
404: UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
405: return 0;
406: }
407:
408: /*
409: * to do a socketpair, we make just connect the two datas, easy! since we
410: * always wait on the socket inode, they're no contention for a wait area,
411: * and deadlock prevention in the case of a process writing to itself is,
412: * ignored, in true unix fashion!
413: */
414: static int
415: unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
416: {
417: struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
418:
419: unix_data_ref(upd1);
420: unix_data_ref(upd2);
421: upd1->peerupd = upd2;
422: upd2->peerupd = upd1;
423: return 0;
424: }
425:
426: /*
427: * on accept, we ref the peer's data for safe writes
428: */
429: static int
1.1.1.5 ! root 430: unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
1.1 root 431: {
1.1.1.5 ! root 432: struct socket *clientsock;
! 433:
1.1 root 434: PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n",
435: sock, newsock);
1.1.1.5 ! root 436:
! 437: /*
! 438: * if there aren't any sockets awaiting connection, then wait for
! 439: * one, unless nonblocking
! 440: */
! 441: while (!(clientsock = sock->iconn)) {
! 442: if (flags & O_NONBLOCK)
! 443: return -EAGAIN;
! 444: interruptible_sleep_on(sock->wait);
! 445: if (current->signal & ~current->blocked) {
! 446: PRINTK("sys_accept: sleep was interrupted\n");
! 447: return -ERESTARTSYS;
! 448: }
! 449: }
! 450:
! 451: /*
! 452: * great. finish the connection relative to server and client,
! 453: * wake up the client and return the new fd to the server
! 454: */
! 455: sock->iconn = clientsock->next;
! 456: clientsock->next = NULL;
! 457: newsock->conn = clientsock;
! 458: clientsock->conn = newsock;
! 459: clientsock->state = SS_CONNECTED;
! 460: newsock->state = SS_CONNECTED;
! 461: wake_up(clientsock->wait);
! 462: unix_data_ref (UN_DATA(newsock->conn));
1.1 root 463: UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn);
464: return 0;
465: }
466:
467: /*
468: * gets the current name or the name of the connected socket.
469: */
470: static int
471: unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
472: int *usockaddr_len, int peer)
473: {
474: struct unix_proto_data *upd;
475: int len;
476:
477: PRINTK("unix_proto_getname: socket 0x%x for %s\n", sock,
478: peer ? "peer" : "self");
479: if (peer) {
480: if (sock->state != SS_CONNECTED) {
481: PRINTK("unix_proto_getname: socket not connected\n");
482: return -EINVAL;
483: }
484: upd = UN_DATA(sock->conn);
485: }
486: else
487: upd = UN_DATA(sock);
488: verify_area(usockaddr_len, sizeof(*usockaddr_len));
489: if ((len = get_fs_long(usockaddr_len)) <= 0)
490: return -EINVAL;
491: if (len > upd->sockaddr_len)
492: len = upd->sockaddr_len;
493: if (len) {
494: verify_area(usockaddr, len);
495: memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
496: }
497: put_fs_long(len, usockaddr_len);
498: return 0;
499: }
500:
501: /*
502: * we read from our own buf.
503: */
504: static int
505: unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
506: {
507: struct unix_proto_data *upd;
508: int todo, avail;
509:
510: if ((todo = size) <= 0)
511: return 0;
512: upd = UN_DATA(sock);
513: while (!(avail = UN_BUF_AVAIL(upd))) {
514: if (sock->state != SS_CONNECTED) {
515: PRINTK("unix_proto_read: socket not connected\n");
516: return (sock->state == SS_DISCONNECTING) ? 0 : -EINVAL;
517: }
518: PRINTK("unix_proto_read: no data available...\n");
519: if (nonblock)
520: return -EAGAIN;
521: interruptible_sleep_on(sock->wait);
522: if (current->signal & ~current->blocked) {
523: PRINTK("unix_proto_read: interrupted\n");
524: return -ERESTARTSYS;
525: }
526: if (sock->state == SS_DISCONNECTING) {
527: PRINTK("unix_proto_read: disconnected\n");
528: return 0;
529: }
530: }
531:
532: /*
533: * copy from the read buffer into the user's buffer, watching for
534: * wraparound. then we wake up the writer
535: */
536: do {
537: int part, cando;
538:
539: if (avail <= 0) {
540: PRINTK("unix_proto_read: AVAIL IS NEGATIVE!!!\n");
1.1.1.3 root 541: send_sig(SIGKILL,current,1);
1.1 root 542: return -EINTR;
543: }
544:
545: if ((cando = todo) > avail)
546: cando = avail;
547: if (cando > (part = BUF_SIZE - upd->bp_tail))
548: cando = part;
549: PRINTK("unix_proto_read: avail=%d, todo=%d, cando=%d\n",
550: avail, todo, cando);
551: verify_area(ubuf, cando);
552: memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
553: upd->bp_tail = (upd->bp_tail + cando) & (BUF_SIZE-1);
554: ubuf += cando;
555: todo -= cando;
556: if (sock->state == SS_CONNECTED)
557: wake_up(sock->conn->wait);
558: avail = UN_BUF_AVAIL(upd);
559: } while (todo && avail);
560: return size - todo;
561: }
562:
563: /*
564: * we write to our peer's buf. when we connected we ref'd this peer so we
565: * are safe that the buffer remains, even after the peer has disconnected,
566: * which we check other ways.
567: */
568: static int
569: unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
570: {
571: struct unix_proto_data *pupd;
572: int todo, space;
573:
574: if ((todo = size) <= 0)
575: return 0;
576: if (sock->state != SS_CONNECTED) {
577: PRINTK("unix_proto_write: socket not connected\n");
578: if (sock->state == SS_DISCONNECTING) {
1.1.1.3 root 579: send_sig(SIGPIPE,current,1);
1.1 root 580: return -EINTR;
581: }
582: return -EINVAL;
583: }
584: pupd = UN_DATA(sock)->peerupd; /* safer than sock->conn */
585:
586: while (!(space = UN_BUF_SPACE(pupd))) {
587: PRINTK("unix_proto_write: no space left...\n");
588: if (nonblock)
1.1.1.3 root 589: return -EAGAIN;
1.1 root 590: interruptible_sleep_on(sock->wait);
591: if (current->signal & ~current->blocked) {
592: PRINTK("unix_proto_write: interrupted\n");
1.1.1.3 root 593: return -ERESTARTSYS;
1.1 root 594: }
595: if (sock->state == SS_DISCONNECTING) {
596: PRINTK("unix_proto_write: disconnected (SIGPIPE)\n");
1.1.1.3 root 597: send_sig(SIGPIPE,current,1);
1.1 root 598: return -EINTR;
599: }
600: }
601:
602: /*
603: * copy from the user's buffer to the write buffer, watching for
604: * wraparound. then we wake up the reader
605: */
606: do {
607: int part, cando;
608:
609: if (space <= 0) {
610: PRINTK("unix_proto_write: SPACE IS NEGATIVE!!!\n");
1.1.1.3 root 611: send_sig(SIGKILL,current,1);
1.1 root 612: return -EINTR;
613: }
614:
615: /*
616: * we may become disconnected inside this loop, so watch
617: * for it (peerupd is safe until we close)
618: */
619: if (sock->state == SS_DISCONNECTING) {
1.1.1.3 root 620: send_sig(SIGPIPE,current,1);
1.1 root 621: return -EINTR;
622: }
623: if ((cando = todo) > space)
624: cando = space;
625: if (cando > (part = BUF_SIZE - pupd->bp_head))
626: cando = part;
627: PRINTK("unix_proto_write: space=%d, todo=%d, cando=%d\n",
628: space, todo, cando);
629: verify_area(ubuf, cando);
630: memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
631: pupd->bp_head = (pupd->bp_head + cando) & (BUF_SIZE-1);
632: ubuf += cando;
633: todo -= cando;
634: if (sock->state == SS_CONNECTED)
635: wake_up(sock->conn->wait);
636: space = UN_BUF_SPACE(pupd);
637: } while (todo && space);
638: return size - todo;
639: }
640:
641: static int
1.1.1.4 root 642: unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
1.1 root 643: {
644: struct unix_proto_data *upd, *peerupd;
645:
1.1.1.5 ! root 646: /*
! 647: * handle server sockets specially
! 648: */
! 649: if (sock->flags & SO_ACCEPTCON) {
! 650: if (sel_type == SEL_IN) {
! 651: PRINTK("sock_select: %sconnections pending\n",
! 652: sock->iconn ? "" : "no ");
! 653: if (sock->iconn)
! 654: return 1;
! 655: select_wait(sock->wait, wait);
! 656: return sock->iconn ? 1 : 0;
! 657: }
! 658: PRINTK("sock_select: nothing else for server socket\n");
! 659: select_wait(sock->wait, wait);
! 660: return 0;
! 661: }
! 662:
1.1.1.4 root 663: if (sel_type == SEL_IN) {
1.1 root 664: upd = UN_DATA(sock);
665: PRINTK("unix_proto_select: there is%s data available\n",
666: UN_BUF_AVAIL(upd) ? "" : " no");
667: if (UN_BUF_AVAIL(upd)) /* even if disconnected */
668: return 1;
669: else if (sock->state != SS_CONNECTED) {
670: PRINTK("unix_proto_select: socket not connected (read EOF)\n");
671: return 1;
672: }
1.1.1.4 root 673: select_wait(sock->wait,wait);
674: return 0;
1.1 root 675: }
1.1.1.4 root 676: if (sel_type == SEL_OUT) {
1.1 root 677: if (sock->state != SS_CONNECTED) {
678: PRINTK("unix_proto_select: socket not connected (write EOF)\n");
679: return 1;
680: }
681: peerupd = UN_DATA(sock->conn);
682: PRINTK("unix_proto_select: there is%s space available\n",
683: UN_BUF_SPACE(peerupd) ? "" : " no");
1.1.1.4 root 684: if (UN_BUF_SPACE(peerupd) > 0)
685: return 1;
686: select_wait(sock->wait,wait);
687: return 0;
1.1 root 688: }
689: /* SEL_EX */
690: PRINTK("unix_proto_select: there are no exceptions here?!\n");
691: return 0;
692: }
693:
694: static int
695: unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
696: {
697: struct unix_proto_data *upd, *peerupd;
698:
699: upd = UN_DATA(sock);
700: peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
701:
702: switch (cmd) {
1.1.1.5 ! root 703:
1.1 root 704: case TIOCINQ:
1.1.1.5 ! root 705: if (sock->flags & SO_ACCEPTCON)
! 706: return -EINVAL;
1.1 root 707: verify_area((void *)arg, sizeof(unsigned long));
708: if (UN_BUF_AVAIL(upd) || peerupd)
709: put_fs_long(UN_BUF_AVAIL(upd), (unsigned long *)arg);
710: else
711: put_fs_long(1, (unsigned long *)arg); /* read EOF */
712: break;
713:
714: case TIOCOUTQ:
1.1.1.5 ! root 715: if (sock->flags & SO_ACCEPTCON)
! 716: return -EINVAL;
1.1 root 717: verify_area((void *)arg, sizeof(unsigned long));
718: if (peerupd)
719: put_fs_long(UN_BUF_SPACE(peerupd),
720: (unsigned long *)arg);
721: else
722: put_fs_long(0, (unsigned long *)arg);
723: break;
724:
725: default:
726: return -EINVAL;
727: }
728: return 0;
729: }
730:
731: static int
732: unix_proto_init(void)
733: {
734: struct unix_proto_data *upd;
735:
736: PRINTK("unix_proto_init: initializing...\n");
737: for (upd = unix_datas; upd <= last_unix_data; ++upd)
738: upd->refcnt = 0;
739: return 0;
740: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.