This source file includes following definitions.
- sockaddr_un_printk
- 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_proto_init
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;
17 struct socket *socket;
18 int protocol;
19 struct sockaddr_un sockaddr_un;
20 short sockaddr_len;
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
33
34
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
156
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
221
222
223
224
225
226
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
259
260
261
262
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;
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
290
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);
324 return 0;
325 }
326
327
328
329
330
331
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
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
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
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
425
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
456
457
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;
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
495
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
508
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))
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
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);
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 }