Telling BSD to stop resetting the connection!
Dan Joumaa
nessup at gmail.com
Wed Jan 11 20:06:15 PST 2006
On Jan 11, 2006, at 7:24 PM, David S. Madole wrote:
> From: "Dan Joumaa" <nessup at gmail.com>
>>
>> I'm trying to code a software gateway with divert sockets. So far
>> basic things are working, but the net stack constantly resets the
>> connection whenever a SYN-ACK is sent to it.
>>
>> Any ideas on how to stop the net stack from resetting my connections,
>> preferably programmatically?
>
> I think you are doing something wrong, either not diverting packets
> that should be, or reinjecting packets from your code that are
> incorrect in some way.
>
> Without seeing the ipfw rules or code, there's not much else that can
> be said.
>
> David
>
>
Here's the rules:
00001 divert 4747 tcp from 192.168.1.6 to any in
00001 divert 4747 udp from 192.168.1.6 to any in
The following rules are added dynamically when my client sends a packet
to a server so we can get it back on the divert socket. In this case,
it would be:
00001 divert 4747 tcp from 205.166.76.216 to any in
00001 divert 4747 udp from 205.166.76.216 to any in
First thing, I receive the packets from the divert socket.
...
if( (datagramlen = recvfrom( sock->ipfd, buffer, buflen, 0x0,
(struct sockaddr *)&sin, &sinlen )) <
0 )
(void)fprintf( stderr, "Failed to receive packet. Error: %i\n",
errno );
...
If it is from my client, I add the destination host the client wants to
talk to as a divert rule to the IPFW...
entry->version = IP_FW_CURRENT_API_VERSION;
entry->fw_number = 1;
entry->fw_src.s_addr = htonl(host);
entry->fw_smsk.s_addr = ~0;
entry->fw_prot = IPPROTO_TCP;
entry->fw_flg = IP_FW_F_DIVERT|IP_FW_F_IN;
entry->fw_un.fu_divert_port = DIVERTSOCKET_PORT;
(void)memcpy( entry->fw_in_if.fu_via_if.name, sock->dev, FW_IFNLEN );
entry->fw_in_if.fu_via_if.unit = -1;
if( setsockopt( sock->fwfd, IPPROTO_IP, IP_FW_ADD, entry,
sizeof(struct ip_fw) ) < 0 ) {
(void)fprintf( stderr, "Failed to add entry to filter. Error:
%i\n",
errno );
return (-1);
}
... modify the packet for sending ...
ip_hdr->ip_src.s_addr = htonl( thisIP );
/* checksuming code below */
... and send it through a raw socket.
sin.sin_family = AF_INET;
sin.sin_port = 0;
sin.sin_addr.s_addr = ip_hdr->ip_dst.s_addr;
if( (datagramlen = sendto( socket->fwfd, buffer, buflen, 0x0,
(struct sockaddr *)&sin, sizeof(sin) ))
< 0 )
(void)fprintf( stderr, "Failed to send packet. Error: %i\n",
errno );
If it's from someone outside the LAN, modify it for forwarding to the
client...
ip_hdr->ip_dst.s_addr = htonl( clientIP );
ip_hdr->ip_sum = 0;
ip_hdr->ip_sum = htons( in_cksum( (u_short *)ip_hdr,
sizeof(struct iphdr) ) );
/* checksuming code below */
And send it through a raw socket.
All in all, that's really what it is. This seems to work with normal
HTTP requests, but fails to work with establishing a connection on
HTTPS. :/
--ness
More information about the freebsd-hackers
mailing list