⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kernel_sunos5.c

📁 ucd-snmp源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifdef KSTAT_DATA_INT32		/* Solaris 2.6 and up */      case KSTAT_DATA_INT32:	*(Counter *)v = d->value.i32;	DEBUGMSGTL(("kernel_sunos5", "value: %d\n", d->value.i32));	break;      case KSTAT_DATA_UINT32:	*(Counter *)v = d->value.ui32;	DEBUGMSGTL(("kernel_sunos5", "value: %u\n", d->value.ui32));	break;      case KSTAT_DATA_INT64:	*(int64_t *)v = d->value.i64;	DEBUGMSGTL(("kernel_sunos5", "value: %ld\n", d->value.i64));	break;      case KSTAT_DATA_UINT64:	*(uint64_t *)v = d->value.ui64;	DEBUGMSGTL(("kernel_sunos5", "value: %lu\n", d->value.ui64));	break;#else      case KSTAT_DATA_LONG:	*(Counter *)v = d->value.l;	DEBUGMSGTL(("kernel_sunos5", "value: %ld\n", d->value.l));	break;      case KSTAT_DATA_ULONG:	*(Counter *)v = d->value.ul;	DEBUGMSGTL(("kernel_sunos5", "value: %lu\n", d->value.ul));	break;      case KSTAT_DATA_LONGLONG:	*(Counter *)v = d->value.ll;	DEBUGMSGTL(("kernel_sunos5", "value: %lld\n", (long)d->value.ll));	break;      case KSTAT_DATA_ULONGLONG:	*(Counter *)v = d->value.ull;	DEBUGMSGTL(("kernel_sunos5", "value: %llu\n", (unsigned long)d->value.ull));	break;#endif      case KSTAT_DATA_FLOAT:	*(float *)v = d->value.f;	DEBUGMSGTL(("kernel_sunos5", "value: %f\n", d->value.f));	break;      case KSTAT_DATA_DOUBLE:	*(double *)v = d->value.d;        DEBUGMSGTL(("kernel_sunos5", "value: %f\n", d->value.d));	break;      default:	DEBUGMSGTL(("kernel_sunos5", "Unknown type in kstat data: %s %s %d\n",		statname, varname, d->data_type));	ret = -3;	goto Return;		/* Invalid data type */      }      ret = 0;			/* Success  */      goto Return;    }  }  ret = -4;			/* Name not found */Return:  return (ret);}/* * get MIB-II statistics. It maintaines a simple cache which buffers * the last read block of MIB statistics (which may contain the whole * table). It calls *comp to compare every entry with an entry pointed * by arg. *comp should return 0 if comparison is successful. * Req_type may be GET_FIRST, GET_EXACT, GET_NEXT. * If search is successful getMibstat returns 0, otherwise 1. */intgetMibstat(mibgroup_e grid,  void *resp, size_t entrysize,	   req_e req_type, int (*comp)(void *, void *), void *arg){    int		ret, rc=-1, mibgr, mibtb, cache_valid;    size_t	length;    mibcache	*cachep;    found_e	result = NOT_FOUND;    void*	ep;    /*     * We assume that Mibcache is initialized in mibgroup_e enum order     * so we don't check the validity of index here.     */    DEBUGMSGTL(("kernel_sunos5", "getMibstat (%d, *, %d, %d, *, *)\n", grid, entrysize, req_type));    cachep = &Mibcache[grid];    mibgr = Mibmap[grid].group;    mibtb = Mibmap[grid].table;    if (cachep->cache_addr == (void *)-1) /* Hasn't been initialized yet */	init_mibcache_element(cachep);    if (cachep->cache_size == 0) { /* Memory allocation problems */	cachep->cache_addr = resp; /* So use caller supplied address instead of cache */	cachep->cache_size = entrysize;        cachep->cache_last_found = 0;    }    if (req_type != GET_NEXT)      cachep->cache_last_found = 0;    cache_valid = (time(NULL) - cachep->cache_time) > cachep->cache_ttl ? 0 : 1;    DEBUGMSGTL(("kernel_sunos5", "... cache_valid %d time %ld ttl %d now %ld\n",                cache_valid, cachep->cache_time, cachep->cache_ttl,                time (NULL)));    if (cache_valid) {	/* Is it really? */	if (cachep->cache_comp != (void *) comp ||	    cachep->cache_arg != arg)		cache_valid = 0;	/* Nope. */    }    if (cache_valid) {      /* Entry is valid, let's try to find a match */      if (req_type == GET_NEXT) {        result = getentry(req_type,                          (void *) ((char *) cachep->cache_addr + (cachep->cache_last_found * entrysize)),                          cachep->cache_length - (cachep->cache_last_found * entrysize),                          entrysize, &ep, comp, arg);      } else {        result = getentry(req_type, cachep->cache_addr, cachep->cache_length,			  entrysize, &ep, comp, arg);      }    }    if ((cache_valid == 0)	|| (result == NOT_FOUND)	|| ((result == NEED_NEXT) && cachep->cache_flags&CACHE_MOREDATA)) {	/*	 *  Either the cache is old, or we haven't found	 *  anything, or need the next item which hasn't been read yet.	 *  In any case, fill the cache up and try to find our entry.	 */	if (grid == MIB_INTERFACES)	    rc = getif((mib2_ifEntry_t *)cachep->cache_addr, cachep->cache_size,		       req_type, (mib2_ifEntry_t *)&ep, &length, comp, arg);	else	    rc = getmib(mibgr, mibtb, cachep->cache_addr, cachep->cache_size, entrysize,			req_type, &ep, &length, comp, arg);	if (rc >= 0) {		/* Cache has been filled up */	    cachep->cache_time = time(NULL);	    cachep->cache_length = length;	    if (rc == 1)	/* Found but there are more unread data */		cachep->cache_flags |= CACHE_MOREDATA;	    else		cachep->cache_flags &= ~CACHE_MOREDATA;	    cachep->cache_comp = (void *) comp;	    cachep->cache_arg = arg;	} else {	    cachep->cache_comp = NULL;	    cachep->cache_arg = NULL;	}    }    DEBUGMSGTL(("kernel_sunos5", "... result %d rc %d\n", result, rc));    if (result == FOUND || rc == 0 || rc == 1) {	/* Entry has been found, deliver it */	if (resp != (void *)NULL) 	    (void)memcpy(resp, ep, entrysize);	ret = 0;	cachep->cache_last_found = ((char *) ep - (char *) cachep->cache_addr) / entrysize;    } else	ret = 1;		/* Not found */    DEBUGMSGTL(("kernel_sunos5", "... getMibstat returns %d\n", ret));    return (ret);}/*  Get a MIB-II entry from the buffer buffaddr, which satisfies *  the criterion, computed by (*comp), which gets arg as the first *  argument and pointer to the current position in the buffer as the *  second. If found entry is pointed by resp. */static found_egetentry(req_e req_type, void *bufaddr, size_t len, size_t entrysize,	 void *resp, int (*comp)(void *, void *), void *arg){         void *bp = bufaddr, **rp = resp;    int previous_found = 0;        /* Here we have to perform address arithmetic with       pointer to void. Ugly... */    for (; len != 0; len -= entrysize, bp = (char *)bp + entrysize) {	if (rp != (void *)NULL)	    *rp = bp;	if ((req_type == GET_FIRST) ||	    ((req_type == GET_NEXT) && previous_found)) {	    return (FOUND);	}	if ((*comp)(arg, bp) == 0) {	    if (req_type == GET_EXACT) {		return (FOUND);	    } else {			/* GET_NEXT */		previous_found++;		continue;	    }        }    }    if (previous_found)	return (NEED_NEXT);    else	return (NOT_FOUND);}/* * Initialize a cache element. It allocates the memory * and sets the time stamp to invalidate the element. */static voidinit_mibcache_element(mibcache *cp){    if (cp == (mibcache *)NULL)	return;    if (cp->cache_size)	    cp->cache_addr = malloc(cp->cache_size);    cp->cache_time = time(NULL) - 100*cp->cache_ttl; /* In the past */    cp->cache_comp = NULL;    cp->cache_arg = NULL;}/* Get MIB-II statistics from the Solaris kernel.   It uses undocumented interface to TCP/IP streams modules, which   provides extended MIB-II for the following groups:   ip, icmp, tcp, udp, egp.   Usage: groupname, subgroupname are from <inet/mib2.h>, size%sizeof(statbuf) == 0,   entrysize should be exact size of MIB-II entry,   req_type:   GET_FIRST - get the first entry in the buffer   GET_EXACT - get exact match   GET_NEXT  - get next entry after the exact match   (*comp) is a compare function, provided by the caller, which gets arg as the   first argument and pointer to the current entry as th second. If compared, should   return 0 and found entry will be pointed by resp.   If search is successful and no more data to read, it returns 0,   if successful and there is more data -- 1,   if not found and end of data -- 2, any other errors -- < 0   (negative error numbers are pretty random).      NOTE: needs to be protected by a mutex in reentrant environment */static intgetmib(int groupname, int subgroupname, void *statbuf, size_t size, size_t entrysize,	   req_e req_type, void *resp, size_t *length, int (*comp)(void *, void *), void *arg){  int 		rc, ret = 0, flags;  char		buf[BUFSIZE];  struct 	strbuf strbuf;  struct 	T_optmgmt_req *tor = (struct T_optmgmt_req *) buf;  struct 	T_optmgmt_ack *toa = (struct T_optmgmt_ack *) buf;  struct 	T_error_ack  *tea = (struct T_error_ack *) buf;  struct 	opthdr *req;  found_e	result = FOUND;  DEBUGMSGTL(("kernel_sunos5", "...... getmib (%d, %d, ...)\n", groupname, subgroupname));  /* Open the stream driver and push all MIB-related modules */  if (sd == -1) {		/* First time */    if ((sd = open(STREAM_DEV, O_RDWR)) == -1) {      ret = -1;      goto Return;    }    if (ioctl(sd, I_PUSH, "arp") == -1) {      ret = -1;      goto Return;    }    if (ioctl(sd, I_PUSH, "tcp") == -1) {      ret = -1;      goto Return;    }    if (ioctl(sd, I_PUSH, "udp") == -1) {      ret = -1;      goto Return;    }    DEBUGMSGTL(("kernel_sunos5", "...... modules pushed OK\n"));  }  /* First, use bigger buffer, to accelerate skipping     unwanted messages */  strbuf.buf = buf;  strbuf.maxlen = BUFSIZE;  tor->PRIM_type = T_OPTMGMT_REQ;  tor->OPT_offset = sizeof(struct T_optmgmt_req);  tor->OPT_length = sizeof(struct opthdr);#ifdef MI_T_CURRENT  tor->MGMT_flags = MI_T_CURRENT;	/* Solaris < 2.6 */#else  tor->MGMT_flags = T_CURRENT;		/* Solaris 2.6 */#endif  req = (struct opthdr *) (tor + 1);  req->level = groupname;  req->name = subgroupname;  req->len = 0;  strbuf.len = tor->OPT_length + tor->OPT_offset;  flags = 0;  if ((rc = putmsg(sd, &strbuf, NULL, flags))) {    ret = -2;    goto Return;  }  req = (struct opthdr *) (toa + 1);  for (;;) {    flags = 0;    if ((rc = getmsg(sd, &strbuf, NULL, &flags)) == -1) {      ret = -EIO;      break;    }    if (rc == 0	&& strbuf.len >= sizeof(struct T_optmgmt_ack)	&& toa->PRIM_type == T_OPTMGMT_ACK	&& toa->MGMT_flags == T_SUCCESS	&& req->len == 0) {      ret = 2;      break;    }    if (strbuf.len >= sizeof(struct T_error_ack)	&& tea->PRIM_type == T_ERROR_ACK) {      ret = -((tea->TLI_error == TSYSERR)?tea->UNIX_error:EPROTO); /* Protocol error */      break;    }    if (rc != MOREDATA	|| strbuf.len < sizeof(struct T_optmgmt_ack)	|| toa->PRIM_type != T_OPTMGMT_ACK	|| toa->MGMT_flags != T_SUCCESS) {      ret = -ENOMSG;			/* No more messages */      break;    }    /* The order in which we get the statistics is determined by the       kernel and not by the group name, so we have to loop until       we get the required statistics. */    if (req->level != groupname || req->name != subgroupname) {      strbuf.maxlen = BUFSIZE;      strbuf.buf = buf;      do {	rc = getmsg(sd, NULL, &strbuf, &flags);      } while (rc == MOREDATA) ;      continue;    }    /* Now when we found our stat, switch buffer to a caller-provided       one. Manipulating the size of it one can control performance,       reducing the number of getmsg calls */    strbuf.buf = statbuf;    strbuf.maxlen = size;    strbuf.len = 0;    flags = 0;    do {      rc = getmsg(sd, NULL, &strbuf, &flags);      switch (rc) {      case -1:	rc = -ENOSR;	goto Return;      default:	rc = -ENODATA;	goto Return;      case MOREDATA:      case 0:	if (req_type == GET_NEXT  && result == NEED_NEXT)	    /* End of buffer, so "next" is the first item in the next buffer */	    req_type = GET_FIRST;	result = getentry(req_type, (void *)strbuf.buf, strbuf.len, entrysize,			  resp, comp, arg);	*length = strbuf.len;	/* To use in caller for cacheing */	break;      }    } while (rc == MOREDATA && result != FOUND);    if (result == FOUND) {	/* Search is successful */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -