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

📄 smux.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 3 页
字号:
	  u_char *val_type,void **val, size_t *val_len){  int j;  struct subtree *subtree;  struct variable *v;  int subresult;  oid *suffix;  int suffix_len;  int result;  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);		  *val = (*v->findVar) (v, suffix, &suffix_len, exact,					val_len, &write_method);		  /* There is no instance. */		  if (*val == NULL)		    return SNMP_NOSUCHINSTANCE;		  /* Call is suceed. */		  *val_type = v->type;		  return 0;		}	      /* 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_getnext (oid *reqid, size_t *reqid_len, int exact, 	      u_char *val_type,void **val, size_t *val_len){  int j;  oid save[MAX_OID_LEN];  int savelen = 0;  struct subtree *subtree;  struct variable *v;  int subresult;  oid *suffix;  int suffix_len;  int result;  WriteMethod *write_method=NULL;  struct listnode *node;  /* Save incoming request. */  oid_copy (save, reqid, *reqid_len);  savelen = *reqid_len;  /* Check */  for (node = treelist->head; node; node = node->next)    {      subtree = node->data;      subresult = oid_compare_part (reqid, *reqid_len, 				    subtree->name, subtree->name_len);      /* If request is in the tree. The agent has to make sure we         only receive requests we have registered for. */      /* Unfortunately, that's not true. In fact, a SMUX subagent has to         behave as if it manages the whole SNMP MIB tree itself. It's the         duty of the master agent to collect the best answer and return it         to the manager. See RFC 1227 chapter 3.1.6 for the glory details         :-). ucd-snmp really behaves bad here as it actually might ask         multiple times for the same GETNEXT request as it throws away the         answer when it expects it in a different subtree and might come         back later with the very same request. --jochen */      if (subresult <= 0)	{	  /* Prepare suffix. */	  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];	      /* Next then check result >= 0. */	      if (result == 0)		result = oid_compare_part (suffix, suffix_len,					   v->name, v->namelen);	      if (result <= 0)		{		  if (debug_smux)		    zlog_info ("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;}/* GET message header. */char *smux_parse_get_header (char *ptr, size_t *len, long *reqid){  u_char type;  long errstat;  long errindex;  /* Request ID. */  ptr = asn_parse_int (ptr, len, &type, reqid, sizeof (*reqid));  if (debug_smux)    zlog_info ("SMUX GET reqid: %d len: %d", (int) *reqid, (int) *len);  /* Error status. */  ptr = asn_parse_int (ptr, len, &type, &errstat, sizeof (errstat));  if (debug_smux)    zlog_info ("SMUX GET errstat %ld len: %d", errstat, *len);  /* Error index. */  ptr = asn_parse_int (ptr, len, &type, &errindex, sizeof (errindex));  if (debug_smux)    zlog_info ("SMUX GET errindex %ld len: %d", errindex, *len);  return ptr;}voidsmux_parse_set (char *ptr, size_t len, int action){  long reqid;  oid oid[MAX_OID_LEN];  size_t oid_len;  u_char val_type;  void *val;  size_t val_len;  int ret;  if (debug_smux)    zlog_info ("SMUX SET(%s) message parse: len %d",               (RESERVE1 == action) ? "RESERVE1" : ((FREE == action) ? "FREE" : "COMMIT"),               len);  /* Parse SET message header. */  ptr = smux_parse_get_header (ptr, &len, &reqid);  /* Parse SET message object ID. */  ptr = smux_var (ptr, len, oid, &oid_len, &val_len, &val_type, &val);  ret = smux_set (oid, &oid_len, val_type, val, val_len, action);  if (debug_smux)    zlog_info ("SMUX SET ret %d", ret);  /* Return result. */  if (RESERVE1 == action)    smux_getresp_send (oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, 0);}voidsmux_parse_get (char *ptr, size_t len, int exact){  long reqid;  oid oid[MAX_OID_LEN];  size_t oid_len;  u_char val_type;  void *val;  size_t val_len;  int ret;  if (debug_smux)    zlog_info ("SMUX GET message parse: len %d", len);    /* Parse GET message header. */  ptr = smux_parse_get_header (ptr, &len, &reqid);    /* Parse GET message object ID. We needn't the value come */  ptr = smux_var (ptr, len, oid, &oid_len, NULL, NULL, NULL);  /* Traditional getstatptr. */  if (exact)    ret = smux_get (oid, &oid_len, exact, &val_type, &val, &val_len);  else    ret = smux_getnext (oid, &oid_len, exact, &val_type, &val, &val_len);  /* Return result. */  if (ret == 0)    smux_getresp_send (oid, oid_len, reqid, 0, 0, val_type, val, val_len);  else    smux_getresp_send (oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, 0);}/* Parse SMUX_CLOSE message. */voidsmux_parse_close (char *ptr, int len){  long reason = 0;  while (len--)    {      reason = (reason << 8) | (long) *ptr;      ptr++;    }  zlog_info ("SMUX_CLOSE with reason: %ld", reason);}/* SMUX_RRSP message. */voidsmux_parse_rrsp (char *ptr, int len){  char val;  long errstat;    ptr = asn_parse_int (ptr, &len, &val, &errstat, sizeof (errstat));  if (debug_smux)    zlog_info ("SMUX_RRSP value: %d errstat: %ld", val, errstat);}/* Parse SMUX message. */intsmux_parse (char *ptr, int len){  /* This buffer we'll use for SOUT message. We could allocate it with     malloc and save only static pointer/lenght, but IMHO static     buffer is a faster solusion. */  static u_char sout_save_buff[SMUXMAXPKTSIZE];  static int sout_save_len = 0;  int len_income = len; /* see note below: YYY */  u_char type;  u_char rollback;  rollback = ptr[2]; /* important only for SMUX_SOUT */process_rest: /* see note below: YYY */  /* Parse SMUX message type and subsequent length. */  ptr = asn_parse_header (ptr, &len, &type);  if (debug_smux)    zlog_info ("SMUX message received type: %d rest len: %d", type, len);  switch (type)    {    case SMUX_OPEN:      /* Open must be not send from SNMP agent. */      zlog_warn ("SMUX_OPEN received: resetting connection.");      return -1;      break;    case SMUX_RREQ:      /* SMUX_RREQ message is invalid for us. */      zlog_warn ("SMUX_RREQ received: resetting connection.");      return -1;      break;    case SMUX_SOUT:      /* SMUX_SOUT message is now valied for us. */      if (debug_smux)        zlog_info ("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        zlog_warn ("SMUX_SOUT sout_save_len=%d - invalid", (int) sout_save_len);      if (len_income > 3)         {          /* YYY: this strange code has to solve the "slow peer"             problem: When agent sends SMUX_SOUT message it doesn't             wait any responce and may send some next message to             subagent. Then the peer in 'smux_read()' will recieve             from socket the 'concatenated' buffer, contaning both             SMUX_SOUT message and the next one             (SMUX_GET/SMUX_GETNEXT/SMUX_GET). So we should check: if             the buffer is longer than 3 ( length of SMUX_SOUT ), we             must process the rest of it.  This effect may be observed             if 'debug_smux' is set to '1' */          ptr++;          len = len_income - 3;          goto process_rest;        }      break;    case SMUX_GETRSP:      /* SMUX_GETRSP message is invalid for us. */      zlog_warn ("SMUX_GETRSP received: resetting connection.");      return -1;      break;    case SMUX_CLOSE:      /* Close SMUX connection. */      if (debug_smux)	zlog_info ("SMUX_CLOSE");      smux_parse_close (ptr, len);      return -1;      break;    case SMUX_RRSP:      /* This is response for register message. */      if (debug_smux)	zlog_info ("SMUX_RRSP");      smux_parse_rrsp (ptr, len);      break;    case SMUX_GET:      /* Exact request for object id. */      if (debug_smux)	zlog_info ("SMUX_GET");      smux_parse_get (ptr, len, 1);      break;    case SMUX_GETNEXT:      /* Next request for object id. */      if (debug_smux)	zlog_info ("SMUX_GETNEXT");      smux_parse_get (ptr, len, 0);      break;    case SMUX_SET:      /* SMUX_SET is supported with some limitations. */      if (debug_smux)	zlog_info ("SMUX_SET");      /* save the data for future SMUX_SOUT */      memcpy (sout_save_buff, ptr, len);      sout_save_len = len;      smux_parse_set (ptr, len, RESERVE1);      break;    default:      zlog_info ("Unknown type: %d", type);      break;    }  return 0;}/* SMUX message read function. */intsmux_read (struct thread *t){  int sock;  int len;  u_char buf[SMUXMAXPKTSIZE];  int ret;  /* Clear thread. */  sock = THREAD_FD (t);  smux_read_thread = NULL;  if (debug_smux)    zlog_info ("SMUX read start");  /* Read message from SMUX socket. */  len = recv (sock, buf, SMUXMAXPKTSIZE, 0);  if (len < 0)    {      zlog_warn ("Can't read all SMUX packet: %s", strerror (errno));      close (sock);      smux_sock = -1;      smux_event (SMUX_CONNECT, 0);      return -1;    }  if (len == 0)    {      zlog_warn ("SMUX connection closed: %d", sock);      close (sock);      smux_sock = -1;      smux_event (SMUX_CONNECT, 0);      return -1;    }  if (debug_smux)    zlog_info ("SMUX read len: %d", len);  /* Parse the message. */  ret = smux_parse (buf, len);  if (ret < 0)    {      close (sock);      smux_sock = -1;      smux_event (SMUX_CONNECT, 0);      return -1;    }  /* Regiser read thread. */  smux_event (SMUX_READ, sock);  return 0;}intsmux_open (int sock){  u_char buf[BUFSIZ];  u_char *ptr;  int len;  u_long version;  u_char progname[] = "zebra-" ZEBRA_VERSION;  if (debug_smux)    {      smux_oid_dump ("SMUX open oid", smux_oid, smux_oid_len);      zlog_info ("SMUX open progname: %s", progname);      zlog_info ("SMUX open password: %s", smux_passwd);    }  ptr = buf;  len = BUFSIZ;  /* SMUX Header.  As placeholder. */  ptr = asn_build_header (ptr, &len, (u_char) SMUX_OPEN, 0);  /* SMUX Open. */  version = 0;  ptr = asn_build_int (ptr, &len, 		       (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),		       &version, sizeof (u_long));  /* SMUX connection oid. */  ptr = asn_build_objid (ptr, &len,			 (u_char) 			 (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),			 smux_oid, smux_oid_len);  /* SMUX connection description. */  ptr = asn_build_string (ptr, &len, 			  (u_char)			  (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),			  progname, strlen (progname));  /* SMUX connection password. */  ptr = asn_build_string (ptr, &len, 			  (u_char)			  (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),			  smux_passwd, strlen (smux_passwd));  /* Fill in real SMUX header.  We exclude ASN header size (2). */  len = BUFSIZ;  asn_build_header (buf, &len, (u_char) SMUX_OPEN, (ptr - buf) - 2);  return send (sock, buf, (ptr - buf), 0);}intsmux_trap (oid *name, size_t namelen,	   oid *iname, size_t inamelen,	   struct trap_object *trapobj, size_t trapobjlen,	   unsigned int tick, u_char sptrap){  int i;

⌨️ 快捷键说明

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