aboutsummaryrefslogtreecommitdiffstats
path: root/net/compat.c
diff options
context:
space:
mode:
authorDmitry Mishin <dim@openvz.org>2006-03-21 01:45:21 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-21 01:45:21 -0500
commit3fdadf7d27e3fbcf72930941884387d1f4936f04 (patch)
tree167072cf1e60b6b307610563614b435ff0caa52d /net/compat.c
parentc750360938b403e6cc193d293cfbcb099dd6c60e (diff)
[NET]: {get|set}sockopt compatibility layer
This patch extends {get|set}sockopt compatibility layer in order to move protocol specific parts to their place and avoid huge universal net/compat.c file in the future. Signed-off-by: Dmitry Mishin <dim@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/compat.c')
-rw-r--r--net/compat.c95
1 files changed, 77 insertions, 18 deletions
diff --git a/net/compat.c b/net/compat.c
index e593dace2fdb..13177a1a4b39 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -416,7 +416,7 @@ struct compat_sock_fprog {
416 compat_uptr_t filter; /* struct sock_filter * */ 416 compat_uptr_t filter; /* struct sock_filter * */
417}; 417};
418 418
419static int do_set_attach_filter(int fd, int level, int optname, 419static int do_set_attach_filter(struct socket *sock, int level, int optname,
420 char __user *optval, int optlen) 420 char __user *optval, int optlen)
421{ 421{
422 struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval; 422 struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval;
@@ -432,11 +432,12 @@ static int do_set_attach_filter(int fd, int level, int optname,
432 __put_user(compat_ptr(ptr), &kfprog->filter)) 432 __put_user(compat_ptr(ptr), &kfprog->filter))
433 return -EFAULT; 433 return -EFAULT;
434 434
435 return sys_setsockopt(fd, level, optname, (char __user *)kfprog, 435 return sock_setsockopt(sock, level, optname, (char __user *)kfprog,
436 sizeof(struct sock_fprog)); 436 sizeof(struct sock_fprog));
437} 437}
438 438
439static int do_set_sock_timeout(int fd, int level, int optname, char __user *optval, int optlen) 439static int do_set_sock_timeout(struct socket *sock, int level,
440 int optname, char __user *optval, int optlen)
440{ 441{
441 struct compat_timeval __user *up = (struct compat_timeval __user *) optval; 442 struct compat_timeval __user *up = (struct compat_timeval __user *) optval;
442 struct timeval ktime; 443 struct timeval ktime;
@@ -451,30 +452,61 @@ static int do_set_sock_timeout(int fd, int level, int optname, char __user *optv
451 return -EFAULT; 452 return -EFAULT;
452 old_fs = get_fs(); 453 old_fs = get_fs();
453 set_fs(KERNEL_DS); 454 set_fs(KERNEL_DS);
454 err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); 455 err = sock_setsockopt(sock, level, optname, (char *) &ktime, sizeof(ktime));
455 set_fs(old_fs); 456 set_fs(old_fs);
456 457
457 return err; 458 return err;
458} 459}
459 460
461static int compat_sock_setsockopt(struct socket *sock, int level, int optname,
462 char __user *optval, int optlen)
463{
464 if (optname == SO_ATTACH_FILTER)
465 return do_set_attach_filter(sock, level, optname,
466 optval, optlen);
467 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
468 return do_set_sock_timeout(sock, level, optname, optval, optlen);
469
470 return sock_setsockopt(sock, level, optname, optval, optlen);
471}
472
460asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, 473asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
461 char __user *optval, int optlen) 474 char __user *optval, int optlen)
462{ 475{
476 int err;
477 struct socket *sock;
478
463 /* SO_SET_REPLACE seems to be the same in all levels */ 479 /* SO_SET_REPLACE seems to be the same in all levels */
464 if (optname == IPT_SO_SET_REPLACE) 480 if (optname == IPT_SO_SET_REPLACE)
465 return do_netfilter_replace(fd, level, optname, 481 return do_netfilter_replace(fd, level, optname,
466 optval, optlen); 482 optval, optlen);
467 if (level == SOL_SOCKET && optname == SO_ATTACH_FILTER)
468 return do_set_attach_filter(fd, level, optname,
469 optval, optlen);
470 if (level == SOL_SOCKET &&
471 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
472 return do_set_sock_timeout(fd, level, optname, optval, optlen);
473 483
474 return sys_setsockopt(fd, level, optname, optval, optlen); 484 if (optlen < 0)
485 return -EINVAL;
486
487 if ((sock = sockfd_lookup(fd, &err))!=NULL)
488 {
489 err = security_socket_setsockopt(sock,level,optname);
490 if (err) {
491 sockfd_put(sock);
492 return err;
493 }
494
495 if (level == SOL_SOCKET)
496 err = compat_sock_setsockopt(sock, level,
497 optname, optval, optlen);
498 else if (sock->ops->compat_setsockopt)
499 err = sock->ops->compat_setsockopt(sock, level,
500 optname, optval, optlen);
501 else
502 err = sock->ops->setsockopt(sock, level,
503 optname, optval, optlen);
504 sockfd_put(sock);
505 }
506 return err;
475} 507}
476 508
477static int do_get_sock_timeout(int fd, int level, int optname, 509static int do_get_sock_timeout(struct socket *sock, int level, int optname,
478 char __user *optval, int __user *optlen) 510 char __user *optval, int __user *optlen)
479{ 511{
480 struct compat_timeval __user *up; 512 struct compat_timeval __user *up;
@@ -490,7 +522,7 @@ static int do_get_sock_timeout(int fd, int level, int optname,
490 len = sizeof(ktime); 522 len = sizeof(ktime);
491 old_fs = get_fs(); 523 old_fs = get_fs();
492 set_fs(KERNEL_DS); 524 set_fs(KERNEL_DS);
493 err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); 525 err = sock_getsockopt(sock, level, optname, (char *) &ktime, &len);
494 set_fs(old_fs); 526 set_fs(old_fs);
495 527
496 if (!err) { 528 if (!err) {
@@ -503,15 +535,42 @@ static int do_get_sock_timeout(int fd, int level, int optname,
503 return err; 535 return err;
504} 536}
505 537
506asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, 538static int compat_sock_getsockopt(struct socket *sock, int level, int optname,
507 char __user *optval, int __user *optlen) 539 char __user *optval, int __user *optlen)
508{ 540{
509 if (level == SOL_SOCKET && 541 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
510 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) 542 return do_get_sock_timeout(sock, level, optname, optval, optlen);
511 return do_get_sock_timeout(fd, level, optname, optval, optlen); 543 return sock_getsockopt(sock, level, optname, optval, optlen);
512 return sys_getsockopt(fd, level, optname, optval, optlen);
513} 544}
514 545
546asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
547 char __user *optval, int __user *optlen)
548{
549 int err;
550 struct socket *sock;
551
552 if ((sock = sockfd_lookup(fd, &err))!=NULL)
553 {
554 err = security_socket_getsockopt(sock, level,
555 optname);
556 if (err) {
557 sockfd_put(sock);
558 return err;
559 }
560
561 if (level == SOL_SOCKET)
562 err = compat_sock_getsockopt(sock, level,
563 optname, optval, optlen);
564 else if (sock->ops->compat_getsockopt)
565 err = sock->ops->compat_getsockopt(sock, level,
566 optname, optval, optlen);
567 else
568 err = sock->ops->getsockopt(sock, level,
569 optname, optval, optlen);
570 sockfd_put(sock);
571 }
572 return err;
573}
515/* Argument list sizes for compat_sys_socketcall */ 574/* Argument list sizes for compat_sys_socketcall */
516#define AL(x) ((x) * sizeof(u32)) 575#define AL(x) ((x) * sizeof(u32))
517static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), 576static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),