diff --git a/socket/socket_broadcast.c b/socket/socket_broadcast.c new file mode 100644 index 0000000..294cfbd --- /dev/null +++ b/socket/socket_broadcast.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include +#include "socket.h" + +int socket_broadcast(int s) +{ + int opt = 1; + return setsockopt(s,SOL_SOCKET,SO_BROADCAST,&opt,sizeof opt); +} + diff --git a/socket/socket_mcjoin4.c b/socket/socket_mcjoin4.c new file mode 100644 index 0000000..fe4299b --- /dev/null +++ b/socket/socket_mcjoin4.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include +#include "socket.h" +#include "byte.h" + +int socket_mcjoin4(int s,const char ip[4],const char interface[4]) +{ + struct ip_mreq opt; + byte_copy(&opt.imr_multiaddr.s_addr,4,ip); + byte_copy(&opt.imr_interface.s_addr,4,interface); + return setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,&opt,sizeof opt); +} + diff --git a/socket/socket_mcjoin6.c b/socket/socket_mcjoin6.c new file mode 100644 index 0000000..28319ea --- /dev/null +++ b/socket/socket_mcjoin6.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include "socket.h" +#include "byte.h" +#include "haveip6.h" +#include "ip6.h" +#include "error.h" + +#ifndef IPV6_ADD_MEMBERSHIP +#ifdef IPV6_JOIN_GROUP +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#else +#undef LIBC_HAS_IP6 +#endif +#endif + +int socket_mcjoin6(int s,const char ip[16],int interface) +{ +#ifdef LIBC_HAS_IP6 + struct ipv6_mreq opt; +#endif + if (ip6_isv4mapped(ip)) + return socket_mcjoin4(s,ip+12,ip); +#ifdef LIBC_HAS_IP6 + byte_copy(&opt.ipv6mr_multiaddr,16,ip); +#ifdef __GLIBC__ + opt.ipv6mr_interface=interface; +#else + opt.ipv6mr_ifindex=interface; +#endif + return setsockopt(s,IPPROTO_IPV6,IPV6_ADD_MEMBERSHIP,&opt,sizeof opt); +#else + errno=error_proto; + return -1; +#endif +} diff --git a/socket/socket_mcleave4.c b/socket/socket_mcleave4.c new file mode 100644 index 0000000..e068c0f --- /dev/null +++ b/socket/socket_mcleave4.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include +#include "socket.h" +#include "byte.h" + +int socket_mcleave4(int s,const char ip[4]) +{ + struct ip_mreq opt; + byte_copy(&opt.imr_multiaddr.s_addr,4,ip); + byte_zero(&opt.imr_interface.s_addr,4); + return setsockopt(s,IPPROTO_IP,IP_DROP_MEMBERSHIP,&opt,sizeof opt); +} + diff --git a/socket/socket_mcleave6.c b/socket/socket_mcleave6.c new file mode 100644 index 0000000..4b8583d --- /dev/null +++ b/socket/socket_mcleave6.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include "socket.h" +#include "byte.h" +#include "haveip6.h" +#include "error.h" +#include "ip6.h" + +#ifndef IPV6_DROP_MEMBERSHIP +#ifdef IPV6_LEAVE_GROUP +#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +#else +#undef LIBC_HAS_IP6 +#endif +#endif + +int socket_mcleave6(int s,const char ip[16]) +{ +#ifdef LIBC_HAS_IP6 + struct ipv6_mreq opt; +#endif + if (ip6_isv4mapped(ip)) + return socket_mcleave4(s,ip+12); +#ifdef LIBC_HAS_IP6 + byte_copy(&opt.ipv6mr_multiaddr,16,ip); +#ifdef __GLIBC__ + opt.ipv6mr_interface=0; +#else + opt.ipv6mr_ifindex=0; +#endif + return setsockopt(s,IPPROTO_IPV6,IPV6_DROP_MEMBERSHIP,&opt,sizeof opt); +#else + errno=EPROTO; + return -1; +#endif +} + diff --git a/socket/socket_mcloop4.c b/socket/socket_mcloop4.c new file mode 100644 index 0000000..eec742d --- /dev/null +++ b/socket/socket_mcloop4.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include +#include "socket.h" + +int socket_mcloop4(int s,char loop) +{ + return setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof loop); +} + diff --git a/socket/socket_mcloop6.c b/socket/socket_mcloop6.c new file mode 100644 index 0000000..88cce9b --- /dev/null +++ b/socket/socket_mcloop6.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include "socket.h" +#include "haveip6.h" + +int socket_mcloop6(int s,char loop) +{ +#ifdef LIBC_HAS_IP6 + if (noipv6) + return setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof loop); + else + return setsockopt(s,IPPROTO_IPV6,IPV6_MULTICAST_LOOP,&loop,sizeof loop); +#else + return setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof loop); +#endif +} + diff --git a/socket/socket_mcttl4.c b/socket/socket_mcttl4.c new file mode 100644 index 0000000..44316de --- /dev/null +++ b/socket/socket_mcttl4.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include +#include "socket.h" + +int socket_mcttl4(int s,char TTL) +{ + return setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,&TTL,sizeof TTL); +} + diff --git a/socket/socket_mcttl6.c b/socket/socket_mcttl6.c new file mode 100644 index 0000000..9c82272 --- /dev/null +++ b/socket/socket_mcttl6.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include "socket.h" +#include "byte.h" +#include "haveip6.h" +#include "ip6.h" + +#ifndef IPV6_MULTICAST_HOPS +#undef LIBC_HAS_IP6 +#endif + +int socket_mcttl6(int s,char TTL) +{ +#ifdef LIBC_HAS_IP6 + return setsockopt(s,IPPROTO_IPV6,IPV6_MULTICAST_HOPS,&TTL,sizeof TTL); +#else + return socket_mcttl4(s,TTL); +#endif +} diff --git a/socket/socket_recv4.c b/socket/socket_recv4.c new file mode 100644 index 0000000..5f0b788 --- /dev/null +++ b/socket/socket_recv4.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include +#include "socket.h" + +int socket_recv4(int s,char *buf,unsigned int len,char ip[4],uint16 *port) { + struct sockaddr_in si; + unsigned int Len = sizeof si; + int r; + + if ((r = recvfrom(s,buf,len,0,(struct sockaddr *) &si,&Len))<0) return -1; + *(uint32*)ip = *(uint32*)&si.sin_addr; + uint16_unpack_big((char *) &si.sin_port,port); + return r; +} diff --git a/socket/socket_recv6.c b/socket/socket_recv6.c new file mode 100644 index 0000000..2901596 --- /dev/null +++ b/socket/socket_recv6.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include "byte.h" +#include "socket.h" +#include "ip6.h" +#include "haveip6.h" +#include "error.h" + +int socket_recv6(int s,char *buf,unsigned int len,char ip[16],uint16 *port,uint32 *scope_id) +{ +#ifdef LIBC_HAS_IP6 + struct sockaddr_in6 si; +#else + struct sockaddr_in si; +#endif + unsigned int Len = sizeof si; + int r; + + byte_zero(&si,Len); + if ((r = recvfrom(s,buf,len,0,(struct sockaddr *) &si,&Len))<0) return -1; + +#ifdef LIBC_HAS_IP6 + if (noipv6) { + struct sockaddr_in *si4=(struct sockaddr_in *)&si; + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip+12,4,(char *) &si4->sin_addr); + uint16_unpack_big((char *) &si4->sin_port,port); + return r; + } + byte_copy(ip,16,(char *) &si.sin6_addr); + uint16_unpack_big((char *) &si.sin6_port,port); + if (scope_id) *scope_id=si.sin6_scope_id; +#else + byte_copy(ip,12,(char *)V4mappedprefix); + byte_copy(ip+12,4,(char *) &si.sin_addr); + uint16_unpack_big((char *) &si.sin_port,port); + if (scope_id) *scope_id=0; +#endif + + return r; +} diff --git a/socket/socket_tryreservein.c b/socket/socket_tryreservein.c new file mode 100644 index 0000000..4093019 --- /dev/null +++ b/socket/socket_tryreservein.c @@ -0,0 +1,10 @@ +#include +#include "socket.h" + +void socket_tryreservein(int s,int size) +{ + while (size >= 1024) { + if (setsockopt(s,SOL_SOCKET,SO_RCVBUF,&size,sizeof size) == 0) return; + size -= (size >> 5); + } +}