yp_match.c revision 7de476d1ec002e6947b1506107cebe636d35e417
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley
* under license from the Regents of the University of
* California.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <unistd.h>
#include "mt.h"
#include "yp_b.h"
#include <malloc.h>
#include <string.h>
extern int __yp_dobind_cflookup(char *, struct dom_binding **, int);
extern int __yp_dobind_rsvdport_cflookup(char *, struct dom_binding **, int);
static int domatch(char *, char *, char *, int, struct dom_binding *,
struct timeval *, char **, int *);
int yp_match_rsvdport();
int yp_match_rsvdport_cflookup();
struct cache {
unsigned int birth;
char *domain;
char *map;
char *key;
int keylen;
char *val;
int vallen;
};
static int generation; /* Incremented when we add to cache */
#define CACHESZ 16
#define CACHETO 600
static void
{
if (n->val != 0)
if (n->key != 0)
if (n->map != 0)
if (n->domain != 0)
free(n);
}
/*
* Attempt to Add item to cache
*/
static struct cache *
{
struct cache *n;
/* Do not cache 'passwd' values i.e. passwd.byname or passwd.byuid. */
return (0);
if ((n = calloc(1, sizeof (*n))) == 0)
return (0);
freenode(n);
return (0);
}
return (n);
}
/*
* Look for a matching result in the per-process cache.
* Upon finding a match set the passed in 'val' and 'vallen'
* parameters and return 1. Otherwise return 0.
*/
static int
int *vallen)
{
int cnt;
/* The 'passwd' data is not cached. */
return (0);
/*
* Assumes that caller (yp_match) has locked the cache
*/
/* cache hit */
/* rats. it is too old to use */
freenode(c);
break;
} else {
/* Ersatz LRU: Move this entry to the front */
head = c;
return (1);
}
}
freenode(c);
break;
}
}
return (0);
}
/*
* Requests the yp server associated with a given domain to attempt to match
* the passed key datum in the named map, and to return the associated value
* datum. This part does parameter checking, and implements the "infinite"
* (until success) sleep loop if 'hardlookup' parameter is set.
*/
int
int *vallen, int hardlookup)
{
int reason;
struct dom_binding *pdomb;
int savesize;
char *my_val;
int my_vallen;
int found_it;
int cachegen;
return (YPERR_BADARGS);
return (YPERR_BADARGS);
(void) mutex_lock(&cache_lock);
if (found_it) {
/* NB: Copy two extra bytes; see below */
(void) mutex_unlock(&cache_lock);
return (YPERR_RESRC);
}
(void) mutex_unlock(&cache_lock);
return (0); /* Success */
}
(void) mutex_unlock(&cache_lock);
for (;;) {
return (reason);
if (hardlookup)
else
return (reason);
} else
break;
} else {
return (YPERR_VERS);
}
}
/* add to our cache */
if (reason == 0) {
(void) mutex_lock(&cache_lock);
/*
* Check whether some other annoying thread did the same
* thing in parallel with us. I hate it when that happens...
*/
if (generation != cachegen &&
/*
* Could get cute and update the birth time, but it's
* not worth the bother.
* It looks strange that we return one val[] array
* to the caller and have a different copy of the
* val[] array in the cache (presumably with the
* same contents), but it should work just fine.
* So, do absolutely nothing...
*/
/* EMPTY */
} else {
struct cache *c;
/*
* NB: allocate and copy extract two bytes of the
* value; these are mandatory CR and NULL bytes.
*/
if (c != 0) {
head = c;
++generation;
}
}
(void) mutex_unlock(&cache_lock);
/*
* Lookup could be for a secure map; fail over to retry
* from a reserved port. Only useful to try this if we're
* the super user.
*/
int rsvdreason;
vallen);
if (rsvdreason == 0)
reason = rsvdreason;
}
return (reason);
}
int
char *domain,
char *map,
char *key,
int keylen,
char **val, /* returns value array */
int *vallen) /* returns bytes in val */
{
/* the traditional yp_match loops forever thus hardlookup is set */
}
extern void
__empty_yp_cache(void)
{
struct cache *p, *n;
/* Copy the cache pointer and make it ZERO */
(void) mutex_lock(&cache_lock);
p = head;
head = 0;
(void) mutex_unlock(&cache_lock);
if (p == 0)
return;
/* Empty the cache */
n = p->next;
while (p) {
freenode(p);
p = n;
if (p)
n = p->next;
}
}
/*
* Requests the yp server associated with a given domain to attempt to match
* the passed key datum in the named map, and to return the associated value
* datum. This part does parameter checking, and implements the "infinite"
* (until success) sleep loop.
*
* XXX special version for handling C2 (passwd.adjunct) lookups when we need
* a reserved port.
* Only difference against yp_match is that this function uses
* __yp_dobind_rsvdport().
*
* Only called from NIS switch backend.
*/
int
char *domain,
char *map,
char *key,
int keylen,
char **val, /* returns value array */
int *vallen, /* returns bytes in val */
int hardlookup) /* retry until we can an answer */
{
int reason;
struct dom_binding *pdomb;
int savesize;
char *my_val;
int my_vallen;
int found_it;
int cachegen;
return (YPERR_BADARGS);
return (YPERR_BADARGS);
(void) mutex_lock(&cache_lock);
if (found_it) {
/* NB: Copy two extra bytes; see below */
(void) mutex_unlock(&cache_lock);
return (YPERR_RESRC);
}
(void) mutex_unlock(&cache_lock);
return (0); /* Success */
}
(void) mutex_unlock(&cache_lock);
for (;;) {
return (reason);
/*
* Have to free the binding since the reserved
* port bindings are not cached.
*/
if (hardlookup)
else
return (reason);
} else
break;
} else {
/*
* Have to free the binding since the reserved
* port bindings are not cached.
*/
return (YPERR_VERS);
}
}
/* add to our cache */
if (reason == 0) {
(void) mutex_lock(&cache_lock);
/*
* Check whether some other annoying thread did the same
* thing in parallel with us. I hate it when that happens...
*/
if (generation != cachegen &&
/*
* Could get cute and update the birth time, but it's
* not worth the bother.
* It looks strange that we return one val[] array
* to the caller and have a different copy of the
* val[] array in the cache (presumably with the
* same contents), but it should work just fine.
* So, do absolutely nothing...
*/
/* EMPTY */
} else {
struct cache *c;
/*
* NB: allocate and copy extract two bytes of the
* value; these are mandatory CR and NULL bytes.
*/
if (c != 0) {
head = c;
++generation;
}
}
(void) mutex_unlock(&cache_lock);
}
return (reason);
}
int
char *domain,
char *map,
char *key,
int keylen,
char **val, /* returns value array */
int *vallen) /* returns bytes in val */
{
/* traditional yp_match retries forever so set hardlookup */
vallen, 1));
}
/*
* This talks v3 protocol to ypserv
*/
static int
int *vallen)
{
struct ypresp_val resp;
unsigned int retval = 0;
/*
* Do the match request. If the rpc call failed, return with status
* from this point.
*/
*timeoutp)) {
case RPC_SUCCESS:
break;
case RPC_TIMEDOUT:
return (YPERR_YPSERV);
default:
return (YPERR_RPC);
}
/* See if the request succeeded */
}
/* Get some memory which the user can get rid of as he likes */
}
/* Copy the returned value byte string into the new memory */
if (!retval) {
}
return (retval);
}