Преглед на файлове

ncd: modules: add net.ipv4.arp_probe()

ambrop7 преди 14 години
родител
ревизия
49406f3f43

+ 1 - 0
blog_channels.txt

@@ -38,6 +38,7 @@ ncd_net_iptables 4
 ncd_net_ipv4_addr 4
 ncd_net_ipv4_route 4
 ncd_net_ipv4_dhcp 4
+ncd_net_ipv4_arp_probe 4
 ncd_net_watch_interfaces 4
 ncd_sys_watch_input 4
 ncd_sys_evdev 4

+ 4 - 0
generated/blog_channel_ncd_net_ipv4_arp_probe.h

@@ -0,0 +1,4 @@
+#ifdef BLOG_CURRENT_CHANNEL
+#undef BLOG_CURRENT_CHANNEL
+#endif
+#define BLOG_CURRENT_CHANNEL BLOG_CHANNEL_ncd_net_ipv4_arp_probe

+ 54 - 53
generated/blog_channels_defines.h

@@ -38,56 +38,57 @@
 #define BLOG_CHANNEL_ncd_net_ipv4_addr 37
 #define BLOG_CHANNEL_ncd_net_ipv4_route 38
 #define BLOG_CHANNEL_ncd_net_ipv4_dhcp 39
-#define BLOG_CHANNEL_ncd_net_watch_interfaces 40
-#define BLOG_CHANNEL_ncd_sys_watch_input 41
-#define BLOG_CHANNEL_ncd_sys_evdev 42
-#define BLOG_CHANNEL_ncd_sys_watch_directory 43
-#define BLOG_CHANNEL_StreamPeerIO 44
-#define BLOG_CHANNEL_DatagramPeerIO 45
-#define BLOG_CHANNEL_BReactor 46
-#define BLOG_CHANNEL_BSignal 47
-#define BLOG_CHANNEL_FragmentProtoAssembler 48
-#define BLOG_CHANNEL_BPredicate 49
-#define BLOG_CHANNEL_ServerConnection 50
-#define BLOG_CHANNEL_Listener 51
-#define BLOG_CHANNEL_DataProto 52
-#define BLOG_CHANNEL_FrameDecider 53
-#define BLOG_CHANNEL_BSocksClient 54
-#define BLOG_CHANNEL_BDHCPClientCore 55
-#define BLOG_CHANNEL_BDHCPClient 56
-#define BLOG_CHANNEL_NCDIfConfig 57
-#define BLOG_CHANNEL_BUnixSignal 58
-#define BLOG_CHANNEL_BProcess 59
-#define BLOG_CHANNEL_PRStreamSink 60
-#define BLOG_CHANNEL_PRStreamSource 61
-#define BLOG_CHANNEL_PacketProtoDecoder 62
-#define BLOG_CHANNEL_DPRelay 63
-#define BLOG_CHANNEL_BThreadWork 64
-#define BLOG_CHANNEL_DPReceive 65
-#define BLOG_CHANNEL_BInputProcess 66
-#define BLOG_CHANNEL_NCDUdevMonitorParser 67
-#define BLOG_CHANNEL_NCDUdevMonitor 68
-#define BLOG_CHANNEL_NCDUdevCache 69
-#define BLOG_CHANNEL_NCDUdevManager 70
-#define BLOG_CHANNEL_BTime 71
-#define BLOG_CHANNEL_BEncryption 72
-#define BLOG_CHANNEL_SPProtoDecoder 73
-#define BLOG_CHANNEL_LineBuffer 74
-#define BLOG_CHANNEL_BTap 75
-#define BLOG_CHANNEL_lwip 76
-#define BLOG_CHANNEL_NCDConfigParser 77
-#define BLOG_CHANNEL_nsskey 78
-#define BLOG_CHANNEL_addr 79
-#define BLOG_CHANNEL_PasswordListener 80
-#define BLOG_CHANNEL_NCDInterfaceMonitor 81
-#define BLOG_CHANNEL_NCDRfkillMonitor 82
-#define BLOG_CHANNEL_udpgw 83
-#define BLOG_CHANNEL_UdpGwClient 84
-#define BLOG_CHANNEL_SocksUdpGwClient 85
-#define BLOG_CHANNEL_BNetwork 86
-#define BLOG_CHANNEL_BConnection 87
-#define BLOG_CHANNEL_BSSLConnection 88
-#define BLOG_CHANNEL_BDatagram 89
-#define BLOG_CHANNEL_PeerChat 90
-#define BLOG_CHANNEL_BArpProbe 91
-#define BLOG_NUM_CHANNELS 92
+#define BLOG_CHANNEL_ncd_net_ipv4_arp_probe 40
+#define BLOG_CHANNEL_ncd_net_watch_interfaces 41
+#define BLOG_CHANNEL_ncd_sys_watch_input 42
+#define BLOG_CHANNEL_ncd_sys_evdev 43
+#define BLOG_CHANNEL_ncd_sys_watch_directory 44
+#define BLOG_CHANNEL_StreamPeerIO 45
+#define BLOG_CHANNEL_DatagramPeerIO 46
+#define BLOG_CHANNEL_BReactor 47
+#define BLOG_CHANNEL_BSignal 48
+#define BLOG_CHANNEL_FragmentProtoAssembler 49
+#define BLOG_CHANNEL_BPredicate 50
+#define BLOG_CHANNEL_ServerConnection 51
+#define BLOG_CHANNEL_Listener 52
+#define BLOG_CHANNEL_DataProto 53
+#define BLOG_CHANNEL_FrameDecider 54
+#define BLOG_CHANNEL_BSocksClient 55
+#define BLOG_CHANNEL_BDHCPClientCore 56
+#define BLOG_CHANNEL_BDHCPClient 57
+#define BLOG_CHANNEL_NCDIfConfig 58
+#define BLOG_CHANNEL_BUnixSignal 59
+#define BLOG_CHANNEL_BProcess 60
+#define BLOG_CHANNEL_PRStreamSink 61
+#define BLOG_CHANNEL_PRStreamSource 62
+#define BLOG_CHANNEL_PacketProtoDecoder 63
+#define BLOG_CHANNEL_DPRelay 64
+#define BLOG_CHANNEL_BThreadWork 65
+#define BLOG_CHANNEL_DPReceive 66
+#define BLOG_CHANNEL_BInputProcess 67
+#define BLOG_CHANNEL_NCDUdevMonitorParser 68
+#define BLOG_CHANNEL_NCDUdevMonitor 69
+#define BLOG_CHANNEL_NCDUdevCache 70
+#define BLOG_CHANNEL_NCDUdevManager 71
+#define BLOG_CHANNEL_BTime 72
+#define BLOG_CHANNEL_BEncryption 73
+#define BLOG_CHANNEL_SPProtoDecoder 74
+#define BLOG_CHANNEL_LineBuffer 75
+#define BLOG_CHANNEL_BTap 76
+#define BLOG_CHANNEL_lwip 77
+#define BLOG_CHANNEL_NCDConfigParser 78
+#define BLOG_CHANNEL_nsskey 79
+#define BLOG_CHANNEL_addr 80
+#define BLOG_CHANNEL_PasswordListener 81
+#define BLOG_CHANNEL_NCDInterfaceMonitor 82
+#define BLOG_CHANNEL_NCDRfkillMonitor 83
+#define BLOG_CHANNEL_udpgw 84
+#define BLOG_CHANNEL_UdpGwClient 85
+#define BLOG_CHANNEL_SocksUdpGwClient 86
+#define BLOG_CHANNEL_BNetwork 87
+#define BLOG_CHANNEL_BConnection 88
+#define BLOG_CHANNEL_BSSLConnection 89
+#define BLOG_CHANNEL_BDatagram 90
+#define BLOG_CHANNEL_PeerChat 91
+#define BLOG_CHANNEL_BArpProbe 92
+#define BLOG_NUM_CHANNELS 93

