📄 sendntfy.c
字号:
retrans = next_retrans) { next_retrans = &(*retrans)->next; /* We're checking for four things: * 1. Blocks marked with an EXPIRED or ACKED flag * 2. New blocks that have completely expired * 3. Blocks that need to be retransmitted. * 4. Blocks that are sending probes that now have valid sec_ids. */ if ((*retrans)->flags & (SNMP_RETRANS_FLAGS_EXPIRED | SNMP_RETRANS_FLAGS_ACKNOWLEDGED)) { if ((*retrans)->ref_cnt == 0) { /* safe to delete at this point */ (*retrans)->cookie->ref_cnt--; dead_retrans = *retrans; *retrans = (*retrans)->next; next_retrans = retrans; SNMP_Free(dead_retrans->pktp); if (dead_retrans->tlp) { dead_retrans->tlp->flags = 0; clean_target_list(dead_retrans->tlp); } SNMP_memory_free(dead_retrans); } continue; } if (((*retrans)->time_sent) && (((*retrans)->time_sent + (*retrans)->timeout) <= ENVOY_NOW())) { /* Packet has timed out. It's either going to be re-sent or * expired, depending on the value of retry_count. */ if (!(*retrans)->retry_count) { /* expired -- flag and try to delete */ (*retrans)->flags |= SNMP_RETRANS_FLAGS_EXPIRED; if ((*retrans)->ref_cnt == 0) { /* safe to delete at this point */ (*retrans)->cookie->ref_cnt--; dead_retrans = *retrans; *retrans = (*retrans)->next; next_retrans = retrans; SNMP_Free(dead_retrans->pktp); if (dead_retrans->tlp) { dead_retrans->tlp->flags = 0; clean_target_list(dead_retrans->tlp); } SNMP_memory_free(dead_retrans); } continue; } else { /* we need to resend the packet */ (*retrans)->ref_cnt++; (*retrans)->retry_count--; bufsize = SNMP_Bufsize_For_Packet((*retrans)->pktp);#if INSTALL_ENVOY_SNMP_LOCK ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endif (*retrans)->io_complete(&(*retrans)->for_addr, &(*retrans)->loc_addr, (PTR_T)(*retrans)->pktp, bufsize, (*retrans)->cookie->cookie);#if INSTALL_ENVOY_SNMP_LOCK ENVOY_SNMP_GET_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endif (*retrans)->time_sent = ENVOY_NOW(); (*retrans)->ref_cnt--; /* This may not be necessary, but it's probably a good * idea to make sure nobody mucked with the list while we * left it unlocked. */ next_retrans = &(*retrans)->next; } } }/* while we're locked, let's do a quick scan of the retrans_cookie list * and clean up anything that nobody cares about anymore. */for (retrans_cookie = &root_retrans_cookie; *retrans_cookie; ) { if ((*retrans_cookie)->ref_cnt) { retrans_cookie = &(*retrans_cookie)->next; continue; } if ((*retrans_cookie)->cleanup_rtn) (*retrans_cookie)->cleanup_rtn((*retrans_cookie)->cookie); dead_retrans_cookie = *retrans_cookie; *retrans_cookie = (*retrans_cookie)->next; SNMP_memory_free(dead_retrans_cookie); } /* kick the timer */retrans_timer_update();#if INSTALL_ENVOY_SNMP_LOCKENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endif}/****************************************************************************\NOMANUALNAME: SNMP_Check_Retrans_ListPURPOSE: Check an incoming packet and see if it matches anything waiting for a response in the retransmit list. If possible, try to remove it from the list.PARAMETERS: SNMP_PKT_T * the packet to be checkedRETURNS: nothing****************************************************************************/void SNMP_Check_Retrans_List(SNMP_PKT_T *pktp){SNMP_RETRANS_T **retrans;SNMP_RETRANS_T *dead_retrans;#if INSTALL_ENVOY_SNMP_LOCKENVOY_SNMP_GET_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endiffor (retrans = &root_retrans_block.retrans; *retrans; retrans = &(*retrans)->next) { /* All we really need to check on is if this packet's request id * matches that of any of the retransmit blocks. We may also want * to check the msgid of SNMPv3 packets in case we receive a report. */ if (pktp->pdu.std_pdu.request_id == (*retrans)->retrans_id) break; if ((pktp->pdu_type == REPORT_PDU) && (pktp->msg_id == (*retrans)->retrans_id)) break; }if (*retrans) { if (pktp->pdu_type == REPORT_PDU) { if ((*retrans)->flags & SNMP_RETRANS_FLAGS_SENDING_PROBE) { /* A report while we're sending a probe is almost * definitely what we've been waiting for. Let's kickstart * the process. */ (*retrans)->time_sent = ENVOY_NOW() - (*retrans)->timeout; retrans_timer_update(); } } else { (*retrans)->flags |= SNMP_RETRANS_FLAGS_ACKNOWLEDGED; if ((*retrans)->ref_cnt == 0) { (*retrans)->cookie->ref_cnt--; dead_retrans = *retrans; *retrans = (*retrans)->next; SNMP_Free(dead_retrans->pktp); SNMP_memory_free(dead_retrans); } retrans_timer_update(); } }#if INSTALL_ENVOY_SNMP_LOCKENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endif}/****************************************************************************\NOMANUALNAME: SNMP_Send_Packet_RetransmitPURPOSE: Send an SNMP_PKT_T according to the instructions passed in. This could be as simple as a single unacknowledged send, or as complicated as multiple retransmits while waiting for an acknowledgement.PARAMETERS: SNMP_PKT_T * the packet to be sent SNMP_ADDR_T * the destination address SNMP_ADDR_T * the local address bits16_t the number of retransmits bits32_t how long to wait between retransmits IO_COMPLETE_T * function used to send packet ERR_COMPLETE_T * function used if an error occurs PTR_T a user cookieRETURNS: nothing****************************************************************************/void SNMP_Send_Packet_Retransmit(SNMP_PKT_T *pktp, SNMPADDR_T *for_addr, SNMPADDR_T *loc_addr, bits16_t retry_count, bits32_t timeout, IO_COMPLETE_T *io_complete, ERR_COMPLETE_T *error_complete, RETRANS_COOKIE_T *cookie){SNMP_RETRANS_T *retrans;SNMP_RETRANS_T dummy_retrans;/* First thing to check is what we're dealing with. Packets without * timeouts or retransmit counts can just be sent off, while those * with need to be processed through our retransmission queue. We * only really need to check whether timeout is nonzero, since we * can't retry anything without a timeout value anyway... * We also check for SNMPv1 traps -- they won't be retransmitted, * because we have no way of matching any responses to them. In fact, * there's no protocol-based response to an SNMPv1 trap, so this is * pretty safe. */if ((!timeout) || ((pktp->snmp_version == SNMP_VERSION_1) && (pktp->pdu_type == TRAP_PDU))) { /* It's a simple send...easy. Just update the request_id and send. */ if (pktp->snmp_version != SNMP_VERSION_1) {#if INSTALL_ENVOY_SNMP_LOCK ENVOY_SNMP_GET_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endif ENVOY_SET_RETRANS_ID(&dummy_retrans); pktp->pdu.std_pdu.request_id = dummy_retrans.retrans_id;#if INSTALL_ENVOY_SNMP_LOCK ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endif } io_complete(for_addr, loc_addr, (PTR_T)pktp, SNMP_Bufsize_For_Packet(pktp), cookie->cookie); SNMP_Free(pktp); return; }/* Allocate a retransmit block and stuff it with the appropriate * information. */if ((retrans = SNMP_memory_alloc(sizeof(SNMP_RETRANS_T))) == 0) { error_complete(for_addr, loc_addr, 1, cookie->cookie); SNMP_Free(pktp); return; }retrans->pktp = pktp;if (for_addr) MEMCPY(&(retrans->for_addr), for_addr, sizeof(SNMPADDR_T));else MEMSET(&(retrans->for_addr), 0, sizeof(SNMPADDR_T));if (loc_addr) MEMCPY(&(retrans->loc_addr), loc_addr, sizeof(SNMPADDR_T));else MEMSET(&(retrans->loc_addr), 0, sizeof(SNMPADDR_T));retrans->retry_count = retry_count;retrans->timeout = timeout;retrans->io_complete = io_complete;retrans->error_complete = error_complete;retrans->cookie = cookie;retrans->flags = 0;retrans->ref_cnt = 1;retrans->tlp = 0;#if INSTALL_ENVOY_SNMP_LOCK/* Now we have to lock the retrans list, insert the retrans block * into the retrans list, and kickstart the timer. */ENVOY_SNMP_GET_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endifENVOY_SET_RETRANS_ID(retrans);pktp->pdu.std_pdu.request_id = retrans->retrans_id;retrans->cookie->ref_cnt++;/* We'd like to be able to match reports to our output as well. */if (pktp->snmp_version == SNMP_VERSION_3) pktp->msg_id = retrans->retrans_id;/* Insert our new retrans block into the retrans list. Sorting is * a waste of time here, since we'd have to constantly rearrange the * list everytime we retransmitted something. */retrans->next = root_retrans_block.retrans;root_retrans_block.retrans = retrans;/* It's better to use the post-sending timestamp, but can't risk * having a random or zero timestamp if the timer fires while we're * waiting...we'll update it after the send. */retrans->time_sent = ENVOY_NOW();#if INSTALL_ENVOY_SNMP_LOCKENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endif/* Now send the packet */io_complete(for_addr, loc_addr, (PTR_T)pktp, SNMP_Bufsize_For_Packet(pktp), cookie->cookie);#if INSTALL_ENVOY_SNMP_LOCKENVOY_SNMP_GET_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endifretrans->time_sent = ENVOY_NOW();retrans->ref_cnt--;/* restart the timer, if necessary */retrans_timer_update();#if INSTALL_ENVOY_SNMP_LOCKENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endif}/****************************************************************************\NOMANUALNAME: SNMP_Send_Packet_ProbePURPOSE: Send an SNMP_PKT_T probe. This packet is just a dummy designed to elicit an UnknownEngineID Report PDU from the target. PARAMETERS: SNMP_TARGET_ADDR_T * RETURNS: nothing****************************************************************************/void SNMP_Send_Packet_Probe(TARGET_LIST_T *tlp, SNMPADDR_T *loc_addr, IO_COMPLETE_T *io_complete, ERR_COMPLETE_T *error_complete, RETRANS_COOKIE_T *cookie){SNMP_RETRANS_T *retrans;/* Allocate a retransmit block and stuff it with the appropriate * information. */if ((retrans = SNMP_memory_alloc(sizeof(SNMP_RETRANS_T))) == 0) { error_complete(&(tlp->for_addr), loc_addr, 1, cookie->cookie); SNMP_Free(tlp->pktp); clean_target_list(tlp); return; }retrans->pktp = tlp->pktp;MEMCPY(&(retrans->for_addr), &(tlp->for_addr), sizeof(SNMPADDR_T));if (loc_addr) MEMCPY(&(retrans->loc_addr), loc_addr, sizeof(SNMPADDR_T));else MEMSET(&(retrans->loc_addr), 0, sizeof(SNMPADDR_T));retrans->retry_count = tlp->retry_count;retrans->timeout = tlp->timeout;retrans->io_complete = io_complete;retrans->error_complete = error_complete;retrans->cookie = cookie;retrans->flags = SNMP_RETRANS_FLAGS_SENDING_PROBE;retrans->ref_cnt = 1;retrans->tlp = tlp;#if INSTALL_ENVOY_SNMP_LOCK/* Now we have to lock the retrans list, insert the retrans block * into the retrans list, and kickstart the timer. */ENVOY_SNMP_GET_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endifENVOY_SET_RETRANS_ID(retrans);tlp->pktp->pdu.std_pdu.request_id = retrans->retrans_id;retrans->cookie->ref_cnt++;/* We'd like to be able to match reports to our output as well. */if (tlp->pktp->snmp_version == SNMP_VERSION_3) tlp->pktp->msg_id = retrans->retrans_id;/* Insert our new retrans block into the retrans list. Sorting is * a waste of time here, since we'd have to constantly rearrange the * list everytime we retransmitted something. */retrans->next = root_retrans_block.retrans;root_retrans_block.retrans = retrans;#if INSTALL_ENVOY_SNMP_LOCKENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_V3_Retrans_Lock);#endif/* Now send the packet */io_complete(&(tlp->for_addr), loc_addr, (PTR_T)tlp->pktp, SNMP_Bufsize_For_Packet(tlp->pktp), cookie->cookie);#if INSTALL_ENVOY_SNMP_LOCKENVOY_SNMP_GET_WRITE_LOCK(SNMP_V3_Retrans_Lock);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -