📄 smux.c
字号:
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. */static 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)); DEBUG2 ("SMUX GET reqid: %ld len: %d", *reqid, (int) *len); /* Error status. */ ptr = asn_parse_int (ptr, len, &type, &errstat, sizeof (errstat)); DEBUG2 ("SMUX GET errstat %ld len: %d", errstat, *len); /* Error index. */ ptr = asn_parse_int (ptr, len, &type, &errindex, sizeof (errindex)); DEBUG2 ("SMUX GET errindex %ld len: %d", errindex, *len); return ptr;}static voidsmux_parse_set (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; DEBUG2 ("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, 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); /* Return result. */ if (RESERVE1 == action) smux_getresp_send (my_oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, 0);}static voidsmux_parse_get (char *ptr, size_t len, int exact){ long reqid; oid my_oid[MAX_OID_LEN]; size_t oid_len; u_char val_type; const void *val; size_t val_len; int ret; DEBUG2 ("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, my_oid, &oid_len, NULL, NULL, NULL); /* Traditional getstatptr. */ 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); /* Return result. */ 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);}/* Parse SMUX_CLOSE message. */static voidsmux_parse_close (char *ptr, int len){ long reason = 0; while (len--) { reason = (reason << 8) | (long) *ptr; ptr++; } DEBUG ("SMUX_CLOSE with reason: %ld", reason);}/* SMUX_RRSP message. */static voidsmux_parse_rrsp (char *ptr, int len){ char val; long errstat; ptr = asn_parse_int (ptr, &len, &val, &errstat, sizeof (errstat)); DEBUG2 ("SMUX_RRSP value: %d errstat: %ld", val, errstat);}/* Parse SMUX message. */static 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); DEBUG2 ("SMUX message received type: %d rest len: %d", type, len); switch (type) { case SMUX_OPEN: /* Open must be not send from SNMP agent. */ DEBUG ("SMUX_OPEN received: resetting connection."); return -1; break; case SMUX_RREQ: /* SMUX_RREQ message is invalid for us. */ DEBUG ("SMUX_RREQ received: resetting connection."); return -1; break; case SMUX_SOUT: /* SMUX_SOUT message is now valied for us. */ 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) { /* 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 is set to >1 */ ptr++; len = len_income - 3; goto process_rest; } break; case SMUX_GETRSP: /* SMUX_GETRSP message is invalid for us. */ DEBUG ("SMUX_GETRSP received: resetting connection."); return -1; break; case SMUX_CLOSE: /* Close SMUX connection. */ DEBUG2 ("SMUX_CLOSE"); smux_parse_close (ptr, len); return -1; break; case SMUX_RRSP: /* This is response for register message. */ DEBUG2 ("SMUX_RRSP"); smux_parse_rrsp (ptr, len); break; case SMUX_GET: /* Exact request for object id. */ DEBUG2 ("SMUX_GET"); smux_parse_get (ptr, len, 1); break; case SMUX_GETNEXT: /* Next request for object id. */ DEBUG2 ("SMUX_GETNEXT"); smux_parse_get (ptr, len, 0); break; case SMUX_SET: /* SMUX_SET is supported with some limitations. */ DEBUG2 ("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: DEBUG ("Unknown type: %d", type); break; } return 0;}/* SMUX message read function. */intsmux_read (){ int len; u_char buf[SMUXMAXPKTSIZE]; int ret; rad_snmp.smux_event=SMUX_NONE; DEBUG2 ("SMUX read start"); /* Read message from SMUX socket. */ 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; } DEBUG2 ("SMUX read len: %d", len); /* Parse the message. */ 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;}intsmux_open(void){ u_char buf[BUFSIZ]; u_char *ptr; int len; u_long smux_proto_version; u_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; /* SMUX Header. As placeholder. */ ptr = asn_build_header (ptr, &len, (u_char) SMUX_OPEN, 0); /* SMUX Open. */ smux_proto_version = 0; ptr = asn_build_int (ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &smux_proto_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), rad_progname, strlen (rad_progname)); /* SMUX connection password. */ ptr = asn_build_string (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), rad_snmp.smux_password, strlen(rad_snmp.smux_password)); /* 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 (rad_snmp.smux_fd, buf, (ptr - buf), 0);}intsmux_register(void){ u_char buf[BUFSIZ]; u_char *ptr; int len, 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; /* SMUX RReq Header. */ ptr = asn_build_header (ptr, &len, (u_char) SMUX_RREQ, 0); /* Register MIB tree. */ ptr = asn_build_objid (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), subtree->name, subtree->name_len); /* Priority. */ priority = -1; ptr = asn_build_int (ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &priority, sizeof (u_long)); /* Operation. */ operation = rad_snmp.snmp_write_access ? 2 : 1; /* Register R/O or R/W */ 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;}/* Try to connect to SNMP agent. */intsmux_connect (){ int ret; rad_snmp.smux_event=SMUX_NONE; DEBUG2 ("SMUX connect try %d", rad_snmp.smux_failures + 1); /* Make socket. Try to connect. */ 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; } /* Send OPEN PDU. */ 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; } /* Send any outstanding register PDUs. */ 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; } /* Everything goes fine. */ rad_snmp.smux_event=SMUX_READ; return 0;}/* Clear all SMUX related resources. */voidsmux_stop(void){ rad_snmp.smux_event=SMUX_NONE; if (rad_snmp.smux_fd >= 0) close (rad_snmp.smux_fd); rad_snmp.smux_fd = -1;}intsmux_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;}intsmux_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; /* Check against full instance. */ ret = oid_compare (name, *length, fulloid, v->namelen + 1); /* Check single instance. */ if ((exact && (ret != 0)) || (!exact && (ret >= 0))) return MATCH_FAILED; /* In case of getnext, fill in full instance. */ memcpy (name, fulloid, (v->namelen + 1) * sizeof (oid)); *length = v->namelen + 1; *write_method = 0; *var_len = sizeof(long); /* default to 'long' results */ return MATCH_SUCCEEDED;}/* Initialize some values then schedule first SMUX connection. */voidsmux_init (oid defoid[], size_t defoid_len){ smux_oid = defoid; smux_oid_len = defoid_len;}/* Register subtree to smux master tree. */voidsmux_register_mib(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;/* Build a treelist sorted by the name. This makes GETNEXT simpler */ 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;}voidsmux_start(void){ rad_snmp.smux_event=SMUX_CONNECT; smux_connect();}#endif /* WITH_SNMP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -