@@ -85,6 +85,7 @@ netsnmp_feature_child_of(usm_support, usm_all)
8585netsnmp_feature_require (usm_support )
8686
8787struct usmStateReference {
88+ int refcnt ;
8889 char * usr_name ;
8990 size_t usr_name_length ;
9091 u_char * usr_engine_id ;
@@ -280,42 +281,63 @@ free_enginetime_on_shutdown(int majorid, int minorid, void *serverarg,
280281static struct usmStateReference *
281282usm_malloc_usmStateReference (void )
282283{
283- struct usmStateReference * retval = (struct usmStateReference * )
284- calloc (1 , sizeof (struct usmStateReference ));
284+ struct usmStateReference * retval ;
285+
286+ retval = calloc (1 , sizeof (struct usmStateReference ));
287+ if (retval )
288+ retval -> refcnt = 1 ;
285289
286290 return retval ;
287291} /* end usm_malloc_usmStateReference() */
288292
293+ static int
294+ usm_clone (netsnmp_pdu * pdu , netsnmp_pdu * new_pdu )
295+ {
296+ struct usmStateReference * ref = pdu -> securityStateRef ;
297+ struct usmStateReference * * new_ref =
298+ (struct usmStateReference * * )& new_pdu -> securityStateRef ;
299+ int ret = 0 ;
300+
301+ if (!ref )
302+ return ret ;
303+
304+ if (pdu -> command == SNMP_MSG_TRAP2 ) {
305+ netsnmp_assert (pdu -> securityModel == SNMP_DEFAULT_SECMODEL );
306+ ret = usm_clone_usmStateReference (ref , new_ref );
307+ } else {
308+ netsnmp_assert (ref == * new_ref );
309+ ref -> refcnt ++ ;
310+ }
311+
312+ return ret ;
313+ }
314+
289315static void
290316usm_free_usmStateReference (void * old )
291317{
292- struct usmStateReference * old_ref = (struct usmStateReference * ) old ;
293-
294- if (old_ref ) {
295-
296- if (old_ref -> usr_name_length )
297- SNMP_FREE (old_ref -> usr_name );
298- if (old_ref -> usr_engine_id_length )
299- SNMP_FREE (old_ref -> usr_engine_id );
300- if (old_ref -> usr_auth_protocol_length )
301- SNMP_FREE (old_ref -> usr_auth_protocol );
302- if (old_ref -> usr_priv_protocol_length )
303- SNMP_FREE (old_ref -> usr_priv_protocol );
304-
305- if (old_ref -> usr_auth_key_length && old_ref -> usr_auth_key ) {
306- SNMP_ZERO (old_ref -> usr_auth_key , old_ref -> usr_auth_key_length );
307- SNMP_FREE (old_ref -> usr_auth_key );
308- }
309- if (old_ref -> usr_priv_key_length && old_ref -> usr_priv_key ) {
310- SNMP_ZERO (old_ref -> usr_priv_key , old_ref -> usr_priv_key_length );
311- SNMP_FREE (old_ref -> usr_priv_key );
312- }
318+ struct usmStateReference * ref = old ;
319+
320+ if (!ref )
321+ return ;
322+
323+ if (-- ref -> refcnt > 0 )
324+ return ;
313325
314- SNMP_ZERO (old_ref , sizeof (* old_ref ));
315- SNMP_FREE (old_ref );
326+ SNMP_FREE (ref -> usr_name );
327+ SNMP_FREE (ref -> usr_engine_id );
328+ SNMP_FREE (ref -> usr_auth_protocol );
329+ SNMP_FREE (ref -> usr_priv_protocol );
316330
331+ if (ref -> usr_auth_key_length && ref -> usr_auth_key ) {
332+ SNMP_ZERO (ref -> usr_auth_key , ref -> usr_auth_key_length );
333+ SNMP_FREE (ref -> usr_auth_key );
334+ }
335+ if (ref -> usr_priv_key_length && ref -> usr_priv_key ) {
336+ SNMP_ZERO (ref -> usr_priv_key , ref -> usr_priv_key_length );
337+ SNMP_FREE (ref -> usr_priv_key );
317338 }
318339
340+ SNMP_FREE (ref );
319341} /* end usm_free_usmStateReference() */
320342
321343struct usmUser *
@@ -4916,6 +4938,7 @@ init_usm(void)
49164938 def -> encode_reverse = usm_secmod_rgenerate_out_msg ;
49174939 def -> encode_forward = usm_secmod_generate_out_msg ;
49184940 def -> decode = usm_secmod_process_in_msg ;
4941+ def -> pdu_clone = usm_clone ;
49194942 def -> pdu_free_state_ref = usm_free_usmStateReference ;
49204943 def -> session_setup = usm_session_init ;
49214944 def -> handle_report = usm_handle_report ;
0 commit comments