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

📄 smux.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 3 页
字号:
/* SNMP support * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org> * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING.  If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA.   */#include <zebra.h>#ifdef HAVE_SNMP#include <asn1.h>#include <snmp.h>#include <snmp_impl.h>#include "smux.h"#include "log.h"#include "thread.h"#include "linklist.h"#include "command.h"#include "version.h"#include "memory.h"#include "sockunion.h"#define min(A,B) ((A) < (B) ? (A) : (B))enum smux_event {SMUX_SCHEDULE, SMUX_CONNECT, SMUX_READ};void smux_event (enum smux_event, int);/* SMUX socket. */int smux_sock = -1;/* SMUX subtree list. */struct list *treelist;/* SMUX oid. */oid *smux_oid;size_t smux_oid_len;/* SMUX default oid. */oid *smux_default_oid;size_t smux_default_oid_len;/* SMUX password. */char *smux_passwd;char *smux_default_passwd = "";/* SMUX read threads. */struct thread *smux_read_thread;/* SMUX connect thrads. */struct thread *smux_connect_thread;/* SMUX debug flag. */int debug_smux = 0;/* SMUX failure count. */int fail = 0;/* SMUX node. */struct cmd_node smux_node ={  SMUX_NODE,  ""                            /* SMUX has no interface. */};void *oid_copy (void *dest, void *src, size_t size){  return memcpy (dest, src, size * sizeof (oid));}voidoid2in_addr (oid 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++ = oid[i];}voidoid_copy_addr (oid 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++)    oid[i] = *pnt++;}intoid_compare (oid *o1, int o1_len, oid *o2, int o2_len){  int 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;}intoid_compare_part (oid *o1, int o1_len, oid *o2, int o2_len){  int 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;}voidsmux_oid_dump (char *prefix, oid *oid, size_t oid_len){  int 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) oid[i]);      first = 0;    }  zlog_info ("%s: %s", prefix, buf);}intsmux_socket (){  int ret;#ifdef HAVE_IPV6  struct addrinfo hints, *res0, *res;  int gai;#else  struct sockaddr_in serv;  struct servent *sp;#endif  int sock = 0;#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);      servbuf[sizeof (servbuf) - 1] = '\0';      gai = getaddrinfo(NULL, servbuf, &hints, &res0);    }  if (gai)    {      zlog_warn("Cannot locate loopback service smux");      return -1;    }  for(res=res0; res; res=res->ai_next)    {      if (res->ai_family != AF_INET #ifdef HAVE_IPV6	  && res->ai_family != AF_INET6#endif /* HAVE_IPV6 */	  )	continue;      sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);      if (sock < 0)	continue;      sockopt_reuseaddr (sock);      sockopt_reuseport (sock);      ret = connect (sock, res->ai_addr, res->ai_addrlen);      if (ret < 0)	{	  close(sock);	  sock = -1;	  continue;	}      break;    }  freeaddrinfo(res0);  if (sock < 0)    zlog_warn ("Can't connect to SNMP agent with SMUX");#else  sock = socket (AF_INET, SOCK_STREAM, 0);  if (sock < 0)    {      zlog_warn ("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 /* HAVE_SIN_LEN */  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);  sockopt_reuseaddr (sock);  sockopt_reuseport (sock);  ret = connect (sock, (struct sockaddr *) &serv, sizeof (struct sockaddr_in));  if (ret < 0)    {      close (sock);      smux_sock = -1;      zlog_warn ("Can't connect to SNMP agent with SMUX");      return -1;    }#endif  return sock;}voidsmux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat,		   long errindex, u_char val_type, void *arg, size_t arg_len){  int ret;  u_char buf[BUFSIZ];  u_char *ptr, *h1, *h1e, *h2, *h2e;  int len, length;  ptr = buf;  len = BUFSIZ;  length = len;  if (debug_smux)    {      zlog_info ("SMUX GETRSP send");      zlog_info ("SMUX GETRSP reqid: %ld", reqid);    }  h1 = ptr;  /* Place holder h1 for complete sequence */  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));  if (debug_smux)    zlog_info ("SMUX GETRSP errstat: %ld", errstat);  ptr = asn_build_int (ptr, &len,		       (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),		       &errstat, sizeof (errstat));  if (debug_smux)    zlog_info ("SMUX GETRSP errindex: %ld", errindex);  ptr = asn_build_int (ptr, &len,		       (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),		       &errindex, sizeof (errindex));  h2 = ptr;  /* Place holder h2 for one variable */  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);  /* Now variable size is known, fill in size */  asn_build_sequence(h2,&length,(u_char)(ASN_SEQUENCE|ASN_CONSTRUCTOR),ptr-h2e);  /* Fill in size of whole sequence */  asn_build_sequence(h1,&length,(u_char)SMUX_GETRSP,ptr-h1e);  if (debug_smux)    zlog_info ("SMUX getresp send: %d", ptr - buf);    ret = send (smux_sock, buf, (ptr - buf), 0);}char *smux_var (char *ptr, int 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;  if (debug_smux)    zlog_info ("SMUX var parse: len %d", len);  /* Parse header. */  ptr = asn_parse_header (ptr, &len, &type);    if (debug_smux)    {      zlog_info ("SMUX var parse: type %d len %d", type, len);      zlog_info ("SMUX var parse: type must be %d", 		 (ASN_SEQUENCE | ASN_CONSTRUCTOR));    }  /* Parse var option. */  *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;  /* Requested object id length is objid_len. */  if (debug_smux)    smux_oid_dump ("Request OID", objid, *objid_len);  if (debug_smux)    zlog_info ("SMUX val_type: %d", val_type);  /* Check request value type. */  if (debug_smux)  switch (val_type)    {    case ASN_NULL:      /* In case of SMUX_GET or SMUX_GET_NEXT val_type is set to         ASN_NULL. */      zlog_info ("ASN_NULL");      break;    case ASN_INTEGER:      zlog_info ("ASN_INTEGER");      break;    case ASN_COUNTER:    case ASN_GAUGE:    case ASN_TIMETICKS:    case ASN_UINTEGER:      zlog_info ("ASN_COUNTER");      break;    case ASN_COUNTER64:      zlog_info ("ASN_COUNTER64");      break;    case ASN_IPADDRESS:      zlog_info ("ASN_IPADDRESS");      break;    case ASN_OCTET_STR:      zlog_info ("ASN_OCTET_STR");      break;    case ASN_OPAQUE:    case ASN_NSAP:    case ASN_OBJECT_ID:      zlog_info ("ASN_OPAQUE");      break;    case SNMP_NOSUCHOBJECT:      zlog_info ("SNMP_NOSUCHOBJECT");      break;    case SNMP_NOSUCHINSTANCE:      zlog_info ("SNMP_NOSUCHINSTANCE");      break;    case SNMP_ENDOFMIBVIEW:      zlog_info ("SNMP_ENDOFMIBVIEW");      break;    case ASN_BIT_STR:      zlog_info ("ASN_BIT_STR");      break;    default:      zlog_info ("Unknown type");      break;    }  return ptr;}/* NOTE: all 3 functions (smux_set, smux_get & smux_getnext) are based on   ucd-snmp smux and as such suppose, that the peer receives in the message   only one variable. Fortunately, IBM seems to do the same in AIX. */intsmux_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;  int subresult;  oid *suffix;  int suffix_len;  int result;  u_char *statP = NULL;  WriteMethod *write_method = NULL;  struct listnode *node;  /* Check */  for (node = treelist->head; node; node = node->next)    {      subtree = node->data;      subresult = oid_compare_part (reqid, *reqid_len,                                    subtree->name, subtree->name_len);      /* Subtree matched. */      if (subresult == 0)        {          /* Prepare suffix. */          suffix = reqid + subtree->name_len;          suffix_len = *reqid_len - subtree->name_len;          result = subresult;          /* Check variables. */          for (j = 0; j < subtree->variables_num; j++)            {              v = &subtree->variables[j];              /* Always check suffix */              result = oid_compare_part (suffix, suffix_len,                                         v->name, v->namelen);              /* This is exact match so result must be zero. */              if (result == 0)                {                  if (debug_smux)                    zlog_info ("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, v);                    }                  else                    {                      return SNMP_ERR_READONLY;                    }                }              /* If above execution is failed or oid is small (so                 there is no further match). */              if (result < 0)                return SNMP_ERR_NOSUCHNAME;            }        }    }  return SNMP_ERR_NOSUCHNAME;}intsmux_get (oid *reqid, size_t *reqid_len, int exact, 

⌨️ 快捷键说明

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