| 3224 | } |
| 3225 | |
| 3226 | int |
| 3227 | lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) |
| 3228 | { |
| 3229 | int err = 0; |
| 3230 | struct lwip_sock *sock = get_socket(s); |
| 3231 | #if !LWIP_TCPIP_CORE_LOCKING |
| 3232 | err_t cberr; |
| 3233 | LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); |
| 3234 | #endif /* !LWIP_TCPIP_CORE_LOCKING */ |
| 3235 | |
| 3236 | if (!sock) { |
| 3237 | return -1; |
| 3238 | } |
| 3239 | |
| 3240 | if (NULL == optval) { |
| 3241 | sock_set_errno(sock, EFAULT); |
| 3242 | done_socket(sock); |
| 3243 | return -1; |
| 3244 | } |
| 3245 | |
| 3246 | #if LWIP_TCPIP_CORE_LOCKING |
| 3247 | /* core-locking can just call the -impl function */ |
| 3248 | LOCK_TCPIP_CORE(); |
| 3249 | err = lwip_setsockopt_impl(s, level, optname, optval, optlen); |
| 3250 | UNLOCK_TCPIP_CORE(); |
| 3251 | |
| 3252 | #else /* LWIP_TCPIP_CORE_LOCKING */ |
| 3253 | |
| 3254 | #if LWIP_MPU_COMPATIBLE |
| 3255 | /* MPU_COMPATIBLE copies the optval data, so check for max size here */ |
| 3256 | if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { |
| 3257 | sock_set_errno(sock, ENOBUFS); |
| 3258 | done_socket(sock); |
| 3259 | return -1; |
| 3260 | } |
| 3261 | #endif /* LWIP_MPU_COMPATIBLE */ |
| 3262 | |
| 3263 | LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); |
| 3264 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; |
| 3265 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; |
| 3266 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; |
| 3267 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; |
| 3268 | #if LWIP_MPU_COMPATIBLE |
| 3269 | MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); |
| 3270 | #else /* LWIP_MPU_COMPATIBLE */ |
| 3271 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void *)optval; |
| 3272 | #endif /* LWIP_MPU_COMPATIBLE */ |
| 3273 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; |
| 3274 | #if LWIP_NETCONN_SEM_PER_THREAD |
| 3275 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); |
| 3276 | #else |
| 3277 | LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; |
| 3278 | #endif |
| 3279 | cberr = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); |
| 3280 | if (cberr != ERR_OK) { |
| 3281 | LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); |
| 3282 | sock_set_errno(sock, err_to_errno(cberr)); |
| 3283 | done_socket(sock); |