"Fossies" - the Fresh Open Source Software Archive

Member "monit-5.28.0/src/net/os/solaris/Link.inc" (28 Mar 2021, 8528 Bytes) of package /linux/privat/monit-5.28.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) fasm source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "Link.inc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.27.2_vs_5.28.0.

    1 /*
    2  * Copyright (C) Tildeslash Ltd. All rights reserved.
    3  *
    4  * This program is free software: you can redistribute it and/or modify
    5  * it under the terms of the GNU Affero General Public License version 3.
    6  *
    7  * This program is distributed in the hope that it will be useful,
    8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10  * GNU Affero General Public License for more details.
   11  *
   12  * You should have received a copy of the GNU Affero General Public License
   13  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   14  *
   15  * In addition, as a special exception, the copyright holders give
   16  * permission to link the code of portions of this program with the
   17  * OpenSSL library under certain conditions as described in each
   18  * individual source file, and distribute linked combinations
   19  * including the two.
   20  *
   21  * You must obey the GNU Affero General Public License in all respects
   22  * for all of the code used other than OpenSSL.
   23  */
   24 
   25 
   26 /**
   27  * Implementation of the Network Statistics for Solaris.
   28  *
   29  * @author http://www.tildeslash.com/
   30  * @see http://www.mmonit.com/
   31  * @file
   32  */
   33 
   34 
   35 #include <ctype.h>
   36 
   37 
   38 /* ------------------------------------------------------------- Definitions */
   39 
   40 
   41 static bool _isSolarisX = false;
   42 
   43 
   44 typedef struct Interface_T {
   45         int instance;
   46         char module[64];
   47 } *Interface_T;
   48 
   49 
   50 /* ----------------------------------------------------------------- Private */
   51 
   52 
   53 // Parse the interface name like e1000g1 into module:instance -> e1000g:1
   54 static bool _parseInterface(const char *name, Interface_T interface) {
   55         for (int len = strlen(name), i = len - 1; i >= 0; i--) {
   56                 if (! isdigit(*(name + i))) {
   57                         strncpy(interface->module, name, i + 1 < (int)sizeof(interface->module) ? i + 1 : (int)sizeof(interface->module) - 1);
   58                         interface->instance = Str_parseInt(name + i + 1);
   59                         return true;
   60                 }
   61         }
   62         return false;
   63 }
   64 
   65 
   66 static kstat_t *_getKstat(kstat_ctl_t *kc, char *name) {
   67         kstat_t *ksp;
   68         struct Interface_T interface = {};
   69         if (! _isSolarisX) {
   70                 if ((ksp = kstat_lookup(kc, "link", -1, name))) {
   71                         /*
   72                          * Solaris11:
   73                          *
   74                          * $ kstat -p -m link -n net0
   75                          * link:0:net0:ifspeed     1000000000
   76                          * link:0:net0:link_duplex 2
   77                          * link:0:net0:link_state  1
   78                          * ...
   79                          * link:0:net0:ierrors     0
   80                          * link:0:net0:ipackets    8748
   81                          * link:0:net0:ipackets64  8748
   82                          * link:0:net0:rbytes      1331127
   83                          * link:0:net0:rbytes64    1331127
   84                          * ...
   85                          * link:0:net0:oerrors     0
   86                          * link:0:net0:opackets    7560
   87                          * link:0:net0:opackets64  7560
   88                          * link:0:net0:obytes      3227785
   89                          * link:0:net0:obytes64    3227785
   90                          */
   91                         return ksp;
   92                 } else if (errno == ENOENT) {
   93                         /*
   94                          * Fallback to Solaris 10:
   95                          *
   96                          * $ kstat -p -m e1000g -n mac
   97                          * e1000g:0:mac:ifspeed    1000000000
   98                          * e1000g:0:mac:link_duplex        2
   99                          * e1000g:0:mac:link_state 1
  100                          * e1000g:0:mac:link_up    1
  101                          * ...
  102                          * e1000g:0:mac:ierrors    0
  103                          * e1000g:0:mac:ipackets   134096
  104                          * e1000g:0:mac:ipackets64 134096
  105                          * e1000g:0:mac:rbytes     150727335
  106                          * e1000g:0:mac:rbytes64   150727335
  107                          * ...
  108                          * e1000g:0:mac:oerrors    0
  109                          * e1000g:0:mac:opackets   81322
  110                          * e1000g:0:mac:opackets64 81322
  111                          * e1000g:0:mac:obytes     9214172
  112                          * e1000g:0:mac:obytes64   9214172
  113                          */
  114                         if (_parseInterface(name, &interface) && (ksp = kstat_lookup(kc, interface.module, interface.instance, "mac"))) {
  115                                 _isSolarisX = true;
  116                                 return ksp;
  117                         }
  118                 }
  119         } else {
  120                 if (_parseInterface(name, &interface) && (ksp = kstat_lookup(kc, interface.module, interface.instance, "mac")))
  121                         return ksp;
  122         }
  123         return NULL;
  124 }
  125 
  126 
  127 static long long _getKstatValue(kstat_t *ksp, char *value) {
  128         const kstat_named_t *kdata = kstat_data_lookup(ksp, value);
  129         if (kdata) {
  130                 switch (kdata->data_type) {
  131                         case KSTAT_DATA_INT32:
  132                                 return (long long)kdata->value.i32;
  133                         case KSTAT_DATA_UINT32:
  134                                 return (long long)kdata->value.ui32;
  135                         case KSTAT_DATA_INT64:
  136                                 return (long long)kdata->value.i64;
  137                         case KSTAT_DATA_UINT64:
  138                                 return (long long)kdata->value.ui64;
  139                 }
  140                 THROW(AssertException, "Unsupported kstat data type 0x%x", kdata->data_type);
  141         }
  142         THROW(AssertException, "Cannot read %s statistics -- %s", value, System_getError(errno));
  143         return -1LL;
  144 }
  145 
  146 
  147 static void _setStatistics(T L, kstat_t *ksp) {
  148         L->state = _getKstatValue(ksp, "link_state") ? 1LL : 0LL;
  149         L->speed = _getKstatValue(ksp, "ifspeed");
  150         L->duplex = _getKstatValue(ksp, "link_duplex") == 2 ? 1LL : 0LL;
  151         _updateValue(&(L->ibytes), _getKstatValue(ksp, "rbytes64"));
  152         _updateValue(&(L->ipackets), _getKstatValue(ksp, "ipackets64"));
  153         _updateValue(&(L->ierrors), _getKstatValue(ksp, "ierrors"));
  154         _updateValue(&(L->obytes), _getKstatValue(ksp, "obytes64"));
  155         _updateValue(&(L->opackets), _getKstatValue(ksp, "opackets64"));
  156         _updateValue(&(L->oerrors), _getKstatValue(ksp, "oerrors"));
  157         L->timestamp.last = L->timestamp.now;
  158         L->timestamp.now = Time_milli();
  159 }
  160 
  161 
  162 static bool _update(T L, const char *interface) {
  163         /*
  164          * Handle IP alias
  165          */
  166         char name[STRLEN];
  167         snprintf(name, sizeof(name), "%s", interface);
  168         Str_replaceChar(name, ':', 0);
  169         kstat_ctl_t *kc = kstat_open();
  170         if (kc) {
  171                 kstat_t *ksp;
  172                 if (Str_isEqual(name, "lo0")) {
  173                         /*
  174                          * Loopback interface has special module on Solaris and provides packets statistics only.
  175                          *
  176                          * $ kstat -p -m lo
  177                          * lo:0:lo0:ipackets       878
  178                          * lo:0:lo0:opackets       878
  179                          */
  180                         if ((ksp = kstat_lookup(kc, "lo", -1, (char *)name)) && kstat_read(kc, ksp, NULL) != -1) {
  181                                 _updateValue(&(L->ipackets), _getKstatValue(ksp, "ipackets"));
  182                                 _updateValue(&(L->opackets), _getKstatValue(ksp, "opackets"));
  183                                 L->timestamp.last = L->timestamp.now;
  184                                 L->timestamp.now = Time_milli();
  185                                 kstat_close(kc);
  186                                 return true;
  187                         } else {
  188                                 kstat_close(kc);
  189                                 THROW(AssertException, "Cannot get kstat data -- %s", System_getError(errno));
  190                         }
  191                 } else {
  192                         if ((ksp = _getKstat(kc, name)) && kstat_read(kc, ksp, NULL) != -1) {
  193                                 _setStatistics(L, ksp);
  194                                 kstat_close(kc);
  195                                 return true;
  196                         } else {
  197                                 kstat_close(kc);
  198                                 THROW(AssertException, "Cannot get kstat data -- %s", System_getError(errno));
  199                         }
  200                 }
  201         }
  202         return false;
  203 }
  204