| 2778 | } |
| 2779 | |
| 2780 | int |
| 2781 | lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) |
| 2782 | { |
| 2783 | int err; |
| 2784 | struct lwip_sock *sock = get_socket(s); |
| 2785 | #if !LWIP_TCPIP_CORE_LOCKING |
| 2786 | err_t cberr; |
| 2787 | LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); |
| 2788 | #endif /* !LWIP_TCPIP_CORE_LOCKING */ |
| 2789 | |
| 2790 | if (!sock) { |
| 2791 | return -1; |
| 2792 | } |
| 2793 | |
| 2794 | if ((NULL == optval) || (NULL == optlen)) { |
| 2795 | sock_set_errno(sock, EFAULT); |
| 2796 | done_socket(sock); |
| 2797 | return -1; |
| 2798 | } |
| 2799 | |
| 2800 | #if LWIP_TCPIP_CORE_LOCKING |
| 2801 | /* core-locking can just call the -impl function */ |
| 2802 | LOCK_TCPIP_CORE(); |
| 2803 | err = lwip_getsockopt_impl(s, level, optname, optval, optlen); |
| 2804 | UNLOCK_TCPIP_CORE(); |
| 2805 | |
| 2806 | #else /* LWIP_TCPIP_CORE_LOCKING */ |
| 2807 | |
| 2808 | #if LWIP_MPU_COMPATIBLE |
| 2809 | /* MPU_COMPATIBLE copies the optval data, so check for max size here */ |
| 2810 | if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { |
| 2811 | sock_set_errno(sock, ENOBUFS); |
| 2812 | done_socket(sock); |
| 2813 | return -1; |
| 2814 | } |
| 2815 | #endif /* LWIP_MPU_COMPATIBLE */ |
| 2816 | |
| 2817 | LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); |
| 2818 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; |
| 2819 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; |
| 2820 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; |
| 2821 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen; |
| 2822 | #if !LWIP_MPU_COMPATIBLE |
| 2823 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval; |
| 2824 | #endif /* !LWIP_MPU_COMPATIBLE */ |
| 2825 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; |
| 2826 | #if LWIP_NETCONN_SEM_PER_THREAD |
| 2827 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); |
| 2828 | #else |
| 2829 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; |
| 2830 | #endif |
| 2831 | cberr = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); |
| 2832 | if (cberr != ERR_OK) { |
| 2833 | LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); |
| 2834 | sock_set_errno(sock, err_to_errno(cberr)); |
| 2835 | done_socket(sock); |
| 2836 | return -1; |
| 2837 | } |