// Details of actualized connections.
struct Remote {
struct SockAddr uaddr; // The remote IP address
- struct SockAddr laddr; // The local IP address
struct Allowed *spec; // Rule being instantiated
struct timeval rec_when; // Last received packet time, in seconds
+ struct SockAddr laddr; // The local IP address
};
// Details of an interface at a remote.
if ( n < 12 ) {
VERBOSE2OUT( "SENDing %d bytes to %s\n", n, inet_stoa( &r->uaddr ) );
} else {
- VERBOSE2OUT( "SENDing %d bytes %s -> %s to %s\n", n,
+ VERBOSE2OUT( "SENDing %d bytes %s -> %s from %s to %s\n", n,
inet_mtoa( buf+6 ), inet_mtoa( buf ),
+ inet_stoa( &r->laddr ),
inet_stoa( &r->uaddr ) );
}
memcpy( output, buf, n ); // Use the private buffer for delivery
} else if ( r->spec->psk.keyfile ) {
encrypt( output, n, &r->spec->psk );
}
- // Setup the packet addressing
+ // Reserve for packet addressing
struct in_pktinfo pkt4info = {
.ipi_ifindex = 0, /* Interface index */
.ipi_spec_dst.s_addr = 0, /* Local address */
struct sockaddr_in6 *sock6 = &r->uaddr.in6;
void *sock;
size_t size;
+ int flags = 0;
if ( udp6 ) {
// Note that the size of +struct sockaddr_in6+ is actually
// larger than the size of +struct sockaddr+ (due to the
// following cuteness for passing arguments to +sendto+.
sock = sock6;
size = sizeof( struct sockaddr_in6 );
- VERBOSE2OUT( "IPv6 UDP %d %s\n",
- udp_fd, inet_stoa( &r->laddr ) );
- if ( r->laddr.in.sa_family ) {
+ VERBOSE2OUT( "IPv6 UDP %d %s %s\n", udp_fd,
+ inet_stoa( &r->laddr ),
+ inet_stoa( &r->uaddr ) );
+ switch ( r->laddr.in.sa_family ) {
+ case AF_INET6:
memcpy( &pkt6info.ipi6_addr, &sock6->sin6_addr, 16 );
pktinfo = &pkt6info;
pktinfosize = sizeof( pkt6info );
- }
- } else {
- sock = sock4;
- size = sizeof( struct sockaddr_in );
- VERBOSE2OUT( "IPv4 UDP %d %s\n",
- udp_fd, inet_stoa( &r->laddr ) );
- if ( r->laddr.in.sa_family ) {
+ flags = IPV6_PKTINFO;
+ break;
+ case AF_INET:
memcpy( &pkt4info.ipi_spec_dst, &sock4->sin_addr, 4 );
pktinfo = &pkt4info;
pktinfosize = sizeof( pkt4info );
+ flags = IP_PKTINFO;
+ break;
}
+ } else {
+ sock = sock4;
+ size = sizeof( struct sockaddr_in );
+ VERBOSE2OUT( "IPv4 UDP %d %s %s\n", udp_fd,
+ inet_stoa( &r->laddr ),
+ inet_stoa( &r->uaddr ) );
+ memcpy( &pkt4info.ipi_spec_dst, &sock4->sin_addr, 4 );
+ pktinfo = &pkt4info;
+ pktinfosize = sizeof( pkt4info );
+ flags = IP_PKTINFO;
}
VERBOSE2OUT( "SEND %d bytes from %s to %s [%s -> %s]\n",
n,
);
// IS sendmsg thread safe??
struct iovec data[1] = {{ output, n }};
- (void)pktinfo;
- (void)pktinfosize;
struct msghdr msg = {
.msg_name = sock,
.msg_namelen = size,
.msg_iov = data,
.msg_iovlen = 1,
- .msg_control = 0, //pktinfo,
- .msg_controllen = 0, //pktinfosize,
+ .msg_control = pktinfo,
+ .msg_controllen = pktinfosize,
.msg_flags = 0 // unused
};
- if ( sendmsg( udp_fd, &msg, 0 ) < n ) {
+ if ( sendmsg( udp_fd, &msg, flags ) < n ) {
perror( "Writing socket" );
// Invalidate remote temporarily instead? But if it's an
// "uplink" it should be retried eventually...
Interface_DEL( y ); // Need to see this interface again
return;
}
- VERBOSE2OUT( "RECV route %s -> %s to %s\n",
- inet_mtoa( buf+6 ), inet_mtoa( buf ),
- inet_stoa( &y->remote->uaddr ) );
// Set the local address for the remote
- memcpy( &y->remote->laddr, &pi->dst, sizeof( pi->dst ) );
+ memcpy( &x->remote->laddr, &pi->dst, sizeof( pi->dst ) );
+ VERBOSE2OUT( "RECV route %s -> %s using %s\n",
+ inet_mtoa( buf+6 ), inet_mtoa( buf ),
+ inet_stoa( &x->remote->laddr ) );
write_remote( buf, len, y->remote );
return;
}
} else {
if ( udp6 ) {
unmap_if_mapped( &todo->src );
+ unmap_if_mapped( &todo->dst );
}
route_packet( todo );
}
+ memset( &todo->src, 0, sizeof( struct SockAddr ) );
+ memset( &todo->dst, 0, sizeof( struct SockAddr ) );
Queue_addItem( &todolist.free, (QueueItem*) todo );
}
return 0;
}
}
-static ssize_t recvpacket(int fd,PacketItem *p) {
- int flags = 0;
- socklen_t addrlen =
- udp6? sizeof( p->src.in6 ) : sizeof( p->src.in4 );
- struct iovec buffer = {
- .iov_base = p->buffer,
- .iov_len = BUFSIZE
- };
- char data[1000];
+// Reads a UDP packet on the given file descriptor and captures the
+// source and destination addresses of the UDP message.
+inline static ssize_t recvpacket(int fd,PacketItem *p) {
+ char data[100]; // Data area for "pktinfo"
+ struct iovec buffer[1] = {{ p->buffer, BUFSIZE }};
struct msghdr msg = {
.msg_name = &p->src.in,
- .msg_namelen = addrlen,
- .msg_iov = &buffer,
+ .msg_namelen = udp6? sizeof( p->src.in6 ) : sizeof( p->src.in4 ),
+ .msg_iov = buffer,
.msg_iovlen = 1,
.msg_control = data,
.msg_controllen = sizeof( data ),
.msg_flags = 0 // Return value
};
- p->len = recvmsg( fd, &msg, flags );
+ p->len = recvmsg( fd, &msg, udp6? 0 : IP_PKTINFO );
struct cmsghdr *cmsg = CMSG_FIRSTHDR( &msg );
- VERBOSE3OUT( "anc %p %ld\n", cmsg, p->len );
- for ( ; cmsg; cmsg = CMSG_NXTHDR( &msg, cmsg ) ) {
- VERBOSE3OUT( "anc type = %d\n", cmsg->cmsg_type );
- }
- cmsg = CMSG_FIRSTHDR( &msg );
if ( cmsg ) {
if ( udp6 ) {
struct in6_pktinfo *pinf = (struct in6_pktinfo*) CMSG_DATA( cmsg );
p->dst.in6.sin6_family = AF_INET6;
memcpy( &p->dst.in6.sin6_addr, &pinf->ipi6_addr, 16 );
- VERBOSE3OUT( "DEST= udp6 %d %s\n",
+ VERBOSE2OUT( "DEST= udp6 %d %s\n",
pinf->ipi6_ifindex, inet_stoa( &p->dst ) );
} else {
struct in_pktinfo *pinf = (struct in_pktinfo*) CMSG_DATA( cmsg );
p->dst.in4.sin_family = AF_INET;
p->dst.in4.sin_addr = pinf->ipi_addr;
- VERBOSE3OUT( "DEST= %d %s\n",
+ VERBOSE2OUT( "DEST= %d %s\n",
pinf->ipi_ifindex, inet_stoa( &p->dst ) );
}
}
while ( 1 ) {
PacketItem *todo = (PacketItem *) Queue_getItem( &todolist.free );
todo->fd = fd;
- memset( &todo->src, 0, sizeof( struct SockAddr ) );
- memset( &todo->dst, 0, sizeof( struct SockAddr ) );
- todo->len = 0;
- VERBOSE3OUT( "Reading packet\n" );
+ VERBOSE3OUT( "Reading packet on %d\n", fd );
ssize_t len = recvpacket( fd, todo );
if ( len == -1) {
perror( "Receiving UDP" );