📄 smux.c
字号:
/* we could receive the reply or another trap */ } else { ptr = buf; ptr = asn_parse_header(ptr, &len, &type); if ((ptr == NULL) || type != SNMP_MSG_RESPONSE) return SNMP_ERR_GENERR; ptr = asn_parse_int(ptr, &len, &type, &reqid, sizeof(reqid)); if ((ptr == NULL) || type != ASN_INTEGER) return SNMP_ERR_GENERR; ptr = asn_parse_int(ptr, &len, &type, &errsts, sizeof(errsts)); if ((ptr == NULL) || type != ASN_INTEGER) return SNMP_ERR_GENERR; if (errsts) { DEBUGMSGTL (("smux","[var_smux_write] errsts returned\n")); return (errsts); } ptr = asn_parse_int(ptr, &len, &type, &erridx, sizeof(erridx)); if ((ptr == NULL) || type != ASN_INTEGER) return SNMP_ERR_GENERR; reterr = SNMP_ERR_NOERROR; break; } } /* while (1) */ break; /* case Action == RESERVE1 */ case RESERVE2: DEBUGMSGTL (("smux","[var_smux_write] entering RESERVE2\n")); reterr = SNMP_ERR_NOERROR; break; /* case Action == RESERVE2 */ case FREE: case COMMIT: ptr = sout; *(ptr++) = (u_char)SMUX_SOUT; *(ptr++) = (u_char)1; if (action==FREE) { *ptr = (u_char)1; /* rollback */ DEBUGMSGTL (("smux","[var_smux_write] entering FREE - sending RollBack \n")); } else { *ptr = (u_char)0; /* commit */ DEBUGMSGTL (("smux","[var_smux_write] entering FREE - sending Commit \n")); } if ((send(rptr->sr_fd, sout, 3, 0)) < 0) { DEBUGMSGTL (("smux","[var_smux_write] send rollback/commit failed\n")); return SNMP_ERR_GENERR; } reterr = SNMP_ERR_NOERROR; break; /* case Action == COMMIT */ default: break; } return reterr;}intsmux_accept(int sd){ u_char data[SMUXMAXPKTSIZE], *ptr, type; struct sockaddr_in in_socket; struct timeval tv; int fail, fd, alen; size_t length, len; alen = sizeof(struct sockaddr_in); /* this may be too high */ tv.tv_sec = 5; tv.tv_usec = 0; /* connection request */ DEBUGMSGTL (("smux","[smux_accept] Calling accept()\n")); errno = 0; if((fd = accept(sd, (struct sockaddr *)&in_socket, &alen)) < 0) { snmp_log_perror("[smux_accept] accept failed"); return -1; } else { snmp_log(LOG_INFO, "[smux_accept] accepted fd %d from %s:%d\n", fd, inet_ntoa(in_socket.sin_addr), ntohs(in_socket.sin_port)); if (npeers + 1 == SMUXMAXPEERS) { snmp_log (LOG_ERR, "[smux_accept] denied peer on fd %d, limit %d reached", fd, SMUXMAXPEERS); close(sd); return -1; } /* now block for an OpenPDU */ if ((length = recv(fd, (char *)data, SMUXMAXPKTSIZE, 0)) <= 0) { DEBUGMSGTL (("smux","[smux_accept] peer on fd %d died or timed out\n", fd)); close(fd); return -1; } /* try to authorize him */ ptr = data; len = length; if ((ptr = asn_parse_header(ptr, &len, &type)) == NULL) { smux_send_close(fd, SMUXC_PACKETFORMAT); close(fd); DEBUGMSGTL (("smux","[smux_accept] peer on %d sent bad open")); return -1; } else if (type != (u_char)SMUX_OPEN) { smux_send_close(fd, SMUXC_PROTOCOLERROR); close(fd); DEBUGMSGTL (("smux","[smux_accept] peer on %d did not send open: (%d)\n", type)); return -1; } ptr = smux_open_process(fd, ptr, &len, &fail); if (fail) { smux_send_close(fd, SMUXC_AUTHENTICATIONFAILURE); close(fd); DEBUGMSGTL (("smux","[smux_accept] peer on %d failed authentication\n", fd)); return -1; } /* he's OK */#ifdef SO_RCVTIMEO if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)) < 0) { DEBUGMSGTL (("smux","[smux_accept] setsockopt(SO_RCVTIMEO) failed fd %d\n", fd)); snmp_log_perror("smux_accept: setsockopt SO_RCVTIMEO"); }#endif npeers++; DEBUGMSGTL (("smux","[smux_accept] fd %d\n", fd)); /* Process other PDUs already read, e.g. a registerRequest. */ len = length - (ptr - data); if (smux_pdu_process(fd, ptr, len) < 0) { /* Easy come, easy go. Clean-up is already done. */ return -1; } } return fd;}intsmux_process(int fd){ size_t length; u_char data[SMUXMAXPKTSIZE]; length = recv(fd, (char *)data, SMUXMAXPKTSIZE, 0); if (length <= 0) { /* the peer went away, close this descriptor * and delete it from the list */ DEBUGMSGTL (("smux","[smux_process] peer on fd %d died or timed out\n", fd)); smux_peer_cleanup(fd); return -1; } return smux_pdu_process(fd, data, length);}static intsmux_pdu_process(int fd, u_char *data, size_t length){ int error; size_t len; u_char *ptr, type; DEBUGMSGTL (("smux","[smux_pdu_process] Processing %d bytes\n", length)); error = 0; ptr = data; while (error == 0 && ptr != NULL && ptr < data + length) { len = length - (ptr - data); ptr = asn_parse_header(ptr, &len, &type); DEBUGMSGTL (("smux","[smux_pdu_process] type is %d\n", (int) type)); switch (type) { case SMUX_OPEN: smux_send_close(fd, SMUXC_PROTOCOLERROR); DEBUGMSGTL (("smux","[smux_pdu_process] peer on fd %d sent duplicate open?\n", fd)); smux_peer_cleanup(fd); error = -1; break; case SMUX_CLOSE: ptr = smux_close_process(fd, ptr, &len); smux_peer_cleanup(fd); error = -1; break; case SMUX_RREQ: ptr = smux_rreq_process(fd, ptr, &len); break; case SMUX_RRSP: error = -1; smux_send_close(fd, SMUXC_PROTOCOLERROR); smux_peer_cleanup(fd); DEBUGMSGTL (("smux","[smux_pdu_process] peer on fd %d sent RRSP!\n", fd)); break; case SMUX_SOUT: error = -1; smux_send_close(fd, SMUXC_PROTOCOLERROR); smux_peer_cleanup(fd); DEBUGMSGTL (("smux","This shouldn't have happened!\n")); break; case SMUX_TRAP: snmp_log(LOG_INFO, "Got trap from peer on fd %d\n", fd); ptr = smux_trap_process(ptr, &len); /* watch out for close on top of this...should return correct end */ /* debug this... */ ptr = NULL; break; default: smux_send_close(fd, SMUXC_PACKETFORMAT); smux_peer_cleanup(fd); DEBUGMSGTL (("smux","[smux_pdu_process] Wrong type %d\n", (int)type)); error = -1; break; } } return error;}static u_char *smux_open_process(int fd, u_char *ptr, size_t *len, int *fail){ u_char type; long version; oid oid_name[MAX_OID_LEN]; char passwd[SMUXMAXSTRLEN]; char descr[SMUXMAXSTRLEN]; char oid_print[SMUXMAXSTRLEN]; int i; size_t oid_name_len, string_len; if (!(ptr = asn_parse_int(ptr, len, &type, &version, sizeof(version)))) { DEBUGMSGTL (("smux","[smux_open_process] version parse failed\n")); *fail = TRUE; return((ptr += *len)); } DEBUGMSGTL(("smux", "[smux_open_process] version %d, len %d, type %d\n", version, *len, (int)type)); oid_name_len = MAX_OID_LEN; if ((ptr = asn_parse_objid(ptr, len, &type, oid_name, &oid_name_len)) == NULL) { DEBUGMSGTL (("smux","[smux_open_process] oid parse failed\n")); *fail = TRUE; return((ptr += *len)); } sprint_objid(oid_print, oid_name, oid_name_len); if (snmp_get_do_debugging()) { DEBUGMSGTL (("smux","[smux_open_process] smux peer: %s\n", oid_print)); DEBUGMSGTL (("smux","[smux_open_process] len %d, type %d\n", *len, (int)type)); } string_len = SMUXMAXSTRLEN; if ((ptr = asn_parse_string(ptr, len, &type, (u_char *)descr, &string_len)) == NULL) { DEBUGMSGTL (("smux","[smux_open_process] descr parse failed\n")); *fail = TRUE; return((ptr += *len)); } if (snmp_get_do_debugging()) { DEBUGMSGTL (("smux","[smux_open_process] smux peer descr: ")); for (i=0; i < (int)string_len; i++) DEBUGMSG (("smux","%c", descr[i])); DEBUGMSG (("smux","\n")); DEBUGMSGTL (("smux","[smux_open_process] len %d, type %d\n", *len, (int)type)); } descr[string_len] = 0; string_len = SMUXMAXSTRLEN; if ((ptr = asn_parse_string(ptr, len, &type, (u_char *)passwd, &string_len)) == NULL) { DEBUGMSGTL (("smux","[smux_open_process] passwd parse failed\n")); *fail = TRUE; return((ptr += *len)); } if (snmp_get_do_debugging()) { DEBUGMSGTL (("smux","[smux_open_process] smux peer passwd: ")); for (i=0; i < (int)string_len; i++) DEBUGMSG (("smux","%c", passwd[i])); DEBUGMSG (("smux","\n")); DEBUGMSGTL (("smux","[smux_open_process] len %d, type %d\n", *len, (int)type)); } passwd[string_len] = '\0'; if(!smux_auth_peer(oid_name, oid_name_len, passwd, fd)) { snmp_log(LOG_WARNING, "refused smux peer: oid %s, password %s, descr %s\n", oid_print, passwd, descr); *fail = TRUE; return ptr; } snmp_log(LOG_INFO, "accepted smux peer: oid %s, password %s, descr %s\n", oid_print, passwd, descr); *fail = FALSE; return ptr;}static voidsmux_send_close(int fd, int reason){ u_char outpacket[3], *ptr; ptr = outpacket; *(ptr++) = (u_char)SMUX_CLOSE; *(ptr++) = (u_char)1; *ptr = (u_char)(reason & 0xFF); if(snmp_get_do_debugging()) DEBUGMSGTL (("smux","[smux_close] sending close to fd %d, reason %d\n", fd, reason)); /* send a response back */ if (send (fd, (char *)outpacket, 3, 0) < 0) { snmp_log_perror("[smux_snmp_close] send failed"); }} static intsmux_auth_peer(oid *name, size_t namelen, char *passwd, int fd){ int i; for (i = 0; i < nauths; i++) { if (snmp_oid_compare(Auths[i]->sa_oid, Auths[i]->sa_oid_len, name, namelen) == 0) { if(!(strcmp(Auths[i]->sa_passwd, passwd)) && (Auths[i]->sa_active_fd == -1)) { /* matched, mark the auth */ Auths[i]->sa_active_fd = fd; return 1; } else return 0; } } /* did not match oid and passwd */ return 0;}/* * XXX - Bells and Whistles: * Need to catch signal when snmpd goes down and send close pdu to gated */static u_char *smux_close_process(int fd, u_char *ptr, size_t *len){ long down = 0; int length = *len; /* This is the integer part of the close pdu */ while (length--) { down = (down << 8) | (long)*ptr; ptr++; } DEBUGMSGTL (("smux","[smux_close_process] close from peer on fd %d reason %d\n", fd, down)); smux_peer_cleanup(fd); return NULL;}static u_char *smux_rreq_process(int sd, u_char *ptr, size_t *len){ long priority, rpriority; long operation; oid oid_name[MAX_OID_LEN]; size_t oid_name_len; int i, result; u_char type; smux_reg *rptr, *nrptr; oid_name_len = MAX_OID_LEN; ptr = asn_parse_objid(ptr, len, &type, oid_name, &oid_name_len); DEBUGMSGTL(("smux", "[smux_rreq_process] smux subtree: ")); DEBUGMSGOID(("smux", oid_name, oid_name_len)); DEBUGMSG(("smux","\n")); if ((ptr = asn_parse_int(ptr, len, &type, &priority, sizeof(priority))) == NULL) { DEBUGMSGTL (("smux","[smux_rreq_process] priority parse failed\n")); smux_send_rrsp(sd, -1); return NULL; } DEBUGMSGTL (("smux","[smux_rreq_process] priority %d\n", priority)); if ((ptr = asn_parse_int(ptr, len, &type, &operation, sizeof(operation))) == NULL) { DEBUGMSGTL (("smux","[smux_rreq_process] operation parse failed\n")); smux_send_rrsp(sd, -1); return NULL; } DEBUGMSGTL (("smux","[smux_rreq_process] operation %d\n", operation)); if(operation == SMUX_REGOP_DELETE) { /* search the active list for this registration */ rptr = smux_find_match(ActiveRegs, sd, oid_name, oid_name_len, priority); if (rptr) { rpriority = rptr->sr_priority; /* unregister the mib */ unregister_mib(rptr->sr_name, rptr->sr_name_len); /* find a replacement */ nrptr = smux_find_replacement(rptr->sr_name, rptr->sr_name_len); if (nrptr) { /* found one */ smux_replace_active(rptr, nrptr); } else { /* no replacement found */ smux_list_detach(&ActiveRegs, &rptr); free(rptr); } smux_send_rrsp(sd, rpriority); return ptr; } /* search the passive list for this registration */ rptr = smux_find_match(PassiveRegs, sd, oid_name, oid_name_len, priority); if (rptr) { rpriority = rptr->sr_priority; smux_list_detach(&PassiveRegs, &rptr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -