📄 proxy.c
字号:
pid = proxy_id++;ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_ProxyLock);/* save the old reqid for later and install the new reqid, then try and send the packet */old_reqid = pktp->pdu.std_pdu.request_id;pktp->pdu.std_pdu.request_id = pid;ttl = ((INT_32_T (*) __((SNMP_PKT_T *)))(pktp->proxy_routine))(pktp);/* restore the old reqid in case we need to send an error packet */pktp->pdu.std_pdu.request_id = old_reqid;/* If the proxy routine failed we send out an error */if (ttl < 0) { ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0); return; }/* Acquire the space for the proxy state block and the timer block */if ((pcb = (PROXY_CB_T *)SNMP_memory_alloc(sizeof(PROXY_CB_T))) == 0) { ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0); return; }EBufferInitialize(&pcb->community);tm32 = (ENVOY_TIMER_32_T *)SNMP_memory_alloc(sizeof(ENVOY_TIMER_32_T));if (tm32 == 0) { Clean_PCB(pcb); ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0); return; }/* Move the community string from the packet structure to the proxy block structure. This code resets the packet flags to STATIC because the ownership now rests with the proxy block structure. */EBufferPreLoad(pktp->community.bflags, &pcb->community, EBufferStart(&pktp->community), EBufferUsed(&pktp->community));pktp->community.bflags = BFL_IS_STATIC;pcb->indx = pid;pcb->reqid = old_reqid;MEMCPY(&pcb->loc_addr, &pktp->pkt_dst, sizeof(SNMPADDR_T));MEMCPY(&pcb->for_addr, &pktp->pkt_src, sizeof(SNMPADDR_T));pcb->io_comp = pktp->io_complete;pcb->err_comp = pktp->error_complete;pcb->async_cookie = pktp->async_cookie;pcb->maxpkt = pktp->maxpkt;pcb->pdu_type = pktp->pdu_type;pcb->original_version = pktp->snmp_version;/* We need to get the proxy lock before trying to install the timer and pcb blocks into their proper lists */#if (INSTALL_ENVOY_SNMP_LOCK)if (ENVOY_SNMP_GET_WRITE_LOCK(SNMP_ProxyLock)) { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "SNMP_Proxy_Request: proxy lock broken", 0)); ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0); Clean_PCB(pcb); SNMP_memory_free(tm32); return; }#endif/* attempt to set up a timer to clean up the pcb if we don't get a response packet, if we can't set up the timer remove the pcb and send an error packet */envoy_tm_init(&(tm32->timer));tm32->id = pcb->indx;tm32->timer.cookie = tm32;tm32->timer.handler = SNMP_Proxy_Timer;if (envoy_tm_set(&(tm32->timer), ttl)) { ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_ProxyLock); ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0); Clean_PCB(pcb); SNMP_memory_free(tm32); return; }/* We have succeeded in building all the right structures, attach the pcb to the list */pcb->next = pcb_root;pcb_root = pcb;ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_ProxyLock);return;}/****************************************************************************NAME: SNMP_Proxy_ResponsePURPOSE: Provide proxy handling, attempt to restore the saved state and transmit a response packet to the original request.PARAMETERS: SNMP_PKT_T * Packet we're working onRETURNS: 0 if successfully processed packet, 1 otherwise****************************************************************************/int SNMP_Proxy_Response(SNMP_PKT_T *pktp){PROXY_CB_T *pcb = 0, **pcbp;UINT_32_T reqid;ALENGTH_T pktsize;/* Dig out the saved state, and prepare the response packet */reqid = pktp->pdu.std_pdu.request_id;#if (INSTALL_ENVOY_SNMP_LOCK)if (ENVOY_SNMP_GET_WRITE_LOCK(SNMP_ProxyLock)) { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "SNMP_Proxy_Response: proxy lock broken", 0)); pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 1, pktp->async_cookie); return 1; }#endiffor(pcbp = &pcb_root; *pcbp; pcbp = &(*pcbp)->next) if ((*pcbp)->indx == reqid) { pcb = *pcbp; *pcbp = pcb->next; break; }ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_ProxyLock);/* if we didn't find any state drop the packet */if (pcb == 0) { pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 1, pktp->async_cookie); return 1; }/* Indicate that we are done with the addressing information from the respone packet */pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 0, pktp->async_cookie);/* restore the state */pktp->pdu.std_pdu.request_id = pcb->reqid;MEMCPY(&pktp->pkt_dst, &pcb->loc_addr, sizeof(SNMPADDR_T));MEMCPY(&pktp->pkt_src, &pcb->for_addr, sizeof(SNMPADDR_T));pktp->io_complete = pcb->io_comp;pktp->error_complete = pcb->err_comp;pktp->async_cookie = pcb->async_cookie;pktp->maxpkt = pcb->maxpkt;pktp->pdu_type = pcb->pdu_type;pktp->snmp_version = pcb->original_version;/* Clean up the current community string and then replace it with the saved community string */EBufferClean(&pktp->community);EBufferPreLoad(pcb->community.bflags, &pktp->community, EBufferStart(&pcb->community), EBufferUsed(&pcb->community));EBufferInitialize(&pcb->community);/* we are done with the pcb so clean it up */Clean_PCB(pcb);/* If the current packet doesn't have it we need to get the read lock */#if (INSTALL_ENVOY_SNMP_LOCK)if (pktp->lockflags == LOCK_NOLOCK) { if (ENVOY_SNMP_GET_READ_LOCK(SNMP_CoarseLock)) { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "SNMP_Proxy_Response: coarse lock broken", 0)); pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 1, pktp->async_cookie); return 1; } pktp->lockflags = LOCK_READ; pktp->coarse_lock = &SNMP_CoarseLock; }#endif/* determine if the packet is small enough to be sent out */pktsize = SNMP_Bufsize_For_Packet(pktp);if (pktsize > pktp->maxpkt) { switch (pktp->pdu_type) { case GET_REQUEST_PDU: case GET_NEXT_REQUEST_PDU: /* set up an alternate response, strip the vbl and tag it as too_big */ Clean_vb_list(&pktp->pdu.std_pdu.std_vbl); pktp->pdu.std_pdu.std_vbl.vblist = 0; pktp->pdu.std_pdu.std_vbl.vbl_count = 0; pktp->pdu.std_pdu.error_status = TOO_BIG; pktp->pdu.std_pdu.error_index = 0; break;#if (INSTALL_ENVOY_SNMP_VERSION_2) case GET_BULK_REQUEST_PDU: /* if we have a BULK request we may need to remove vbs to fit in to the maximum packet size */ { int indx; VB_T *vbp; for (indx = pktp->pdu.std_pdu.std_vbl.vbl_count, vbp = pktp->pdu.std_pdu.std_vbl.vblist + indx - 1; indx; indx--, vbp--) { Clean_vb(vbp); /* Recalculate the pktsize, 2 is for the tag and length fields, the length field may be greater than 1 but that is ok, the only thing that will happen is we may put less than the maximum in a buffer */ pktsize -= 2 + vbp->vb_seq_size; if (pktsize < pktp->maxpkt) { pktp->pdu.std_pdu.std_vbl.vbl_count = indx - 1; break; } } } break;#endif /* #if (INSTALL_ENVOY_SNMP_VERSION_2) */ } }ENVOY_Send_SNMP_Packet(pktp);return 0;}/****************************************************************************NAME: SNMP_Proxy_Traps_And_ReportsPURPOSE: Provide proxy handling for traps and reports Figure out if we have the information for a proxy event, if so ship the message onward if not tag the appropriate error. In any case indicate that we are finished with the packet and free it.PARAMETERS: SNMP_PKT_T * Packet we're working onRETURNS: void****************************************************************************/void SNMP_Proxy_Traps_And_Reports(SNMP_PKT_T *pktp){/* If we don't have a translation routine we bail out */if (pktp->proxy_routine == 0) { pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 1, pktp->async_cookie); return; } /* If the current packet doesn't have it we need to get the read lock */#if (INSTALL_ENVOY_SNMP_LOCK)if (pktp->lockflags == LOCK_NOLOCK) { if (ENVOY_SNMP_GET_READ_LOCK(SNMP_CoarseLock)) { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "SNMP_Proxy_Traps_and_Reports: coarse lock broken", 0)); pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 1, pktp->async_cookie); return; } pktp->lockflags = LOCK_READ; pktp->coarse_lock = &SNMP_CoarseLock; }#endifif ((((INT_32_T (*) __((SNMP_PKT_T *)))(pktp->proxy_routine))(pktp)) < 0) pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 1, pktp->async_cookie);else pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 0, pktp->async_cookie);return;}#endif /* INSTALL_ENVOY_SNMP_PROXY */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -