|
|
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>
6: #include <asm/system.h>
7: #include <asm/segment.h>
8: #include <sys/socket.h>
9: #include <sys/un.h>
10: #include <sys/stat.h>
11: #include <fcntl.h>
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: unsigned short old_euid;
237:
238: PRINTK("unix_proto_bind: socket 0x%x, len=%d\n", sock,
239: sockaddr_len);
240: if (sockaddr_len <= UN_PATH_OFFSET ||
241: sockaddr_len >= sizeof(struct sockaddr_un)) {
242: PRINTK("unix_proto_bind: bad length %d\n", sockaddr_len);
243: return -EINVAL;
244: }
245: if (upd->sockaddr_len || upd->inode) {
246: printk("unix_proto_bind: already bound!\n");
247: return -EINVAL;
248: }
249: verify_area(umyaddr, sockaddr_len);
250: memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len);
251: if (upd->sockaddr_un.sun_family != AF_UNIX) {
252: PRINTK("unix_proto_bind: family is %d, not AF_UNIX (%d)\n",
253: upd->sockaddr_un.sun_family, AF_UNIX);
254: return -EINVAL;
255: }
256:
257: /*
258: * W A R N I N G
259: * this is a terrible hack. i want to create a socket in the
260: * filesystem and get its inode. sys_mknod() can create one for
261: * me, but it needs superuser privs and doesn't give me the inode.
262: * we fake suser here and get the file created... ugh.
263: */
264: memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
265: fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
266: old_fs = get_fs();
267: set_fs(get_ds());
268: old_euid = current->euid;
269: current->euid = 0;
270: i = sys_mknod(fname, S_IFSOCK, 0);
271: current->euid = old_euid;
272: if (i == 0)
273: i = open_namei(fname, 0, S_IFSOCK, &upd->inode);
274: set_fs(old_fs);
275: if (i < 0) {
276: printk("unix_proto_bind: can't open socket %s\n", fname);
277: return i;
278: }
279:
280: upd->sockaddr_len = sockaddr_len; /* now its legal */
281: PRINTK("unix_proto_bind: bound socket address: ");
282: #ifdef SOCK_DEBUG
283: sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
284: #endif
285: return 0;
286: }
287:
288: /*
289: * perform a connection. we can only connect to unix sockets (i can't for
290: * the life of me find an application where that wouldn't be the case!)
291: */
292: static int
293: unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
294: int sockaddr_len)
295: {
296: int i;
297: struct unix_proto_data *serv_upd;
298: struct sockaddr_un sockun;
299:
300: PRINTK("unix_proto_connect: socket 0x%x, servlen=%d\n", sock,
301: sockaddr_len);
302: if (sockaddr_len <= UN_PATH_OFFSET ||
303: sockaddr_len >= sizeof(struct sockaddr_un)) {
304: PRINTK("unix_proto_connect: bad length %d\n", sockaddr_len);
305: return -EINVAL;
306: }
307: verify_area(uservaddr, sockaddr_len);
308: memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
309: if (sockun.sun_family != AF_UNIX) {
310: PRINTK("unix_proto_connect: family is %d, not AF_UNIX (%d)\n",
311: sockun.sun_family, AF_UNIX);
312: return -EINVAL;
313: }
314: if (!(serv_upd = unix_data_lookup(&sockun, sockaddr_len))) {
315: PRINTK("unix_proto_connect: can't locate peer\n");
316: return -EINVAL;
317: }
318: if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
319: PRINTK("unix_proto_connect: can't await connection\n");
320: return i;
321: }
322: unix_data_ref(UN_DATA(sock->conn));
323: UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
324: return 0;
325: }
326:
327: /*
328: * to do a socketpair, we make just connect the two datas, easy! since we
329: * always wait on the socket inode, they're no contention for a wait area,
330: * and deadlock prevention in the case of a process writing to itself is,
331: * ignored, in true unix fashion!
332: */
333: static int
334: unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
335: {
336: struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
337:
338: unix_data_ref(upd1);
339: unix_data_ref(upd2);
340: upd1->peerupd = upd2;
341: upd2->peerupd = upd1;
342: return 0;
343: }
344:
345: /*
346: * on accept, we ref the peer's data for safe writes
347: */
348: static int
349: unix_proto_accept(struct socket *sock, struct socket *newsock)
350: {
351: PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n",
352: sock, newsock);
353: unix_data_ref(UN_DATA(newsock->conn));
354: UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn);
355: return 0;
356: }
357:
358: /*
359: * gets the current name or the name of the connected socket.
360: */
361: static int
362: unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
363: int *usockaddr_len, int peer)
364: {
365: struct unix_proto_data *upd;
366: int len;
367:
368: PRINTK("unix_proto_getname: socket 0x%x for %s\n", sock,
369: peer ? "peer" : "self");
370: if (peer) {
371: if (sock->state != SS_CONNECTED) {
372: PRINTK("unix_proto_getname: socket not connected\n");
373: return -EINVAL;
374: }
375: upd = UN_DATA(sock->conn);
376: }
377: else
378: upd = UN_DATA(sock);
379: verify_area(usockaddr_len, sizeof(*usockaddr_len));
380: if ((len = get_fs_long(usockaddr_len)) <= 0)
381: return -EINVAL;
382: if (len > upd->sockaddr_len)
383: len = upd->sockaddr_len;
384: if (len) {
385: verify_area(usockaddr, len);
386: memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
387: }
388: put_fs_long(len, usockaddr_len);
389: return 0;
390: }
391:
392: /*
393: * we read from our own buf.
394: */
395: static int
396: unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
397: {
398: struct unix_proto_data *upd;
399: int todo, avail;
400:
401: if ((todo = size) <= 0)
402: return 0;
403: upd = UN_DATA(sock);
404: while (!(avail = UN_BUF_AVAIL(upd))) {
405: if (sock->state != SS_CONNECTED) {
406: PRINTK("unix_proto_read: socket not connected\n");
407: return (sock->state == SS_DISCONNECTING) ? 0 : -EINVAL;
408: }
409: PRINTK("unix_proto_read: no data available...\n");
410: if (nonblock)
411: return -EAGAIN;
412: interruptible_sleep_on(sock->wait);
413: if (current->signal & ~current->blocked) {
414: PRINTK("unix_proto_read: interrupted\n");
415: return -ERESTARTSYS;
416: }
417: if (sock->state == SS_DISCONNECTING) {
418: PRINTK("unix_proto_read: disconnected\n");
419: return 0;
420: }
421: }
422:
423: /*
424: * copy from the read buffer into the user's buffer, watching for
425: * wraparound. then we wake up the writer
426: */
427: do {
428: int part, cando;
429:
430: if (avail <= 0) {
431: PRINTK("unix_proto_read: AVAIL IS NEGATIVE!!!\n");
432: current->signal |= (1 << (SIGKILL-1));
433: return -EINTR;
434: }
435:
436: if ((cando = todo) > avail)
437: cando = avail;
438: if (cando > (part = BUF_SIZE - upd->bp_tail))
439: cando = part;
440: PRINTK("unix_proto_read: avail=%d, todo=%d, cando=%d\n",
441: avail, todo, cando);
442: verify_area(ubuf, cando);
443: memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
444: upd->bp_tail = (upd->bp_tail + cando) & (BUF_SIZE-1);
445: ubuf += cando;
446: todo -= cando;
447: if (sock->state == SS_CONNECTED)
448: wake_up(sock->conn->wait);
449: avail = UN_BUF_AVAIL(upd);
450: } while (todo && avail);
451: return size - todo;
452: }
453:
454: /*
455: * we write to our peer's buf. when we connected we ref'd this peer so we
456: * are safe that the buffer remains, even after the peer has disconnected,
457: * which we check other ways.
458: */
459: static int
460: unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
461: {
462: struct unix_proto_data *pupd;
463: int todo, space;
464:
465: if ((todo = size) <= 0)
466: return 0;
467: if (sock->state != SS_CONNECTED) {
468: PRINTK("unix_proto_write: socket not connected\n");
469: if (sock->state == SS_DISCONNECTING) {
470: current->signal |= (1 << (SIGPIPE-1));
471: return -EINTR;
472: }
473: return -EINVAL;
474: }
475: pupd = UN_DATA(sock)->peerupd; /* safer than sock->conn */
476:
477: while (!(space = UN_BUF_SPACE(pupd))) {
478: PRINTK("unix_proto_write: no space left...\n");
479: if (nonblock)
480: return 0;
481: interruptible_sleep_on(sock->wait);
482: if (current->signal & ~current->blocked) {
483: PRINTK("unix_proto_write: interrupted\n");
484: return -EINTR;
485: }
486: if (sock->state == SS_DISCONNECTING) {
487: PRINTK("unix_proto_write: disconnected (SIGPIPE)\n");
488: current->signal |= (1 << (SIGPIPE-1));
489: return -EINTR;
490: }
491: }
492:
493: /*
494: * copy from the user's buffer to the write buffer, watching for
495: * wraparound. then we wake up the reader
496: */
497: do {
498: int part, cando;
499:
500: if (space <= 0) {
501: PRINTK("unix_proto_write: SPACE IS NEGATIVE!!!\n");
502: current->signal |= (1 << (SIGKILL-1));
503: return -EINTR;
504: }
505:
506: /*
507: * we may become disconnected inside this loop, so watch
508: * for it (peerupd is safe until we close)
509: */
510: if (sock->state == SS_DISCONNECTING) {
511: current->signal |= (1 << (SIGPIPE-1));
512: return -EINTR;
513: }
514: if ((cando = todo) > space)
515: cando = space;
516: if (cando > (part = BUF_SIZE - pupd->bp_head))
517: cando = part;
518: PRINTK("unix_proto_write: space=%d, todo=%d, cando=%d\n",
519: space, todo, cando);
520: verify_area(ubuf, cando);
521: memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
522: pupd->bp_head = (pupd->bp_head + cando) & (BUF_SIZE-1);
523: ubuf += cando;
524: todo -= cando;
525: if (sock->state == SS_CONNECTED)
526: wake_up(sock->conn->wait);
527: space = UN_BUF_SPACE(pupd);
528: } while (todo && space);
529: return size - todo;
530: }
531:
532: static int
533: unix_proto_select(struct socket *sock, int which)
534: {
535: struct unix_proto_data *upd, *peerupd;
536:
537: if (which == SEL_IN) {
538: upd = UN_DATA(sock);
539: PRINTK("unix_proto_select: there is%s data available\n",
540: UN_BUF_AVAIL(upd) ? "" : " no");
541: if (UN_BUF_AVAIL(upd)) /* even if disconnected */
542: return 1;
543: else if (sock->state != SS_CONNECTED) {
544: PRINTK("unix_proto_select: socket not connected (read EOF)\n");
545: return 1;
546: }
547: else
548: return 0;
549: }
550: if (which == SEL_OUT) {
551: if (sock->state != SS_CONNECTED) {
552: PRINTK("unix_proto_select: socket not connected (write EOF)\n");
553: return 1;
554: }
555: peerupd = UN_DATA(sock->conn);
556: PRINTK("unix_proto_select: there is%s space available\n",
557: UN_BUF_SPACE(peerupd) ? "" : " no");
558: return (UN_BUF_SPACE(peerupd) > 0);
559: }
560: /* SEL_EX */
561: PRINTK("unix_proto_select: there are no exceptions here?!\n");
562: return 0;
563: }
564:
565: static int
566: unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
567: {
568: struct unix_proto_data *upd, *peerupd;
569:
570: upd = UN_DATA(sock);
571: peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
572:
573: switch (cmd) {
574: case TIOCINQ:
575: verify_area((void *)arg, sizeof(unsigned long));
576: if (UN_BUF_AVAIL(upd) || peerupd)
577: put_fs_long(UN_BUF_AVAIL(upd), (unsigned long *)arg);
578: else
579: put_fs_long(1, (unsigned long *)arg); /* read EOF */
580: break;
581:
582: case TIOCOUTQ:
583: verify_area((void *)arg, sizeof(unsigned long));
584: if (peerupd)
585: put_fs_long(UN_BUF_SPACE(peerupd),
586: (unsigned long *)arg);
587: else
588: put_fs_long(0, (unsigned long *)arg);
589: break;
590:
591: default:
592: return -EINVAL;
593: }
594: return 0;
595: }
596:
597: static int
598: unix_proto_init(void)
599: {
600: struct unix_proto_data *upd;
601:
602: PRINTK("unix_proto_init: initializing...\n");
603: for (upd = unix_datas; upd <= last_unix_data; ++upd)
604: upd->refcnt = 0;
605: return 0;
606: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.