diff options
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r-- | net/x25/af_x25.c | 115 |
1 files changed, 93 insertions, 22 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 7fa9c7ad3d3b..e3219e4cd044 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -415,6 +415,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, | |||
415 | struct sock *sk = sock->sk; | 415 | struct sock *sk = sock->sk; |
416 | int rc = -ENOPROTOOPT; | 416 | int rc = -ENOPROTOOPT; |
417 | 417 | ||
418 | lock_kernel(); | ||
418 | if (level != SOL_X25 || optname != X25_QBITINCL) | 419 | if (level != SOL_X25 || optname != X25_QBITINCL) |
419 | goto out; | 420 | goto out; |
420 | 421 | ||
@@ -429,6 +430,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, | |||
429 | x25_sk(sk)->qbitincl = !!opt; | 430 | x25_sk(sk)->qbitincl = !!opt; |
430 | rc = 0; | 431 | rc = 0; |
431 | out: | 432 | out: |
433 | unlock_kernel(); | ||
432 | return rc; | 434 | return rc; |
433 | } | 435 | } |
434 | 436 | ||
@@ -438,6 +440,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, | |||
438 | struct sock *sk = sock->sk; | 440 | struct sock *sk = sock->sk; |
439 | int val, len, rc = -ENOPROTOOPT; | 441 | int val, len, rc = -ENOPROTOOPT; |
440 | 442 | ||
443 | lock_kernel(); | ||
441 | if (level != SOL_X25 || optname != X25_QBITINCL) | 444 | if (level != SOL_X25 || optname != X25_QBITINCL) |
442 | goto out; | 445 | goto out; |
443 | 446 | ||
@@ -458,6 +461,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, | |||
458 | val = x25_sk(sk)->qbitincl; | 461 | val = x25_sk(sk)->qbitincl; |
459 | rc = copy_to_user(optval, &val, len) ? -EFAULT : 0; | 462 | rc = copy_to_user(optval, &val, len) ? -EFAULT : 0; |
460 | out: | 463 | out: |
464 | unlock_kernel(); | ||
461 | return rc; | 465 | return rc; |
462 | } | 466 | } |
463 | 467 | ||
@@ -466,12 +470,14 @@ static int x25_listen(struct socket *sock, int backlog) | |||
466 | struct sock *sk = sock->sk; | 470 | struct sock *sk = sock->sk; |
467 | int rc = -EOPNOTSUPP; | 471 | int rc = -EOPNOTSUPP; |
468 | 472 | ||
473 | lock_kernel(); | ||
469 | if (sk->sk_state != TCP_LISTEN) { | 474 | if (sk->sk_state != TCP_LISTEN) { |
470 | memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN); | 475 | memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN); |
471 | sk->sk_max_ack_backlog = backlog; | 476 | sk->sk_max_ack_backlog = backlog; |
472 | sk->sk_state = TCP_LISTEN; | 477 | sk->sk_state = TCP_LISTEN; |
473 | rc = 0; | 478 | rc = 0; |
474 | } | 479 | } |
480 | unlock_kernel(); | ||
475 | 481 | ||
476 | return rc; | 482 | return rc; |
477 | } | 483 | } |
@@ -501,13 +507,14 @@ out: | |||
501 | return sk; | 507 | return sk; |
502 | } | 508 | } |
503 | 509 | ||
504 | static int x25_create(struct net *net, struct socket *sock, int protocol) | 510 | static int x25_create(struct net *net, struct socket *sock, int protocol, |
511 | int kern) | ||
505 | { | 512 | { |
506 | struct sock *sk; | 513 | struct sock *sk; |
507 | struct x25_sock *x25; | 514 | struct x25_sock *x25; |
508 | int rc = -ESOCKTNOSUPPORT; | 515 | int rc = -ESOCKTNOSUPPORT; |
509 | 516 | ||
510 | if (net != &init_net) | 517 | if (!net_eq(net, &init_net)) |
511 | return -EAFNOSUPPORT; | 518 | return -EAFNOSUPPORT; |
512 | 519 | ||
513 | if (sock->type != SOCK_SEQPACKET || protocol) | 520 | if (sock->type != SOCK_SEQPACKET || protocol) |
@@ -597,6 +604,7 @@ static int x25_release(struct socket *sock) | |||
597 | struct sock *sk = sock->sk; | 604 | struct sock *sk = sock->sk; |
598 | struct x25_sock *x25; | 605 | struct x25_sock *x25; |
599 | 606 | ||
607 | lock_kernel(); | ||
600 | if (!sk) | 608 | if (!sk) |
601 | goto out; | 609 | goto out; |
602 | 610 | ||
@@ -627,6 +635,7 @@ static int x25_release(struct socket *sock) | |||
627 | 635 | ||
628 | sock_orphan(sk); | 636 | sock_orphan(sk); |
629 | out: | 637 | out: |
638 | unlock_kernel(); | ||
630 | return 0; | 639 | return 0; |
631 | } | 640 | } |
632 | 641 | ||
@@ -634,18 +643,23 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
634 | { | 643 | { |
635 | struct sock *sk = sock->sk; | 644 | struct sock *sk = sock->sk; |
636 | struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; | 645 | struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; |
646 | int rc = 0; | ||
637 | 647 | ||
648 | lock_kernel(); | ||
638 | if (!sock_flag(sk, SOCK_ZAPPED) || | 649 | if (!sock_flag(sk, SOCK_ZAPPED) || |
639 | addr_len != sizeof(struct sockaddr_x25) || | 650 | addr_len != sizeof(struct sockaddr_x25) || |
640 | addr->sx25_family != AF_X25) | 651 | addr->sx25_family != AF_X25) { |
641 | return -EINVAL; | 652 | rc = -EINVAL; |
653 | goto out; | ||
654 | } | ||
642 | 655 | ||
643 | x25_sk(sk)->source_addr = addr->sx25_addr; | 656 | x25_sk(sk)->source_addr = addr->sx25_addr; |
644 | x25_insert_socket(sk); | 657 | x25_insert_socket(sk); |
645 | sock_reset_flag(sk, SOCK_ZAPPED); | 658 | sock_reset_flag(sk, SOCK_ZAPPED); |
646 | SOCK_DEBUG(sk, "x25_bind: socket is bound\n"); | 659 | SOCK_DEBUG(sk, "x25_bind: socket is bound\n"); |
647 | 660 | out: | |
648 | return 0; | 661 | unlock_kernel(); |
662 | return rc; | ||
649 | } | 663 | } |
650 | 664 | ||
651 | static int x25_wait_for_connection_establishment(struct sock *sk) | 665 | static int x25_wait_for_connection_establishment(struct sock *sk) |
@@ -686,6 +700,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, | |||
686 | struct x25_route *rt; | 700 | struct x25_route *rt; |
687 | int rc = 0; | 701 | int rc = 0; |
688 | 702 | ||
703 | lock_kernel(); | ||
689 | lock_sock(sk); | 704 | lock_sock(sk); |
690 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { | 705 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { |
691 | sock->state = SS_CONNECTED; | 706 | sock->state = SS_CONNECTED; |
@@ -763,6 +778,7 @@ out_put_route: | |||
763 | x25_route_put(rt); | 778 | x25_route_put(rt); |
764 | out: | 779 | out: |
765 | release_sock(sk); | 780 | release_sock(sk); |
781 | unlock_kernel(); | ||
766 | return rc; | 782 | return rc; |
767 | } | 783 | } |
768 | 784 | ||
@@ -802,6 +818,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
802 | struct sk_buff *skb; | 818 | struct sk_buff *skb; |
803 | int rc = -EINVAL; | 819 | int rc = -EINVAL; |
804 | 820 | ||
821 | lock_kernel(); | ||
805 | if (!sk || sk->sk_state != TCP_LISTEN) | 822 | if (!sk || sk->sk_state != TCP_LISTEN) |
806 | goto out; | 823 | goto out; |
807 | 824 | ||
@@ -829,6 +846,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
829 | out2: | 846 | out2: |
830 | release_sock(sk); | 847 | release_sock(sk); |
831 | out: | 848 | out: |
849 | unlock_kernel(); | ||
832 | return rc; | 850 | return rc; |
833 | } | 851 | } |
834 | 852 | ||
@@ -838,10 +856,14 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, | |||
838 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr; | 856 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr; |
839 | struct sock *sk = sock->sk; | 857 | struct sock *sk = sock->sk; |
840 | struct x25_sock *x25 = x25_sk(sk); | 858 | struct x25_sock *x25 = x25_sk(sk); |
859 | int rc = 0; | ||
841 | 860 | ||
861 | lock_kernel(); | ||
842 | if (peer) { | 862 | if (peer) { |
843 | if (sk->sk_state != TCP_ESTABLISHED) | 863 | if (sk->sk_state != TCP_ESTABLISHED) { |
844 | return -ENOTCONN; | 864 | rc = -ENOTCONN; |
865 | goto out; | ||
866 | } | ||
845 | sx25->sx25_addr = x25->dest_addr; | 867 | sx25->sx25_addr = x25->dest_addr; |
846 | } else | 868 | } else |
847 | sx25->sx25_addr = x25->source_addr; | 869 | sx25->sx25_addr = x25->source_addr; |
@@ -849,7 +871,21 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, | |||
849 | sx25->sx25_family = AF_X25; | 871 | sx25->sx25_family = AF_X25; |
850 | *uaddr_len = sizeof(*sx25); | 872 | *uaddr_len = sizeof(*sx25); |
851 | 873 | ||
852 | return 0; | 874 | out: |
875 | unlock_kernel(); | ||
876 | return rc; | ||
877 | } | ||
878 | |||
879 | static unsigned int x25_datagram_poll(struct file *file, struct socket *sock, | ||
880 | poll_table *wait) | ||
881 | { | ||
882 | int rc; | ||
883 | |||
884 | lock_kernel(); | ||
885 | rc = datagram_poll(file, sock, wait); | ||
886 | unlock_kernel(); | ||
887 | |||
888 | return rc; | ||
853 | } | 889 | } |
854 | 890 | ||
855 | int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | 891 | int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, |
@@ -1002,6 +1038,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1002 | size_t size; | 1038 | size_t size; |
1003 | int qbit = 0, rc = -EINVAL; | 1039 | int qbit = 0, rc = -EINVAL; |
1004 | 1040 | ||
1041 | lock_kernel(); | ||
1005 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) | 1042 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) |
1006 | goto out; | 1043 | goto out; |
1007 | 1044 | ||
@@ -1166,6 +1203,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1166 | release_sock(sk); | 1203 | release_sock(sk); |
1167 | rc = len; | 1204 | rc = len; |
1168 | out: | 1205 | out: |
1206 | unlock_kernel(); | ||
1169 | return rc; | 1207 | return rc; |
1170 | out_kfree_skb: | 1208 | out_kfree_skb: |
1171 | kfree_skb(skb); | 1209 | kfree_skb(skb); |
@@ -1186,6 +1224,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1186 | unsigned char *asmptr; | 1224 | unsigned char *asmptr; |
1187 | int rc = -ENOTCONN; | 1225 | int rc = -ENOTCONN; |
1188 | 1226 | ||
1227 | lock_kernel(); | ||
1189 | /* | 1228 | /* |
1190 | * This works for seqpacket too. The receiver has ordered the queue for | 1229 | * This works for seqpacket too. The receiver has ordered the queue for |
1191 | * us! We do one quick check first though | 1230 | * us! We do one quick check first though |
@@ -1259,6 +1298,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1259 | out_free_dgram: | 1298 | out_free_dgram: |
1260 | skb_free_datagram(sk, skb); | 1299 | skb_free_datagram(sk, skb); |
1261 | out: | 1300 | out: |
1301 | unlock_kernel(); | ||
1262 | return rc; | 1302 | return rc; |
1263 | } | 1303 | } |
1264 | 1304 | ||
@@ -1270,6 +1310,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1270 | void __user *argp = (void __user *)arg; | 1310 | void __user *argp = (void __user *)arg; |
1271 | int rc; | 1311 | int rc; |
1272 | 1312 | ||
1313 | lock_kernel(); | ||
1273 | switch (cmd) { | 1314 | switch (cmd) { |
1274 | case TIOCOUTQ: { | 1315 | case TIOCOUTQ: { |
1275 | int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | 1316 | int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
@@ -1363,7 +1404,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1363 | facilities.throughput > 0xDD) | 1404 | facilities.throughput > 0xDD) |
1364 | break; | 1405 | break; |
1365 | if (facilities.reverse && | 1406 | if (facilities.reverse && |
1366 | (facilities.reverse | 0x81)!= 0x81) | 1407 | (facilities.reverse & 0x81) != 0x81) |
1367 | break; | 1408 | break; |
1368 | x25->facilities = facilities; | 1409 | x25->facilities = facilities; |
1369 | rc = 0; | 1410 | rc = 0; |
@@ -1430,6 +1471,17 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1430 | break; | 1471 | break; |
1431 | } | 1472 | } |
1432 | 1473 | ||
1474 | case SIOCX25SCAUSEDIAG: { | ||
1475 | struct x25_causediag causediag; | ||
1476 | rc = -EFAULT; | ||
1477 | if (copy_from_user(&causediag, argp, sizeof(causediag))) | ||
1478 | break; | ||
1479 | x25->causediag = causediag; | ||
1480 | rc = 0; | ||
1481 | break; | ||
1482 | |||
1483 | } | ||
1484 | |||
1433 | case SIOCX25SCUDMATCHLEN: { | 1485 | case SIOCX25SCUDMATCHLEN: { |
1434 | struct x25_subaddr sub_addr; | 1486 | struct x25_subaddr sub_addr; |
1435 | rc = -EINVAL; | 1487 | rc = -EINVAL; |
@@ -1472,11 +1524,12 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1472 | rc = -ENOIOCTLCMD; | 1524 | rc = -ENOIOCTLCMD; |
1473 | break; | 1525 | break; |
1474 | } | 1526 | } |
1527 | unlock_kernel(); | ||
1475 | 1528 | ||
1476 | return rc; | 1529 | return rc; |
1477 | } | 1530 | } |
1478 | 1531 | ||
1479 | static struct net_proto_family x25_family_ops = { | 1532 | static const struct net_proto_family x25_family_ops = { |
1480 | .family = AF_X25, | 1533 | .family = AF_X25, |
1481 | .create = x25_create, | 1534 | .create = x25_create, |
1482 | .owner = THIS_MODULE, | 1535 | .owner = THIS_MODULE, |
@@ -1542,15 +1595,19 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1542 | break; | 1595 | break; |
1543 | case SIOCGSTAMP: | 1596 | case SIOCGSTAMP: |
1544 | rc = -EINVAL; | 1597 | rc = -EINVAL; |
1598 | lock_kernel(); | ||
1545 | if (sk) | 1599 | if (sk) |
1546 | rc = compat_sock_get_timestamp(sk, | 1600 | rc = compat_sock_get_timestamp(sk, |
1547 | (struct timeval __user*)argp); | 1601 | (struct timeval __user*)argp); |
1602 | unlock_kernel(); | ||
1548 | break; | 1603 | break; |
1549 | case SIOCGSTAMPNS: | 1604 | case SIOCGSTAMPNS: |
1550 | rc = -EINVAL; | 1605 | rc = -EINVAL; |
1606 | lock_kernel(); | ||
1551 | if (sk) | 1607 | if (sk) |
1552 | rc = compat_sock_get_timestampns(sk, | 1608 | rc = compat_sock_get_timestampns(sk, |
1553 | (struct timespec __user*)argp); | 1609 | (struct timespec __user*)argp); |
1610 | unlock_kernel(); | ||
1554 | break; | 1611 | break; |
1555 | case SIOCGIFADDR: | 1612 | case SIOCGIFADDR: |
1556 | case SIOCSIFADDR: | 1613 | case SIOCSIFADDR: |
@@ -1569,16 +1626,22 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1569 | rc = -EPERM; | 1626 | rc = -EPERM; |
1570 | if (!capable(CAP_NET_ADMIN)) | 1627 | if (!capable(CAP_NET_ADMIN)) |
1571 | break; | 1628 | break; |
1629 | lock_kernel(); | ||
1572 | rc = x25_route_ioctl(cmd, argp); | 1630 | rc = x25_route_ioctl(cmd, argp); |
1631 | unlock_kernel(); | ||
1573 | break; | 1632 | break; |
1574 | case SIOCX25GSUBSCRIP: | 1633 | case SIOCX25GSUBSCRIP: |
1634 | lock_kernel(); | ||
1575 | rc = compat_x25_subscr_ioctl(cmd, argp); | 1635 | rc = compat_x25_subscr_ioctl(cmd, argp); |
1636 | unlock_kernel(); | ||
1576 | break; | 1637 | break; |
1577 | case SIOCX25SSUBSCRIP: | 1638 | case SIOCX25SSUBSCRIP: |
1578 | rc = -EPERM; | 1639 | rc = -EPERM; |
1579 | if (!capable(CAP_NET_ADMIN)) | 1640 | if (!capable(CAP_NET_ADMIN)) |
1580 | break; | 1641 | break; |
1642 | lock_kernel(); | ||
1581 | rc = compat_x25_subscr_ioctl(cmd, argp); | 1643 | rc = compat_x25_subscr_ioctl(cmd, argp); |
1644 | unlock_kernel(); | ||
1582 | break; | 1645 | break; |
1583 | case SIOCX25GFACILITIES: | 1646 | case SIOCX25GFACILITIES: |
1584 | case SIOCX25SFACILITIES: | 1647 | case SIOCX25SFACILITIES: |
@@ -1587,6 +1650,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1587 | case SIOCX25GCALLUSERDATA: | 1650 | case SIOCX25GCALLUSERDATA: |
1588 | case SIOCX25SCALLUSERDATA: | 1651 | case SIOCX25SCALLUSERDATA: |
1589 | case SIOCX25GCAUSEDIAG: | 1652 | case SIOCX25GCAUSEDIAG: |
1653 | case SIOCX25SCAUSEDIAG: | ||
1590 | case SIOCX25SCUDMATCHLEN: | 1654 | case SIOCX25SCUDMATCHLEN: |
1591 | case SIOCX25CALLACCPTAPPRV: | 1655 | case SIOCX25CALLACCPTAPPRV: |
1592 | case SIOCX25SENDCALLACCPT: | 1656 | case SIOCX25SENDCALLACCPT: |
@@ -1600,7 +1664,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1600 | } | 1664 | } |
1601 | #endif | 1665 | #endif |
1602 | 1666 | ||
1603 | static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | 1667 | static const struct proto_ops x25_proto_ops = { |
1604 | .family = AF_X25, | 1668 | .family = AF_X25, |
1605 | .owner = THIS_MODULE, | 1669 | .owner = THIS_MODULE, |
1606 | .release = x25_release, | 1670 | .release = x25_release, |
@@ -1609,7 +1673,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | |||
1609 | .socketpair = sock_no_socketpair, | 1673 | .socketpair = sock_no_socketpair, |
1610 | .accept = x25_accept, | 1674 | .accept = x25_accept, |
1611 | .getname = x25_getname, | 1675 | .getname = x25_getname, |
1612 | .poll = datagram_poll, | 1676 | .poll = x25_datagram_poll, |
1613 | .ioctl = x25_ioctl, | 1677 | .ioctl = x25_ioctl, |
1614 | #ifdef CONFIG_COMPAT | 1678 | #ifdef CONFIG_COMPAT |
1615 | .compat_ioctl = compat_x25_ioctl, | 1679 | .compat_ioctl = compat_x25_ioctl, |
@@ -1624,8 +1688,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | |||
1624 | .sendpage = sock_no_sendpage, | 1688 | .sendpage = sock_no_sendpage, |
1625 | }; | 1689 | }; |
1626 | 1690 | ||
1627 | SOCKOPS_WRAP(x25_proto, AF_X25); | ||
1628 | |||
1629 | static struct packet_type x25_packet_type __read_mostly = { | 1691 | static struct packet_type x25_packet_type __read_mostly = { |
1630 | .type = cpu_to_be16(ETH_P_X25), | 1692 | .type = cpu_to_be16(ETH_P_X25), |
1631 | .func = x25_lapb_receive_frame, | 1693 | .func = x25_lapb_receive_frame, |
@@ -1659,20 +1721,31 @@ static int __init x25_init(void) | |||
1659 | if (rc != 0) | 1721 | if (rc != 0) |
1660 | goto out; | 1722 | goto out; |
1661 | 1723 | ||
1662 | sock_register(&x25_family_ops); | 1724 | rc = sock_register(&x25_family_ops); |
1725 | if (rc != 0) | ||
1726 | goto out_proto; | ||
1663 | 1727 | ||
1664 | dev_add_pack(&x25_packet_type); | 1728 | dev_add_pack(&x25_packet_type); |
1665 | 1729 | ||
1666 | register_netdevice_notifier(&x25_dev_notifier); | 1730 | rc = register_netdevice_notifier(&x25_dev_notifier); |
1731 | if (rc != 0) | ||
1732 | goto out_sock; | ||
1667 | 1733 | ||
1668 | printk(KERN_INFO "X.25 for Linux Version 0.2\n"); | 1734 | printk(KERN_INFO "X.25 for Linux Version 0.2\n"); |
1669 | 1735 | ||
1670 | #ifdef CONFIG_SYSCTL | ||
1671 | x25_register_sysctl(); | 1736 | x25_register_sysctl(); |
1672 | #endif | 1737 | rc = x25_proc_init(); |
1673 | x25_proc_init(); | 1738 | if (rc != 0) |
1739 | goto out_dev; | ||
1674 | out: | 1740 | out: |
1675 | return rc; | 1741 | return rc; |
1742 | out_dev: | ||
1743 | unregister_netdevice_notifier(&x25_dev_notifier); | ||
1744 | out_sock: | ||
1745 | sock_unregister(AF_X25); | ||
1746 | out_proto: | ||
1747 | proto_unregister(&x25_proto); | ||
1748 | goto out; | ||
1676 | } | 1749 | } |
1677 | module_init(x25_init); | 1750 | module_init(x25_init); |
1678 | 1751 | ||
@@ -1682,9 +1755,7 @@ static void __exit x25_exit(void) | |||
1682 | x25_link_free(); | 1755 | x25_link_free(); |
1683 | x25_route_free(); | 1756 | x25_route_free(); |
1684 | 1757 | ||
1685 | #ifdef CONFIG_SYSCTL | ||
1686 | x25_unregister_sysctl(); | 1758 | x25_unregister_sysctl(); |
1687 | #endif | ||
1688 | 1759 | ||
1689 | unregister_netdevice_notifier(&x25_dev_notifier); | 1760 | unregister_netdevice_notifier(&x25_dev_notifier); |
1690 | 1761 | ||