LCOV - code coverage report
Current view: top level - lib/util - server_id.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 94 109 86.2 %
Date: 2024-04-13 12:30:31 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Samba utility functions
       4             :    Copyright (C) Andrew Bartlett 2011
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "replace.h"
      21             : #include "lib/util/debug.h"
      22             : #include "lib/util/fault.h"
      23             : #include "lib/util/server_id.h"
      24             : #include "lib/util/byteorder.h"
      25             : #include "librpc/gen_ndr/server_id.h"
      26             : 
      27       99506 : bool server_id_same_process(const struct server_id *p1,
      28             :                             const struct server_id *p2)
      29             : {
      30       99506 :         return ((p1->pid == p2->pid) && (p1->vnn == p2->vnn));
      31             : }
      32             : 
      33     3011924 : int server_id_cmp(const struct server_id *p1, const struct server_id *p2)
      34             : {
      35     3011924 :         if (p1->vnn != p2->vnn) {
      36        1208 :                 return (p1->vnn < p2->vnn) ? -1 : 1;
      37             :         }
      38     3010716 :         if (p1->pid != p2->pid) {
      39     1434510 :                 return (p1->pid < p2->pid) ? -1 : 1;
      40             :         }
      41     1576206 :         if (p1->task_id != p2->task_id) {
      42           0 :                 return (p1->task_id < p2->task_id) ? -1 : 1;
      43             :         }
      44     1576206 :         if (p1->unique_id != p2->unique_id) {
      45           0 :                 return (p1->unique_id < p2->unique_id) ? -1 : 1;
      46             :         }
      47     1572955 :         return 0;
      48             : }
      49             : 
      50     2513958 : bool server_id_equal(const struct server_id *p1, const struct server_id *p2)
      51             : {
      52     2513958 :         int cmp = server_id_cmp(p1, p2);
      53     2513958 :         return (cmp == 0);
      54             : }
      55             : 
      56      257981 : char *server_id_str_buf(struct server_id id, struct server_id_buf *dst)
      57             : {
      58      257981 :         if (server_id_is_disconnected(&id)) {
      59           0 :                 strlcpy(dst->buf, "disconnected", sizeof(dst->buf));
      60      257981 :         } else if ((id.vnn == NONCLUSTER_VNN) && (id.task_id == 0)) {
      61       88046 :                 snprintf(dst->buf, sizeof(dst->buf), "%llu",
      62       83778 :                          (unsigned long long)id.pid);
      63      174203 :         } else if (id.vnn == NONCLUSTER_VNN) {
      64      178471 :                 snprintf(dst->buf, sizeof(dst->buf), "%llu.%u",
      65      174203 :                          (unsigned long long)id.pid, (unsigned)id.task_id);
      66           0 :         } else if (id.task_id == 0) {
      67        4268 :                 snprintf(dst->buf, sizeof(dst->buf), "%u:%llu",
      68           0 :                          (unsigned)id.vnn, (unsigned long long)id.pid);
      69             :         } else {
      70        4268 :                 snprintf(dst->buf, sizeof(dst->buf), "%u:%llu.%u",
      71           0 :                          (unsigned)id.vnn,
      72           0 :                          (unsigned long long)id.pid,
      73           0 :                          (unsigned)id.task_id);
      74             :         }
      75      257981 :         return dst->buf;
      76             : }
      77             : 
      78      128136 : size_t server_id_str_buf_unique(struct server_id id, char *buf, size_t buflen)
      79             : {
      80         920 :         struct server_id_buf idbuf;
      81         920 :         char unique_buf[21];    /* 2^64 is 18446744073709551616, 20 chars */
      82         920 :         size_t idlen, unique_len, needed;
      83             : 
      84      128136 :         server_id_str_buf(id, &idbuf);
      85             : 
      86      128136 :         idlen = strlen(idbuf.buf);
      87      128136 :         unique_len = snprintf(unique_buf, sizeof(unique_buf), "%"PRIu64,
      88             :                               id.unique_id);
      89      128136 :         needed = idlen + unique_len + 2;
      90             : 
      91      128136 :         if (buflen >= needed) {
      92       64068 :                 memcpy(buf, idbuf.buf, idlen);
      93       64068 :                 buf[idlen] = '/';
      94       64068 :                 memcpy(buf + idlen + 1, unique_buf, unique_len+1);
      95             :         }
      96             : 
      97      128136 :         return needed;
      98             : }
      99             : 
     100       58702 : struct server_id server_id_from_string(uint32_t local_vnn,
     101             :                                        const char *pid_string)
     102             : {
     103       58702 :         struct server_id templ = {
     104             :                 .vnn = NONCLUSTER_VNN, .pid = UINT64_MAX
     105             :         };
     106        1763 :         struct server_id result;
     107        1763 :         int ret;
     108             : 
     109             :         /*
     110             :          * We accept various forms with 1, 2 or 3 component forms
     111             :          * because the server_id_str_buf() can print different forms, and
     112             :          * we want backwards compatibility for scripts that may call
     113             :          * smbclient.
     114             :          */
     115             : 
     116       58702 :         result = templ;
     117       58702 :         ret = sscanf(pid_string, "%"SCNu32":%"SCNu64".%"SCNu32"/%"SCNu64,
     118             :                      &result.vnn, &result.pid, &result.task_id,
     119             :                      &result.unique_id);
     120       58702 :         if (ret == 4) {
     121           0 :                 return result;
     122             :         }
     123             : 
     124       58702 :         result = templ;
     125       58702 :         ret = sscanf(pid_string, "%"SCNu32":%"SCNu64".%"SCNu32,
     126             :                      &result.vnn, &result.pid, &result.task_id);
     127       58702 :         if (ret == 3) {
     128           0 :                 return result;
     129             :         }
     130             : 
     131       58702 :         result = templ;
     132       58702 :         ret = sscanf(pid_string, "%"SCNu32":%"SCNu64"/%"SCNu64,
     133             :                      &result.vnn, &result.pid, &result.unique_id);
     134       58702 :         if (ret == 3) {
     135           0 :                 return result;
     136             :         }
     137             : 
     138       58702 :         result = templ;
     139       58702 :         ret = sscanf(pid_string, "%"SCNu32":%"SCNu64,
     140             :                      &result.vnn, &result.pid);
     141       58702 :         if (ret == 2) {
     142           4 :                 return result;
     143             :         }
     144             : 
     145       58698 :         result = templ;
     146       58698 :         ret = sscanf(pid_string, "%"SCNu64".%"SCNu32"/%"SCNu64,
     147             :                      &result.pid, &result.task_id, &result.unique_id);
     148       58698 :         if (ret == 3) {
     149        4203 :                 result.vnn = local_vnn;
     150        4203 :                 return result;
     151             :         }
     152             : 
     153       54495 :         result = templ;
     154       54495 :         ret = sscanf(pid_string, "%"SCNu64".%"SCNu32,
     155             :                      &result.pid, &result.task_id);
     156       54495 :         if (ret == 2) {
     157           0 :                 result.vnn = local_vnn;
     158           0 :                 return result;
     159             :         }
     160             : 
     161       54495 :         result = templ;
     162       54495 :         ret = sscanf(pid_string, "%"SCNu64"/%"SCNu64,
     163             :                      &result.pid, &result.unique_id);
     164       54495 :         if (ret == 2) {
     165       54295 :                 result.vnn = local_vnn;
     166       54295 :                 return result;
     167             :         }
     168             : 
     169         200 :         result = templ;
     170         200 :         ret = sscanf(pid_string, "%"SCNu64, &result.pid);
     171         200 :         if (ret == 1) {
     172         154 :                 result.vnn = local_vnn;
     173         154 :                 return result;
     174             :         }
     175             : 
     176          46 :         if (strcmp(pid_string, "disconnected") == 0) {
     177           0 :                 server_id_set_disconnected(&result);
     178           0 :                 return result;
     179             :         }
     180             : 
     181          46 :         return templ;
     182             : }
     183             : 
     184             : /**
     185             :  * Set the serverid to the special value that represents a disconnected
     186             :  * client for (e.g.) durable handles.
     187             :  */
     188     1463364 : void server_id_set_disconnected(struct server_id *id)
     189             : {
     190     1463364 :         *id = (struct server_id) {
     191             :                 .pid = UINT64_MAX,
     192             :                 .task_id = UINT32_MAX,
     193             :                 .vnn = NONCLUSTER_VNN,
     194             :                 .unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY,
     195             :         };
     196     1463364 : }
     197             : 
     198             : /**
     199             :  * check whether a serverid is the special placeholder for
     200             :  * a disconnected client
     201             :  */
     202      869872 : bool server_id_is_disconnected(const struct server_id *id)
     203             : {
     204        6004 :         struct server_id dis;
     205             : 
     206      869872 :         SMB_ASSERT(id != NULL);
     207             : 
     208      869872 :         server_id_set_disconnected(&dis);
     209             : 
     210      869872 :         return server_id_equal(id, &dis);
     211             : }
     212             : 
     213     2224773 : void server_id_put(uint8_t buf[SERVER_ID_BUF_LENGTH],
     214             :                    const struct server_id id)
     215             : {
     216     2224773 :         SBVAL(buf, 0,  id.pid);
     217     2224773 :         SIVAL(buf, 8,  id.task_id);
     218     2224773 :         SIVAL(buf, 12, id.vnn);
     219     2224773 :         SBVAL(buf, 16, id.unique_id);
     220     2224773 : }
     221             : 
     222     2390400 : void server_id_get(struct server_id *id,
     223             :                    const uint8_t buf[SERVER_ID_BUF_LENGTH])
     224             : {
     225     2390400 :         id->pid       = BVAL(buf, 0);
     226     2390400 :         id->task_id   = IVAL(buf, 8);
     227     2390400 :         id->vnn       = IVAL(buf, 12);
     228     2390400 :         id->unique_id = BVAL(buf, 16);
     229     2390400 : }

Generated by: LCOV version 1.14