+ 1 - 0
generated/blog_channels_list.h

@@ -38,6 +38,7 @@
 {.name = "ncd_net_ipv4_addr", .loglevel = 4},
 {.name = "ncd_net_ipv4_route", .loglevel = 4},
 {.name = "ncd_net_ipv4_dhcp", .loglevel = 4},
+{.name = "ncd_net_ipv4_arp_probe", .loglevel = 4},
 {.name = "ncd_net_watch_interfaces", .loglevel = 4},
 {.name = "ncd_sys_watch_input", .loglevel = 4},
 {.name = "ncd_sys_evdev", .loglevel = 4},

+ 2 - 1
ncd/CMakeLists.txt

@@ -71,11 +71,12 @@ add_executable(badvpn-ncd
     modules/net_ipv4_addr.c
     modules/net_ipv4_route.c
     modules/net_ipv4_dhcp.c
+    modules/net_ipv4_arp_probe.c
     modules/net_watch_interfaces.c
     modules/sys_watch_input.c
     ${NCD_ADDITIONAL_SOURCES}
 )
-target_link_libraries(badvpn-ncd system flow flowextra dhcpclient ncdconfig udevmonitor)
+target_link_libraries(badvpn-ncd system flow flowextra dhcpclient arpprobe ncdconfig udevmonitor)
 
 if (BADVPN_USE_LINUX_INPUT)
     string(REPLACE " " ";" FLAGS_LIST "${CMAKE_C_FLAGS}")

