#!/bin/sh # This is `snmp2.04' (part 4 of snmp2). # Do not concatenate these parts, unpack them in order with `/bin/sh'. # File `snmp2/snmplib/snmp_api.c' is being continued... # touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo echo 'WARNING: not restoring timestamps. Consider getting and' echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # if test ! -r _sharseq.tmp; then echo 'Please unpack part 1 first!' exit 1 fi shar_sequence=`cat _sharseq.tmp` if test "$shar_sequence" != 4; then echo "Please unpack part $shar_sequence next!" exit 1 fi if test ! -f _sharnew.tmp; then echo 'x - still skipping snmp2/snmplib/snmp_api.c' else echo 'x - continuing file snmp2/snmplib/snmp_api.c' sed 's/^X//' << 'SHAR_EOF' >> 'snmp2/snmplib/snmp_api.c' && X pdu->context = pdu->contextBuf; X pdu->srcPartyLen = MAX_NAME_LEN; X pdu->dstPartyLen = MAX_NAME_LEN; X pdu->contextLen = MAX_NAME_LEN; X X /* authenticates message and returns length if valid */ X data = snmp_secauth_parse(data, &length, pi, X pdu->srcParty, &pdu->srcPartyLen, X pdu->dstParty, &pdu->dstPartyLen, X pdu->context, &pdu->contextLen, X FIRST_PASS | LAST_PASS); X if (data == NULL) X return -1; X version = pi->version; X } else { X ERROR("unknown auth header type"); X return NULL; X } X pdu->version = version; X X data = asn_parse_header(data, &length, &msg_type); X if (data == NULL) X return -1; X X /* the calling sequence for has_access is wrong - fix it or nuke it XXX */ X /* should the following be for version 2? If so make it so, if not, X * nuke it. X */ X if (version == SNMP_SECURITY_1 X && !has_access(msg_type, pdu->srcParty, pdu->srcPartyLen, X pdu->dstParty, pdu->dstPartyLen)) X return -1; X pdu->command = msg_type; X if (pdu->command != TRP_REQ_MSG){ X data = asn_parse_int(data, &length, &type, &pdu->reqid, X sizeof(pdu->reqid)); X if (data == NULL) X return -1; X data = asn_parse_int(data, &length, &type, &pdu->errstat, X sizeof(pdu->errstat)); X if (data == NULL) X return -1; X data = asn_parse_int(data, &length, &type, &pdu->errindex, X sizeof(pdu->errindex)); X if (data == NULL) X return -1; X } else { X pdu->enterprise_length = MAX_NAME_LEN; X data = asn_parse_objid(data, &length, &type, objid, X &pdu->enterprise_length); X if (data == NULL) X return -1; X pdu->enterprise = (oid *)malloc(pdu->enterprise_length * sizeof(oid)); X bcopy((char *)objid, (char *)pdu->enterprise, X pdu->enterprise_length * sizeof(oid)); X X four = 4; X data = asn_parse_string(data, &length, &type, X (u_char *)&pdu->agent_addr.sin_addr.s_addr, X &four); X if (data == NULL) X return -1; X data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, X sizeof(pdu->trap_type)); X if (data == NULL) X return -1; X data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, X sizeof(pdu->specific_type)); X if (data == NULL) X return -1; X data = asn_parse_unsigned_int(data, &length, &type, &pdu->time, X sizeof(pdu->time)); X if (data == NULL) X return -1; X } X data = asn_parse_header(data, &length, &type); X if (data == NULL) X return -1; X if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) X return -1; X while((int)length > 0){ X if (pdu->variables == NULL){ X if (SavedVars){ X pdu->variables = (struct variable_list *)SavedVars; X vp = SavedVars; X SavedVars = X (struct internal_variable_list *)SavedVars->next_variable; X } else { X vp = (struct internal_variable_list *) X malloc(sizeof(struct internal_variable_list)); X pdu->variables = (struct variable_list *)vp; X } X } else { X if (SavedVars){ X vp->next_variable = (struct variable_list *)SavedVars; X SavedVars = X (struct internal_variable_list *)SavedVars->next_variable; X vp = (struct internal_variable_list *)vp->next_variable; X } else { X vp->next_variable = X (struct variable_list *)malloc(sizeof(struct internal_variable_list)); X vp = (struct internal_variable_list *)vp->next_variable; X } X } X vp->next_variable = NULL; X vp->val.string = NULL; X vp->name = NULL; X vp->name_length = MAX_NAME_LEN; X vp->name = vp->name_loc; X vp->usedBuf = FALSE; X data = snmp_parse_var_op(data, vp->name, &vp->name_length, &vp->type, X &vp->val_len, &var_val, (int *)&length); X if (data == NULL) X return -1; X X len = PACKET_LENGTH; X switch((short)vp->type){ X case ASN_INTEGER: X vp->val.integer = (long *)vp->buf; X vp->usedBuf = TRUE; X vp->val_len = sizeof(long); X asn_parse_int(var_val, &len, &vp->type, X (long *)vp->val.integer, X sizeof(vp->val.integer)); X break; X case COUNTER: X case GAUGE: X case TIMETICKS: X case UINTEGER: X vp->val.integer = (long *)vp->buf; X vp->usedBuf = TRUE; X vp->val_len = sizeof(u_long); X asn_parse_unsigned_int(var_val, &len, &vp->type, X (u_long *)vp->val.integer, X sizeof(vp->val.integer)); X break; X case COUNTER64: X vp->val.counter64 = (struct counter64 *)vp->buf; X vp->usedBuf = TRUE; X vp->val_len = sizeof(struct counter64); X asn_parse_unsigned_int64(var_val, &len, &vp->type, X (struct counter64 *)vp->val.counter64, X sizeof(*vp->val.counter64)); X break; X case ASN_OCTET_STR: X case IPADDRESS: X case OPAQUE: X case NSAP: X if (vp->val_len < 32){ X vp->val.string = (u_char *)vp->buf; X vp->usedBuf = TRUE; X } else { X vp->val.string = (u_char *)malloc((unsigned)vp->val_len); X } X asn_parse_string(var_val, &len, &vp->type, vp->val.string, X &vp->val_len); X break; X case ASN_OBJECT_ID: X vp->val_len = MAX_NAME_LEN; X asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); X vp->val_len *= sizeof(oid); X vp->val.objid = (oid *)malloc((unsigned)vp->val_len); X bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); X break; X case SNMP_NOSUCHOBJECT: X case SNMP_NOSUCHINSTANCE: X case SNMP_ENDOFMIBVIEW: X case ASN_NULL: X break; X case ASN_BIT_STR: X vp->val.bitstring = (u_char *)malloc(vp->val_len); X asn_parse_bitstring(var_val, &len, &vp->type, X vp->val.bitstring, &vp->val_len); X break; X default: X fprintf(stderr, "bad type returned (%x)\n", vp->type); X break; X } X } X return 0; } X /* X * Sends the input pdu on the session after calling snmp_build to create X * a serialized packet. If necessary, set some of the pdu data from the X * session defaults. Add a request corresponding to this pdu to the list X * of outstanding requests on this session, then send the pdu. X * Returns the request id of the generated packet if applicable, otherwise 1. X * On any error, 0 is returned. X * The pdu is freed by snmp_send() unless a failure occured. X */ int snmp_send(session, pdu) X struct snmp_session *session; X struct snmp_pdu *pdu; { X struct session_list *slp; X struct snmp_internal_session *isp = NULL; X u_char packet[PACKET_LENGTH]; X int length = PACKET_LENGTH; X struct request_list *rp; X struct timeval tv; X X for(slp = Sessions; slp; slp = slp->next){ X if (slp->session == session){ X isp = slp->internal; X break; X } X } X if (isp == NULL){ X snmp_errno = SNMPERR_BAD_SESSION; X return 0; X } X if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG X || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG){ X if (pdu->reqid == SNMP_DEFAULT_REQID) X pdu->reqid = ++Reqid; X if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) X pdu->errstat = 0; X if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) X pdu->errindex = 0; X } else if (pdu->command == INFORM_REQ_MSG || pdu->command == TRP2_REQ_MSG){ X if (session->version != SNMP_VERSION_2){ X fprintf(stderr, "Cant send SNMP PDU's in SNMPv2 message.\n"); X snmp_errno = SNMPERR_GENERR;/* Fix this XXXXX */ X return 0; X } X if (pdu->reqid == SNMP_DEFAULT_REQID) X pdu->reqid = ++Reqid; X if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) X pdu->errstat = 0; X if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) X pdu->errindex = 0; X } else if (pdu->command == BULK_REQ_MSG){ X if (pdu->reqid == SNMP_DEFAULT_REQID) X pdu->reqid = ++Reqid; X if (pdu->max_repetitions < 0 || pdu->non_repeaters < 0){ X fprintf(stderr, "Invalid parameters for max_repetitions or non_repeaters\n"); X snmp_errno = SNMPERR_GENERR; /* Fix this XXXXX */ X return 0; X } X X } else { X if (session->version == SNMP_VERSION_2){ X fprintf(stderr, "Cant send old Trap PDU in SNMPv2 message.\n"); X snmp_errno = SNMPERR_GENERR;/* Fix this XXXXX */ X return 0; X } X /* fill in trap defaults */ X pdu->reqid = 1; /* give a bogus non-error reqid for traps */ X if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ X pdu->enterprise = (oid *)malloc(sizeof(DEFAULT_ENTERPRISE)); X bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, X sizeof(DEFAULT_ENTERPRISE)); X pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); X } X if (pdu->time == SNMP_DEFAULT_TIME) X pdu->time = DEFAULT_TIME; X } X if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ X if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ X bcopy((char *)&isp->addr, (char *)&pdu->address, X sizeof(pdu->address)); X } else { X fprintf(stderr, "No remote IP address specified\n"); X snmp_errno = SNMPERR_BAD_ADDRESS; X return 0; X } X } X X /* !!!!!!!!!!!!!!!!!!!!!! MAJOR PROBLEM !!!!!!!!!!!!!!!!!!!!!!! X * X * This stuff needs to be cleanly added to the api. X * currently some applications are passing non-malloc'd data. X * we can't free this stuff because they would get hosed. X * Therefore this is a core leak. X * !!!!!!!!!!!!!!!!!!!!!! MAJOR PROBLEM !!!!!!!!!!!!!!!!!!!!!!! X */ X if (pdu->version == SNMP_DEFAULT_VERSION){ X pdu->version = session->version; X } X if (pdu->version == SNMP_DEFAULT_VERSION){ X fprintf(stderr, "No version specified\n"); X snmp_errno = SNMPERR_BAD_ADDRESS; X return 0; X } X if (pdu->version == SNMP_VERSION_2){ X if (pdu->srcPartyLen == 0){ X if (session->srcPartyLen == 0){ X fprintf(stderr, "No source party specified\n"); X snmp_errno = SNMPERR_BAD_ADDRESS; X return 0; X } X pdu->srcParty = (oid *)malloc(session->srcPartyLen * sizeof(oid)); X bcopy((char *)session->srcParty, (char *)pdu->srcParty, X session->srcPartyLen * sizeof(oid)); X pdu->srcPartyLen = session->srcPartyLen; X } X if (pdu->dstPartyLen == 0){ X if (session->dstPartyLen == 0){ X fprintf(stderr, "No destination party specified\n"); X snmp_errno = SNMPERR_BAD_ADDRESS; X return 0; X } X pdu->dstParty = (oid *)malloc(session->dstPartyLen * sizeof(oid)); X bcopy((char *)session->dstParty, (char *)pdu->dstParty, X session->dstPartyLen * sizeof(oid)); X pdu->dstPartyLen = session->dstPartyLen; X } X if (pdu->contextLen == 0){ X if (session->contextLen == 0){ X fprintf(stderr, "No context specified\n"); X snmp_errno = SNMPERR_BAD_ADDRESS; X return 0; X } X pdu->context = (oid *)malloc(session->contextLen * sizeof(oid)); X bcopy((char *)session->context, (char *)pdu->context, X session->contextLen * sizeof(oid)); X pdu->contextLen = session->contextLen; X } X } else if (pdu->version == SNMP_VERSION_1){ X if (pdu->community_len == 0){ X if (session->community_len == 0){ X fprintf(stderr, "No community name specified\n"); X snmp_errno = SNMPERR_BAD_ADDRESS; X return 0; X } X pdu->community = (u_char *)malloc(session->community_len); X bcopy((char *)session->community, (char *)pdu->community, X session->community_len); X pdu->community_len = session->community_len; X } X } X X if (snmp_build(session, pdu, packet, &length) < 0){ X fprintf(stderr, "Error building packet\n"); X snmp_errno = SNMPERR_GENERR; X return 0; X } X if (snmp_dump_packet){ X printf("sending %d bytes to %s:\n", length, X inet_ntoa(pdu->address.sin_addr)); X xdump(packet, length, ""); X printf("\n\n"); X } X X X if (sendto(isp->sd, (char *)packet, length, 0, X (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ X perror("sendto"); X snmp_errno = SNMPERR_GENERR; X return 0; X } /* gettimeofday(&tv, (struct timezone *)0); */ X tv = Now; X if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG X || pdu->command == SET_REQ_MSG || pdu->command == BULK_REQ_MSG X || pdu->command == INFORM_REQ_MSG){ X /* set up to expect a response */ X rp = (struct request_list *)malloc(sizeof(struct request_list)); X if (isp->requestsEnd){ X rp->next_request = isp->requestsEnd->next_request; X isp->requestsEnd->next_request = rp; X isp->requestsEnd = rp; X } else { X rp->next_request = isp->requests; X isp->requests = rp; X isp->requestsEnd = rp; X } X rp->pdu = pdu; X rp->request_id = pdu->reqid; X X rp->retries = 1; X rp->timeout = session->timeout; X rp->time = tv; X tv.tv_usec += rp->timeout; X tv.tv_sec += tv.tv_usec / 1000000L; X tv.tv_usec %= 1000000L; X rp->expire = tv; X } X return pdu->reqid; } X /* X * Frees the pdu and any malloc'd data associated with it. X */ void snmp_free_pdu(pdu) X struct snmp_pdu *pdu; { X struct variable_list *vp, *ovp; X X vp = pdu->variables; X while(vp){ X if (vp->name) X free((char *)vp->name); X if (vp->val.string) X free((char *)vp->val.string); X ovp = vp; X vp = vp->next_variable; X free((char *)ovp); X } X if (pdu->enterprise) X free((char *)pdu->enterprise); X free((char *)pdu); } X X /* X * Frees the pdu and any malloc'd data associated with it. X */ void snmp_free_internal_pdu(pdu) X struct snmp_pdu *pdu; { X struct internal_variable_list *vp, *ovp; X X vp = (struct internal_variable_list *)pdu->variables; X while(vp){ X if (vp->val.string && !vp->usedBuf) X free((char *)vp->val.string); X ovp = vp; X vp = (struct internal_variable_list *)vp->next_variable; X ovp->next_variable = (struct variable_list *)SavedVars; X SavedVars = ovp; X } X if (pdu->enterprise) X free((char *)pdu->enterprise); X if (!SavedPdu) X SavedPdu = pdu; X else X free((char *)pdu); X } X X /* X * Checks to see if any of the fd's set in the fdset belong to X * snmp. Each socket with it's fd set has a packet read from it X * and snmp_parse is called on the packet received. The resulting pdu X * is passed to the callback routine for that session. If the callback X * routine returns successfully, the pdu and it's request are deleted. X */ void snmp_read(fdset) X fd_set *fdset; { X struct session_list *slp; X struct snmp_session *sp; X struct snmp_internal_session *isp; X u_char packet[PACKET_LENGTH]; X struct sockaddr_in from; X int length, fromlength; X struct snmp_pdu *pdu; X struct request_list *rp, *orp; X X for(slp = Sessions; slp; slp = slp->next){ X if (FD_ISSET(slp->internal->sd, fdset)){ X sp = slp->session; X isp = slp->internal; X fromlength = sizeof from; X length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, X (struct sockaddr *)&from, &fromlength); X if (length == -1) X perror("recvfrom"); X if (snmp_dump_packet){ X printf("received %d bytes from %s:\n", length, X inet_ntoa(from.sin_addr)); X xdump(packet, length, ""); X printf("\n\n"); X } X X if (SavedPdu){ X pdu = SavedPdu; X SavedPdu = NULL; X } else { X pdu = (struct snmp_pdu *)malloc(sizeof(struct internal_snmp_pdu)); X } X pdu->address = from; X pdu->reqid = 0; X pdu->variables = NULL; X pdu->enterprise = NULL; X pdu->enterprise_length = 0; X if (snmp_parse(sp, pdu, packet, length) != SNMP_ERR_NOERROR){ X fprintf(stderr, "Unrecognizable or unauthentic packet received\n"); X snmp_free_internal_pdu(pdu); X return; X } X X if (pdu->command == GET_RSP_MSG){ X for(rp = isp->requests; rp; rp = rp->next_request){ X if (rp->request_id == pdu->reqid){ X if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, X pdu, sp->callback_magic) == 1){ X /* successful, so delete request */ X orp = rp; X if (isp->requests == orp){ X /* first in list */ X isp->requests = orp->next_request; X if (isp->requestsEnd == orp) X isp->requestsEnd = NULL; X } else { X for(rp = isp->requests; rp; X rp = rp->next_request){ X if (rp->next_request == orp){ X if (isp->requestsEnd == orp) X isp->requestsEnd = rp; X /* check logic ^^^: is this the X new "end"? XXX */ X /* link around it */ X rp->next_request = orp->next_request; X break; X } X } X } X snmp_free_pdu(orp->pdu); X free((char *)orp); X /* there shouldn't be any more requests with the X same reqid */ X break; X } X } X } X } else if (pdu->command == GET_REQ_MSG X || pdu->command == GETNEXT_REQ_MSG X || pdu->command == TRP_REQ_MSG X || pdu->command == SET_REQ_MSG X || pdu->command == BULK_REQ_MSG X || pdu->command == INFORM_REQ_MSG X || pdu->command == TRP2_REQ_MSG){ X sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, X sp->callback_magic); X } X snmp_free_internal_pdu(pdu); X } X } } X /* X * Returns info about what snmp requires from a select statement. X * numfds is the number of fds in the list that are significant. X * All file descriptors opened for SNMP are OR'd into the fdset. X * If activity occurs on any of these file descriptors, snmp_read X * should be called with that file descriptor set X * X * The timeout is the latest time that SNMP can wait for a timeout. The X * select should be done with the minimum time between timeout and any other X * timeouts necessary. This should be checked upon each invocation of select. X * If a timeout is received, snmp_timeout should be called to check if the X * timeout was for SNMP. (snmp_timeout is idempotent) X * X * Block is 1 if the select is requested to block indefinitely, rather than X * time out. X * If block is input as 1, the timeout value will be treated as undefined, X * but it must be available for setting in snmp_select_info. On return, if X * block is true, the value of timeout will be undefined. X * X * snmp_select_info returns the number of open sockets. (i.e. The number of X * sessions open) X */ int snmp_select_info(numfds, fdset, timeout, block) X int *numfds; X fd_set *fdset; X struct timeval *timeout; X int *block; /* should the select block until input arrives X (i.e. no input) */ { X struct session_list *slp; X struct snmp_internal_session *isp; X struct request_list *rp; X struct timeval now, earliest; X int active = 0, requests = 0; X X timerclear(&earliest); X /* X * For each request outstanding, add it's socket to the fdset, X * and if it is the earliest timeout to expire, mark it as lowest. X */ X for(slp = Sessions; slp; slp = slp->next){ X active++; X isp = slp->internal; X if ((isp->sd + 1) > *numfds) X *numfds = (isp->sd + 1); X FD_SET(isp->sd, fdset); X if (isp->requests){ X /* found another session with outstanding requests */ X requests++; X for(rp = isp->requests; rp; rp = rp->next_request){ X if (!timerisset(&earliest) X || timercmp(&rp->expire, &earliest, <)) X earliest = rp->expire; X } X } X } X if (requests == 0) /* if none are active, skip arithmetic */ X return active; X X /* X * Now find out how much time until the earliest timeout. This X * transforms earliest from an absolute time into a delta time, the X * time left until the select should timeout. X */ X gettimeofday(&now, (struct timezone *)0); X Now = now; X earliest.tv_sec--; /* adjust time to make arithmetic easier */ X earliest.tv_usec += 1000000L; X earliest.tv_sec -= now.tv_sec; X earliest.tv_usec -= now.tv_usec; X while (earliest.tv_usec >= 1000000L){ X earliest.tv_usec -= 1000000L; X earliest.tv_sec += 1; X } X if (earliest.tv_sec < 0){ X earliest.tv_sec = 0; X earliest.tv_usec = 0; X } X X /* if it was blocking before or our delta time is less, reset timeout */ X if (*block == 1 || timercmp(&earliest, timeout, <)){ X *timeout = earliest; X *block = 0; X } X return active; } X /* X * snmp_timeout should be called whenever the timeout from snmp_select_info X * expires, but it is idempotent, so snmp_timeout can be polled (probably a X * cpu expensive proposition). snmp_timeout checks to see if any of the X * sessions have an outstanding request that has timed out. If it finds one X * (or more), and that pdu has more retries available, a new packet is formed X * from the pdu and is resent. If there are no more retries available, the X * callback for the session is used to alert the user of the timeout. X */ void snmp_timeout(){ X struct session_list *slp; X struct snmp_session *sp; X struct snmp_internal_session *isp; X struct request_list *rp, *orp, *freeme = NULL; X struct timeval now; X X gettimeofday(&now, (struct timezone *)0); X /* X * For each request outstanding, check to see if it has expired. X */ X for(slp = Sessions; slp; slp = slp->next){ X sp = slp->session; X isp = slp->internal; X orp = NULL; X for(rp = isp->requests; rp; rp = rp->next_request){ X if (freeme != NULL){ X /* frees rp's after the for loop goes on to the next_request */ X free((char *)freeme); X freeme = NULL; X } X if (timercmp(&rp->expire, &now, <)){ X /* this timer has expired */ X if (rp->retries >= sp->retries){ X /* No more chances, delete this entry */ X sp->callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, X sp->callback_magic); X if (orp == NULL){ X isp->requests = rp->next_request; X if (isp->requestsEnd == rp) X isp->requestsEnd = NULL; X } else { X orp->next_request = rp->next_request; X if (isp->requestsEnd == rp) X isp->requestsEnd = rp->next_request; X /* check logic ^^^: is this the new "end"? XXX */ X } X snmp_free_pdu(rp->pdu); X freeme = rp; X continue; /* don't update orp below */ X } else { X u_char packet[PACKET_LENGTH]; X int length = PACKET_LENGTH; X struct timeval tv; X X /* retransmit this pdu */ X rp->retries++; X if (rp->retries > 3) X rp->timeout <<= 1; X if (rp->timeout > 30000000L) X rp->timeout = 30000000L; X if (snmp_build(sp, rp->pdu, packet, &length) < 0){ X fprintf(stderr, "Error building packet\n"); X } X if (snmp_dump_packet){ X printf("sending %d bytes to %s:\n", length, X inet_ntoa(rp->pdu->address.sin_addr)); X xdump(packet, length, ""); X printf("\n\n"); X } X if (sendto(isp->sd, (char *)packet, length, 0, X (struct sockaddr *)&rp->pdu->address, X sizeof(rp->pdu->address)) < 0){ X perror("sendto"); X } X tv = now; X rp->time = tv; X tv.tv_usec += rp->timeout; X tv.tv_sec += tv.tv_usec / 1000000L; X tv.tv_usec %= 1000000L; X rp->expire = tv; X } X } X orp = rp; X } X if (freeme != NULL){ X free((char *)freeme); X freeme = NULL; X } X } } SHAR_EOF echo 'File snmp2/snmplib/snmp_api.c is complete' && $shar_touch -am 1015123593 'snmp2/snmplib/snmp_api.c' && chmod 0644 'snmp2/snmplib/snmp_api.c' || echo 'restore of snmp2/snmplib/snmp_api.c failed' shar_count="`wc -c < 'snmp2/snmplib/snmp_api.c'`" test 41889 -eq "$shar_count" || echo "snmp2/snmplib/snmp_api.c: original size 41889, current size $shar_count" rm -f _sharnew.tmp fi # ============= snmp2/snmplib/snmp_auth.c ============== if test -f 'snmp2/snmplib/snmp_auth.c' && test X"$1" != X"-c"; then echo 'x - skipping snmp2/snmplib/snmp_auth.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting snmp2/snmplib/snmp_auth.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'snmp2/snmplib/snmp_auth.c' && /* X * snmp_auth.c - X * Authentication for SNMP (RFC 1067). This implements a null X * authentication layer. X * X * X */ /********************************************************************** X Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University X X All Rights Reserved X Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of CMU not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. X CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ X #ifdef KINETICS #include "gw.h" #include "fp4/cmdmacro.h" #endif X #if (defined(unix) && !defined(KINETICS)) #include #include #include #ifndef NULL #define NULL 0 #endif #endif X #ifdef vms #include #endif X #ifdef VXWORKS #include "VXtypes.h" #include "VXtime.h" #endif X #include "asn1.h" #include "snmp.h" #include "snmp_impl.h" #include "party.h" #include "context.h" #include "md5.h" #include "acl.h" X X /* this should be set to TRUE for machines that use network byte ordering, ** and FALSE for machines that byte swap. */ #define LOWBYTEFIRST FALSE X u_char * snmp_auth_parse(data, length, sid, slen, version) u_char *data; int *length; u_char *sid; int *slen; long *version; { X u_char type; X X data = asn_parse_header(data, length, &type); X if (data == NULL){ X ERROR("bad header"); X return NULL; X } X if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)){ X ERROR("wrong auth header type"); X return NULL; X } X data = asn_parse_int(data, length, &type, version, sizeof(*version)); X if (data == NULL){ X ERROR("bad parse of version"); X return NULL; X } X data = asn_parse_string(data, length, &type, sid, slen); X if (data == NULL){ X ERROR("bad parse of community"); X return NULL; X } X sid[*slen] = '\0'; X return (u_char *)data; } X u_char * snmp_secauth_parse(data, length, pi, srcParty, srcPartyLength, X dstParty, dstPartyLength, context, contextLength, pass) u_char *data; int *length; struct packet_info *pi; oid *srcParty, *dstParty, *context; int *srcPartyLength, *dstPartyLength, *contextLength; int pass; { X u_char type; X oid dstParty2[64]; X int dstParty2Length = 64, authMsgLen, authMsgInternalLen; X u_long authSrcTimeStamp, authDstTimeStamp; X u_char authDigest[16], digest[16]; X int authDigestLen; X u_char *authMsg, *digestStart, *digestEnd; X struct partyEntry *srcp, *dstp; X struct contextEntry *cxp; X int biglen, ismd5 = 0; X struct timeval now; X X data = asn_parse_header(data, length, &type); X if (data == NULL){ X ERROR("bad header"); X return NULL; X } X if (type != (ASN_CONTEXT | ASN_CONSTRUCTOR | 1)){ X ERROR("wrong auth header type"); X return NULL; X } X data = asn_parse_objid(data, length, &type, dstParty, dstPartyLength); X if (data == NULL){ X ERROR("bad parse of dstParty"); X return NULL; X } X dstp = party_getEntry(dstParty, *dstPartyLength); X if (!dstp){ X printf("Unknown destination party: "); X print_objid(dstParty, *dstPartyLength); X return NULL; X } X pi->dstp = dstp; X /* check to see if TDomain and TAddr match here. X * If they don't, discard the packet X * This might be best handled by adding a user-supplied X * function to the API that would validate the address. X */ X X data = asn_parse_header(data, length, &type); X if (data == NULL || type != (ASN_CONTEXT | 1)){ X ERROR("bad parse of privData"); X return NULL; X } X authMsg = data; X data = asn_parse_header(data, length, &type); X if (data == NULL || type != (ASN_CONTEXT | ASN_CONSTRUCTOR | 1)){ X ERROR("bad parse of snmpAuthMsg (DES decode probably failed!)"); X return NULL; X } X authMsgLen = *length + data - authMsg; X authMsgInternalLen = *length; X data = asn_parse_header(data, &authMsgInternalLen, &type); X if (data == NULL){ X ERROR("bad parse of snmpAuthMsg"); X return NULL; X } X if (type == (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)){ X /* noAuth */ X pi->version = SNMP_VERSION_2; X X } else if (type == (ASN_CONTEXT | ASN_CONSTRUCTOR | 2)){ X /* AuthInformation */ X pi->version = SNMP_VERSION_2; X ismd5 = 1; X X digestStart = data; X authDigestLen = sizeof(authDigest); X data = asn_parse_string(data, length, &type, authDigest, X &authDigestLen); X if (data == NULL){ X ERROR("Digest"); X return NULL; X } X digestEnd = data; X X data = asn_parse_unsigned_int(data, length, &type, &authDstTimeStamp, X sizeof(authDstTimeStamp)); X if (data == NULL){ X ERROR("DstTimeStamp"); X return NULL; X } X X data = asn_parse_unsigned_int(data, length, &type, &authSrcTimeStamp, X sizeof(authSrcTimeStamp)); X if (data == NULL){ X ERROR("SrcTimeStamp"); X return NULL; X } X } else { X ERROR("Bad format for authData"); X return NULL; X } X data = asn_parse_header(data, length, &type); X if (data == NULL){ X ERROR("bad parse of snmpMgmtCom"); X return NULL; X } X data = asn_parse_objid(data, length, &type, dstParty2, &dstParty2Length); X if (data == NULL){ X ERROR("bad parse of dstParty"); X return NULL; X } X data = asn_parse_objid(data, length, &type, srcParty, srcPartyLength); X if (data == NULL){ X ERROR("bad parse of srcParty"); X printf("Source party: "); X print_objid(srcParty, *srcPartyLength); X return NULL; X } X data = asn_parse_objid(data, length, &type, context, contextLength); X if (data == NULL){ X ERROR("bad parse of context"); X printf("Context: "); X print_objid(context, *contextLength); X return NULL; X } X if (*dstPartyLength != dstParty2Length X || bcmp((char *)dstParty, (char *)dstParty2, dstParty2Length)){ X ERROR("Mismatch of destination parties\n"); X return NULL; X } X X srcp = party_getEntry(srcParty, *srcPartyLength); X if (!srcp) X return NULL; X pi->srcp = srcp; X X cxp = context_getEntry(context, *contextLength); X if (!cxp) X return NULL; X pi->cxp = cxp; X X /* Only perform the following authentication checks if this is the X * first time called for this packet. X */ X if (srcp->partyAuthProtocol == SNMPV2MD5AUTHPROT X && pi->version != SNMP_VERSION_2) X return NULL; X if ((pass & FIRST_PASS) && (srcp->partyAuthProtocol == SNMPV2MD5AUTHPROT)){ X /* RFC1446, Pg 18, 3.2.1 */ X if (!ismd5){ X /* snmpStatsBadAuths++ */ X return NULL; X } X X gettimeofday(&now, (struct timezone *)0); X srcp->partyAuthClock = now.tv_sec - srcp->tv.tv_sec; X dstp->partyAuthClock = now.tv_sec - dstp->tv.tv_sec; X /* RFC1446, Pg 18, 3.2.3 */ X if (authSrcTimeStamp + srcp->partyAuthLifetime < srcp->partyAuthClock){ X ERROR("Late message"); X /* snmpStatsNotInLifetimes */ X return NULL; X } X X /* RFC1446, Pg 18, 3.2.5 */ X biglen = 5000; X if (digestEnd != asn_build_string(digestStart, &biglen, X (u_char)(ASN_UNIVERSAL X | ASN_PRIMITIVE X | ASN_OCTET_STR), X srcp->partyAuthPrivate, X srcp->partyAuthPrivateLen)){ X ERROR("couldn't stuff digest"); X return NULL; X } X md5Digest(authMsg, authMsgLen, digest); X X /* RFC1446, Pg 19, 3.2.6 */ X if (authDigestLen != 16 || bcmp(authDigest, digest, 16)){ X ERROR("unauthentic"); X /* snmpStatsWrongDigestValues++ */ X return NULL; X } X /* As per RFC1446, Pg 19, 3.2.7, the message is authentic */ X X biglen = 5000; X if (digestEnd != asn_build_string(digestStart, &biglen, X (u_char)(ASN_UNIVERSAL X | ASN_PRIMITIVE X | ASN_OCTET_STR), X authDigest, 16)){ X ERROR("couldn't stuff digest back"); X return NULL; X } X X /* Now that we know the message is authentic, update X * the lastTimeStamp. X * As per RFC1446, Pg 19, 3.2.8, we should check that there is an X * acl. X */ X /* RFC1446, Pg 19, 3.2.8 */ X if (srcp->partyAuthClock < authSrcTimeStamp){ X srcp->partyAuthClock = authSrcTimeStamp; X gettimeofday(&srcp->tv, (struct timezone *)0); X srcp->tv.tv_sec -= srcp->partyAuthClock; X } X if (dstp->partyAuthClock < authDstTimeStamp){ X dstp->partyAuthClock = authDstTimeStamp; X gettimeofday(&dstp->tv, (struct timezone *)0); X dstp->tv.tv_sec -= dstp->partyAuthClock; X } X } else if ((pass & FIRST_PASS) && dstp->partyPrivProtocol == DESPRIVPROT){ X /* noAuth and desPriv */ X ERROR("noAuth and desPriv"); X return NULL; X } X return data; } X u_char * snmp_auth_build(data, length, sid, slen, version, messagelen) X u_char *data; X int *length; X u_char *sid; X int *slen; X long *version; X int messagelen; { X data = asn_build_sequence(data, length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), messagelen + *slen + 5); X if (data == NULL){ X ERROR("buildheader"); X return NULL; X } X data = asn_build_int(data, length, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), X (long *)version, sizeof(*version)); X if (data == NULL){ X ERROR("buildint"); X return NULL; X } X data = asn_build_string(data, length, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), X sid, *slen); X if (data == NULL){ X ERROR("buildstring"); X return NULL; X } X return (u_char *)data; } X X u_char * snmp_secauth_build(data, length, pi, messagelen, srcParty, srcPartyLen, X dstParty, dstPartyLen, context, contextLen, X packet_len, pass) X u_char *data; X int *length; X struct packet_info *pi; X int messagelen; X oid *srcParty; X int srcPartyLen; X oid *dstParty; X int dstPartyLen; X oid *context; X int contextLen; X int *packet_len; /* OUT - length of complete packet */ X int pass; /* FIRST_PASS, LAST_PASS, none, or both */ { X struct partyEntry *srcp, *dstp; X struct timeval now; X u_char *cp, *cp1, *block, *endOfPacket; X int dummyLength, count; X u_char key[8], iv[8]; /* initialization vector */ X u_char *digestStart = NULL, *digestEnd, *authMsgStart; X u_char authDigest[16]; X static struct partyEntry *lastParty = NULL; X u_char *h1, *h2, *h3, *h4, *h5; X int pad; X int authInfoSize; X X X srcp = pi->srcp; X dstp = pi->dstp; X if (!srcp || !dstp){ X srcp = party_getEntry(srcParty, srcPartyLen); X if (!srcp) X return NULL; X dstp = party_getEntry(dstParty, dstPartyLen); X if (!dstp) X return NULL; X pi->srcp = srcp; X pi->dstp = dstp; X } X if (srcp->partyAuthProtocol == SNMPV2MD5AUTHPROT){ X if (pass & FIRST_PASS){ X /* get timestamp now because they are needed for the X * length predictions. X */ X gettimeofday(&now, (struct timezone *)0); X srcp->partyAuthClock = now.tv_sec - srcp->tv.tv_sec; X } X /* What if we don't actually send the message? Are we now X * out of sync due to the above line? Answer: No, this X * is just like dropping a packet, except that it is dropped X * due to some error detected in the software protocol layers X * between here and the network. X */ X } else { X /* Don't send noAuth/desPriv. User interface should check for X * this so that it can give a reasonable error message X */ X if (dstp->partyPrivProtocol == DESPRIVPROT) X return NULL; X } X h1 = data; X data = asn_build_sequence(data, length, X (u_char)(ASN_CONTEXT | ASN_CONSTRUCTOR | 1), 0); X if (data == NULL){ X ERROR("build_header2"); X return NULL; X } X data = asn_build_objid(data, length, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), dstParty, dstPartyLen); X if (data == NULL){ X ERROR("build_objid"); X return NULL; X } X h2 = data; X data = asn_build_sequence(data, length, X (u_char)(ASN_CONTEXT | 1), 0); X if (data == NULL){ X ERROR("build_header2"); X return NULL; X } X authMsgStart = data; X data = asn_build_sequence(data, length, X (u_char)(ASN_CONTEXT | ASN_CONSTRUCTOR | 1), 0); X if (data == NULL){ X ERROR("build_header2"); X return NULL; X } X if (srcp->partyAuthProtocol == SNMPV2MD5AUTHPROT){ X h3 = data; X data = asn_build_sequence(data, length, X (u_char)(ASN_CONTEXT |ASN_CONSTRUCTOR | 2), X 0); X if (data == NULL){ X ERROR("build_header2"); X return NULL; X } X X digestStart = data; X data = asn_build_string(data, length, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE X | ASN_OCTET_STR), X srcp->partyAuthPrivate, X srcp->partyAuthPrivateLen); X if (data == NULL){ X ERROR("build_string"); X return NULL; X } X digestEnd = data; X X data = asn_build_unsigned_int(data, length, X (u_char)(UINTEGER), X &dstp->partyAuthClock, X sizeof(dstp->partyAuthClock)); X if (data == NULL){ X ERROR("build_unsigned_int"); X return NULL; X } X X data = asn_build_unsigned_int(data, length, X (u_char)(UINTEGER), X &srcp->partyAuthClock, X sizeof(srcp->partyAuthClock)); X if (data == NULL){ X ERROR("build_unsigned_int"); X return NULL; X } X authInfoSize = data - digestStart; X } else { X data = asn_build_string(data, length, (u_char)(ASN_UNIVERSAL X | ASN_PRIMITIVE X | ASN_OCTET_STR), X (u_char *)"", 0); X if (data == NULL){ X ERROR("build_string"); X return NULL; X } X } X h5 = data; X data = asn_build_sequence(data, length, X (u_char)(ASN_CONTEXT | ASN_CONSTRUCTOR | 2), X 0); X if (data == NULL){ X ERROR("build_header2"); X return NULL; X } X data = asn_build_objid(data, length, X (u_char)(ASN_UNIVERSAL X | ASN_PRIMITIVE | ASN_OBJECT_ID), X dstParty, dstPartyLen); X if (data == NULL){ X ERROR("build_objid"); X return NULL; X } X data = asn_build_objid(data, length, X (u_char)(ASN_UNIVERSAL X | ASN_PRIMITIVE | ASN_OBJECT_ID), X srcParty, srcPartyLen); X if (data == NULL){ X ERROR("build_objid"); X return NULL; X } X data = asn_build_objid(data, length, X (u_char)(ASN_UNIVERSAL X | ASN_PRIMITIVE | ASN_OBJECT_ID), X context, contextLen); X if (data == NULL){ X ERROR("build_objid"); X return NULL; X } X endOfPacket = data; X /* if not last pass, skip md5 and des computation */ X if (!(pass & LAST_PASS)) X return (u_char *)endOfPacket; X X pad = 0; X *packet_len = (endOfPacket - h1) + messagelen + pad; X asn_build_sequence(h1, length, (u_char)(ASN_CONTEXT | ASN_CONSTRUCTOR | 1), X (endOfPacket - h1) + messagelen + pad - 4); X X asn_build_sequence(h2, length, (u_char)(ASN_CONTEXT | 1), X (endOfPacket - h2) + messagelen + pad - 4); X X asn_build_sequence(authMsgStart, length, X (u_char)(ASN_CONTEXT | ASN_CONSTRUCTOR | 1), X (endOfPacket - authMsgStart) + messagelen - 4); X X if (srcp->partyAuthProtocol == SNMPV2MD5AUTHPROT){ X asn_build_sequence(h3, length, X (u_char)(ASN_CONTEXT |ASN_CONSTRUCTOR | 2), X authInfoSize); X } X asn_build_sequence(h5, length, X (u_char)(ASN_CONTEXT | ASN_CONSTRUCTOR | 2), X (endOfPacket - h5) + messagelen - 4); X X /* if it isn't MD5, we'll never do DES, so we're done */ X if (srcp->partyAuthProtocol != SNMPV2MD5AUTHPROT) X return (u_char *)endOfPacket; /* xdump(srcp->partyAuthPrivate, 16, "authPrivate: "); */ X md5Digest(authMsgStart, (endOfPacket - authMsgStart) + messagelen, X authDigest); X dummyLength = 5000; X data = asn_build_string(digestStart, &dummyLength, X (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE X | ASN_OCTET_STR), X authDigest, sizeof(authDigest)); X if (data != digestEnd){ X ERROR("stuffing digest"); X return NULL; X } X return (u_char *)endOfPacket; } X md5Digest(start, length, digest) X u_char *start; X int length; X u_char *digest; { X u_char *buf, *cp; X MDstruct MD; X int i, j; #if (LOWBYTEFIRST == FALSE) X static u_char buffer[SNMP_MAX_LEN]; #endif X #if 0 X int count, sum; X X sum = 0; X for(count = 0; count < length; count++) X sum += start[count]; X printf("sum %d (%d)\n", sum, length); #endif X #if LOWBYTEFIRST X /* do the computation in place */ X cp = start; #else X /* do the computation in a static array */ X cp = buf = buffer; X bcopy((char *)start, buf, length); #endif X X MDbegin(&MD); X while(length >= 64){ X MDupdate(&MD, cp, 64 * 8); X cp += 64; X length -= 64; X } X MDupdate(&MD, cp, length * 8); /* MDprint(&MD); */ X for (i=0;i<4;i++) X for (j=0;j<32;j=j+8) X *digest++ = (MD.buffer[i]>>j) & 0xFF; } X int has_access(msg_type, target, subject, resources) X u_char msg_type; X int target, subject, resources; { X struct aclEntry *ap; X X ap = acl_getEntry(target, subject, resources); X if (!ap) X return 0; X if (ap->aclPriveleges & (1 << (msg_type & 0x1F))) X return 1; X return 0; } X SHAR_EOF $shar_touch -am 1015123593 'snmp2/snmplib/snmp_auth.c' && chmod 0644 'snmp2/snmplib/snmp_auth.c' || echo 'restore of snmp2/snmplib/snmp_auth.c failed' shar_count="`wc -c < 'snmp2/snmplib/snmp_auth.c'`" test 17385 -eq "$shar_count" || echo "snmp2/snmplib/snmp_auth.c: original size 17385, current size $shar_count" rm -f _sharnew.tmp fi # ============= snmp2/snmplib/snmp_client.c ============== if test -f 'snmp2/snmplib/snmp_client.c' && test X"$1" != X"-c"; then echo 'x - skipping snmp2/snmplib/snmp_client.c (file already exists)' rm -f _sharnew.tmp else > _sharnew.tmp echo 'x - extracting snmp2/snmplib/snmp_client.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'snmp2/snmplib/snmp_client.c' && /* X * snmp_client.c - a toolkit of common functions for an SNMP client. X * X */ /********************************************************************** X Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University X X All Rights Reserved X Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of CMU not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. X CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ #include #ifndef VXWORKS #include #endif #include #include X #ifdef VXWORKS #include "VXtime.h" #else #include #endif X #include X #include "asn1.h" #include "snmp.h" #include "snmp_impl.h" #include "snmp_api.h" #include "snmp_client.h" #include "party.h" #include "context.h" #include "view.h" #include "acl.h" X #ifndef BSD4_3 #define BSD4_2 #endif X #ifndef FD_SET X typedef long fd_mask; #define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ X #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) #endif X X extern int errno; struct synch_state snmp_synch_state; X struct snmp_pdu * snmp_pdu_create(command) X int command; { X struct snmp_pdu *pdu; X X pdu = (struct snmp_pdu *)malloc(sizeof(struct snmp_pdu)); X bzero((char *)pdu, sizeof(struct snmp_pdu)); X pdu->version = SNMP_DEFAULT_VERSION; X pdu->srcPartyLen = 0; X pdu->dstPartyLen = 0; X pdu->community_len = 0; X pdu->command = command; X pdu->errstat = SNMP_DEFAULT_ERRSTAT; X pdu->errindex = SNMP_DEFAULT_ERRINDEX; X pdu->address.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; X pdu->enterprise = NULL; X pdu->enterprise_length = 0; X pdu->variables = NULL; X return pdu; } X /* X * Add a null variable with the requested name to the end of the list of X * variables for this pdu. X */ snmp_add_null_var(pdu, name, name_length) X struct snmp_pdu *pdu; X oid *name; X int name_length; { X struct variable_list *vars; X X if (pdu->variables == NULL){ X pdu->variables = vars = (struct variable_list *)malloc(sizeof(struct variable_list)); X } else { X for(vars = pdu->variables; vars->next_variable; vars = vars->next_variable) X /*EXIT*/; X vars->next_variable = (struct variable_list *)malloc(sizeof(struct variable_list)); X vars = vars->next_variable; X } X X vars->next_variable = NULL; X vars->name = (oid *)malloc(name_length * sizeof(oid)); X bcopy((char *)name, (char *)vars->name, name_length * sizeof(oid)); X vars->name_length = name_length; X vars->type = ASN_NULL; X vars->val.string = NULL; X vars->val_len = 0; } X snmp_synch_input(op, session, reqid, pdu, magic) X int op; X struct snmp_session *session; X int reqid; X struct snmp_pdu *pdu; X void *magic; { X struct variable_list *var, *newvar; X struct synch_state *state = (struct synch_state *)magic; X struct snmp_pdu *newpdu; X X if (reqid != state->reqid) X return 0; X state->waiting = 0; X if (op == RECEIVED_MESSAGE && pdu->command == GET_RSP_MSG){ X /* clone the pdu */ X state->pdu = newpdu = (struct snmp_pdu *)malloc(sizeof(struct snmp_pdu)); X bcopy((char *)pdu, (char *)newpdu, sizeof(struct snmp_pdu)); X newpdu->variables = 0; X var = pdu->variables; X if (var != NULL){ X newpdu->variables = newvar = (struct variable_list *)malloc(sizeof(struct variable_list)); X bcopy((char *)var, (char *)newvar, sizeof(struct variable_list)); X if (var->name != NULL){ X newvar->name = (oid *)malloc(var->name_length * sizeof(oid)); X bcopy((char *)var->name, (char *)newvar->name, var->name_length * sizeof(oid)); X } X if (var->val.string != NULL){ X newvar->val.string = (u_char *)malloc(var->val_len); X bcopy((char *)var->val.string, (char *)newvar->val.string, var->val_len); X } X newvar->next_variable = 0; X while(var->next_variable){ X newvar->next_variable = (struct variable_list *)malloc(sizeof(struct variable_list)); X var = var->next_variable; X newvar = newvar->next_variable; X bcopy((char *)var, (char *)newvar, sizeof(struct variable_list)); X if (var->name != NULL){ X newvar->name = (oid *)malloc(var->name_length * sizeof(oid)); X bcopy((char *)var->name, (char *)newvar->name, var->name_length * sizeof(oid)); X } X if (var->val.string != NULL){ X newvar->val.string = (u_char *)malloc(var->val_len); X bcopy((char *)var->val.string, (char *)newvar->val.string, var->val_len); SHAR_EOF : || echo 'restore of snmp2/snmplib/snmp_client.c failed' fi echo 'End of snmp2 part 4' echo 'File snmp2/snmplib/snmp_client.c is continued in part 5' echo 5 > _sharseq.tmp exit 0