capturing for ipv4
authorRalph Ronnquist <ralph.ronnquist@gmail.com>
Thu, 10 Nov 2022 03:11:08 +0000 (14:11 +1100)
committerRalph Ronnquist <ralph.ronnquist@gmail.com>
Thu, 10 Nov 2022 03:11:08 +0000 (14:11 +1100)
rrqnet.c

index 005fd209f6b84e7cef8c2bfdef80a5a0bf342ef6..cf0617ed2b198d2d6124c12ddb10bf1a979ec245 100644 (file)
--- a/rrqnet.c
+++ b/rrqnet.c
@@ -26,6 +26,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <sys/socket.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -64,7 +65,8 @@ struct Allowed {
 
 // Details of actualized connections.
 struct Remote {
-    struct SockAddr uaddr;
+    struct SockAddr uaddr;     // The remote IP address
+    struct SockAddr iaddr;     // The receiving IP address
     struct Allowed *spec;      // Rule being instantiated
     struct timeval rec_when;   // Last received packet time, in seconds
 };
@@ -83,6 +85,7 @@ typedef struct _PacketItem {
     QueueItem base;
     int fd;
     struct SockAddr src;
+    struct SockAddr dst;
     ssize_t len;
     unsigned char buffer[ BUFSIZE ];
 } PacketItem;
@@ -1256,6 +1259,46 @@ void todolist_initialize(int nbuf,int nthr) {
     }
 }
 
+static ssize_t recvpacket(int fd,PacketItem *p) {
+    int flags = udp6? IPV6_PKTINFO : IP_PKTINFO;
+    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];
+    struct msghdr msg = {
+       .msg_name =  &p->src.in,
+       .msg_namelen = addrlen,
+       .msg_iov = &buffer,
+       .msg_iovlen = 1,
+       .msg_control = data,
+       .msg_controllen = sizeof( data ),
+       .msg_flags = flags // Return value
+    };
+    p->len = recvmsg( fd, &msg, flags );
+    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 ) {
+       } 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",
+                        pinf->ipi_ifindex, inet_stoa( &p->dst ) );
+       }
+    }
+    return p->len;
+}
+
+
+
 // Read a full UDP packet into the given buffer, associate with a
 // connection, or create a new connection, the decrypt the as
 // specified, and capture the sender MAC address. The connection table
@@ -1266,18 +1309,24 @@ static void *doreadUDP(void *data) {
     int fd = ((ReaderData *) data)->fd;
     while ( 1 ) {
        PacketItem *todo = (PacketItem *) Queue_getItem( &todolist.free );
+#if 0 
        socklen_t addrlen =
            udp6? sizeof( todo->src.in6 ) : sizeof( todo->src.in4 );
+#endif
        memset( &todo->src, 0, sizeof( todo->src ) );
        todo->fd = fd;
+#if 0
        todo->len = recvfrom(
            fd, todo->buffer, BUFSIZE, 0, &todo->src.in, &addrlen );
-       if ( todo->len == -1) {
+#endif
+       VERBOSE3OUT( "Reading packet\n" );
+       ssize_t len = recvpacket( fd, todo );
+       if ( len == -1) {
            perror( "Receiving UDP" );
            exit( 1 );
        }
 #ifdef GPROF
-       if ( todo->len == 17 &&
+       if ( len == 17 &&
             memcmp( todo->buffer, "STOPSTOPSTOPSTOP", 16 ) == 0 ) {
            exit( 0 );
        }
@@ -1612,6 +1661,11 @@ int main(int argc, char *argv[]) {
            exit(1);
        }
        VERBOSEOUT( "Using ipv4 UDP at %d\n", udp_fd );
+       int opt = 1;
+       if ( setsockopt( udp_fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) ) {
+           fprintf( stderr, "Error configuring socket!\n");
+            exit(1);
+       }
     } else {
        // set up ipv6 socket
        if ( ( udp_fd = socket( AF_INET6, SOCK_DGRAM, 0 ) ) == 0 ) {