+ 2 - 0
ncd/modules/modules.h

@@ -64,6 +64,7 @@ extern const struct NCDModuleGroup ncdmodule_net_iptables;
 extern const struct NCDModuleGroup ncdmodule_net_ipv4_addr;
 extern const struct NCDModuleGroup ncdmodule_net_ipv4_route;
 extern const struct NCDModuleGroup ncdmodule_net_ipv4_dhcp;
+extern const struct NCDModuleGroup ncdmodule_net_ipv4_arp_probe;
 extern const struct NCDModuleGroup ncdmodule_net_watch_interfaces;
 extern const struct NCDModuleGroup ncdmodule_sys_watch_input;
 #ifdef BADVPN_USE_LINUX_INPUT
@@ -111,6 +112,7 @@ static const struct NCDModuleGroup *ncd_modules[] = {
     &ncdmodule_net_ipv4_addr,
     &ncdmodule_net_ipv4_route,
     &ncdmodule_net_ipv4_dhcp,
+    &ncdmodule_net_ipv4_arp_probe,
     &ncdmodule_net_watch_interfaces,
     &ncdmodule_sys_watch_input,
 #ifdef BADVPN_USE_LINUX_INPUT

+ 217 - 0
ncd/modules/net_ipv4_arp_probe.c

@@ -0,0 +1,217 @@
+/**
+ * @file net_ipv4_arp_probe.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * @section DESCRIPTION
+ * 
+ * ARP probing module.
+ * 
+ * Synopsis:
+ *   net.ipv4.arp_probe(string ifname, string addr)
+ * 
+ * Description:
+ *   Monitors local presence of an IPv4 host on a network interface.
+ *   On initialization, may take some time to determine whether
+ *   the host is present or not, then goes to UP state. When it
+ *   determines that presence has changed, toggles itself DOWN then
+ *   UP to expose the new determination.
+ * 
+ * Variables:
+ *   exists - "true" if the host exists, "false" if not
+ */
+
+#include <stdlib.h>
+
+#include <misc/ipaddr.h>
+#include <arpprobe/BArpProbe.h>
+#include <ncd/NCDModule.h>
+
+#include <generated/blog_channel_ncd_net_ipv4_arp_probe.h>
+
+#define ModuleLog(i, ...) NCDModuleInst_Backend_Log((i), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
+
+#define STATE_UNKNOWN 1
+#define STATE_EXIST 2
+#define STATE_NOEXIST 3
+
+struct instance {
+    NCDModuleInst *i;
+    BArpProbe arpprobe;
+    int state;
+};
+
+static void instance_free (struct instance *o);
+
+static void arpprobe_handler (struct instance *o, int event)
+{
+    switch (event) {
+        case BARPPROBE_EVENT_EXIST: {
+            ASSERT(o->state == STATE_UNKNOWN || o->state == STATE_NOEXIST)
+            
+            ModuleLog(o->i, BLOG_INFO, "exist");
+            
+            if (o->state == STATE_NOEXIST) {
+                // signal down
+                NCDModuleInst_Backend_Down(o->i);
+            }
+            
+            // signal up
+            NCDModuleInst_Backend_Up(o->i);
+            
+            // set state exist
+            o->state = STATE_EXIST;
+        } break;
+        
+        case BARPPROBE_EVENT_NOEXIST: {
+            ASSERT(o->state == STATE_UNKNOWN || o->state == STATE_EXIST)
+            
+            ModuleLog(o->i, BLOG_INFO, "noexist");
+            
+            if (o->state == STATE_EXIST) {
+                // signal down
+                NCDModuleInst_Backend_Down(o->i);
+            }
+            
+            // signal up
+            NCDModuleInst_Backend_Up(o->i);
+            
+            // set state noexist
+            o->state = STATE_NOEXIST;
+        } break;
+        
+        case BARPPROBE_EVENT_ERROR: {
+            ModuleLog(o->i, BLOG_ERROR, "error");
+            
+            // set error
+            NCDModuleInst_Backend_SetError(o->i);
+            
+            // die
+            instance_free(o);
+            return;
+        } break;
+        
+        default: ASSERT(0);
+    }
+}
+
+static void func_new (NCDModuleInst *i)
+{
+    // allocate instance
+    struct instance *o = malloc(sizeof(*o));
+    if (!o) {
+        ModuleLog(i, BLOG_ERROR, "failed to allocate instance");
+        goto fail0;
+    }
+    NCDModuleInst_Backend_SetUser(i, o);
+    
+    // init arguments
+    o->i = i;
+    
+    // read arguments
+    NCDValue *arg_ifname;
+    NCDValue *arg_addr;
+    if (!NCDValue_ListRead(i->args, 2, &arg_ifname, &arg_addr)) {
+        ModuleLog(o->i, BLOG_ERROR, "wrong arity");
+        goto fail1;
+    }
+    if (NCDValue_Type(arg_ifname) != NCDVALUE_STRING || NCDValue_Type(arg_addr) != NCDVALUE_STRING) {
+        ModuleLog(o->i, BLOG_ERROR, "wrong type");
+        goto fail1;
+    }
+    char *ifname = NCDValue_StringValue(arg_ifname);
+    char *addr_str = NCDValue_StringValue(arg_addr);
+    
+    // parse address
+    uint32_t addr;
+    if (!ipaddr_parse_ipv4_addr(addr_str, &addr)) {
+        ModuleLog(o->i, BLOG_ERROR, "wrong address");
+        goto fail1;
+    }
+    
+    // init arpprobe
+    if (!BArpProbe_Init(&o->arpprobe, ifname, addr, i->reactor, o, (BArpProbe_handler)arpprobe_handler)) {
+        ModuleLog(o->i, BLOG_ERROR, "BArpProbe_Init failed");
+        goto fail1;
+    }
+    
+    // set state unknown
+    o->state = STATE_UNKNOWN;
+    return;
+    
+fail1:
+    free(o);
+fail0:
+    NCDModuleInst_Backend_SetError(i);
+    NCDModuleInst_Backend_Dead(i);
+}
+
+static void instance_free (struct instance *o)
+{
+    NCDModuleInst *i = o->i;
+    
+    // free arpprobe
+    BArpProbe_Free(&o->arpprobe);
+    
+    // free instance
+    free(o);
+    
+    NCDModuleInst_Backend_Dead(i);
+}
+
+static void func_die (void *vo)
+{
+    struct instance *o = vo;
+    
+    instance_free(o);
+}
+
+static int func_getvar (void *vo, const char *name, NCDValue *out)
+{
+    struct instance *o = vo;
+    ASSERT(o->state == STATE_EXIST || o->state == STATE_NOEXIST)
+    
+    if (!strcmp(name, "exists")) {
+        const char *str = (o->state == STATE_EXIST ? "true" : "false");
+        
+        if (!NCDValue_InitString(out, str)) {
+            ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitString failed");
+            return 0;
+        }
+        
+        return 1;
+    }
+    
+    return 0;
+}
+
+static const struct NCDModule modules[] = {
+    {
+        .type = "net.ipv4.arp_probe",
+        .func_new = func_new,
+        .func_die = func_die,
+        .func_getvar = func_getvar
+    }, {
+        .type = NULL
+    }
+};
+
+const struct NCDModuleGroup ncdmodule_net_ipv4_arp_probe = {
+    .modules = modules
+};