dvtws: do not use raw sockets on BSD. always use divert.

This commit is contained in:
bol-van 2024-08-21 17:59:09 +03:00
parent 600b6c6521
commit a863c35ce3

View File

@ -1621,7 +1621,7 @@ static int rawsend_socket(sa_family_t family)
// IPPROTO_RAW with ipv6 in FreeBSD always returns EACCES on sendto.
// must use IPPROTO_TCP for ipv6. IPPROTO_RAW works for ipv4
// divert sockets are always v4 but accept both v4 and v6
*sock = (family==AF_INET) ? rawsend_socket_raw(family, IPPROTO_TCP) : rawsend_socket_divert(AF_INET);
*sock = rawsend_socket_divert(AF_INET);
#elif defined(__OpenBSD__) || defined (__APPLE__)
// OpenBSD does not allow sending TCP frames through raw sockets
// I dont know about macos. They have dropped ipfw in recent versions and their PF does not support divert-packet
@ -1634,16 +1634,6 @@ static int rawsend_socket(sa_family_t family)
perror("rawsend: socket()");
return -1;
}
#ifdef BSD
#if !(defined(__OpenBSD__) || defined (__APPLE__))
// HDRINCL not supported for ipv6 in any BSD
if (family==AF_INET && setsockopt(*sock,IPPROTO_IP,IP_HDRINCL,&yes,sizeof(yes)) == -1)
{
perror("rawsend: setsockopt(IP_HDRINCL)");
goto exiterr;
}
#endif
#endif
#ifdef __linux__
if (setsockopt(*sock, SOL_SOCKET, SO_PRIORITY, &pri, sizeof(pri)) == -1)
{
@ -1691,51 +1681,19 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const
memcpy(&dst2,dst,salen);
if (dst->sa_family==AF_INET6)
((struct sockaddr_in6 *)&dst2)->sin6_port = 0; // or will be EINVAL in linux
#ifdef BSD
/*
// this works only for local connections and not working for transit : cant spoof source addr
if (len>=sizeof(struct ip6_hdr))
{
// BSD ipv6 raw socks are limited. cannot pass the whole packet with ip6 header.
struct sockaddr_storage sa_src;
int v;
extract_endpoints(NULL,(struct ip6_hdr *)data,NULL,NULL, &sa_src, NULL);
v = ((struct ip6_hdr *)data)->ip6_ctlun.ip6_un1.ip6_un1_hlim;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &v, sizeof(v)) == -1)
perror("rawsend: setsockopt(IPV6_HOPLIMIT)");
// the only way to control source address is bind. make it equal to ip6_hdr
if (bind(sock, (struct sockaddr*)&sa_src, salen) < 0)
perror("rawsend bind: ");
//printf("BSD v6 RAWSEND "); print_sockaddr((struct sockaddr*)&sa_src); printf(" -> "); print_sockaddr((struct sockaddr*)&dst2); printf("\n");
proto_skip_ipv6((uint8_t**)&data, &len, NULL);
}
*/
#if !(defined(__OpenBSD__) || defined (__APPLE__))
// OpenBSD doesnt allow rawsending tcp frames. always use divert socket
if (dst->sa_family==AF_INET6)
#endif
#if defined(BSD)
bytes = rawsend_sendto_divert(dst->sa_family,sock,data,len);
if (bytes==-1)
{
ssize_t bytes = rawsend_sendto_divert(dst->sa_family,sock,data,len);
if (bytes==-1)
{
perror("rawsend: sendto_divert");
return false;
}
return true;
perror("rawsend: sendto_divert");
return false;
}
#endif
return true;
#if defined(__FreeBSD__) && __FreeBSD__<=10
// old FreeBSD requires some fields in host byte order
if (dst->sa_family==AF_INET && len>=sizeof(struct ip))
{
((struct ip*)data)->ip_len = htons(((struct ip*)data)->ip_len);
((struct ip*)data)->ip_off = htons(((struct ip*)data)->ip_off);
}
#endif
#else
#if defined(__linux__)
#ifdef __linux__
struct sockaddr_storage sa_src;
switch(dst->sa_family)
{
@ -1774,20 +1732,13 @@ nofix:
// normal raw socket sendto
bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen);
#if defined(__FreeBSD) && __FreeBSD__<=10
// restore byte order
if (dst->sa_family==AF_INET && len>=sizeof(struct ip))
{
((struct ip*)data)->ip_len = htons(((struct ip*)data)->ip_len);
((struct ip*)data)->ip_off = htons(((struct ip*)data)->ip_off);
}
#endif
if (bytes==-1)
{
perror("rawsend: sendto");
return false;
}
return true;
#endif
}
#endif // not CYGWIN