#include <netdb.h>
#include <mach/mach.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "lu_utils.h"
#include "lu_overrides.h"
struct li_netgrent
{
char *ng_host;
char *ng_user;
char *ng_domain;
};
#define ENTRY_SIZE sizeof(struct li_netgrent)
#define ENTRY_KEY _li_data_key_netgroup
static struct li_netgrent *
copy_netgroup(struct li_netgrent *in)
{
if (in == NULL) return NULL;
return (struct li_netgrent *)LI_ils_create("sss", in->ng_host, in->ng_user, in->ng_domain);
}
static struct li_netgrent *
extract_netgroup(kvarray_t *in)
{
struct li_netgrent tmp;
uint32_t d, k, kcount;
if (in == NULL) return NULL;
d = in->curr;
in->curr++;
if (d >= in->count) return NULL;
memset(&tmp, 0, ENTRY_SIZE);
kcount = in->dict[d].kcount;
for (k = 0; k < kcount; k++)
{
if (!strcmp(in->dict[d].key[k], "user"))
{
if (tmp.ng_user != NULL) continue;
if (in->dict[d].vcount[k] == 0) continue;
tmp.ng_user = (char *)in->dict[d].val[k][0];
}
else if (!strcmp(in->dict[d].key[k], "host"))
{
if (tmp.ng_host != NULL) continue;
if (in->dict[d].vcount[k] == 0) continue;
tmp.ng_host = (char *)in->dict[d].val[k][0];
}
else if (!strcmp(in->dict[d].key[k], "domain"))
{
if (tmp.ng_domain != NULL) continue;
if (in->dict[d].vcount[k] == 0) continue;
tmp.ng_domain = (char *)in->dict[d].val[k][0];
}
}
if (tmp.ng_user == NULL) tmp.ng_user = "";
if (tmp.ng_host == NULL) tmp.ng_host = "";
if (tmp.ng_domain == NULL) tmp.ng_domain = "";
return copy_netgroup(&tmp);
}
static int
check_innetgr(kvarray_t *in)
{
uint32_t d, k, kcount;
if (in == NULL) return 0;
d = in->curr;
if (d >= in->count) return 0;
kcount = in->dict[d].kcount;
for (k = 0; k < kcount; k++)
{
if (!strcmp(in->dict[d].key[k], "result"))
{
if (in->dict[d].vcount[k] == 0) continue;
return atoi(in->dict[d].val[k][0]);
}
}
return 0;
}
static int
ds_innetgr(const char *group, const char *host, const char *user, const char *domain)
{
int is_innetgr;
kvbuf_t *request;
kvarray_t *reply;
kern_return_t status;
static int proc = -1;
if (proc < 0)
{
status = LI_DSLookupGetProcedureNumber("innetgr", &proc);
if (status != KERN_SUCCESS) return 0;
}
if (group == NULL) group = "";
if (host == NULL) host = "";
if (user == NULL) user = "";
if (domain == NULL) domain = "";
request = kvbuf_query("ksksksks", "netgroup", group, "host", host, "user", user, "domain", domain);
if (request == NULL) return 0;
reply = NULL;
status = LI_DSLookupQuery(proc, request, &reply);
kvbuf_free(request);
if (status != KERN_SUCCESS) return 0;
is_innetgr = check_innetgr(reply);
kvarray_free(reply);
return is_innetgr;
}
static void
ds_endnetgrent(void)
{
LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY));
}
static void
ds_setnetgrent(const char *name)
{
struct li_thread_info *tdata;
kvbuf_t *request;
kvarray_t *reply;
kern_return_t status;
static int proc = -1;
tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE);
if (tdata == NULL) return;
if (tdata->li_vm != NULL) return;
if (proc < 0)
{
status = LI_DSLookupGetProcedureNumber("getnetgrent", &proc);
if (status != KERN_SUCCESS)
{
LI_data_free_kvarray(tdata);
return;
}
}
request = kvbuf_query_key_val("netgroup", name);
if (request == NULL) return;
reply = NULL;
status = LI_DSLookupQuery(proc, request, &reply);
kvbuf_free(request);
if (status != KERN_SUCCESS)
{
LI_data_free_kvarray(tdata);
return;
}
tdata->li_vm = (char *)reply;
}
static struct li_netgrent *
ds_getnetgrent(void)
{
struct li_netgrent *entry;
struct li_thread_info *tdata;
tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE);
if (tdata == NULL) return NULL;
entry = extract_netgroup((kvarray_t *)(tdata->li_vm));
if (entry == NULL)
{
ds_endnetgrent();
return NULL;
}
return entry;
}
int
innetgr(const char *group, const char *host, const char *user,
const char *domain)
{
if (_ds_running()) return (ds_innetgr(group, host, user, domain));
return 0;
}
int
getnetgrent(char **host, char **user, char **domain)
{
struct li_netgrent *res = NULL;
struct li_thread_info *tdata;
tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE);
if (tdata == NULL) return 0;
res = NULL;
if (_ds_running()) res = ds_getnetgrent();
LI_data_recycle(tdata, res, ENTRY_SIZE);
if (res == NULL) return 0;
if (host != NULL) *host = res->ng_host;
if (user != NULL) *user = res->ng_user;
if (domain != NULL) *domain = res->ng_domain;
return 1;
}
void
setnetgrent(const char *name)
{
if (_ds_running()) ds_setnetgrent(name);
}
void
endnetgrent(void)
{
if (_ds_running()) ds_endnetgrent();
}