Procházet zdrojové kódy

BSocket: add support for Ethernet packet sockets

ambrop7 před 15 roky
rodič
revize
409acf90e0
2 změnil soubory, kde provedl 97 přidání a 1 odebrání
  1. 56 1
      system/BAddr.h
  2. 41 0
      system/BSocket.c

+ 56 - 1
system/BAddr.h

@@ -50,12 +50,21 @@
 #define BADDR_TYPE_IPV6 2
 #ifndef BADVPN_USE_WINAPI
     #define BADDR_TYPE_UNIX 3 // only a domain number for BSocket
+    #define BADDR_TYPE_PACKET 4
 #endif
 
 #define BADDR_MAX_ADDR_LEN 128
 
 #define BIPADDR_MAX_PRINT_LEN 40
-#define BADDR_MAX_PRINT_LEN 46
+#define BADDR_MAX_PRINT_LEN 120
+
+#define BADDR_PACKET_HEADER_TYPE_ETHERNET 1
+
+#define BADDR_PACKET_PACKET_TYPE_HOST 1
+#define BADDR_PACKET_PACKET_TYPE_BROADCAST 2
+#define BADDR_PACKET_PACKET_TYPE_MULTICAST 3
+#define BADDR_PACKET_PACKET_TYPE_OTHERHOST 4
+#define BADDR_PACKET_PACKET_TYPE_OUTGOING 5
 
 typedef struct {
     int type;
@@ -101,6 +110,13 @@ typedef struct {
             uint8_t ip[16];
             uint16_t port;
         } ipv6;
+        struct {
+            uint16_t phys_proto;
+            int interface_index;
+            int header_type;
+            int packet_type;
+            uint8_t phys_addr[8];
+        } packet;
     };
 } BAddr;
 
@@ -127,6 +143,22 @@ static void BAddr_InitIPv4 (BAddr *addr, uint32_t ip, uint16_t port);
  */
 static void BAddr_InitIPv6 (BAddr *addr, uint8_t *ip, uint16_t port);
 
