📄 sockets.c
字号:
#endif /* LWIP_SO_RCVBUF */
#if LWIP_UDP
case SO_NO_CHECK:
*(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
break;
#endif /* LWIP_UDP*/
default:
LWIP_ASSERT("unhandled optname", 0);
break;
} /* switch (optname) */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch (optname) {
case IP_TTL:
*(int*)optval = sock->conn->pcb.ip->ttl;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
s, *(int *)optval));
break;
case IP_TOS:
*(int*)optval = sock->conn->pcb.ip->tos;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
s, *(int *)optval));
break;
#if LWIP_IGMP
case IP_MULTICAST_TTL:
*(u8_t*)optval = sock->conn->pcb.ip->ttl;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
s, *(int *)optval));
break;
case IP_MULTICAST_IF:
inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
s, *(u32_t *)optval));
break;
case IP_MULTICAST_LOOP:
if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
*(u8_t*)optval = 1;
} else {
*(u8_t*)optval = 0;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n",
s, *(int *)optval));
break;
#endif /* LWIP_IGMP */
default:
LWIP_ASSERT("unhandled optname", 0);
break;
} /* switch (optname) */
break;
#if LWIP_TCP
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
switch (optname) {
case TCP_NODELAY:
*(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
s, (*(int*)optval)?"on":"off") );
break;
case TCP_KEEPALIVE:
*(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n",
s, *(int *)optval));
break;
#if LWIP_TCP_KEEPALIVE
case TCP_KEEPIDLE:
*(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n",
s, *(int *)optval));
break;
case TCP_KEEPINTVL:
*(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n",
s, *(int *)optval));
break;
case TCP_KEEPCNT:
*(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n",
s, *(int *)optval));
break;
#endif /* LWIP_TCP_KEEPALIVE */
default:
LWIP_ASSERT("unhandled optname", 0);
break;
} /* switch (optname) */
break;
#endif /* LWIP_TCP */
#if LWIP_UDP && LWIP_UDPLITE
/* Level: IPPROTO_UDPLITE */
case IPPROTO_UDPLITE:
switch (optname) {
case UDPLITE_SEND_CSCOV:
*(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
s, (*(int*)optval)) );
break;
case UDPLITE_RECV_CSCOV:
*(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
s, (*(int*)optval)) );
break;
default:
LWIP_ASSERT("unhandled optname", 0);
break;
} /* switch (optname) */
break;
#endif /* LWIP_UDP */
default:
LWIP_ASSERT("unhandled level", 0);
break;
} /* switch (level) */
sys_sem_signal(&sock->conn->op_completed);
}
int
lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
{
struct lwip_sock *sock = get_socket(s);
err_t err = ERR_OK;
struct lwip_setgetsockopt_data data;
if (!sock) {
return -1;
}
if (NULL == optval) {
sock_set_errno(sock, EFAULT);
return -1;
}
/* Do length and type checks for the various options first, to keep it readable. */
switch (level) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch (optname) {
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case case SO_CONTIMEO: */
/* UNIMPL case case SO_SNDTIMEO: */
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO:
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
case SO_RCVBUF:
#endif /* LWIP_SO_RCVBUF */
/* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_SNDBUF: */
/* UNIMPL case SO_RCVLOWAT: */
/* UNIMPL case SO_SNDLOWAT: */
#if SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
/* UNIMPL case SO_USELOOPBACK: */
if (optlen < sizeof(int)) {
err = EINVAL;
}
break;
case SO_NO_CHECK:
if (optlen < sizeof(int)) {
err = EINVAL;
}
#if LWIP_UDP
if ((sock->conn->type != NETCONN_UDP) ||
((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
/* this flag is only available for UDP, not for UDP lite */
err = EAFNOSUPPORT;
}
#endif /* LWIP_UDP */
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
s, optname));
err = ENOPROTOOPT;
} /* switch (optname) */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch (optname) {
/* UNIMPL case IP_HDRINCL: */
/* UNIMPL case IP_RCVDSTADDR: */
/* UNIMPL case IP_RCVIF: */
case IP_TTL:
case IP_TOS:
if (optlen < sizeof(int)) {
err = EINVAL;
}
break;
#if LWIP_IGMP
case IP_MULTICAST_TTL:
if (optlen < sizeof(u8_t)) {
err = EINVAL;
}
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
err = EAFNOSUPPORT;
}
break;
case IP_MULTICAST_IF:
if (optlen < sizeof(struct in_addr)) {
err = EINVAL;
}
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
err = EAFNOSUPPORT;
}
break;
case IP_MULTICAST_LOOP:
if (optlen < sizeof(u8_t)) {
err = EINVAL;
}
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
err = EAFNOSUPPORT;
}
break;
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
if (optlen < sizeof(struct ip_mreq)) {
err = EINVAL;
}
if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
err = EAFNOSUPPORT;
}
break;
#endif /* LWIP_IGMP */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
s, optname));
err = ENOPROTOOPT;
} /* switch (optname) */
break;
#if LWIP_TCP
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
if (optlen < sizeof(int)) {
err = EINVAL;
break;
}
/* If this is no TCP socket, ignore any options. */
if (sock->conn->type != NETCONN_TCP)
return 0;
switch (optname) {
case TCP_NODELAY:
case TCP_KEEPALIVE:
#if LWIP_TCP_KEEPALIVE
case TCP_KEEPIDLE:
case TCP_KEEPINTVL:
case TCP_KEEPCNT:
#endif /* LWIP_TCP_KEEPALIVE */
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
s, optname));
err = ENOPROTOOPT;
} /* switch (optname) */
break;
#endif /* LWIP_TCP */
#if LWIP_UDP && LWIP_UDPLITE
/* Level: IPPROTO_UDPLITE */
case IPPROTO_UDPLITE:
if (optlen < sizeof(int)) {
err = EINVAL;
break;
}
/* If this is no UDP lite socket, ignore any options. */
if (sock->conn->type != NETCONN_UDPLITE)
return 0;
switch (optname) {
case UDPLITE_SEND_CSCOV:
case UDPLITE_RECV_CSCOV:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
s, optname));
err = ENOPROTOOPT;
} /* switch (optname) */
break;
#endif /* LWIP_UDP && LWIP_UDPLITE */
/* UNDEFINED LEVEL */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
s, level, optname));
err = ENOPROTOOPT;
} /* switch (level) */
if (err != ERR_OK) {
sock_set_errno(sock, err);
return -1;
}
/* Now do the actual option processing */
data.sock = sock;
#ifdef LWIP_DEBUG
data.s = s;
#endif /* LWIP_DEBUG */
data.level = level;
data.optname = optname;
data.optval = (void*)optval;
data.optlen = &optlen;
data.err = err;
tcpip_callback(lwip_setsockopt_internal, &data);
sys_arch_sem_wait(&sock->conn->op_completed, 0);
/* maybe lwip_setsockopt_internal has changed err */
err = data.err;
sock_set_errno(sock, err);
return err ? -1 : 0;
}
static void
lwip_setsockopt_internal(void *arg)
{
struct lwip_sock *sock;
#ifdef LWIP_DEBUG
int s;
#endif /* LWIP_DEBUG */
int level, optname;
const void *optval;
struct lwip_setgetsockopt_data *data;
LWIP_ASSERT("arg != NULL", arg != NULL);
data = (struct lwip_setgetsockopt_data*)arg;
sock = data->sock;
#ifdef LWIP_DEBUG
s = data->s;
#endif /* LWIP_DEBUG */
level = data->level;
optname = data->optname;
optval = data->optval;
switch (level) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch (optname) {
/* The option flags */
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINCLUDE: */
#if SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
/* UNIMPL case SO_USELOOPBACK: */
if (*(int*)optval) {
sock->conn->pcb.ip->so_options |= optname;
} else {
sock->conn->pcb.ip->so_options &= ~optname;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
s, optname, (*(int*)optval?"on":"off")));
break;
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO:
netconn_set_recvtimeout(sock->conn, *(int*)optval);
break;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
case SO_RCVBUF:
netconn_set_recvbufsize(sock->conn, *(int*)optval);
break;
#endif /* LWIP_SO_RCVBUF */
#if LWIP_UDP
case SO_NO_CHECK:
if (*(int*)optval) {
udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
} else {
udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
}
break;
#endif /* LWIP_UDP */
default:
LWIP_ASSERT("unhandled optname", 0);
break;
} /* switch (optname) */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch (optname) {
case IP_TTL:
sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
s, sock->conn->pcb.ip->ttl));
break;
case IP_TOS:
sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
s, sock->conn->pcb.ip->tos));
break;
#if LWIP_IGMP
case IP_MULTICAST_TTL:
sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval);
break;
case IP_MULTICAST_IF:
inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval);
break;
case IP_MULTICAST_LOOP:
if (*(u8_t*)optval) {
udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
} else {
udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
}
break;
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
{
/* If this is a TCP or a RAW socket, ignore these optio
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -