#include <freeradius-devel/ident.h>
RCSID("$Id: smux.c,v 1.26 2007/12/02 16:37:16 aland Exp $")
#include <freeradius-devel/radiusd.h>
#ifdef WITH_SNMP
#include <freeradius-devel/radius_snmp.h>
#include <freeradius-devel/smux.h>
#include <sys/file.h>
#include <fcntl.h>
#include <ctype.h>
#define min(A,B) ((A) < (B) ? (A) : (B))
static int oid_compare (oid *, size_t, oid *, size_t);
static struct list *treelist = NULL;
static oid *smux_oid;
static size_t smux_oid_len;
static void *
oid_copy (void *dest, void *src, size_t size)
{
return memcpy (dest, src, size * sizeof (oid));
}
#if 0
static void
oid2in_addr (oid my_oid[], int len, struct in_addr *addr)
{
int i;
u_char *pnt;
if (len == 0)
return;
pnt = (u_char *) addr;
for (i = 0; i < len; i++)
*pnt++ = my_oid[i];
}
static void
oid_copy_addr (oid my_oid[], struct in_addr *addr, int len)
{
int i;
u_char *pnt;
if (len == 0)
return;
pnt = (u_char *) addr;
for (i = 0; i < len; i++)
my_oid[i] = *pnt++;
}
#endif
static int
oid_compare (oid *o1, size_t o1_len, oid *o2, size_t o2_len)
{
size_t i;
for (i = 0; i < min (o1_len, o2_len); i++) {
if (o1[i] < o2[i])
return -1;
else if (o1[i] > o2[i])
return 1;
}
if (o1_len < o2_len)
return -1;
if (o1_len > o2_len)
return 1;
return 0;
}
static int
oid_compare_part (oid *o1, size_t o1_len, oid *o2, size_t o2_len)
{
size_t i;
for (i = 0; i < min (o1_len, o2_len); i++) {
if (o1[i] < o2[i])
return -1;
else if (o1[i] > o2[i])
return 1;
}
if (o1_len < o2_len)
return -1;
return 0;
}
static void
smux_oid_dump(const char *prefix, oid *my_oid, size_t oid_len)
{
size_t i;
int first = 1;
char buf[MAX_OID_LEN * 3];
buf[0] = '\0';
for (i = 0; i < oid_len; i++) {
sprintf (buf + strlen (buf), "%s%d", first ? "" : ".", (int) my_oid[i]);
first = 0;
}
DEBUG2 ("SMUX %s: %s", prefix, buf);
}
static int
smux_sock (void)
{
int ret;
int on = 1;
#ifdef HAVE_IPV6
struct addrinfo hints, *res0, *res;
int gai;
#else
struct sockaddr_in serv;
struct servent *sp;
#endif
int fd;
#ifdef HAVE_IPV6
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
gai = getaddrinfo(NULL, "smux", &hints, &res0);
if (gai == EAI_SERVICE) {
char servbuf[NI_MAXSERV];
sprintf(servbuf,"%d",SMUX_PORT_DEFAULT);
gai = getaddrinfo(NULL, servbuf, &hints, &res0);
}
if (gai) {
DEBUG("Cannot locate loopback service smux");
return -1;
}
for(res=res0; res; res=res->ai_next) {
fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (fd < 0)
continue;
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof (on));
#ifdef SO_REUSEPORT
setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (void *)&on, sizeof (on));
#endif
ret = connect (fd, res->ai_addr, res->ai_addrlen);
if (ret < 0) {
close(fd);
fd = -1;
continue;
}
break;
}
freeaddrinfo(res0);
if (fd < 0)
DEBUG ("Can't connect to SNMP agent with SMUX");
#else
fd = socket (AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
DEBUG ("Can't make socket for SNMP");
return -1;
}
memset (&serv, 0, sizeof (struct sockaddr_in));
serv.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
serv.sin_len = sizeof (struct sockaddr_in);
#endif
sp = getservbyname ("smux", "tcp");
if (sp != NULL)
serv.sin_port = sp->s_port;
else
serv.sin_port = htons (SMUX_PORT_DEFAULT);
serv.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof (on));
#ifdef SO_REUSEPORT
setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (void *)&on, sizeof (on));
#endif
ret = connect (fd, (struct sockaddr *) &serv, sizeof (struct sockaddr_in));
if (ret < 0) {
close (fd);
DEBUG ("Can't connect to SNMP agent with SMUX: %s", strerror(errno));
fd = -1;
}
#endif
return fd;
}
static void
smux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat,
long errindex, u_char val_type, void *arg, size_t arg_len)
{
size_t ret;
u_char buf[BUFSIZ];
u_char *ptr, *h1, *h1e, *h2, *h2e;
size_t len, length;
ptr = buf;
len = BUFSIZ;
length = len;
DEBUG3("SMUX GETRSP send");
DEBUG3("SMUX GETRSP reqid: %ld", reqid);
h1 = ptr;
ptr = asn_build_sequence (ptr, &len, (u_char) SMUX_GETRSP, 0);
h1e = ptr;
ptr = asn_build_int (ptr, &len,
(u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&reqid, sizeof (reqid));
DEBUG3("SMUX GETRSP errstat: %ld", errstat);
ptr = asn_build_int (ptr, &len,
(u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&errstat, sizeof (errstat));
DEBUG3("SMUX GETRSP errindex: %ld", errindex);
ptr = asn_build_int (ptr, &len,
(u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&errindex, sizeof (errindex));
h2 = ptr;
ptr = asn_build_sequence (ptr, &len,
(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
0);
h2e = ptr;
ptr = snmp_build_var_op (ptr, objid, &objid_len,
val_type, arg_len, arg, &len);
asn_build_sequence(h2,&length,(u_char)(ASN_SEQUENCE|ASN_CONSTRUCTOR),ptr-h2e);
asn_build_sequence(h1,&length,(u_char)SMUX_GETRSP,ptr-h1e);
DEBUG2("SMUX getresp send: %d", ptr - buf);
ret = send (rad_snmp.smux_fd, buf, (ptr - buf), 0);
}
static u_char *
smux_var (u_char *ptr, size_t len, oid objid[], size_t *objid_len,
size_t *var_val_len,
u_char *var_val_type,
void **var_value)
{
u_char type;
u_char val_type;
size_t val_len;
u_char *val;
DEBUG3("SMUX var parse: len %d", len);
ptr = asn_parse_header (ptr, &len, &type);
DEBUG3("SMUX var parse: type %d len %d", type, len);
DEBUG3("SMUX var parse: type must be %d", (ASN_SEQUENCE | ASN_CONSTRUCTOR));
*objid_len = MAX_OID_LEN;
ptr = snmp_parse_var_op(ptr, objid, objid_len, &val_type,
&val_len, &val, &len);
if (var_val_len)
*var_val_len = val_len;
if (var_value)
*var_value = (void*) val;
if (var_val_type)
*var_val_type = val_type;
smux_oid_dump ("Request OID", objid, *objid_len);
DEBUG3 ("SMUX val_type: %d", val_type);
switch (val_type) {
case ASN_NULL:
DEBUG3 ("ASN_NULL");
break;
case ASN_INTEGER:
DEBUG3 ("ASN_INTEGER");
break;
case ASN_COUNTER:
case ASN_GAUGE:
case ASN_TIMETICKS:
case ASN_UINTEGER:
DEBUG3 ("ASN_COUNTER");
break;
case ASN_COUNTER64:
DEBUG3 ("ASN_COUNTER64");
break;
case ASN_IPADDRESS:
DEBUG3 ("ASN_IPADDRESS");
break;
case ASN_OCTET_STR:
DEBUG3 ("ASN_OCTET_STR");
break;
case ASN_OPAQUE:
case ASN_NSAP:
case ASN_OBJECT_ID:
DEBUG3 ("ASN_OPAQUE");
break;
case SNMP_NOSUCHOBJECT:
DEBUG3 ("SNMP_NOSUCHOBJECT");
break;
case SNMP_NOSUCHINSTANCE:
DEBUG3 ("SNMP_NOSUCHINSTANCE");
break;
case SNMP_ENDOFMIBVIEW:
DEBUG3 ("SNMP_ENDOFMIBVIEW");
break;
case ASN_BIT_STR:
DEBUG3 ("ASN_BIT_STR");
break;
default:
DEBUG3 ("Unknown type");
break;
}
return ptr;
}
static int
smux_set (oid *reqid, size_t *reqid_len,
u_char val_type, void *val, size_t val_len, int action)
{
int j;
struct subtree *subtree;
struct variable *v;
struct list *l;
int subresult;
oid *suffix;
size_t suffix_len;
int result;
const unsigned char *statP = NULL;
WriteMethod *write_method = NULL;
if (!rad_snmp.snmp_write_access)
return SNMP_ERR_NOSUCHNAME;
for (l = treelist; l; l=l->next) {
subtree = l->data;
subresult = oid_compare_part (reqid, *reqid_len,
subtree->name, subtree->name_len);
if (subresult == 0) {
suffix = reqid + subtree->name_len;
suffix_len = *reqid_len - subtree->name_len;
result = subresult;
for (j = 0; j < subtree->variables_num; j++) {
v = &subtree->variables[j];
result = oid_compare_part (suffix, suffix_len,
v->name, v->namelen);
if (result == 0) {
DEBUG3 ("SMUX function call index is %d", v->magic);
statP = (*v->findVar) (v, suffix, &suffix_len, 1,
&val_len, &write_method);
if (write_method) {
return (*write_method)(action, val, val_type, val_len, statP, suffix, suffix_len);
} else {
return SNMP_ERR_READONLY;
}
}
if (result < 0)
return SNMP_ERR_NOSUCHNAME;
}
}
}
return SNMP_ERR_NOSUCHNAME;
}
static int
smux_get (oid *reqid, size_t *reqid_len, int exact,
u_char *val_type,u_char **val, size_t *val_len)
{
int j;
struct subtree *subtree;
struct variable *v;
struct list *l;
int subresult;
oid *suffix;
size_t suffix_len;
int result;
WriteMethod *write_method=NULL;
for (l = treelist; l; l=l->next) {
subtree = l->data;
subresult = oid_compare_part (reqid, *reqid_len,
subtree->name, subtree->name_len);
if (subresult == 0) {
suffix = reqid + subtree->name_len;
suffix_len = *reqid_len - subtree->name_len;
result = subresult;
for (j = 0; j < subtree->variables_num; j++) {
v = &subtree->variables[j];
result = oid_compare_part (suffix, suffix_len,
v->name, v->namelen);
if (result == 0) {
DEBUG3 ("SMUX function call index is %d", v->magic);
*val = (*v->findVar) (v, suffix, &suffix_len, exact,
val_len, &write_method);
if (*val == NULL)
return SNMP_ERR_NOSUCHNAME;
*val_type = v->type;
return 0;
}
if (result < 0)
return SNMP_ERR_NOSUCHNAME;
}
}
}
return SNMP_ERR_NOSUCHNAME;
}
static int
smux_getnext (oid *reqid, size_t *reqid_len, int exact,
u_char *val_type, u_char **val, size_t *val_len)
{
int j;
oid save[MAX_OID_LEN];
int savelen = 0;
struct subtree *subtree;
struct variable *v;
struct list *l;
int subresult;
oid *suffix;
size_t suffix_len;
int result;
WriteMethod *write_method=NULL;
oid_copy (save, reqid, *reqid_len);
savelen = *reqid_len;
for (l = treelist; l; l=l->next) {
subtree = l->data;
subresult = oid_compare_part (reqid, *reqid_len,
subtree->name, subtree->name_len);
if (subresult <= 0) {
suffix = reqid + subtree->name_len;
suffix_len = *reqid_len - subtree->name_len;
if (subresult < 0) {
oid_copy(reqid, subtree->name, subtree->name_len);
*reqid_len = subtree->name_len;
}
for (j = 0; j < subtree->variables_num; j++) {
result = subresult;
v = &subtree->variables[j];
if (result == 0)
result = oid_compare_part (suffix, suffix_len,
v->name, v->namelen);
if (result <= 0) {
DEBUG3 ("SMUX function call index is %d", v->magic);
if(result<0) {
oid_copy(suffix, v->name, v->namelen);
suffix_len = v->namelen;
}
*val = (*v->findVar) (v, suffix, &suffix_len, exact,
val_len, &write_method);
*reqid_len = suffix_len + subtree->name_len;
if (*val) {
*val_type = v->type;
return 0;
}
}
}
}
}
memcpy (reqid, save, savelen * sizeof(oid));
*reqid_len = savelen;
return SNMP_ERR_NOSUCHNAME;
}
static u_char *
smux_parse_get_header (u_char *ptr, size_t *len, long *reqid)
{
u_char type;
long errstat;
long errindex;
ptr = asn_parse_int (ptr, len, &type, reqid, sizeof (*reqid));
DEBUG3 ("SMUX GET reqid: %ld len: %d", *reqid, (int) *len);
ptr = asn_parse_int (ptr, len, &type, &errstat, sizeof (errstat));
DEBUG3 ("SMUX GET errstat %ld len: %d", errstat, *len);
ptr = asn_parse_int (ptr, len, &type, &errindex, sizeof (errindex));
DEBUG3 ("SMUX GET errindex %ld len: %d", errindex, *len);
return ptr;
}
static void
smux_parse_set (u_char *ptr, size_t len, int action)
{
long reqid;
oid my_oid[MAX_OID_LEN];
size_t oid_len;
u_char val_type;
void *val;
size_t val_len;
int ret;
DEBUG3 ("SMUX SET(%s) message parse: len %d",
(RESERVE1 == action) ? "RESERVE1" : ((FREE == action) ? "FREE" : "COMMIT"),
len);
ptr = smux_parse_get_header (ptr, &len, &reqid);
ptr = smux_var (ptr, len, my_oid, &oid_len, &val_len, &val_type, &val);
ret = smux_set (my_oid, &oid_len, val_type, val, val_len, action);
DEBUG2 ("SMUX SET ret %d", ret);
if (RESERVE1 == action)
smux_getresp_send (my_oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, 0);
}
static void
smux_parse_get (u_char *ptr, size_t len, int exact)
{
long reqid;
oid my_oid[MAX_OID_LEN];
size_t oid_len;
u_char val_type;
u_char *val;
size_t val_len;
int ret;
DEBUG3 ("SMUX GET message parse: len %d", len);
ptr = smux_parse_get_header (ptr, &len, &reqid);
ptr = smux_var (ptr, len, my_oid, &oid_len, NULL, NULL, NULL);
if (exact)
ret = smux_get (my_oid, &oid_len, exact, &val_type, &val, &val_len);
else
ret = smux_getnext (my_oid, &oid_len, exact, &val_type, &val, &val_len);
if (ret == 0)
smux_getresp_send (my_oid, oid_len, reqid, 0, 0, val_type, val, val_len);
else
smux_getresp_send (my_oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, 0);
}
static void
smux_parse_close (u_char *ptr, size_t len)
{
long reason = 0;
while (len--) {
reason = (reason << 8) | (long) *ptr;
ptr++;
}
DEBUG ("SMUX_CLOSE with reason: %ld", reason);
}
static void
smux_parse_rrsp (u_char *ptr, size_t len)
{
u_char val;
long errstat;
ptr = asn_parse_int (ptr, &len, &val, &errstat, sizeof (errstat));
DEBUG3 ("SMUX_RRSP value: %d errstat: %ld", val, errstat);
}
static int
smux_parse (u_char *ptr, size_t len)
{
static u_char sout_save_buff[SMUXMAXPKTSIZE];
static size_t sout_save_len = 0;
int len_income = len;
u_char type;
u_char rollback;
rollback = ptr[2];
process_rest:
ptr = asn_parse_header (ptr, &len, &type);
DEBUG2 ("SMUX message received type: %d rest len: %d", type, len);
switch (type) {
case SMUX_OPEN:
DEBUG ("SMUX_OPEN received: resetting connection.");
return -1;
break;
case SMUX_RREQ:
DEBUG ("SMUX_RREQ received: resetting connection.");
return -1;
break;
case SMUX_SOUT:
DEBUG2 ("SMUX_SOUT(%s)", rollback ? "rollback" : "commit");
if (sout_save_len > 0) {
smux_parse_set (sout_save_buff, sout_save_len, rollback ? FREE : COMMIT);
sout_save_len = 0;
} else
DEBUG ("SMUX_SOUT sout_save_len=%d - invalid", (int) sout_save_len);
if (len_income > 3) {
ptr++;
len = len_income - 3;
goto process_rest;
}
break;
case SMUX_GETRSP:
DEBUG ("SMUX_GETRSP received: resetting connection.");
return -1;
break;
case SMUX_CLOSE:
DEBUG3 ("SMUX_CLOSE");
smux_parse_close (ptr, len);
return -1;
break;
case SMUX_RRSP:
DEBUG3 ("SMUX_RRSP");
smux_parse_rrsp (ptr, len);
break;
case SMUX_GET:
DEBUG3 ("SMUX_GET");
smux_parse_get (ptr, len, 1);
break;
case SMUX_GETNEXT:
DEBUG3 ("SMUX_GETNEXT");
smux_parse_get (ptr, len, 0);
break;
case SMUX_SET:
DEBUG3 ("SMUX_SET");
memcpy (sout_save_buff, ptr, len);
sout_save_len = len;
smux_parse_set (ptr, len, RESERVE1);
break;
default:
DEBUG ("SMUX Unknown type: %d", type);
break;
}
return 0;
}
int
smux_read ()
{
int len;
u_char buf[SMUXMAXPKTSIZE];
int ret;
rad_snmp.smux_event=SMUX_NONE;
DEBUG3 ("SMUX read start");
len = recv (rad_snmp.smux_fd, buf, SMUXMAXPKTSIZE, 0);
if (len < 0) {
DEBUG ("Can't read all SMUX packet: %s", strerror (errno));
close (rad_snmp.smux_fd);
rad_snmp.smux_fd = -1;
rad_snmp.smux_event=SMUX_CONNECT;
return -1;
}
if (len == 0) {
DEBUG ("SMUX connection closed: %d", rad_snmp.smux_fd);
close (rad_snmp.smux_fd);
rad_snmp.smux_fd = -1;
rad_snmp.smux_event=SMUX_CONNECT;
return -1;
}
DEBUG3 ("SMUX read len: %d", len);
ret = smux_parse (buf, len);
if (ret < 0) {
close (rad_snmp.smux_fd);
rad_snmp.smux_fd = -1;
rad_snmp.smux_event=SMUX_CONNECT;
return -1;
}
rad_snmp.smux_event=SMUX_READ;
return 0;
}
int
smux_open(void)
{
u_char buf[BUFSIZ];
u_char *ptr;
size_t len;
long smux_proto_version;
char rad_progname[] = "radiusd";
smux_oid_dump ("SMUX open oid", smux_oid, smux_oid_len);
DEBUG2 ("SMUX open progname: %s", rad_progname);
DEBUG2 ("SMUX open password: %s", rad_snmp.smux_password);
ptr = buf;
len = BUFSIZ;
ptr = asn_build_header (ptr, &len, (u_char) SMUX_OPEN, 0);
smux_proto_version = 0;
ptr = asn_build_int (ptr, &len,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&smux_proto_version, sizeof (u_long));
ptr = asn_build_objid (ptr, &len,
(u_char)
(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),
smux_oid, smux_oid_len);
ptr = asn_build_string (ptr, &len,
(u_char)
(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
(u_char *) rad_progname, strlen(rad_progname));
ptr = asn_build_string (ptr, &len,
(u_char)
(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
(const u_char *) rad_snmp.smux_password, strlen(rad_snmp.smux_password));
len = BUFSIZ;
asn_build_header (buf, &len, (u_char) SMUX_OPEN, (ptr - buf) - 2);
return send (rad_snmp.smux_fd, buf, (ptr - buf), 0);
}
int
smux_register(void)
{
u_char buf[BUFSIZ];
u_char *ptr;
size_t len;
int ret;
long priority;
long operation;
struct subtree *subtree;
struct list *l;
ret = 0;
for (l = treelist; l; l=l->next) {
subtree = l->data;
ptr = buf;
len = BUFSIZ;
ptr = asn_build_header (ptr, &len, (u_char) SMUX_RREQ, 0);
ptr = asn_build_objid (ptr, &len,
(u_char)
(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),
subtree->name, subtree->name_len);
priority = -1;
ptr = asn_build_int (ptr, &len,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&priority, sizeof (u_long));
operation = rad_snmp.snmp_write_access ? 2 : 1;
ptr = asn_build_int (ptr, &len,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
&operation, sizeof (u_long));
smux_oid_dump ("SMUX register oid", subtree->name, subtree->name_len);
DEBUG2 ("SMUX register priority: %ld", priority);
DEBUG2 ("SMUX register operation: %ld", operation);
len = BUFSIZ;
asn_build_header (buf, &len, (u_char) SMUX_RREQ, (ptr - buf) - 2);
ret = send (rad_snmp.smux_fd, buf, (ptr - buf), 0);
if (ret < 0) {
return ret;
}
}
return ret;
}
int
smux_connect ()
{
int ret;
rad_snmp.smux_event=SMUX_NONE;
DEBUG2 ("SMUX connect try %d", rad_snmp.smux_failures + 1);
rad_snmp.smux_fd = smux_sock ();
if (rad_snmp.smux_fd < 0) {
if (++rad_snmp.smux_failures < rad_snmp.smux_max_failures)
rad_snmp.smux_event=SMUX_CONNECT;
return 0;
}
ret = smux_open ();
if (ret < 0) {
DEBUG ("SMUX open message send failed: %s", strerror (errno));
close (rad_snmp.smux_fd);
rad_snmp.smux_fd = -1;
rad_snmp.smux_event=SMUX_CONNECT;
return -1;
}
ret = smux_register ();
if (ret < 0) {
DEBUG ("SMUX register message send failed: %s", strerror (errno));
close (rad_snmp.smux_fd);
rad_snmp.smux_fd = -1;
rad_snmp.smux_event=SMUX_CONNECT;
return -1;
}
rad_snmp.smux_event=SMUX_READ;
return 0;
}
void
smux_stop(void)
{
rad_snmp.smux_event=SMUX_NONE;
if (rad_snmp.smux_fd >= 0)
close (rad_snmp.smux_fd);
rad_snmp.smux_fd = -1;
}
int
smux_str2oid (char *str, oid *my_oid, size_t *oid_len)
{
int len;
int val;
len = 0;
val = 0;
*oid_len = 0;
if (*str == '.')
str++;
if (*str == '\0')
return 0;
while (1) {
if (! isdigit ((int) *str))
return -1;
while (isdigit ((int) *str)) {
val *= 10;
val += (*str - '0');
str++;
}
if (*str == '\0')
break;
if (*str != '.')
return -1;
my_oid[len++] = val;
val = 0;
str++;
}
my_oid[len++] = val;
*oid_len = len;
return 0;
}
oid *
smux_oid_dup (oid *objid, size_t objid_len)
{
oid *new;
new = (oid *)rad_malloc(sizeof (oid) * objid_len);
oid_copy (new, objid, objid_len);
return new;
}
int
smux_header_generic (struct variable *v, oid *name, size_t *length, int exact,
size_t *var_len, WriteMethod **write_method)
{
oid fulloid[MAX_OID_LEN];
int ret;
oid_copy (fulloid, v->name, v->namelen);
fulloid[v->namelen] = 0;
ret = oid_compare (name, *length, fulloid, v->namelen + 1);
if ((exact && (ret != 0)) || (!exact && (ret >= 0)))
return MATCH_FAILED;
memcpy (name, fulloid, (v->namelen + 1) * sizeof (oid));
*length = v->namelen + 1;
*write_method = 0;
*var_len = sizeof(long);
return MATCH_SUCCEEDED;
}
void
smux_init (oid defoid[], size_t defoid_len)
{
smux_oid = defoid;
smux_oid_len = defoid_len;
}
void
smux_register_mib(UNUSED const char *descr, struct variable *var, size_t width,
int num, oid name[], size_t namelen)
{
struct subtree *tree, *tt;
struct list *l, *ll;
tree = (struct subtree *)rad_malloc(sizeof(struct subtree));
oid_copy (tree->name, name, namelen);
tree->name_len = namelen;
tree->variables = var;
tree->variables_num = num;
tree->variables_width = width;
tree->registered = 0;
l = (struct list *)rad_malloc(sizeof(struct list));
l->data = tree;
l->next = NULL;
if (treelist == NULL) {
treelist = l;
return;
}
tt = (struct subtree*) treelist->data;
if (oid_compare(name, namelen, tt->name, tt->name_len) < 0) {
l->next = treelist;
treelist = l;
return;
}
for (ll = treelist; ll->next; ll=ll->next) {
tt = (struct subtree*) ll->next->data;
if (oid_compare(name, namelen, tt->name, tt->name_len) < 0) {
l->next = ll->next;
ll->next = l;
return;
}
}
ll->next = l;
}
void
smux_start(void)
{
rad_snmp.smux_event=SMUX_CONNECT;
smux_connect();
}
#endif