(linenum→info "unix/slp.c:2238")

glibc/2.7/nis/nis_callback.c

    1: /* Copyright (C) 1997,1998,1999,2000,2005,2006 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3:    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <errno.h>
   21: #include <stdio.h>
   22: #include <stdlib.h>
   23: #include <unistd.h>
   24: #include <libintl.h>
   25: #include <rpc/rpc.h>
   26: #include <rpc/pmap_clnt.h>
   27: #include <string.h>
   28: #include <memory.h>
   29: #include <syslog.h>
   30: #include <sys/poll.h>
   31: #include <sys/socket.h>
   32: #include <netinet/in.h>
   33: #include <arpa/inet.h>
   34: #include <rpc/key_prot.h>
   35: #include <rpcsvc/nis.h>
   36: #include <rpcsvc/nis_callback.h>
   37: #include <bits/libc-lock.h>
   38: 
   39: #include "nis_xdr.h"
   40: #include "nis_intern.h"
   41: 
   42: /* Sorry, we are not able to make this threadsafe. Stupid. But some
   43:    functions doesn't send us a nis_result obj, so we don't have a
   44:    cookie. Maybe we could use keys for threads ? Have to learn more
   45:    about pthreads -- kukuk@vt.uni-paderborn.de */
   46: 
   47: static nis_cb *data;
   48: 
   49: __libc_lock_define_initialized (static, callback)
   50: 
   51: 
   52: #if 0
   53: static char *
   54: __nis_getpkey(const char *sname)
   55: {
   56:   char buf[(strlen (sname) + 1) * 2 + 40];
   57:   char pkey[HEXKEYBYTES + 1];
   58:   char *cp, *domain;
   59:   nis_result *res;
   60:   unsigned int len = 0;
   61: 
   62:   domain = strchr (sname, '.');
   63:   if (domain == NULL)
   64:     return NULL;
   65: 
   66:   /* Remove prefixing dot */
   67:   ++domain;
   68: 
   69:   cp = stpcpy (buf, "[cname=");
   70:   cp = stpcpy (cp, sname);
   71:   cp = stpcpy (cp, ",auth_type=DES],cred.org_dir.");
   72:   cp = stpcpy (cp, domain);
   73: 
   74:   res = nis_list (buf, USE_DGRAM|NO_AUTHINFO|FOLLOW_LINKS|FOLLOW_PATH,
   75:                   NULL, NULL);
   76: 
   77:   if (res == NULL)
   78:     return NULL;
   79: 
   80:   if (NIS_RES_STATUS (res) != NIS_SUCCESS)
   81:     {
   82:       nis_freeresult (res);
   83:       return NULL;
   84:     }
   85: 
   86:   len = ENTRY_LEN(NIS_RES_OBJECT(res), 3);
   87:   strncpy (pkey, ENTRY_VAL(NIS_RES_OBJECT(res), 3), len);
   88:   pkey[len] = '\0';
   89:   cp = strchr (pkey, ':');
   90:   if (cp != NULL)
   91:     *cp = '\0';
   92: 
   93:   nis_freeresult (res);
   94: 
   95:   return strdup (pkey);
   96: }
   97: #endif
   98: 
   99: static void
  100: cb_prog_1 (struct svc_req *rqstp, SVCXPRT *transp)
  101: {
  102:   union
  103:     {
  104:       cback_data cbproc_receive_1_arg;
  105:       nis_error cbproc_error_1_arg;
  106:     }
  107:   argument;
  108:   char *result;
  109:   xdrproc_t xdr_argument, xdr_result;
  110:   bool_t bool_result;
  111: 
  112:   switch (rqstp->rq_proc)
  113:     {
  114:     case NULLPROC:
  115:       svc_sendreply (transp, (xdrproc_t) xdr_void, (char *) NULL);
  116:       return;
  117: 
  118:     case CBPROC_RECEIVE:
  119:       {
  120:         unsigned int i;
  121: 
  122:         xdr_argument = (xdrproc_t) xdr_cback_data;
  123:         xdr_result = (xdrproc_t) xdr_bool;
  124:         memset (&argument, 0, sizeof (argument));
  125:         if (!svc_getargs (transp, xdr_argument, (caddr_t) & argument))
  126:           {
  127:             svcerr_decode (transp);
  128:             return;
  129:           }
  130:         bool_result = FALSE;
  131:         for (i = 0; i < argument.cbproc_receive_1_arg.entries.entries_len; ++i)
  132:           {
  133: #define cbproc_entry(a) argument.cbproc_receive_1_arg.entries.entries_val[a]
  134:             char name[strlen (cbproc_entry(i)->zo_name) +
  135:                       strlen (cbproc_entry(i)->zo_domain) + 3];
  136:             char *cp;
  137: 
  138:             cp = stpcpy (name, cbproc_entry(i)->zo_name);
  139:             *cp++ = '.';
  140:             cp = stpcpy (cp, cbproc_entry(i)->zo_domain);
  141: 
  142:             if ((data->callback) (name, cbproc_entry(i), data->userdata))
  143:               {
  144:                 bool_result = TRUE;
  145:                 data->nomore = 1;
  146:                 data->result = NIS_SUCCESS;
  147:                 break;
  148:               }
  149:           }
  150:         result = (char *) &bool_result;
  151:       }
  152:       break;
  153:     case CBPROC_FINISH:
  154:       xdr_argument = (xdrproc_t) xdr_void;
  155:       xdr_result = (xdrproc_t) xdr_void;
  156:       memset (&argument, 0, sizeof (argument));
  157:       if (!svc_getargs (transp, xdr_argument, (caddr_t) & argument))
  158:         {
  159:           svcerr_decode (transp);
  160:           return;
  161:         }
  162:       data->nomore = 1;
  163:       data->result = NIS_SUCCESS;
  164:       bool_result = TRUE;       /* to make gcc happy, not necessary */
  165:       result = (char *) &bool_result;
  166:       break;
  167:     case CBPROC_ERROR:
  168:       xdr_argument = (xdrproc_t) _xdr_nis_error;
  169:       xdr_result = (xdrproc_t) xdr_void;
  170:       memset (&argument, 0, sizeof (argument));
  171:       if (!svc_getargs (transp, xdr_argument, (caddr_t) & argument))
  172:         {
  173:           svcerr_decode (transp);
  174:           return;
  175:         }
  176:       data->nomore = 1;
  177:       data->result = argument.cbproc_error_1_arg;
  178:       bool_result = TRUE;       /* to make gcc happy, not necessary */
  179:       result = (char *) &bool_result;
  180:       break;
  181:     default:
  182:       svcerr_noproc (transp);
  183:       return;
  184:     }
  185:   if (result != NULL && !svc_sendreply (transp, xdr_result, result))
  186:     svcerr_systemerr (transp);
  187:   if (!svc_freeargs (transp, xdr_argument, (caddr_t) & argument))
  188:     {
  189:       fputs (_ ("unable to free arguments"), stderr);
  190:       exit (1);
  191:     }
  192:   return;
  193: }
  194: 
  195: static nis_error
  196: internal_nis_do_callback (struct dir_binding *bptr, netobj *cookie,
  197:                           struct nis_cb *cb)
  198: {
  199:   struct timeval TIMEOUT = {25, 0};
  200:   bool_t cb_is_running;
  201: 
  202:   data = cb;
  203: 
  204:   for (;;)
  205:     {
  206:       struct pollfd my_pollfd[svc_max_pollfd];
  207:       int i;
  208: 
  209:       if (svc_max_pollfd == 0 && svc_pollfd == NULL)
  210:         return NIS_CBERROR;
  211: 
  212:       for (i = 0; i < svc_max_pollfd; ++i)
  213:         {
  214:           my_pollfd[i].fd = svc_pollfd[i].fd;
  215:           my_pollfd[i].events = svc_pollfd[i].events;
  216:           my_pollfd[i].revents = 0;
  217:         }
  218: 
  219:       switch (i = TEMP_FAILURE_RETRY (__poll (my_pollfd, svc_max_pollfd,
  220:                                               25*1000)))
  221:         {
  222:         case -1:
  223:           return NIS_CBERROR;
  224:         case 0:
  225:           /* See if callback 'thread' in the server is still alive. */
  226:           cb_is_running = FALSE;
  227:           if (clnt_call (bptr->clnt, NIS_CALLBACK, (xdrproc_t) xdr_netobj,
  228:                          (caddr_t) cookie, (xdrproc_t) xdr_bool,
  229:                          (caddr_t) &cb_is_running, TIMEOUT) != RPC_SUCCESS)
  230:             cb_is_running = FALSE;
  231: 
  232:           if (cb_is_running == FALSE)
  233:             {
  234:               syslog (LOG_ERR, "NIS+: callback timed out");
  235:               return NIS_CBERROR;
  236:             }
  237:           break;
  238:         default:
  239:           svc_getreq_poll (my_pollfd, i);
  240:           if (data->nomore)
  241:             return data->result;
  242:         }
  243:     }
  244: }
  245: 
  246: nis_error
  247: __nis_do_callback (struct dir_binding *bptr, netobj *cookie,
  248:                    struct nis_cb *cb)
  249: {
  250:   nis_error result;
  251: 
  252:   __libc_lock_lock (callback);
  253: 
  254:   result = internal_nis_do_callback (bptr, cookie, cb);
  255: 
  256:   __libc_lock_unlock (callback);
  257: 
  258:   return result;
  259: }
  260: 
  261: struct nis_cb *
  262: __nis_create_callback (int (*callback) (const_nis_name, const nis_object *,
  263:                                         const void *),
  264:                        const void *userdata, unsigned int flags)
  265: {
  266:   struct nis_cb *cb;
  267:   int sock = RPC_ANYSOCK;
  268:   struct sockaddr_in sin;
  269:   socklen_t len = sizeof (struct sockaddr_in);
  270:   unsigned short port;
  271:   int nomsg = 0;
  272: 
  273:   cb = (struct nis_cb *) calloc (1,
  274:                                  sizeof (struct nis_cb) + sizeof (nis_server));
  275:   if (__builtin_expect (cb == NULL, 0))
  276:     goto failed;
  277:   cb->serv = (nis_server *) (cb + 1);
  278:   cb->serv->name = strdup (nis_local_principal ());
  279:   if (__builtin_expect (cb->serv->name == NULL, 0))
  280:     goto failed;
  281:   cb->serv->ep.ep_val = (endpoint *) calloc (2, sizeof (endpoint));
  282:   if (__builtin_expect (cb->serv->ep.ep_val == NULL, 0))
  283:     goto failed;
  284:   cb->serv->ep.ep_len = 1;
  285:   cb->serv->ep.ep_val[0].family = strdup ("inet");
  286:   if (__builtin_expect (cb->serv->ep.ep_val[0].family == NULL, 0))
  287:     goto failed;
  288:   cb->callback = callback;
  289:   cb->userdata = userdata;
  290: 
  291:   if ((flags & NO_AUTHINFO) || !key_secretkey_is_set ())
  292:     {
  293:       cb->serv->key_type = NIS_PK_NONE;
  294:       cb->serv->pkey.n_bytes = NULL;
  295:       cb->serv->pkey.n_len = 0;
  296:     }
  297:   else
  298:     {
  299: #if 0
  300:       if ((cb->serv->pkey.n_bytes = __nis_getpkey (cb->serv->name)) == NULL)
  301:         {
  302:           cb->serv->pkey.n_len = 0;
  303:           cb->serv->key_type = NIS_PK_NONE;
  304:         }
  305:       else
  306:         {
  307:           cb->serv->key_type = NIS_PK_DH;
  308:           cb->serv->pkey.n_len = strlen(cb->serv->pkey.n_bytes);
  309:         }
  310: #else
  311:       cb->serv->pkey.n_len =0;
  312:       cb->serv->pkey.n_bytes = NULL;
  313:       cb->serv->key_type = NIS_PK_NONE;
  314: #endif
  315:     }
  316: 
  317:   cb->serv->ep.ep_val[0].proto = strdup ((flags & USE_DGRAM) ? "udp" : "tcp");
  318:   if (__builtin_expect (cb->serv->ep.ep_val[0].proto == NULL, 0))
  319:     goto failed;
  320:   cb->xprt = ((flags & USE_DGRAM)
  321:               ? svcudp_bufcreate (sock, 100, 8192)
  322:               : svctcp_create (sock, 100, 8192));
  323:   if (cb->xprt == NULL)
  324:     {
  325:       nomsg = 1;
  326:       goto failed;
  327:     }
  328:   cb->sock = cb->xprt->xp_sock;
  329:   if (!svc_register (cb->xprt, CB_PROG, CB_VERS, cb_prog_1, 0))
  330:     {
  331:       xprt_unregister (cb->xprt);
  332:       svc_destroy (cb->xprt);
  333:       xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
  334:       free (cb);
  335:       syslog (LOG_ERR, "NIS+: failed to register callback dispatcher");
  336:       return NULL;
  337:     }
  338: 
  339:   if (getsockname (cb->sock, (struct sockaddr *) &sin, &len) == -1)
  340:     {
  341:       xprt_unregister (cb->xprt);
  342:       svc_destroy (cb->xprt);
  343:       xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
  344:       free (cb);
  345:       syslog (LOG_ERR, "NIS+: failed to read local socket info");
  346:       return NULL;
  347:     }
  348:   port = ntohs (sin.sin_port);
  349:   get_myaddress (&sin);
  350: 
  351:   if (asprintf (&cb->serv->ep.ep_val[0].uaddr, "%s.%d.%d",
  352:                 inet_ntoa (sin.sin_addr), (port & 0xFF00) >> 8, port & 0x00FF)
  353:       < 0)
  354:     goto failed;
  355: 
  356:   return cb;
  357: 
  358:  failed:
  359:   if (cb)
  360:     {
  361:       if (cb->xprt)
  362:         svc_destroy (cb->xprt);
  363:       xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
  364:       free (cb);
  365:     }
  366:   if (!nomsg)
  367:     syslog (LOG_ERR, "NIS+: out of memory allocating callback");
  368:   return NULL;
  369: }
  370: 
  371: nis_error
  372: __nis_destroy_callback (struct nis_cb *cb)
  373: {
  374:   xprt_unregister (cb->xprt);
  375:   svc_destroy (cb->xprt);
  376:   close (cb->sock);
  377:   xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
  378:   free (cb);
  379: 
  380:   return NIS_SUCCESS;
  381: }
Syntax (Markdown)