diff options
Diffstat (limited to 'lib')
83 files changed, 6110 insertions, 5100 deletions
diff --git a/lib/.gitignore b/lib/.gitignore index 56b1ed2b84..4125111ebd 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -7,6 +7,7 @@ /common_test/doc/src/ct_rpc.xml /common_test/doc/src/ct_snmp.xml /common_test/doc/src/ct_ssh.xml +/common_test/doc/src/ct_netconfc.xml /common_test/doc/src/ct_telnet.xml /common_test/doc/src/unix_telnet.xml diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index 494a2eddd9..59e82b7a57 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -4177,7 +4177,7 @@ check_constraint(S,{'SizeConstraint',Lb}) -> check_constraint(S,{'SingleValue', L}) when is_list(L) -> F = fun(A) -> resolv_value(S,A) end, - {'SingleValue',lists:map(F,L)}; + {'SingleValue',lists:sort(lists:map(F,L))}; check_constraint(S,{'SingleValue', V}) when is_integer(V) -> Val = resolv_value(S,V), diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index fda4e1c6d9..64a3555f62 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -129,28 +129,39 @@ pgen_types(Rtmod,Erules,N2nConvEnums,Module,[H|T]) -> end, pgen_types(Rtmod,Erules,N2nConvEnums,Module,T). +%% Enumerated type with extension marker pgen_n2nconversion(_Erules,#typedef{name=TypeName,typespec=#type{def={'ENUMERATED',{NN1,NN2}}}}) -> NN = NN1 ++ NN2, - pgen_name2numfunc(TypeName,NN), - pgen_num2namefunc(TypeName,NN); + pgen_name2numfunc(TypeName,NN, extension_marker), + pgen_num2namefunc(TypeName,NN, extension_marker); +%% Without extension marker +pgen_n2nconversion(_Erules,#typedef{name=TypeName,typespec=#type{def={'ENUMERATED',NN}}}) -> + pgen_name2numfunc(TypeName,NN, no_extension_marker), + pgen_num2namefunc(TypeName,NN, no_extension_marker); pgen_n2nconversion(_Erules,_) -> true. -pgen_name2numfunc(_TypeName,[]) -> +pgen_name2numfunc(_TypeName,[], _) -> true; -pgen_name2numfunc(TypeName,[{Atom,Number}]) -> +pgen_name2numfunc(TypeName,[{Atom,Number}], extension_marker) -> + emit(["name2num_",TypeName,"(",{asis,Atom},") ->",Number,";",nl]), + emit(["name2num_",TypeName,"({asn1_enum, Num}) -> Num.",nl,nl]); +pgen_name2numfunc(TypeName,[{Atom,Number}], _) -> emit(["name2num_",TypeName,"(",{asis,Atom},") ->",Number,".",nl,nl]); -pgen_name2numfunc(TypeName,[{Atom,Number}|NNRest]) -> +pgen_name2numfunc(TypeName,[{Atom,Number}|NNRest], EM) -> emit(["name2num_",TypeName,"(",{asis,Atom},") ->",Number,";",nl]), - pgen_name2numfunc(TypeName,NNRest). + pgen_name2numfunc(TypeName,NNRest, EM). -pgen_num2namefunc(_TypeName,[]) -> +pgen_num2namefunc(_TypeName,[], _) -> true; -pgen_num2namefunc(TypeName,[{Atom,Number}]) -> +pgen_num2namefunc(TypeName,[{Atom,Number}], extension_marker) -> + emit(["num2name_",TypeName,"(",Number,") ->",{asis,Atom},";",nl]), + emit(["num2name_",TypeName,"(ExtensionNum) -> {asn1_enum, ExtensionNum}.",nl,nl]); +pgen_num2namefunc(TypeName,[{Atom,Number}], _) -> emit(["num2name_",TypeName,"(",Number,") ->",{asis,Atom},".",nl,nl]); -pgen_num2namefunc(TypeName,[{Atom,Number}|NNRest]) -> +pgen_num2namefunc(TypeName,[{Atom,Number}|NNRest], EM) -> emit(["num2name_",TypeName,"(",Number,") ->",{asis,Atom},";",nl]), - pgen_num2namefunc(TypeName,NNRest). + pgen_num2namefunc(TypeName,NNRest, EM). pgen_objects(_,_,_,[]) -> true; diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index 5f42eacbdc..bd5b81991d 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -321,19 +321,13 @@ effective_constr(_,[]) -> []; effective_constr('SingleValue',List) -> SVList = lists:flatten(lists:map(fun(X)->element(2,X)end,List)), - % sort and remove duplicates - SortedSVList = lists:sort(SVList), - RemoveDup = fun([],_) ->[]; - ([H],_) -> [H]; - ([H,H|T],F) -> F([H|T],F); - ([H|T],F) -> [H|F(T,F)] - end, - - case RemoveDup(SortedSVList,RemoveDup) of + %% Sort and remove duplicates before generating SingleValue or ValueRange + %% In case of ValueRange, also check for 'MIN and 'MAX' + case lists:usort(SVList) of [N] -> [{'SingleValue',N}]; - L when is_list(L) -> - [{'ValueRange',{hd(L),lists:last(L)}}] + L when is_list(L) -> + [{'ValueRange',{least_Lb(L),greatest_Ub(L)}}] end; effective_constr('ValueRange',List) -> LBs = lists:map(fun({_,{Lb,_}})-> Lb end,List), diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl index eda0faad3c..16eec92847 100644 --- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl +++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl @@ -670,18 +670,13 @@ effective_constr(_,[]) -> []; effective_constr('SingleValue',List) -> SVList = lists:flatten(lists:map(fun(X)->element(2,X)end,List)), - % sort and remove duplicates - RemoveDup = fun([],_) ->[]; - ([H],_) -> [H]; - ([H,H|T],F) -> F([H|T],F); - ([H|T],F) -> [H|F(T,F)] - end, - - case RemoveDup(SVList,RemoveDup) of + %% Sort and remove duplicates before generating SingleValue or ValueRange + %% In case of ValueRange, also check for 'MIN and 'MAX' + case lists:usort(SVList) of [N] -> [{'SingleValue',N}]; - L when is_list(L) -> - [{'ValueRange',{hd(L),lists:last(L)}}] + L when is_list(L) -> + [{'ValueRange',{least_Lb(L),greatest_Ub(L)}}] end; effective_constr('ValueRange',List) -> LBs = lists:map(fun({_,{Lb,_}})-> Lb end,List), diff --git a/lib/asn1/src/asn1rt_per_bin.erl b/lib/asn1/src/asn1rt_per_bin.erl index a124c7553d..85988aa21d 100644 --- a/lib/asn1/src/asn1rt_per_bin.erl +++ b/lib/asn1/src/asn1rt_per_bin.erl @@ -18,7 +18,6 @@ %% %% -module(asn1rt_per_bin). - %% encoding / decoding of PER aligned -include("asn1_records.hrl"). @@ -57,7 +56,7 @@ encode_NumericString/2, decode_NumericString/2, encode_ObjectDescriptor/2, decode_ObjectDescriptor/1 ]). --export([complete_bytes/1, getbits/2, getoctets/2]). +-export([complete_bytes/1, getbits/2, getoctets/2, minimum_bits/1]). -define('16K',16384). -define('32K',32768). @@ -695,21 +694,28 @@ encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val -> {octets,[Val2]}; Range =< 65536 -> {octets,<<Val2:16>>}; - Range =< 16#1000000 -> - Octs = eint_positive(Val2), - [{bits,2,length(Octs)-1},{octets,Octs}]; - Range =< 16#100000000 -> - Octs = eint_positive(Val2), - [{bits,2,length(Octs)-1},{octets,Octs}]; - Range =< 16#10000000000 -> - Octs = eint_positive(Val2), - [{bits,3,length(Octs)-1},{octets,Octs}]; + Range =< (1 bsl (255*8)) -> + Octs = binary:encode_unsigned(Val2), + RangeOcts = binary:encode_unsigned(Range - 1), + OctsLen = erlang:byte_size(Octs), + RangeOctsLen = erlang:byte_size(RangeOcts), + LengthBitsNeeded = minimum_bits(RangeOctsLen - 1), + [{bits, LengthBitsNeeded, OctsLen - 1}, {octets, Octs}]; true -> exit({not_supported,{integer_range,Range}}) end; encode_constrained_number(Range,Val) -> exit({error,{asn1,{integer_range,Range,value,Val}}}). +%% For some reason the minimum bits needed in the length field in encoding of +%% constrained whole numbers must always be atleast 2? +minimum_bits(N) when N < 4 -> 2; +minimum_bits(N) when N < 8 -> 3; +minimum_bits(N) when N < 16 -> 4; +minimum_bits(N) when N < 32 -> 5; +minimum_bits(N) when N < 64 -> 6; +minimum_bits(N) when N < 128 -> 7; +minimum_bits(_N) -> 8. decode_constrained_number(Buffer,{Lb,Ub}) -> Range = Ub - Lb + 1, @@ -738,18 +744,12 @@ decode_constrained_number(Buffer,{Lb,Ub}) -> getoctets(Buffer,1); Range =< 65536 -> getoctets(Buffer,2); - Range =< 16#1000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,3}), - {Octs,Bytes3} = getoctets_as_list(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - Range =< 16#100000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,4}), - {Octs,Bytes3} = getoctets_as_list(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - Range =< 16#10000000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,5}), - {Octs,Bytes3} = getoctets_as_list(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; + Range =< (1 bsl (255*8)) -> + OList = binary:bin_to_list(binary:encode_unsigned(Range - 1)), + RangeOctLen = length(OList), + {Len, Bytes} = decode_length(Buffer, {1, RangeOctLen}), + {Octs, RestBytes} = getoctets_as_list(Bytes, Len), + {binary:decode_unsigned(binary:list_to_bin(Octs)), RestBytes}; true -> exit({not_supported,{integer_range,Range}}) end, diff --git a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl index 750b59aba6..46d4bcb065 100644 --- a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl +++ b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl @@ -18,7 +18,6 @@ %% %% -module(asn1rt_per_bin_rt2ct). - %% encoding / decoding of PER aligned -include("asn1_records.hrl"). @@ -605,19 +604,13 @@ encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val -> Range =< 65536 -> % Size = {octets,<<Val2:16>>}; [20,2,<<Val2:16>>]; - Range =< 16#1000000 -> - Octs = eint_positive(Val2), -% [{bits,2,length(Octs)-1},{octets,Octs}]; - Len = length(Octs), - [10,2,Len-1,20,Len,Octs]; - Range =< 16#100000000 -> - Octs = eint_positive(Val2), - Len = length(Octs), - [10,2,Len-1,20,Len,Octs]; - Range =< 16#10000000000 -> - Octs = eint_positive(Val2), - Len = length(Octs), - [10,3,Len-1,20,Len,Octs]; + Range =< (1 bsl (255*8)) -> + Octs = binary:encode_unsigned(Val2), + RangeOcts = binary:encode_unsigned(Range - 1), + OctsLen = erlang:byte_size(Octs), + RangeOctsLen = erlang:byte_size(RangeOcts), + LengthBitsNeeded = asn1rt_per_bin:minimum_bits(RangeOctsLen - 1), + [10,LengthBitsNeeded,OctsLen-1,20,OctsLen,Octs]; true -> exit({not_supported,{integer_range,Range}}) end; @@ -661,18 +654,12 @@ decode_constrained_number(Buffer,{Lb,_Ub},Range) -> getoctets(Buffer,1); Range =< 65536 -> getoctets(Buffer,2); - Range =< 16#1000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,3}), - {Octs,Bytes3} = getoctets_as_bin(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - Range =< 16#100000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,4}), - {Octs,Bytes3} = getoctets_as_bin(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - Range =< 16#10000000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,5}), - {Octs,Bytes3} = getoctets_as_bin(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; + Range =< (1 bsl (255*8)) -> + OList = binary:bin_to_list(binary:encode_unsigned(Range - 1)), + RangeOctLen = length(OList), + {Len, Bytes} = decode_length(Buffer, {1, RangeOctLen}), + {Octs, RestBytes} = getoctets_as_bin(Bytes, Len), + {binary:decode_unsigned(Octs), RestBytes}; true -> exit({not_supported,{integer_range,Range}}) end, diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl index 3b9a7532c0..56f31de638 100644 --- a/lib/asn1/test/asn1_SUITE.erl +++ b/lib/asn1/test/asn1_SUITE.erl @@ -773,6 +773,7 @@ per_open_type(Config, Rule, Opts) -> testConstraints(Config) -> test(Config, fun testConstraints/3). testConstraints(Config, Rule, Opts) -> asn1_test_lib:compile("Constraints", Config, [Rule|Opts]), + asn1_test_lib:compile("LargeConstraints", Config, [Rule|Opts]), testConstraints:int_constraints(Rule). @@ -1236,6 +1237,27 @@ testName2Number(Config) -> 0 = 'S1AP-IEs':name2num_CauseMisc('control-processing-overload'), 'unknown-PLMN' = 'S1AP-IEs':num2name_CauseMisc(5), + + %% OTP-10144 + %% Test that n2n option generates name2num and num2name functions supporting + %% values not within the extension root if the enumeration type has an + %% extension marker. + N2NOptionsExt = [{n2n, 'NoExt'}, {n2n, 'Ext'}, {n2n, 'Ext2'}], + asn1_test_lib:compile("EnumN2N", Config, N2NOptionsExt), + %% Previously, name2num and num2name was not generated if the type didn't + %% have an extension marker: + 0 = 'EnumN2N':name2num_NoExt('blue'), + 2 = 'EnumN2N':name2num_NoExt('green'), + blue = 'EnumN2N':num2name_NoExt(0), + green = 'EnumN2N':num2name_NoExt(2), + + %% Test enumeration extension: + 7 = 'EnumN2N':name2num_Ext2('orange'), + orange = 'EnumN2N':num2name_Ext2(7), + %% 7 is not defined in Ext, only in Ext2. + {asn1_enum, 7} = 'EnumN2N':num2name_Ext(7), + 7 = 'EnumN2N':name2num_Ext({asn1_enum, 7}), + 42 = 'EnumN2N':name2num_Ext2({asn1_enum, 42}), ok. ticket_7407(Config) -> diff --git a/lib/asn1/test/asn1_SUITE_data/Constraints.py b/lib/asn1/test/asn1_SUITE_data/Constraints.py index de48c4c2ca..87243121f7 100644 --- a/lib/asn1/test/asn1_SUITE_data/Constraints.py +++ b/lib/asn1/test/asn1_SUITE_data/Constraints.py @@ -4,9 +4,14 @@ BEGIN -- Single Value SingleValue ::= INTEGER (1) SingleValue2 ::= INTEGER (1..20) +predefined INTEGER ::= 1 +SingleValue3 ::= INTEGER (predefined | 5 | 10) Range2to19 ::= INTEGER (1<..<20) Range10to20 ::= INTEGER (10..20) ContainedSubtype ::= INTEGER (INCLUDES Range10to20) +-- Some ranges for additional constrained number testing. +LongLong ::= INTEGER (0..18446744073709551615) +Range256to65536 ::= INTEGER (256..65536) FixedSize ::= OCTET STRING (SIZE(10)) FixedSize2 ::= OCTET STRING (SIZE(10|20)) VariableSize ::= OCTET STRING (SIZE(1..10)) diff --git a/lib/asn1/test/asn1_SUITE_data/EnumN2N.asn1 b/lib/asn1/test/asn1_SUITE_data/EnumN2N.asn1 new file mode 100644 index 0000000000..a724f2f3f5 --- /dev/null +++ b/lib/asn1/test/asn1_SUITE_data/EnumN2N.asn1 @@ -0,0 +1,25 @@ +EnumN2N DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + +NoExt ::= ENUMERATED { + blue(0), + red(1), + green(2) +} + +Ext ::= ENUMERATED { + blue(0), + red(1), + green(2), + ... +} + +Ext2 ::= ENUMERATED { + blue(0), + red(1), + green(2), + ..., + orange(7) +} + +END diff --git a/lib/asn1/test/asn1_SUITE_data/LargeConstraints.py b/lib/asn1/test/asn1_SUITE_data/LargeConstraints.py new file mode 100644 index 0000000000..68c7616b62 --- /dev/null +++ b/lib/asn1/test/asn1_SUITE_data/LargeConstraints.py @@ -0,0 +1,9 @@ +LargeConstraints DEFINITIONS ::= +BEGIN + +-- Maximum number that can be encoded as a constrained whole number: 1 bsl (255*8) +-- The number of octets needed to represent a number cannot be more than 255 +-- As the length field is encoded as a 8-bit bitfield. +RangeMax ::= INTEGER (1..126238304966058622268417487065116999845484776053576109500509161826268184136202698801551568013761380717534054534851164138648904527931605160527688095259563605939964364716019515983399209962459578542172100149937763938581219604072733422507180056009672540900709554109516816573779593326332288314873251559077853068444977864803391962580800682760017849589281937637993445539366428356761821065267423102149447628375691862210717202025241630303118559188678304314076943801692528246980959705901641444238894928620825482303431806955690226308773426829503900930529395181208739591967195841536053143145775307050594328881077553168201547776) + +END diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl index 1ce68ec522..543c106e8a 100644 --- a/lib/asn1/test/testConstraints.erl +++ b/lib/asn1/test/testConstraints.erl @@ -52,8 +52,6 @@ int_constraints(Rules) -> ?line {error,_Reason2} = asn1_wrapper:encode('Constraints','SingleValue',1000) end, - - %%========================================================== %% SingleValue2 ::= INTEGER (1..20) @@ -86,7 +84,21 @@ int_constraints(Rules) -> asn1_wrapper:encode('Constraints','SingleValue',1000) end, + %%========================================================== + %% SingleValue3 ::= INTEGER (Predefined | 5 | 10) + %% Testcase for OTP-10139. A single value subtyping of an integer type + %% where one value is predefined. + %%========================================================== + ?line {ok,BytesSV3} = asn1_wrapper:encode('Constraints','SingleValue3',1), + ?line {ok,1} = asn1_wrapper:decode('Constraints','SingleValue3', + lists:flatten(BytesSV3)), + ?line {ok,BytesSV3_2} = asn1_wrapper:encode('Constraints','SingleValue3',5), + ?line {ok,5} = asn1_wrapper:decode('Constraints','SingleValue3', + lists:flatten(BytesSV3_2)), + ?line {ok,BytesSV3_3} = asn1_wrapper:encode('Constraints','SingleValue3',10), + ?line {ok,10} = asn1_wrapper:decode('Constraints','SingleValue3', + lists:flatten(BytesSV3_3)), %%========================================================== %% Range2to19 ::= INTEGER (1<..<20) @@ -116,7 +128,65 @@ int_constraints(Rules) -> ?line {error,_Reason6} = asn1_wrapper:encode('Constraints','Range2to19',20) end, + + %%========================================================== + %% Tests for Range above 16^4 up to maximum supported by asn1 assuming the + %% octet length field is encoded on max 8 bits + %%========================================================== + LastNumWithoutLengthEncoding = 65536, + ?line {ok,BytesFoo} = asn1_wrapper:encode('Constraints','Range256to65536', + LastNumWithoutLengthEncoding), + ?line {ok,LastNumWithoutLengthEncoding} = + asn1_wrapper:decode('Constraints','Range256to65536',lists:flatten(BytesFoo)), + + FirstNumWithLengthEncoding = 65537, + ?line {ok,BytesBar} = asn1_wrapper:encode('LargeConstraints','RangeMax', + FirstNumWithLengthEncoding), + ?line {ok,FirstNumWithLengthEncoding} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBar)), + + FirstNumOver16_6 = 16777217, + ?line {ok, BytesBaz} = + asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_6), + ?line {ok, FirstNumOver16_6} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBaz)), + + FirstNumOver16_8 = 4294967297, + ?line {ok, BytesQux} = + asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_8), + ?line {ok, FirstNumOver16_8} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesQux)), + + FirstNumOver16_10 = 1099511627776, + ?line {ok, BytesBur} = + asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_10), + ?line {ok, FirstNumOver16_10} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBur)), + + FirstNumOver16_10 = 1099511627776, + ?line {ok, BytesBur} = + asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_10), + ?line {ok, FirstNumOver16_10} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBur)), + + HalfMax = 1 bsl (128*8), + ?line {ok, BytesHalfMax} = + asn1_wrapper:encode('LargeConstraints','RangeMax', HalfMax), + ?line {ok, HalfMax} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesHalfMax)), + + Max = 1 bsl (255*8), + ?line {ok, BytesMax} = + asn1_wrapper:encode('LargeConstraints','RangeMax', Max), + ?line {ok, Max} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesMax)), + %% Random number within longlong range + LongLong = 12672809400538808320, + ?line {ok, BytesLongLong} = + asn1_wrapper:encode('Constraints','LongLong', LongLong), + ?line {ok, LongLong} = + asn1_wrapper:decode('Constraints','LongLong',lists:flatten(BytesLongLong)), %%========================================================== %% Constraint Combinations (Duboisson p. 285) diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile index 2ec6952710..99161ce68a 100644 --- a/lib/common_test/doc/src/Makefile +++ b/lib/common_test/doc/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2003-2011. All Rights Reserved. +# Copyright Ericsson AB 2003-2012. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -46,7 +46,8 @@ CT_MODULES = \ ct_rpc \ ct_snmp \ unix_telnet \ - ct_slave + ct_slave \ + ct_netconfc CT_XML_FILES = $(CT_MODULES:=.xml) @@ -123,7 +124,7 @@ $(HTMLDIR)/%.gif: %.gif docs: pdf html man -$(CT_XML_FILES): +$(CT_XML_FILES): %.xml: ../../src/%.erl escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -preprocess true -i $(XMERL_DIR)/include \ -i ../../../test_server/include -i ../../include \ -i ../../../../erts/lib/kernel/include -i ../../../../lib/kernel/include \ diff --git a/lib/common_test/doc/src/ref_man.xml b/lib/common_test/doc/src/ref_man.xml index a9fdef7359..6fede88434 100644 --- a/lib/common_test/doc/src/ref_man.xml +++ b/lib/common_test/doc/src/ref_man.xml @@ -4,7 +4,7 @@ <application xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>2003</year><year>2011</year> + <year>2003</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -71,6 +71,7 @@ <xi:include href="ct_cover.xml"/> <xi:include href="ct_ftp.xml"/> <xi:include href="ct_ssh.xml"/> + <xi:include href="ct_netconfc.xml"/> <xi:include href="ct_rpc.xml"/> <xi:include href="ct_snmp.xml"/> <xi:include href="ct_telnet.xml"/> diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile index 037a686963..f7dce195d7 100644 --- a/lib/common_test/src/Makefile +++ b/lib/common_test/src/Makefile @@ -70,14 +70,18 @@ MODULES= \ ct_hooks\ ct_hooks_lock\ cth_log_redirect\ - cth_surefire + cth_surefire \ + ct_netconfc \ + ct_conn_log_h \ + cth_conn_log TARGET_MODULES= $(MODULES:%=$(EBIN)/%) BEAM_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) ERL_FILES= $(MODULES:=.erl) HRL_FILES = \ - ct_util.hrl + ct_util.hrl \ + ct_netconfc.hrl EXTERNAL_HRL_FILES = \ ../include/ct.hrl \ ../include/ct_event.hrl diff --git a/lib/common_test/src/common_test.app.src b/lib/common_test/src/common_test.app.src index ae9a51faeb..18c1dec784 100644 --- a/lib/common_test/src/common_test.app.src +++ b/lib/common_test/src/common_test.app.src @@ -33,6 +33,8 @@ ct_master_event, ct_master_logs, ct_master_status, + ct_netconfc, + ct_conn_log_h, ct_repeat, ct_rpc, ct_run, @@ -49,6 +51,7 @@ ct_config_xml, ct_slave, cth_log_redirect, + cth_conn_log, cth_surefire ]}, {registered, [ct_logs, diff --git a/lib/common_test/src/ct_conn_log_h.erl b/lib/common_test/src/ct_conn_log_h.erl new file mode 100644 index 0000000000..f3b6781971 --- /dev/null +++ b/lib/common_test/src/ct_conn_log_h.erl @@ -0,0 +1,230 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(ct_conn_log_h). + +%%% +%%% A handler that can be connected to the error_logger event +%%% handler. Writes all ct connection events. See comments in +%%% cth_conn_log for more information. +%%% + +-include("ct_util.hrl"). + +-export([init/1, + handle_event/2, handle_call/2, handle_info/2, + terminate/2]). + +-record(state, {group_leader,logs=[]}). + +-define(WIDTH,80). + +%%%----------------------------------------------------------------- +%%% Callbacks +init({GL,Logs}) -> + open_files(Logs,#state{group_leader=GL}). + +open_files([{ConnMod,{LogType,Logs}}|T],State) -> + case do_open_files(Logs,[]) of + {ok,Fds} -> + open_files(T,State#state{logs=[{ConnMod,{LogType,Fds}} | + State#state.logs]}); + Error -> + Error + end; +open_files([],State) -> + {ok,State}. + + +do_open_files([{Tag,File}|Logs],Acc) -> + case file:open(File, [write]) of + {ok,Fd} -> + do_open_files(Logs,[{Tag,Fd}|Acc]); + {error,Reason} -> + {error,{could_not_open_log,File,Reason}} + end; +do_open_files([],Acc) -> + {ok,lists:reverse(Acc)}. + +handle_event({_Type, GL, _Msg}, State) when node(GL) /= node() -> + {ok, State}; +handle_event({_Type,_GL,{Pid,{ct_connection,Action,ConnName},Report}},State) -> + Info = conn_info(Pid,#conn_log{name=ConnName,action=Action}), + write_report(now(),Info,Report,State), + {ok, State}; +handle_event({_Type,_GL,{Pid,Info=#conn_log{},Report}},State) -> + write_report(now(),conn_info(Pid,Info),Report,State), + {ok, State}; +handle_event({error_report,_,{Pid,_,[{ct_connection,ConnName}|R]}},State) -> + %% Error reports from connection + write_error(now(),conn_info(Pid,#conn_log{name=ConnName}),R,State), + {ok, State}; +handle_event(_, State) -> + {ok, State}. + +handle_info(_, State) -> + {ok, State}. + +handle_call(_Query, State) -> + {ok, {error, bad_query}, State}. + +terminate(_,#state{logs=Logs}) -> + [file:close(Fd) || {_,_,Fds} <- Logs, Fd <- Fds], + ok. + + +%%%----------------------------------------------------------------- +%%% Writing reports +write_report(Time,#conn_log{module=ConnMod}=Info,Data,State) -> + {LogType,Fd} = get_log(Info,State), + io:format(Fd,"~n~s~s~s",[format_head(ConnMod,LogType,Time), + format_title(LogType,Info), + format_data(ConnMod,LogType,Data)]). + +write_error(Time,#conn_log{module=ConnMod}=Info,Report,State) -> + case get_log(Info,State) of + {html,_} -> + %% The error will anyway be written in the html log by the + %% sasl error handler, so don't write it again. + ok; + {LogType,Fd} -> + io:format(Fd,"~n~s~s~s",[format_head(ConnMod,LogType,Time," ERROR"), + format_title(LogType,Info), + format_error(LogType,Report)]) + end. + +get_log(Info,State) -> + case proplists:get_value(Info#conn_log.module,State#state.logs) of + {html,_} -> + {html,State#state.group_leader}; + {LogType,Fds} -> + {LogType,get_fd(Info,Fds)}; + undefined -> + {html,State#state.group_leader} + end. + +get_fd(#conn_log{name=undefined},Fds) -> + proplists:get_value(default,Fds); +get_fd(#conn_log{name=ConnName},Fds) -> + case proplists:get_value(ConnName,Fds) of + undefined -> + proplists:get_value(default,Fds); + Fd -> + Fd + end. + +%%%----------------------------------------------------------------- +%%% Formatting +format_head(ConnMod,LogType,Time) -> + format_head(ConnMod,LogType,Time,""). + +format_head(ConnMod,raw,Time,Text) -> + io_lib:format("~n~p, ~p~s, ",[now_to_time(Time),ConnMod,Text]); +format_head(ConnMod,_,Time,Text) -> + Head = pad_char_end(?WIDTH,pretty_head(now_to_time(Time),ConnMod,Text),$=), + io_lib:format("~n~s",[Head]). + +format_title(raw,#conn_log{client=Client}=Info) -> + io_lib:format("Client ~p ~s ~s",[Client,actionstr(Info),serverstr(Info)]); +format_title(_,Info) -> + Title = pad_char_end(?WIDTH,pretty_title(Info),$=), + io_lib:format("~n~s", [Title]). + +format_data(_,_,NoData) when NoData == ""; NoData == <<>> -> + ""; +format_data(ConnMod,LogType,Data) -> + ConnMod:format_data(LogType,Data). + +format_error(raw,Report) -> + io_lib:format("~n~p~n",[Report]); +format_error(pretty,Report) -> + [io_lib:format("~n ~p: ~p",[K,V]) || {K,V} <- Report]. + + + + +%%%----------------------------------------------------------------- +%%% Helpers +conn_info(LoggingProc, #conn_log{client=undefined} = ConnInfo) -> + conn_info(ConnInfo#conn_log{client=LoggingProc}); +conn_info(_, ConnInfo) -> + conn_info(ConnInfo). + +conn_info(#conn_log{client=Client, module=undefined} = ConnInfo) -> + case ets:lookup(ct_connections,Client) of + [#conn{address=Address,callback=Callback}] -> + ConnInfo#conn_log{address=Address,module=Callback}; + [] -> + ConnInfo + end; +conn_info(ConnInfo) -> + ConnInfo. + + +now_to_time({_,_,MicroS}=Now) -> + {calendar:now_to_local_time(Now),MicroS}. + +pretty_head({{{Y,Mo,D},{H,Mi,S}},MicroS},ConnMod,Text0) -> + Text = string:to_upper(atom_to_list(ConnMod) ++ Text0), + io_lib:format("= ~s ==== ~s-~s-~p::~s:~s:~s,~s ", + [Text,t(D),month(Mo),Y,t(H),t(Mi),t(S), + micro2milli(MicroS)]). + +pretty_title(#conn_log{client=Client}=Info) -> + io_lib:format("= Client ~p ~s Server ~s ", + [Client,actionstr(Info),serverstr(Info)]). + +actionstr(#conn_log{action=send}) -> "----->"; +actionstr(#conn_log{action=recv}) -> "<-----"; +actionstr(#conn_log{action=open}) -> "opened session to"; +actionstr(#conn_log{action=close}) -> "closed session to"; +actionstr(_) -> "<---->". + +serverstr(#conn_log{name=undefined,address=Address}) -> + io_lib:format("~p",[Address]); +serverstr(#conn_log{name=Alias,address=Address}) -> + io_lib:format("~p(~p)",[Alias,Address]). + +month(1) -> "Jan"; +month(2) -> "Feb"; +month(3) -> "Mar"; +month(4) -> "Apr"; +month(5) -> "May"; +month(6) -> "Jun"; +month(7) -> "Jul"; +month(8) -> "Aug"; +month(9) -> "Sep"; +month(10) -> "Oct"; +month(11) -> "Nov"; +month(12) -> "Dec". + +micro2milli(X) -> + pad0(3,integer_to_list(X div 1000)). + +t(X) -> + pad0(2,integer_to_list(X)). + +pad0(N,Str) -> + M = length(Str), + lists:duplicate(N-M,$0) ++ Str. + +pad_char_end(N,Str,Char) -> + case length(lists:flatten(Str)) of + M when M<N -> Str ++ lists:duplicate(N-M,Char); + _ -> Str + end. diff --git a/lib/common_test/src/ct_gen_conn.erl b/lib/common_test/src/ct_gen_conn.erl index 5aab4dd2dd..5df9127725 100644 --- a/lib/common_test/src/ct_gen_conn.erl +++ b/lib/common_test/src/ct_gen_conn.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -27,7 +27,7 @@ -compile(export_all). -export([start/4, stop/1]). --export([call/2, do_within_time/2]). +-export([call/2, call/3, return/2, do_within_time/2]). -ifdef(debug). -define(dbg,true). @@ -39,17 +39,24 @@ name, address, init_data, + reconnect = true, + forward = false, + use_existing = true, + old = false, conn_pid, cb_state, ct_util_server}). %%%----------------------------------------------------------------- -%%% @spec start(Name,Address,InitData,CallbackMod) -> +%%% @spec start(Address,InitData,CallbackMod,Opts) -> %%% {ok,Handle} | {error,Reason} %%% Name = term() %%% CallbackMod = atom() %%% InitData = term() %%% Address = term() +%%% Opts = [Opt] +%%% Opt = {name,Name} | {use_existing_connection,boolean()} | +%%% {reconnect,boolean()} | {forward_messages,boolean()} %%% %%% @doc Open a connection and start the generic connection owner process. %%% @@ -60,42 +67,59 @@ %%% <code>InitData</code> and returna %%% <code>{ok,ConnectionPid,State}</code> or %%% <code>{error,Reason}</code>.</p> +%%% +%%% If no name is given, the <code>Name</code> argument in init/3 will +%%% have the value <code>undefined</code>. +%%% +%%% The callback modules must also export +%%% ``` +%%% handle_msg(Msg,From,State) -> {reply,Reply,State} | +%%% {noreply,State} | +%%% {stop,Reply,State} +%%% terminate(ConnectionPid,State) -> term() +%%% close(Handle) -> term() +%%% ''' +%%% +%%% The <code>close/1</code> callback function is actually a callback +%%% for ct_util, for closing registered connections when +%%% ct_util_server is terminated. <code>Handle</code> is the Pid of +%%% the ct_gen_conn process. +%%% +%%% If option <code>reconnect</code> is <code>true</code>, then the +%%% callback must also export +%%% ``` +%%% reconnect(Address,State) -> {ok,ConnectionPid,State} +%%% ''' +%%% +%%% If option <code>forward_messages</code> is <ocde>true</code>, then +%%% the callback must also export +%%% ``` +%%% handle_msg(Msg,State) -> {noreply,State} | {stop,State} +%%% ''' +%%% +%%% An old interface still exists. This is used by ct_telnet, ct_ftp +%%% and ct_ssh. The start function then has an explicit +%%% <code>Name</code> argument, and no <code>Opts</code> argument. The +%%% callback must export: +%%% +%%% ``` +%%% init(Name,Address,InitData) -> {ok,ConnectionPid,State} +%%% handle_msg(Msg,State) -> {Reply,State} +%%% reconnect(Address,State) -> {ok,ConnectionPid,State} +%%% terminate(ConnectionPid,State) -> term() +%%% close(Handle) -> term() +%%% ''' +%%% +start(Address,InitData,CallbackMod,Opts) when is_list(Opts) -> + do_start(Address,InitData,CallbackMod,Opts); start(Name,Address,InitData,CallbackMod) -> - case ct_util:does_connection_exist(Name,Address,CallbackMod) of - {ok,Pid} -> - log("ct_gen_conn:start","Using existing connection!\n",[]), - {ok,Pid}; - false -> - Self = self(), - Pid = spawn(fun() -> - init_gen(Self, #gen_opts{callback=CallbackMod, - name=Name, - address=Address, - init_data=InitData}) - end), - MRef = erlang:monitor(process,Pid), - receive - {connected,Pid} -> - erlang:demonitor(MRef, [flush]), - ct_util:register_connection(Name,Address,CallbackMod,Pid), - {ok,Pid}; - {Error,Pid} -> - receive {'DOWN',MRef,process,_,_} -> ok end, - Error; - {'DOWN',MRef,process,_,Reason} -> - log("ct_gen_conn:start", - "Connection process died: ~p\n", - [Reason]), - {error,{connection_process_died,Reason}} - end - end. - + do_start(Address,InitData,CallbackMod,[{name,Name},{old,true}]). %%%----------------------------------------------------------------- %%% @spec stop(Handle) -> ok %%% Handle = handle() %%% -%%% @doc Close the telnet connection and stop the process managing it. +%%% @doc Close the connection and stop the process managing it. stop(Pid) -> call(Pid,stop). @@ -103,7 +127,7 @@ stop(Pid) -> %%% @spec log(Heading,Format,Args) -> ok %%% %%% @doc Log activities on the current connection (tool-internal use only). -%%% @see ct_logs:log/3 +%%% @see ct_logs:log/3 log(Heading,Format,Args) -> log(log,[Heading,Format,Args]). @@ -111,7 +135,7 @@ log(Heading,Format,Args) -> %%% @spec start_log(Heading) -> ok %%% %%% @doc Log activities on the current connection (tool-internal use only). -%%% @see ct_logs:start_log/1 +%%% @see ct_logs:start_log/1 start_log(Heading) -> log(start_log,[Heading]). @@ -119,7 +143,7 @@ start_log(Heading) -> %%% @spec cont_log(Format,Args) -> ok %%% %%% @doc Log activities on the current connection (tool-internal use only). -%%% @see ct_logs:cont_log/2 +%%% @see ct_logs:cont_log/2 cont_log(Format,Args) -> log(cont_log,[Format,Args]). @@ -127,7 +151,7 @@ cont_log(Format,Args) -> %%% @spec end_log() -> ok %%% %%% @doc Log activities on the current connection (tool-internal use only). -%%% @see ct_logs:end_log/0 +%%% @see ct_logs:end_log/0 end_log() -> log(end_log,[]). @@ -148,10 +172,10 @@ do_within_time(Fun,Timeout) -> Silent = get(silent), TmpPid = spawn_link(fun() -> put(silent,Silent), R = Fun(), - Self ! {self(),R} + Self ! {self(),R} end), ConnPid = get(conn_pid), - receive + receive {TmpPid,Result} -> Result; {'EXIT',ConnPid,_Reason}=M -> @@ -159,7 +183,7 @@ do_within_time(Fun,Timeout) -> exit(TmpPid,kill), self() ! M, {error,connection_closed} - after + after Timeout -> exit(TmpPid,kill), receive @@ -176,12 +200,65 @@ do_within_time(Fun,Timeout) -> %%%================================================================= %%% Internal functions +do_start(Address,InitData,CallbackMod,Opts0) -> + Opts = check_opts(Opts0,#gen_opts{callback=CallbackMod, + address=Address, + init_data=InitData}), + case ct_util:does_connection_exist(Opts#gen_opts.name, + Address,CallbackMod) of + {ok,Pid} when Opts#gen_opts.use_existing -> + log("ct_gen_conn:start","Using existing connection!\n",[]), + {ok,Pid}; + {ok,Pid} when not Opts#gen_opts.use_existing -> + {error,{connection_exists,Pid}}; + false -> + do_start(Opts) + end. + +do_start(Opts) -> + Self = self(), + Pid = spawn(fun() -> init_gen(Self, Opts) end), + MRef = erlang:monitor(process,Pid), + receive + {connected,Pid} -> + erlang:demonitor(MRef, [flush]), + ct_util:register_connection(Opts#gen_opts.name, Opts#gen_opts.address, + Opts#gen_opts.callback, Pid), + {ok,Pid}; + {Error,Pid} -> + receive {'DOWN',MRef,process,_,_} -> ok end, + Error; + {'DOWN',MRef,process,_,Reason} -> + log("ct_gen_conn:start", + "Connection process died: ~p\n", + [Reason]), + {error,{connection_process_died,Reason}} + end. + +check_opts(Opts0) -> + check_opts(Opts0,#gen_opts{}). + +check_opts([{name,Name}|T],Opts) -> + check_opts(T,Opts#gen_opts{name=Name}); +check_opts([{reconnect,Bool}|T],Opts) -> + check_opts(T,Opts#gen_opts{reconnect=Bool}); +check_opts([{forward_messages,Bool}|T],Opts) -> + check_opts(T,Opts#gen_opts{forward=Bool}); +check_opts([{use_existing_connection,Bool}|T],Opts) -> + check_opts(T,Opts#gen_opts{use_existing=Bool}); +check_opts([{old,Bool}|T],Opts) -> + check_opts(T,Opts#gen_opts{old=Bool}); +check_opts([],Opts) -> + Opts. + call(Pid,Msg) -> + call(Pid,Msg,infinity). +call(Pid,Msg,Timeout) -> MRef = erlang:monitor(process,Pid), Ref = make_ref(), Pid ! {Msg,{self(),Ref}}, receive - {Ref, Result} -> + {Ref, Result} -> erlang:demonitor(MRef, [flush]), case Result of {retry,_Data} -> @@ -189,8 +266,11 @@ call(Pid,Msg) -> Other -> Other end; - {'DOWN',MRef,process,_,Reason} -> + {'DOWN',MRef,process,_,Reason} -> {error,{process_down,Pid,Reason}} + after Timeout -> + erlang:demonitor(MRef, [flush]), + exit(timeout) end. return({To,Ref},Result) -> @@ -198,36 +278,47 @@ return({To,Ref},Result) -> init_gen(Parent,Opts) -> process_flag(trap_exit,true), - CtUtilServer = whereis(ct_util_server), - link(CtUtilServer), put(silent,false), - case catch (Opts#gen_opts.callback):init(Opts#gen_opts.name, - Opts#gen_opts.address, - Opts#gen_opts.init_data) of + try (Opts#gen_opts.callback):init(Opts#gen_opts.name, + Opts#gen_opts.address, + Opts#gen_opts.init_data) of {ok,ConnPid,State} when is_pid(ConnPid) -> link(ConnPid), put(conn_pid,ConnPid), + CtUtilServer = whereis(ct_util_server), + link(CtUtilServer), Parent ! {connected,self()}, loop(Opts#gen_opts{conn_pid=ConnPid, cb_state=State, ct_util_server=CtUtilServer}); {error,Reason} -> Parent ! {{error,Reason},self()} + catch + throw:{error,Reason} -> + Parent ! {{error,Reason},self()} end. loop(Opts) -> receive {'EXIT',Pid,Reason} when Pid==Opts#gen_opts.conn_pid -> - log("Connection down!\nOpening new!","Reason: ~p\nAddress: ~p\n", - [Reason,Opts#gen_opts.address]), - case reconnect(Opts) of - {ok, NewPid, NewState} -> - link(NewPid), - put(conn_pid,NewPid), - loop(Opts#gen_opts{conn_pid=NewPid,cb_state=NewState}); - Error -> + case Opts#gen_opts.reconnect of + true -> + log("Connection down!\nOpening new!", + "Reason: ~p\nAddress: ~p\n", + [Reason,Opts#gen_opts.address]), + case reconnect(Opts) of + {ok, NewPid, NewState} -> + link(NewPid), + put(conn_pid,NewPid), + loop(Opts#gen_opts{conn_pid=NewPid,cb_state=NewState}); + Error -> + ct_util:unregister_connection(self()), + log("Reconnect failed. Giving up!","Reason: ~p\n", + [Error]) + end; + false -> ct_util:unregister_connection(self()), - log("Reconnect failed. Giving up!","Reason: ~p\n",[Error]) + log("Connection closed!","Reason: ~p\n",[Reason]) end; {'EXIT',Pid,Reason} -> case Opts#gen_opts.ct_util_server of @@ -252,24 +343,40 @@ loop(Opts) -> loop(Opts); {{retry,{_Error,_Name,_CPid,Msg}}, From} -> log("Rerunning command","Connection reestablished. Rerunning command...",[]), - {Return,NewState} = + {Return,NewState} = (Opts#gen_opts.callback):handle_msg(Msg,Opts#gen_opts.cb_state), return(From, Return), - loop(Opts#gen_opts{cb_state=NewState}); - {Msg,From={Pid,_Ref}} when is_pid(Pid) -> - {Return,NewState} = + loop(Opts#gen_opts{cb_state=NewState}); + {Msg,From={Pid,_Ref}} when is_pid(Pid), Opts#gen_opts.old==true -> + {Return,NewState} = (Opts#gen_opts.callback):handle_msg(Msg,Opts#gen_opts.cb_state), return(From, Return), - loop(Opts#gen_opts{cb_state=NewState}) + loop(Opts#gen_opts{cb_state=NewState}); + {Msg,From={Pid,_Ref}} when is_pid(Pid) -> + case (Opts#gen_opts.callback):handle_msg(Msg,From, + Opts#gen_opts.cb_state) of + {reply,Reply,NewState} -> + return(From,Reply), + loop(Opts#gen_opts{cb_state=NewState}); + {noreply,NewState} -> + loop(Opts#gen_opts{cb_state=NewState}); + {stop,Reply,NewState} -> + ct_util:unregister_connection(self()), + (Opts#gen_opts.callback):terminate(Opts#gen_opts.conn_pid, + NewState), + return(From,Reply) + end; + Msg when Opts#gen_opts.forward==true -> + case (Opts#gen_opts.callback):handle_msg(Msg,Opts#gen_opts.cb_state) of + {noreply,NewState} -> + loop(Opts#gen_opts{cb_state=NewState}); + {stop,NewState} -> + ct_util:unregister_connection(self()), + (Opts#gen_opts.callback):terminate(Opts#gen_opts.conn_pid, + NewState) + end end. -nozero({ok,S}) when is_list(S) -> - {ok,[C || C <- S, - C=/=0, - C=/=13]}; -nozero(M) -> - M. - reconnect(Opts) -> (Opts#gen_opts.callback):reconnect(Opts#gen_opts.address, Opts#gen_opts.cb_state). @@ -277,10 +384,8 @@ reconnect(Opts) -> log(Func,Args) -> case get(silent) of - true when not ?dbg-> + true when not ?dbg-> ok; _ -> apply(ct_logs,Func,Args) end. - - diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl new file mode 100644 index 0000000000..d9c4a962dc --- /dev/null +++ b/lib/common_test/src/ct_netconfc.erl @@ -0,0 +1,1828 @@ +%%---------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%---------------------------------------------------------------------- +%% File: ct_netconfc.erl +%% +%% Description: +%% This file contains the Netconf client interface +%% +%% @author Support +%% +%% @doc Netconf client module. +%% +%% <p>The Netconf client is compliant with RFC4741 and RFC4742.</p> +%% +%% <p> For each server to test against, the following entry can be +%% added to a configuration file:</p> +%% +%% <p>`{server_id(),options()}.'</p> +%% +%% <p> The `server_id()' or an associated `target_name()' (see +%% {@link ct}) shall then be used in calls to {@link open/2}.</p> +%% +%% <p>If no configuration exists for a server, a session can still be +%% opened by calling {@link open/2} with all necessary options given +%% in the call. The first argument to {@link open/2} can then be any +%% atom.</p> +%% +%% == Logging == +%% +%% The netconf server uses the `error_logger' for logging of netconf +%% traffic. A special purpose error handler is implemented in +%% `ct_conn_log_h'. To use this error handler, add the `cth_conn_log' +%% hook in your test suite, e.g. +%% +%% ``` +%% suite() -> +%% [{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}]. +%%''' +%% +%% The `conn_mod()' is the name of the common_test module implementing +%% the connection protocol, e.g. `ct_netconfc'. +%% +%% The hook option `log_type' specifies the type of logging: +%% +%% <dl> +%% <dt>`raw'</dt> +%% <dd>The sent and received netconf data is logged to a separate +%% text file as is without any formatting. A link to the file is +%% added to the test case HTML log.</dd> +%% +%% <dt>`pretty'</dt> +%% <dd>The sent and received netconf data is logged to a separate +%% text file with XML data nicely indented. A link to the file is +%% added to the test case HTML log.</dd> +%% +%% <dt>`html (default)'</dt> +%% <dd>The sent and received netconf traffic is pretty printed +%% directly in the test case HTML log.</dd> +%% +%% <dt>`silent'</dt> +%% <dd>Netconf traffic is not logged.</dd> +%% </dl> +%% +%% By default, all netconf traffic is logged in one single log +%% file. However, it is possible to have different connections logged +%% in separate files. To do this, use the hook option `hosts' and +%% list the names of the servers/connections that will be used in the +%% suite. Note that the connections must be named for this to work, +%% i.e. they must be opened with {@link open/2}. +%% +%% The `hosts' option has no effect if `log_type' is set to `html' or +%% `silent'. +%% +%% The hook options can also be specified in a configuration file with +%% the configuration variable `ct_conn_log': +%% +%% ``` +%% {ct_conn_log,[{conn_mod(),hook_options()}]}. +%% ''' +%% +%% For example: +%% +%% ``` +%% {ct_conn_log,[{ct_netconfc,[{log_type,pretty}, +%% {hosts,[key_or_name()]}]}]} +%% ''' +%% +%% <b>Note</b> that hook options specified in a configuration file +%% will overwrite the hardcoded hook options in the test suite. +%% +%% === Logging example 1 === +%% +%% The following `ct_hooks' statement will cause pretty printing of +%% netconf traffic to separate logs for the connections named +%% `nc_server1' and `nc_server2'. Any other connections will be logged +%% to default netconf log. +%% +%% ``` +%% suite() -> +%% [{ct_hooks, [{cth_conn_log, [{ct_netconfc,[{log_type,pretty}}, +%% {hosts,[nc_server1,nc_server2]}]} +%% ]}]}]. +%%''' +%% +%% Connections must be opened like this: +%% +%% ``` +%% open(nc_server1,[...]), +%% open(nc_server2,[...]). +%% ''' +%% +%% === Logging example 2 === +%% +%% The following configuration file will cause raw logging of all +%% netconf traffic into one single text file. +%% +%% ``` +%% {ct_conn_log,[{ct_netconfc,[{log_type,raw}]}]}. +%% ''' +%% +%% The `ct_hooks' statement must look like this: +%% +%% ``` +%% suite() -> +%% [{ct_hooks, [{cth_conn_log, []}]}]. +%% ''' +%% +%% The same `ct_hooks' statement without the configuration file would +%% cause HTML logging of all netconf connections into the test case +%% HTML log. +%% +%% == Notifications == +%% +%% The netconf client is also compliant with RFC5277 NETCONF Event +%% Notifications, which defines a mechanism for an asynchronous +%% message notification delivery service for the netconf protocol. +%% +%% Specific functions to support this are {@link +%% create_subscription/6} and {@link get_event_streams/3}. (The +%% functions also exist with other arities.) +%% +%% @end +%%---------------------------------------------------------------------- +-module(ct_netconfc). + +-include("ct_netconfc.hrl"). +-include("ct_util.hrl"). +-include_lib("xmerl/include/xmerl.hrl"). + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([open/1, + open/2, + only_open/1, + only_open/2, + hello/1, + hello/2, + close_session/1, + close_session/2, + kill_session/2, + kill_session/3, + send/2, + send/3, + send_rpc/2, + send_rpc/3, + lock/2, + lock/3, + unlock/2, + unlock/3, + get/2, + get/3, + get_config/3, + get_config/4, + edit_config/3, + edit_config/4, + delete_config/2, + delete_config/3, + copy_config/3, + copy_config/4, + action/2, + action/3, + create_subscription/1, + create_subscription/2, + create_subscription/3, + create_subscription/4, + create_subscription/5, + create_subscription/6, + get_event_streams/2, + get_event_streams/3, + get_capabilities/1, + get_capabilities/2, + get_session_id/1, + get_session_id/2]). + +%%---------------------------------------------------------------------- +%% Exported types +%%---------------------------------------------------------------------- +-export_type([hook_options/0, + conn_mod/0, + log_type/0, + key_or_name/0, + notification/0]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +%% ct_gen_conn callbacks +-export([init/3, + handle_msg/3, + handle_msg/2, + terminate/2, + close/1]). + +%% ct_conn_log callback +-export([format_data/2]). + +%%---------------------------------------------------------------------- +%% Internal defines +%%---------------------------------------------------------------------- +-define(APPLICATION,?MODULE). +-define(VALID_SSH_OPTS,[user, password, user_dir]). +-define(DEFAULT_STREAM,"NETCONF"). + +-define(error(ConnName,Report), + error_logger:error_report([{ct_connection,ConnName}, + {client,self()}, + {module,?MODULE}, + {line,?LINE} | + Report])). + +-define(is_timeout(T), (is_integer(T) orelse T==infinity)). +-define(is_filter(F), + (is_atom(F) orelse (is_tuple(F) andalso is_atom(element(1,F))))). +-define(is_string(S), (is_list(S) andalso is_integer(hd(S)))). + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- +%% Client state +-record(state, {host, + port, + connection, % #connection + capabilities, + session_id, + msg_id = 1, + hello_status, + buff = <<>>, + pending = [], % [#pending] + event_receiver}).% pid + +%% Run-time client options. +-record(options, {ssh = [], % Options for the ssh application + host, + port = ?DEFAULT_PORT, + timeout = ?DEFAULT_TIMEOUT, + name}). + +%% Connection reference +-record(connection, {reference, % {CM,Ch} + host, + port, + name}). + +%% Pending replies from server +-record(pending, {tref, % timer ref (returned from timer:xxx) + ref, % pending ref + msg_id, + op, + caller}).% pid which sent the request + +%%---------------------------------------------------------------------- +%% Type declarations +%%---------------------------------------------------------------------- +-type client() :: handle() | server_id() | target_name(). +-type handle() :: term(). +%% An opaque reference for a connection (netconf session). See {@link +%% ct} for more information. + +-type server_id() :: atom(). +%% A `ServerId' which exists in a configuration file. +-type target_name() :: atom(). +%% A name which is associated to a `server_id()' via a +%% `require' statement or a call to {@link ct:require/2} in the +%% test suite. +-type key_or_name() :: server_id() | target_name(). + +-type options() :: [option()]. +%% Options used for setting up ssh connection to a netconf server. + +-type option() :: {ssh,host()} | {port,inet:port_number()} | {user,string()} | + {password,string()} | {user_dir,string()} | + {timeout,timeout()}. +-type host() :: inet:host_name() | inet:ip_address(). + +-type notification() :: {notification, xml_attributes(), notification_content()}. +-type notification_content() :: [event_time()|simple_xml()]. +-type event_time() :: {eventTime,xml_attributes(),[xs_datetime()]}. + +-type stream_name() :: string(). +-type streams() :: [{stream_name(),[stream_data()]}]. +-type stream_data() :: {description,string()} | + {replaySupport,string()} | + {replayLogCreationTime,string()} | + {replayLogAgedTime,string()}. +%% See XML Schema for Event Notifications found in RFC5277 for further +%% detail about the data format for the string values. + +-type hook_options() :: [hook_option()]. +%% Options that can be given to `cth_conn_log' in the `ct_hook' statement. +-type hook_option() :: {log_type,log_type()} | + {hosts,[key_or_name()]}. +-type log_type() :: raw | pretty | html | silent. +%-type error_handler() :: module(). +-type conn_mod() :: ct_netconfc. + +-type error_reason() :: term(). + +-type simple_xml() :: {xml_tag(), xml_attributes(), xml_content()} | + {xml_tag(), xml_content()} | + xml_tag(). +%% <p>This type is further described in the documentation for the +%% <tt>Xmerl</tt> application.</p> +-type xml_tag() :: atom(). +-type xml_attributes() :: [{xml_attribute_tag(),xml_attribute_value()}]. +-type xml_attribute_tag() :: atom(). +-type xml_attribute_value() :: string(). +-type xml_content() :: [simple_xml() | iolist()]. +-type xpath() :: {xpath,string()}. + +-type netconf_db() :: running | startup | candidate. +-type xs_datetime() :: string(). +%% This date and time identifyer has the same format as the XML type +%% dateTime and compliant to RFC3339. The format is +%% ```[-]CCYY-MM-DDThh:mm:ss[.s][Z|(+|-)hh:mm]''' + +%%---------------------------------------------------------------------- +%% External interface functions +%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +-spec open(Options) -> Result when + Options :: options(), + Result :: {ok,handle()} | {error,error_reason()}. +%% @doc Open a netconf session and exchange `hello' messages. +%% +%% If the server options are specified in a configuration file, or if +%% a named client is needed for logging purposes (see {@section +%% Logging}) use {@link open/2} instead. +%% +%% The opaque `handler()' reference which is returned from this +%% function is required as client identifier when calling any other +%% function in this module. +%% +%% The `timeout' option (milli seconds) is used when setting up +%% the ssh connection and when waiting for the hello message from the +%% server. It is not used for any other purposes during the lifetime +%% of the connection. +%% +%% @end +%%---------------------------------------------------------------------- +open(Options) -> + open(Options,#options{},[],true). + +%%---------------------------------------------------------------------- +-spec open(KeyOrName, ExtraOptions) -> Result when + KeyOrName :: key_or_name(), + ExtraOptions :: options(), + Result :: {ok,handle()} | {error,error_reason()}. +%% @doc Open a named netconf session and exchange `hello' messages. +%% +%% If `KeyOrName' is a configured `server_id()' or a +%% `target_name()' associated with such an ID, then the options +%% for this server will be fetched from the configuration file. +% +%% The `ExtraOptions' argument will be added to the options found in +%% the configuration file. If the same options are given, the values +%% from the configuration file will overwrite `ExtraOptions'. +%% +%% If the server is not specified in a configuration file, use {@link +%% open/1} instead. +%% +%% The opaque `handle()' reference which is returned from this +%% function can be used as client identifier when calling any other +%% function in this module. However, if `KeyOrName' is a +%% `target_name()', i.e. if the server is named via a call to +%% `ct:require/2' or a `require' statement in the test +%% suite, then this name may be used instead of the `handle()'. +%% +%% The `timeout' option (milli seconds) is used when setting up +%% the ssh connection and when waiting for the hello message from the +%% server. It is not used for any other purposes during the lifetime +%% of the connection. +%% +%% @end +%%---------------------------------------------------------------------- +open(KeyOrName, ExtraOpts) -> + open(KeyOrName, ExtraOpts, true). + +open(KeyOrName, ExtraOpts, Hello) -> + SortedExtra = lists:keysort(1,ExtraOpts), + SortedConfig = lists:keysort(1,ct:get_config(KeyOrName,[])), + AllOpts = lists:ukeymerge(1,SortedConfig,SortedExtra), + open(AllOpts,#options{name=KeyOrName},[{name,KeyOrName}],Hello). + +open(OptList,InitOptRec,NameOpt,Hello) -> + case check_options(OptList,undefined,undefined,InitOptRec) of + {Host,Port,Options} -> + case ct_gen_conn:start({Host,Port},Options,?MODULE, + NameOpt ++ [{reconnect,false}, + {use_existing_connection,false}, + {forward_messages,true}]) of + {ok,Client} when Hello==true -> + case hello(Client,Options#options.timeout) of + ok -> + {ok,Client}; + Error -> + Error + end; + Other -> + Other + end; + Error -> + Error + end. + + +%%---------------------------------------------------------------------- +-spec only_open(Options) -> Result when + Options :: options(), + Result :: {ok,handle()} | {error,error_reason()}. +%% @doc Open a netconf session, but don't send `hello'. +%% +%% As {@link open/1} but does not send a `hello' message. +%% +%% @end +%%---------------------------------------------------------------------- +only_open(Options) -> + open(Options,#options{},[],false). + +%%---------------------------------------------------------------------- +-spec only_open(KeyOrName,ExtraOptions) -> Result when + KeyOrName :: key_or_name(), + ExtraOptions :: options(), + Result :: {ok,handle()} | {error,error_reason()}. +%% @doc Open a name netconf session, but don't send `hello'. +%% +%% As {@link open/2} but does not send a `hello' message. +%% +%% @end +%%---------------------------------------------------------------------- +only_open(KeyOrName, ExtraOpts) -> + open(KeyOrName, ExtraOpts, false). + +%%---------------------------------------------------------------------- +%% @spec hello(Client) -> Result +%% @equiv hello(Client, infinity) +hello(Client) -> + hello(Client,?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec hello(Client,Timeout) -> Result when + Client :: handle(), + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Exchange `hello' messages with the server. +%% +%% Sends a `hello' message to the server and waits for the return. +%% +%% @end +%%---------------------------------------------------------------------- +hello(Client,Timeout) -> + call(Client, {hello, Timeout}). + +%%---------------------------------------------------------------------- +%% @spec get_session_id(Client) -> Result +%% @equiv get_session_id(Client, infinity) +get_session_id(Client) -> + get_session_id(Client, ?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec get_session_id(Client, Timeout) -> Result when + Client :: client(), + Timeout :: timeout(), + Result :: pos_integer() | {error,error_reason()}. +%% @doc Returns the session id associated with the given client. +%% +%% @end +%%---------------------------------------------------------------------- +get_session_id(Client, Timeout) -> + call(Client, get_session_id, Timeout). + +%%---------------------------------------------------------------------- +%% @spec get_capabilities(Client) -> Result +%% @equiv get_capabilities(Client, infinity) +get_capabilities(Client) -> + get_capabilities(Client, ?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec get_capabilities(Client, Timeout) -> Result when + Client :: client(), + Timeout :: timeout(), + Result :: [string()] | {error,error_reason()}. +%% @doc Returns the server side capabilities +%% +%% The following capability identifiers, defined in RFC 4741, can be returned: +%% +%% <ul> +%% <li>`"urn:ietf:params:netconf:base:1.0"'</li> +%% <li>`"urn:ietf:params:netconf:capability:writable-running:1.0"'</li> +%% <li>`"urn:ietf:params:netconf:capability:candidate:1.0"'</li> +%% <li>`"urn:ietf:params:netconf:capability:confirmed-commit:1.0"'</li> +%% <li>`"urn:ietf:params:netconf:capability:rollback-on-error:1.0"'</li> +%% <li>`"urn:ietf:params:netconf:capability:startup:1.0"'</li> +%% <li>`"urn:ietf:params:netconf:capability:url:1.0"'</li> +%% <li>`"urn:ietf:params:netconf:capability:xpath:1.0"'</li> +%% </ul> +%% +%% Note, additional identifiers may exist, e.g. server side namespace. +%% +%% @end +%%---------------------------------------------------------------------- +get_capabilities(Client, Timeout) -> + call(Client, get_capabilities, Timeout). + +%% @private +send(Client, SimpleXml) -> + send(Client, SimpleXml, ?DEFAULT_TIMEOUT). +%% @private +send(Client, SimpleXml, Timeout) -> + call(Client,{send, Timeout, SimpleXml}). + +%% @private +send_rpc(Client, SimpleXml) -> + send_rpc(Client, SimpleXml, ?DEFAULT_TIMEOUT). +%% @private +send_rpc(Client, SimpleXml, Timeout) -> + call(Client,{send_rpc, SimpleXml, Timeout}). + + + +%%---------------------------------------------------------------------- +%% @spec lock(Client, Target) -> Result +%% @equiv lock(Client, Target, infinity) +lock(Client, Target) -> + lock(Client, Target,?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec lock(Client, Target, Timeout) -> Result when + Client :: client(), + Target :: netconf_db(), + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Unlock configuration target. +%% +%% Which target parameters that can be used depends on if +%% `:candidate' and/or `:startup' are supported by the +%% server. If successfull, the configuration system of the device is +%% not available to other clients (Netconf, CORBA, SNMP etc). Locks +%% are intended to be short-lived. +%% +%% The operations {@link kill_session/2} or {@link kill_session/3} can +%% be used to force the release of a lock owned by another Netconf +%% session. How this is achieved by the server side is implementation +%% specific. +%% +%% @end +%%---------------------------------------------------------------------- +lock(Client, Target, Timeout) -> + call(Client,{send_rpc_op,lock,[Target],Timeout}). + +%%---------------------------------------------------------------------- +%% @spec unlock(Client, Target) -> Result +%% @equiv unlock(Client, Target, infinity) +unlock(Client, Target) -> + unlock(Client, Target,?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec unlock(Client, Target, Timeout) -> Result when + Client :: client(), + Target :: netconf_db(), + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Unlock configuration target. +%% +%% If the client earlier has aquired a lock, via {@link lock/2} or +%% {@link lock/3}, this operation release the associated lock. To be +%% able to access another target than `running', the server must +%% support `:candidate' and/or `:startup'. +%% +%% @end +%%---------------------------------------------------------------------- +unlock(Client, Target, Timeout) -> + call(Client, {send_rpc_op, unlock, [Target], Timeout}). + +%%---------------------------------------------------------------------- +%% @spec get(Client, Filter) -> Result +%% @equiv get(Client, Filter, infinity) +get(Client, Filter) -> + get(Client, Filter, ?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec get(Client, Filter, Timeout) -> Result when + Client :: client(), + Filter :: simple_xml() | xpath(), + Timeout :: timeout(), + Result :: {ok,simple_xml()} | {error,error_reason()}. +%% @doc Get data. +%% +%% This operation returns both configuration and state data from the +%% server. +%% +%% Filter type `xpath' can only be used if the server supports +%% `:xpath'. +%% +%% @end +%%---------------------------------------------------------------------- +get(Client, Filter, Timeout) -> + call(Client,{send_rpc_op, get, [Filter], Timeout}). + +%%---------------------------------------------------------------------- +%% @spec get_config(Client, Source, Filter) -> Result +%% @equiv get_config(Client, Source, Filter, infinity) +get_config(Client, Source, Filter) -> + get_config(Client, Source, Filter, ?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec get_config(Client, Source, Filter, Timeout) -> Result when + Client :: client(), + Source :: netconf_db(), + Filter :: simple_xml() | xpath(), + Timeout :: timeout(), + Result :: {ok,simple_xml()} | {error,error_reason()}. +%% @doc Get configuration data. +%% +%% To be able to access another source than `running', the server +%% must advertise `:candidate' and/or `:startup'. +%% +%% Filter type `xpath' can only be used if the server supports +%% `:xpath'. +%% +%% +%% @end +%%---------------------------------------------------------------------- +get_config(Client, Source, Filter, Timeout) -> + call(Client, {send_rpc_op, get_config, [Source, Filter], Timeout}). + +%%---------------------------------------------------------------------- +%% @spec edit_config(Client, Target, Config) -> Result +%% @equiv edit_config(Client, Target, Config, infinity) +edit_config(Client, Target, Config) -> + edit_config(Client, Target, Config, ?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec edit_config(Client, Target, Config, Timeout) -> Result when + Client :: client(), + Target :: netconf_db(), + Config :: simple_xml(), + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Edit configuration data. +%% +%% Per default only the running target is available, unless the server +%% include `:candidate' or `:startup' in its list of +%% capabilities. +%% +%% @end +%%---------------------------------------------------------------------- +edit_config(Client, Target, Config, Timeout) -> + call(Client, {send_rpc_op, edit_config, [Target,Config], Timeout}). + + +%%---------------------------------------------------------------------- +%% @spec delete_config(Client, Target) -> Result +%% @equiv delete_config(Client, Target, infinity) +delete_config(Client, Target) -> + delete_config(Client, Target, ?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec delete_config(Client, Target, Timeout) -> Result when + Client :: client(), + Target :: startup | candidate, + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Delete configuration data. +%% +%% The running configuration cannot be deleted and `:candidate' +%% or `:startup' must be advertised by the server. +%% +%% @end +%%---------------------------------------------------------------------- +delete_config(Client, Target, Timeout) when Target == startup; + Target == candidate -> + call(Client,{send_rpc_op, delete_config, [Target], Timeout}). + +%%---------------------------------------------------------------------- +%% @spec copy_config(Client, Source, Target) -> Result +%% @equiv copy_config(Client, Source, Target, infinity) +copy_config(Client, Source, Target) -> + copy_config(Client, Source, Target, ?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec copy_config(Client, Target, Source, Timeout) -> Result when + Client :: client(), + Target :: netconf_db(), + Source :: netconf_db(), + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Copy configuration data. +%% +%% Which source and target options that can be issued depends on the +%% capabilities supported by the server. I.e. `:candidate' and/or +%% `:startup' are required. +%% +%% @end +%%---------------------------------------------------------------------- +copy_config(Client, Target, Source, Timeout) -> + call(Client,{send_rpc_op, copy_config, [Target, Source], Timeout}). + +%%---------------------------------------------------------------------- +%% @spec action(Client, Action) -> Result +%% @equiv action(Client, Action, infinity) +action(Client,Action) -> + action(Client,Action,?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec action(Client, Action, Timeout) -> Result when + Client :: client(), + Action :: simple_xml(), + Timeout :: timeout(), + Result :: {ok,simple_xml()} | {error,error_reason()}. +%% @doc Execute an action. +%% +%% @end +%%---------------------------------------------------------------------- +action(Client,Action,Timeout) -> + call(Client,{send_rpc_op, action, [Action], Timeout}). + +%%---------------------------------------------------------------------- +create_subscription(Client) -> + create_subscription(Client,?DEFAULT_STREAM,?DEFAULT_TIMEOUT). + +create_subscription(Client,Timeout) + when ?is_timeout(Timeout) -> + create_subscription(Client,?DEFAULT_STREAM,Timeout); +create_subscription(Client,Stream) + when is_list(Stream) -> + create_subscription(Client,Stream,?DEFAULT_TIMEOUT); +create_subscription(Client,Filter) + when ?is_filter(Filter) -> + create_subscription(Client,?DEFAULT_STREAM,Filter, + ?DEFAULT_TIMEOUT). + +create_subscription(Client,Stream,Timeout) + when is_list(Stream) andalso + ?is_timeout(Timeout) -> + call(Client,{send_rpc_op,{create_subscription,self()}, + [Stream,undefined,undefined,undefined], + Timeout}); +create_subscription(Client,StartTime,StopTime) + when is_list(StartTime) andalso + is_list(StopTime) -> + create_subscription(Client,?DEFAULT_STREAM,StartTime,StopTime, + ?DEFAULT_TIMEOUT); +create_subscription(Client,Filter,Timeout) + when ?is_filter(Filter) andalso + ?is_timeout(Timeout) -> + create_subscription(Client,?DEFAULT_STREAM,Filter,Timeout); +create_subscription(Client,Stream,Filter) + when is_list(Stream) andalso + ?is_filter(Filter) -> + create_subscription(Client,Stream,Filter,?DEFAULT_TIMEOUT). + +create_subscription(Client,StartTime,StopTime,Timeout) + when is_list(StartTime) andalso + is_list(StopTime) andalso + ?is_timeout(Timeout) -> + create_subscription(Client,?DEFAULT_STREAM,StartTime,StopTime,Timeout); +create_subscription(Client,Stream,StartTime,StopTime) + when is_list(Stream) andalso + is_list(StartTime) andalso + is_list(StopTime) -> + create_subscription(Client,Stream,StartTime,StopTime,?DEFAULT_TIMEOUT); +create_subscription(Client,Filter,StartTime,StopTime) + when ?is_filter(Filter) andalso + is_list(StartTime) andalso + is_list(StopTime) -> + create_subscription(Client,?DEFAULT_STREAM,Filter, + StartTime,StopTime,?DEFAULT_TIMEOUT); +create_subscription(Client,Stream,Filter,Timeout) + when is_list(Stream) andalso + ?is_filter(Filter) andalso + ?is_timeout(Timeout) -> + call(Client,{send_rpc_op,{create_subscription,self()}, + [Stream,Filter,undefined,undefined], + Timeout}). + +create_subscription(Client,Stream,StartTime,StopTime,Timeout) + when is_list(Stream) andalso + is_list(StartTime) andalso + is_list(StopTime) andalso + ?is_timeout(Timeout) -> + call(Client,{send_rpc_op,{create_subscription,self()}, + [Stream,undefined,StartTime,StopTime], + Timeout}); +create_subscription(Client,Stream,Filter,StartTime,StopTime) + when is_list(Stream) andalso + ?is_filter(Filter) andalso + is_list(StartTime) andalso + is_list(StopTime) -> + create_subscription(Client,Stream,Filter,StartTime,StopTime,?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec create_subscription(Client, Stream, Filter,StartTime, StopTime, Timeout) -> + Result when + Client :: client(), + Stream :: stream_name(), + Filter :: simple_xml(), + StartTime :: xs_datetime(), + StopTime :: xs_datetime(), + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Create a subscription for event notifications. +%% +%% This function sets up a subscription for netconf event +%% notifications of the given stream type, matching the given +%% filter. The calling process will receive notifications as messages +%% of type `notification()'. +%% +%% <dl> +%% <dt>Stream:</dt> +%% <dd> An optional parameter that indicates which stream of events +%% is of interest. If not present, events in the default NETCONF +%% stream will be sent.</dd> +%% +%% <dt>Filter:</dt> +%% <dd>An optional parameter that indicates which subset of all +%% possible events is of interest. The format of this parameter is +%% the same as that of the filter parameter in the NETCONF protocol +%% operations. If not present, all events not precluded by other +%% parameters will be sent. See section 3.6 for more information on +%% filters.</dd> +%% +%% <dt>StartTime:</dt> +%% <dd>An optional parameter used to trigger the replay feature and +%% indicate that the replay should start at the time specified. If +%% `StartTime' is not present, this is not a replay subscription. +%% It is not valid to specify start times that are later than the +%% current time. If the `StartTime' specified is earlier than the +%% log can support, the replay will begin with the earliest +%% available notification. This parameter is of type dateTime and +%% compliant to [RFC3339]. Implementations must support time +%% zones.</dd> +%% +%% <dt>StopTime:</dt> +%% <dd>An optional parameter used with the optional replay feature +%% to indicate the newest notifications of interest. If `StopTime' +%% is not present, the notifications will continue until the +%% subscription is terminated. Must be used with and be later than +%% `StartTime'. Values of `StopTime' in the future are valid. This +%% parameter is of type dateTime and compliant to [RFC3339]. +%% Implementations must support time zones.</dd> +%% </dl> +%% +%% See RFC5277 for further details about the event notification +%% mechanism. +%% +%% @end +%%---------------------------------------------------------------------- +create_subscription(Client,Stream,Filter,StartTime,StopTime,Timeout) -> + call(Client,{send_rpc_op,{create_subscription, self()}, + [Stream,Filter,StartTime,StopTime], + Timeout}). + +%%---------------------------------------------------------------------- +%% @spec get_event_streams(Client, Timeout) -> Result +%% @equiv get_event_streams(Client, [], Timeout) +get_event_streams(Client,Timeout) when is_integer(Timeout); Timeout==infinity -> + get_event_streams(Client,[],Timeout); + +%%---------------------------------------------------------------------- +%% @spec get_event_streams(Client, Streams) -> Result +%% @equiv get_event_streams(Client, Streams, infinity) +get_event_streams(Client,Streams) when is_list(Streams) -> + get_event_streams(Client,Streams,?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec get_event_streams(Client, Streams, Timeout) + -> Result when + Client :: client(), + Streams :: [stream_name()], + Timeout :: timeout(), + Result :: {ok,streams()} | {error,error_reason()}. +%% @doc Send a request to get the given event streams. +%% +%% `Streams' is a list of stream names. The following filter will +%% be sent to the netconf server in a `get' request: +%% +%% ``` +%% <netconf xmlns="urn:ietf:params:xml:ns:netmod:notification"> +%% <streams> +%% <stream> +%% <name>StreamName1</name> +%% </stream> +%% <stream> +%% <name>StreamName2</name> +%% </stream> +%% ... +%% </streams> +%% </netconf> +%% ''' +%% +%% If `Streams' is an empty list, ALL streams will be requested +%% by sending the following filter: +%% +%% ``` +%% <netconf xmlns="urn:ietf:params:xml:ns:netmod:notification"> +%% <streams/> +%% </netconf> +%% ''' +%% +%% If more complex filtering is needed, a use {@link get/2} or {@link +%% get/3} and specify the exact filter according to XML Schema for +%% Event Notifications found in RFC5277. +%% +%% @end +%%---------------------------------------------------------------------- +get_event_streams(Client,Streams,Timeout) -> + call(Client,{get_event_streams,Streams,Timeout}). + + +%%---------------------------------------------------------------------- +%% @spec close_session(Client) -> Result +%% @equiv close_session(Client, infinity) +close_session(Client) -> + close_session(Client, ?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec close_session(Client, Timeout) -> Result when + Client :: client(), + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Request graceful termination of the session associated with the client. +%% +%% When a netconf server receives a `close-session' request, it +%% will gracefully close the session. The server will release any +%% locks and resources associated with the session and gracefully +%% close any associated connections. Any NETCONF requests received +%% after a `close-session' request will be ignored. +%% +%% @end +%%---------------------------------------------------------------------- +close_session(Client, Timeout) -> + call(Client,{send_rpc_op, close_session, [], Timeout}). + + +%%---------------------------------------------------------------------- +%% @spec kill_session(Client, SessionId) -> Result +%% @equiv kill_session(Client, SessionId, infinity) +kill_session(Client, SessionId) -> + kill_session(Client, SessionId, ?DEFAULT_TIMEOUT). + +%%---------------------------------------------------------------------- +-spec kill_session(Client, SessionId, Timeout) -> Result when + Client :: client(), + SessionId :: pos_integer(), + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Force termination of the session associated with the supplied +%% session id. +%% +%% The server side shall abort any operations currently in process, +%% release any locks and resources associated with the session, and +%% close any associated connections. +%% +%% Only if the server is in the confirmed commit phase, the +%% configuration will be restored to its state before entering the +%% confirmed commit phase. Otherwise, no configuration roll back will +%% be performed. +%% +%% If the given `SessionId' is equal to the current session id, +%% an error will be returned. +%% +%% @end +%% ---------------------------------------------------------------------- +kill_session(Client, SessionId, Timeout) -> + call(Client,{send_rpc_op, kill_session, [SessionId], Timeout}). + + +%%---------------------------------------------------------------------- +%% Callback functions +%%---------------------------------------------------------------------- + +%% @private +init(_KeyOrName,{_Host,_Port},Options) -> + case ssh_open(Options) of + {ok, Connection} -> + log(Connection,open), + {ConnPid,_} = Connection#connection.reference, + {ok, ConnPid, #state{connection = Connection}}; + {error,Reason}-> + {error,Reason} + end. + +%% @private +terminate(_, #state{connection=Connection}) -> + ssh_close(Connection), + log(Connection,close), + ok. + +%% @private +handle_msg({hello,Timeout}, From, + #state{connection=Connection,hello_status=HelloStatus} = State) -> + case do_send(Connection, client_hello()) of + ok -> + case HelloStatus of + undefined -> + {Ref,TRef} = set_request_timer(Timeout), + {noreply, State#state{hello_status=#pending{tref=TRef, + ref=Ref, + caller=From}}}; + received -> + {reply, ok, State#state{hello_status=done}}; + {error,Reason} -> + {stop, {error,Reason}, State} + end; + Error -> + {stop, Error, State} + end; +handle_msg(_, _From, #state{session_id=undefined} = State) -> + %% Hello is not yet excanged - this shall never happen + {reply,{error,waiting_for_hello},State}; +handle_msg(get_capabilities, _From, #state{capabilities = Caps} = State) -> + {reply, Caps, State}; +handle_msg(get_session_id, _From, #state{session_id = Id} = State) -> + {reply, Id, State}; +handle_msg({send, Timeout, SimpleXml}, From, + #state{connection=Connection,pending=Pending} = State) -> + case do_send(Connection, SimpleXml) of + ok -> + {Ref,TRef} = set_request_timer(Timeout), + {noreply, State#state{pending=[#pending{tref=TRef, + ref=Ref, + caller=From} | Pending]}}; + Error -> + {reply, Error, State} + end; +handle_msg({send_rpc, SimpleXml, Timeout}, From, State) -> + do_send_rpc(undefined, SimpleXml, Timeout, From, State); +handle_msg({send_rpc_op, Op, Data, Timeout}, From, State) -> + SimpleXml = encode_rpc_operation(Op,Data), + do_send_rpc(Op, SimpleXml, Timeout, From, State); +handle_msg({get_event_streams=Op,Streams,Timeout}, From, State) -> + Filter = {netconf,?NETMOD_NOTIF_NAMESPACE_ATTR, + [{streams,[{stream,[{name,[Name]}]} || Name <- Streams]}]}, + SimpleXml = encode_rpc_operation(get,[Filter]), + do_send_rpc(Op, SimpleXml, Timeout, From, State). + +handle_msg({ssh_cm, _CM, {data, _Ch, _Type, Data}}, State) -> + handle_data(Data, State); +handle_msg({ssh_cm, _CM, {closed,_Ch}}, State) -> + %% This will happen if the server terminates the connection, as in + %% kill-session (or if ssh:close is called from somewhere + %% unexpected). + + %%! Log this?? - i.e. as server closing the connection + %%! Currently the log will say that the client closed the + %%! connection - due to terminate/2 + + {stop, State}; +handle_msg({Ref,timeout}, + #state{hello_status=#pending{ref=Ref,caller=Caller}} = State) -> + ct_gen_conn:return(Caller,{error,{hello_session_failed,timeout}}), + {stop,State#state{hello_status={error,timeout}}}; +handle_msg({Ref,timeout},#state{pending=Pending} = State) -> + {value,#pending{caller=Caller},Pending1} = + lists:keytake(Ref,#pending.ref,Pending), + ct_gen_conn:return(Caller,{error,timeout}), + {noreply,State#state{pending=Pending1}}. + +%% @private +%% Called by ct_util_server to close registered connections before terminate. +close(Client) -> + case get_handle(Client) of + {ok,Pid} -> + case ct_gen_conn:stop(Pid) of + {error,{process_down,Pid,noproc}} -> + {error,already_closed}; + Result -> + Result + end; + Error -> + Error + end. + + +%%---------------------------------------------------------------------- +%% Internal functions +%%---------------------------------------------------------------------- +call(Client, Msg) -> + call(Client, Msg, infinity). +call(Client, Msg, Timeout) -> + case get_handle(Client) of + {ok,Pid} -> + case ct_gen_conn:call(Pid,Msg,Timeout) of + {error,{process_down,Client,noproc}} -> + {error,no_such_client}; + {error,{process_down,Client,normal}} -> + {error,closed}; + {error,{process_down,Client,Reason}} -> + {error,{closed,Reason}}; + Other -> + Other + end; + Error -> + Error + end. + +get_handle(Client) when is_pid(Client) -> + {ok,Client}; +get_handle(Client) -> + case ct_util:get_connections(Client, ?MODULE) of + {ok,[{Pid,_}]} -> + {ok,Pid}; + {ok,[]} -> + {error,{no_connection_found,Client}}; + {ok,Conns} -> + {error,{multiple_connections_found,Client,Conns}}; + Error -> + Error + end. + +check_options([], undefined, _Port, _Options) -> + {error, no_host_address}; +check_options([], _Host, undefined, _Options) -> + {error, no_port}; +check_options([], Host, Port, Options) -> + {Host,Port,Options}; +check_options([{ssh, Host}|T], _, Port, #options{} = Options) -> + check_options(T, Host, Port, Options#options{host=Host}); +check_options([{port,Port}|T], Host, _, #options{} = Options) -> + check_options(T, Host, Port, Options#options{port=Port}); +check_options([{timeout, Timeout}|T], Host, Port, Options) + when is_integer(Timeout); Timeout==infinity -> + check_options(T, Host, Port, Options#options{timeout = Timeout}); +check_options([{X,_}=Opt|T], Host, Port, #options{ssh=SshOpts}=Options) -> + case lists:member(X,?VALID_SSH_OPTS) of + true -> + check_options(T, Host, Port, Options#options{ssh=[Opt|SshOpts]}); + false -> + {error, {invalid_option, Opt}} + end. + +%%%----------------------------------------------------------------- +set_request_timer(infinity) -> + {undefined,undefined}; +set_request_timer(T) -> + Ref = make_ref(), + {ok,TRef} = timer:send_after(T,{Ref,timeout}), + {Ref,TRef}. + + +%%%----------------------------------------------------------------- +client_hello() -> + {hello, ?NETCONF_NAMESPACE_ATTR, + [{capabilities, + [{capability,[?NETCONF_BASE_CAP++?NETCONF_BASE_CAP_VSN]}]}]}. + +%%%----------------------------------------------------------------- + +encode_rpc_operation(Lock,[Target]) when Lock==lock; Lock==unlock -> + {Lock,[{target,[Target]}]}; +encode_rpc_operation(get,[Filter]) -> + {get,filter(Filter)}; +encode_rpc_operation(get_config,[Source,Filter]) -> + {'get-config',[{source,[Source]}] ++ filter(Filter)}; +encode_rpc_operation(edit_config,[Target,Config]) -> + {'edit-config',[{target,[Target]},{config,[Config]}]}; +encode_rpc_operation(delete_config,[Target]) -> + {'delete-config',[{target,[Target]}]}; +encode_rpc_operation(copy_config,[Target,Source]) -> + {'copy-config',[{target,[Target]},{source,[Source]}]}; +encode_rpc_operation(action,[Action]) -> + {action,?ACTION_NAMESPACE_ATTR,[{data,[Action]}]}; +encode_rpc_operation(kill_session,[SessionId]) -> + {'kill-session',[{'session-id',[integer_to_list(SessionId)]}]}; +encode_rpc_operation(close_session,[]) -> + 'close-session'; +encode_rpc_operation({create_subscription,_}, + [Stream,Filter,StartTime,StopTime]) -> + {'create-subscription',?NETCONF_NOTIF_NAMESPACE_ATTR, + [{stream,[Stream]}] ++ + filter(Filter) ++ + maybe_element(startTime,StartTime) ++ + maybe_element(stopTime,StopTime)}. + +filter(undefined) -> + []; +filter({xpath,Filter}) when ?is_string(Filter) -> + [{filter,[{type,"xpath"},{select, Filter}],[]}]; +filter(Filter) -> + [{filter,[{type,"subtree"}],[Filter]}]. + +maybe_element(_,undefined) -> + []; +maybe_element(Tag,Value) -> + [{Tag,[Value]}]. + +%%%----------------------------------------------------------------- +%%% Send XML data to server +do_send_rpc(PendingOp,SimpleXml,Timeout,Caller, + #state{connection=Connection,msg_id=MsgId,pending=Pending} = State) -> + case do_send_rpc(Connection, MsgId, SimpleXml) of + ok -> + {Ref,TRef} = set_request_timer(Timeout), + {noreply, State#state{msg_id=MsgId+1, + pending=[#pending{tref=TRef, + ref=Ref, + msg_id=MsgId, + op=PendingOp, + caller=Caller} | Pending]}}; + Error -> + {reply, Error, State#state{msg_id=MsgId+1}} + end. + +do_send_rpc(Connection, MsgId, SimpleXml) -> + do_send(Connection, + {rpc, + [{'message-id',MsgId} | ?NETCONF_NAMESPACE_ATTR], + [SimpleXml]}). + +do_send(Connection, SimpleXml) -> + Xml=to_xml_doc(SimpleXml), + log(Connection,send,Xml), + ssh_send(Connection, Xml). + +to_xml_doc(Simple) -> + Prolog = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", + Xml = list_to_binary(xmerl:export_simple([Simple], + xmerl_xml, + [#xmlAttribute{name=prolog, + value=Prolog}])), + <<Xml/binary,?END_TAG/binary>>. + +%%%----------------------------------------------------------------- +%%% Parse and handle received XML data +handle_data(NewData,#state{connection=Connection,buff=Buff} = State) -> + log(Connection,recv,NewData), + Data = <<Buff/binary,NewData/binary>>, + case xmerl_sax_parser:stream(<<>>, + [{continuation_fun,fun sax_cont/1}, + {continuation_state,{Data,Connection,false}}, + {event_fun,fun sax_event/3}, + {event_state,[]}]) of + {ok, Simple, Rest} -> + decode(Simple,State#state{buff=Rest}); + {fatal_error,_Loc,Reason,_EndTags,_EventState} -> + ?error(Connection#connection.name,[{parse_error,Reason}, + {data,Data}]), + case Reason of + {could_not_fetch_data,Msg} -> + handle_msg(Msg,State#state{buff = <<>>}); + _Other -> + Pending1 = + case State#state.pending of + [] -> + []; + Pending -> + %% Assuming the first request gets the + %% first answer + P=#pending{tref=TRef,caller=Caller} = + lists:last(Pending), + timer:cancel(TRef), + Reason1 = {failed_to_parse_received_data,Reason}, + ct_gen_conn:return(Caller,{error,Reason1}), + lists:delete(P,Pending) + end, + {noreply,State#state{pending=Pending1,buff = <<>>}} + end + end. + +%%%----------------------------------------------------------------- +%%% Parsing of XML data +%% Contiuation function for the sax parser +sax_cont(done) -> + {<<>>,done}; +sax_cont({Data,Connection,false}) -> + case binary:split(Data,[?END_TAG],[]) of + [All] -> + %% No end tag found. Remove what could be a part + %% of an end tag from the data and save for next + %% iteration + SafeSize = size(All)-5, + <<New:SafeSize/binary,Save:5/binary>> = All, + {New,{Save,Connection,true}}; + [_Msg,_Rest]=Msgs -> + %% We have at least one full message. Any excess data will + %% be returned from xmerl_sax_parser:stream/2 in the Rest + %% parameter. + {list_to_binary(Msgs),done} + end; +sax_cont({Data,Connection,true}) -> + case ssh_receive_data() of + {ok,Bin} -> + log(Connection,recv,Bin), + sax_cont({<<Data/binary,Bin/binary>>,Connection,false}); + {error,Reason} -> + throw({could_not_fetch_data,Reason}) + end. + + + +%% Event function for the sax parser. It builds a simple XML structure. +%% Care is taken to keep namespace attributes and prefixes as in the original XML. +sax_event(Event,_Loc,State) -> + sax_event(Event,State). + +sax_event({startPrefixMapping, Prefix, Uri},Acc) -> + %% startPrefixMapping will always come immediately before the + %% startElement where the namespace is defined. + [{xmlns,{Prefix,Uri}}|Acc]; +sax_event({startElement,_Uri,_Name,QN,Attrs},Acc) -> + %% Pick out any namespace attributes inserted due to a + %% startPrefixMapping event.The rest of Acc will then be only + %% elements. + {NsAttrs,NewAcc} = split_attrs_and_elements(Acc,[]), + Tag = qn_to_tag(QN), + [{Tag,NsAttrs ++ parse_attrs(Attrs),[]}|NewAcc]; +sax_event({endElement,_Uri,_Name,_QN},[{Name,Attrs,Cont},{Parent,PA,PC}|Acc]) -> + [{Parent,PA,[{Name,Attrs,lists:reverse(Cont)}|PC]}|Acc]; +sax_event(endDocument,[{Tag,Attrs,Cont}]) -> + {Tag,Attrs,lists:reverse(Cont)}; +sax_event({characters,String},[{Name,Attrs,Cont}|Acc]) -> + [{Name,Attrs,[String|Cont]}|Acc]; +sax_event(_Event,State) -> + State. + +split_attrs_and_elements([{xmlns,{Prefix,Uri}}|Rest],Attrs) -> + split_attrs_and_elements(Rest,[{xmlnstag(Prefix),Uri}|Attrs]); +split_attrs_and_elements(Elements,Attrs) -> + {Attrs,Elements}. + +xmlnstag([]) -> + xmlns; +xmlnstag(Prefix) -> + list_to_atom("xmlns:"++Prefix). + +qn_to_tag({[],Name}) -> + list_to_atom(Name); +qn_to_tag({Prefix,Name}) -> + list_to_atom(Prefix ++ ":" ++ Name). + +parse_attrs([{_Uri, [], Name, Value}|Attrs]) -> + [{list_to_atom(Name),Value}|parse_attrs(Attrs)]; +parse_attrs([{_Uri, Prefix, Name, Value}|Attrs]) -> + [{list_to_atom(Prefix ++ ":" ++ Name),Value}|parse_attrs(Attrs)]; +parse_attrs([]) -> + []. + + +%%%----------------------------------------------------------------- +%%% Decoding of parsed XML data +decode({Tag,Attrs,_}=E, #state{connection=Connection,pending=Pending}=State) -> + ConnName = Connection#connection.name, + case get_local_name_atom(Tag) of + 'rpc-reply' -> + case get_msg_id(Attrs) of + undefined -> + case Pending of + [#pending{msg_id=MsgId}] -> + ?error(ConnName,[{warning,rpc_reply_missing_msg_id}, + {assuming,MsgId}]), + decode_rpc_reply(MsgId,E,State); + _ -> + ?error(ConnName,[{error,rpc_reply_missing_msg_id}]), + {noreply,State} + end; + MsgId -> + decode_rpc_reply(MsgId,E,State) + end; + hello -> + case State#state.hello_status of + undefined -> + case decode_hello(E) of + {ok,SessionId,Capabilities} -> + {noreply,State#state{session_id = SessionId, + capabilities = Capabilities, + hello_status = received}}; + {error,Reason} -> + {noreply,State#state{hello_status = {error,Reason}}} + end; + #pending{tref=TRef,caller=Caller} -> + timer:cancel(TRef), + case decode_hello(E) of + {ok,SessionId,Capabilities} -> + ct_gen_conn:return(Caller,ok), + {noreply,State#state{session_id = SessionId, + capabilities = Capabilities, + hello_status = done}}; + {error,Reason} -> + ct_gen_conn:return(Caller,{error,Reason}), + {stop,State#state{hello_status={error,Reason}}} + end; + Other -> + ?error(ConnName,[{got_unexpected_hello,E}, + {hello_status,Other}]), + {noreply,State} + end; + notification -> + EventReceiver = State#state.event_receiver, + EventReceiver ! E, + {noreply,State}; + Other -> + %% Result of send/2, when not sending an rpc request - or + %% if netconf server sends noise. Can handle this only if + %% there is just one pending that matches (i.e. has + %% undefined msg_id and op) + case [P || P = #pending{msg_id=undefined,op=undefined} <- Pending] of + [#pending{tref=TRef, + caller=Caller}] -> + timer:cancel(TRef), + ct_gen_conn:return(Caller,E), + {noreply,State#state{pending=[]}}; + _ -> + ?error(ConnName,[{got_unexpected_msg,Other}, + {expecting,Pending}]), + {noreply,State} + end + + end. + +get_msg_id(Attrs) -> + case lists:keyfind('message-id',1,Attrs) of + {_,Str} -> + list_to_integer(Str); + false -> + undefined + end. + +decode_rpc_reply(MsgId,{_,Attrs,Content0}=E,#state{pending=Pending} = State) -> + case lists:keytake(MsgId,#pending.msg_id,Pending) of + {value, #pending{tref=TRef,op=Op,caller=Caller}, Pending1} -> + timer:cancel(TRef), + Content = forward_xmlns_attr(Attrs,Content0), + {CallerReply,{ServerReply,State2}} = + do_decode_rpc_reply(Op,Content,State#state{pending=Pending1}), + ct_gen_conn:return(Caller,CallerReply), + {ServerReply,State2}; + false -> + %% Result of send/2, when receiving a correct + %% rpc-reply. Can handle this only if there is just one + %% pending that matches (i.e. has undefined msg_id and op) + case [P || P = #pending{msg_id=undefined,op=undefined} <- Pending] of + [#pending{tref=TRef, + msg_id=undefined, + op=undefined, + caller=Caller}] -> + timer:cancel(TRef), + ct_gen_conn:return(Caller,E), + {noreply,State#state{pending=[]}}; + _ -> + ConnName = (State#state.connection)#connection.name, + ?error(ConnName,[{got_unexpected_msg_id,MsgId}, + {expecting,Pending}]), + {noreply,State} + end + end. + +do_decode_rpc_reply(Op,Result,State) + when Op==lock; Op==unlock; Op==edit_config; Op==delete_config; + Op==copy_config; Op==kill_session -> + {decode_ok(Result),{noreply,State}}; +do_decode_rpc_reply(Op,Result,State) + when Op==get; Op==get_config; Op==action -> + {decode_data(Result),{noreply,State}}; +do_decode_rpc_reply(close_session,Result,State) -> + case decode_ok(Result) of + ok -> {ok,{stop,State}}; + Other -> {Other,{noreply,State}} + end; +do_decode_rpc_reply({create_subscription,Caller},Result,State) -> + case decode_ok(Result) of + ok -> + {ok,{noreply,State#state{event_receiver=Caller}}}; + Other -> + {Other,{noreply,State}} + end; +do_decode_rpc_reply(get_event_streams,Result,State) -> + {decode_streams(decode_data(Result)),{noreply,State}}; +do_decode_rpc_reply(undefined,Result,State) -> + {Result,{noreply,State}}. + + + +decode_ok([{Tag,Attrs,Content}]) -> + case get_local_name_atom(Tag) of + ok -> + ok; + 'rpc-error' -> + {error,forward_xmlns_attr(Attrs,Content)}; + _Other -> + {error,{unexpected_rpc_reply,[{Tag,Attrs,Content}]}} + end; +decode_ok(Other) -> + {error,{unexpected_rpc_reply,Other}}. + +decode_data([{Tag,Attrs,Content}]) -> + case get_local_name_atom(Tag) of + data -> + %% Since content of data has nothing from the netconf + %% namespace, we remove the parent's xmlns attribute here + %% - just to make the result cleaner + {ok,forward_xmlns_attr(remove_xmlnsattr_for_tag(Tag,Attrs),Content)}; + 'rpc-error' -> + {error,forward_xmlns_attr(Attrs,Content)}; + _Other -> + {error,{unexpected_rpc_reply,[{Tag,Attrs,Content}]}} + end; +decode_data(Other) -> + {error,{unexpected_rpc_reply,Other}}. + +get_qualified_name(Tag) -> + case string:tokens(atom_to_list(Tag),":") of + [TagStr] -> {[],TagStr}; + [PrefixStr,TagStr] -> {PrefixStr,TagStr} + end. + +get_local_name_atom(Tag) -> + {_,TagStr} = get_qualified_name(Tag), + list_to_atom(TagStr). + + +%% Remove the xmlns attr that points to the tag. I.e. if the tag has a +%% prefix, remove {'xmlns:prefix',_}, else remove default {xmlns,_}. +remove_xmlnsattr_for_tag(Tag,Attrs) -> + {Prefix,_TagStr} = get_qualified_name(Tag), + XmlnsTag = xmlnstag(Prefix), + case lists:keytake(XmlnsTag,1,Attrs) of + {value,_,NoNsAttrs} -> + NoNsAttrs; + false -> + Attrs + end. + +%% Take all xmlns attributes from the parent's attribute list and +%% forward into all childrens' attribute lists. But do not overwrite +%% any. +forward_xmlns_attr(ParentAttrs,Children) -> + do_forward_xmlns_attr(get_all_xmlns_attrs(ParentAttrs,[]),Children). + +do_forward_xmlns_attr(XmlnsAttrs,[{ChT,ChA,ChC}|Children]) -> + ChA1 = add_xmlns_attrs(XmlnsAttrs,ChA), + [{ChT,ChA1,ChC} | do_forward_xmlns_attr(XmlnsAttrs,Children)]; +do_forward_xmlns_attr(_XmlnsAttrs,[]) -> + []. + +add_xmlns_attrs([{Key,_}=A|XmlnsAttrs],ChA) -> + case lists:keymember(Key,1,ChA) of + true -> + add_xmlns_attrs(XmlnsAttrs,ChA); + false -> + add_xmlns_attrs(XmlnsAttrs,[A|ChA]) + end; +add_xmlns_attrs([],ChA) -> + ChA. + +get_all_xmlns_attrs([{xmlns,_}=Default|Attrs],XmlnsAttrs) -> + get_all_xmlns_attrs(Attrs,[Default|XmlnsAttrs]); +get_all_xmlns_attrs([{Key,_}=Attr|Attrs],XmlnsAttrs) -> + case atom_to_list(Key) of + "xmlns:"++_Prefix -> + get_all_xmlns_attrs(Attrs,[Attr|XmlnsAttrs]); + _ -> + get_all_xmlns_attrs(Attrs,XmlnsAttrs) + end; +get_all_xmlns_attrs([],XmlnsAttrs) -> + XmlnsAttrs. + + +%% Decode server hello to pick out session id and capabilities +decode_hello({hello,_Attrs,Hello}) -> + case lists:keyfind('session-id',1,Hello) of + {'session-id',_,[SessionId]} -> + case lists:keyfind(capabilities,1,Hello) of + {capabilities,_,Capabilities} -> + case decode_caps(Capabilities,[],false) of + {ok,Caps} -> + {ok,list_to_integer(SessionId),Caps}; + Error -> + Error + end; + false -> + {error,{incorrect_hello,capabilities_not_found}} + end; + false -> + {error,{incorrect_hello,no_session_id_found}} + end. + +decode_caps([{capability,[],[?NETCONF_BASE_CAP++Vsn=Cap]} |Caps], Acc, _) -> + case Vsn of + ?NETCONF_BASE_CAP_VSN -> + decode_caps(Caps, [Cap|Acc], true); + _ -> + {error,{incompatible_base_capability_vsn,Vsn}} + end; +decode_caps([{capability,[],[Cap]}|Caps],Acc,Base) -> + decode_caps(Caps,[Cap|Acc],Base); +decode_caps([H|_T],_,_) -> + {error,{unexpected_capability_element,H}}; +decode_caps([],_,false) -> + {error,{incorrect_hello,no_base_capability_found}}; +decode_caps([],Acc,true) -> + {ok,lists:reverse(Acc)}. + + +%% Return a list of {Name,Data}, where data is a {Tag,Value} list for each stream +decode_streams({error,Reason}) -> + {error,Reason}; +decode_streams({ok,[{netconf,_,Streams}]}) -> + {ok,decode_streams(Streams)}; +decode_streams([{streams,_,Streams}]) -> + decode_streams(Streams); +decode_streams([{stream,_,Stream} | Streams]) -> + {name,_,[Name]} = lists:keyfind(name,1,Stream), + [{Name,[{Tag,Value} || {Tag,_,[Value]} <- Stream, Tag /= name]} + | decode_streams(Streams)]; +decode_streams([]) -> + []. + + +%%%----------------------------------------------------------------- +%%% Logging + +log(Connection,Action) -> + log(Connection,Action,<<>>). +log(#connection{host=Host,port=Port,name=Name},Action,Data) -> + error_logger:info_report(#conn_log{client=self(), + address={Host,Port}, + name=Name, + action=Action, + module=?MODULE}, + Data). + + +%% Log callback - called from the error handler process +format_data(raw,Data) -> + io_lib:format("~n~s~n",[hide_password(Data)]); +format_data(pretty,Data) -> + io_lib:format("~n~s~n",[indent(Data)]); +format_data(html,Data) -> + io_lib:format("~n~s~n",[html_format(Data)]). + +%%%----------------------------------------------------------------- +%%% Hide password elements from XML data +hide_password(Bin) -> + re:replace(Bin,<<"(<password[^>]*>)[^<]*(</password>)">>,<<"\\1*****\\2">>, + [global,{return,binary}]). + +%%%----------------------------------------------------------------- +%%% HTML formatting +html_format(Bin) -> + binary:replace(indent(Bin),<<"<">>,<<"<">>,[global]). + +%%%----------------------------------------------------------------- +%%% Indentation of XML code +indent(Bin) -> + String = normalize(hide_password(Bin)), + IndentedString = + case erase(part_of_line) of + undefined -> + indent1(String,[]); + Part -> + indent1(lists:reverse(Part)++String,erase(indent)) + end, + list_to_binary(IndentedString). + +%% Normalizes the XML document by removing all space and newline +%% between two XML tags. +%% Returns a list, no matter if the input was a list or a binary. +normalize(Str) -> + re:replace(Str,<<">[ \r\n\t]+<">>,<<"><">>,[global,{return,list}]). + + +indent1("<?"++Rest1,Indent1) -> + %% Prolog + {Line,Rest2,Indent2} = indent_line(Rest1,Indent1,[$?,$<]), + Line++indent1(Rest2,Indent2); +indent1("</"++Rest1,Indent1) -> + %% Stop tag + {Line,Rest2,Indent2} = indent_line1(Rest1,Indent1,[$/,$<]), + "\n"++Line++indent1(Rest2,Indent2); +indent1("<"++Rest1,Indent1) -> + %% Start- or empty tag + put(tag,get_tag(Rest1)), + {Line,Rest2,Indent2} = indent_line(Rest1,Indent1,[$<]), + "\n"++Line++indent1(Rest2,Indent2); +indent1([H|T],Indent) -> + [H|indent1(T,Indent)]; +indent1([],_Indent) -> + []. + +indent_line("?>"++Rest,Indent,Line) -> + %% Prolog + {lists:reverse(Line)++"?>",Rest,Indent}; +indent_line("/></"++Rest,Indent,Line) -> + %% Empty tag, and stop of parent tag -> one step out in indentation + {Indent++lists:reverse(Line)++"/>","</"++Rest,Indent--" "}; +indent_line("/>"++Rest,Indent,Line) -> + %% Empty tag, then probably next tag -> keep indentation + {Indent++lists:reverse(Line)++"/>",Rest,Indent}; +indent_line("></"++Rest,Indent,Line) -> + LastTag = erase(tag), + case get_tag(Rest) of + LastTag -> + %% Start and stop tag, but no content + indent_line1(Rest,Indent,[$/,$<,$>|Line]); + _ -> + %% Stop tag completed, and then stop tag of parent -> one step out + {Indent++lists:reverse(Line)++">","</"++Rest,Indent--" "} + end; +indent_line("><"++Rest,Indent,Line) -> + %% Stop tag completed, and new tag comming -> keep indentation + {Indent++lists:reverse(Line)++">","<"++Rest," "++Indent}; +indent_line("</"++Rest,Indent,Line) -> + %% Stop tag starting -> search for end of this tag + indent_line1(Rest,Indent,[$/,$<|Line]); +indent_line([H|T],Indent,Line) -> + indent_line(T,Indent,[H|Line]); +indent_line([],Indent,Line) -> + %% The line is not complete - will be continued later + put(part_of_line,Line), + put(indent,Indent), + {[],[],Indent}. + +indent_line1("></"++Rest,Indent,Line) -> + %% Stop tag completed, and then stop tag of parent -> one step out + {Indent++lists:reverse(Line)++">","</"++Rest,Indent--" "}; +indent_line1(">"++Rest,Indent,Line) -> + %% Stop tag completed -> keep indentation + {Indent++lists:reverse(Line)++">",Rest,Indent}; +indent_line1([H|T],Indent,Line) -> + indent_line1(T,Indent,[H|Line]); +indent_line1([],Indent,Line) -> + %% The line is not complete - will be continued later + put(part_of_line,Line), + put(indent,Indent), + {[],[],Indent}. + +get_tag("/>"++_) -> + []; +get_tag(">"++_) -> + []; +get_tag([H|T]) -> + [H|get_tag(T)]; +get_tag([]) -> + %% The line is not complete - will be continued later. + []. + + +%%%----------------------------------------------------------------- +%%% SSH stuff +ssh_receive_data() -> + receive + {ssh_cm, _CM, {data, _Ch, _Type, Data}} -> + {ok, Data}; + {ssh_cm, _CM, {Closed, _Ch}} = X when Closed == closed; Closed == eof -> + {error,X}; + {_Ref,timeout} = X -> + {error,X} + end. + +ssh_open(#options{host=Host,timeout=Timeout,port=Port,ssh=SshOpts,name=Name}) -> + case ssh:connect(Host, Port, + [{user_interaction,false}, + {silently_accept_hosts, true}|SshOpts]) of + {ok,CM} -> + case ssh_connection:session_channel(CM, Timeout) of + {ok,Ch} -> + case ssh_connection:subsystem(CM, Ch, "netconf", Timeout) of + success -> + {ok, #connection{reference = {CM,Ch}, + host = Host, + port = Port, + name = Name}}; + failure -> + ssh:close(CM), + {error,{ssh,could_not_execute_netconf_subsystem}} + end; + {error, Reason} -> + ssh:close(CM), + {error,{ssh,could_not_open_channel,Reason}}; + Other -> + %% Bug in ssh?? got {closed,0} here once... + {error,{ssh,unexpected_from_session_channel,Other}} + end; + {error,Reason} -> + {error,{ssh,could_not_connect_to_server,Reason}} + end. + +ssh_send(#connection{reference = {CM,Ch}}, Data) -> + case ssh_connection:send(CM, Ch, Data) of + ok -> ok; + {error,Reason} -> {error,{ssh,failed_to_send_data,Reason}} + end. + +ssh_close(#connection{reference = {CM,_Ch}}) -> + ssh:close(CM). + + +%%---------------------------------------------------------------------- +%% END OF MODULE +%%---------------------------------------------------------------------- diff --git a/lib/common_test/src/ct_netconfc.hrl b/lib/common_test/src/ct_netconfc.hrl new file mode 100644 index 0000000000..295a61a98b --- /dev/null +++ b/lib/common_test/src/ct_netconfc.hrl @@ -0,0 +1,58 @@ +%%-------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%---------------------------------------------------------------------- +%% File: ct_netconfc.hrl +%% +%% Description: +%% This file defines constant values and records used by the +%% netconf client ct_netconfc. +%% +%% @author Support +%% @doc Netconf Client Interface. +%% @end +%%---------------------------------------------------------------------- +%%---------------------------------------------------------------------- + + +%% Default port number (RFC 4742/IANA). +-define(DEFAULT_PORT, 830). + +%% Default timeout to wait for netconf server to reply to a request +-define(DEFAULT_TIMEOUT, infinity). %% msec + +%% Namespaces +-define(NETCONF_NAMESPACE_ATTR,[{xmlns,?NETCONF_NAMESPACE}]). +-define(ACTION_NAMESPACE_ATTR,[{xmlns,?ACTION_NAMESPACE}]). +-define(NETCONF_NOTIF_NAMESPACE_ATTR,[{xmlns,?NETCONF_NOTIF_NAMESPACE}]). +-define(NETMOD_NOTIF_NAMESPACE_ATTR,[{xmlns,?NETMOD_NOTIF_NAMESPACE}]). + +-define(NETCONF_NAMESPACE,"urn:ietf:params:xml:ns:netconf:base:1.0"). +-define(ACTION_NAMESPACE,"urn:com:ericsson:ecim:1.0"). +-define(NETCONF_NOTIF_NAMESPACE, + "urn:ietf:params:xml:ns:netconf:notification:1.0"). +-define(NETMOD_NOTIF_NAMESPACE,"urn:ietf:params:xml:ns:netmod:notification"). + +%% Capabilities +-define(NETCONF_BASE_CAP,"urn:ietf:params:netconf:base:"). +-define(NETCONF_BASE_CAP_VSN,"1.0"). + +%% Misc +-define(END_TAG,<<"]]>]]>">>). + +-define(FORMAT(_F, _A), lists:flatten(io_lib:format(_F, _A))). diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index 9d6ee3c8b9..66ecb142ca 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -369,11 +369,23 @@ loop(Mode,TestData,StartDir) -> {'EXIT',_Pid,normal} -> loop(Mode,TestData,StartDir); {'EXIT',Pid,Reason} -> - %% Let process crash in case of error, this shouldn't happen! - io:format("\n\nct_util_server got EXIT from ~p: ~p\n\n", - [Pid,Reason]), - file:set_cwd(StartDir), - exit(Reason) + case ets:lookup(?conn_table,Pid) of + [#conn{address=A,callback=CB}] -> + %% A connection crashed - remove the connection but don't die + ct_logs:tc_log_async(ct_error_notify, + "Connection process died: " + "Pid: ~p, Address: ~p, Callback: ~p\n" + "Reason: ~p\n\n", + [Pid,A,CB,Reason]), + catch CB:close(Pid), + loop(Mode,TestData,StartDir); + _ -> + %% Let process crash in case of error, this shouldn't happen! + io:format("\n\nct_util_server got EXIT from ~p: ~p\n\n", + [Pid,Reason]), + file:set_cwd(StartDir), + exit(Reason) + end end. diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl index 6b016e95df..474d36574e 100644 --- a/lib/common_test/src/ct_util.hrl +++ b/lib/common_test/src/ct_util.hrl @@ -64,3 +64,6 @@ -define(ct_config_txt, ct_config_plain). -define(ct_profile_file, ".common_test"). + +%% Logging information for error handler +-record(conn_log, {client, name, address, action, module}). diff --git a/lib/common_test/src/cth_conn_log.erl b/lib/common_test/src/cth_conn_log.erl new file mode 100644 index 0000000000..3af89db3a5 --- /dev/null +++ b/lib/common_test/src/cth_conn_log.erl @@ -0,0 +1,124 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%---------------------------------------------------------------------- +%% CT hook for logging of connections. +%% +%% HookOptions can be hardcoded in the test suite: +%% +%% suite() -> +%% [{ct_hooks, [{cth_conn_log, +%% [{ct_netconfc:conn_mod(),ct_netconfc:hook_options()}]}]}]. +%% +%% or specified in a configuration file: +%% +%% {ct_conn_log,[{ct_netconfc:conn_mod(),ct_netconfc:hook_options()}]}. +%% +%% The conn_mod() is the common test module implementing the protocol, +%% e.g. ct_netconfc, ct_telnet, etc. This module must log by calling +%% +%% error_logger:info_report(ConnLogInfo,Data). +%% ConnLogInfo = #conn_log{} | {ct_connection,Action,ConnName} +%% Action = open | close | send | recv | term() +%% ConnName = atom() - The 'KeyOrName' argument used when opening the connection +%% +%% ct_conn_log_h will print to html log or separate file (depending on +%% log_type() option). conn_mod() must implement and export +%% +%% format_data(log_type(), Data). +%% +%% If logging to separate file, ct_conn_log_h will also log error +%% reports which are witten like this: +%% +%% error_logger:error_report([{ct_connection,ConnName} | Report]). +%% +%%---------------------------------------------------------------------- +-module(cth_conn_log). + +-include_lib("common_test/include/ct.hrl"). + +-export([init/2, + pre_init_per_testcase/3, + post_end_per_testcase/4]). + +-spec init(Id, HookOpts) -> Result when + Id :: term(), + HookOpts :: ct:hook_options(), + Result :: {ok,[{ct_netconfc:conn_mod(), + {ct_netconfc:log_type(),[ct_netconfc:key_or_name()]}}]}. +init(_Id, HookOpts) -> + ConfOpts = ct:get_config(ct_conn_log,[]), + {ok,merge_log_info(ConfOpts,HookOpts)}. + +merge_log_info([{Mod,ConfOpts}|ConfList],HookList) -> + {Opts,HookList1} = + case lists:keytake(Mod,1,HookList) of + false -> + {ConfOpts,HookList}; + {value,{_,HookOpts},HL1} -> + {ConfOpts ++ HookOpts, HL1} % ConfOpts overwrites HookOpts! + end, + [{Mod,get_log_opts(Opts)} | merge_log_info(ConfList,HookList1)]; +merge_log_info([],HookList) -> + [{Mod,get_log_opts(Opts)} || {Mod,Opts} <- HookList]. + +get_log_opts(Opts) -> + LogType = proplists:get_value(log_type,Opts,html), + Hosts = proplists:get_value(hosts,Opts,[]), + {LogType,Hosts}. + + +pre_init_per_testcase(TestCase,Config,CthState) -> + Logs = + lists:map( + fun({ConnMod,{LogType,Hosts}}) -> + case LogType of + LogType when LogType==raw; LogType==pretty -> + Dir = ?config(priv_dir,Config), + TCStr = atom_to_list(TestCase), + ConnModStr = atom_to_list(ConnMod), + DefLogName = TCStr ++ "-" ++ ConnModStr ++ ".txt", + DefLog = filename:join(Dir,DefLogName), + Ls = [{Host, + filename:join(Dir,TCStr ++ "-"++ + atom_to_list(Host) ++ "-" ++ + ConnModStr ++ + ".txt")} + || Host <- Hosts] + ++[{default,DefLog}], + Str = + "<table borders=1>" + "<b>" ++ ConnModStr ++ " logs:</b>\n" ++ + [io_lib:format( + "<tr><td>~p</td><td><a href=~p>~s</a></td></tr>", + [S,L,filename:basename(L)]) + || {S,L} <- Ls] ++ + "</table>", + io:format(Str,[]), + {ConnMod,{LogType,Ls}}; + _ -> + {ConnMod,{LogType,[]}} + end + end, + CthState), + error_logger:add_report_handler(ct_conn_log_h,{group_leader(),Logs}), + {Config,CthState}. + +post_end_per_testcase(_TestCase,_Config,Return,CthState) -> + error_logger:delete_report_handler(ct_conn_log_h), + {Return,CthState}. diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile index 560a0b0d5a..4d85b84b5b 100644 --- a/lib/common_test/test/Makefile +++ b/lib/common_test/test/Makefile @@ -45,7 +45,8 @@ MODULES= \ ct_config_SUITE \ ct_master_SUITE \ ct_misc_1_SUITE \ - ct_hooks_SUITE + ct_hooks_SUITE \ + ct_netconfc_SUITE ERL_FILES= $(MODULES:%=%.erl) diff --git a/lib/common_test/test/common_test.spec b/lib/common_test/test/common_test.spec index 8755b08117..8bec66d6f2 100644 --- a/lib/common_test/test/common_test.spec +++ b/lib/common_test/test/common_test.spec @@ -1 +1 @@ -{suites,"../common_test_test",all}.
\ No newline at end of file +{suites,"../common_test_test",all}. diff --git a/lib/common_test/test/ct_netconfc_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE.erl new file mode 100644 index 0000000000..e6e8d5b09c --- /dev/null +++ b/lib/common_test/test/ct_netconfc_SUITE.erl @@ -0,0 +1,124 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% File: ct_netconfc_SUITE +%%% +%%% Description: +%%% Test ct_netconfc module +%%% +%%%------------------------------------------------------------------- +-module(ct_netconfc_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-define(eh, ct_test_support_eh). + +%%-------------------------------------------------------------------- +%% TEST SERVER CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Description: Since Common Test starts another Test Server +%% instance, the tests need to be performed on a separate node (or +%% there will be clashes with logging processes etc). +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config1 = ct_test_support:init_per_suite(Config), + Config1. + +end_per_suite(Config) -> + ct_test_support:end_per_suite(Config). + +init_per_testcase(TestCase, Config) -> + ct_test_support:init_per_testcase(TestCase, Config). + +end_per_testcase(TestCase, Config) -> + ct_test_support:end_per_testcase(TestCase, Config). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [ + default + ]. + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +%%%----------------------------------------------------------------- +%%% +default(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "netconfc1_SUITE"), + CfgFile = filename:join(DataDir, "netconfc1.cfg"), + {Opts,ERPid} = setup([{suite,Suite},{config,CfgFile}, + {label,default}], Config), + + ok = execute(default, Opts, ERPid, Config). + + +%%%----------------------------------------------------------------- +%%% HELP FUNCTIONS +%%%----------------------------------------------------------------- + +setup(Test, Config) -> + Opts0 = ct_test_support:get_opts(Config), + Level = ?config(trace_level, Config), + EvHArgs = [{cbm,ct_test_support},{trace_level,Level}], + Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test], + ERPid = ct_test_support:start_event_receiver(Config), + {Opts,ERPid}. + +execute(Name, Opts, ERPid, Config) -> + ok = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(Name, + reformat(Events, ?eh), + ?config(priv_dir, Config), + Opts), + + TestEvents = events_to_check(Name,Config), + ct_test_support:verify_events(TestEvents, Events, Config). + +reformat(Events, EH) -> + ct_test_support:reformat(Events, EH). + +%%%----------------------------------------------------------------- +%%% TEST EVENTS +%%%----------------------------------------------------------------- +events_to_check(Test,Config) -> + {module,_} = code:load_abs(filename:join(?config(data_dir,Config), + netconfc1_SUITE)), + TCs = netconfc1_SUITE:all(), + code:purge(netconfc1_SUITE), + code:delete(netconfc1_SUITE), + + OneTest = + [{?eh,start_logging,{'DEF','RUNDIR'}}] ++ + [{?eh,tc_done,{netconfc1_SUITE,TC,ok}} || TC <- TCs] ++ + [{?eh,stop_logging,[]}], + + %% 2 tests (ct:run_test + script_start) is default + OneTest ++ OneTest. diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1.cfg b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1.cfg new file mode 100644 index 0000000000..6466571623 --- /dev/null +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1.cfg @@ -0,0 +1,6 @@ +%% -*- erlang -*- +{netconf1,[{ssh,"localhost"}, + {port,2060}, + {user,"xxx"}, + {password,"xxx"}]}. +{ct_conn_log,[{ct_netconfc,[{log_type,pretty}]}]}. %overrides args to cth_conn_log diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl new file mode 100644 index 0000000000..79768a9a6a --- /dev/null +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl @@ -0,0 +1,1130 @@ +%%-------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%---------------------------------------------------------------------- +%% File: ct_netconfc_SUITE.erl +%% +%% Description: +%% This file contains the test cases for the ct_netconfc API. +%% +%% @author Support +%% @doc Netconf Client Interface. +%% @end +%%---------------------------------------------------------------------- +%%---------------------------------------------------------------------- +-module(netconfc1_SUITE). +-include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/src/ct_netconfc.hrl"). +-include_lib("public_key/include/public_key.hrl"). + +-compile(export_all). + +%% Default timetrap timeout (set in init_per_testcase). +-define(default_timeout, ?t:minutes(1)). + +-define(NS,ns). +-define(LOCALHOST, "127.0.0.1"). +-define(SSH_PORT, 2060). + +-define(DEFAULT_SSH_OPTS,[{ssh,?LOCALHOST}, + {port,?SSH_PORT}, + {user,"xxx"}, + {password,"xxx"}]). +-define(DEFAULT_SSH_OPTS(Dir), ?DEFAULT_SSH_OPTS++[{user_dir,Dir}]). + +-define(ok,ok). + +suite() -> + [{ct_hooks, [{cth_conn_log, + [{ct_netconfc,[{log_type,html}, %will be overwritten by config + {hosts,[my_named_connection,netconf1]}] + }] + }] + }]. + +all() -> + case os:find_executable("ssh") of + false -> + {skip, "SSH not installed on host"}; + _ -> + [hello, + hello_from_server_first, + hello_named, + hello_configured, + hello_configured_extraopts, + hello_required, + hello_required_exists, + hello_global_pwd, + hello_no_session_id, + hello_incomp_base_vsn, + hello_no_base_cap, + hello_no_caps, + no_server_hello, + no_client_hello, + get_session_id, + get_capabilities, + faulty_user, + faulty_passwd, + faulty_port, + no_host, + no_port, + invalid_opt, + get, + get_xpath, + get_config, + get_config_xpath, + edit_config, + copy_config, + delete_config, + lock, + unlock, + kill_session, + get_no_such_client, + action, + send_any_rpc, + send_any, + hide_password, + not_proper_xml, + prefixed_namespace, + receive_chunked_data, + timeout_receive_chunked_data, + close_while_waiting_for_chunked_data, + connection_crash, + get_event_streams, + create_subscription, + receive_event] + end. + + +groups() -> + []. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +init_per_testcase(_Case, Config) -> + ets:delete_all_objects(ns_tab), + Dog = test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + +end_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +init_per_suite(Config) -> + case catch {crypto:start(), ssh:start()} of + {ok, ok} -> + {ok, _} = get_id_keys(Config), + make_dsa_files(Config), + Server = ?NS:start(?config(data_dir,Config)), + [{server,Server}|Config]; + _ -> + {skip, "Crypto and/or SSH could not be started!"} + end. + +end_per_suite(Config) -> + PrivDir = ?config(priv_dir, Config), + ?NS:stop(?config(server,Config)), + ssh:stop(), + crypto:stop(), + remove_id_keys(PrivDir), + Config. + +hello(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +hello_from_server_first(Config) -> + DataDir = ?config(data_dir,Config), + ?NS:hello(1), + {ok,Client} = ct_netconfc:only_open(?DEFAULT_SSH_OPTS(DataDir)), + ct:sleep(500), + ?NS:expect(hello), + ?ok = ct_netconfc:hello(Client), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +hello_named(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(any_name,DataDir), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +hello_configured() -> + [{require, netconf1}]. +hello_configured(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_configured_success(netconf1,DataDir), + ?NS:expect_do_reply('close-session',close,ok), + {error, {no_such_name,netconf1}} = ct_netconfc:close_session(netconf1), + ?ok = ct_netconfc:close_session(Client), + ok. + +hello_configured_extraopts() -> + [{require, netconf1}]. +hello_configured_extraopts(Config) -> + DataDir = ?config(data_dir,Config), + %% Test that the cofiguration overwrites the ExtraOpts parameter + %% to ct_netconfc:open/2. + {ok,Client} = open_configured_success(netconf1,DataDir,[{password,"faulty"}]), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +hello_required() -> + [{require, my_named_connection, netconf1}]. +hello_required(Config) -> + DataDir = ?config(data_dir,Config), + {ok,_Client} = open_configured_success(my_named_connection,DataDir), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(my_named_connection), + ok. + +hello_required_exists() -> + [{require, my_named_connection, netconf1}]. +hello_required_exists(Config) -> + DataDir = ?config(data_dir,Config), + {ok,_Client1} = open_configured_success(my_named_connection,DataDir), + + %% Check that same name can not be used twice + {error,{connection_exists,_Client1}} = + ct_netconfc:open(my_named_connection,[{user_dir,DataDir}]), + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(my_named_connection), + + %% Then check that it can be used again after the first is closed + {ok,_Client2} = open_configured_success(my_named_connection,DataDir), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(my_named_connection), + ok. + +hello_global_pwd(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir,[{user,"any-user"}, + {password,"global-xxx"}]), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +hello_no_session_id(Config) -> + DataDir = ?config(data_dir,Config), + ?NS:hello(no_session_id), + ?NS:expect(hello), + {error,{incorrect_hello,no_session_id_found}} = open(DataDir), + ok. + +hello_incomp_base_vsn(Config) -> + DataDir = ?config(data_dir,Config), + ?NS:hello(1,{base,"1.1"}), + ?NS:expect(hello), + {error,{incompatible_base_capability_vsn,"1.1"}} = open(DataDir), + ok. + +hello_no_base_cap(Config) -> + DataDir = ?config(data_dir,Config), + ?NS:hello(1,no_base), + ?NS:expect(hello), + {error,{incorrect_hello,no_base_capability_found}} = open(DataDir), + ok. + +hello_no_caps(Config) -> + DataDir = ?config(data_dir,Config), + ?NS:hello(1,no_caps), + ?NS:expect(hello), + {error,{incorrect_hello,capabilities_not_found}} = open(DataDir), + ok. + +no_server_hello(Config) -> + DataDir = ?config(data_dir,Config), + ?NS:expect(hello), + {error,{hello_session_failed,timeout}} = open(DataDir,[{timeout,2000}]), + ok. + +no_client_hello(Config) -> + DataDir = ?config(data_dir,Config), + ?NS:hello(1), + {ok,Client} = ct_netconfc:only_open(?DEFAULT_SSH_OPTS(DataDir)), + + %% Allow server hello to arrive + ct:sleep(500), + + %% Tell server to receive a get request and then die without + %% replying since no hello has been received. (is this correct + %% behavoiur??) + ?NS:expect_do(get,close), + {error,closed} = ct_netconfc:get(Client,whatever), + ok. + +get_session_id(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + + 1 = ct_netconfc:get_session_id(Client), + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +get_capabilities(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + + Caps = ct_netconfc:get_capabilities(Client), + BaseCap = ?NETCONF_BASE_CAP ++ ?NETCONF_BASE_CAP_VSN, + [BaseCap,"urn:ietf:params:netconf:capability:writable-running:1.0" |_] = Caps, + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +faulty_user(Config) -> + DataDir = ?config(data_dir,Config), + {error,{ssh,could_not_connect_to_server, + "Unable to connect using the available authentication methods"}} = + open(DataDir,[{user,"yyy"}]), + ok. + +faulty_passwd(Config) -> + DataDir = ?config(data_dir,Config), + {error,{ssh,could_not_connect_to_server, + "Unable to connect using the available authentication methods"}} = + open(DataDir,[{password,"yyy"}]), + ok. + +faulty_port(Config) -> + DataDir = ?config(data_dir,Config), + {error,{ssh,could_not_connect_to_server,econnrefused}} = + open(DataDir,[{port,2062}]), + ok. + +no_host(Config) -> + DataDir = ?config(data_dir,Config), + Opts = lists:keydelete(ssh,1,?DEFAULT_SSH_OPTS(DataDir)), + {error,no_host_address} = ct_netconfc:open(Opts), + ok. + +no_port(Config) -> + DataDir = ?config(data_dir,Config), + Opts = lists:keydelete(port,1,?DEFAULT_SSH_OPTS(DataDir)), + {error,no_port} = ct_netconfc:open(Opts), + ok. + +invalid_opt(Config) -> + DataDir = ?config(data_dir,Config), + Opts1 = ?DEFAULT_SSH_OPTS(DataDir) ++ [{timeout,invalidvalue}], + {error,{invalid_option,{timeout,invalidvalue}}} = ct_netconfc:open(Opts1), + Opts2 = ?DEFAULT_SSH_OPTS(DataDir) ++ [{some_other_opt,true}], + {error,{invalid_option,{some_other_opt,true}}} = ct_netconfc:open(Opts2), + ok. + +get(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}], + ?NS:expect_reply('get',{data,Data}), + {ok,Data} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +get_xpath(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}], + ?NS:expect_reply({'get',xpath},{data,Data}), + {ok,Data} = ct_netconfc:get(Client,{xpath,"/server"}), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +get_config(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}], + ?NS:expect_reply('get-config',{data,Data}), + {ok,Data} = ct_netconfc:get_config(Client,running, + {server,[{xmlns,"myns"}],[]}), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +get_config_xpath(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}], + ?NS:expect_reply({'get-config',xpath},{data,Data}), + {ok,Data} = ct_netconfc:get_config(Client,running,{xpath,"/server"}), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +edit_config(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + ?NS:expect_reply('edit-config',ok), + ?ok = ct_netconfc:edit_config(Client,running, + {server,[{xmlns,"myns"}], + [{name,["myserver"]}]}), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +copy_config(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + ?NS:expect_reply('copy-config',ok), + ?ok = ct_netconfc:copy_config(Client,startup,running), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +delete_config(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + ?NS:expect_reply('delete-config',ok), + ?ok = ct_netconfc:delete_config(Client,startup), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +lock(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + ?NS:expect_reply('lock',ok), + ?ok = ct_netconfc:lock(Client,running), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +unlock(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + ?NS:expect_reply('unlock',ok), + ?ok = ct_netconfc:unlock(Client,running), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +kill_session(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + + ?NS:hello(2), + ?NS:expect(hello), + {ok,_OtherClient} = open(DataDir), + + ?NS:expect_do_reply('kill-session',{kill,2},ok), + ?ok = ct_netconfc:kill_session(Client,2), + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + + ok. + +get_no_such_client(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + case ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}) of + {error,no_such_client} -> + ok; + {error,closed} -> + %% Means that the Client process was not terminated before the call. + %% Give it one more go. + {error,no_such_client} = + ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}) + end, + ok. + +action(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + Data = [{myactionreturn,[{xmlns,"myns"}],["value"]}], + ?NS:expect_reply(action,{data,Data}), + {ok,Data} = ct_netconfc:action(Client,{myaction,[{xmlns,"myns"}],[]}), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +send_any_rpc(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}], + GetConf = {'get-config', + [{source,["running"]}, + {filter,[{type,"subtree"}], + [{server,[{xmlns,"myns"}],[]}]}]}, + ?NS:expect_reply('get-config',{data,Data}), + [{data,?NETCONF_NAMESPACE_ATTR,Data}] = ct_netconfc:send_rpc(Client,GetConf), + + EditConf = {'edit-config', + [{target,["running"]}, + {config,[{server,[{xmlns,"myns"}], + [{name,["myserver"]}]}]}]}, + ?NS:expect_reply('edit-config',ok), + [{ok,?NETCONF_NAMESPACE_ATTR,[]}] = ct_netconfc:send_rpc(Client,EditConf), + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +send_any(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + + %% Correct get-config rpc + Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}], + RpcAttr1 = ?NETCONF_NAMESPACE_ATTR ++ [{'message-id',"1"}], + RpcGetConf = {rpc,RpcAttr1, + [{'get-config', + [{source,["running"]}, + {filter,[{type,"subtree"}], + [{server,[{xmlns,"myns"}],[]}]}]}]}, + ?NS:expect_reply('get-config',{data,Data}), + {'rpc-reply',RpcAttr1,[{data,_,Data}]} = ct_netconfc:send(Client,RpcGetConf), + + %% Correct edit-config rpc + RpcAttr2 = ?NETCONF_NAMESPACE_ATTR ++ [{'message-id',"2"}], + RpcEditConf = {rpc,RpcAttr2, + [{'edit-config', + [{target,["running"]}, + {config,[{server,[{xmlns,"myns"}], + [{name,["myserver"]}]}]}]}]}, + ?NS:expect_reply('edit-config',ok), + {'rpc-reply',RpcAttr2,[{ok,_,[]}]} = ct_netconfc:send(Client,RpcEditConf), + + %% Send any data + ?NS:expect_reply(any,{ok,[],[]}), + {ok,_,[]} = ct_netconfc:send(Client,{any,[],[]}), + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +hide_password(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + Password = "my_very_secret_password", + Data = [{passwords,[{xmlns,"myns"}], + [{password,[{xmlns,"pwdns"}],[Password]}, + {password,[],[Password]}]}], + ?NS:expect_reply('get',{data,Data}), + ct:capture_start(), % in case of html logging + {ok,Data} = ct_netconfc:get(Client,{passwords,[{xmlns,"myns"}],[]}), + ct:capture_stop(), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + + Log = filename:join(?config(priv_dir,Config),"hide_password-netconf.txt"), + + Text = + case file:read_file(Log) of + {ok,Bin} -> + Bin; + _NoLog -> + %% Assume html logging + list_to_binary(ct:capture_get()) + end, + + nomatch = binary:match(Text,list_to_binary(Password)), + + ok. + +not_proper_xml(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + NS = list_to_binary(?NETCONF_NAMESPACE), + NotProper = <<"<rpc-reply message-id=\"1\" xmlns=\"", + NS/binary,"\"><data></rpc-reply>">>, + ?NS:expect_reply('get',NotProper), + {error,{failed_to_parse_received_data,_}} = + ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +prefixed_namespace(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + NS = list_to_binary(?NETCONF_NAMESPACE), + + %% Test that data element can be properly decoded and that + %% prefixed namespace attributes (exepct the netconf namespace) + %% are forwarded to the content of the data element - i.e. that + %% the xmlns:my is forwarded from the rpc-reply element to the + %% server element below. + Data = <<"<nc:rpc-reply message-id=\"1\" xmlns:nc=\"", + NS/binary,"\" xmlns:my=\"myns\"><nc:data><my:server>", + "<my:name my:lang=\"en\">myserver</my:name></my:server>" + "</nc:data></nc:rpc-reply>">>, + ?NS:expect_reply('get',Data), + {ok,[{'my:server',[{'xmlns:my',"myns"}], + [{'my:name',[{'my:lang',"en"}],["myserver"]}]}]} = + ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}), + + Ok = <<"<nc:rpc-reply message-id=\"2\" xmlns:nc=\"", + NS/binary,"\"><nc:ok/></nc:rpc-reply>">>, + ?NS:expect_reply('edit-config',Ok), + ?ok = ct_netconfc:edit_config(Client,running, + {server,[{xmlns,"myns"}], + [{name,["myserver"]}]}), + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +%% Test that the client can parse data which is received in chunks, +%% i.e. when the complete rpc-reply is not contained in one single ssh +%% data message. +receive_chunked_data(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + + %% Construct the data to return from netconf server + Data = [{servers,[{xmlns,"myns"}], + [{server,[],[{name,[],["server0"]}]}, + {server,[],[{name,[],["server1"]}]}, + {server,[],[{name,[],["server2"]}]}, + {server,[],[{name,[],["server3"]}]}, + {server,[],[{name,[],["server4"]}]}, + {server,[],[{name,[],["server5"]}]}, + {server,[],[{name,[],["server6"]}]}, + {server,[],[{name,[],["server7"]}]}, + {server,[],[{name,[],["server8"]}]}, + {server,[],[{name,[],["server9"]}]}] + }], + Rpc = {'rpc-reply',?NETCONF_NAMESPACE_ATTR ++ [{'message-id',"1"}], + [{data,Data}]}, + Xml = list_to_binary(xmerl:export_simple_element(Rpc,xmerl_xml)), + Netconf = + <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", + Xml/binary,"\n",?END_TAG/binary>>, + + %% Split the data in some chunks + PartLength = size(Netconf) div 3, + <<Part1:PartLength/binary,Part2:PartLength/binary,Part3:PartLength/binary, + Part4/binary>> = Netconf, + + %% Spawn a process which will wait a bit for the client to send + %% the request (below), then order the server to the chunks of the + %% rpc-reply one by one. + spawn(fun() -> timer:sleep(500),?NS:hupp(send,Part1), + timer:sleep(100),?NS:hupp(send,Part2), + timer:sleep(100),?NS:hupp(send,Part3), + timer:sleep(100),?NS:hupp(send,Part4) + end), + + %% Order server to expect a get - then the process above will make + %% sure the rpc-reply is sent. + ?NS:expect('get'), + {ok,Data} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}), + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +%% Same as receive_chunked_data, but timeout waiting for last part. +timeout_receive_chunked_data(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + + %% Construct the data to return from netconf server + Data = [{servers,[{xmlns,"myns"}], + [{server,[],[{name,[],["server0"]}]}, + {server,[],[{name,[],["server1"]}]}, + {server,[],[{name,[],["server2"]}]}, + {server,[],[{name,[],["server3"]}]}, + {server,[],[{name,[],["server4"]}]}, + {server,[],[{name,[],["server5"]}]}, + {server,[],[{name,[],["server6"]}]}, + {server,[],[{name,[],["server7"]}]}, + {server,[],[{name,[],["server8"]}]}, + {server,[],[{name,[],["server9"]}]}] + }], + Rpc = {'rpc-reply',?NETCONF_NAMESPACE_ATTR ++ [{'message-id',"1"}], + [{data,Data}]}, + Xml = list_to_binary(xmerl:export_simple_element(Rpc,xmerl_xml)), + Netconf = + <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", + Xml/binary,"\n",?END_TAG/binary>>, + + %% Split the data in some chunks + PartLength = size(Netconf) div 3, + <<Part1:PartLength/binary,Part2:PartLength/binary,_Part3:PartLength/binary, + _Part4/binary>> = Netconf, + + %% Spawn a process which will wait a bit for the client to send + %% the request (below), then order the server to the chunks of the + %% rpc-reply one by one. + spawn(fun() -> timer:sleep(500),?NS:hupp(send,Part1), + timer:sleep(100),?NS:hupp(send,Part2) + end), + + %% Order server to expect a get - then the process above will make + %% sure the rpc-reply is sent - but only a part of it - then timeout. + ?NS:expect('get'), + {error,timeout} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]},2000), + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +%% Same as receive_chunked_data, but timeout waiting for last part. +close_while_waiting_for_chunked_data(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + + %% Construct the data to return from netconf server + Data = [{servers,[{xmlns,"myns"}], + [{server,[],[{name,[],["server0"]}]}, + {server,[],[{name,[],["server1"]}]}, + {server,[],[{name,[],["server2"]}]}, + {server,[],[{name,[],["server3"]}]}, + {server,[],[{name,[],["server4"]}]}, + {server,[],[{name,[],["server5"]}]}, + {server,[],[{name,[],["server6"]}]}, + {server,[],[{name,[],["server7"]}]}, + {server,[],[{name,[],["server8"]}]}, + {server,[],[{name,[],["server9"]}]}] + }], + Rpc = {'rpc-reply',?NETCONF_NAMESPACE_ATTR ++ [{'message-id',"1"}], + [{data,Data}]}, + Xml = list_to_binary(xmerl:export_simple_element(Rpc,xmerl_xml)), + Netconf = + <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", + Xml/binary,"\n",?END_TAG/binary>>, + + %% Split the data in some chunks + PartLength = size(Netconf) div 3, + <<Part1:PartLength/binary,Part2:PartLength/binary,_Part3:PartLength/binary, + _Part4/binary>> = Netconf, + + %% Spawn a process which will wait a bit for the client to send + %% the request (below), then order the server to the chunks of the + %% rpc-reply one by one. + spawn(fun() -> timer:sleep(500),?NS:hupp(send,Part1), + timer:sleep(100),?NS:hupp(send,Part2), + timer:sleep(100),?NS:hupp(kill) + end), + + %% Order server to expect a get - then the process above will make + %% sure the rpc-reply is sent - but only a part of it - then close. + ?NS:expect('get'), + {error,closed} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]},2000), + ok. + +connection_crash(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + + %% Test that if the test survives killing the connection + %% process. Earlier this caused ct_util_server to terminate, and + %% this aborting the complete test run. + spawn(fun() -> timer:sleep(500),exit(Client,kill) end), + ?NS:expect(get), + {error,{closed,killed}}=ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}), + ok. + +get_event_streams(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + StreamNames = ["NETCONF","stream1","stream2"], + Streams = [{N,[{description,"descr of " ++ N}]} || N <- StreamNames], + StreamsXml = [{stream,[{name,[N]}|[{Tag,[Value]} || {Tag,Value} <- Data]]} + || {N,Data} <- Streams], + ReplyData = [{netconf,?NETMOD_NOTIF_NAMESPACE_ATTR,[{streams,StreamsXml}]}], + ?NS:expect_reply('get',{data,ReplyData}), + {ok,Streams} = ct_netconfc:get_event_streams(Client,StreamNames), + + ?NS:expect_reply('get',{data,ReplyData}), + {ok,Streams} = ct_netconfc:get_event_streams(Client,StreamNames,5000), + + ?NS:expect('get'), + {error,timeout} = ct_netconfc:get_event_streams(Client,100), + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + ok. + +create_subscription(Config) -> + DataDir = ?config(data_dir,Config), + + %% All defaults + {ok,Client1} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream]},ok), + ?ok = ct_netconfc:create_subscription(Client1), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client1), + + %% All defaults with timeout + {ok,Client1a} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream]},ok), + ?ok = ct_netconfc:create_subscription(Client1a,5000), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client1a), + + %% All defaults timing out + {ok,Client1b} = open_success(DataDir), + ?NS:expect({'create-subscription',[stream]}), + {error,timeout} = ct_netconfc:create_subscription(Client1b,100), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client1b), + + %% Stream + {ok,Client2} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream]},ok), + Stream = "some_stream", + ?ok = ct_netconfc:create_subscription(Client2,Stream), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client2), + + %% Filter + {ok,Client3} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream,filter]},ok), + Filter = {notification,?NETMOD_NOTIF_NAMESPACE_ATTR, + [eventTime]}, + ?ok = ct_netconfc:create_subscription(Client3,Filter), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client3), + + %% Filter with timeout + {ok,Client3a} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream,filter]},ok), + ?ok = ct_netconfc:create_subscription(Client3a,Filter,5000), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client3a), + + %% Filter timing out + {ok,Client3b} = open_success(DataDir), + ?NS:expect({'create-subscription',[stream,filter]}), + {error,timeout}=ct_netconfc:create_subscription(Client3b,Filter,100), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client3b), + + %% Stream and filter + {ok,Client4} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream,filter]},ok), + ?ok = ct_netconfc:create_subscription(Client4,Stream,Filter), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client4), + + %% Start/stop time + {ok,Client5} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream,startTime,stopTime]},ok), + StartTime = xs_datetime({D,{H,M,S}}= calendar:local_time()), + StopTime = xs_datetime({D,{H+2,M,S}}), + ?ok = ct_netconfc:create_subscription(Client5,StartTime,StopTime), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client5), + + %% Start/stop time with timeout + {ok,Client5a} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream,startTime,stopTime]},ok), + ?ok = ct_netconfc:create_subscription(Client5a,StartTime,StopTime,5000), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client5a), + + %% Start/stop time timing out + {ok,Client5b} = open_success(DataDir), + ?NS:expect({'create-subscription',[stream,startTime,stopTime]}), + {error,timeout} = + ct_netconfc:create_subscription(Client5b,StartTime,StopTime,100), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client5b), + + %% Stream and start/stop time + {ok,Client6} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream,startTime,stopTime]},ok), + ?ok = ct_netconfc:create_subscription(Client6,Stream,StartTime,StopTime), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client6), + + %% Filter and start/stop time + {ok,Client7} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream,filter,startTime,stopTime]}, + ok), + ?ok = ct_netconfc:create_subscription(Client7,Filter, + StartTime,StopTime), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client7), + + %% Stream, filter and start/stop time + {ok,Client8} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream,filter,startTime,stopTime]}, + ok), + ?ok = ct_netconfc:create_subscription(Client8,Stream,Filter, + StartTime,StopTime), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client8), + + ok. + +receive_event(Config) -> + DataDir = ?config(data_dir,Config), + {ok,Client} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream]},ok), + ?ok = ct_netconfc:create_subscription(Client), + + ?NS:hupp(send_event), + + receive + %% Matching ?NS:make_msg(event) + {notification,?NETCONF_NOTIF_NAMESPACE_ATTR, + [{eventTime,[],[_Time]}, + {event,[{xmlns,"http://my.namespaces.com/event"}], + [{severity,_,_}, + {description,_,_}]}]} -> + ok; + Other -> + ct:fail({got_unexpected_while_waiting_for_event, Other}) + after 3000 -> + ct:fail(timeout_waiting_for_event) + end, + + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client), + + ok. + +%%%----------------------------------------------------------------- + +break(_Config) -> + test_server:break("break test case"). + +br() -> + test_server:break(""). + +%%%----------------------------------------------------------------- +%% Open a netconf session which is not specified in a config file +open_success(Dir) -> + open_success(Dir,[]). + +%% Open a netconf session which is not specified in a config file, and +%% give som extra options in addition to the test defaults. +open_success(Dir,ExtraOpts) when is_list(Dir), is_list(ExtraOpts) -> + ?NS:hello(1), % tell server to send hello with session id 1 + ?NS:expect(hello), % tell server to expect a hello message from client + open(Dir,ExtraOpts); + +%% Open a named netconf session which is not specified in a config file +open_success(KeyOrName,Dir) when is_atom(KeyOrName), is_list(Dir) -> + ?NS:hello(1), + ?NS:expect(hello), + ct_netconfc:open(KeyOrName,?DEFAULT_SSH_OPTS(Dir)). + +open(Dir) -> + open(Dir,[]). +open(Dir,ExtraOpts) -> + Opts = lists:ukeymerge(1,lists:keysort(1,ExtraOpts), + lists:keysort(1,?DEFAULT_SSH_OPTS(Dir))), + ct_netconfc:open(Opts). + +%%%----------------------------------------------------------------- +%%% Open a netconf session which is specified in a config file +%%% KeyOrName is the config key (server_id()) or name given in a +%%% require statement (target_name()). +open_configured_success(KeyOrName,Dir) when is_atom(KeyOrName) -> + open_configured_success(KeyOrName,Dir,[]). +open_configured_success(KeyOrName,Dir,ExtraOpts) when is_atom(KeyOrName) -> + ?NS:hello(1), + ?NS:expect(hello), + ct_netconfc:open(KeyOrName,[{user_dir,Dir}|ExtraOpts]). + +%%%----------------------------------------------------------------- +%%% Convert erlang datetime to the simplest variant of XML dateTime +xs_datetime({{Y,M,D},{H,Mi,S}}) -> + lists:flatten( + io_lib:format("~p-~s-~sT~s:~s:~s",[Y,pad(M),pad(D),pad(H),pad(Mi),pad(S)])). + +pad(I) when I<10 -> + "0"++integer_to_list(I); +pad(I) -> + integer_to_list(I). + + +%%%----------------------------------------------------------------- +%%% BEGIN SSH key management +%% copy private keys to given dir from ~/.ssh +get_id_keys(Config) -> + DstDir = ?config(priv_dir, Config), + SrcDir = filename:join(os:getenv("HOME"), ".ssh"), + RsaOk = copyfile(SrcDir, DstDir, "id_rsa"), + DsaOk = copyfile(SrcDir, DstDir, "id_dsa"), + case {RsaOk, DsaOk} of + {{ok, _}, {ok, _}} -> {ok, both}; + {{ok, _}, _} -> {ok, rsa}; + {_, {ok, _}} -> {ok, dsa}; + {Error, _} -> Error + end. + +%% Remove later on. Use make_dsa_files instead. +remove_id_keys(Config) -> + Dir = ?config(priv_dir, Config), + file:delete(filename:join(Dir, "id_rsa")), + file:delete(filename:join(Dir, "id_dsa")). + + +make_dsa_files(Config) -> + make_dsa_files(Config, rfc4716_public_key). +make_dsa_files(Config, Type) -> + {DSA, EncodedKey} = gen_dsa(128, 20), + PKey = DSA#'DSAPrivateKey'.y, + P = DSA#'DSAPrivateKey'.p, + Q = DSA#'DSAPrivateKey'.q, + G = DSA#'DSAPrivateKey'.g, + Dss = #'Dss-Parms'{p=P, q=Q, g=G}, + {ok, Hostname} = inet:gethostname(), + {ok, {A, B, C, D}} = inet:getaddr(Hostname, inet), + IP = lists:concat([A, ".", B, ".", C, ".", D]), + Attributes = [], % Could be [{comment,"user@" ++ Hostname}], + HostNames = [{hostnames,[IP, IP]}], + PublicKey = [{{PKey, Dss}, Attributes}], + KnownHosts = [{{PKey, Dss}, HostNames}], + + KnownHostsEnc = public_key:ssh_encode(KnownHosts, known_hosts), + KnownHosts = public_key:ssh_decode(KnownHostsEnc, known_hosts), + + PublicKeyEnc = public_key:ssh_encode(PublicKey, Type), + + SystemTmpDir = ?config(data_dir, Config), + filelib:ensure_dir(SystemTmpDir), + file:make_dir(SystemTmpDir), + + DSAFile = filename:join(SystemTmpDir, "ssh_host_dsa_key.pub"), + file:delete(DSAFile), + + DSAPrivateFile = filename:join(SystemTmpDir, "ssh_host_dsa_key"), + file:delete(DSAPrivateFile), + + KHFile = filename:join(SystemTmpDir, "known_hosts"), + file:delete(KHFile), + + PemBin = public_key:pem_encode([EncodedKey]), + + file:write_file(DSAFile, PublicKeyEnc), + file:write_file(KHFile, KnownHostsEnc), + file:write_file(DSAPrivateFile, PemBin), + ok. + +%%-------------------------------------------------------------------- +%% Creates a dsa key (OBS: for testing only) +%% the sizes are in bytes +%% gen_dsa(::integer()) -> {::atom(), ::binary(), ::opaque()} +%%-------------------------------------------------------------------- +gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) -> + Key = gen_dsa2(LSize, NSize), + {Key, encode_key(Key)}. + +encode_key(Key = #'RSAPrivateKey'{}) -> + {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key), + {'RSAPrivateKey', list_to_binary(Der), not_encrypted}; +encode_key(Key = #'DSAPrivateKey'{}) -> + {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key), + {'DSAPrivateKey', list_to_binary(Der), not_encrypted}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% DSA key generation (OBS: for testing only) +%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm +%% and the fips_186-3.pdf +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +gen_dsa2(LSize, NSize) -> + Q = prime(NSize), %% Choose N-bit prime Q + X0 = prime(LSize), + P0 = prime((LSize div 2) +1), + + %% Choose L-bit prime modulus P such that p-1 is a multiple of q. + case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of + error -> + gen_dsa2(LSize, NSize); + P -> + G = crypto:mod_exp(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q. + %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used. + + X = prime(20), %% Choose x by some random method, where 0 < x < q. + Y = crypto:mod_exp(G, X, P), %% Calculate y = g^x mod p. + + #'DSAPrivateKey'{version=0, p=P, q=Q, g=G, y=Y, x=X} + end. + +%% See fips_186-3.pdf +dsa_search(T, P0, Q, Iter) when Iter > 0 -> + P = 2*T*Q*P0 + 1, + case is_prime(crypto:mpint(P), 50) of + true -> P; + false -> dsa_search(T+1, P0, Q, Iter-1) + end; +dsa_search(_,_,_,_) -> + error. + + +%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +prime(ByteSize) -> + Rand = odd_rand(ByteSize), + crypto:erlint(prime_odd(Rand, 0)). + +prime_odd(Rand, N) -> + case is_prime(Rand, 50) of + true -> + Rand; + false -> + NotPrime = crypto:erlint(Rand), + prime_odd(crypto:mpint(NotPrime+2), N+1) + end. + +%% see http://en.wikipedia.org/wiki/Fermat_primality_test +is_prime(_, 0) -> true; +is_prime(Candidate, Test) -> + CoPrime = odd_rand(<<0,0,0,4, 10000:32>>, Candidate), + case crypto:mod_exp(CoPrime, Candidate, Candidate) of + CoPrime -> is_prime(Candidate, Test-1); + _ -> false + end. + +odd_rand(Size) -> + Min = 1 bsl (Size*8-1), + Max = (1 bsl (Size*8))-1, + odd_rand(crypto:mpint(Min), crypto:mpint(Max)). + +odd_rand(Min,Max) -> + Rand = <<Sz:32, _/binary>> = crypto:rand_uniform(Min,Max), + BitSkip = (Sz+4)*8-1, + case Rand of + Odd = <<_:BitSkip, 1:1>> -> Odd; + Even = <<_:BitSkip, 0:1>> -> + crypto:mpint(crypto:erlint(Even)+1) + end. + +copyfile(SrcDir, DstDir, Fn) -> + file:copy(filename:join(SrcDir, Fn), + filename:join(DstDir, Fn)). + +%%% END SSH key management +%%%----------------------------------------------------------------- diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl new file mode 100644 index 0000000000..665b0e556c --- /dev/null +++ b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl @@ -0,0 +1,506 @@ +%%-------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%---------------------------------------------------------------------- +%% A netconf server used for testing of netconfc +-module(ns). + +%-compile(export_all). +-include_lib("common_test/src/ct_netconfc.hrl"). + + +%%%----------------------------------------------------------------- +%%% API +-export([start/1, + stop/1, + hello/1, + hello/2, + expect/1, + expect_reply/2, + expect_do/2, + expect_do_reply/3, + hupp/1, + hupp/2]). + +%%%----------------------------------------------------------------- +%%% ssh_channel callbacks +-export([init/1, + terminate/2, + handle_ssh_msg/2, + handle_msg/2]). + +%%%----------------------------------------------------------------- +%% Server specifications +-define(SERVER_DATA_NAMESPACE, "ClientTest"). +-define(CAPABILITIES,?CAPABILITIES_VSN("1.0")). +-define(CAPABILITIES_VSN(Vsn), + [ + ?NETCONF_BASE_CAP ++ Vsn, + "urn:ietf:params:netconf:capability:writable-running:1.0", + "urn:ietf:params:netconf:capability:candidate:1.0", + "urn:ietf:params:netconf:capability:confirmed-commit:1.0", + "urn:ietf:params:netconf:capability:rollback-on-error:1.0", + "urn:ietf:params:netconf:capability:startup:1.0", + "urn:ietf:params:netconf:capability:url:1.0", + "urn:ietf:params:netconf:capability:xpath:1.0", + "urn:ietf:params:netconf:capability:notification:1.0", + "urn:ietf:params:netconf:capability:interleave:1.0", + ?ACTION_NAMESPACE, + ?SERVER_DATA_NAMESPACE + ]). +-define(SSH_PORT, 2060). +-define(ssh_config(Dir),[{port, ?SSH_PORT}, + {interface, {127,0,0,1}}, + {system_dir, Dir}, + {user_dir, Dir}, + {user_passwords, [{"xxx","xxx"}]}, + {password, "global-xxx"}]). + +%% Some help for debugging +%-define(dbg(F,A),io:format(F,A)). +-define(dbg(F,A),ok). +-define(dbg_event(Event,Expect), + ?dbg("Event: ~p~nExpected: ~p~n",[Event,Expect])). + +%% State +-record(session, {cb, + connection, + buffer = <<>>, + session_id}). + + +%%%----------------------------------------------------------------- +%%% API + +%% Start the netconf server and use the given directory as system_dir +%% and user_dir +start(Dir) -> + spawn(fun() -> init_server(Dir) end). + +%% Stop the netconf server +stop(Pid) -> + Pid ! {stop,self()}, + receive stopped -> ok end. + +%% Set the session id for the hello message. +%% If this is not called prior to starting the session, no hello +%% message will be sent. +%% 'Stuff' indicates some special handling to e.g. provoke error cases +hello(SessionId) -> + hello(SessionId,undefined). +hello(SessionId,Stuff) -> + insert(hello,{SessionId,Stuff}). + +%% Tell server to expect the given message without doing any further +%% actions. To be called directly before sending a request. +expect(Expect) -> + expect_do_reply(Expect,undefined,undefined). + +%% Tell server to expect the given message and reply with the give +%% reply. To be called directly before sending a request. +expect_reply(Expect,Reply) -> + expect_do_reply(Expect,undefined,Reply). + +%% Tell server to expect the given message and perform an action. To +%% be called directly before sending a request. +expect_do(Expect,Do) -> + expect_do_reply(Expect,Do,undefined). + +%% Tell server to expect the given message, perform an action and +%% reply with the given reply. To be called directly before sending a +%% request. +expect_do_reply(Expect,Do,Reply) -> + add_expect({Expect,Do,Reply}). + +%% Hupp the server - i.e. tell it to do something - +%% e.g. hupp(send_event) will cause send_event(State) to be called on +%% the session channel process. +hupp(send_event) -> + hupp(send,[make_msg(event)]); +hupp(kill) -> + hupp(fun hupp_kill/1,[]). + +hupp(send,Data) -> + hupp(fun hupp_send/2,[Data]); +hupp(Fun,Args) when is_function(Fun) -> + [{_,Pid}] = lookup(channel_process), + Pid ! {hupp,Fun,Args}. + +%%%----------------------------------------------------------------- +%%% Main loop of the netconf server +init_server(Dir) -> + ets:new(ns_tab,[set,named_table,public]), + Config = ?ssh_config(Dir), + {_,Host} = lists:keyfind(interface, 1, Config), + {_,Port} = lists:keyfind(port, 1, Config), + Opts = lists:filter(fun({Key,_}) -> + lists:member(Key,[system_dir, + password, + user_passwords, + pwdfun]) + end, + Config), + {ok, Daemon} = + ssh:daemon(Host, Port, + [{subsystems,[{"netconf",{?MODULE,[]}}]} + |Opts]), + loop(Daemon). + +loop(Daemon) -> + receive + {stop,From} -> + ssh:stop_daemon(Daemon), + From ! stopped + end. + +%%---------------------------------------------------------------------- +%% Behaviour callback functions (ssh_channel) +%%---------------------------------------------------------------------- +init([]) -> + {ok, undefined}. + +terminate(_Reason, _State) -> + ok. + +handle_ssh_msg({ssh_cm,CM,{data, Ch, _Type = 0, Data}}, State) -> + %% erlang:display({self(),data,CM,Ch,State}), + data_for_channel(CM, Ch, Data, State); +handle_ssh_msg({ssh_cm,CM,{closed, Ch}}, State) -> + %% erlang:display({self(),closed,CM,Ch,State}), + stop_channel(CM, Ch, State); +handle_ssh_msg({ssh_cm,CM,{eof, Ch}}, State) -> + %% erlang:display({self(),eof,CM,Ch,State}), + data_for_channel(CM,Ch, <<>>, State). + + +handle_msg({'EXIT', _Pid, _Reason}, State) -> + {ok, State}; +handle_msg({ssh_channel_up,Ch,CM},undefined) -> + %% erlang:display({self(),up,CM,Ch}), + ConnRef = {CM,Ch}, + SessionId = maybe_hello(ConnRef), + insert(channel_process,self()), % used to hupp the server + {ok, #session{connection = ConnRef, + session_id = SessionId}}; +handle_msg({hupp,Fun,Args},State) -> + {ok,apply(Fun,Args ++ [State])}. + +data_for_channel(CM, Ch, Data, State) -> + try data(Data, State) of + {ok, NewState} -> + case erase(stop) of + true -> + stop_channel(CM, Ch, NewState); + _ -> + {ok, NewState} + end + catch + Class:Reason -> + Stacktrace = erlang:get_stacktrace(), + error_logger:error_report([{?MODULE, data_for_channel}, + {request, Data}, + {reason, {Class, Reason}}, + {stacktrace, Stacktrace}]), + stop_channel(CM, Ch, State) + end. + +data(Data, State = #session{connection = ConnRef, + buffer = Buffer}) -> + AllData = <<Buffer/binary,Data/binary>>, + case find_endtag(AllData) of + {ok,Msgs,Rest} -> + [check_expected(ConnRef,Msg) || Msg <- Msgs], + {ok,State#session{buffer=Rest}}; + need_more -> + {ok,State#session{buffer=AllData}} + end. + +stop_channel(CM, Ch, State) -> + ssh:close(CM), + {stop, Ch, State}. + + +%%%----------------------------------------------------------------- +%%% Functions to trigg via hupp/1: + +%% Send data spontaneously - e.g. an event +hupp_send(Data,State = #session{connection = ConnRef}) -> + send(ConnRef,Data), + State. +hupp_kill(State = #session{connection = ConnRef}) -> + kill(ConnRef), + State. + +%%%----------------------------------------------------------------- +%%% Internal functions + + +%%% Send ssh data to the client +send({CM,Ch},Data) -> + ssh_connection:send(CM, Ch, Data). + +%%% Kill ssh connection +kill({CM,_Ch}) -> + ssh:close(CM). + +add_expect(Add) -> + case lookup(expect) of + [] -> + insert(expect,[Add]); + [{expect,First}] -> + insert(expect,First ++ [Add]) + end, + ok. + +insert(Key,Value) -> + ets:insert(ns_tab,{Key,Value}). +lookup(Key) -> + ets:lookup(ns_tab,Key). + +maybe_hello(ConnRef) -> + case lookup(hello) of + [{hello,{SessionId,Stuff}}] -> + %% erlang:display({SessionId,Stuff}), + ets:delete(ns_tab,hello), + insert({session,SessionId},ConnRef), + reply(ConnRef,{hello,SessionId,Stuff}), + SessionId; + [] -> + undefined + end. + +find_endtag(Data) -> + case binary:split(Data,[?END_TAG],[global]) of + [Data] -> + need_more; + Msgs -> + {ok,lists:sublist(Msgs,length(Msgs)-1),lists:last(Msgs)} + end. + +check_expected(ConnRef,Msg) -> + case lookup(expect) of + [{expect,[{Expect,Do,Reply}|Rest]}] -> + insert(expect,Rest), + %% erlang:display({got,io_lib:format("~s",[Msg])}), + %% erlang:display({expected,Expect}), + match(Msg,Expect), + do(ConnRef, Do), + reply(ConnRef,Reply); + Expected -> + exit({error,{got_unexpected,Msg,Expected}}) + end. + +match(Msg,Expect) -> + ?dbg("Match: ~p~n",[Msg]), + {ok,ok,<<>>} = xmerl_sax_parser:stream(Msg,[{event_fun,fun event/3}, + {event_state,Expect}]). + +event(Event,_Loc,Expect) -> + ?dbg_event(Event,Expect), + event(Event,Expect). + +event(startDocument,Expect) -> match(Expect); +event({startElement,_,Name,_,Attrs},[{se,Name}|Match]) -> + msg_id(Name,Attrs), + Match; +event({startElement,_,Name,_,Attrs},[ignore,{se,Name}|Match]) -> + msg_id(Name,Attrs), + Match; +event({startElement,_,Name,_,Attrs},[{se,Name,As}|Match]) -> + msg_id(Name,Attrs), + match_attrs(Name,As,Attrs), + Match; +event({startElement,_,Name,_,Attrs},[ignore,{se,Name,As}|Match]) -> + msg_id(Name,Attrs), + match_attrs(Name,As,Attrs), + Match; +event({startPrefixMapping,_,Ns},[{ns,Ns}|Match]) -> Match; +event({startPrefixMapping,_,Ns},[ignore,{ns,Ns}|Match]) -> Match; +event({endPrefixMapping,_},Match) -> Match; +event({endElement,_,Name,_},[{ee,Name}|Match]) -> Match; +event({endElement,_,Name,_},[ignore,{ee,Name}|Match]) -> Match; +event(endDocument,Match) when Match==[]; Match==[ignore] -> ok; +event(_,[ignore|_]=Match) -> Match; +event(Event,Match) -> throw({nomatch,{Event,Match}}). + +msg_id("rpc",Attrs) -> + case lists:keyfind("message-id",3,Attrs) of + {_,_,_,Str} -> put(msg_id,Str); + false -> erase(msg_id) + end; +msg_id(_,_) -> + ok. + +match_attrs(Name,[{Key,Value}|As],Attrs) -> + case lists:keyfind(atom_to_list(Key),3,Attrs) of + {_,_,_,Value} -> match_attrs(Name,As,Attrs); + false -> throw({missing_attr,Key,Name,Attrs}); + _ -> throw({faulty_attr_value,Key,Name,Attrs}) + end; +match_attrs(_,[],_) -> + ok. + +do(ConnRef, close) -> + ets:match_delete(ns_tab,{{session,'_'},ConnRef}), + put(stop,true); +do(_ConnRef, {kill,SessionId}) -> + case lookup({session,SessionId}) of + [{_,Owner}] -> + ets:delete(ns_tab,{session,SessionId}), + kill(Owner); + _ -> + exit({no_session_to_kill,SessionId}) + end; +do(_, undefined) -> + ok. + +reply(_,undefined) -> + ?dbg("no reply~n",[]), + ok; +reply(ConnRef,Reply) -> + ?dbg("Reply: ~p~n",[Reply]), + send(ConnRef, make_msg(Reply)). + +from_simple(Simple) -> + list_to_binary(xmerl:export_simple_element(Simple,xmerl_xml)). + +xml(Content) -> + <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", + Content/binary,"\n",?END_TAG/binary>>. + +rpc_reply(Content) when is_binary(Content) -> + MsgId = case erase(msg_id) of + undefined -> <<>>; + Id -> list_to_binary([" message-id=\"",Id,"\""]) + end, + <<"<rpc-reply xmlns=\"",?NETCONF_NAMESPACE,"\"",MsgId/binary,">\n", + Content/binary,"\n</rpc-reply>">>; +rpc_reply(Content) -> + rpc_reply(list_to_binary(Content)). + +session_id(no_session_id) -> + <<>>; +session_id(SessionId0) -> + SessionId = list_to_binary(integer_to_list(SessionId0)), + <<"<session-id>",SessionId/binary,"</session-id>\n">>. + +capabilities(undefined) -> + CapsXml = list_to_binary([["<capability>",C,"</capability>\n"] + || C <- ?CAPABILITIES]), + <<"<capabilities>\n",CapsXml/binary,"</capabilities>\n">>; +capabilities({base,Vsn}) -> + CapsXml = list_to_binary([["<capability>",C,"</capability>\n"] + || C <- ?CAPABILITIES_VSN(Vsn)]), + <<"<capabilities>\n",CapsXml/binary,"</capabilities>\n">>; +capabilities(no_base) -> + [_|Caps] = ?CAPABILITIES, + CapsXml = list_to_binary([["<capability>",C,"</capability>\n"] || C <- Caps]), + <<"<capabilities>\n",CapsXml/binary,"</capabilities>\n">>; +capabilities(no_caps) -> + <<>>. + +%%%----------------------------------------------------------------- +%%% Match received netconf message from the client. Add a new clause +%%% for each new message to recognize. The clause argument shall match +%%% the Expect argument in expect/1, expect_reply/2 or +%%% expect_do_reply/3. +%%% +%%% match(term()) -> [Match]. +%%% Match = ignore | {se,Name} | {se,Name,Attrs} | {ee,Name} | {ns,Namespace} +%%% Name = string() +%%% Attrs = [{atom(),string()}] +%%% Namespace = string() +%%% +%%% 'se' means start element, 'ee' means end element - i.e. to match +%%% an XML element you need one 'se' entry and one 'ee' entry with the +%%% same name in the match list. +match(hello) -> + [ignore,{se,"hello"},ignore,{ee,"hello"},ignore]; +match('close-session') -> + [ignore,{se,"rpc"},{se,"close-session"}, + {ee,"close-session"},{ee,"rpc"},ignore]; +match('edit-config') -> + [ignore,{se,"rpc"},{se,"edit-config"},{se,"target"},ignore,{ee,"target"}, + {se,"config"},ignore,{ee,"config"},{ee,"edit-config"},{ee,"rpc"},ignore]; +match('get') -> + match({get,subtree}); +match({'get',FilterType}) -> + [ignore,{se,"rpc"},{se,"get"},{se,"filter",[{type,atom_to_list(FilterType)}]}, + ignore,{ee,"filter"},{ee,"get"},{ee,"rpc"},ignore]; +match('get-config') -> + match({'get-config',subtree}); +match({'get-config',FilterType}) -> + [ignore,{se,"rpc"},{se,"get-config"},{se,"source"},ignore,{ee,"source"}, + {se,"filter",[{type,atom_to_list(FilterType)}]},ignore,{ee,"filter"}, + {ee,"get-config"},{ee,"rpc"},ignore]; +match('copy-config') -> + [ignore,{se,"rpc"},{se,"copy-config"},{se,"target"},ignore,{ee,"target"}, + {se,"source"},ignore,{ee,"source"},{ee,"copy-config"},{ee,"rpc"},ignore]; +match('delete-config') -> + [ignore,{se,"rpc"},{se,"delete-config"},{se,"target"},ignore,{ee,"target"}, + {ee,"delete-config"},{ee,"rpc"},ignore]; +match('lock') -> + [ignore,{se,"rpc"},{se,"lock"},{se,"target"},ignore,{ee,"target"}, + {ee,"lock"},{ee,"rpc"},ignore]; +match('unlock') -> + [ignore,{se,"rpc"},{se,"unlock"},{se,"target"},ignore,{ee,"target"}, + {ee,"unlock"},{ee,"rpc"},ignore]; +match('kill-session') -> + [ignore,{se,"rpc"},{se,"kill-session"},{se,"session-id"},ignore, + {ee,"session-id"},{ee,"kill-session"},{ee,"rpc"},ignore]; +match(action) -> + [ignore,{se,"rpc"},{ns,?ACTION_NAMESPACE},{se,"action"},{se,"data"},ignore, + {ee,"data"},{ee,"action"},{ee,"rpc"},ignore]; +match({'create-subscription',Content}) -> + [ignore,{se,"rpc"},{ns,?NETCONF_NOTIF_NAMESPACE}, + {se,"create-subscription"}] ++ + lists:flatmap(fun(X) -> + [{se,atom_to_list(X)},ignore,{ee,atom_to_list(X)}] + end, Content) ++ + [{ee,"create-subscription"},{ee,"rpc"},ignore]; +match(any) -> + [ignore]. + + + +%%%----------------------------------------------------------------- +%%% Make message to send to the client. +%%% Add a new clause for each new message that shall be sent. The +%%% clause shall match the Reply argument in expect_reply/2 or +%%% expect_do_reply/3. +make_msg({hello,SessionId,Stuff}) -> + SessionIdXml = session_id(SessionId), + CapsXml = capabilities(Stuff), + xml(<<"<hello xmlns=\"",?NETCONF_NAMESPACE,"\">\n",CapsXml/binary, + SessionIdXml/binary,"</hello>">>); +make_msg(ok) -> + xml(rpc_reply("<ok/>")); +make_msg({data,Data}) -> + xml(rpc_reply(from_simple({data,Data}))); +make_msg(event) -> + xml(<<"<notification xmlns=\"",?NETCONF_NOTIF_NAMESPACE,"\">" + "<eventTime>2012-06-14T14:50:54+02:00</eventTime>" + "<event xmlns=\"http://my.namespaces.com/event\">" + "<severity>major</severity>" + "<description>Something terrible happened</description>" + "</event>" + "</notification>">>); +make_msg(Xml) when is_binary(Xml) -> + xml(Xml); +make_msg(Simple) when is_tuple(Simple) -> + xml(from_simple(Simple)). diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml index be9eb1cd75..b87e32a3d9 100644 --- a/lib/compiler/doc/src/compile.xml +++ b/lib/compiler/doc/src/compile.xml @@ -108,6 +108,11 @@ See the <em>Efficiency Guide</em> for further information.</p> </item> + <tag><c>column</c></tag> + <item> + <p>The compiler will keep the column numbers while parsing.</p> + </item> + <tag><c>compressed</c></tag> <item> <p>The compiler will compress the generated object code, diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl index 6f0ffb5b25..d307d192b2 100644 --- a/lib/compiler/src/beam_type.erl +++ b/lib/compiler/src/beam_type.erl @@ -29,10 +29,17 @@ module({Mod,Exp,Attr,Fs0,Lc}, _Opts) -> {ok,{Mod,Exp,Attr,Fs,Lc}}. function({function,Name,Arity,CLabel,Asm0}) -> - Asm1 = beam_utils:live_opt(Asm0), - Asm2 = opt(Asm1, [], tdb_new()), - Asm = beam_utils:delete_live_annos(Asm2), - {function,Name,Arity,CLabel,Asm}. + try + Asm1 = beam_utils:live_opt(Asm0), + Asm2 = opt(Asm1, [], tdb_new()), + Asm = beam_utils:delete_live_annos(Asm2), + {function,Name,Arity,CLabel,Asm} + catch + Class:Error -> + Stack = erlang:get_stacktrace(), + io:fwrite("Function: ~w/~w\n", [Name,Arity]), + erlang:raise(Class, Error, Stack) + end. %% opt([Instruction], Accumulator, TypeDb) -> {[Instruction'],TypeDb'} %% Keep track of type information; try to simplify. diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index abcd93f280..194f089ba1 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -741,6 +741,9 @@ live_opt([{badmatch,Src}=I|Is], _, D, Acc) -> live_opt([{case_end,Src}=I|Is], _, D, Acc) -> Regs = x_live([Src], 0), live_opt(Is, Regs, D, [I|Acc]); +live_opt([{try_case_end,Src}=I|Is], _, D, Acc) -> + Regs = x_live([Src], 0), + live_opt(Is, Regs, D, [I|Acc]); live_opt([if_end=I|Is], _, D, Acc) -> Regs = 0, live_opt(Is, Regs, D, [I|Acc]); @@ -802,8 +805,6 @@ live_opt([{deallocate,_}=I|Is], Regs, D, Acc) -> live_opt(Is, Regs, D, [I|Acc]); live_opt([{kill,_}=I|Is], Regs, D, Acc) -> live_opt(Is, Regs, D, [I|Acc]); -live_opt([{try_case_end,_}=I|Is], Regs, D, Acc) -> - live_opt(Is, Regs, D, [I|Acc]); live_opt([{try_end,_}=I|Is], Regs, D, Acc) -> live_opt(Is, Regs, D, [I|Acc]); live_opt([{loop_rec_end,_}=I|Is], Regs, D, Acc) -> diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index a52e7bb761..9f0bca9dd5 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -783,15 +783,27 @@ valfun_4({bs_utf16_size,{f,Fail},A,Dst}, Vst) -> valfun_4({bs_bits_to_bytes,{f,Fail},Src,Dst}, Vst) -> assert_term(Src, Vst), set_type_reg({integer,[]}, Dst, branch_state(Fail, Vst)); -valfun_4({bs_init2,{f,Fail},_,Heap,Live,_,Dst}, Vst0) -> +valfun_4({bs_init2,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) -> verify_live(Live, Vst0), + if + is_integer(Sz) -> + ok; + true -> + assert_term(Sz, Vst0) + end, Vst1 = heap_alloc(Heap, Vst0), Vst2 = branch_state(Fail, Vst1), Vst3 = prune_x_regs(Live, Vst2), Vst = bs_zero_bits(Vst3), set_type_reg(binary, Dst, Vst); -valfun_4({bs_init_bits,{f,Fail},_,Heap,Live,_,Dst}, Vst0) -> +valfun_4({bs_init_bits,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) -> verify_live(Live, Vst0), + if + is_integer(Sz) -> + ok; + true -> + assert_term(Sz, Vst0) + end, Vst1 = heap_alloc(Heap, Vst0), Vst2 = branch_state(Fail, Vst1), Vst3 = prune_x_regs(Live, Vst2), diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index 7365706b94..fbaacc08da 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -41,7 +41,7 @@ -type option() :: atom() | {atom(), term()} | {'d', atom(), term()}. --type err_info() :: {erl_scan:line(), module(), term()}. %% ErrorDescriptor +-type err_info() :: erl_scan:error_info(). %% ErrorDescriptor -type errors() :: [{file:filename(), [err_info()]}]. -type warnings() :: [{file:filename(), [err_info()]}]. -type mod_ret() :: {'ok', module()} @@ -363,7 +363,17 @@ messages_per_file(Ms) -> (_) -> false end, A) end, T, PrioMs), - Prio = lists:sort(fun({_,{L1,_,_}}, {_,{L2,_,_}}) -> L1 =< L2 end, + Prio = lists:sort(fun({_,{As1,_,_}}, {_,{As2,_,_}}) -> + {location, Loc1} = + erl_scan:attributes_info(As1, location), + {location, Loc2} = + erl_scan:attributes_info(As2, location), + case {Loc1, Loc2} of + {{L1, _}, L2} when is_integer(L2) -> L1 < L2; + {L1, {L2, _}} when is_integer(L1) -> L1 =< L2; + {_, _} -> Loc1 =< Loc2 + end + end, lists:append(Prio0)), flatmap(fun mpf/1, [Prio, Rest]). @@ -773,7 +783,8 @@ parse_module(St) -> Opts = St#compile.options, Cwd = ".", IncludePath = [Cwd, St#compile.dir|inc_paths(Opts)], - R = epp:parse_file(St#compile.ifile, IncludePath, pre_defs(Opts)), + AtPos = initial_position(Opts), + R = epp:parse_file(St#compile.ifile, AtPos, IncludePath, pre_defs(Opts)), case R of {ok,Forms} -> {ok,St#compile{code=Forms}}; @@ -1423,7 +1434,7 @@ report_warnings(#compile{options=Opts,warnings=Ws0}) -> end. format_message(F, P, [{{Line,Column}=Loc,Mod,E}|Es]) -> - M = {{F,Loc},io_lib:format("~s:~w:~w ~s~s\n", + M = {{F,Loc},io_lib:format("~s:~w:~w: ~s~s\n", [F,Line,Column,P,Mod:format_error(E)])}, [M|format_message(F, P, Es)]; format_message(F, P, [{Line,Mod,E}|Es]) -> @@ -1479,6 +1490,12 @@ objfile(Base, St) -> tmpfile(Ofile) -> reverse([$#|tl(reverse(Ofile))]). +initial_position(Opts) -> + case lists:member(column, Opts) of + true -> {1, 1}; + false -> 1 + end. + %% pre_defs(Options) %% inc_paths(Options) %% Extract the predefined macros and include paths from the option list. diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index 68bc83433e..6cea783090 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -119,7 +119,7 @@ expand_pmod(Fs0, St0) -> get_base(As) -> case lists:keyfind(extends, 1, As) of - {extends,[Base]} when is_atom(Base) -> + {extends,_,[Base]} when is_atom(Base) -> Base; _ -> [] diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl index eb5e50818e..47698ecdb7 100644 --- a/lib/compiler/test/error_SUITE.erl +++ b/lib/compiler/test/error_SUITE.erl @@ -22,13 +22,15 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - head_mismatch_line/1,warnings_as_errors/1, bif_clashes/1]). + head_mismatch_line/1,warnings_as_errors/1, bif_clashes/1, + column_number/1 + ]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> test_lib:recompile(?MODULE), - [head_mismatch_line, warnings_as_errors, bif_clashes]. + [head_mismatch_line, warnings_as_errors, bif_clashes, column_number]. groups() -> []. @@ -166,6 +168,15 @@ bif_clashes(Config) when is_list(Config) -> +%% Tests that messages are correctly reported with column numbers +%% if the column option is set. +column_number(Config) when is_list(Config) -> + Ts1 = [{column_number_warning, + <<"\nt(X) -> ok.">>, + [return_warnings, export_all, column], + {warning, [{{2, 3}, erl_lint, {unused_var, 'X'}}]}}], + ?line [] = run(Config, Ts1), + ok. %% Tests that a head mismatch is reported on the correct line (OTP-2125). head_mismatch_line(Config) when is_list(Config) -> diff --git a/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S b/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S index c0bf04ed8f..cffb792920 100644 --- a/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S +++ b/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S @@ -19,10 +19,10 @@ {get_tuple_element,{x,0},1,{x,2}}. {get_tuple_element,{x,0},2,{x,3}}. {get_tuple_element,{x,0},3,{x,4}}. - {gc_bif,'+',{f,0},5,[{x,1},{x,2}],{x,0}}. - {gc_bif,'+',{f,0},5,[{x,0},{x,3}],{x,0}}. - {gc_bif,'+',{f,0},5,[{x,0},{x,4}],{x,0}}. - {gc_bif,'+',{f,0},5,[{x,0},{x,5}],{x,0}}. + {gc_bif,'+',{f,0},6,[{x,1},{x,2}],{x,0}}. + {gc_bif,'+',{f,0},6,[{x,0},{x,3}],{x,0}}. + {gc_bif,'+',{f,0},6,[{x,0},{x,4}],{x,0}}. + {gc_bif,'+',{f,0},6,[{x,0},{x,5}],{x,0}}. return. {label,3}. {badmatch,{x,0}}. diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index 5e13a93c52..b53d0dba1d 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -190,6 +190,15 @@ silly_coverage(Config) when is_list(Config) -> {label,2}|non_proper_list]}],99}, ?line expect_error(fun() -> beam_block:module(BlockInput, []) end), + %% beam_type + TypeInput = {?MODULE,[{foo,0}],[], + [{function,foo,0,2, + [{label,1}, + {line,loc}, + {func_info,{atom,?MODULE},{atom,foo},0}, + {label,2}|non_proper_list]}],99}, + expect_error(fun() -> beam_type:module(TypeInput, []) end), + %% beam_except ExceptInput = {?MODULE,[{foo,0}],[], [{function,foo,0,2, diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 4be593e208..a6a81d6fe2 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -954,8 +954,7 @@ static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 16 || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16 - || !enif_inspect_iolist_as_binary(env, argv[2], &text) - || text.size % 16 != 0) { + || !enif_inspect_iolist_as_binary(env, argv[2], &text)) { return enif_make_badarg(env); } diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 19db6c9dd4..2868fe05f0 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -643,16 +643,14 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]> <func> <name>aes_cfb_128_encrypt(Key, IVec, Text) -> Cipher</name> - <name>aes_cbc_128_encrypt(Key, IVec, Text) -> Cipher</name> - <fsummary>Encrypt <c>Text</c>according to AES in Cipher Feedback mode or Cipher Block Chaining mode</fsummary> + <fsummary>Encrypt <c>Text</c>according to AES in Cipher Feedback mode</fsummary> <type> <v>Key = Text = iolist() | binary()</v> <v>IVec = Cipher = binary()</v> </type> <desc> <p>Encrypts <c>Text</c> according to AES in Cipher Feedback - mode (CFB) or Cipher Block Chaining mode (CBC). <c>Text</c> - must be a multiple of 128 bits (16 bytes). <c>Key</c> is the + mode (CFB). <c>Key</c> is the AES key, and <c>IVec</c> is an arbitrary initializing vector. The lengths of <c>Key</c> and <c>IVec</c> must be 128 bits (16 bytes).</p> @@ -660,15 +658,45 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]> </func> <func> <name>aes_cfb_128_decrypt(Key, IVec, Cipher) -> Text</name> + <fsummary>Decrypt <c>Cipher</c>according to AES in Cipher Feedback mode</fsummary> + <type> + <v>Key = Cipher = iolist() | binary()</v> + <v>IVec = Text = binary()</v> + </type> + <desc> + <p>Decrypts <c>Cipher</c> according to AES in Cipher Feedback Mode (CFB). + <c>Key</c> is the AES key, and <c>IVec</c> is an arbitrary + initializing vector. <c>Key</c> and <c>IVec</c> must have + the same values as those used when encrypting. The lengths of + <c>Key</c> and <c>IVec</c> must be 128 bits (16 bytes).</p> + </desc> + </func> + <func> + <name>aes_cbc_128_encrypt(Key, IVec, Text) -> Cipher</name> + <fsummary>Encrypt <c>Text</c>according to AES in Cipher Block Chaining mode</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Encrypts <c>Text</c> according to AES in Cipher Block Chaining + mode (CBC). <c>Text</c> + must be a multiple of 128 bits (16 bytes). <c>Key</c> is the + AES key, and <c>IVec</c> is an arbitrary initializing vector. + The lengths of <c>Key</c> and <c>IVec</c> must be 128 bits + (16 bytes).</p> + </desc> + </func> + <func> <name>aes_cbc_128_decrypt(Key, IVec, Cipher) -> Text</name> - <fsummary>Decrypt <c>Cipher</c>according to AES in Cipher Feedback mode or Cipher Block Chaining mode</fsummary> + <fsummary>Decrypt <c>Cipher</c>according to AES in Cipher Block Chaining mode</fsummary> <type> <v>Key = Cipher = iolist() | binary()</v> <v>IVec = Text = binary()</v> </type> <desc> - <p>Decrypts <c>Cipher</c> according to Cipher Feedback Mode (CFB) - or Cipher Block Chaining mode (CBC). + <p>Decrypts <c>Cipher</c> according to AES in Cipher Block + Chaining mode (CBC). <c>Key</c> is the AES key, and <c>IVec</c> is an arbitrary initializing vector. <c>Key</c> and <c>IVec</c> must have the same values as those used when encrypting. <c>Cipher</c> diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 627c966dfb..196f00da5d 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -717,10 +717,19 @@ aes_cfb(Config) when is_list(Config) -> ?line Key = hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), ?line IVec = hexstr2bin("000102030405060708090a0b0c0d0e0f"), ?line Plain = hexstr2bin("6bc1bee22e409f96e93d7e117393172a"), - ?line Cipher = crypto:aes_cfb_128_encrypt(Key, IVec, Plain), - ?line m(Cipher, hexstr2bin("3b3fd92eb72dad20333449f8e83cfb4a")), - ?line m(Plain, - crypto:aes_cfb_128_decrypt(Key, IVec, Cipher)). + ?line Cipher = hexstr2bin("3b3fd92eb72dad20333449f8e83cfb4a"), + + %% Try all prefixes of plain and cipher. + aes_cfb_do(byte_size(Plain), Plain, Cipher, Key, IVec). + +aes_cfb_do(N, Plain, Cipher, Key, IVec) when N >= 0 -> + <<P:N/binary, _/binary>> = Plain, + <<C:N/binary, _/binary>> = Cipher, + ?line C = crypto:aes_cfb_128_encrypt(Key, IVec, P), + ?line P = crypto:aes_cfb_128_decrypt(Key, IVec, C), + aes_cfb_do(N-1, Plain, Cipher, Key, IVec); +aes_cfb_do(_, _, _, _, _) -> ok. + %% %% diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml index 70c845bade..14ce3cbe7f 100644 --- a/lib/inets/doc/src/httpc.xml +++ b/lib/inets/doc/src/httpc.xml @@ -480,66 +480,69 @@ apply(Module, Function, [ReplyInfo | Args]) <d>ex: "134.138" or "[FEDC:BA98" (all IP-addresses starting with 134.138 or FEDC:BA98), "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP-address).</d> <v>MaxSessions = integer() </v> <d>Default is <c>2</c>. - Maximum number of persistent connections to a host.</d> + Maximum number of persistent connections to a host.</d> <v>MaxKeepAlive = integer() </v> - <d>Default is <c>5</c>. - Maximum number of outstanding requests on the same connection to - a host.</d> - <v>KeepAliveTimeout = integer() </v> - <d>Default is <c>120000</c> (= 2 min). - If a persistent connection is idle longer than the - <c>keep_alive_timeout</c> the client will close the connection. - The server may also have such a time out but you should - not count on it!</d> + <d>Default is <c>5</c>. + Maximum number of outstanding requests on the same connection to + a host.</d> + <v>KeepAliveTimeout = integer() </v> + <d>Default is <c>120000</c> (= 2 min). + If a persistent connection is idle longer than the + <c>keep_alive_timeout</c> in milliseconds, + the client will close the connection. + The server may also have such a time out but you should + not count on it!</d> <v>MaxPipeline = integer() </v> - <d>Default is <c>2</c>. - Maximum number of outstanding requests on a pipelined connection to a host.</d> - <v>PipelineTimeout = integer() </v> - <d>Default is <c>0</c>, - which will result in pipelining not being used. - If a persistent connection is idle longer than the - <c>pipeline_timeout</c> the client will close the connection. </d> + <d>Default is <c>2</c>. + Maximum number of outstanding requests on a pipelined connection + to a host.</d> + <v>PipelineTimeout = integer() </v> + <d>Default is <c>0</c>, + which will result in pipelining not being used. + If a persistent connection is idle longer than the + <c>pipeline_timeout</c> in milliseconds, + the client will close the connection. </d> <v>CookieMode = enabled | disabled | verify </v> <d>Default is <c>disabled</c>. - If Cookies are enabled all valid cookies will automatically be - saved in the client manager's cookie database. - If the option <c>verify</c> is used the function <c>store_cookies/2</c> - has to be called for the cookies to be saved.</d> - <v>IpFamily = inet | inet6 | inet6fb4 </v> - <d>By default <c>inet</c>. - When it is set to <c>inet6fb4</c> you can use both ipv4 and ipv6. - It first tries <c>inet6</c> and if that does not works falls back to <c>inet</c>. - The option is here to provide a workaround for buggy ipv6 stacks to ensure that - ipv4 will always work.</d> + If Cookies are enabled all valid cookies will automatically be + saved in the client manager's cookie database. + If the option <c>verify</c> is used the function <c>store_cookies/2</c> + has to be called for the cookies to be saved.</d> + <v>IpFamily = inet | inet6 | inet6fb4 </v> + <d>By default <c>inet</c>. + When it is set to <c>inet6fb4</c> you can use both ipv4 and ipv6. + It first tries <c>inet6</c> and if that does not works falls back to <c>inet</c>. + The option is here to provide a workaround for buggy ipv6 stacks to ensure that + ipv4 will always work.</d> <v>IpAddress = ip_address() </v> - <d>If the host has several network interfaces, this option specifies which one to use. - See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> for more info. </d> + <d>If the host has several network interfaces, this option specifies which one to use. + See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> for more info. </d> <v>Port = integer() </v> - <d>Specify which local port number to use. - See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> for more info. </d> - <v>VerboseMode = false | verbose | debug | trace </v> - <d>Default is <c>false</c>. - This option is used to switch on (or off) - different levels of erlang trace on the client. - It is a debug feature.</d> + <d>Specify which local port number to use. + See <seealso marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seealso> for more info. </d> + <v>VerboseMode = false | verbose | debug | trace </v> + <d>Default is <c>false</c>. + This option is used to switch on (or off) + different levels of erlang trace on the client. + It is a debug feature.</d> <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> </type> <desc> - <p>Sets options to be used for subsequent requests.</p> - <note> - <p>If possible the client will keep its connections - alive and use persistent connections - with or without pipeline depending on configuration - and current circumstances. The HTTP/1.1 specification does not - provide a guideline for how many requests would be - ideal to be sent on a persistent connection, - this very much depends on the - application. Note that a very long queue of requests may cause a - user perceived delay as earlier requests may take a long time - to complete. The HTTP/1.1 specification does suggest a - limit of 2 persistent connections per server, which is the - default value of the <c>max_sessions</c> option. </p> - </note> + <p>Sets options to be used for subsequent requests.</p> + <note> + <p>If possible the client will keep its connections + alive and use persistent connections + with or without pipeline depending on configuration + and current circumstances. The HTTP/1.1 specification does not + provide a guideline for how many requests would be + ideal to be sent on a persistent connection, + this very much depends on the + application. Note that a very long queue of requests may cause a + user perceived delay as earlier requests may take a long time + to complete. The HTTP/1.1 specification does suggest a + limit of 2 persistent connections per server, which is the + default value of the <c>max_sessions</c> option. </p> + </note> <marker id="get_options"></marker> </desc> @@ -648,6 +651,8 @@ apply(Module, Function, [ReplyInfo | Args]) <p>Resets (clears) the cookie database for the specified <c>Profile</c>. If no profile is specified the default profile will be used. </p> + + <marker id="which_cookies"></marker> </desc> </func> @@ -667,6 +672,42 @@ apply(Module, Function, [ReplyInfo | Args]) <p>This function produces a list of the entire cookie database. It is intended for debugging/testing purposes. If no profile is specified the default profile will be used. </p> + + <marker id="which_sessions"></marker> + </desc> + </func> + + <func> + <name>which_sessions() -> session_info()</name> + <name>which_sessions(Profile) -> session_info()</name> + <fsummary>Produces a slightly processed dump of the sessions database.</fsummary> + <type> + <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> + <v>session_info() = {GoodSessions, BadSessions, NonSessions}</v> + <v>GoodSessions = session()</v> + <v>BadSessions = tuple()</v> + <v>NonSessions = term()</v> + </type> + <desc> + <p>This function produces a slightly processed dump of the session + database. It is intended for debugging. + If no profile is specified the default profile will be used. </p> + + <marker id="info"></marker> + </desc> + </func> + + <func> + <name>info() -> list()</name> + <name>info(Profile) -> list()</name> + <fsummary>Produces a list of miscelleneous info</fsummary> + <type> + <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v> + </type> + <desc> + <p>This function produces a list of miscelleneous info. + It is intended for debugging. + If no profile is specified the default profile will be used. </p> </desc> </func> </funcs> diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index dfdeb4016c..3aae1ff70a 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -13,12 +13,12 @@ compliance with the License. You should have received a copy of the Erlang Public License along with this software. If not, it can be retrieved online at http://www.erlang.org/. - + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. - + </legalnotice> <title>Inets Release Notes</title> @@ -32,16 +32,93 @@ <file>notes.xml</file> </header> + + <section> + <title>Inets 5.9.1</title> + + <section> + <title>Improvements and New Features</title> + <!-- + <p>-</p> + --> + + <list> + <item> + <p>Better handling of errorI(s) during update of the session + database. </p> + <p>Also added and updated some debugging functions + <seealso marker="httpc#which_sessions">which_sessions/10,1</seealso> + and + <seealso marker="httpc#info">info/0</seealso>. </p> + <p>Own Id: OTP-10093</p> + <p>Aux Id: Seq 12062</p> + </item> - <section><title>Inets 5.9</title> - - <section><title>Improvements and New Features</title> -<!-- - <p>-</p> ---> + <item> + <p>Removed R14B compatible version of (inets-service and + tftp) behaviour definition. </p> + <p>Own Id: OTP-10095</p> + </item> + + <item> + <p>[httpc] Documentation of KeepAlive and Pipeline timeout + options have been improved. </p> + <p>Own Id: OTP-10114</p> + </item> + </list> + + </section> + <section> + <title>Fixed Bugs and Malfunctions</title> + <!-- + <p>-</p> + --> + <list> <item> + <p>[httpc] Cancel request does not work due to incorrect + handler table creation (wrong keypos). </p> + <p>Vyacheslav Vorobyov</p> + <p>Own Id: OTP-10092</p> + </item> + + </list> + + </section> + + <section> + <title>Incompatibilities</title> + <p>-</p> + + <!-- + <list> + <item> + <p>[httpc|httpd] The old ssl implementation (based on OpenSSL), + has been deprecated. The config option that specified usage of + this version of the ssl app, <c>ossl</c>, has been removed. </p> + <p>Own Id: OTP-9522</p> + </item> + + </list> + --> + + </section> + + </section> <!-- 5.9.1 --> + + + <section> + <title>Inets 5.9</title> + + <section> + <title>Improvements and New Features</title> + <!-- + <p>-</p> + --> + + <list> + <item> <p>[httpd] Make the server header configurable with new config option <seealso marker="httpd#prop_server_tokens">server_tokens</seealso>. @@ -102,11 +179,11 @@ </section> +<!-- <section> <title>Incompatibilities</title> <p>-</p> -<!-- <list> <item> <p>[httpc|httpd] The old ssl implementation (based on OpenSSL), @@ -116,9 +193,9 @@ </item> </list> ---> </section> +--> </section> <!-- 5.9 --> @@ -285,31 +362,6 @@ </section> - <section> - <title>Incompatibilities</title> -<!-- - <p>-</p> ---> - - <list> - <item> - <p>[httpc] Deprecated interface module <c>http</c> has been removed. - It has (long) been replaced by http client interface module - <seealso marker="httpc#">httpc</seealso>. </p> - <p>Own Id: OTP-9359</p> - </item> - - <item> - <p>[httpc|httpd] The old ssl implementation (based on OpenSSL), - has been deprecated. The config option that specified usage of - this version of the ssl app, <c>ossl</c>, has been removed. </p> - <p>Own Id: OTP-9522</p> - </item> - - </list> - - </section> - <section><title>Fixed Bugs and Malfunctions</title> <!-- <p>-</p> @@ -332,6 +384,24 @@ </list> </section> +<!-- + <section> + <title>Incompatibilities</title> + <p>-</p> + + <list> + <item> + <p>[httpc] Deprecated interface module <c>http</c> has been removed. + It has (long) been replaced by http client interface module + <seealso marker="httpc#">httpc</seealso>. </p> + <p>Own Id: OTP-9359</p> + </item> + + </list> + + </section> +--> + </section> <!-- 5.7.2 --> diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index f4802fb96d..b6e7708353 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -39,6 +39,7 @@ cookie_header/1, cookie_header/2, cookie_header/3, which_cookies/0, which_cookies/1, reset_cookies/0, reset_cookies/1, + which_sessions/0, which_sessions/1, stream_next/1, default_profile/0, profile_name/1, profile_name/2, @@ -267,6 +268,7 @@ set_option(Key, Value, Profile) -> %% Reason - term() %% Description: Retrieves the current options. %%------------------------------------------------------------------------- + get_options() -> record_info(fields, options). @@ -373,8 +375,6 @@ cookie_header(Url, Opts, Profile) {error, {not_started, Profile}} end. - - %%-------------------------------------------------------------------------- %% which_cookies() -> [cookie()] @@ -398,6 +398,28 @@ which_cookies(Profile) -> %%-------------------------------------------------------------------------- +%% which_sessions() -> {GoodSession, BadSessions, NonSessions} +%% which_sessions(Profile) -> {GoodSession, BadSessions, NonSessions} +%% +%% Description: Debug function, dumping the sessions database, sorted +%% into three groups (Good-, Bad- and Non-sessions). +%%------------------------------------------------------------------------- +which_sessions() -> + which_sessions(default_profile()). + +which_sessions(Profile) -> + ?hcrt("which sessions", [{profile, Profile}]), + try + begin + httpc_manager:which_sessions(profile_name(Profile)) + end + catch + exit:{noproc, _} -> + {[], [], []} + end. + + +%%-------------------------------------------------------------------------- %% info() -> list() %% info(Profile) -> list() %% diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index b8c34bd99b..6fe05dec80 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1713,7 +1713,32 @@ update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) -> catch error:undef -> % This could happen during code upgrade Session2 = erlang:setelement(Pos, Session, Value), - insert_session(Session2, ProfileName) + insert_session(Session2, ProfileName); + T:E -> + error_logger:error_msg("Failed updating session: " + "~n ProfileName: ~p" + "~n SessionId: ~p" + "~n Pos: ~p" + "~n Value: ~p" + "~nwhen" + "~n Session (db) info: ~p" + "~n Session (db): ~p" + "~n Session (record): ~p" + "~n T: ~p" + "~n E: ~p", + [ProfileName, SessionId, Pos, Value, + (catch httpc_manager:which_session_info(ProfileName)), + Session, + (catch httpc_manager:lookup_session(ProfileName, SessionId)), + T, E]), + exit({failed_updating_session, + [{profile, ProfileName}, + {session_id, SessionId}, + {pos, Pos}, + {value, Value}, + {etype, T}, + {error, E}, + {stacktrace, erlang:get_stacktrace()}]}) end. diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index b225b43214..3612b331e7 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -34,8 +34,11 @@ retry_request/2, redirect_request/2, insert_session/2, + lookup_session/2, update_session/4, delete_session/2, + which_sessions/1, + which_session_info/1, set_options/2, get_options/2, store_cookies/3, @@ -59,17 +62,9 @@ options = #options{} }). --record(handler_info, - { - id, % Id of the request: request_id() - starter, % Pid of the handler starter process (temp): pid() - handler, % Pid of the handler process: pid() - from, % From for the request: from() - state % State of the handler: initiating | started | operational | canceled - }). - -define(DELAY, 500). + %%==================================================================== %% Internal Application API %%==================================================================== @@ -195,13 +190,28 @@ insert_session(Session, ProfileName) -> %%-------------------------------------------------------------------- +%% Function: lookup_session(SessionId, ProfileName) -> _ +%% SessionId - term() +%% ProfileName - atom() +%% +%% Description: Looks up a session record in the httpc manager +%% table <ProfileName>__session_db. +%%-------------------------------------------------------------------- + +lookup_session(SessionId, ProfileName) -> + SessionDbName = session_db_name(ProfileName), + ?hcrt("lookup session", [{session_id, SessionId}, {profile, ProfileName}]), + ets:lookup(SessionDbName, SessionId). + + +%%-------------------------------------------------------------------- %% Function: update_session(ProfileName, SessionId, Pos, Value) -> _ %% Session - #session{} %% ProfileName - atom() %% %% Description: Update, only one field (Pos) of the session record %% identified by the SessionId, the session information -%% of the httpc manager table <ProfileName>_session_db. +%% of the httpc manager table <ProfileName>__session_db. %% Intended to be called by the httpc request handler process. %%-------------------------------------------------------------------- @@ -216,12 +226,12 @@ update_session(ProfileName, SessionId, Pos, Value) -> %%-------------------------------------------------------------------- -%% Function: delete_session(SessionId, ProfileName) -> _ +%% Function: delete_session(SessionId, ProfileName) -> void() %% SessionId - {{Host, Port}, HandlerPid} %% ProfileName - atom() %% %% Description: Deletes session information from the httpc manager -%% table httpc_manager_session_db_<Profile>. Intended to be called by +%% table <ProfileName>__session_db. Intended to be called by %% the httpc request handler process. %%-------------------------------------------------------------------- @@ -232,6 +242,57 @@ delete_session(SessionId, ProfileName) -> %%-------------------------------------------------------------------- +%% Function: which sessions(ProfileName) -> SessionsInfo +%% ProfileName - atom() +%% SessionsInfo - {GoodSessions, BadSessions, NonSessions} +%% GoodSessions - [#session{}] +%% BadSessions - [tuple()] +%% NonSessions - [term()] +%% +%% Description: Produces a list of all sessions in the session db. +%% Used for debugging and since that is the intent, there is some +%% checking and transforming done, which produces the results. +%%-------------------------------------------------------------------- + +which_sessions(ProfileName) -> + ?hcrt("which_sessions", [{profile, ProfileName}]), + SessionDbName = session_db_name(ProfileName), + which_sessions2(SessionDbName). + +which_sessions2(SessionDbName) -> + Sessions = which_sessions_order(ets:tab2list(SessionDbName)), + GoodSessions = [GoodSession || {good_session, GoodSession} <- Sessions], + BadSessions = [BadSession || {bad_session, BadSession} <- Sessions], + NonSessions = [NonSession || {non_session, NonSession} <- Sessions], + {lists:keysort(#session.id, GoodSessions), + lists:keysort(#session.id, BadSessions), + lists:sort(NonSessions)}. + +which_sessions_order([]) -> + []; +which_sessions_order([Session|Sessions]) when is_record(Session, session) -> + [{good_session, Session} | which_sessions_order(Sessions)]; +which_sessions_order([BadSession|Sessions]) + when is_tuple(BadSession) andalso + (element(1, BadSession) =:= session) -> + [{bad_session, BadSession} | which_sessions_order(Sessions)]; +which_sessions_order([NonSession|Sessions]) -> + [{non_session, NonSession} | which_sessions_order(Sessions)]. + + +%%-------------------------------------------------------------------- +%% Function: which session_info(ProfileName) -> list() +%% +%% Description: Produces a ets table info list of the sessions table +%%-------------------------------------------------------------------- + +which_session_info(ProfileName) -> + SessionDbName = session_db_name(ProfileName), + ?hcrt("which_session_info", [{profile, ProfileName}]), + ets:info(SessionDbName). + + +%%-------------------------------------------------------------------- %% Function: set_options(Options, ProfileName) -> ok %% %% Options = [Option] @@ -379,8 +440,7 @@ do_init(ProfileName, CookiesDir) -> %% Create handler db ?hcrt("create handler/request db", []), HandlerDbName = handler_db_name(ProfileName), - ets:new(HandlerDbName, - [protected, set, named_table, {keypos, #handler_info.id}]), + ets:new(HandlerDbName, [protected, set, named_table, {keypos, 1}]), %% Cookie DB ?hcrt("create cookie db", []), @@ -414,9 +474,10 @@ handle_call({request, Request}, _, State) -> {stop, Error, httpc_response:error(Request, Error), State} end; -handle_call({cancel_request, RequestId}, From, State) -> +handle_call({cancel_request, RequestId}, From, + #state{handler_db = HandlerDb} = State) -> ?hcri("cancel_request", [{request_id, RequestId}]), - case ets:lookup(State#state.handler_db, RequestId) of + case ets:lookup(HandlerDb, RequestId) of [] -> %% The request has allready compleated make sure %% it is deliverd to the client process queue so @@ -428,9 +489,9 @@ handle_call({cancel_request, RequestId}, From, State) -> {noreply, State}; [{_, Pid, _}] -> httpc_handler:cancel(RequestId, Pid, From), - {noreply, State#state{cancel = - [{RequestId, Pid, From} | - State#state.cancel]}} + {noreply, + State#state{cancel = + [{RequestId, Pid, From} | State#state.cancel]}} end; handle_call(reset_cookies, _, #state{cookie_db = CookieDb} = State) -> @@ -457,8 +518,8 @@ handle_call({which_cookies, Url, Options}, _, handle_call({get_options, OptionItems}, _, #state{options = Options} = State) -> ?hcrv("get options", [{option_items, OptionItems}]), - Reply = [{OptionItem, get_option(OptionItem, Options)} || OptionItem <- - OptionItems], + Reply = [{OptionItem, get_option(OptionItem, Options)} || + OptionItem <- OptionItems], {reply, Reply, State}; handle_call(info, _, State) -> @@ -645,7 +706,7 @@ code_change(_, code_change(_, State, _) -> {ok, State}. -%% This function is to catch everything that calls through the cracks... +%% This function is used to catch everything that falls through the cracks... update_session_table(SessionDB, Transform) -> ets:safe_fixtable(SessionDB, true), update_session_table(SessionDB, ets:first(SessionDB), Transform), @@ -673,40 +734,56 @@ update_session_table(SessionDB, Key, Transform) -> %%-------------------------------------------------------------------- get_manager_info(#state{handler_db = HDB, - cookie_db = CDB} = _State) -> + session_db = SDB, + cookie_db = CDB, + options = Options} = _State) -> HandlerInfo = get_handler_info(HDB), + SessionInfo = which_sessions2(SDB), + OptionsInfo = + [{Item, get_option(Item, Options)} || + Item <- record_info(fields, options)], CookieInfo = httpc_cookie:which_cookies(CDB), - [{handlers, HandlerInfo}, {cookies, CookieInfo}]. + [{handlers, HandlerInfo}, + {sessions, SessionInfo}, + {options, OptionsInfo}, + {cookies, CookieInfo}]. + +sort_handlers(Unsorted) -> + sort_handlers2(lists:keysort(1, Unsorted)). + +sort_handlers2([]) -> + []; +sort_handlers2([{HandlerPid, RequestId}|L]) -> + {Handler, Rest} = sort_handlers2(HandlerPid, [RequestId], L), + [Handler | sort_handlers2(Rest)]. + +sort_handlers2(HandlerPid, Reqs, []) -> + {{HandlerPid, lists:sort(Reqs)}, []}; +sort_handlers2(HandlerPid, Reqs, [{HandlerPid, ReqId}|Rest]) -> + sort_handlers2(HandlerPid, [ReqId|Reqs], Rest); +sort_handlers2(HandlerPid1, Reqs, [{HandlerPid2, _}|_] = Rest) + when HandlerPid1 =/= HandlerPid2 -> + {{HandlerPid1, lists:sort(Reqs)}, Rest}. get_handler_info(Tab) -> - Pattern = #handler_info{handler = '$1', - state = '$2', - _ = '_'}, - Handlers1 = [{Pid, State} || [Pid, State] <- ets:match(Tab, Pattern)], - F = fun({Pid, State} = Elem, Acc) when State =/= canceled -> - case lists:keymember(Pid, 1, Acc) of - true -> - Acc; - false -> - [Elem | Acc] - end; - (_, Acc) -> - Acc - end, - Handlers2 = lists:foldl(F, [], Handlers1), - Handlers3 = [{Pid, State, - case (catch httpc_handler:info(Pid)) of - {'EXIT', _} -> + Pattern = {'$2', '$1', '_'}, + Handlers1 = [{Pid, Id} || [Pid, Id] <- ets:match(Tab, Pattern)], + Handlers2 = sort_handlers(Handlers1), + Handlers3 = [{Pid, Reqs, + try + begin + httpc_handler:info(Pid) + end + catch + _:_ -> %% Why would this crash? %% Only if the process has died, but we don't %% know about it? - []; - Else -> - Else - end} || - {Pid, State} <- Handlers2], + [] + end} || {Pid, Reqs} <- Handlers2], Handlers3. + handle_request(#request{settings = #http_options{version = "HTTP/0.9"}} = Request, State) -> @@ -758,19 +835,21 @@ handle_request(Request, State = #state{options = Options}) -> {reply, {ok, NewRequest#request.id}, State}. -start_handler(Request, State) -> +start_handler(#request{id = Id, + from = From} = Request, + #state{profile_name = ProfileName, + handler_db = HandlerDb, + options = Options}) -> {ok, Pid} = case is_inets_manager() of true -> httpc_handler_sup:start_child([whereis(httpc_handler_sup), - Request, State#state.options, - State#state.profile_name]); + Request, Options, ProfileName]); false -> - httpc_handler:start_link(self(), Request, State#state.options, - State#state.profile_name) + httpc_handler:start_link(self(), Request, Options, ProfileName) end, - ets:insert(State#state.handler_db, {Request#request.id, - Pid, Request#request.from}), + HandlerInfo = {Id, Pid, From}, + ets:insert(HandlerDb, HandlerInfo), erlang:monitor(process, Pid). @@ -827,12 +906,14 @@ select_session(Candidates, Max) -> {ok, HandlerPid} end. -pipeline_or_keep_alive(Request, HandlerPid, State) -> +pipeline_or_keep_alive(#request{id = Id, + from = From} = Request, + HandlerPid, + #state{handler_db = HandlerDb} = State) -> case (catch httpc_handler:send(Request, HandlerPid)) of ok -> - ets:insert(State#state.handler_db, {Request#request.id, - HandlerPid, - Request#request.from}); + HandlerInfo = {Id, HandlerPid, From}, + ets:insert(HandlerDb, HandlerInfo); _ -> % timeout pipelining failed start_handler(Request, State) end. diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index c7029f7b31..2adb2a0fc8 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -18,14 +18,25 @@ {"%VSN%", [ + {"5.9", + [ + {load_module, tftp, soft_purge, soft_purge, [inets_service]}, + {load_module, inets_service, soft_purge, soft_purge, []}, + {load_module, httpc, soft_purge, soft_purge, [httpc_manager]}, + {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]}, + {update, httpc_manager, soft, soft_purge, soft_purge, []} + ] + }, {"5.8.1", [ + {load_module, tftp, soft_purge, soft_purge, [inets_service]}, + {load_module, inets_service, soft_purge, soft_purge, []}, + {load_module, http_uri, soft_purge, soft_purge, []}, {load_module, httpc_response, soft_purge, soft_purge, [http_uri]}, {load_module, httpc, soft_purge, soft_purge, [http_uri, httpc_manager]}, - {update, httpc_manager, soft, soft_purge, soft_purge, [http_uri]}, {load_module, inets_app, soft_purge, soft_purge, [inets_sup]}, {update, inets_sup, soft, soft_purge, soft_purge, []}, @@ -35,36 +46,15 @@ {load_module, httpd_script_env, soft_purge, soft_purge, []}, {load_module, inets, soft_purge, soft_purge, [inets_trace]}, - {update, httpc_handler, soft, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, [http_uri]}, + {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]}, {update, httpd_sup, soft, soft_purge, soft_purge, []}, {add_module, inets_trace} ] }, - {"5.8", + {"5.8", [ - {load_module, http_uri, soft_purge, soft_purge, []}, - {load_module, httpc_response, soft_purge, soft_purge, [http_uri]}, - - {load_module, httpc, soft_purge, soft_purge, - [http_uri, httpc_manager]}, - - {load_module, inets_app, soft_purge, soft_purge, [inets_sup]}, - {update, inets_sup, soft, soft_purge, soft_purge, []}, - - {load_module, inets, soft_purge, soft_purge, [inets_trace]}, - - {load_module, httpd_conf, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, []}, - {load_module, httpd_script_env, soft_purge, soft_purge, []}, - - {load_module, ftp, soft_purge, soft_purge, []}, - {update, httpc_handler, {advanced, upgrade_from_pre_5_8_1}, - soft_purge, soft_purge, []}, - {update, httpc_manager, {advanced, upgrade_from_pre_5_8_1}, - soft_purge, soft_purge, [http_uri, httpc_handler]}, - {update, httpd_sup, soft, soft_purge, soft_purge, []}, - - {add_module, inets_trace} + {restart_application, inets} ] }, {"5.7.2", @@ -74,14 +64,25 @@ } ], [ + {"5.9", + [ + {load_module, tftp, soft_purge, soft_purge, [inets_service]}, + {load_module, inets_service, soft_purge, soft_purge, []}, + {load_module, httpc, soft_purge, soft_purge, [httpc_manager]}, + {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]}, + {update, httpc_manager, soft, soft_purge, soft_purge, []} + ] + }, {"5.8.1", [ + {load_module, tftp, soft_purge, soft_purge, [inets_service]}, + {load_module, inets_service, soft_purge, soft_purge, []}, + {load_module, http_uri, soft_purge, soft_purge, []}, {load_module, httpc_response, soft_purge, soft_purge, [http_uri]}, {load_module, httpc, soft_purge, soft_purge, [http_uri, httpc_manager]}, - {update, httpc_manager, soft, soft_purge, soft_purge, [http_uri]}, {load_module, inets_app, soft_purge, soft_purge, [inets_sup]}, {update, inets_sup, soft, soft_purge, soft_purge, []}, @@ -91,36 +92,15 @@ {load_module, httpd_script_env, soft_purge, soft_purge, []}, {load_module, inets, soft_purge, soft_purge, []}, - {update, httpc_handler, soft, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, [http_uri]}, + {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]}, {update, httpd_sup, soft, soft_purge, soft_purge, []}, {remove, {inets_trace, soft_purge, brutal_purge}} ] }, {"5.8", [ - {load_module, http_uri, soft_purge, soft_purge, []}, - {load_module, httpc_response, soft_purge, soft_purge, [http_uri]}, - - {load_module, httpc, soft_purge, soft_purge, - [http_uri, httpc_manager]}, - - {load_module, inets_app, soft_purge, soft_purge, [inets_sup]}, - {update, inets_sup, soft, soft_purge, soft_purge, []}, - - {load_module, inets, soft_purge, soft_purge, []}, - - {load_module, httpd_conf, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, []}, - {load_module, httpd_script_env, soft_purge, soft_purge, []}, - - {load_module, ftp, soft_purge, soft_purge, []}, - {update, httpc_handler, {advanced, upgrade_from_pre_5_8_1}, - soft_purge, soft_purge, []}, - {update, httpc_manager, {advanced, upgrade_from_pre_5_8_1}, - soft_purge, soft_purge, [http_uri, httpc_handler]}, - {update, httpd_sup, soft, soft_purge, soft_purge, []}, - - {remove, {inets_trace, soft_purge, brutal_purge}} + {restart_application, inets} ] }, {"5.7.2", diff --git a/lib/inets/src/inets_app/inets.mk b/lib/inets/src/inets_app/inets.mk index d24cc0aea3..adef32dc19 100644 --- a/lib/inets/src/inets_app/inets.mk +++ b/lib/inets/src/inets_app/inets.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2010-2011. All Rights Reserved. +# Copyright Ericsson AB 2010-2012. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -33,10 +33,6 @@ ifeq ($(WARN_UNUSED_WARS), true) ERL_COMPILE_FLAGS += +warn_unused_vars endif -ifeq ($(shell erl -noshell -eval 'io:format("~4s", [erlang:system_info(otp_release)])' -s init stop), R14B) -INETS_ERL_COMPILE_FLAGS += -D'OTP-R14B-COMPILER' -endif - INETS_APP_VSN_COMPILE_FLAGS = \ +'{parse_transform,sys_pre_attributes}' \ +'{attribute,insert,app_vsn,$(APP_VSN)}' diff --git a/lib/inets/src/inets_app/inets_service.erl b/lib/inets/src/inets_app/inets_service.erl index a057a51e2c..d17fdfe13e 100644 --- a/lib/inets/src/inets_app/inets_service.erl +++ b/lib/inets/src/inets_app/inets_service.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,20 +20,6 @@ -module(inets_service). --ifdef('OTP-R14B-COMPILER'). - --export([behaviour_info/1]). - -behaviour_info(callbacks) -> - [{start_standalone, 1}, - {start_service, 1}, - {stop_service, 1}, - {services, 0}, - {service_info, 1}]; -behaviour_info(_) -> - undefined. - --else. %% Starts service stand-alone %% start_standalone(Config) -> % {ok, Pid} | {error, Reason} @@ -83,4 +69,3 @@ behaviour_info(_) -> -callback service_info(Service :: term()) -> {ok, [{Property :: term(), Value :: term()}]} | {error, Reason :: term()}. --endif. diff --git a/lib/inets/src/tftp/tftp.erl b/lib/inets/src/tftp/tftp.erl index 0d7ae1a89e..1621add246 100644 --- a/lib/inets/src/tftp/tftp.erl +++ b/lib/inets/src/tftp/tftp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2011. All Rights Reserved. +%% Copyright Ericsson AB 2005-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -224,20 +224,6 @@ service_info/1 ]). --ifdef('OTP-R14B-COMPILER'). - --export([behaviour_info/1]). - -behaviour_info(callbacks) -> - [{prepare, 6}, - {open, 6}, - {read, 1}, - {write, 2}, - {abort, 3}]; -behaviour_info(_) -> - undefined. - --else. -type peer() :: {PeerType :: inet | inet6, PeerHost :: inet:ip_address(), @@ -280,8 +266,6 @@ behaviour_info(_) -> -callback abort(Code :: error_code(), string(), State :: term()) -> 'ok'. --endif. - -include("tftp.hrl"). diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index a116edef77..1cdd96f0b0 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -761,116 +761,158 @@ http_inets_pipe(Config) when is_list(Config) -> test_pipeline(URL) -> - p("test_pipeline -> entry with" - "~n URL: ~p", [URL]), - - httpc:set_options([{pipeline_timeout, 50000}]), - - p("test_pipeline -> issue (async) request 1"), - {ok, RequestId1} = + p("test_pipeline -> entry with" + "~n URL: ~p", [URL]), + + httpc:set_options([{pipeline_timeout, 50000}]), + + p("test_pipeline -> issue (async) request 1" + "~n when profile info: ~p", [httpc:info()]), + {ok, RequestIdA1} = httpc:request(get, {URL, []}, [], [{sync, false}]), - test_server:format("RequestId1: ~p~n", [RequestId1]), - p("test_pipeline -> RequestId1: ~p", [RequestId1]), - - %% Make sure pipeline is initiated - p("test_pipeline -> sleep some", []), - test_server:sleep(4000), - - p("test_pipeline -> issue (async) request 2"), - {ok, RequestId2} = + tsp("RequestIdA1: ~p", [RequestIdA1]), + p("test_pipeline -> RequestIdA1: ~p" + "~n when profile info: ~p", [RequestIdA1, httpc:info()]), + + %% Make sure pipeline is initiated + p("test_pipeline -> sleep some", []), + test_server:sleep(4000), + + p("test_pipeline -> issue (async) request A2, A3 and A4" + "~n when profile info: ~p", [httpc:info()]), + {ok, RequestIdA2} = httpc:request(get, {URL, []}, [], [{sync, false}]), - tsp("RequestId2: ~p", [RequestId2]), - p("test_pipeline -> RequestId2: ~p", [RequestId2]), - - p("test_pipeline -> issue (sync) request 3"), - {ok, {{_,200,_}, [_ | _], [_ | _]}} = + {ok, RequestIdA3} = + httpc:request(get, {URL, []}, [], [{sync, false}]), + {ok, RequestIdA4} = + httpc:request(get, {URL, []}, [], [{sync, false}]), + tsp("RequestIdAs => A2: ~p, A3: ~p and A4: ~p", + [RequestIdA2, RequestIdA3, RequestIdA4]), + p("test_pipeline -> RequestIds => A2: ~p, A3: ~p and A4: ~p" + "~n when profile info: ~p", + [RequestIdA2, RequestIdA3, RequestIdA4, httpc:info()]), + + p("test_pipeline -> issue (sync) request 3"), + {ok, {{_,200,_}, [_ | _], [_ | _]}} = httpc:request(get, {URL, []}, [], []), + + p("test_pipeline -> expect reply for (async) request A1, A2, A3 and A4" + "~n when profile info: ~p", [httpc:info()]), + pipeline_await_async_reply([{RequestIdA1, a1, 200}, + {RequestIdA2, a2, 200}, + {RequestIdA3, a3, 200}, + {RequestIdA4, a4, 200}], ?MINS(1)), - p("test_pipeline -> expect reply for (async) request 1 or 2"), - receive - {http, {RequestId1, {{_, 200, _}, _, _}}} -> - p("test_pipeline -> received reply for (async) request 1 - now wait for 2"), - receive - {http, {RequestId2, {{_, 200, _}, _, _}}} -> - p("test_pipeline -> received reply for (async) request 2"), - ok; - {http, Msg1} -> - tsf(Msg1) - end; - {http, {RequestId2, {{_, 200, _}, _, _}}} -> - io:format("test_pipeline -> received reply for (async) request 2 - now wait for 1"), - receive - {http, {RequestId1, {{_, 200, _}, _, _}}} -> - io:format("test_pipeline -> received reply for (async) request 1"), - ok; - {http, Msg2} -> - tsf(Msg2) - end; - {http, Msg3} -> - tsf(Msg3) - after 60000 -> - receive Any1 -> - tsp("received crap after timeout: ~n ~p", [Any1]), - tsf({error, {timeout, Any1}}) - end - end, - - p("test_pipeline -> sleep some"), - test_server:sleep(4000), - - p("test_pipeline -> issue (async) request 4"), - {ok, RequestId3} = + p("test_pipeline -> sleep some" + "~n when profile info: ~p", [httpc:info()]), + test_server:sleep(4000), + + p("test_pipeline -> issue (async) request B1, B2, B3 and B4" + "~n when profile info: ~p", [httpc:info()]), + {ok, RequestIdB1} = httpc:request(get, {URL, []}, [], [{sync, false}]), - tsp("RequestId3: ~p", [RequestId3]), - p("test_pipeline -> RequestId3: ~p", [RequestId3]), - - p("test_pipeline -> issue (async) request 5"), - {ok, RequestId4} = + {ok, RequestIdB2} = httpc:request(get, {URL, []}, [], [{sync, false}]), - tsp("RequestId4: ~p~n", [RequestId4]), - p("test_pipeline -> RequestId4: ~p", [RequestId4]), - - p("test_pipeline -> cancel (async) request 4"), - ok = httpc:cancel_request(RequestId3), - - p("test_pipeline -> expect *no* reply for cancelled (async) request 4 (for 3 secs)"), - receive - {http, {RequestId3, _}} -> - tsf(http_cancel_request_failed) - after 3000 -> - ok - end, - - p("test_pipeline -> expect reply for (async) request 4"), - Body = - receive - {http, {RequestId4, {{_, 200, _}, _, BinBody4}}} = Res -> - p("test_pipeline -> received reply for (async) request 5"), - tsp("Receive : ~p", [Res]), - BinBody4; - {http, Msg4} -> - tsf(Msg4) - after 60000 -> - receive Any2 -> - tsp("received crap after timeout: ~n ~p", [Any2]), - tsf({error, {timeout, Any2}}) - end - end, + {ok, RequestIdB3} = + httpc:request(get, {URL, []}, [], [{sync, false}]), + {ok, RequestIdB4} = + httpc:request(get, {URL, []}, [], [{sync, false}]), + tsp("RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p", + [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4]), + p("test_pipeline -> RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p" + "~n when profile info: ~p", + [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4, httpc:info()]), + + p("test_pipeline -> cancel (async) request B2" + "~n when profile info: ~p", [httpc:info()]), + ok = httpc:cancel_request(RequestIdB2), + + p("test_pipeline -> " + "expect *no* reply for cancelled (async) request B2 (for 3 secs)" + "~n when profile info: ~p", [httpc:info()]), + receive + {http, {RequestIdB2, _}} -> + tsf(http_cancel_request_failed) + after 3000 -> + ok + end, + + p("test_pipeline -> expect reply for (async) request B1, B3 and B4" + "~n when profile info: ~p", [httpc:info()]), + Bodies = pipeline_await_async_reply([{RequestIdB1, b1, 200}, + {RequestIdB3, b3, 200}, + {RequestIdB4, b4, 200}], ?MINS(1)), + [{b1, Body}|_] = Bodies, - p("test_pipeline -> check reply for (async) request 5"), + p("test_pipeline -> check reply for (async) request B1" + "~n when profile info: ~p", [httpc:info()]), inets_test_lib:check_body(binary_to_list(Body)), - - p("test_pipeline -> ensure no unexpected incomming"), + + p("test_pipeline -> ensure no unexpected incomming" + "~n when profile info: ~p", [httpc:info()]), receive {http, Any} -> tsf({unexpected_message, Any}) after 500 -> ok end, - - p("test_pipeline -> done"), + + p("test_pipeline -> done" + "~n when profile info: ~p", [httpc:info()]), ok. +pipeline_await_async_reply(ReqIds, Timeout) -> + pipeline_await_async_reply(ReqIds, Timeout, []). + +pipeline_await_async_reply([], _, Acc) -> + lists:keysort(1, Acc); +pipeline_await_async_reply(ReqIds, Timeout, Acc) when Timeout > 0 -> + T1 = inets_test_lib:timestamp(), + p("pipeline_await_async_reply -> await replies" + "~n ReqIds: ~p" + "~n Timeout: ~p", [ReqIds, Timeout]), + receive + {http, {RequestId, {{_, Status, _}, _, Body}}} -> + p("pipeline_await_async_reply -> received reply for" + "~n RequestId: ~p" + "~n Status: ~p", [RequestId, Status]), + case lists:keysearch(RequestId, 1, ReqIds) of + {value, {RequestId, N, Status}} -> + p("pipeline_await_async_reply -> " + "found expected request ~w", [N]), + ReqIds2 = lists:keydelete(RequestId, 1, ReqIds), + NewTimeout = Timeout - (inets_test_lib:timestamp()-T1), + pipeline_await_async_reply(ReqIds2, NewTimeout, + [{N, Body} | Acc]); + {value, {RequestId, N, WrongStatus}} -> + p("pipeline_await_async_reply -> " + "found request ~w with wrong status", [N]), + tsf({reply_with_unexpected_status, + {RequestId, N, WrongStatus}}); + false -> + tsf({unexpected_reply, {RequestId, Status}}) + end; + {http, Msg} -> + tsf({unexpected_reply, Msg}) + after Timeout -> + receive + Any -> + tsp("pipeline_await_async_reply -> " + "received unknown data after timeout: " + "~n ~p", [Any]), + tsf({timeout, {unknown, Any}}) + end + end; +pipeline_await_async_reply(ReqIds, _, Acc) -> + tsp("pipeline_await_async_reply -> " + "timeout: " + "~n ~p" + "~nwhen" + "~n ~p", [ReqIds, Acc]), + tsf({timeout, ReqIds, Acc}). + + + %%------------------------------------------------------------------------- http_trace(doc) -> ["Perform a TRACE request that goes through a proxy."]; diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl index cb1214b7fb..387263ce58 100644 --- a/lib/inets/test/httpd_mod.erl +++ b/lib/inets/test/httpd_mod.erl @@ -82,19 +82,23 @@ actions(Type, Port, Host, Node) -> [{statuscode, 200}, {version, "HTTP/1.0"}]). + %%------------------------------------------------------------------------- security(ServerRoot, Type, Port, Host, Node) -> - %% io:format(user, "~w:security -> entry with" - %% "~n ServerRoot: ~p" - %% "~n Type: ~p" - %% "~n Port: ~p" - %% "~n Host: ~p" - %% "~n Node: ~p" - %% "~n", [?MODULE, ServerRoot, Type, Port, Host, Node]), - -%% io:format(user, "~w:security -> register~n", [?MODULE]), + tsp("security -> " + "entry with" + "~n ServerRoot: ~p" + "~n Type: ~p" + "~n Port: ~p" + "~n Host: ~p" + "~n Node: ~p", [ServerRoot, Type, Port, Host, Node]), + + tsp("security -> " + "register - receive security events"), global:register_name(mod_security_test, self()), % Receive events + tsp("security -> " + "sleep"), test_server:sleep(5000), OpenDir = filename:join([ServerRoot, "htdocs", "open"]), @@ -102,133 +106,240 @@ security(ServerRoot, Type, Port, Host, Node) -> %% Test blocking / unblocking of users. %% /open, require user one Aladdin -%% io:format(user, "~w:security -> remove user~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "remove all existing users"), remove_users(Node, ServerRoot, Host, Port, "open"), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request for nonex user 'one' - expect 401"), auth_request(Type, Host, Port, Node, "/open/", "one", "onePassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]), + + tsp("security -> " + "blocking and unblocking of users - " + "await fail security event"), receive_security_event({event, auth_fail, Port, OpenDir, [{user, "one"}, {password, "onePassword"}]}, Node, Port), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request for nonex user 'two' - expect 401"), auth_request(Type,Host,Port,Node,"/open/", "two", "twoPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]), + + tsp("security -> " + "blocking and unblocking of users - " + "await fail security event"), receive_security_event({event, auth_fail, Port, OpenDir, [{user, "two"}, {password, "twoPassword"}]}, Node, Port), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request for nonex user 'Alladin' - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "Aladdin", "AladdinPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]), + + tsp("security -> " + "blocking and unblocking of users - " + "await fail security event"), receive_security_event({event, auth_fail, Port, OpenDir, [{user, "Aladdin"}, {password, "AladdinPassword"}]}, Node, Port), -%% io:format(user, "~w:security -> add users~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "add user 'one'"), add_user(Node, ServerRoot, Port, "open", "one", "onePassword", []), + + tsp("security -> " + "blocking and unblocking of users - " + "add user 'two'"), add_user(Node, ServerRoot, Port, "open", "two", "twoPassword", []), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request 1 for user 'one' with wrong password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]), + + tsp("security -> " + "blocking and unblocking of users - " + "await fail security event"), receive_security_event({event, auth_fail, Port, OpenDir, [{user, "one"}, {password, "WrongPassword"}]}, Node, Port), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request 2 for user 'one' with wrong password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]), + + tsp("security -> " + "blocking and unblocking of users - " + "await fail security event"), receive_security_event({event, auth_fail, Port, OpenDir, [{user, "one"}, {password, "WrongPassword"}]}, Node, Port), -%% io:format(user, "~w:security -> await block security event~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "await block security event (two failed attempts)"), receive_security_event({event, user_block, Port, OpenDir, [{user, "one"}]}, Node, Port), -%% io:format(user, "~w:security -> unregister~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "unregister - no more security events"), global:unregister_name(mod_security_test), % No more events. -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request for user 'one' with wrong password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request for user 'one' with correct password - expect 403"), auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword", [{statuscode, 403}]), %% User "one" should be blocked now.. - %% [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node,Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "list blocked users - 'one' should be the only one"), case list_blocked_users(Node, Port) of [{"one",_, Port, OpenDir,_}] -> ok; Blocked -> - %% io:format(user, "~w:security -> Blocked: ~p" - %% "~n", [?MODULE, Blocked]), + tsp(" *** unexpected blocked users ***" + "~n Blocked: ~p", [Blocked]), exit({unexpected_blocked, Blocked}) end, - -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), - [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node,Port,OpenDir), -%% io:format(user, "~w:security -> unblock user~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "list users blocked for dir '~p' - " + "user 'one' should be the only one", [OpenDir]), + [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node, Port, OpenDir), + + tsp("security -> " + "blocking and unblocking of users - " + "unblock user 'one' for dir '~p'", [OpenDir]), true = unblock_user(Node, "one", Port, OpenDir), - %% User "one" should not be blocked any more.. -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + %% User "one" should not be blocked any more. + + tsp("security -> " + "blocking and unblocking of users - " + "ensure user 'one' is no longer blocked"), [] = list_blocked_users(Node, Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), - [] = list_blocked_users(Node, Port, OpenDir), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + + + tsp("security -> " + "blocking and unblocking of users - " + "auth request for user 'one' with correct password - expect 200"), auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword", [{statuscode, 200}]), + + %% Test list_auth_users & auth_timeout -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users - expect user 'one'"), ["one"] = list_auth_users(Node, Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), - ["one"] = list_auth_users(Node, Port, OpenDir), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "auth request for user 'two' with wrong password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "two", "onePassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users - expect user 'one'"), ["one"] = list_auth_users(Node, Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users for dir '~p' - expect user 'one'", [OpenDir]), ["one"] = list_auth_users(Node, Port, OpenDir), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "auth request for user 'two' with correct password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users - expect user 'one'"), ["one"] = list_auth_users(Node, Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users for dir '~p' - expect user 'one'", [OpenDir]), ["one"] = list_auth_users(Node, Port, OpenDir), + %% Wait for successful auth to timeout. + tsp("security -> " + "list-auth-users and auth-timeout - " + "wait for successful auth to timeout"), test_server:sleep(?AUTH_TIMEOUT*1001), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users - expect none"), [] = list_auth_users(Node, Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users for dir '~p'~n - expect none", [OpenDir]), [] = list_auth_users(Node, Port, OpenDir), + %% "two" is blocked. -%% io:format(user, "~w:security -> unblock user~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "unblock user 'two' for dir '~p'", [OpenDir]), true = unblock_user(Node, "two", Port, OpenDir), + + %% Test explicit blocking. Block user 'two'. -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "explicit blocking - list blocked users - should be none"), [] = list_blocked_users(Node,Port,OpenDir), -%% io:format(user, "~w:security -> block user~n", [?MODULE]), + + tsp("security -> " + "explicit blocking - " + "block user 'two' for dir '~p'", [OpenDir]), true = block_user(Node, "two", Port, OpenDir, 10), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + + tsp("security -> " + "explicit blocking - " + "auth request for user 'two' with correct password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword", - [{statuscode, 401}]). + [{statuscode, 401}]), + tsp("security -> " + "done"). + %%------------------------------------------------------------------------- auth(Type, Port, Host, Node) -> + tsp("auth -> " + "entry with" + "~n Type: ~p" + "~n Port: ~p" + "~n Host: ~p" + "~n Node: ~p", [Type, Port, Host, Node]), + %% Authentication required! ok = httpd_test_lib:verify_request(Type,Host,Port,Node, "GET /open/ HTTP/1.0\r\n\r\n", @@ -913,13 +1024,11 @@ list_users(Node, Root, _Host, Port, Dir) -> receive_security_event(Event, Node, Port) -> - %% io:format(user, "~w:receive_security_event -> entry with" - %% "~n Event: ~p" - %% "~n Node: ~p" - %% "~n Port: ~p" - %% "~n", [?MODULE, Event, Node, Port]), + tsp("receive_security_event -> await ~w event", [element(2, Event)]), receive Event -> + tsp("receive_security_event -> " + "received expected ~w event", [element(2, Event)]), ok; {'EXIT', _, _} -> receive_security_event(Event, Node, Port) @@ -1027,8 +1136,14 @@ check_lists_members1(L1,L2) -> {error,{lists_not_equal,L1,L2}}. -%% tsp(F) -> -%% inets_test_lib:tsp(F). +%% p(F) -> +%% p(F, []). + +%% p(F, A) -> +%% io:format(user, "~w:" ++ F ++ "~n", [?MODULE|A]). + +tsp(F) -> + inets_test_lib:tsp(F). tsp(F, A) -> inets_test_lib:tsp(F, A). diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl index c94be796cd..0f8671b682 100644 --- a/lib/inets/test/inets_test_lib.erl +++ b/lib/inets/test/inets_test_lib.erl @@ -31,6 +31,7 @@ send/3, close/2]). -export([copy_file/3, copy_files/2, copy_dirs/2, del_dirs/1]). -export([info/4, log/4, debug/4, print/4]). +-export([timestamp/0, formated_timestamp/0]). -export([tsp/1, tsp/2, tsf/1, tss/1]). -export([check_body/1]). -export([millis/0, millis_diff/2, hours/1, minutes/1, seconds/1, sleep/1]). @@ -530,34 +531,27 @@ connect(ip_comm, Host, Port, Opts, Type) -> "~n Opts: ~p" "~n Type: ~p", [Host, Port, Opts, Type]), - case gen_tcp:connect(Host, Port, Opts) of + case gen_tcp:connect(Host, Port, Opts, timer:seconds(10)) of {ok, Socket} -> tsp("connect success"), {ok, Socket}; - {error, nxdomain} when Type =:= inet6 -> - tsp("connect error nxdomain when" - "~n Opts: ~p", [Opts]), - connect(ip_comm, Host, Port, Opts -- [inet6], inet); - {error, eafnosupport} when Type =:= inet6 -> - tsp("connect error eafnosupport when" - "~n Opts: ~p", [Opts]), - connect(ip_comm, Host, Port, Opts -- [inet6], inet); - {error, econnreset} when Type =:= inet6 -> - tsp("connect error econnreset when" - "~n Opts: ~p", [Opts]), - connect(ip_comm, Host, Port, Opts -- [inet6], inet); - {error, enetunreach} when Type =:= inet6 -> - tsp("connect error eafnosupport when" - "~n Opts: ~p", [Opts]), - connect(ip_comm, Host, Port, Opts -- [inet6], inet); - {error, econnrefused} when Type =:= inet6 -> - tsp("connect error econnrefused when" - "~n Opts: ~p", [Opts]), + {error, Reason} when ((Type =:= inet6) andalso + ((Reason =:= timeout) orelse + (Reason =:= nxdomain) orelse + (Reason =:= eafnosupport) orelse + (Reason =:= econnreset) orelse + (Reason =:= enetunreach) orelse + (Reason =:= econnrefused) orelse + (Reason =:= ehostunreach))) -> + tsp("connect(ip_comm) -> Connect error: " + "~n Reason: ~p" + "~n Type: ~p" + "~n Opts: ~p", [Reason, Type, Opts]), connect(ip_comm, Host, Port, Opts -- [inet6], inet); Error -> - tsp("connect(ip_conn) -> Fatal connect error: " + tsp("connect(ip_comm) -> Fatal connect error: " "~n Error: ~p" "~nwhen" "~n Host: ~p" @@ -642,6 +636,9 @@ tsf(Reason) -> tss(Time) -> test_server:sleep(Time). +timestamp() -> + http_util:timestamp(). + formated_timestamp() -> format_timestamp( os:timestamp() ). diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 488947c3a1..949eceea7f 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 5.9 +INETS_VSN = 5.9.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" diff --git a/lib/kernel/doc/src/packages.xml b/lib/kernel/doc/src/packages.xml index 80de2e05fc..81b8693baa 100644 --- a/lib/kernel/doc/src/packages.xml +++ b/lib/kernel/doc/src/packages.xml @@ -204,11 +204,5 @@ ok Explicitly declaring each use of a module makes for safe code.</p> </description> - <funcs> - <func> - <name>no functions exported</name> - <fsummary>x</fsummary> - </func> - </funcs> </erlref> diff --git a/lib/runtime_tools/c_src/dtrace_user.d b/lib/runtime_tools/c_src/dtrace_user.d index 02150375af..9e180a3cb2 100644 --- a/lib/runtime_tools/c_src/dtrace_user.d +++ b/lib/runtime_tools/c_src/dtrace_user.d @@ -19,3118 +19,11 @@ */ provider erlang { - /** - * Send a single string to a probe. - * - * @param NUL-terminated string + /* + * The set of probes for use by Erlang code ... moved from here to + * erts/emulator/beam/erlang_dtrace.d until a more portable solution is + * found; see erlang_dtrace.d for details. */ - probe user_trace__s1(char* message); - - /** - * Multi-purpose probe: up to 4 NUL-terminated strings and 4 - * 64-bit integer arguments. - * - * @param proc, the PID (string form) of the sending process - * @param user_tag, the user tag of the sender - * @param i1, integer - * @param i2, integer - * @param i3, integer - * @param i4, integer - * @param s1, string/iolist. D's arg6 is NULL if not given by Erlang - * @param s2, string/iolist. D's arg7 is NULL if not given by Erlang - * @param s3, string/iolist. D's arg8 is NULL if not given by Erlang - * @param s4, string/iolist. D's arg9 is NULL if not given by Erlang - */ - probe user_trace__i4s4(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - - /** - * Same args as user_trace__i4s4, but lots of different probes - * to avoid the "one probe to rule them all and in the runtime - * molasses bind them" problem. - * - * (I.e. If you use only a single probe, but you also embed that probe - * in many different places in your code, if that probe fires 100K or - * more times per second, then it *will* hurt when you have to enable - * that probe. However, if you have any different probes, then you - * can ensure that any probe on a hot code path will use separate - * probe(s) than everyone else ... and you can then enable many non- - * hot probes in production without worry about creating too much - * measurement overhead. - */ - probe user_trace__n0(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n2(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n3(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n4(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n5(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n6(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n7(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n8(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n9(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n10(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n11(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n12(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n13(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n14(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n15(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n16(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n17(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n18(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n19(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n20(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n21(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n22(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n23(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n24(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n25(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n26(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n27(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n28(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n29(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n30(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n31(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n32(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n33(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n34(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n35(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n36(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n37(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n38(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n39(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n40(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n41(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n42(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n43(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n44(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n45(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n46(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n47(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n48(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n49(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n50(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n51(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n52(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n53(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n54(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n55(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n56(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n57(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n58(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n59(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n60(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n61(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n62(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n63(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n64(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n65(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n66(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n67(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n68(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n69(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n70(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n71(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n72(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n73(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n74(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n75(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n76(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n77(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n78(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n79(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n80(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n81(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n82(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n83(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n84(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n85(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n86(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n87(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n88(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n89(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n90(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n91(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n92(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n93(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n94(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n95(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n96(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n97(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n98(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n99(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n100(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n101(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n102(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n103(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n104(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n105(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n106(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n107(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n108(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n109(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n110(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n111(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n112(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n113(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n114(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n115(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n116(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n117(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n118(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n119(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n120(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n121(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n122(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n123(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n124(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n125(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n126(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n127(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n128(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n129(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n130(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n131(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n132(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n133(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n134(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n135(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n136(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n137(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n138(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n139(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n140(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n141(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n142(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n143(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n144(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n145(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n146(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n147(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n148(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n149(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n150(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n151(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n152(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n153(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n154(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n155(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n156(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n157(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n158(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n159(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n160(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n161(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n162(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n163(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n164(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n165(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n166(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n167(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n168(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n169(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n170(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n171(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n172(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n173(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n174(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n175(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n176(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n177(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n178(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n179(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n180(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n181(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n182(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n183(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n184(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n185(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n186(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n187(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n188(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n189(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n190(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n191(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n192(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n193(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n194(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n195(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n196(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n197(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n198(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n199(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n200(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n201(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n202(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n203(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n204(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n205(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n206(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n207(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n208(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n209(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n210(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n211(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n212(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n213(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n214(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n215(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n216(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n217(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n218(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n219(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n220(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n221(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n222(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n223(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n224(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n225(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n226(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n227(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n228(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n229(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n230(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n231(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n232(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n233(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n234(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n235(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n236(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n237(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n238(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n239(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n240(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n241(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n242(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n243(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n244(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n245(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n246(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n247(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n248(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n249(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n250(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n251(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n252(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n253(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n254(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n255(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n256(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n257(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n258(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n259(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n260(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n261(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n262(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n263(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n264(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n265(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n266(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n267(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n268(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n269(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n270(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n271(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n272(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n273(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n274(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n275(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n276(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n277(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n278(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n279(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n280(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n281(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n282(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n283(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n284(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n285(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n286(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n287(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n288(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n289(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n290(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n291(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n292(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n293(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n294(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n295(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n296(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n297(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n298(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n299(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n300(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n301(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n302(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n303(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n304(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n305(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n306(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n307(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n308(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n309(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n310(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n311(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n312(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n313(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n314(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n315(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n316(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n317(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n318(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n319(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n320(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n321(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n322(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n323(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n324(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n325(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n326(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n327(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n328(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n329(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n330(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n331(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n332(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n333(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n334(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n335(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n336(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n337(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n338(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n339(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n340(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n341(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n342(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n343(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n344(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n345(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n346(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n347(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n348(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n349(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n350(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n351(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n352(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n353(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n354(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n355(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n356(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n357(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n358(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n359(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n360(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n361(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n362(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n363(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n364(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n365(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n366(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n367(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n368(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n369(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n370(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n371(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n372(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n373(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n374(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n375(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n376(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n377(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n378(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n379(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n380(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n381(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n382(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n383(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n384(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n385(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n386(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n387(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n388(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n389(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n390(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n391(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n392(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n393(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n394(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n395(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n396(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n397(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n398(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n399(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n400(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n401(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n402(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n403(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n404(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n405(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n406(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n407(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n408(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n409(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n410(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n411(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n412(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n413(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n414(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n415(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n416(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n417(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n418(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n419(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n420(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n421(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n422(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n423(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n424(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n425(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n426(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n427(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n428(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n429(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n430(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n431(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n432(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n433(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n434(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n435(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n436(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n437(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n438(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n439(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n440(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n441(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n442(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n443(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n444(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n445(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n446(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n447(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n448(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n449(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n450(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n451(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n452(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n453(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n454(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n455(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n456(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n457(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n458(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n459(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n460(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n461(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n462(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n463(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n464(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n465(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n466(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n467(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n468(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n469(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n470(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n471(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n472(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n473(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n474(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n475(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n476(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n477(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n478(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n479(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n480(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n481(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n482(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n483(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n484(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n485(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n486(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n487(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n488(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n489(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n490(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n491(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n492(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n493(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n494(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n495(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n496(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n497(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n498(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n499(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n500(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n501(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n502(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n503(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n504(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n505(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n506(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n507(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n508(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n509(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n510(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n511(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n512(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n513(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n514(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n515(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n516(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n517(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n518(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n519(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n520(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n521(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n522(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n523(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n524(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n525(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n526(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n527(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n528(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n529(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n530(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n531(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n532(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n533(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n534(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n535(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n536(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n537(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n538(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n539(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n540(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n541(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n542(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n543(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n544(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n545(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n546(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n547(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n548(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n549(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n550(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n551(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n552(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n553(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n554(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n555(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n556(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n557(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n558(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n559(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n560(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n561(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n562(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n563(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n564(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n565(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n566(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n567(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n568(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n569(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n570(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n571(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n572(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n573(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n574(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n575(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n576(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n577(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n578(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n579(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n580(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n581(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n582(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n583(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n584(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n585(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n586(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n587(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n588(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n589(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n590(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n591(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n592(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n593(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n594(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n595(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n596(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n597(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n598(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n599(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n600(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n601(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n602(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n603(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n604(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n605(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n606(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n607(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n608(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n609(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n610(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n611(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n612(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n613(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n614(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n615(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n616(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n617(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n618(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n619(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n620(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n621(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n622(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n623(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n624(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n625(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n626(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n627(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n628(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n629(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n630(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n631(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n632(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n633(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n634(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n635(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n636(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n637(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n638(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n639(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n640(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n641(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n642(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n643(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n644(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n645(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n646(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n647(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n648(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n649(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n650(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n651(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n652(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n653(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n654(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n655(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n656(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n657(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n658(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n659(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n660(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n661(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n662(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n663(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n664(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n665(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n666(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n667(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n668(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n669(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n670(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n671(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n672(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n673(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n674(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n675(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n676(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n677(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n678(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n679(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n680(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n681(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n682(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n683(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n684(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n685(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n686(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n687(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n688(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n689(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n690(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n691(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n692(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n693(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n694(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n695(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n696(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n697(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n698(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n699(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n700(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n701(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n702(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n703(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n704(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n705(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n706(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n707(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n708(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n709(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n710(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n711(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n712(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n713(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n714(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n715(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n716(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n717(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n718(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n719(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n720(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n721(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n722(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n723(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n724(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n725(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n726(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n727(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n728(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n729(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n730(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n731(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n732(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n733(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n734(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n735(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n736(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n737(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n738(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n739(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n740(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n741(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n742(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n743(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n744(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n745(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n746(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n747(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n748(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n749(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n750(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n751(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n752(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n753(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n754(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n755(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n756(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n757(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n758(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n759(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n760(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n761(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n762(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n763(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n764(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n765(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n766(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n767(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n768(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n769(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n770(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n771(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n772(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n773(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n774(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n775(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n776(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n777(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n778(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n779(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n780(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n781(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n782(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n783(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n784(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n785(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n786(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n787(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n788(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n789(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n790(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n791(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n792(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n793(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n794(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n795(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n796(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n797(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n798(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n799(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n800(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n801(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n802(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n803(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n804(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n805(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n806(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n807(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n808(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n809(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n810(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n811(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n812(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n813(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n814(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n815(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n816(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n817(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n818(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n819(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n820(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n821(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n822(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n823(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n824(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n825(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n826(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n827(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n828(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n829(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n830(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n831(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n832(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n833(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n834(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n835(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n836(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n837(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n838(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n839(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n840(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n841(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n842(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n843(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n844(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n845(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n846(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n847(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n848(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n849(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n850(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n851(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n852(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n853(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n854(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n855(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n856(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n857(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n858(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n859(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n860(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n861(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n862(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n863(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n864(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n865(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n866(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n867(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n868(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n869(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n870(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n871(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n872(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n873(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n874(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n875(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n876(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n877(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n878(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n879(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n880(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n881(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n882(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n883(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n884(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n885(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n886(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n887(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n888(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n889(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n890(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n891(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n892(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n893(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n894(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n895(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n896(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n897(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n898(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n899(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n900(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n901(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n902(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n903(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n904(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n905(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n906(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n907(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n908(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n909(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n910(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n911(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n912(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n913(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n914(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n915(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n916(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n917(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n918(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n919(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n920(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n921(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n922(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n923(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n924(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n925(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n926(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n927(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n928(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n929(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n930(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n931(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n932(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n933(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n934(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n935(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n936(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n937(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n938(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n939(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n940(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n941(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n942(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n943(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n944(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n945(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n946(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n947(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n948(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n949(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n950(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n951(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n952(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n953(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n954(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n955(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n956(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n957(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n958(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n959(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n960(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n961(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n962(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n963(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n964(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n965(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n966(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n967(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n968(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n969(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n970(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n971(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n972(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n973(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n974(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n975(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n976(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n977(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n978(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n979(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n980(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n981(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n982(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n983(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n984(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n985(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n986(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n987(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n988(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n989(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n990(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n991(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n992(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n993(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n994(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n995(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n996(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n997(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n998(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n999(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1000(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1001(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1002(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1003(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1004(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1005(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1006(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1007(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1008(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1009(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1010(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1011(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1012(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1013(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1014(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1015(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1016(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1017(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1018(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1019(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1020(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1021(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1022(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); - probe user_trace__n1023(char *proc, char *user_tag, - int i1, int i2, int i3, int i4, - char *s1, char *s2, char *s3, char *s4); }; #pragma D attributes Evolving/Evolving/Common provider erlang provider diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 62a392fe56..eef03afd1c 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -36,6 +36,10 @@ void dtrace_nifenv_str(ErlNifEnv *env, char *process_buf); void get_string_maybe(ErlNifEnv *env, const ERL_NIF_TERM term, char **ptr, char *buf, int bufsiz); +#ifdef HAVE_USE_DTRACE +ERL_NIF_TERM erl_nif_user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM erl_nif_user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +#endif #ifdef VALGRIND # include <valgrind/memcheck.h> @@ -98,1151 +102,25 @@ static ERL_NIF_TERM available(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ static ERL_NIF_TERM user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { #ifdef HAVE_USE_DTRACE - ErlNifBinary message_bin; - DTRACE_CHARBUF(messagebuf, MESSAGE_BUFSIZ + 1); - - if (DTRACE_ENABLED(user_trace_s1)) { - if (!enif_inspect_iolist_as_binary(env, argv[0], &message_bin) || - message_bin.size > MESSAGE_BUFSIZ) { - return atom_badarg; - } - memcpy(messagebuf, (char *) message_bin.data, message_bin.size); - messagebuf[message_bin.size] = '\0'; - DTRACE1(user_trace_s1, messagebuf); - return atom_true; - } else { - return atom_false; - } + return erl_nif_user_trace_s1(env, argc, argv); #else return atom_error; #endif } -void -get_string_maybe(ErlNifEnv *env, - const ERL_NIF_TERM term, char **ptr, char *buf, int bufsiz) -{ - ErlNifBinary str_bin; - - if (!enif_inspect_iolist_as_binary(env, term, &str_bin) || - str_bin.size > bufsiz) { - *ptr = NULL; - } else { - memcpy(buf, (char *) str_bin.data, str_bin.size); - buf[str_bin.size] = '\0'; - *ptr = buf; - } -} - static ERL_NIF_TERM user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { #ifdef HAVE_USE_DTRACE - DTRACE_CHARBUF(procbuf, 32 + 1); - DTRACE_CHARBUF(user_tagbuf, MESSAGE_BUFSIZ + 1); - char *utbuf = NULL; - ErlNifSInt64 i1, i2, i3, i4; - DTRACE_CHARBUF(messagebuf1, MESSAGE_BUFSIZ + 1); - DTRACE_CHARBUF(messagebuf2, MESSAGE_BUFSIZ + 1); - DTRACE_CHARBUF(messagebuf3, MESSAGE_BUFSIZ + 1); - DTRACE_CHARBUF(messagebuf4, MESSAGE_BUFSIZ + 1); - char *mbuf1 = NULL, *mbuf2 = NULL, *mbuf3 = NULL, *mbuf4 = NULL; - - if (DTRACE_ENABLED(user_trace_i4s4)) { - dtrace_nifenv_str(env, procbuf); - get_string_maybe(env, argv[0], &utbuf, user_tagbuf, MESSAGE_BUFSIZ); - if (! enif_get_int64(env, argv[1], &i1)) - i1 = 0; - if (! enif_get_int64(env, argv[2], &i2)) - i2 = 0; - if (! enif_get_int64(env, argv[3], &i3)) - i3 = 0; - if (! enif_get_int64(env, argv[4], &i4)) - i4 = 0; - get_string_maybe(env, argv[5], &mbuf1, messagebuf1, MESSAGE_BUFSIZ); - get_string_maybe(env, argv[6], &mbuf2, messagebuf2, MESSAGE_BUFSIZ); - get_string_maybe(env, argv[7], &mbuf3, messagebuf3, MESSAGE_BUFSIZ); - get_string_maybe(env, argv[8], &mbuf4, messagebuf4, MESSAGE_BUFSIZ); - DTRACE10(user_trace_i4s4, procbuf, utbuf, - i1, i2, i3, i4, mbuf1, mbuf2, mbuf3, mbuf4); - return atom_true; - } else { - return atom_false; - } + return erl_nif_user_trace_i4s4(env, argc, argv); #else return atom_error; #endif } -#define DTRACE10_LABEL(name, label, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ - erlang_##name##label((a0), (a1), (a2), (a3), (a4), (a5), (a6), (a7), (a8), (a9)) -#define N_STATEMENT(the_label) \ - case the_label: \ - if (DTRACE_ENABLED(user_trace_n##the_label)) { \ - dtrace_nifenv_str(env, procbuf); \ - get_string_maybe(env, argv[1], &utbuf, user_tagbuf, MESSAGE_BUFSIZ); \ - if (! enif_get_int64(env, argv[2], &i1)) \ - i1 = 0; \ - if (! enif_get_int64(env, argv[3], &i2)) \ - i2 = 0; \ - if (! enif_get_int64(env, argv[4], &i3)) \ - i3 = 0; \ - if (! enif_get_int64(env, argv[5], &i4)) \ - i4 = 0; \ - get_string_maybe(env, argv[6], &mbuf1, messagebuf1, MESSAGE_BUFSIZ); \ - get_string_maybe(env, argv[7], &mbuf2, messagebuf2, MESSAGE_BUFSIZ); \ - get_string_maybe(env, argv[8], &mbuf3, messagebuf3, MESSAGE_BUFSIZ); \ - get_string_maybe(env, argv[9], &mbuf4, messagebuf4, MESSAGE_BUFSIZ); \ - DTRACE10_LABEL(user_trace_n, the_label, procbuf, utbuf, \ - i1, i2, i3, i4, mbuf1, mbuf2, mbuf3, mbuf4); \ - return atom_true; \ - } else { \ - return atom_false; \ - } \ - break - static ERL_NIF_TERM user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { #ifdef HAVE_USE_DTRACE - DTRACE_CHARBUF(procbuf, 32 + 1); - DTRACE_CHARBUF(user_tagbuf, MESSAGE_BUFSIZ + 1); - char *utbuf = NULL; - ErlNifSInt64 i1, i2, i3, i4; - DTRACE_CHARBUF(messagebuf1, MESSAGE_BUFSIZ + 1); - DTRACE_CHARBUF(messagebuf2, MESSAGE_BUFSIZ + 1); - DTRACE_CHARBUF(messagebuf3, MESSAGE_BUFSIZ + 1); - DTRACE_CHARBUF(messagebuf4, MESSAGE_BUFSIZ + 1); - char *mbuf1 = NULL, *mbuf2 = NULL, *mbuf3 = NULL, *mbuf4 = NULL; - ErlNifSInt64 label = 0; - - if (! enif_get_int64(env, argv[0], &label) || label < 0 || label > 1023) - return atom_badarg; - switch (label) { - N_STATEMENT(0); - N_STATEMENT(1); - N_STATEMENT(2); - N_STATEMENT(3); - N_STATEMENT(4); - N_STATEMENT(5); - N_STATEMENT(6); - N_STATEMENT(7); - N_STATEMENT(8); - N_STATEMENT(9); - N_STATEMENT(10); - N_STATEMENT(11); - N_STATEMENT(12); - N_STATEMENT(13); - N_STATEMENT(14); - N_STATEMENT(15); - N_STATEMENT(16); - N_STATEMENT(17); - N_STATEMENT(18); - N_STATEMENT(19); - N_STATEMENT(20); - N_STATEMENT(21); - N_STATEMENT(22); - N_STATEMENT(23); - N_STATEMENT(24); - N_STATEMENT(25); - N_STATEMENT(26); - N_STATEMENT(27); - N_STATEMENT(28); - N_STATEMENT(29); - N_STATEMENT(30); - N_STATEMENT(31); - N_STATEMENT(32); - N_STATEMENT(33); - N_STATEMENT(34); - N_STATEMENT(35); - N_STATEMENT(36); - N_STATEMENT(37); - N_STATEMENT(38); - N_STATEMENT(39); - N_STATEMENT(40); - N_STATEMENT(41); - N_STATEMENT(42); - N_STATEMENT(43); - N_STATEMENT(44); - N_STATEMENT(45); - N_STATEMENT(46); - N_STATEMENT(47); - N_STATEMENT(48); - N_STATEMENT(49); - N_STATEMENT(50); - N_STATEMENT(51); - N_STATEMENT(52); - N_STATEMENT(53); - N_STATEMENT(54); - N_STATEMENT(55); - N_STATEMENT(56); - N_STATEMENT(57); - N_STATEMENT(58); - N_STATEMENT(59); - N_STATEMENT(60); - N_STATEMENT(61); - N_STATEMENT(62); - N_STATEMENT(63); - N_STATEMENT(64); - N_STATEMENT(65); - N_STATEMENT(66); - N_STATEMENT(67); - N_STATEMENT(68); - N_STATEMENT(69); - N_STATEMENT(70); - N_STATEMENT(71); - N_STATEMENT(72); - N_STATEMENT(73); - N_STATEMENT(74); - N_STATEMENT(75); - N_STATEMENT(76); - N_STATEMENT(77); - N_STATEMENT(78); - N_STATEMENT(79); - N_STATEMENT(80); - N_STATEMENT(81); - N_STATEMENT(82); - N_STATEMENT(83); - N_STATEMENT(84); - N_STATEMENT(85); - N_STATEMENT(86); - N_STATEMENT(87); - N_STATEMENT(88); - N_STATEMENT(89); - N_STATEMENT(90); - N_STATEMENT(91); - N_STATEMENT(92); - N_STATEMENT(93); - N_STATEMENT(94); - N_STATEMENT(95); - N_STATEMENT(96); - N_STATEMENT(97); - N_STATEMENT(98); - N_STATEMENT(99); - N_STATEMENT(100); - N_STATEMENT(101); - N_STATEMENT(102); - N_STATEMENT(103); - N_STATEMENT(104); - N_STATEMENT(105); - N_STATEMENT(106); - N_STATEMENT(107); - N_STATEMENT(108); - N_STATEMENT(109); - N_STATEMENT(110); - N_STATEMENT(111); - N_STATEMENT(112); - N_STATEMENT(113); - N_STATEMENT(114); - N_STATEMENT(115); - N_STATEMENT(116); - N_STATEMENT(117); - N_STATEMENT(118); - N_STATEMENT(119); - N_STATEMENT(120); - N_STATEMENT(121); - N_STATEMENT(122); - N_STATEMENT(123); - N_STATEMENT(124); - N_STATEMENT(125); - N_STATEMENT(126); - N_STATEMENT(127); - N_STATEMENT(128); - N_STATEMENT(129); - N_STATEMENT(130); - N_STATEMENT(131); - N_STATEMENT(132); - N_STATEMENT(133); - N_STATEMENT(134); - N_STATEMENT(135); - N_STATEMENT(136); - N_STATEMENT(137); - N_STATEMENT(138); - N_STATEMENT(139); - N_STATEMENT(140); - N_STATEMENT(141); - N_STATEMENT(142); - N_STATEMENT(143); - N_STATEMENT(144); - N_STATEMENT(145); - N_STATEMENT(146); - N_STATEMENT(147); - N_STATEMENT(148); - N_STATEMENT(149); - N_STATEMENT(150); - N_STATEMENT(151); - N_STATEMENT(152); - N_STATEMENT(153); - N_STATEMENT(154); - N_STATEMENT(155); - N_STATEMENT(156); - N_STATEMENT(157); - N_STATEMENT(158); - N_STATEMENT(159); - N_STATEMENT(160); - N_STATEMENT(161); - N_STATEMENT(162); - N_STATEMENT(163); - N_STATEMENT(164); - N_STATEMENT(165); - N_STATEMENT(166); - N_STATEMENT(167); - N_STATEMENT(168); - N_STATEMENT(169); - N_STATEMENT(170); - N_STATEMENT(171); - N_STATEMENT(172); - N_STATEMENT(173); - N_STATEMENT(174); - N_STATEMENT(175); - N_STATEMENT(176); - N_STATEMENT(177); - N_STATEMENT(178); - N_STATEMENT(179); - N_STATEMENT(180); - N_STATEMENT(181); - N_STATEMENT(182); - N_STATEMENT(183); - N_STATEMENT(184); - N_STATEMENT(185); - N_STATEMENT(186); - N_STATEMENT(187); - N_STATEMENT(188); - N_STATEMENT(189); - N_STATEMENT(190); - N_STATEMENT(191); - N_STATEMENT(192); - N_STATEMENT(193); - N_STATEMENT(194); - N_STATEMENT(195); - N_STATEMENT(196); - N_STATEMENT(197); - N_STATEMENT(198); - N_STATEMENT(199); - N_STATEMENT(200); - N_STATEMENT(201); - N_STATEMENT(202); - N_STATEMENT(203); - N_STATEMENT(204); - N_STATEMENT(205); - N_STATEMENT(206); - N_STATEMENT(207); - N_STATEMENT(208); - N_STATEMENT(209); - N_STATEMENT(210); - N_STATEMENT(211); - N_STATEMENT(212); - N_STATEMENT(213); - N_STATEMENT(214); - N_STATEMENT(215); - N_STATEMENT(216); - N_STATEMENT(217); - N_STATEMENT(218); - N_STATEMENT(219); - N_STATEMENT(220); - N_STATEMENT(221); - N_STATEMENT(222); - N_STATEMENT(223); - N_STATEMENT(224); - N_STATEMENT(225); - N_STATEMENT(226); - N_STATEMENT(227); - N_STATEMENT(228); - N_STATEMENT(229); - N_STATEMENT(230); - N_STATEMENT(231); - N_STATEMENT(232); - N_STATEMENT(233); - N_STATEMENT(234); - N_STATEMENT(235); - N_STATEMENT(236); - N_STATEMENT(237); - N_STATEMENT(238); - N_STATEMENT(239); - N_STATEMENT(240); - N_STATEMENT(241); - N_STATEMENT(242); - N_STATEMENT(243); - N_STATEMENT(244); - N_STATEMENT(245); - N_STATEMENT(246); - N_STATEMENT(247); - N_STATEMENT(248); - N_STATEMENT(249); - N_STATEMENT(250); - N_STATEMENT(251); - N_STATEMENT(252); - N_STATEMENT(253); - N_STATEMENT(254); - N_STATEMENT(255); - N_STATEMENT(256); - N_STATEMENT(257); - N_STATEMENT(258); - N_STATEMENT(259); - N_STATEMENT(260); - N_STATEMENT(261); - N_STATEMENT(262); - N_STATEMENT(263); - N_STATEMENT(264); - N_STATEMENT(265); - N_STATEMENT(266); - N_STATEMENT(267); - N_STATEMENT(268); - N_STATEMENT(269); - N_STATEMENT(270); - N_STATEMENT(271); - N_STATEMENT(272); - N_STATEMENT(273); - N_STATEMENT(274); - N_STATEMENT(275); - N_STATEMENT(276); - N_STATEMENT(277); - N_STATEMENT(278); - N_STATEMENT(279); - N_STATEMENT(280); - N_STATEMENT(281); - N_STATEMENT(282); - N_STATEMENT(283); - N_STATEMENT(284); - N_STATEMENT(285); - N_STATEMENT(286); - N_STATEMENT(287); - N_STATEMENT(288); - N_STATEMENT(289); - N_STATEMENT(290); - N_STATEMENT(291); - N_STATEMENT(292); - N_STATEMENT(293); - N_STATEMENT(294); - N_STATEMENT(295); - N_STATEMENT(296); - N_STATEMENT(297); - N_STATEMENT(298); - N_STATEMENT(299); - N_STATEMENT(300); - N_STATEMENT(301); - N_STATEMENT(302); - N_STATEMENT(303); - N_STATEMENT(304); - N_STATEMENT(305); - N_STATEMENT(306); - N_STATEMENT(307); - N_STATEMENT(308); - N_STATEMENT(309); - N_STATEMENT(310); - N_STATEMENT(311); - N_STATEMENT(312); - N_STATEMENT(313); - N_STATEMENT(314); - N_STATEMENT(315); - N_STATEMENT(316); - N_STATEMENT(317); - N_STATEMENT(318); - N_STATEMENT(319); - N_STATEMENT(320); - N_STATEMENT(321); - N_STATEMENT(322); - N_STATEMENT(323); - N_STATEMENT(324); - N_STATEMENT(325); - N_STATEMENT(326); - N_STATEMENT(327); - N_STATEMENT(328); - N_STATEMENT(329); - N_STATEMENT(330); - N_STATEMENT(331); - N_STATEMENT(332); - N_STATEMENT(333); - N_STATEMENT(334); - N_STATEMENT(335); - N_STATEMENT(336); - N_STATEMENT(337); - N_STATEMENT(338); - N_STATEMENT(339); - N_STATEMENT(340); - N_STATEMENT(341); - N_STATEMENT(342); - N_STATEMENT(343); - N_STATEMENT(344); - N_STATEMENT(345); - N_STATEMENT(346); - N_STATEMENT(347); - N_STATEMENT(348); - N_STATEMENT(349); - N_STATEMENT(350); - N_STATEMENT(351); - N_STATEMENT(352); - N_STATEMENT(353); - N_STATEMENT(354); - N_STATEMENT(355); - N_STATEMENT(356); - N_STATEMENT(357); - N_STATEMENT(358); - N_STATEMENT(359); - N_STATEMENT(360); - N_STATEMENT(361); - N_STATEMENT(362); - N_STATEMENT(363); - N_STATEMENT(364); - N_STATEMENT(365); - N_STATEMENT(366); - N_STATEMENT(367); - N_STATEMENT(368); - N_STATEMENT(369); - N_STATEMENT(370); - N_STATEMENT(371); - N_STATEMENT(372); - N_STATEMENT(373); - N_STATEMENT(374); - N_STATEMENT(375); - N_STATEMENT(376); - N_STATEMENT(377); - N_STATEMENT(378); - N_STATEMENT(379); - N_STATEMENT(380); - N_STATEMENT(381); - N_STATEMENT(382); - N_STATEMENT(383); - N_STATEMENT(384); - N_STATEMENT(385); - N_STATEMENT(386); - N_STATEMENT(387); - N_STATEMENT(388); - N_STATEMENT(389); - N_STATEMENT(390); - N_STATEMENT(391); - N_STATEMENT(392); - N_STATEMENT(393); - N_STATEMENT(394); - N_STATEMENT(395); - N_STATEMENT(396); - N_STATEMENT(397); - N_STATEMENT(398); - N_STATEMENT(399); - N_STATEMENT(400); - N_STATEMENT(401); - N_STATEMENT(402); - N_STATEMENT(403); - N_STATEMENT(404); - N_STATEMENT(405); - N_STATEMENT(406); - N_STATEMENT(407); - N_STATEMENT(408); - N_STATEMENT(409); - N_STATEMENT(410); - N_STATEMENT(411); - N_STATEMENT(412); - N_STATEMENT(413); - N_STATEMENT(414); - N_STATEMENT(415); - N_STATEMENT(416); - N_STATEMENT(417); - N_STATEMENT(418); - N_STATEMENT(419); - N_STATEMENT(420); - N_STATEMENT(421); - N_STATEMENT(422); - N_STATEMENT(423); - N_STATEMENT(424); - N_STATEMENT(425); - N_STATEMENT(426); - N_STATEMENT(427); - N_STATEMENT(428); - N_STATEMENT(429); - N_STATEMENT(430); - N_STATEMENT(431); - N_STATEMENT(432); - N_STATEMENT(433); - N_STATEMENT(434); - N_STATEMENT(435); - N_STATEMENT(436); - N_STATEMENT(437); - N_STATEMENT(438); - N_STATEMENT(439); - N_STATEMENT(440); - N_STATEMENT(441); - N_STATEMENT(442); - N_STATEMENT(443); - N_STATEMENT(444); - N_STATEMENT(445); - N_STATEMENT(446); - N_STATEMENT(447); - N_STATEMENT(448); - N_STATEMENT(449); - N_STATEMENT(450); - N_STATEMENT(451); - N_STATEMENT(452); - N_STATEMENT(453); - N_STATEMENT(454); - N_STATEMENT(455); - N_STATEMENT(456); - N_STATEMENT(457); - N_STATEMENT(458); - N_STATEMENT(459); - N_STATEMENT(460); - N_STATEMENT(461); - N_STATEMENT(462); - N_STATEMENT(463); - N_STATEMENT(464); - N_STATEMENT(465); - N_STATEMENT(466); - N_STATEMENT(467); - N_STATEMENT(468); - N_STATEMENT(469); - N_STATEMENT(470); - N_STATEMENT(471); - N_STATEMENT(472); - N_STATEMENT(473); - N_STATEMENT(474); - N_STATEMENT(475); - N_STATEMENT(476); - N_STATEMENT(477); - N_STATEMENT(478); - N_STATEMENT(479); - N_STATEMENT(480); - N_STATEMENT(481); - N_STATEMENT(482); - N_STATEMENT(483); - N_STATEMENT(484); - N_STATEMENT(485); - N_STATEMENT(486); - N_STATEMENT(487); - N_STATEMENT(488); - N_STATEMENT(489); - N_STATEMENT(490); - N_STATEMENT(491); - N_STATEMENT(492); - N_STATEMENT(493); - N_STATEMENT(494); - N_STATEMENT(495); - N_STATEMENT(496); - N_STATEMENT(497); - N_STATEMENT(498); - N_STATEMENT(499); - N_STATEMENT(500); - N_STATEMENT(501); - N_STATEMENT(502); - N_STATEMENT(503); - N_STATEMENT(504); - N_STATEMENT(505); - N_STATEMENT(506); - N_STATEMENT(507); - N_STATEMENT(508); - N_STATEMENT(509); - N_STATEMENT(510); - N_STATEMENT(511); - N_STATEMENT(512); - N_STATEMENT(513); - N_STATEMENT(514); - N_STATEMENT(515); - N_STATEMENT(516); - N_STATEMENT(517); - N_STATEMENT(518); - N_STATEMENT(519); - N_STATEMENT(520); - N_STATEMENT(521); - N_STATEMENT(522); - N_STATEMENT(523); - N_STATEMENT(524); - N_STATEMENT(525); - N_STATEMENT(526); - N_STATEMENT(527); - N_STATEMENT(528); - N_STATEMENT(529); - N_STATEMENT(530); - N_STATEMENT(531); - N_STATEMENT(532); - N_STATEMENT(533); - N_STATEMENT(534); - N_STATEMENT(535); - N_STATEMENT(536); - N_STATEMENT(537); - N_STATEMENT(538); - N_STATEMENT(539); - N_STATEMENT(540); - N_STATEMENT(541); - N_STATEMENT(542); - N_STATEMENT(543); - N_STATEMENT(544); - N_STATEMENT(545); - N_STATEMENT(546); - N_STATEMENT(547); - N_STATEMENT(548); - N_STATEMENT(549); - N_STATEMENT(550); - N_STATEMENT(551); - N_STATEMENT(552); - N_STATEMENT(553); - N_STATEMENT(554); - N_STATEMENT(555); - N_STATEMENT(556); - N_STATEMENT(557); - N_STATEMENT(558); - N_STATEMENT(559); - N_STATEMENT(560); - N_STATEMENT(561); - N_STATEMENT(562); - N_STATEMENT(563); - N_STATEMENT(564); - N_STATEMENT(565); - N_STATEMENT(566); - N_STATEMENT(567); - N_STATEMENT(568); - N_STATEMENT(569); - N_STATEMENT(570); - N_STATEMENT(571); - N_STATEMENT(572); - N_STATEMENT(573); - N_STATEMENT(574); - N_STATEMENT(575); - N_STATEMENT(576); - N_STATEMENT(577); - N_STATEMENT(578); - N_STATEMENT(579); - N_STATEMENT(580); - N_STATEMENT(581); - N_STATEMENT(582); - N_STATEMENT(583); - N_STATEMENT(584); - N_STATEMENT(585); - N_STATEMENT(586); - N_STATEMENT(587); - N_STATEMENT(588); - N_STATEMENT(589); - N_STATEMENT(590); - N_STATEMENT(591); - N_STATEMENT(592); - N_STATEMENT(593); - N_STATEMENT(594); - N_STATEMENT(595); - N_STATEMENT(596); - N_STATEMENT(597); - N_STATEMENT(598); - N_STATEMENT(599); - N_STATEMENT(600); - N_STATEMENT(601); - N_STATEMENT(602); - N_STATEMENT(603); - N_STATEMENT(604); - N_STATEMENT(605); - N_STATEMENT(606); - N_STATEMENT(607); - N_STATEMENT(608); - N_STATEMENT(609); - N_STATEMENT(610); - N_STATEMENT(611); - N_STATEMENT(612); - N_STATEMENT(613); - N_STATEMENT(614); - N_STATEMENT(615); - N_STATEMENT(616); - N_STATEMENT(617); - N_STATEMENT(618); - N_STATEMENT(619); - N_STATEMENT(620); - N_STATEMENT(621); - N_STATEMENT(622); - N_STATEMENT(623); - N_STATEMENT(624); - N_STATEMENT(625); - N_STATEMENT(626); - N_STATEMENT(627); - N_STATEMENT(628); - N_STATEMENT(629); - N_STATEMENT(630); - N_STATEMENT(631); - N_STATEMENT(632); - N_STATEMENT(633); - N_STATEMENT(634); - N_STATEMENT(635); - N_STATEMENT(636); - N_STATEMENT(637); - N_STATEMENT(638); - N_STATEMENT(639); - N_STATEMENT(640); - N_STATEMENT(641); - N_STATEMENT(642); - N_STATEMENT(643); - N_STATEMENT(644); - N_STATEMENT(645); - N_STATEMENT(646); - N_STATEMENT(647); - N_STATEMENT(648); - N_STATEMENT(649); - N_STATEMENT(650); - N_STATEMENT(651); - N_STATEMENT(652); - N_STATEMENT(653); - N_STATEMENT(654); - N_STATEMENT(655); - N_STATEMENT(656); - N_STATEMENT(657); - N_STATEMENT(658); - N_STATEMENT(659); - N_STATEMENT(660); - N_STATEMENT(661); - N_STATEMENT(662); - N_STATEMENT(663); - N_STATEMENT(664); - N_STATEMENT(665); - N_STATEMENT(666); - N_STATEMENT(667); - N_STATEMENT(668); - N_STATEMENT(669); - N_STATEMENT(670); - N_STATEMENT(671); - N_STATEMENT(672); - N_STATEMENT(673); - N_STATEMENT(674); - N_STATEMENT(675); - N_STATEMENT(676); - N_STATEMENT(677); - N_STATEMENT(678); - N_STATEMENT(679); - N_STATEMENT(680); - N_STATEMENT(681); - N_STATEMENT(682); - N_STATEMENT(683); - N_STATEMENT(684); - N_STATEMENT(685); - N_STATEMENT(686); - N_STATEMENT(687); - N_STATEMENT(688); - N_STATEMENT(689); - N_STATEMENT(690); - N_STATEMENT(691); - N_STATEMENT(692); - N_STATEMENT(693); - N_STATEMENT(694); - N_STATEMENT(695); - N_STATEMENT(696); - N_STATEMENT(697); - N_STATEMENT(698); - N_STATEMENT(699); - N_STATEMENT(700); - N_STATEMENT(701); - N_STATEMENT(702); - N_STATEMENT(703); - N_STATEMENT(704); - N_STATEMENT(705); - N_STATEMENT(706); - N_STATEMENT(707); - N_STATEMENT(708); - N_STATEMENT(709); - N_STATEMENT(710); - N_STATEMENT(711); - N_STATEMENT(712); - N_STATEMENT(713); - N_STATEMENT(714); - N_STATEMENT(715); - N_STATEMENT(716); - N_STATEMENT(717); - N_STATEMENT(718); - N_STATEMENT(719); - N_STATEMENT(720); - N_STATEMENT(721); - N_STATEMENT(722); - N_STATEMENT(723); - N_STATEMENT(724); - N_STATEMENT(725); - N_STATEMENT(726); - N_STATEMENT(727); - N_STATEMENT(728); - N_STATEMENT(729); - N_STATEMENT(730); - N_STATEMENT(731); - N_STATEMENT(732); - N_STATEMENT(733); - N_STATEMENT(734); - N_STATEMENT(735); - N_STATEMENT(736); - N_STATEMENT(737); - N_STATEMENT(738); - N_STATEMENT(739); - N_STATEMENT(740); - N_STATEMENT(741); - N_STATEMENT(742); - N_STATEMENT(743); - N_STATEMENT(744); - N_STATEMENT(745); - N_STATEMENT(746); - N_STATEMENT(747); - N_STATEMENT(748); - N_STATEMENT(749); - N_STATEMENT(750); - N_STATEMENT(751); - N_STATEMENT(752); - N_STATEMENT(753); - N_STATEMENT(754); - N_STATEMENT(755); - N_STATEMENT(756); - N_STATEMENT(757); - N_STATEMENT(758); - N_STATEMENT(759); - N_STATEMENT(760); - N_STATEMENT(761); - N_STATEMENT(762); - N_STATEMENT(763); - N_STATEMENT(764); - N_STATEMENT(765); - N_STATEMENT(766); - N_STATEMENT(767); - N_STATEMENT(768); - N_STATEMENT(769); - N_STATEMENT(770); - N_STATEMENT(771); - N_STATEMENT(772); - N_STATEMENT(773); - N_STATEMENT(774); - N_STATEMENT(775); - N_STATEMENT(776); - N_STATEMENT(777); - N_STATEMENT(778); - N_STATEMENT(779); - N_STATEMENT(780); - N_STATEMENT(781); - N_STATEMENT(782); - N_STATEMENT(783); - N_STATEMENT(784); - N_STATEMENT(785); - N_STATEMENT(786); - N_STATEMENT(787); - N_STATEMENT(788); - N_STATEMENT(789); - N_STATEMENT(790); - N_STATEMENT(791); - N_STATEMENT(792); - N_STATEMENT(793); - N_STATEMENT(794); - N_STATEMENT(795); - N_STATEMENT(796); - N_STATEMENT(797); - N_STATEMENT(798); - N_STATEMENT(799); - N_STATEMENT(800); - N_STATEMENT(801); - N_STATEMENT(802); - N_STATEMENT(803); - N_STATEMENT(804); - N_STATEMENT(805); - N_STATEMENT(806); - N_STATEMENT(807); - N_STATEMENT(808); - N_STATEMENT(809); - N_STATEMENT(810); - N_STATEMENT(811); - N_STATEMENT(812); - N_STATEMENT(813); - N_STATEMENT(814); - N_STATEMENT(815); - N_STATEMENT(816); - N_STATEMENT(817); - N_STATEMENT(818); - N_STATEMENT(819); - N_STATEMENT(820); - N_STATEMENT(821); - N_STATEMENT(822); - N_STATEMENT(823); - N_STATEMENT(824); - N_STATEMENT(825); - N_STATEMENT(826); - N_STATEMENT(827); - N_STATEMENT(828); - N_STATEMENT(829); - N_STATEMENT(830); - N_STATEMENT(831); - N_STATEMENT(832); - N_STATEMENT(833); - N_STATEMENT(834); - N_STATEMENT(835); - N_STATEMENT(836); - N_STATEMENT(837); - N_STATEMENT(838); - N_STATEMENT(839); - N_STATEMENT(840); - N_STATEMENT(841); - N_STATEMENT(842); - N_STATEMENT(843); - N_STATEMENT(844); - N_STATEMENT(845); - N_STATEMENT(846); - N_STATEMENT(847); - N_STATEMENT(848); - N_STATEMENT(849); - N_STATEMENT(850); - N_STATEMENT(851); - N_STATEMENT(852); - N_STATEMENT(853); - N_STATEMENT(854); - N_STATEMENT(855); - N_STATEMENT(856); - N_STATEMENT(857); - N_STATEMENT(858); - N_STATEMENT(859); - N_STATEMENT(860); - N_STATEMENT(861); - N_STATEMENT(862); - N_STATEMENT(863); - N_STATEMENT(864); - N_STATEMENT(865); - N_STATEMENT(866); - N_STATEMENT(867); - N_STATEMENT(868); - N_STATEMENT(869); - N_STATEMENT(870); - N_STATEMENT(871); - N_STATEMENT(872); - N_STATEMENT(873); - N_STATEMENT(874); - N_STATEMENT(875); - N_STATEMENT(876); - N_STATEMENT(877); - N_STATEMENT(878); - N_STATEMENT(879); - N_STATEMENT(880); - N_STATEMENT(881); - N_STATEMENT(882); - N_STATEMENT(883); - N_STATEMENT(884); - N_STATEMENT(885); - N_STATEMENT(886); - N_STATEMENT(887); - N_STATEMENT(888); - N_STATEMENT(889); - N_STATEMENT(890); - N_STATEMENT(891); - N_STATEMENT(892); - N_STATEMENT(893); - N_STATEMENT(894); - N_STATEMENT(895); - N_STATEMENT(896); - N_STATEMENT(897); - N_STATEMENT(898); - N_STATEMENT(899); - N_STATEMENT(900); - N_STATEMENT(901); - N_STATEMENT(902); - N_STATEMENT(903); - N_STATEMENT(904); - N_STATEMENT(905); - N_STATEMENT(906); - N_STATEMENT(907); - N_STATEMENT(908); - N_STATEMENT(909); - N_STATEMENT(910); - N_STATEMENT(911); - N_STATEMENT(912); - N_STATEMENT(913); - N_STATEMENT(914); - N_STATEMENT(915); - N_STATEMENT(916); - N_STATEMENT(917); - N_STATEMENT(918); - N_STATEMENT(919); - N_STATEMENT(920); - N_STATEMENT(921); - N_STATEMENT(922); - N_STATEMENT(923); - N_STATEMENT(924); - N_STATEMENT(925); - N_STATEMENT(926); - N_STATEMENT(927); - N_STATEMENT(928); - N_STATEMENT(929); - N_STATEMENT(930); - N_STATEMENT(931); - N_STATEMENT(932); - N_STATEMENT(933); - N_STATEMENT(934); - N_STATEMENT(935); - N_STATEMENT(936); - N_STATEMENT(937); - N_STATEMENT(938); - N_STATEMENT(939); - N_STATEMENT(940); - N_STATEMENT(941); - N_STATEMENT(942); - N_STATEMENT(943); - N_STATEMENT(944); - N_STATEMENT(945); - N_STATEMENT(946); - N_STATEMENT(947); - N_STATEMENT(948); - N_STATEMENT(949); - N_STATEMENT(950); - N_STATEMENT(951); - N_STATEMENT(952); - N_STATEMENT(953); - N_STATEMENT(954); - N_STATEMENT(955); - N_STATEMENT(956); - N_STATEMENT(957); - N_STATEMENT(958); - N_STATEMENT(959); - N_STATEMENT(960); - N_STATEMENT(961); - N_STATEMENT(962); - N_STATEMENT(963); - N_STATEMENT(964); - N_STATEMENT(965); - N_STATEMENT(966); - N_STATEMENT(967); - N_STATEMENT(968); - N_STATEMENT(969); - N_STATEMENT(970); - N_STATEMENT(971); - N_STATEMENT(972); - N_STATEMENT(973); - N_STATEMENT(974); - N_STATEMENT(975); - N_STATEMENT(976); - N_STATEMENT(977); - N_STATEMENT(978); - N_STATEMENT(979); - N_STATEMENT(980); - N_STATEMENT(981); - N_STATEMENT(982); - N_STATEMENT(983); - N_STATEMENT(984); - N_STATEMENT(985); - N_STATEMENT(986); - N_STATEMENT(987); - N_STATEMENT(988); - N_STATEMENT(989); - N_STATEMENT(990); - N_STATEMENT(991); - N_STATEMENT(992); - N_STATEMENT(993); - N_STATEMENT(994); - N_STATEMENT(995); - N_STATEMENT(996); - N_STATEMENT(997); - N_STATEMENT(998); - N_STATEMENT(999); - N_STATEMENT(1000); - N_STATEMENT(1001); - N_STATEMENT(1002); - N_STATEMENT(1003); - N_STATEMENT(1004); - N_STATEMENT(1005); - N_STATEMENT(1006); - N_STATEMENT(1007); - N_STATEMENT(1008); - N_STATEMENT(1009); - N_STATEMENT(1010); - N_STATEMENT(1011); - N_STATEMENT(1012); - N_STATEMENT(1013); - N_STATEMENT(1014); - N_STATEMENT(1015); - N_STATEMENT(1016); - N_STATEMENT(1017); - N_STATEMENT(1018); - N_STATEMENT(1019); - N_STATEMENT(1020); - N_STATEMENT(1021); - N_STATEMENT(1022); - N_STATEMENT(1023); - } - return atom_error; /* NOTREACHED, shut up the compiler */ + return erl_nif_user_trace_n(env, argc, argv); #else return atom_error; #endif diff --git a/lib/runtime_tools/examples/user-probe-n.d b/lib/runtime_tools/examples/user-probe-n.d new file mode 100644 index 0000000000..06a3e5c9b9 --- /dev/null +++ b/lib/runtime_tools/examples/user-probe-n.d @@ -0,0 +1,44 @@ +/* example usage: dtrace -q -s /path/to/user-probe.d */ +/* + * %CopyrightBegin% + * + * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +erlang*:::user_trace-n0 +{ + printf("probe n0: %s %s %d %d %d %d '%s' '%s' '%s' '%s'\n", + copyinstr(arg0), + arg1 == NULL ? "" : copyinstr(arg1), + arg2, arg3, arg4, arg5, + arg6 == NULL ? "" : copyinstr(arg6), + arg7 == NULL ? "" : copyinstr(arg7), + arg8 == NULL ? "" : copyinstr(arg8), + arg9 == NULL ? "" : copyinstr(arg9)); +} + +erlang*:::user_trace-n1 +{ + printf("probe n1: %s %s %d %d %d %d '%s' '%s' '%s' '%s'\n", + copyinstr(arg0), + arg1 == NULL ? "" : copyinstr(arg1), + arg2, arg3, arg4, arg5, + arg6 == NULL ? "" : copyinstr(arg6), + arg7 == NULL ? "" : copyinstr(arg7), + arg8 == NULL ? "" : copyinstr(arg8), + arg9 == NULL ? "" : copyinstr(arg9)); +} + diff --git a/lib/runtime_tools/examples/user-probe-n.systemtap b/lib/runtime_tools/examples/user-probe-n.systemtap new file mode 100644 index 0000000000..6aa415bb67 --- /dev/null +++ b/lib/runtime_tools/examples/user-probe-n.systemtap @@ -0,0 +1,53 @@ +/* + * %CopyrightBegin% + * + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +/* + * Note: This file assumes that you're using the non-SMP-enabled Erlang + * virtual machine, "beam". The SMP-enabled VM is called "beam.smp". + * Note that other variations of the virtual machine also have + * different names, e.g. the debug build of the SMP-enabled VM + * is "beam.debug.smp". + * + * To use a different virtual machine, replace each instance of + * "beam" with "beam.smp" or the VM name appropriate to your + * environment. + */ + +probe process("beam").mark("user_trace-n0") +{ + printf("probe n0: %s %s %d %d %d %d '%s' '%s' '%s' '%s'\n", + user_string($arg1), + $arg2 == NULL ? "" : user_string($arg2), + $arg3, $arg4, $arg5, $arg6, + $arg7 == NULL ? "" : user_string($arg7), + $arg8 == NULL ? "" : user_string($arg8), + $arg9 == NULL ? "" : user_string($arg9), + $arg9 == NULL ? "" : user_string($arg9)); +} + +probe process("beam").mark("user_trace-n1") +{ + printf("probe n1: %s %s %d %d %d %d '%s' '%s' '%s' '%s'\n", + user_string($arg1), + $arg2 == NULL ? "" : user_string($arg2), + $arg3, $arg4, $arg5, $arg6, + $arg7 == NULL ? "" : user_string($arg7), + $arg8 == NULL ? "" : user_string($arg8), + $arg9 == NULL ? "" : user_string($arg9), + $arg9 == NULL ? "" : user_string($arg9)); +} diff --git a/lib/runtime_tools/examples/user-probe.systemtap b/lib/runtime_tools/examples/user-probe.systemtap index b41d7483ad..0482235324 100644 --- a/lib/runtime_tools/examples/user-probe.systemtap +++ b/lib/runtime_tools/examples/user-probe.systemtap @@ -28,12 +28,12 @@ * environment. */ -probe process("dyntrace.so").mark("user_trace-s1") +probe process("beam").mark("user_trace-s1") { printf("%s\n", user_string($arg1)); } -probe process("dyntrace.so").mark("user_trace-i4s4") +probe process("beam").mark("user_trace-i4s4") { printf("%s %s %d %d %d %d '%s' '%s' '%s' '%s'\n", user_string($arg1), diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 2d045faa0f..442837d57d 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -34,6 +34,98 @@ <section> + <title>SNMP Development Toolkit 4.22.1</title> + <p>Version 4.22.1 supports code replacement in runtime from/to + version 4.22, 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and + 4.21. </p> + + <section> + <title>Improvements and new features</title> +<!-- + <p>-</p> +--> + + <list type="bulleted"> + <item> + <p>[agent] Sematic fixes to SNMP-USER-BASED-SM-MIB. + The semantics allow the <c>usmUserAuthKeyChange</c> and + <c>usmUserPrivKeyChange</c> objects to be written to in the + same set requests that also creates and clones the user. + This was not possible beforehand, causing test tools checking + semantic SNMPv3 behaviour to fail on a lot of test cases. </p> + <p>Furthermore, once the user has been cloned by writing to an + instance of <c>usmUserCloneFrom</c>, further set-operations to + the same object will not return an error, but be no-ops. + Especially, it must be avoided to copy security parameters + again (possibly even from a different user). </p> + <p>Stefan Zegenhagen</p> + <p>Own Id: OTP-10166</p> + </item> + + <item> + <p>[agent] Errors in <c>vacmAccessTable</c> RowStatus handling. + There are problems with the handling of vacmAccessTableStatus + that cause some SNMP test suites to report errors. + Most notably, erroneous set operations frequently cause "genErr" + errors to be returned. These "genErr" errors are usually caused + by badmatch exceptions coming from + <c>{ok, Row} = snmpa_vacm:get_row(RowIndex)</c> + if the row does not exist. </p> + <p>The semantics of the RowStatus handling in that table has + been adjusted to be compliant with the RowStatus + textual description of SNPMv2-TC MIB. </p> + <p>Stefan Zegenhagen</p> + <p>Own Id: OTP-10164</p> + </item> + </list> + + </section> + + <section> + <title>Fixed Bugs and Malfunctions</title> +<!-- + <p>-</p> +--> + + <list type="bulleted"> + <item> + <p>[agent] Fix walk over vacmAccessTable. + Fix the get_next implementation of vacmAccessTable to + return all table entries. </p> + <p>The get_next implementation of vacmAccessTable did not return + all available table data. Instead, it only returned the first + column for each row, and all columns for the last row available. </p> + <p>Stefan Zegenhagen</p> + <p>Own Id: OTP-10165</p> + </item> + + <item> + <p>[manager] + <seealso marker="snmpm#log_to_io">snmpm:log_to_io/6</seealso> + did not use the LogName argument. </p> + <p>Own Id: OTP-10066</p> + </item> + + <item> + <p>Incorrect TimeTicks decode. Also bad handling of + invalid encode (value outside of value range) for both + <c>TimeTicks</c> and <c>Unsigned32</c>. </p> + <p>Own Id: OTP-10132</p> + </item> + + </list> + + </section> + + <section> + <title>Incompatibilities</title> + <p>-</p> + </section> + + </section> <!-- 4.22.1 --> + + + <section> <title>SNMP Development Toolkit 4.22</title> <p>Version 4.22 supports code replacement in runtime from/to version 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21. </p> diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml index 340f2f1fa7..eec53162a1 100644 --- a/lib/snmp/doc/src/snmp_config.xml +++ b/lib/snmp/doc/src/snmp_config.xml @@ -963,7 +963,8 @@ Manager snmp config: 7b. User name? hobbes 7c. Security name? [hobbes] 7d. Authentication protocol (no/sha/md5)? [no] sha -7e Authentication [sha] key (length 0 or 20)? [""] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] +7e Authentication [sha] key (length 0 or 20)? [""] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \ + 17,18,19,20] 7d. Priv protocol (no/des/aes)? [no] des 7f Priv [des] key (length 0 or 16)? [""] 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 7. Configure an usm user handled by this manager (y/n)? [y] n diff --git a/lib/snmp/doc/src/snmpa_network_interface_filter.xml b/lib/snmp/doc/src/snmpa_network_interface_filter.xml index 10419517dd..84953c5270 100644 --- a/lib/snmp/doc/src/snmpa_network_interface_filter.xml +++ b/lib/snmp/doc/src/snmpa_network_interface_filter.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> @@ -84,7 +84,9 @@ <title>DATA TYPES</title> <code type="none"> port() = integer() > 0 -pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | 'set-request' | trap | 'get-bulk-request' | 'inform-request' | report +pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | + 'set-request' | trap | 'get-bulk-request' | 'inform-request' | + report </code> <marker id="accept_recv"></marker> </section> diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml index 9bbb6cdbdb..8ab3be8e18 100644 --- a/lib/snmp/doc/src/snmpm.xml +++ b/lib/snmp/doc/src/snmpm.xml @@ -173,16 +173,16 @@ sec_level() = noAuthNoPriv | authNoPriv | authPriv </type> <desc> <p>Register the manager entity (=user) responsible for specific - agent(s). </p> + agent(s). </p> <p><c>Module</c> is the callback module (snmpm_user behaviour) which - will be called whenever something happens (detected - agent, incoming reply or incoming trap/notification). - Note that this could have already been done as a - consequence of the node config. (see users.conf).</p> + will be called whenever something happens (detected + agent, incoming reply or incoming trap/notification). + Note that this could have already been done as a + consequence of the node config. (see users.conf).</p> - <p>The argument <c>DefaultAgentConfig</c> is used as default values when - this user register agents.</p> + <p>The argument <c>DefaultAgentConfig</c> is used as default + values when this user register agents.</p> <p>The type of <c>Val</c> depends on <c>Item</c>: </p> <code type="none"><![CDATA[ diff --git a/lib/snmp/doc/src/snmpm_network_interface_filter.xml b/lib/snmp/doc/src/snmpm_network_interface_filter.xml index 5f80cec94e..4dc133dd71 100644 --- a/lib/snmp/doc/src/snmpm_network_interface_filter.xml +++ b/lib/snmp/doc/src/snmpm_network_interface_filter.xml @@ -82,7 +82,9 @@ <title>DATA TYPES</title> <code type="none"> port() = integer() > 0 -pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | 'set-request' | trap | 'get-bulk-request' | 'inform-request' | report | trappdu +pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | + 'set-request' | trap | 'get-bulk-request' | 'inform-request' | + report | trappdu </code> <marker id="accept_recv"></marker> </section> diff --git a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl index 2e801622e7..3c4ba1af66 100644 --- a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl +++ b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl @@ -54,6 +54,7 @@ %% Columns not accessible via SNMP -define(usmUserAuthKey, 14). -define(usmUserPrivKey, 15). +-define(is_cloning, 16). %%%----------------------------------------------------------------- @@ -564,7 +565,9 @@ usmUserTable(set, RowIndex, Cols0) -> {ok, Cols} -> ?vtrace("usmUserTable(set) -> verified" "~n Cols: ~p", [Cols]), - NCols = pre_set(RowIndex, Cols), + % check whether we're cloning. if so, get cloned params and add a few + % defaults that might be needed. + NCols = pre_set(RowIndex, validate_clone_from(RowIndex, Cols)), ?vtrace("usmUserTable(set) -> pre-set: " "~n NCols: ~p", [NCols]), %% NOTE: The NCols parameter is sent to snmp_generic, but not to @@ -730,30 +733,40 @@ validate_is_set_ok(Error, _RowIndex, _Cols) -> Error. do_validate_is_set_ok(RowIndex, Cols) -> - validate_clone_from(RowIndex, Cols), - validate_auth_protocol(RowIndex, Cols), - validate_auth_key_change(RowIndex, Cols), - validate_own_auth_key_change(RowIndex, Cols), - validate_priv_protocol(RowIndex, Cols), - validate_priv_key_change(RowIndex, Cols), - validate_own_priv_key_change(RowIndex, Cols), + NCols = validate_clone_from(RowIndex, Cols), + validate_auth_protocol(RowIndex, NCols), + validate_auth_key_change(RowIndex, NCols), + validate_own_auth_key_change(RowIndex, NCols), + validate_priv_protocol(RowIndex, NCols), + validate_priv_key_change(RowIndex, NCols), + validate_own_priv_key_change(RowIndex, NCols), ok. pre_set(RowIndex, Cols) -> + %% Remove the ?is_cloning member again; it must no longer be + %% present. + Cols0 = key1delete(?is_cloning, Cols), %% Possibly initialize the usmUserSecurityName and privacy keys case snmp_generic:table_row_exists(db(usmUserTable), RowIndex) of - true -> Cols; + true -> Cols0; false -> SecName = get_user_name(RowIndex), - [{?usmUserSecurityName, SecName} | Cols] ++ - [{?usmUserAuthKey, ""}, - {?usmUserPrivKey, ""}] + Cols1 = [{?usmUserSecurityName, SecName} | Cols0], + case proplists:get_value(?is_cloning, Cols) of + true -> + % the row is just being cloned. the cloned user's + % passwords are already present in Cols and must + % not be overwritten. + Cols1; + _ -> + Cols1 ++ [{?usmUserAuthKey, ""}, + {?usmUserPrivKey, ""}] + end end. validate_set({noError, 0}, RowIndex, Cols) -> %% Now, all is_set_ok validation steps have been executed. So %% everything is ready for the set. - set_clone_from(RowIndex, Cols), set_auth_key_change(RowIndex, Cols), set_own_auth_key_change(RowIndex, Cols), set_priv_key_change(RowIndex, Cols), @@ -769,7 +782,7 @@ validate_set(Error, _RowIndex, _Cols) -> %% no further checks. %%----------------------------------------------------------------- validate_clone_from(RowIndex, Cols) -> - case lists:keysearch(?usmUserCloneFrom, 1, Cols) of + case key1search(?usmUserCloneFrom, Cols) of {value, {_Col, RowPointer}} -> RowIndex2 = extract_row(RowPointer), OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable), @@ -778,35 +791,63 @@ validate_clone_from(RowIndex, Cols) -> case OldCloneFrom of {value, Val} when Val /= noinit -> %% This means that the cloning is already done... - ok; + no_cloning(Cols); _ -> - %% Otherwise, we must check the CloneFrom value - case snmp_generic:table_get_element(db(usmUserTable), - RowIndex2, - ?usmUserStatus) of - {value, ?'RowStatus_active'} -> ok; - _ -> inconsistentName(?usmUserCloneFrom) - end + %% Otherwise, we must check the CloneFrom value. It + %% must relate to a usmUserEntry that exists and is active. + case snmp_generic:table_get_row(db(usmUserTable), RowIndex2) of + CloneFromRow when is_tuple(CloneFromRow) -> + case element(?usmUserStatus, CloneFromRow) of + ?'RowStatus_active' -> + get_cloned_cols(CloneFromRow, Cols); + _ -> + inconsistentName(?usmUserCloneFrom) + end; + undefined -> + inconsistentName(?usmUserCloneFrom) + end end; false -> - ok + % no ?usmUserCloneFrom specified, don't modify columns + no_cloning(Cols) end. +get_cloned_cols(CloneFromRow, Cols) -> + % initialize cloned columns with data from CloneFromRow + % and overwrite that again with data found in Cols + AuthP = element(?usmUserAuthProtocol, CloneFromRow), + PrivP = element(?usmUserPrivProtocol, CloneFromRow), + AuthK = element(?usmUserAuthKey, CloneFromRow), + PrivK = element(?usmUserPrivKey, CloneFromRow), + ClonedCols = [{?usmUserAuthProtocol, AuthP}, + {?usmUserPrivProtocol, PrivP}, + {?usmUserAuthKey, AuthK}, + {?usmUserPrivKey, PrivK}, + {?is_cloning, true} + ], + Func = fun({Col, _} = Item, NCols) -> + key1store(Col, NCols, Item) + end, + Cols1 = lists:foldl(Func, ClonedCols, Cols), + key1sort(Cols1). + +no_cloning(Cols0) -> + Cols1 = key1delete(?usmUserCloneFrom, Cols0), + key1delete(?is_cloning, Cols1). + validate_auth_protocol(RowIndex, Cols) -> - case lists:keysearch(?usmUserAuthProtocol, 1, Cols) of + case key1search(?usmUserAuthProtocol, Cols) of {value, {_Col, AuthProtocol}} -> - %% Check if the row has been cloned; we can't check the + %% Check if the row is being cloned; we can't check the %% old value of authProtocol, because if the row was %% createAndWaited, the default value would have been %% written (usmNoAuthProtocol). - OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable), - RowIndex, - ?usmUserCloneFrom), - case OldCloneFrom of - {value, Val} when Val /= noinit -> - %% This means that the cloning is already done; set is ok - %% if new protocol is usmNoAuthProtocol + IsCloning = proplists:get_value(?is_cloning, Cols, false), + if + not IsCloning -> + %% This means that the row is not being cloned right + %% now; set is ok if new protocol is usmNoAuthProtocol case AuthProtocol of ?usmNoAuthProtocol -> %% Check that the Priv protocl is noPriv @@ -821,7 +862,7 @@ validate_auth_protocol(RowIndex, Cols) -> _ -> wrongValue(?usmUserAuthProtocol) end; - _ -> + true -> %% Otherwise, check that the new protocol is known, %% and that the system we're running supports the %% hash function. @@ -867,7 +908,7 @@ validate_own_priv_key_change(RowIndex, Cols) -> %% Check that the requesting user is the same as the modified user validate_requester(RowIndex, Cols, KeyChangeCol) -> - case lists:keysearch(KeyChangeCol, 1, Cols) of + case key1search(KeyChangeCol, Cols) of {value, _} -> case get(sec_model) of % Check the securityModel in the request ?SEC_USM -> ok; @@ -890,17 +931,14 @@ validate_requester(RowIndex, Cols, KeyChangeCol) -> end. validate_key_change(RowIndex, Cols, KeyChangeCol, Type) -> - case lists:keysearch(KeyChangeCol, 1, Cols) of + case key1search(KeyChangeCol, Cols) of {value, {_Col, KeyC}} -> %% Check if the row has been cloned; or if it is cloned in %% this set-operation. OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable), RowIndex, ?usmUserCloneFrom), - IsClonePresent = case lists:keysearch(?usmUserCloneFrom, 1, Cols) of - {value, _} -> true; - false -> false - end, + IsClonePresent = proplists:get_value(?is_cloning, Cols, false), %% Set is ok if 1) the user already is created, 2) this is %% a new user, which has been cloned, or is about to be %% cloned. @@ -912,7 +950,7 @@ validate_key_change(RowIndex, Cols, KeyChangeCol, Type) -> %% The user is cloned in this operation ok; _ -> - %% The user doen't exist, or hasn't been cloned, + %% The user doesn't exist, or hasn't been cloned, %% and is not cloned in this operation. inconsistentName(KeyChangeCol) end, @@ -939,17 +977,15 @@ validate_key_change(RowIndex, Cols, KeyChangeCol, Type) -> end. validate_priv_protocol(RowIndex, Cols) -> - case lists:keysearch(?usmUserPrivProtocol, 1, Cols) of + case key1search(?usmUserPrivProtocol, Cols) of {value, {_Col, PrivProtocol}} -> %% Check if the row has been cloned; we can't check the %% old value of privhProtocol, because if the row was %% createAndWaited, the default value would have been %% written (usmNoPrivProtocol). - OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable), - RowIndex, - ?usmUserCloneFrom), - case OldCloneFrom of - {value, Val} when Val /= noinit -> + IsCloning = proplists:get_value(?is_cloning, Cols, false), + if + not IsCloning -> %% This means that the cloning is already done; set is ok %% if new protocol is usmNoPrivProtocol case PrivProtocol of @@ -962,7 +998,7 @@ validate_priv_protocol(RowIndex, Cols) -> _ -> wrongValue(?usmUserPrivProtocol) end; - _ -> + true -> %% Otherwise, check that the new protocol is known, %% and that the system we're running supports the %% crypto function. @@ -1005,31 +1041,6 @@ validate_priv_protocol(RowIndex, Cols) -> end. -set_clone_from(RowIndex, Cols) -> - %% If CloneFrom is modified, do the cloning. - case lists:keysearch(?usmUserCloneFrom, 1, Cols) of - {value, {_Col, RowPointer}} -> - RowIndex2 = extract_row(RowPointer), % won't fail - CloneRow = snmp_generic:table_get_row(db(usmUserTable), RowIndex2, - foi(usmUserTable)), - AuthP = element(?usmUserAuthProtocol, CloneRow), - PrivP = element(?usmUserPrivProtocol, CloneRow), - AuthK = element(?usmUserAuthKey, CloneRow), - PrivK = element(?usmUserPrivKey, CloneRow), - SCols = [{?usmUserAuthProtocol, AuthP}, - {?usmUserPrivProtocol, PrivP}, - {?usmUserAuthKey, AuthK}, - {?usmUserPrivKey, PrivK}], - case snmp_generic:table_set_elements(db(usmUserTable), - RowIndex, - SCols) of - true -> ok; - false -> {commitFailed, ?usmUserCloneFrom} - end; - false -> - ok - end. - set_auth_key_change(RowIndex, Cols) -> set_key_change(RowIndex, Cols, ?usmUserAuthKeyChange, auth). @@ -1043,7 +1054,7 @@ set_own_priv_key_change(RowIndex, Cols) -> set_key_change(RowIndex, Cols, ?usmUserOwnPrivKeyChange, priv). set_key_change(RowIndex, Cols, KeyChangeCol, Type) -> - case lists:keysearch(KeyChangeCol, 1, Cols) of + case key1search(KeyChangeCol, Cols) of {value, {_Col, KeyChange}} -> KeyCol = case Type of auth -> ?usmUserAuthKey; @@ -1071,11 +1082,11 @@ extract_row([H | T], [H | T2]) -> extract_row(T, T2); extract_row([], [?usmUserSecurityName | T]) -> T; extract_row(_, _) -> wrongValue(?usmUserCloneFrom). -%% Pre: the user exixt +%% Pre: the user exists or is being cloned in this operation get_auth_proto(RowIndex, Cols) -> - %% The protocol can be chanegd by the request too, otherwise, + %% The protocol can be changed by the request too, otherwise, %% check the stored protocol. - case lists:keysearch(?usmUserAuthProtocol, 1, Cols) of + case key1search(?usmUserAuthProtocol, Cols) of {value, {_, Protocol}} -> Protocol; false -> @@ -1090,11 +1101,11 @@ get_auth_proto(RowIndex, Cols) -> end end. -%% Pre: the user exixt +%% Pre: the user exists or is being cloned in this operation get_priv_proto(RowIndex, Cols) -> - %% The protocol can be chanegd by the request too, otherwise, + %% The protocol can be changed by the request too, otherwise, %% check the stored protocol. - case lists:keysearch(?usmUserPrivProtocol, 1, Cols) of + case key1search(?usmUserPrivProtocol, Cols) of {value, {_, Protocol}} -> Protocol; false -> @@ -1232,6 +1243,27 @@ set_sname(_) -> %% Keep it, if already set. error(Reason) -> throw({error, Reason}). + +%%----------------------------------------------------------------- +%% lists key-function(s) wrappers + +-compile({inline,key1delete/2}). +key1delete(Key, List) -> + lists:keydelete(Key, 1, List). + +-compile({inline,key1search/2}). +key1search(Key, List) -> + lists:keysearch(Key, 1, List). + +-compile({inline,key1store/3}). +key1store(Key, List, Elem) -> + lists:keystore(Key, 1, List, Elem). + +-compile({inline,key1sort/1}). +key1sort(List) -> + lists:keysort(1, List). + + %%----------------------------------------------------------------- info_msg(F, A) -> diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl index 479a44795f..436f15eb9c 100644 --- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl +++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl @@ -565,45 +565,85 @@ vacmAccessTable(is_set_ok, RowIndex, Cols0) -> case (catch verify_vacmAccessTable_cols(Cols0, [])) of {ok, Cols} -> IsValidKey = is_valid_key(RowIndex), - case lists:keysearch(?vacmAccessStatus, 1, Cols) of - %% Ok, if contextMatch is init - {value, {Col, ?'RowStatus_active'}} -> - {ok, Row} = snmpa_vacm:get_row(RowIndex), - case element(?vacmAContextMatch, Row) of - noinit -> {inconsistentValue, Col}; - _ -> {noError, 0} + StatusCol = lists:keyfind(?vacmAccessStatus, 1, Cols), + MaybeRow = snmpa_vacm:get_row(RowIndex), + case {StatusCol, MaybeRow} of + {{Col, ?'RowStatus_active'}, false} -> + %% row does not yet exist => inconsistentValue + %% (see SNMPv2-TC.mib, RowStatus textual convention) + {inconsistentValue, Col}; + {{Col, ?'RowStatus_active'}, {ok, Row}} -> + %% Ok, if contextMatch is init + case element(?vacmAContextMatch, Row) of + noinit -> + %% check whether ContextMatch is being set in + %% the same operation + case proplists:get_value(?vacmAccessContextMatch, + Cols) of + undefined -> + %% no, we can't make this row active yet + {inconsistentValue, Col}; + _ -> + %% ok, activate the row + {noError, 0} + end; + _ -> + {noError, 0} end; - {value, {Col, ?'RowStatus_notInService'}} -> % Ok, if not notReady - {ok, Row} = snmpa_vacm:get_row(RowIndex), + {{Col, ?'RowStatus_notInService'}, false} -> + %% row does not yet exist => inconsistentValue + %% (see SNMPv2-TC.mib, RowStatus textual convention) + {inconsistentValue, Col}; + {{Col, ?'RowStatus_notInService'}, {ok, Row}} -> + %% Ok, if not notReady case element(?vacmAStatus, Row) of - ?'RowStatus_notReady' -> {inconsistentValue, Col}; - _ -> {noError, 0} + ?'RowStatus_notReady' -> + {inconsistentValue, Col}; + _ -> + {noError, 0} end; - {value, {Col, ?'RowStatus_notReady'}} -> % never ok! + {{Col, ?'RowStatus_notReady'}, _} -> + %% never ok! {inconsistentValue, Col}; - {value, {Col, ?'RowStatus_createAndGo'}} -> % ok, if it doesn't exist + {{Col, ?'RowStatus_createAndGo'}, false} -> + %% ok, if it doesn't exist Res = lists:keysearch(?vacmAccessContextMatch, 1, Cols), - case snmpa_vacm:get_row(RowIndex) of - false when (IsValidKey =:= true) andalso - is_tuple(Res) -> {noError, 0}; - false -> {noCreation, Col}; % Bad RowIndex - _ -> {inconsistentValue, Col} + if + IsValidKey =/= true -> + %% bad RowIndex => noCreation + {noCreation, Col}; + is_tuple(Res) -> + %% required field is present => noError + {noError, 0}; + true -> + %% required field is missing => inconsistentValue + {inconsistentValue, Col} end; - {value, {Col, ?'RowStatus_createAndWait'}} -> % ok, if it doesn't exist - case snmpa_vacm:get_row(RowIndex) of - false when (IsValidKey =:= true) -> {noError, 0}; - false -> {noCreation, Col}; % Bad RowIndex - _ -> {inconsistentValue, Col} + {{Col, ?'RowStatus_createAndGo'}, _} -> + %% row already exists => inconsistentValue + {inconsistentValue, Col}; + {{Col, ?'RowStatus_createAndWait'}, false} -> + %% ok, if it doesn't exist + if + IsValidKey =:= true -> + %% RowIndex is valid => noError + {noError, 0}; + true -> + {noCreation, Col} end; - {value, {_Col, ?'RowStatus_destroy'}} -> % always ok! + {{Col, ?'RowStatus_createAndWait'}, _} -> + %% Row already exists => inconsistentValue + {inconsistentValue, Col}; + {value, {_Col, ?'RowStatus_destroy'}} -> + %% always ok! {noError, 0}; - _ -> % otherwise, it's a change; it must exist - case snmpa_vacm:get_row(RowIndex) of - {ok, _} -> - {noError, 0}; - false -> - {inconsistentName, element(1, hd(Cols))} - end + {_, false} -> + %% otherwise, it's a row change; + %% row does not exist => inconsistentName + {inconsistentName, element(1, hd(Cols))}; + _ -> + %% row change and row exists => noError + {noError, 0} end; Error -> Error @@ -734,10 +774,15 @@ do_vacmAccessTable_set(RowIndex, Cols) -> %% Cols are sorted, and all columns are > 3. +do_get_next(_RowIndex, []) -> + % Cols can be empty because we're called for each + % output of split_cols(); and one of that may well + % be empty. + []; do_get_next(RowIndex, Cols) -> case snmpa_vacm:get_next_row(RowIndex) of {NextIndex, Row} -> - F1 = fun(Col) when Col < ?vacmAccessStatus -> + F1 = fun(Col) when Col =< ?vacmAccessStatus -> {[Col | NextIndex], element(Col-3, Row)}; (_) -> endOfTable @@ -745,9 +790,9 @@ do_get_next(RowIndex, Cols) -> lists:map(F1, Cols); false -> case snmpa_vacm:get_next_row([]) of - {_NextIndex, Row} -> + {NextIndex2, Row} -> F2 = fun(Col) when Col < ?vacmAccessStatus -> - {[Col+1 | RowIndex], element(Col-2, Row)}; + {[Col+1 | NextIndex2], element(Col-2, Row)}; (_) -> endOfTable end, diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 8360d88c94..593ddd82bd 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -22,8 +22,18 @@ %% ----- U p g r a d e ------------------------------------------------------- [ + {"4.22", + [ + {load_module, snmpm, soft_purge, soft_purge, []}, + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []} + ] + }, {"4.21.7", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -50,6 +60,8 @@ }, {"4.21.6", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -76,6 +88,8 @@ }, {"4.21.5", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -107,6 +121,8 @@ }, {"4.21.4", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -141,6 +157,8 @@ }, {"4.21.3", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -175,6 +193,8 @@ }, {"4.21.2", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -211,6 +231,8 @@ }, {"4.21.1", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -248,6 +270,8 @@ }, {"4.21", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -288,8 +312,19 @@ %% ------D o w n g r a d e --------------------------------------------------- [ + {"4.22", + [ + {load_module, snmpm, soft_purge, soft_purge, []}, + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []} + ] + }, {"4.21.7", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + + {load_module, snmp_pdus, soft_purge, soft_purge, []}, {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -316,6 +351,8 @@ }, {"4.21.6", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -342,6 +379,8 @@ }, {"4.21.5", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -373,6 +412,8 @@ }, {"4.21.4", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -407,6 +448,8 @@ }, {"4.21.3", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -441,6 +484,8 @@ }, {"4.21.2", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -477,6 +522,8 @@ }, {"4.21.1", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, @@ -514,6 +561,8 @@ }, {"4.21", [ + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_conf, soft_purge, soft_purge, []}, {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl index 89eaee9f80..f590892c66 100644 --- a/lib/snmp/src/manager/snmpm.erl +++ b/lib/snmp/src/manager/snmpm.erl @@ -1411,7 +1411,7 @@ log_to_io(LogDir, Mibs, LogName, LogFile) -> log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start). log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> - snmp:log_to_io(LogDir, Mibs, LogFile, Start, Stop). + snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop). change_log_size(NewSize) -> diff --git a/lib/snmp/src/misc/snmp_pdus.erl b/lib/snmp/src/misc/snmp_pdus.erl index 0788d86b2d..5b8be90a71 100644 --- a/lib/snmp/src/misc/snmp_pdus.erl +++ b/lib/snmp/src/misc/snmp_pdus.erl @@ -254,68 +254,95 @@ strip(0, _Tail) -> %%---------------------------------------------------------------------- %% Returns:{Type, Value} %%---------------------------------------------------------------------- + +%% OBJECT IDENTIFIER dec_value([6 | Bytes]) -> {Value, Rest} = dec_oid_notag(Bytes), {{'OBJECT IDENTIFIER', Value}, Rest}; dec_value([5,0 | T]) -> {{'NULL', 'NULL'}, T}; + +%% INTEGER dec_value([2 | Bytes]) -> {Value, Rest} = dec_integer_notag(Bytes), {{'INTEGER', Value}, Rest}; + +%% OCTET STRING dec_value([4 | Bytes]) -> {Value, Rest} = dec_oct_str_notag(Bytes), {{'OCTET STRING', Value}, Rest}; + +%% IpAddress dec_value([64 | Bytes]) -> {Value, Rest} = dec_oct_str_notag(Bytes), {{'IpAddress', Value}, Rest}; + +%% Counter32 dec_value([65 | Bytes]) -> %% Counter32 is an unsigned 32 but is actually encoded as %% a signed integer 32 (INTEGER). {Value, Rest} = dec_integer_notag(Bytes), Value2 = - if + if + (Value >= 0) andalso (Value =< 16#ffffffff) -> + %% We accept value above 16#7fffffff + %% in order to be backward bug-compatible + Value; + (Value < 0) -> + 16#ffffffff + Value + 1; + true -> + exit({error, {bad_counter32, Value}}) + end, + {{'Counter32', Value2}, Rest}; + +%% Unsigned32 +dec_value([66 | Bytes]) -> + {Value, Rest} = dec_integer_notag(Bytes), + Value2 = + if (Value >= 0) andalso (Value =< 16#ffffffff) -> - %% We accept value above 16#7fffffff - %% in order to be backward bug-compatible Value; (Value < 0) -> 16#ffffffff + Value + 1; true -> - exit({error, {bad_counter32, Value}}) + exit({error, {bad_unsigned32, Value}}) end, - {{'Counter32', Value2}, Rest}; -dec_value([66 | Bytes]) -> - {Value, Rest} = dec_integer_notag(Bytes), - if - (Value >= 0) andalso (Value =< 4294967295) -> - {{'Unsigned32', Value}, Rest}; - true -> - exit({error, {bad_unsigned32, Value}}) - end; + {{'Unsigned32', Value2}, Rest}; + +%% TimeTicks dec_value([67 | Bytes]) -> {Value, Rest} = dec_integer_notag(Bytes), - if - (Value >= 0) andalso (Value =< 4294967295) -> - {{'TimeTicks', Value}, Rest}; + Value2 = + if + (Value >= 0) andalso (Value =< 16#ffffffff) -> + Value; + (Value < 0) -> + 16#ffffffff + Value + 1; true -> exit({error, {bad_timeticks, Value}}) - end; + end, + {{'TimeTicks', Value2}, Rest}; + +%% Opaque dec_value([68 | Bytes]) -> {Value, Rest} = dec_oct_str_notag(Bytes), {{'Opaque', Value}, Rest}; + +%% Counter64 dec_value([70 | Bytes]) -> %% Counter64 is an unsigned 64 but is actually encoded as %% a signed integer 64. {Value, Rest} = dec_integer_notag(Bytes), Value2 = - if - (Value >= 0) andalso (Value < 16#8000000000000000) -> - Value; - (Value < 0) -> - 18446744073709551615 + Value + 1; - true -> - exit({error, {bad_counter64, Value}}) end, + if + (Value >= 0) andalso (Value < 16#8000000000000000) -> + Value; + (Value < 0) -> + 16#ffffffffffffffff + Value + 1; + true -> + exit({error, {bad_counter64, Value}}) end, {{'Counter64', Value2}, Rest}; + dec_value([128,0|T]) -> {{'NULL', noSuchObject}, T}; dec_value([129,0|T]) -> @@ -629,7 +656,7 @@ enc_VarBind_attributes(#varbind{oid = Oid, variabletype = Type,value = Val}) -> ValueBytes = enc_value(Type, Val), lists:append(OidBytes, ValueBytes). -enc_value('INTEGER',Val) -> +enc_value('INTEGER', Val) -> enc_integer_tag(Val); enc_value('OCTET STRING', Val) -> enc_oct_str_tag(Val); @@ -637,7 +664,7 @@ enc_value('BITS', Val) -> enc_oct_str_tag(bits_to_str(Val)); enc_value('OBJECT IDENTIFIER', Val) -> enc_oid_tag(Val); -enc_value('IpAddress',Val) -> +enc_value('IpAddress', Val) -> Bytes2 = enc_oct_str_notag(Val), Len2 = elength(length(Bytes2)), lists:append([64 | Len2],Bytes2); @@ -668,6 +695,24 @@ enc_value('Counter32', Val) -> Bytes2 = enc_integer_notag(Val2), Len2 = elength(length(Bytes2)), lists:append([65 | Len2],Bytes2); +enc_value('Unsigned32', Val) -> + if + (Val >= 0) andalso (Val =< 4294967295) -> + Bytes2 = enc_integer_notag(Val), + Len2 = elength(length(Bytes2)), + lists:append([66 | Len2], Bytes2); + true -> + exit({error, {bad_counter32, Val}}) + end; +enc_value('TimeTicks', Val) -> + if + (Val >= 0) andalso (Val =< 4294967295) -> + Bytes2 = enc_integer_notag(Val), + Len2 = elength(length(Bytes2)), + lists:append([67 | Len2], Bytes2); + true -> + exit({error, {bad_timeticks, Val}}) + end; enc_value('Counter64', Val) -> Val2 = if @@ -682,18 +727,7 @@ enc_value('Counter64', Val) -> end, Bytes2 = enc_integer_notag(Val2), Len2 = elength(length(Bytes2)), - lists:append([70 | Len2],Bytes2); -enc_value(Type, Val) -> - Bytes2 = enc_integer_notag(Val), - Len2 = elength(length(Bytes2)), - lists:append([enc_val_tag(Type,Val) | Len2],Bytes2). - -enc_val_tag('Counter32',Val) when (Val >= 0) andalso (Val =< 4294967295) -> - 65; -enc_val_tag('Unsigned32', Val) when (Val >= 0) andalso (Val =< 4294967295) -> - 66; -enc_val_tag('TimeTicks', Val) when (Val >= 0) andalso (Val =< 4294967295) -> - 67. + lists:append([70 | Len2],Bytes2). %%---------------------------------------------------------------------- diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl index 8ee5dd534d..e1d7f33b3f 100644 --- a/lib/snmp/test/snmp_agent_test.erl +++ b/lib/snmp/test/snmp_agent_test.erl @@ -346,47 +346,72 @@ end_per_group(_GroupName, Config) -> -init_per_testcase(otp8395 = Case, Config) when is_list(Config) -> +%% ---- Init Per TestCase ---- + +init_per_testcase(Case, Config) when is_list(Config) -> ?DBG("init_per_testcase -> entry with" + "~n Config: ~p", [Config]), + + p("Agent Info: " + "~n ~p", [snmpa:info()]), + + init_per_testcase1(Case, Config). + +init_per_testcase1(otp8395 = Case, Config) when is_list(Config) -> + ?DBG("init_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [Case, Config]), otp8395({init, init_per_testcase2(Case, Config)}); -init_per_testcase(otp9884 = Case, Config) when is_list(Config) -> - ?DBG("init_per_testcase -> entry with" +init_per_testcase1(otp9884 = Case, Config) when is_list(Config) -> + ?DBG("init_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [Case, Config]), otp9884({init, init_per_testcase2(Case, Config)}); -init_per_testcase(otp_7157_test = _Case, Config) when is_list(Config) -> - ?DBG("init_per_testcase -> entry with" +init_per_testcase1(otp_7157_test = _Case, Config) when is_list(Config) -> + ?DBG("init_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), Dog = ?WD_START(?MINS(1)), [{watchdog, Dog} | Config ]; -init_per_testcase(v2_inform_i = _Case, Config) when is_list(Config) -> - ?DBG("init_per_testcase -> entry with" +init_per_testcase1(v2_inform_i = _Case, Config) when is_list(Config) -> + ?DBG("init_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), Dog = ?WD_START(?MINS(10)), [{watchdog, Dog} | Config ]; -init_per_testcase(v3_inform_i = _Case, Config) when is_list(Config) -> - ?DBG("init_per_testcase -> entry with" +init_per_testcase1(v3_inform_i = _Case, Config) when is_list(Config) -> + ?DBG("init_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), Dog = ?WD_START(?MINS(10)), [{watchdog, Dog} | Config ]; -init_per_testcase(_Case, Config) when is_list(Config) -> +init_per_testcase1(_Case, Config) when is_list(Config) -> ?DBG("init_per_testcase -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), Dog = ?WD_START(?MINS(6)), [{watchdog, Dog}| Config ]. -end_per_testcase(otp8395, Config) when is_list(Config) -> + +%% ---- End Per TestCase ---- + +end_per_testcase(Case, Config) when is_list(Config) -> + ?DBG("end_per_testcase -> entry with" + "~n Config: ~p", [Config]), + + p("Agent Info: " + "~n ~p", [snmpa:info()]), + + display_log(Config), + + end_per_testcase1(Case, Config). + +end_per_testcase1(otp8395, Config) when is_list(Config) -> otp8395({fin, Config}); -end_per_testcase(otp9884, Config) when is_list(Config) -> +end_per_testcase1(otp9884, Config) when is_list(Config) -> otp9884({fin, Config}); -end_per_testcase(_Case, Config) when is_list(Config) -> - ?DBG("end_per_testcase -> entry with" +end_per_testcase1(_Case, Config) when is_list(Config) -> + ?DBG("end_per_testcase1 -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), Dog = ?config(watchdog, Config), @@ -1406,9 +1431,6 @@ simple(Config) when is_list(Config) -> try_test(simple_standard_test), - p("Display log"), - display_log(Config), - p("done"), ok. diff --git a/lib/snmp/test/snmp_pdus_test.erl b/lib/snmp/test/snmp_pdus_test.erl index 07b6d6b657..0d78749bcb 100644 --- a/lib/snmp/test/snmp_pdus_test.erl +++ b/lib/snmp/test/snmp_pdus_test.erl @@ -39,6 +39,7 @@ otp7575/1, otp8563/1, otp9022/1, + otp10132/1, init_per_testcase/2, end_per_testcase/2 ]). @@ -74,16 +75,16 @@ end_per_testcase(_Case, Config) when is_list(Config) -> %% Test case definitions %%====================================================================== all() -> -[{group, tickets}]. + [{group, tickets}]. groups() -> - [{tickets, [], [otp7575, otp8563, otp9022]}]. + [{tickets, [], [otp7575, otp8563, otp9022, otp10132]}]. init_per_group(_GroupName, Config) -> - Config. + Config. end_per_group(_GroupName, Config) -> - Config. + Config. @@ -94,7 +95,7 @@ end_per_group(_GroupName, Config) -> %%====================================================================== otp7575(suite) -> []; -otp7575(doc) -> ["OTP-7575"]; +otp7575(doc) -> ["OTP-7575 - Message version"]; otp7575(Config) when is_list(Config) -> io:format("attempt to decode message with valid version~n", []), MsgWithOkVersion = <<48,39,2,1,0,4,6,112,117,98,108,105,99,160,26,2,2,1,49,2,1,0,2,1,0,48,14,48,12,6,8,43,6,1,2,1,1,5,0,5,0>>, @@ -127,48 +128,55 @@ otp7575(Config) when is_list(Config) -> otp8563(suite) -> []; -otp8563(doc) -> ["OTP-8563"]; +otp8563(doc) -> ["OTP-8563 - Counter64"]; otp8563(Config) when is_list(Config) -> Val1 = 16#7fffffffffffffff, - io:format("try encode and decode ~w~n", [Val1]), + io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]), Enc1 = snmp_pdus:enc_value('Counter64', Val1), + io:format(" => ~w~n", [Enc1]), {{'Counter64', Val1}, []} = snmp_pdus:dec_value(Enc1), Val2 = Val1 + 1, - io:format("try encode and decode ~w~n", [Val2]), + io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]), Enc2 = snmp_pdus:enc_value('Counter64', Val2), + io:format(" => ~w~n", [Enc2]), {{'Counter64', Val2}, []} = snmp_pdus:dec_value(Enc2), Val3 = Val2 + 1, - io:format("try encode and decode ~w~n", [Val3]), + io:format("try encode and decode valule 3: ~w (0x~.16b)~n", [Val3, Val3]), Enc3 = snmp_pdus:enc_value('Counter64', Val3), + io:format(" => ~w~n", [Enc3]), {{'Counter64', Val3}, []} = snmp_pdus:dec_value(Enc3), Val4 = 16#fffffffffffffffe, - io:format("try encode and decode ~w~n", [Val4]), + io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]), Enc4 = snmp_pdus:enc_value('Counter64', Val4), + io:format(" => ~w~n", [Enc4]), {{'Counter64', Val4}, []} = snmp_pdus:dec_value(Enc4), Val5 = Val4 + 1, - io:format("try encode and decode ~w~n", [Val5]), + io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]), Enc5 = snmp_pdus:enc_value('Counter64', Val5), + io:format(" => ~w~n", [Enc5]), {{'Counter64', Val5}, []} = snmp_pdus:dec_value(Enc5), Val6 = 16#ffffffffffffffff + 1, - io:format("try and fail to encode ~w~n", [Val6]), + io:format("try and fail to encode value 6: ~w (0x~.16b)~n", [Val6, Val6]), case (catch snmp_pdus:enc_value('Counter64', Val6)) of {'EXIT', {error, {bad_counter64, Val6}}} -> ok; Unexpected6 -> + io:format(" => ~w~n", [Unexpected6]), exit({unexpected_encode_result, Unexpected6, Val6}) end, Val7 = -1, - io:format("try and fail to encode ~w~n", [Val7]), + io:format("try and fail to encode value 7: ~w~n", [Val7]), case (catch snmp_pdus:enc_value('Counter64', Val7)) of {'EXIT', {error, {bad_counter64, Val7}}} -> ok; Unexpected7 -> + io:format(" => ~w~n", [Unexpected7]), exit({unexpected_encode_result, Unexpected7, Val7}) end, @@ -176,51 +184,151 @@ otp8563(Config) when is_list(Config) -> otp9022(suite) -> []; -otp9022(doc) -> ["OTP-9022"]; +otp9022(doc) -> ["OTP-9022 - Counter32"]; otp9022(Config) when is_list(Config) -> - Val1 = 16#7fffffff, - io:format("try encode and decode ~w~n", [Val1]), + Val0 = 2908389204, + io:format("try encode and decode value 0: ~w (0x~.16b)~n", [Val0, Val0]), + Enc0 = snmp_pdus:enc_value('Counter32', Val0), + io:format(" => ~w~n", [Enc0]), + {{'Counter32', Val0}, []} = snmp_pdus:dec_value(Enc0), + + Val1 = 0, + io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]), Enc1 = snmp_pdus:enc_value('Counter32', Val1), + io:format(" => ~w~n", [Enc1]), {{'Counter32', Val1}, []} = snmp_pdus:dec_value(Enc1), Val2 = Val1 + 1, - io:format("try encode and decode ~w~n", [Val2]), + io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]), Enc2 = snmp_pdus:enc_value('Counter32', Val2), + io:format(" => ~w~n", [Enc2]), {{'Counter32', Val2}, []} = snmp_pdus:dec_value(Enc2), - Val3 = Val2 + 1, - io:format("try encode and decode ~w~n", [Val3]), + Val3 = 16#7ffffffe, + io:format("try encode and decode value 3: ~w (0x~.16b)~n", [Val3, Val3]), Enc3 = snmp_pdus:enc_value('Counter32', Val3), + io:format(" => ~w~n", [Enc3]), {{'Counter32', Val3}, []} = snmp_pdus:dec_value(Enc3), - Val4 = 16#fffffffe, - io:format("try encode and decode ~w~n", [Val4]), + Val4 = Val3 + 1, + io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]), Enc4 = snmp_pdus:enc_value('Counter32', Val4), + io:format(" => ~w~n", [Enc4]), {{'Counter32', Val4}, []} = snmp_pdus:dec_value(Enc4), Val5 = Val4 + 1, - io:format("try encode and decode ~w~n", [Val5]), + io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]), Enc5 = snmp_pdus:enc_value('Counter32', Val5), + io:format(" => ~w~n", [Enc5]), {{'Counter32', Val5}, []} = snmp_pdus:dec_value(Enc5), - Val6 = 16#ffffffff + 1, - io:format("try and fail to encode ~w~n", [Val6]), - case (catch snmp_pdus:enc_value('Counter32', Val6)) of - {'EXIT', {error, {bad_counter32, Val6}}} -> + Val6 = 16#fffffffe, + io:format("try encode and decode value 6: ~w (0x~.16b)~n", [Val6, Val6]), + Enc6 = snmp_pdus:enc_value('Counter32', Val6), + io:format(" => ~w~n", [Enc6]), + {{'Counter32', Val6}, []} = snmp_pdus:dec_value(Enc6), + + Val7 = Val6 + 1, + io:format("try encode and decode value 7: ~w (0x~.16b)~n", [Val7, Val7]), + Enc7 = snmp_pdus:enc_value('Counter32', Val7), + io:format(" => ~w~n", [Enc7]), + {{'Counter32', Val7}, []} = snmp_pdus:dec_value(Enc7), + + Val8 = 16#ffffffff + 1, + io:format("try and fail to encode value 8: ~w (0x~.16b)~n", [Val8, Val8]), + case (catch snmp_pdus:enc_value('Counter32', Val8)) of + {'EXIT', {error, {bad_counter32, Val8}}} -> ok; - Unexpected6 -> - exit({unexpected_encode_result, Unexpected6, Val6}) + Unexpected8 -> + io:format(" => ~w~n", [Unexpected8]), + exit({unexpected_encode_result, Unexpected8, Val8}) end, - Val7 = -1, - io:format("try and fail to encode ~w~n", [Val7]), - case (catch snmp_pdus:enc_value('Counter32', Val7)) of - {'EXIT', {error, {bad_counter32, Val7}}} -> + Val9 = -1, + io:format("try and fail to encode value 9: ~w~n", [Val9]), + case (catch snmp_pdus:enc_value('Counter32', Val9)) of + {'EXIT', {error, {bad_counter32, Val9}}} -> ok; - Unexpected7 -> - exit({unexpected_encode_result, Unexpected7, Val7}) + Unexpected9 -> + io:format(" => ~w~n", [Unexpected9]), + exit({unexpected_encode_result, Unexpected9, Val9}) + end, + + ok. + + +otp10132(suite) -> []; +otp10132(doc) -> ["OTP-10132 - TimeTicks"]; +otp10132(Config) when is_list(Config) -> + Val0 = 2159001034, + io:format("try encode and decode value 0: ~w (0x~.16b)~n", [Val0, Val0]), + Enc0 = snmp_pdus:enc_value('TimeTicks', Val0), + io:format(" => ~w~n", [Enc0]), + {{'TimeTicks', Val0}, []} = snmp_pdus:dec_value(Enc0), + + Val1 = 0, + io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]), + Enc1 = snmp_pdus:enc_value('TimeTicks', Val1), + io:format(" => ~w~n", [Enc1]), + {{'TimeTicks', Val1}, []} = snmp_pdus:dec_value(Enc1), + + Val2 = Val1 + 1, + io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]), + Enc2 = snmp_pdus:enc_value('TimeTicks', Val2), + io:format(" => ~w~n", [Enc2]), + {{'TimeTicks', Val2}, []} = snmp_pdus:dec_value(Enc2), + + Val3 = 16#7ffffffe, + io:format("try encode and decode value 3: ~w (0x~.16b)~n", [Val3, Val3]), + Enc3 = snmp_pdus:enc_value('TimeTicks', Val3), + io:format(" => ~w~n", [Enc3]), + {{'TimeTicks', Val3}, []} = snmp_pdus:dec_value(Enc3), + + Val4 = Val3 + 1, + io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]), + Enc4 = snmp_pdus:enc_value('TimeTicks', Val4), + io:format(" => ~w~n", [Enc4]), + {{'TimeTicks', Val4}, []} = snmp_pdus:dec_value(Enc4), + + Val5 = Val4 + 1, + io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]), + Enc5 = snmp_pdus:enc_value('TimeTicks', Val5), + io:format(" => ~w~n", [Enc5]), + {{'TimeTicks', Val5}, []} = snmp_pdus:dec_value(Enc5), + + Val6 = 16#fffffffe, + io:format("try encode and decode value 6: ~w (0x~.16b)~n", [Val6, Val6]), + Enc6 = snmp_pdus:enc_value('TimeTicks', Val6), + io:format(" => ~w~n", [Enc6]), + {{'TimeTicks', Val6}, []} = snmp_pdus:dec_value(Enc6), + + Val7 = Val6 + 1, + io:format("try encode and decode value 7: ~w (0x~.16b)~n", [Val7, Val7]), + Enc7 = snmp_pdus:enc_value('TimeTicks', Val7), + io:format(" => ~w~n", [Enc7]), + {{'TimeTicks', Val7}, []} = snmp_pdus:dec_value(Enc7), + + Val8 = Val7 + 1, + io:format("try and fail to encode value 8: ~w (0x~.16b)~n", [Val8, Val8]), + case (catch snmp_pdus:enc_value('TimeTicks', Val8)) of + {'EXIT', {error, {bad_timeticks, Val8}}} -> + ok; + Unexpected8 -> + io:format(" => ~w~n", [Unexpected8]), + exit({unexpected_encode_result, Unexpected8, Val8}) end, + Val9 = -1, + io:format("try and fail to encode value 9: ~w~n", [Val9]), + case (catch snmp_pdus:enc_value('TimeTicks', Val9)) of + {'EXIT', {error, {bad_timeticks, Val9}}} -> + ok; + Unexpected9 -> + io:format(" => ~w~n", [Unexpected9]), + exit({unexpected_encode_result, Unexpected9, Val9}) + end, + + io:format("done~n", []), ok. diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index 36b9764bc8..b90dbe4eef 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = snmp -SNMP_VSN = 4.22 +SNMP_VSN = 4.22.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)" diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml index 488499581f..a57c7084fa 100644 --- a/lib/stdlib/doc/src/epp.xml +++ b/lib/stdlib/doc/src/epp.xml @@ -51,6 +51,7 @@ <func> <name name="open" arity="2"/> <name name="open" arity="3"/> + <name name="open" arity="4"/> <fsummary>Open a file for preprocessing</fsummary> <desc> <p>Opens a file for preprocessing.</p> @@ -75,6 +76,7 @@ </func> <func> <name name="parse_file" arity="3"/> + <name name="parse_file" arity="4"/> <fsummary>Preprocess and parse an Erlang source file</fsummary> <desc> <p>Preprocesses and parses an Erlang source file. diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile index 8bdaae57fd..54186a3ba7 100644 --- a/lib/stdlib/src/Makefile +++ b/lib/stdlib/src/Makefile @@ -167,6 +167,7 @@ docs: # This is a trick so that the preloaded files will get the correct type # specifications. primary_bootstrap_compiler: \ + $(BOOTSTRAP_COMPILER)/ebin/epp.beam \ $(BOOTSTRAP_COMPILER)/ebin/erl_scan.beam \ $(BOOTSTRAP_COMPILER)/ebin/erl_parse.beam \ $(BOOTSTRAP_COMPILER)/ebin/erl_lint.beam \ diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index ccc14610d7..d958b0af2a 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -20,9 +20,9 @@ %% An Erlang code preprocessor. --export([open/2,open/3,open/5,close/1,format_error/1]). +-export([open/2,open/3,open/4, open/5,close/1,format_error/1]). -export([scan_erl_form/1,parse_erl_form/1,macro_defs/1]). --export([parse_file/1, parse_file/3]). +-export([parse_file/1, parse_file/3, parse_file/4]). -export([interpret_file_attribute/1]). -export([normalize_typed_record_fields/1,restore_typed_record_fields/1]). @@ -54,12 +54,14 @@ %% open(FileName, IncludePath) %% open(FileName, IncludePath, PreDefMacros) +%% open(FileName, StartLocation, IncludePath, PredefMacros) %% open(FileName, IoDevice, StartLocation, IncludePath, PreDefMacros) %% close(Epp) %% scan_erl_form(Epp) %% parse_erl_form(Epp) %% parse_file(Epp) %% parse_file(FileName, IncludePath, PreDefMacros) +%% parse_file(FileName, StartLocation, IncludePath, PreDefMacros) %% macro_defs(Epp) -spec open(FileName, IncludePath) -> @@ -81,8 +83,20 @@ open(Name, Path) -> ErrorDescriptor :: term(). open(Name, Path, Pdm) -> + open(Name, 1, Path, Pdm). + +-spec open(FileName, StartLocation, IncludePath, PredefMacros) -> + {'ok', Epp} | {'error', ErrorDescriptor} when + FileName :: file:name(), + StartLocation :: erl_scan:location(), + IncludePath :: [DirectoryName :: file:name()], + PredefMacros :: macros(), + Epp :: epp_handle(), + ErrorDescriptor :: term(). + +open(Name, StartLocation, Path, Pdm) -> Self = self(), - Epp = spawn(fun() -> server(Self, Name, Path, Pdm) end), + Epp = spawn(fun() -> server(Self, Name, StartLocation, Path, Pdm) end), epp_request(Epp). open(Name, File, StartLocation, Path, Pdm) -> @@ -178,7 +192,21 @@ format_error(E) -> file:format_error(E). OpenError :: file:posix() | badarg | system_limit. parse_file(Ifile, Path, Predefs) -> - case open(Ifile, Path, Predefs) of + parse_file(Ifile, 1, Path, Predefs). + +-spec parse_file(FileName, StartLocation, IncludePath, PredefMacros) -> + {'ok', [Form]} | {error, OpenError} when + FileName :: file:name(), + StartLocation :: erl_scan:location(), + IncludePath :: [DirectoryName :: file:name()], + Form :: erl_parse:abstract_form() | {'error', ErrorInfo} | {'eof',Line}, + PredefMacros :: macros(), + Line :: erl_scan:line(), + ErrorInfo :: erl_scan:error_info() | erl_parse:error_info(), + OpenError :: file:posix() | badarg | system_limit. + +parse_file(Ifile, StartLocation, Path, Predefs) -> + case open(Ifile, StartLocation, Path, Predefs) of {ok,Epp} -> Forms = parse_file(Epp), close(Epp), @@ -245,14 +273,12 @@ restore_typed_record_fields([{attribute,La,type,{{record,Record},Fields,[]}}| restore_typed_record_fields([Form|Forms]) -> [Form|restore_typed_record_fields(Forms)]. -%% server(StarterPid, FileName, Path, PreDefMacros) - -server(Pid, Name, Path, Pdm) -> +%% server(StarterPid, FileName, Location, Path, PreDefMacros) +server(Pid, Name, AtLocation, Path, Pdm) -> process_flag(trap_exit, true), case file:open(Name, [read]) of {ok,File} -> - Location = 1, - init_server(Pid, Name, File, Location, Path, Pdm, false); + init_server(Pid, Name, File, AtLocation, Path, Pdm, false); {error,E} -> epp_reply(Pid, {error,E}) end. diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index abab81d31f..648ff349a4 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -248,6 +248,8 @@ format_error({illegal_guard_local_call, {F,A}}) -> io_lib:format("call to local/imported function ~w/~w is illegal in guard", [F,A]); format_error(illegal_guard_expr) -> "illegal guard expression"; +format_error(deprecated_tuple_fun) -> + "tuple funs are deprecated and will be removed in R16"; %% --- exports --- format_error({explicit_export,F,A}) -> io_lib:format("in this release, the call to ~w/~w must be written " @@ -1914,7 +1916,8 @@ gexpr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,F}},As}, Vt, St0) -> true -> {Asvt,St1}; false -> {Asvt,add_error(Line, illegal_guard_expr, St1)} end; -gexpr({call,L,{tuple,Lt,[{atom,Lm,erlang},{atom,Lf,F}]},As}, Vt, St) -> +gexpr({call,L,{tuple,Lt,[{atom,Lm,erlang},{atom,Lf,F}]},As}, Vt, St0) -> + St = add_warning(L, deprecated_tuple_fun, St0), gexpr({call,L,{remote,Lt,{atom,Lm,erlang},{atom,Lf,F}},As}, Vt, St); gexpr({op,Line,Op,A}, Vt, St0) -> {Avt,St1} = gexpr(A, Vt, St0), diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl index 10b2ed2e49..be64b428b1 100644 --- a/lib/stdlib/src/erl_scan.erl +++ b/lib/stdlib/src/erl_scan.erl @@ -55,7 +55,7 @@ token_info/1,token_info/2, attributes_info/1,attributes_info/2,set_attribute/3]). --export_type([error_info/0, line/0, tokens_result/0]). +-export_type([error_info/0, line/0, location/0, tokens_result/0]). %%% %%% Defines and type definitions diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl index dbfcbea4f7..870af4e95f 100644 --- a/lib/stdlib/src/filename.erl +++ b/lib/stdlib/src/filename.erl @@ -726,6 +726,8 @@ nativename(Name0) -> _ -> Name end. +win32_nativename(Name) when is_binary(Name) -> + binary:replace(Name, <<"/">>, <<"\\">>, [global]); win32_nativename([$/|Rest]) -> [$\\|win32_nativename(Rest)]; win32_nativename([C|Rest]) -> diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index dcd622b984..9f9d97b619 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -1331,17 +1331,20 @@ guard(Config) when is_list(Config) -> foo. ">>, [warn_unused_vars, nowarn_obsolete_guard], - {errors,[{2,erl_lint,illegal_guard_expr}, - {4,erl_lint,illegal_guard_expr}, - {6,erl_lint,illegal_guard_expr}, - {8,erl_lint,illegal_guard_expr}, - {10,erl_lint,illegal_guard_expr}, - {12,erl_lint,illegal_guard_expr}, - {14,erl_lint,illegal_guard_expr}, - {16,erl_lint,illegal_guard_expr}, - {18,erl_lint,illegal_guard_expr}, - {20,erl_lint,illegal_guard_expr}], - []}}, + {error,[{2,erl_lint,illegal_guard_expr}, + {4,erl_lint,illegal_guard_expr}, + {6,erl_lint,illegal_guard_expr}, + {8,erl_lint,illegal_guard_expr}, + {10,erl_lint,illegal_guard_expr}, + {12,erl_lint,illegal_guard_expr}, + {14,erl_lint,illegal_guard_expr}, + {16,erl_lint,illegal_guard_expr}, + {18,erl_lint,illegal_guard_expr}, + {20,erl_lint,illegal_guard_expr}], + [{8,erl_lint,deprecated_tuple_fun}, + {14,erl_lint,deprecated_tuple_fun}, + {20,erl_lint,deprecated_tuple_fun}, + {28,erl_lint,deprecated_tuple_fun}]}}, {guard6, <<"-record(apa,{a=a,b=foo:bar()}). apa() -> diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index 297c4ec1c9..97ac433cb9 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -74,6 +74,7 @@ -export([bad_table/1, types/1]). -export([otp_9932/1]). -export([otp_9423/1]). +-export([otp_10182/1]). -export([init_per_testcase/2, end_per_testcase/2]). %% Convenience for manual testing @@ -146,6 +147,7 @@ all() -> exit_many_large_table_owner, exit_many_tables_owner, exit_many_many_tables_owner, write_concurrency, heir, give_away, setopts, bad_table, types, + otp_10182, otp_9932, otp_9423]. @@ -5470,6 +5472,20 @@ otp_9423(Config) when is_list(Config) -> Skipped -> Skipped end. + +%% Corrupted binary in compressed table +otp_10182(Config) when is_list(Config) -> + Bin = <<"aHR0cDovL2hvb3RzdWl0ZS5jb20vYy9wcm8tYWRyb2xsLWFi">>, + Key = {test, Bin}, + Value = base64:decode(Bin), + In = {Key,Value}, + Db = ets:new(undefined, [set, protected, {read_concurrency, true}, compressed]), + ets:insert(Db, In), + [Out] = ets:lookup(Db, Key), + io:format("In : ~p\nOut: ~p\n", [In,Out]), + ets:delete(Db), + In = Out. + diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl index 4cfa589660..99516c0c04 100644 --- a/lib/stdlib/test/filename_SUITE.erl +++ b/lib/stdlib/test/filename_SUITE.erl @@ -25,7 +25,7 @@ -export([pathtype/1,rootname/1,split/1,find_src/1]). -export([absname_bin/1, absname_bin_2/1, basename_bin_1/1, basename_bin_2/1, - dirname_bin/1, extension_bin/1, join_bin/1]). + dirname_bin/1, extension_bin/1, join_bin/1, t_nativename_bin/1]). -export([pathtype_bin/1,rootname_bin/1,split_bin/1]). -include_lib("test_server/include/test_server.hrl"). @@ -38,7 +38,7 @@ all() -> join, pathtype, rootname, split, t_nativename, find_src, absname_bin, absname_bin_2, basename_bin_1, basename_bin_2, dirname_bin, extension_bin, - join_bin, pathtype_bin, rootname_bin, split_bin]. + join_bin, pathtype_bin, rootname_bin, split_bin, t_nativename_bin]. groups() -> []. @@ -804,3 +804,14 @@ split_bin(Config) when is_list(Config) -> ok end. +t_nativename_bin(Config) when is_list(Config) -> + ?line <<"abcedf">> = filename:nativename(<<"abcedf">>), + case os:type() of + {win32, _} -> + ?line <<"a:\\temp\\arne.exe">> = + filename:nativename(<<"A:/temp//arne.exe/">>); + _ -> + ?line <<"/usr/tmp/arne">> = + filename:nativename(<<"/usr/tmp//arne/">>) + end. + diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl index 1e74ad7727..192268f90e 100644 --- a/lib/stdlib/test/qlc_SUITE.erl +++ b/lib/stdlib/test/qlc_SUITE.erl @@ -2969,12 +2969,14 @@ lookup1(Config) when is_list(Config) -> [3] = lookup_keys(Q) end, [{1,a},{3,3}])">>, + {cres, <<"A = 3, etsc(fun(E) -> Q = qlc:q([X || X <- ets:table(E), A =:= {erlang,element}(1, X)]), [{3,3}] = qlc:e(Q), [3] = lookup_keys(Q) end, [{1,a},{3,3}])">>, + {warnings,[{3,erl_lint,deprecated_tuple_fun}]}}, <<"etsc(fun(E) -> A = 3, @@ -3439,12 +3441,14 @@ lookup2(Config) when is_list(Config) -> [r] = qlc:e(Q), [r] = lookup_keys(Q) end, [{keypos,1}], [#r{}])">>, + {cres, <<"etsc(fun(E) -> Q = qlc:q([element(1, X) || X <- ets:table(E), {erlang,is_record}(X, r, 2)]), [r] = qlc:e(Q), [r] = lookup_keys(Q) end, [{keypos,1}], [#r{}])">>, + {warnings,[{4,erl_lint,deprecated_tuple_fun}]}}, {cres, <<"etsc(fun(E) -> Q = qlc:q([element(1, X) || X <- ets:table(E), @@ -3465,12 +3469,14 @@ lookup2(Config) when is_list(Config) -> [r] = qlc:e(Q), [r] = lookup_keys(Q) end, [{keypos,1}], [#r{}])">>, + {cres, <<"etsc(fun(E) -> Q = qlc:q([element(1, X) || X <- ets:table(E), {erlang,is_record}(X, r)]), [r] = qlc:e(Q), [r] = lookup_keys(Q) - end, [{keypos,1}], [#r{}])">> + end, [{keypos,1}], [#r{}])">>, + {warnings,[{4,erl_lint,deprecated_tuple_fun}]}} ], ?line run(Config, <<"-record(r, {a}).\n">>, TsR), |