LCOV - code coverage report
Current view: top level - src/plugins/ipaddr - ipaddr.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 59 61 96.7 %
Date: 2019-09-12 12:28:41 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Source for ipaddr plugin
       5             :  *
       6             :  * @copyright BSD License (see doc/LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : #include <kdberrors.h>
      11             : #include <regex.h>
      12             : #include <stdio.h>
      13             : 
      14             : #include "ipaddr.h"
      15             : 
      16          36 : static int validateIPv4 (const char * addr)
      17             : {
      18          36 :         if (!addr) return 0;
      19             :         unsigned int a, b, c, d;
      20          36 :         a = b = c = d = 0;
      21          36 :         const char * regexString = "^([0-9]{1,3}\\.){3}([0-9]{1,3})$";
      22             :         regex_t regex;
      23             :         regmatch_t offsets;
      24          36 :         int ret = regcomp (&regex, regexString, REG_NOSUB | REG_EXTENDED | REG_NEWLINE);
      25          36 :         if (ret) return -1;
      26          36 :         ret = regexec (&regex, addr, 1, &offsets, 0);
      27          36 :         regfree (&regex);
      28          36 :         if (!ret)
      29             :         {
      30          18 :                 sscanf (addr, "%u.%u.%u.%u", &a, &b, &c, &d);
      31          18 :                 if (a > 255 || b > 255 || c > 255 || d > 255)
      32             :                 {
      33             :                         return 0;
      34             :                 }
      35             :                 else
      36          16 :                         return 1;
      37             :         }
      38             :         return 0;
      39             : }
      40             : 
      41          35 : static int validateIPv6 (const char * addr)
      42             : {
      43          35 :         if (!addr) return 0;
      44          35 :         const char * regexString =
      45             :                 "(^((:(([0-9A-Fa-f]{0,4}):){1,6}(([0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4})(:([0-9A-Fa-f]{0,4})){1,7}))$)|(^((:(([0-9A-Fa-f]{"
      46             :                 "0,4}):){1,4}(([0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4})(:([0-9A-Fa-f]{0,4})){1,5}))((([0-9]{1,3}\\.){3})([0-9]{1,3}))$)";
      47             :         regex_t regex;
      48             :         regmatch_t offsets;
      49          35 :         int ret = regcomp (&regex, regexString, REG_NOSUB | REG_EXTENDED | REG_NEWLINE);
      50          35 :         if (ret) return -1;
      51          35 :         ret = regexec (&regex, addr, 1, &offsets, 0);
      52          35 :         regfree (&regex);
      53          35 :         if (ret)
      54             :                 return 0;
      55             :         else
      56             :         {
      57             :                 char * ptr = (char *) addr;
      58             :                 int count = 0;
      59         330 :                 while (*ptr)
      60             :                 {
      61         313 :                         if (*ptr == ':') ++count;
      62         313 :                         ++ptr;
      63             :                 }
      64          17 :                 if (count > 7)
      65             :                 {
      66             :                         return 0;
      67             :                 }
      68          17 :                 else if (count < 7)
      69             :                 {
      70          13 :                         if (!strstr (addr, "::")) return 0;
      71             :                 }
      72          15 :                 if (strchr (addr, '.'))
      73             :                 {
      74           2 :                         char * ipv4ptr = strrchr (addr, ':');
      75           2 :                         ++ipv4ptr;
      76           2 :                         ret = validateIPv4 (ipv4ptr);
      77           2 :                         if (!ret) return 0;
      78             :                 }
      79             :                 return 1;
      80             :         }
      81             : }
      82             : 
      83          60 : static int validateKey (Key * key, Key * parentKey)
      84             : {
      85          60 :         const Key * meta = keyGetMeta (key, "check/ipaddr");
      86          60 :         if (!meta) return 1;
      87          60 :         int rc = 0;
      88             : 
      89          60 :         if (!strcasecmp (keyString (meta), "ipv4"))
      90             :         {
      91          20 :                 rc = validateIPv4 (keyString (key));
      92             :         }
      93          40 :         else if (!strcasecmp (keyString (meta), "ipv6"))
      94             :         {
      95          26 :                 rc = validateIPv6 (keyString (key));
      96             :         }
      97             :         else
      98             :         {
      99             :                 // By default we allow both type of addresses
     100          14 :                 if (!(rc = validateIPv4 (keyString (key)))) rc = validateIPv6 (keyString (key));
     101             :         }
     102             : 
     103          60 :         if (!rc)
     104             :         {
     105          31 :                 ELEKTRA_SET_VALIDATION_SEMANTIC_ERRORF (parentKey, "Validation of key %s with value %s failed", keyName (key),
     106             :                                                         keyString (key));
     107             :         }
     108          29 :         else if (rc == -1)
     109             :         {
     110           0 :                 ELEKTRA_SET_OUT_OF_MEMORY_ERROR (parentKey, "Out of memory");
     111           0 :                 rc = 0;
     112             :         }
     113             : 
     114             :         return rc;
     115             : }
     116             : 
     117          31 : int elektraIpaddrGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
     118             : {
     119          31 :         if (!elektraStrCmp (keyName (parentKey), "system/elektra/modules/ipaddr"))
     120             :         {
     121          31 :                 KeySet * contract =
     122          31 :                         ksNew (30, keyNew ("system/elektra/modules/ipaddr", KEY_VALUE, "ipaddr plugin waits for your orders", KEY_END),
     123             :                                keyNew ("system/elektra/modules/ipaddr/exports", KEY_END),
     124             :                                keyNew ("system/elektra/modules/ipaddr/exports/get", KEY_FUNC, elektraIpaddrGet, KEY_END),
     125             :                                keyNew ("system/elektra/modules/ipaddr/exports/set", KEY_FUNC, elektraIpaddrSet, KEY_END),
     126             : #include ELEKTRA_README
     127             :                                keyNew ("system/elektra/modules/ipaddr/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
     128          31 :                 ksAppend (returned, contract);
     129          31 :                 ksDel (contract);
     130          31 :                 return ELEKTRA_PLUGIN_STATUS_SUCCESS;
     131             :         }
     132             :         return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
     133             : }
     134             : 
     135          58 : int elektraIpaddrSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
     136             : {
     137             :         // set all keys
     138             :         // this function is optional
     139             :         Key * cur;
     140          58 :         ksRewind (returned);
     141         145 :         while ((cur = ksNext (returned)) != NULL)
     142             :         {
     143          60 :                 const Key * meta = keyGetMeta (cur, "check/ipaddr");
     144          60 :                 if (!meta) continue;
     145          60 :                 int rc = validateKey (cur, parentKey);
     146          60 :                 if (!rc) return ELEKTRA_PLUGIN_STATUS_ERROR;
     147             :         }
     148             :         return ELEKTRA_PLUGIN_STATUS_SUCCESS;
     149             : }
     150             : 
     151         127 : Plugin * ELEKTRA_PLUGIN_EXPORT
     152             : {
     153             :         // clang-format off
     154         127 :         return elektraPluginExport ("ipaddr",
     155             :                 ELEKTRA_PLUGIN_GET,     &elektraIpaddrGet,
     156             :                 ELEKTRA_PLUGIN_SET,     &elektraIpaddrSet,
     157             :                 ELEKTRA_PLUGIN_END);
     158             : }
     159             : 

Generated by: LCOV version 1.13