LCOV - code coverage report
Current view: top level - responder/common - responder_cmd.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 95 0.0 %
Date: 2012-11-29 Functions: 0 12 0.0 %
Branches: 0 96 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :    SSSD
       3                 :            : 
       4                 :            :    SSS Client Responder, command parser
       5                 :            : 
       6                 :            :    Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
       7                 :            : 
       8                 :            :    This program is free software; you can redistribute it and/or modify
       9                 :            :    it under the terms of the GNU General Public License as published by
      10                 :            :    the Free Software Foundation; either version 3 of the License, or
      11                 :            :    (at your option) any later version.
      12                 :            : 
      13                 :            :    This program is distributed in the hope that it will be useful,
      14                 :            :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16                 :            :    GNU General Public License for more details.
      17                 :            : 
      18                 :            :    You should have received a copy of the GNU General Public License
      19                 :            :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20                 :            : */
      21                 :            : #include <errno.h>
      22                 :            : #include "db/sysdb.h"
      23                 :            : #include "util/util.h"
      24                 :            : #include "responder/common/responder.h"
      25                 :            : #include "responder/common/responder_packet.h"
      26                 :            : 
      27                 :          0 : int sss_cmd_send_error(struct cli_ctx *cctx, int err)
      28                 :            : {
      29                 :            :     int ret;
      30                 :            : 
      31                 :            :     /* create response packet */
      32                 :          0 :     ret = sss_packet_new(cctx->creq, 0,
      33                 :            :                          sss_packet_get_cmd(cctx->creq->in),
      34                 :          0 :                          &cctx->creq->out);
      35         [ #  # ]:          0 :     if (ret != EOK) {
      36 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot create new packet: %d\n", ret));
         [ #  # ][ #  # ]
                 [ #  # ]
      37                 :          0 :         return ret;
      38                 :            :     }
      39                 :            : 
      40                 :          0 :     sss_packet_set_error(cctx->creq->out, err);
      41                 :          0 :     return EOK;
      42                 :            : }
      43                 :            : 
      44                 :          0 : int sss_cmd_empty_packet(struct sss_packet *packet)
      45                 :            : {
      46                 :            :     uint8_t *body;
      47                 :            :     size_t blen;
      48                 :            :     int ret;
      49                 :            : 
      50                 :          0 :     ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
      51         [ #  # ]:          0 :     if (ret != EOK) return ret;
      52                 :            : 
      53                 :          0 :     sss_packet_get_body(packet, &body, &blen);
      54                 :          0 :     ((uint32_t *)body)[0] = 0; /* num results */
      55                 :          0 :     ((uint32_t *)body)[1] = 0; /* reserved */
      56                 :            : 
      57                 :            :     return EOK;
      58                 :            : }
      59                 :            : 
      60                 :          0 : int sss_cmd_send_empty(struct cli_ctx *cctx, TALLOC_CTX *freectx)
      61                 :            : {
      62                 :            :     int ret;
      63                 :            : 
      64                 :            :     /* create response packet */
      65                 :          0 :     ret = sss_packet_new(cctx->creq, 0,
      66                 :            :                          sss_packet_get_cmd(cctx->creq->in),
      67                 :          0 :                          &cctx->creq->out);
      68         [ #  # ]:          0 :     if (ret != EOK) {
      69                 :            :         return ret;
      70                 :            :     }
      71                 :            : 
      72                 :          0 :     ret = sss_cmd_empty_packet(cctx->creq->out);
      73         [ #  # ]:          0 :     if (ret != EOK) {
      74                 :            :         return ret;
      75                 :            :     }
      76                 :            : 
      77                 :          0 :     sss_packet_set_error(cctx->creq->out, EOK);
      78                 :          0 :     sss_cmd_done(cctx, freectx);
      79                 :          0 :     return EOK;
      80                 :            : }
      81                 :            : 
      82                 :          0 : void sss_cmd_done(struct cli_ctx *cctx, void *freectx)
      83                 :            : {
      84                 :            :     /* now that the packet is in place, unlock queue
      85                 :            :      * making the event writable */
      86                 :          0 :     TEVENT_FD_WRITEABLE(cctx->cfde);
      87                 :            : 
      88                 :            :     /* free all request related data through the talloc hierarchy */
      89                 :          0 :     talloc_free(freectx);
      90                 :          0 : }
      91                 :            : 
      92                 :          0 : int sss_cmd_get_version(struct cli_ctx *cctx)
      93                 :            : {
      94                 :            :     uint8_t *req_body;
      95                 :            :     size_t req_blen;
      96                 :            :     uint8_t *body;
      97                 :            :     size_t blen;
      98                 :            :     int ret;
      99                 :            :     uint32_t client_version;
     100                 :            :     int i;
     101                 :            :     static struct cli_protocol_version *cli_protocol_version = NULL;
     102                 :            : 
     103                 :          0 :     cctx->cli_protocol_version = NULL;
     104                 :            : 
     105         [ #  # ]:          0 :     if (cli_protocol_version == NULL) {
     106                 :          0 :         cli_protocol_version = register_cli_protocol_version();
     107                 :            :     }
     108                 :            : 
     109         [ #  # ]:          0 :     if (cli_protocol_version != NULL) {
     110                 :          0 :         cctx->cli_protocol_version = &cli_protocol_version[0];
     111                 :            : 
     112                 :          0 :         sss_packet_get_body(cctx->creq->in, &req_body, &req_blen);
     113         [ #  # ]:          0 :         if (req_blen == sizeof(uint32_t)) {
     114                 :          0 :             memcpy(&client_version, req_body, sizeof(uint32_t));
     115 [ #  # ][ #  # ]:          0 :             DEBUG(5, ("Received client version [%d].\n", client_version));
         [ #  # ][ #  # ]
                 [ #  # ]
     116                 :            : 
     117                 :          0 :             i=0;
     118         [ #  # ]:          0 :             while(cli_protocol_version[i].version>0) {
     119         [ #  # ]:          0 :                 if (cli_protocol_version[i].version == client_version) {
     120                 :          0 :                     cctx->cli_protocol_version = &cli_protocol_version[i];
     121                 :          0 :                     break;
     122                 :            :                 }
     123                 :          0 :                 i++;
     124                 :            :             }
     125                 :            :         }
     126                 :            :     }
     127                 :            : 
     128                 :            :     /* create response packet */
     129                 :          0 :     ret = sss_packet_new(cctx->creq, sizeof(uint32_t),
     130                 :            :                          sss_packet_get_cmd(cctx->creq->in),
     131                 :          0 :                          &cctx->creq->out);
     132         [ #  # ]:          0 :     if (ret != EOK) {
     133                 :            :         return ret;
     134                 :            :     }
     135                 :          0 :     sss_packet_get_body(cctx->creq->out, &body, &blen);
     136                 :          0 :     ((uint32_t *)body)[0] = cctx->cli_protocol_version!=NULL ?
     137         [ #  # ]:          0 :                                 cctx->cli_protocol_version->version : 0;
     138 [ #  # ][ #  # ]:          0 :     DEBUG(5, ("Offered version [%d].\n", ((uint32_t *)body)[0]));
         [ #  # ][ #  # ]
                 [ #  # ]
     139                 :            : 
     140                 :          0 :     sss_cmd_done(cctx, NULL);
     141                 :            :     return EOK;
     142                 :            : }
     143                 :            : 
     144                 :          0 : int sss_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds)
     145                 :            : {
     146                 :            :     enum sss_cli_command cmd;
     147                 :            :     int i;
     148                 :            : 
     149                 :          0 :     cmd = sss_packet_get_cmd(cctx->creq->in);
     150                 :            : 
     151         [ #  # ]:          0 :     for (i = 0; sss_cmds[i].cmd != SSS_CLI_NULL; i++) {
     152         [ #  # ]:          0 :         if (cmd == sss_cmds[i].cmd) {
     153                 :          0 :             return sss_cmds[i].fn(cctx);
     154                 :            :         }
     155                 :            :     }
     156                 :            : 
     157                 :            :     return EINVAL;
     158                 :            : }
     159                 :            : 
     160                 :            : struct setent_req_list {
     161                 :            :     struct setent_req_list *prev;
     162                 :            :     struct setent_req_list *next;
     163                 :            :     /* Need to modify the list from a talloc destructor */
     164                 :            :     struct setent_req_list **head;
     165                 :            : 
     166                 :            :     void *pvt;
     167                 :            : 
     168                 :            :     struct tevent_req *req;
     169                 :            : };
     170                 :            : 
     171                 :            : struct tevent_req *
     172                 :          0 : setent_get_req(struct setent_req_list *sl)
     173                 :            : {
     174                 :          0 :     return sl->req;
     175                 :            : }
     176                 :            : 
     177                 :          0 : int setent_remove_ref(TALLOC_CTX *ctx)
     178                 :            : {
     179                 :          0 :     struct setent_req_list *entry =
     180                 :            :             talloc_get_type(ctx, struct setent_req_list);
     181 [ #  # ][ #  # ]:          0 :     DLIST_REMOVE(*(entry->head), entry);
         [ #  # ][ #  # ]
                 [ #  # ]
     182                 :          0 :     return 0;
     183                 :            : }
     184                 :            : 
     185                 :          0 : errno_t setent_add_ref(TALLOC_CTX *memctx,
     186                 :            :                        void *pvt,
     187                 :            :                        struct setent_req_list **list,
     188                 :            :                        struct tevent_req *req)
     189                 :            : {
     190                 :            :     struct setent_req_list *entry;
     191                 :            : 
     192                 :          0 :     entry = talloc_zero(memctx, struct setent_req_list);
     193         [ #  # ]:          0 :     if (!entry) {
     194                 :            :         return ENOMEM;
     195                 :            :     }
     196                 :            : 
     197                 :          0 :     entry->req = req;
     198                 :          0 :     entry->pvt = pvt;
     199 [ #  # ][ #  # ]:          0 :     DLIST_ADD_END(*list, entry, struct setent_req_list *);
     200                 :          0 :     entry->head = list;
     201                 :            : 
     202                 :          0 :     talloc_set_destructor((TALLOC_CTX *)entry, setent_remove_ref);
     203                 :          0 :     return EOK;
     204                 :            : }
     205                 :            : 
     206                 :          0 : void setent_notify(struct setent_req_list **list, errno_t err)
     207                 :            : {
     208                 :            :     struct setent_req_list *reql;
     209                 :            : 
     210                 :            :     /* Notify the waiting clients */
     211         [ #  # ]:          0 :     while ((reql = *list) != NULL) {
     212                 :            :         /* Each tevent_req_done() call will free
     213                 :            :          * the request, removing it from the list.
     214                 :            :          */
     215         [ #  # ]:          0 :         if (err == EOK) {
     216                 :          0 :             tevent_req_done(reql->req);
     217                 :            :         } else {
     218                 :          0 :             tevent_req_error(reql->req, err);
     219                 :            :         }
     220                 :            : 
     221         [ #  # ]:          0 :         if (reql == *list) {
     222                 :            :             /* The consumer failed to free the
     223                 :            :              * request. Log a bug and continue.
     224                 :            :              */
     225 [ #  # ][ #  # ]:          0 :             DEBUG(SSSDBG_FATAL_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
     226                 :            :                   ("BUG: a callback did not free its request. "
     227                 :            :                    "May leak memory\n"));
     228                 :            :             /* Skip to the next since a memory leak is non-fatal */
     229                 :          0 :             *list = (*list)->next;
     230                 :            :         }
     231                 :            :     }
     232                 :          0 : }
     233                 :            : 
     234                 :          0 : void setent_notify_done(struct setent_req_list **list)
     235                 :            : {
     236                 :          0 :     return setent_notify(list, EOK);
     237                 :            : }
     238                 :            : 
     239                 :            : /*
     240                 :            :  * Return values:
     241                 :            :  *  EOK     -   cache hit
     242                 :            :  *  EAGAIN  -   cache hit, but schedule off band update
     243                 :            :  *  ENOENT  -   cache miss
     244                 :            :  */
     245                 :            : errno_t
     246                 :          0 : sss_cmd_check_cache(struct ldb_message *msg,
     247                 :            :                     int cache_refresh_percent,
     248                 :            :                     uint64_t cache_expire)
     249                 :            : {
     250                 :            :     uint64_t lastUpdate;
     251                 :          0 :     uint64_t midpoint_refresh = 0;
     252                 :            :     time_t now;
     253                 :            : 
     254                 :          0 :     now = time(NULL);
     255                 :          0 :     lastUpdate = ldb_msg_find_attr_as_uint64(msg, SYSDB_LAST_UPDATE, 0);
     256                 :          0 :     midpoint_refresh = 0;
     257                 :            : 
     258         [ #  # ]:          0 :     if(cache_refresh_percent) {
     259                 :          0 :         midpoint_refresh = lastUpdate +
     260                 :          0 :             (cache_expire - lastUpdate)*cache_refresh_percent/100;
     261         [ #  # ]:          0 :         if (midpoint_refresh - lastUpdate < 10) {
     262                 :            :             /* If the percentage results in an expiration
     263                 :            :              * less than ten seconds after the lastUpdate time,
     264                 :            :              * that's too often we will simply set it to 10s
     265                 :            :              */
     266                 :          0 :             midpoint_refresh = lastUpdate+10;
     267                 :            :         }
     268                 :            :     }
     269                 :            : 
     270         [ #  # ]:          0 :     if (cache_expire > now) {
     271                 :            :         /* cache still valid */
     272                 :            : 
     273         [ #  # ]:          0 :         if (midpoint_refresh && midpoint_refresh < now) {
     274                 :            :             /* We're past the cache refresh timeout
     275                 :            :              * We'll return the value from the cache, but we'll also
     276                 :            :              * queue the cache entry for update out-of-band.
     277                 :            :              */
     278                 :            :             return EAGAIN;
     279                 :            :         } else {
     280                 :            :             /* Cache is still valid. */
     281                 :          0 :             return EOK;
     282                 :            :         }
     283                 :            :     }
     284                 :            : 
     285                 :            :     /* Cache needs to be updated */
     286                 :            :     return ENOENT;
     287                 :            : }

Generated by: LCOV version 1.9