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