+/**
+ * Initializes a packet socket (data link layer) address.
+ * Only Ethernet addresses are supported.
+ * 
+ * @param addr the object
+ * @param phys_proto identifier for the upper protocol, network byte order (EtherType)
+ * @param interface_index network interface index
+ * @param header_type data link layer header type. Must be BADDR_PACKET_HEADER_TYPE_ETHERNET.
+ * @param packet_type the manner in which packets are sent/received. Must be one of
+ *   BADDR_PACKET_PACKET_TYPE_HOST, BADDR_PACKET_PACKET_TYPE_BROADCAST,
+ *   BADDR_PACKET_PACKET_TYPE_MULTICAST, BADDR_PACKET_PACKET_TYPE_OTHERHOST,
+ *   BADDR_PACKET_PACKET_TYPE_OUTGOING.
+ * @param phys_addr data link layer address (MAC address)
+ */
+static void BAddr_InitPacket (BAddr *addr, uint16_t phys_proto, int interface_index, int header_type, int packet_type, uint8_t *phys_addr);
+
 /**
  * Determines whether the address is recognized.
  *
@@ -437,12 +469,28 @@ void BAddr_InitIPv6 (BAddr *addr, uint8_t *ip, uint16_t port)
     addr->ipv6.port = port;
 }
 
+void BAddr_InitPacket (BAddr *addr, uint16_t phys_proto, int interface_index, int header_type, int packet_type, uint8_t *phys_addr)
+{
+    ASSERT(header_type == BADDR_PACKET_HEADER_TYPE_ETHERNET)
+    ASSERT(packet_type == BADDR_PACKET_PACKET_TYPE_HOST || packet_type == BADDR_PACKET_PACKET_TYPE_BROADCAST || 
+           packet_type == BADDR_PACKET_PACKET_TYPE_MULTICAST || packet_type == BADDR_PACKET_PACKET_TYPE_OTHERHOST ||
+           packet_type == BADDR_PACKET_PACKET_TYPE_OUTGOING)
+    
+    addr->type = BADDR_TYPE_PACKET;
+    addr->packet.phys_proto = phys_proto;
+    addr->packet.interface_index = interface_index;
+    addr->packet.header_type = header_type;
+    addr->packet.packet_type = packet_type;
+    memcpy(addr->packet.phys_addr, phys_addr, 6);
+}
+
 int BAddr_IsRecognized (BAddr *addr)
 {
     switch (addr->type) {
         case BADDR_TYPE_NONE:
         case BADDR_TYPE_IPV4:
         case BADDR_TYPE_IPV6:
+        case BADDR_TYPE_PACKET:
             return 1;
         default:
             return 0;
@@ -476,6 +524,13 @@ void BAddr_Print (BAddr *addr, char *out)
             BIPAddr_Print(&ipaddr, out);
             sprintf(out + strlen(out), ":%"PRIu16, ntoh16(addr->ipv6.port));
             break;
+        case BADDR_TYPE_PACKET:
+            ASSERT(addr->packet.header_type == BADDR_PACKET_HEADER_TYPE_ETHERNET)
+            sprintf(out, "proto=%"PRIu16",ifindex=%d,htype=eth,ptype=%d,addr=%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8,
+                    addr->packet.phys_proto, (int)addr->packet.interface_index, (int)addr->packet.packet_type,
+                    addr->packet.phys_addr[0], addr->packet.phys_addr[1], addr->packet.phys_addr[2],
+                    addr->packet.phys_addr[3], addr->packet.phys_addr[4], addr->packet.phys_addr[5]);
+            break;
         default:
             ASSERT(0);
     }

+ 41 - 0
system/BSocket.c

@@ -31,6 +31,9 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <sys/socket.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
 #endif
 
 #include <stdlib.h>
@@ -182,6 +185,9 @@ struct sys_addr {
         struct sockaddr generic;
         struct sockaddr_in ipv4;
         struct sockaddr_in6 ipv6;
+        #ifndef BADVPN_USE_WINAPI
+        struct sockaddr_ll packet;
+        #endif
     } addr;
 };
 
@@ -204,6 +210,38 @@ static void addr_socket_to_sys (struct sys_addr *out, BAddr *addr)
             memcpy(out->addr.ipv6.sin6_addr.s6_addr, addr->ipv6.ip, 16);
             out->addr.ipv6.sin6_scope_id = 0;
             break;
+        #ifndef BADVPN_USE_WINAPI
+        case BADDR_TYPE_PACKET:
+            ASSERT(addr->packet.header_type == BADDR_PACKET_HEADER_TYPE_ETHERNET)
+            memset(&out->addr.packet, 0, sizeof(out->addr.packet));
+            out->len = sizeof(out->addr.packet);
+            out->addr.packet.sll_family = AF_PACKET;
+            out->addr.packet.sll_protocol = addr->packet.phys_proto;
+            out->addr.packet.sll_ifindex = addr->packet.interface_index;
+            out->addr.packet.sll_hatype = 1; // linux/if_arp.h: #define ARPHRD_ETHER 1
+            switch (addr->packet.packet_type) {
+                case BADDR_PACKET_PACKET_TYPE_HOST:
+                    out->addr.packet.sll_pkttype = PACKET_HOST;
+                    break;
+                case BADDR_PACKET_PACKET_TYPE_BROADCAST:
+                    out->addr.packet.sll_pkttype = PACKET_BROADCAST;
+                    break;
+                case BADDR_PACKET_PACKET_TYPE_MULTICAST:
+                    out->addr.packet.sll_pkttype = PACKET_MULTICAST;
+                    break;
+                case BADDR_PACKET_PACKET_TYPE_OTHERHOST:
+                    out->addr.packet.sll_pkttype = PACKET_OTHERHOST;
+                    break;
+                case BADDR_PACKET_PACKET_TYPE_OUTGOING:
+                    out->addr.packet.sll_pkttype = PACKET_OUTGOING;
+                    break;
+                default:
+                    ASSERT(0);
+            }
+            out->addr.packet.sll_halen = 6;
+            memcpy(out->addr.packet.sll_addr, addr->packet.phys_addr, 6);
+            break;
+        #endif
         default:
             ASSERT(0)
             break;
@@ -561,6 +599,9 @@ int BSocket_Init (BSocket *bs, BReactor *bsys, int domain, int type)
         case BADDR_TYPE_UNIX:
             sys_domain = AF_UNIX;
             break;
+        case BADDR_TYPE_PACKET:
+            sys_domain = AF_PACKET;
+            break;
         #endif
         default:
             ASSERT(0)