From: chas w. <ch...@us...> - 2009-08-03 20:37:07
|
Update of /cvsroot/linux-atm/linux-atm/src/q2931 In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv4419/src/q2931 Added Files: Tag: V2_5_1 .cvsignore Makefile.am TODO incl.pl mknl.pl msg.fmt op.h qlib.c qlib.h qtest.c uni.h Log Message: in order to make cross compling more sane and easier to follow, we split qgen (which is the only program that needs to be built and run on the host system) into qgen and q2931. so qgen now contains only host system binaries and as such doesnt need HAVE_CONFIG_H since that is really meant for the target system. also added the CFLAGS_FOR_BUILD flag that overrides CFLAGS in src/qgen. automake complains about this but i dont see a better way really unless i rewrite COMPILE. --- NEW FILE: .cvsignore --- Makefile Makefile.in .deps .libs default.nl q.out.c q.out.h qd.dump.c qd.out.c qd.out.h q.test.c qd.test.c q.dump --- NEW FILE: Makefile.am --- noinst_PROGRAMS = q.dump check_PROGRAMS = q.test q_dump_SOURCES = q_dump_LDADD = qd.dump.standalone.o # FIXME: paulsch: We don't really depend on qd.dump.o or q.out.o here, but this # trick will get it built with only a minor glitch in the dependency checking # for q.dump. q_dump_DEPENDENCIES = $(q_dump_LDADD) qd.dump.o q.out.o EXTRA_q_dump_SOURCES = op.h uni.h qlib.c qlib.h q_test_SOURCES = qtest.c uni.h q_test_DEPENDENCIES = q.test.c #TESTS = $(check_PROGRAMS) EXTRA_DIST = incl.pl mknl.pl msg.fmt TODO CLEANFILES = q.out.h q.out.c q.test.c qd.out.h qd.out.c qd.dump.c qd.test.c \ default.nl NLS = atm_ai_msg atm_ai_ie atm_loc atm_cv atm_pu atm_na atm_cond atm_ie \ atm_msg atm_np atm_ton atm_sat atm_prs atm_scrn atm_vpa atm_poe \ q2931_cs atm_td atm_bc atm_tc atm_stc atm_upcc q2931_proto atm_flag \ atm_aalp atm_fd atm_tag atm_l2 atm_l3 atm_tt atm_mc atm_hl atm_imd \ atm_tdl atm_tni atm_nip atm_shi atm_oci atm_unfm atm_ofi atm_irs \ atm_it atm_lit atm_lsi atm_tcs atm_css atm_eqo atm_eqp atm_aap \ atm_asp atm_tor SYMFILES = $(srcdir)/uni.h $(shell @PERL@ $(srcdir)/incl.pl $(CFLAGS) linux/atmsap.h) default.nl: mknl.pl $(SYMFILES) cat $(SYMFILES) | @PERL@ $(srcdir)/mknl.pl $(NLS) >default.nl || \ { rm -f default.nl; echo 1; } q.out.h q.out.c q.test.c: msg.fmt default.nl $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) - < $(srcdir)/msg.fmt | ../qgen/qgen qd.out.h qd.out.c qd.dump.c: msg.fmt default.nl $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) - < $(srcdir)/msg.fmt | ../qgen/qgen -D q.out.o: q.out.c q.out.h qlib.c qlib.h $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(TARGET_CFLAGS) -c q.out.c qd.dump.o: qd.dump.c qd.out.c qlib.c qlib.h $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(TARGET_CFLAGS) -c qd.dump.c qd.dump.standalone.o: qd.dump.c qd.out.c qlib.c qlib.h $(CC) $(DEFS) $(DEFAULT_INCLUDES) -DSTANDALONE $(INCLUDES) $(CFLAGS) -c qd.dump.c \ -o qd.dump.standalone.o --- NEW FILE: TODO --- - handle repeated IEs - q_assign should remove old value (i.e. zero destination) - bit numbering is wrong; should be <size@high> - should be library (well, need at least more flexible name selection) - copies of adjacent fields should be merged - copies of partial bytes should be byte-wide if rest is only zeroes - should be able to have multiple selectors in one byte - case/default needs better compile-time check - parser shouldn't copy unnamed fields - optimize - code needs a lot of cleaning Restrictions ------------ - there's only very limited error checking - no support for arrays (repeated IEs) - copy operations are not optimized --- NEW FILE: incl.pl --- #!/usr/bin/perl # # Find include files. # # usage: incl.pl ... [-nostdinc] ... [-I dir] ... file ... # # -Idir and -I dir are equivalent, argument order doesn't matter, but # file may be mis-detected if other options follow. # @STD = ("/usr/include","/usr/local/include"); while (@ARGV) { $arg = shift @ARGV; if ($arg eq "-nostdinc") { undef @STD; } if ($arg =~ /-I/) { if ($' ne "") { push(@USR,$'); } else { push(@USR,shift @ARGV); } next; } next if $arg =~ /^-/; next if $arg =~ /\.h$/ && defined $last; $last = $arg; } die "no include file specified" unless defined $last; for (@STD,@USR) { next unless defined stat $_."/".$last; print $_."/".$last."\n" || die "print STDOUT: $!"; exit 0; } die "$last not found"; --- NEW FILE: mknl.pl --- #!/usr/bin/perl print "# THIS IS A MACHINE-GENERATED FILE. DO NOT EDIT !\n" || die "write: $!"; while ($line = <STDIN>) { chop($line); next unless $line =~ /^#define\s/; while ($line =~ m|/\*| && $line !~ m|\*/|) { $line .= <STDIN>; } $line =~ s/\s+/ /g; if (!defined($curr) || $line !~ /^#define ${curr}_/) { undef $curr; for (@ARGV) { ($tmp = $_) =~ tr/a-z/A-Z/; next unless $line =~ /^#define ${tmp}_/; $curr = $tmp; print "\n:$_\n" || die "write: $!"; last; } } next unless defined $curr; next unless $line =~ m|^#define (\S+) (\S+)( (/\*\s*(.*\S)\s*\*/))?|; # if (defined $3) { # print "$2=$1 $4\n" || die "write: $!"; # } if (defined $3) { print "$2=$2 \\\"$5\\\"\n" || die "write: $!"; } else { print "$2=$1\n" || die "write: $!"; } } --- NEW FILE: msg.fmt --- /* msg.fmt - Signaling message format decription for UNI 3.0, 3.1, and 4.0 */ /* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #undef linux /* grr ... */ include "atmsap.h" include "uni.h" #define VAR_STD_HDR(name,defl) \ _ext <1@8,more> = 1 \ name##_cs "q2931_cs" <2@6,more> = defl \ _flag "atm_flag" <1@5,more> = ATM_FLAG_NO \ _action_ind "atm_ai_ie" <3@1> = 0 /* only 2 bits in UNI 3.0 */ \ _ie_len <16> = recover RECOV_IND_IE length #define ITU_STD_HDR VAR_STD_HDR(,Q2931_CS_ITU) #define NET_STD_HDR VAR_STD_HDR(,Q2931_CS_NET) def ie_aal = { ITU_STD_HDR { aal_type <8> = case { 5 { _id "atm_aalp" <8> = multi { ATM_AALP_FW_MAX_SDU { fw_max_sdu <16> } ATM_AALP_BW_MAX_SDU { bw_max_sdu <16> } #if defined(UNI30) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI) ATM_AALP_AAL_MODE { aal_mode <8> # UNI 3.0 only } #endif ATM_AALP_SSCS { sscs_type <8> } } } } } } #define TRAFFIC_DESCRIPTOR_PCR(p) \ ATM_TD_FW_PCR_0 { p##fw_pcr_0 <24> } \ ATM_TD_BW_PCR_0 { p##bw_pcr_0 <24> } \ ATM_TD_FW_PCR_01 { p##fw_pcr_01 <24> } \ ATM_TD_BW_PCR_01 { p##bw_pcr_01 <24> } \ #define TRAFFIC_DESCRIPTOR_VBR(p) \ ATM_TD_FW_SCR_0 { p##fw_scr_0 <24> } \ ATM_TD_BW_SCR_0 { p##bw_scr_0 <24> } \ ATM_TD_FW_SCR_01 { p##fw_scr_01 <24> } \ ATM_TD_BW_SCR_01 { p##bw_scr_01 <24> } \ ATM_TD_FW_MBS_0 { p##fw_mbs_0 <24> } \ ATM_TD_BW_MBS_0 { p##bw_mbs_0 <24> } \ ATM_TD_FW_MBS_01 { p##fw_mbs_01 <24> } \ ATM_TD_BW_MBS_01 { p##bw_mbs_01 <24> } \ #define TRAFFIC_DESCRIPTOR_BE(p) \ ATM_TD_BEST_EFFORT { p##best_effort <0> } \ #if defined(UNI40) || defined(DYNAMIC_UNI) #define TRAFFIC_DESCRIPTOR_ABR(p) \ ATM_TD_FW_MCR_01 { p##fw_mcr_01 <24> } \ ATM_TD_BW_MCR_01 { p##bw_mcr_01 <24> } \ #else #define TRAFFIC_DESCRIPTOR_ABR(p) /* not yet */ #endif #define TRAFFIC_DESCRIPTOR(p) \ TRAFFIC_DESCRIPTOR_PCR(p) \ TRAFFIC_DESCRIPTOR_VBR(p) \ TRAFFIC_DESCRIPTOR_BE(p) #ifdef NOT_YET TRAFFIC_DESCRIPTOR_ABR(p) #endif def ie_td = { # UNI 3.0 calls this "User Cell Rate" ITU_STD_HDR { _id "atm_td" <8> = multi { TRAFFIC_DESCRIPTOR() ATM_TD_TM_OPT { # @@@ should this also go into the TD macro ? #if defined(UNI40) || defined(DYNAMIC_UNI) fw_fdisc "atm_fd" <1@8,more> = ATM_FD_NO bw_fdisc "atm_fd" <1@7,more> = ATM_FD_NO #endif bw_tag "atm_tag" <1@2,more> = ATM_TAG_NO fw_tag "atm_tag" <1@1> = ATM_TAG_NO } } } } def ie_bbcap = { ITU_STD_HDR { bearer_class "atm_bc" <5@1,more> _ext <1@8> = case { 0 { _ext <1@8,more> = 1 trans_cap "atm_tc" <7@1> } default 1 {} } _ext <1@8,more> = 1 susc_clip "atm_stc" <2@6,more> = ATM_STC_NO upcc "atm_upcc" <2@1> = ATM_UPCC_P2P } } def ie_bhli = { ITU_STD_HDR { _ext <1@8,more> = 1 hli_type <7@1> = case { /* Note: cannot use ATM_HL_* here, because those values are incremented by one to keep zero available for ATM_HL_NONE */ 0 { # ISO iso_hli <-64> } 1 { # User Specific user_hli <-64> } #if defined(UNI30) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI) 2 { # High layer profile - UNI 3.0 only hlp <32> } #endif 3 { # Vendor-Specific Application identifier hli_oui <24> app_id <32> } #if defined(UNI40) || defined(DYNAMIC_UNI) 4 { # Reference to ITU-T SG 1 B-ISDN Teleservice Recommendation tobedefined <8> } #endif } } } def ie_blli = { ITU_STD_HDR { _lid <2@6,more> = multi { 1 { _ext <1@8,more> = 1 uil1_proto <5@1> } 2 { uil2_proto "atm_l2" <5@1,more> = case { ATM_L2_X25_LL,ATM_L2_X25_ML,ATM_L2_HDLC_ARM, ATM_L2_HDLC_NRM,ATM_L2_HDLC_ABM,ATM_L2_Q922, ATM_L2_ISO7776 { # CCITT encoding _ext <1@8> = case { 0 { l2_mode "atm_imd" <2@6,more> = ATM_IMD_NORMAL q933 <2@1,more> = 0 _ext <1@8> = case { 0 { window_size <7@1,more> _ext <1@8> = 1 } default 1 {} } } default 1 {} } } ATM_L2_USER { # User specified _ext <1@8> = 0 user_l2 <7@1,more> _ext <1@8> = 1 } default ATM_L2_ISO1745,ATM_L2_Q291,ATM_L2_LAPB, ATM_L2_ISO8802,ATM_L2_X75 { # No additional data _ext <1@8> = 1 } } } 3 { uil3_proto "atm_l3" <5@1,more> = case { ATM_L3_X25,ATM_L3_ISO8208,ATM_L3_X223 { # CCITT coding _ext <1@8> = case { 0 { l3_mode "atm_imd" <2@6,more> = ATM_IMD_NORMAL _ext <1@8> = case { 0 { def_pck_size <4@1,more> _ext <1@8> = case { 0 { _ext <1@8> = 1 pck_win_size <7@1> } default 1 {} } } default 1 {} } } default 1 {} } } #if defined(UNI40) || defined(DYNAMIC_UNI) ATM_L3_H310 { # ITU-T Rec. H.310 _ext <1@8> = case { 0 { term_type "atm_tt" <4@1,more> = ATM_TT_RXTX _ext <1@8> = case { 0 { _ext <1@8,more> = 1 fw_mpx_cap "atm_mc" <3@4,more> = ATM_MC_NONE bw_mpx_cap "atm_mc" <3@1> = ATM_MC_NONE } default 1 {} } } default 1 {} } } #endif ATM_L3_TR9577 { # ISO/IEC TR9577 _ext <1@8> = case { 0 { _ext <1@8,more> = 0 ipi_high <7@1> = case { 0x40 { # SNAP hack _ext <1@8,more> = 1 _ipi_low <1@7> = case { # ugly 0 { _ext <1@8,more> = 1 _snap_id <2@6> = 0 oui <24> pid <16> } default 1 {} } } default 0x0 { # ugly _ext <1@8,more> = 1 ipi_low <1@7> } } } default 1 {} } } ATM_L3_USER { # User specified _ext <1@8> = 0 user_l3 <7@1,more> _ext <1@8> = 1 } } } } } } def ie_call_state = { ITU_STD_HDR { call_state <6@1> } } def ie_cdpn = { ITU_STD_HDR { _ext <1@8,more> = 1 _plan "atm_np" <4@1,more> = case { ATM_NP_E164 { _type "atm_ton" <3@5> = ATM_TON_INTRNTNL cdpn_e164 <-96> } ATM_NP_AEA { # ATM Endsystem Address _type "atm_ton" <3@5> = ATM_TON_UNKNOWN cdpn_esa <-160> } } } } def ie_cdps = { ITU_STD_HDR { _ext <1@8,more> = 1 #ifdef UNI30 _type "atm_sat" <3@5,more> = ATM_SAT_AEA #endif #if defined(UNI31) || defined(DYNAMIC_UNI) cdps_type "atm_sat" <3@5,more> = ATM_SAT_AEA #endif _oddeven <1@4> = 0 cdps <-160> } } def ie_cgpn = { # @@@ extend language to allow same trick as for cdpn ITU_STD_HDR { cgpn_plan "atm_np" <4@1,more> cgpn_type "atm_ton" <3@5,more> _ext <1@8> = case { 0 { _ext <1@8,more> = 1 pres_ind "atm_prs" <2@6,more> = ATM_PRS_ALLOW scr_ind "atm_scrn" <2@1> = ATM_SCRN_UP_NS } default 1 {} } cgpn <-160> } } def ie_cgps = { ITU_STD_HDR { _ext <1@8,more> = 1 #ifdef UNI30 _type "atm_sat" <3@5,more> = ATM_SAT_AEA #endif #if defined(UNI31) || defined(DYNAMIC_UNI) cgps_type "atm_sat" <3@5,more> = ATM_SAT_AEA #endif _oddeven <1@4> = 0 cgps <-160> } } def ie_cause = { VAR_STD_HDR(cause,Q2931_CS_ITU) { _ext <1@8,more> = 1 location "atm_loc" <4@1> = ATM_LOC_USER _ext <1@8,more> = 1 cause "atm_cv" <7@1> = case { ATM_CV_UNALLOC,ATM_CV_NO_ROUTE_DEST,ATM_CV_QOS_UNAVAIL { # Note 2 break _ext <1@8,more> = 1 pu "atm_pu" <1@4,more> = ATM_PU_USER na "atm_na" <1@3,more> = ATM_NA_NORMAL cond2 "atm_cond" <2@1> = ATM_COND_UNKNOWN } ATM_CV_CALL_REJ { # Note 3 break _ext <1@8,more> = 1 cond3 "atm_cond" <2@1,more> = ATM_COND_UNKNOWN reason <5@3> = case { ATM_RSN_USER { user_diag <-216> } ATM_RSN_IE_MISS,ATM_RSN_IE_INSUFF { ie_id3 "atm_ie" <8> } } } ATM_CV_NUM_CHANGED { # Note 4 break new_dest <-224> # good luck ... } ATM_CV_REJ_CLIR { # Note 5 break invalid <8> # not supported } ATM_CV_ACC_INF_DISC,ATM_CV_INCOMP_DEST,ATM_CV_MAND_IE_MISSING, ATM_CV_UNKNOWN_IE,ATM_CV_INVALID_IE { # Note 6 break ie_id6 <-224> } #if defined(DYNAMIC_UNI) || defined(ALLOW_UNI30) ATM_CV_UCR_UNAVAIL_OLD,ATM_CV_UCR_UNAVAIL_NEW { # Note 8 #else #ifdef UNI30 ATM_CV_UCR_UNAVAIL_OLD { # Note 8 #else ATM_CV_UCR_UNAVAIL_NEW { # Note 8 #endif #endif break ucr_id <-224> } ATM_CV_NO_SUCH_CHAN { # Note 9 break unav_vpci <16> unav_vci <16> } ATM_CV_UNKNOWN_MSG_TYPE,ATM_CV_INCOMP_MSG { # Note 10 break bad_msg_type "atm_msg" <8> } ATM_CV_TIMER_EXP { # Note 11 break timer <24> } default 0 {} } } } def ie_conn_id = { ITU_STD_HDR { _ext <1@8,more> = 1 _vp_ass "atm_vpa" <2@4,more> = ATM_VPA_EXPL /* explicit */ _pref_exc "atm_poe" <3@1> = 0 vpi <16> vci <16> } } #if defined(UNI40) || defined(DYNAMIC_UNI) def ie_e2e_tdl = { ITU_STD_HDR { _id "atm_tdl" <8> = multi { ATM_TDL_CUM { cum_delay <16> } ATM_TDL_E2EMAX { max_delay <16> } ATM_TDL_NGI {} } } } #endif def ie_qos = { #if defined(UNI30) && !defined(DYNAMIC_UNI) NET_STD_HDR { #else /* * Depending on what values are put into qos_fw and qos_bw, this may * still be invalid. But at least the defaults should be okay. Note * that defining UNI30 and UNI31 together yields only the UNI30 * behaviour. We assume that everybody who implements UNI 3.1 today * has a similar kludge in their networking code, so we should get * away with that. */ VAR_STD_HDR(qos,Q2931_CS_NET) { #endif qos_fw <8> = 0 qos_bw <8> = 0 } } def ie_bbrep = { ITU_STD_HDR { _ext <1@8,more> = 1 rep_ind <4@1> = 2 } } def ie_restart = { ITU_STD_HDR { _ext <1@8,more> = 1 rst_class <3@1> } } def ie_bbs_comp = { ITU_STD_HDR { _ext <1@8,more> = 1 bbsc_ind <7@1> = 0x21 } } def ie_tns = { ITU_STD_HDR { _ext <1@8,more> = 1 _net_type "atm_tni" <3@5,more> = ATM_TNI_NNI /* @@@ default ? */ _carrier_id "atm_nip" <4@1> = ATM_NIP_CARRIER /* @@@ default ? */ net_id <-32> } } #if defined(UNI40) || defined(DYNAMIC_UNI) def ie_notify = { ITU_STD_HDR { notification <-32> # @@@ how many actually ? } } def ie_oam_td = { ITU_STD_HDR { _ext <1@8,more> = 1 shaping "atm_shi" <2@6,more> = ATM_SHI_NONE compliance "atm_oci" <1@5,more> = ATM_OCI_OPT fault "atm_unfm" <3@1> = ATM_UNFM_NONE _ext <1@8,more> = 1 fwd_ofi "atm_ofi" <3@5,more> = ATM_OFI_0_0 bwd_ofi "atm_ofi" <3@1> = ATM_OFI_0_0 } } def ie_git = { NET_STD_HDR { # @@@ UNI 4.0 does not specify the coding _dummy <1@8> = 0 # bit is "spare", although not indicated in spec id_std_app "atm_irs" <7@1> = case { ATM_IRS_DSMCC,ATM_IRS_H245 { _type "atm_it" <8> = ATM_IT_SESSION _length <8> = length { session_id <-160> } _type "atm_it" <8> = ATM_IT_RESOURCE _length <8> = length { resource_id <-32> } } default 0 { unrecognized_git_identifiers <-224> # 33-5 bytes } } } } def ie_lij_id = { NET_STD_HDR { # @@@ UNI 4.0 does not specify the coding _ext <1@8,more> = 1 lij_id_type "atm_lit" <7@1> = ATM_LIT_ROOT lij_id <32> } } def ie_lij_prm = { NET_STD_HDR { # @@@ UNI 4.0 does not specify the coding _ext <1@8,more> = 1 lij_scr_ind "atm_lsi" <2@1> } } def ie_leaf_sn = { NET_STD_HDR { # @@@ UNI 4.0 does not specify the coding leaf_sn <32> } } def ie_scope_sel = { NET_STD_HDR { # @@@ UNI 4.0 does not specify the coding _ext <1@8,more> = 1 scope_type "atm_tcs" <4@1> = ATM_TCS_ORGANIZATIONAL scope_sel "atm_css" <8> } } def ie_alt_td = { ITU_STD_HDR { _id "atm_td" <8> = multi { TRAFFIC_DESCRIPTOR(alt) } } } def ie_min_td = { NET_STD_HDR { # @@@ UNI 4.0 does not specify the coding _id "atm_td" <8> = multi { TRAFFIC_DESCRIPTOR_PCR(min) TRAFFIC_DESCRIPTOR_ABR(min) } } } def ie_eqos = { NET_STD_HDR { eqos_origin "atm_eqo" <8> _id "atm_eqp" <8> = multi { ATM_EQP_ACC_FW_CDV { acc_fw_cdv <24> } ATM_EQP_ACC_BW_CDV { acc_bw_cdv <24> } ATM_EQP_CUM_FW_CDV { cum_fw_cdv <24> } ATM_EQP_CUM_BW_CDV { cum_bw_cdv <24> } ATM_EQP_ACC_FW_CLR { acc_fw_clr <8> } ATM_EQP_ACC_BW_CLR { acc_bw_clr <8> } } } } def ie_abr_add_prm = { NET_STD_HDR { _id "atm_aap" <8> = multi { ATM_AAP_FW_REC { abr_fw_add_rec <32> } ATM_AAP_BW_REC { abr_bw_add_rec <32> } } } } def ie_abr_set_prm = { NET_STD_HDR { # @@@ UNI 4.0 does not specify the coding _id "atm_asp" <8> = multi { ATM_ASP_FW_ICR { abr_fw_icr <24> } ATM_ASP_BW_ICR { abr_bw_icr <24> } ATM_ASP_FW_TBE { abr_fw_tbe <24> } ATM_ASP_BW_TBE { abr_bw_tbe <24> } ATM_ASP_CRF_RTT { atm_crf_rtt <24> } ATM_ASP_FW_RIF { atm_fw_rif <8> } ATM_ASP_BW_RIF { atm_bw_rif <8> } ATM_ASP_FW_RDF { atm_fw_rdf <8> } ATM_ASP_BW_RDF { atm_bw_rdf <8> } } } } #endif def ie_ep_ref = { ITU_STD_HDR { _ep_type <8> = 0 ep_ref <16> } } def ie_ep_state = { ITU_STD_HDR { ep_state <6@1> } } #if defined(Q2963_1) || defined(DYNAMIC_UNI) def ie_bbrt = { ITU_STD_HDR { type_of_report "atm_tor" <8> } } #endif { _pdsc "q2931_proto" <8> = Q2931_PROTO_DSC _cr_len <8> = 3 call_ref <24> msg_type "atm_msg" <8> _ext <1@8,more> = 1 _flag "atm_flag" <1@5,more> = ATM_FLAG_NO _action_ind "atm_ai_msg" <2@1> = 0 msg_len <16> = length { _ie_id "atm_ie" <8> = multi { aal: ATM_IE_AAL ie_aal td: ATM_IE_TD ie_td bbcap: ATM_IE_BBCAP ie_bbcap bhli: ATM_IE_BHLI ie_bhli blli1: ATM_IE_BLLI ie_blli blli2: ATM_IE_BLLI ie_blli blli3: ATM_IE_BLLI ie_blli call_state: ATM_IE_CALL_STATE ie_call_state cdpn: ATM_IE_CDPN ie_cdpn cdps: ATM_IE_CDPS ie_cdps cgpn: ATM_IE_CGPN ie_cgpn cgps: ATM_IE_CGPS ie_cgps cause: ATM_IE_CAUSE ie_cause cause2: ATM_IE_CAUSE ie_cause conn_id: ATM_IE_CONN_ID ie_conn_id #if defined(UNI40) || defined(DYNAMIC_UNI) e2e_tdl: ATM_IE_E2E_TDL ie_e2e_tdl #endif qos: ATM_IE_QOS ie_qos bbrep: ATM_IE_BBREP ie_bbrep restart: ATM_IE_RESTART ie_restart bbs_comp: ATM_IE_BBS_COMP ie_bbs_comp tns: ATM_IE_TNS ie_tns #if defined(UNI40) || defined(DYNAMIC_UNI) notify: ATM_IE_NOTIFY ie_notify oam_td: ATM_IE_OAM_TD ie_oam_td git: ATM_IE_GIT ie_git git2: ATM_IE_GIT ie_git git3: ATM_IE_GIT ie_git lij_id: ATM_IE_LIJ_ID ie_lij_id lij_prm: ATM_IE_LIJ_PRM ie_lij_prm leaf_sn: ATM_IE_LEAF_SN ie_leaf_sn scope_sel: ATM_IE_SCOPE_SEL ie_scope_sel alt_td: ATM_IE_ALT_TD ie_alt_td min_td: ATM_IE_MIN_TD ie_min_td eqos: ATM_IE_EQOS ie_eqos abr_add_prm:ATM_IE_ABR_ADD_PRM ie_abr_add_prm abr_set_prm:ATM_IE_ABR_SET_PRM ie_abr_set_prm #endif ep_ref: ATM_IE_EPR ie_ep_ref ep_state: ATM_IE_EP_STATE ie_ep_state #if defined(Q2963_1) || defined(DYNAMIC_UNI) bbrt: ATM_IE_BBRT ie_bbrt #endif default 0 { VAR_STD_HDR(_,0) abort RECOV_ASE_UNKNOWN_IE } } } } --- NEW FILE: op.h --- /* op.h - message processor opcodes */ /* Written 1995,1996 by Werner Almesberger, EPFL-LRC */ #ifndef OP_H #define OP_H /* construction */ #define OP_INVALID 0 /* crash here */ #define OP_COPY 1 /* copy <jump>,<src>,<size> */ #define OP_COPYVAR 2 /* copy <index>,<src>,<maxsize(bytes)> */ #define OP_BEGIN_LEN 3 /* begin_length <jump>,<src>,<size> */ #define OP_END_LEN 4 /* end_length */ #if 0 #define OP_CASE 4 /* case <groups>, { <group>,<offset>,... { <op>,..., jump }, ... } */ #endif #define OP_JUMP 5 /* jump <addr> */ #define OP_END 6 /* end */ #define OP_IFGROUP 7 /* ifgroup <group>,<jump> */ /* parsing */ #define OP_MULTI 8 /* multi <size>,case,... */ #define OP_CASE 9 /* case <jump>,<src>,<size>,<groups>, { <pattern>, <group>,<offset>,... { <op>,...,jump }, ... } */ #define OP_IFEND 10 /* ifend <addr> */ #define OP_DUMP 11 /* dump <index>; dumper only */ #define OP_BEGIN_REC 12 /* begin_recovery <id>,<group>,<addr> */ #define OP_END_REC 13 /* end_recovery */ #define OP_ABORT 14 /* abort <id> */ #endif --- NEW FILE: qlib.c --- /* qlib.c - run-time library */ /* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #ifdef DUMP_MODE static int q_dump = 0; #else int q_dump = 0; #endif #ifndef STANDALONE #define DUMP qd_dump #else #define DUMP printf #include <stdarg.h> #include <stdio.h> #include <unistd.h> #include "qlib.h" #include "op.h" int debug = 0; void PREFIX(report)(int severity,const char *msg,...) { va_list ap; if (!debug && severity > Q_ERROR) return; va_start(ap,msg); vprintf(msg,ap); printf("\n"); va_end(ap); if (severity == Q_FATAL) exit(1); } #endif #define LENGTH_STACK 10 #define LENGTH_R_STACK 5 typedef struct { int pos,size; unsigned char *start; } LEN_BUF; typedef struct _rstack { int *pc; int sp; unsigned char *pos; unsigned char *end; struct _rstack *next; } RSTACK; static int q_test(unsigned char *table,int pos) { return !!(table[pos >> 3] & (1 << (pos & 7))); } static void q_set(unsigned char *table,int pos) { table[pos >> 3] |= 1 << (pos & 7); } static void q_clear(unsigned char *table,int pos) { table[pos >> 3] &= ~(1 << (pos & 7)); } /* slightly ugly */ static void q_put(unsigned char *table,int pos,int size,unsigned long value) { int end; PREFIX(report)(Q_DEBUG,"put %d %d %ld",pos,size,value); end = pos+size; if (((pos | size) & 7) && ((pos ^ (end-1)) & ~7)) PREFIX(report)(Q_FATAL,"unsupported alignment (put %d,%d)",pos,size); if (size <= 8) { unsigned char *here; int shift; here = &table[pos >> 3]; shift = pos & 7; *here = (*here & ~(((1 << size)-1) << shift)) | value << shift; } else { table = table+end/8-1; while (size > 0) { *table-- = value; value >>= 8; size -= 8; } } } static unsigned long q_get(unsigned char *table,int pos,int size) { unsigned long value; int end; PREFIX(report)(Q_DEBUG,"get %d %d ...",pos,size); end = pos+size; if (((pos | size) & 7) && ((pos ^ (end-1)) & ~7)) PREFIX(report)(Q_FATAL,"unsupported alignment (get %d,%d)",pos,size); if (size <= 8) value = (table[pos >> 3] >> (pos & 7)) & ((1 << size)-1); else { table += pos >> 3; value = 0; while (size > 0) { value = (value << 8) | *table++; size -= 8; } } PREFIX(report)(Q_DEBUG," %ld",value); return value; } static void q_copy(unsigned char *src,int pos,unsigned char *dst,int size) { src += pos >> 3; pos &= 7; if (pos+size <= 8) *dst |= *src & (((1 << size)-1) << pos); else { if (pos) { *dst++ |= *src++ & (0xff << pos); size -= 8-pos; } while (size >= 8) { *dst++ = *src++; size -= 8; } if (size > 0) *dst |= *src & ((1 << size)-1); } } void PREFIX(start)(void) { q_init_global(); } static int q_init(Q_DSC *dsc) { size_t bytes; int i; /* initialize verything in case anything goes wrong during allocations. */ dsc->errors = NULL; dsc->field_present = NULL; dsc->group_present = NULL; dsc->data = NULL; dsc->required = NULL; dsc->length = NULL; dsc->field_map = NULL; dsc->group_map = NULL; dsc->data = malloc((size_t) Q_DATA_BYTES); dsc->error = 1; if (!dsc->data) { perror("out of memory"); return -1; } memcpy(dsc->data,q_initial,Q_DATA_BYTES); bytes = (Q_FIELDS+7) >> 3; dsc->required = malloc(bytes); if (!dsc->required) { perror("out of memory"); return -1; } memset(dsc->required,0,bytes); dsc->field_present = malloc(bytes); if (!dsc->field_present) { perror("out of memory"); return -1; } memset(dsc->field_present,0,bytes); bytes = (Q_GROUPS+(sizeof(unsigned long)*8-1)) >> 3; dsc->group_present = malloc(bytes); if (!dsc->group_present) { perror("out of memory"); return -1; } memset(dsc->group_present,0,bytes); if (!Q_VARLEN_FIELDS) dsc->length = NULL; else { dsc->length = malloc(sizeof(int)*Q_VARLEN_FIELDS); if (!dsc->length) { perror("out of memory"); return -1; } memset(dsc->length,0,sizeof(int)*Q_VARLEN_FIELDS); } dsc->field_map = malloc(sizeof(int)*Q_FIELDS); if (!dsc->field_map) { perror("out of memory"); return -1; } for (i = 0; i < Q_FIELDS; i++) dsc->field_map[i] = i; dsc->group_map = malloc(sizeof(int)*Q_GROUPS); if (!dsc->group_map) { perror("out of memory"); return -1; } for (i = 0; i < Q_GROUPS; i++) dsc->group_map[i] = i; dsc->error = 0; return 0; } #ifndef DUMP_MODE static void use_group(Q_DSC *dsc,int group) { int *scan; while (group != -1) { q_set((unsigned char *) dsc->group_present,group); for (scan = groups[group].required; scan && *scan != -1; scan++) q_set(dsc->required,*scan); group = groups[group].parent; } } void q_assign(Q_DSC *dsc,int field,unsigned long value) { int *walk; if (field < 0 || field >= Q_FIELDS) PREFIX(report)(Q_FATAL,"invalid field value (%d)",field); field = dsc->field_map[field]; if (!fields[field].values) { if (q_test(dsc->field_present,field)) /* probably an error ... */ PREFIX(report)(Q_ERROR,"changing field %d",field); q_set(dsc->field_present,field); q_put(dsc->data,fields[field].pos,fields[field].size,value); use_group(dsc,fields[field].parent); } else { if (q_test(dsc->field_present,field)) PREFIX(report)(Q_FATAL,"can't change field %d",field); q_set(dsc->field_present,field); q_put(dsc->data,fields[field].pos,fields[field].size,value); for (walk = fields[field].values; walk[1] != -1; walk += 2) if (*walk == value || *walk == -2) { use_group(dsc,walk[1]); return; } PREFIX(report)(Q_ERROR,"invalid value (%d in field %d)",value,field); dsc->error = 1; } } void q_write(Q_DSC *dsc,int field,const void *buf,int size) { if (field < 0 || field >= Q_FIELDS) PREFIX(report)(Q_FATAL,"invalid field value (%d)",field); field = dsc->field_map[field]; if (fields[field].pos & 7) PREFIX(report)(Q_FATAL,"invalid use of q_write (%d)",field); if (fields[field].actual >= 0) { if (size > fields[field].size/8) { PREFIX(report)(Q_ERROR,"%d bytes too big for %d byte field %d", size,fields[field].size/8,field); dsc->error = 1; return; } dsc->length[fields[field].actual] = size; } else if ((fields[field].pos | fields[field].size) & 7) PREFIX(report)(Q_FATAL,"field %d is neither var-len nor " "well-shaped",field); memcpy(dsc->data+(fields[field].pos/8),buf,(size_t) size); q_set(dsc->field_present,field); use_group(dsc,fields[field].parent); } int q_present(const Q_DSC *dsc,int field) { if (field < 0) { if (field < -Q_GROUPS) PREFIX(report)(Q_FATAL,"invalid group number (%d)",field); if (!dsc->group_present) return 0; field = dsc->group_map[-field-1]; return q_test((unsigned char *) dsc->group_present,field); } else { if (field >= Q_FIELDS) PREFIX(report)(Q_FATAL,"invalid field number (%d)",field); if (!dsc->field_present) return 0; field = dsc->field_map[field]; if (q_test(dsc->field_present,field)) return 1; return q_test((unsigned char *) dsc->group_present, fields[field].parent); } } unsigned long q_fetch(const Q_DSC *dsc,int field) { if (field < 0 || field >= Q_FIELDS) PREFIX(report)(Q_FATAL,"invalid field value (%d)",field); field = dsc->field_map[field]; return q_get(dsc->data,fields[field].pos,fields[field].size); } int q_length(const Q_DSC *dsc,int field) { if (field < 0 || field >= Q_FIELDS) PREFIX(report)(Q_FATAL,"invalid field value (%d)",field); field = dsc->field_map[field]; if (fields[field].pos & 7) PREFIX(report)(Q_FATAL,"invalid use of q_length (%d)",field); if (fields[field].actual < 0) PREFIX(report)(Q_FATAL,"field %d is not var-len",field); return dsc->length[fields[field].actual]; } int q_read(Q_DSC *dsc,int field,void *buf,int size) { int len; len = 0; /* for gcc */ if (field < 0 || field >= Q_FIELDS) PREFIX(report)(Q_FATAL,"invalid field value (%d)",field); field = dsc->field_map[field]; if (fields[field].pos & 7) PREFIX(report)(Q_FATAL,"invalid use of q_read (%d)",field); if (fields[field].actual >= 0) len = dsc->length[fields[field].actual]; else if (!(fields[field].size & 7)) len = fields[field].size >> 3; else PREFIX(report)(Q_FATAL,"field %d is not byte-sized (%d bits)", field,fields[field].size); if (size < len) { PREFIX(report)(Q_ERROR,"%d bytes too big for %d byte buffer (field " "%d)",len,size,field); dsc->error = 1; return -1; } memcpy(buf,dsc->data+(fields[field].pos/8),len); return len; } void q_instance(Q_DSC *dsc,int group) { int i; if (group >= 0 || group < -Q_GROUPS) PREFIX(report)(Q_FATAL,"invalid group number (%d)",group); if (groups[-group-1].start == -1) PREFIX(report)(Q_FATAL,"group %d is unique",group); for (i = 0; i < groups[-group-1].length; i++) dsc->field_map[groups[-group-1].start+i] = groups[-group-1].start+i+ groups[-group-1].offset; } static int q_compose(Q_DSC *dsc,unsigned char *buf,int size) { LEN_BUF stack[LENGTH_STACK]; unsigned char *pos; int *pc; int j,i,sp; for (i = 0; i < Q_FIELDS; i++) if (q_test(dsc->required,i) && !q_test(dsc->field_present,i)) PREFIX(report)(Q_ERROR,"required field %d is missing",i); memset(buf,0,(size_t) size); if (q_dump) for (j = 0; j < 100; j += 20) { fprintf(stderr,"%3d:",j); for (i = 0; i < 20; i++) fprintf(stderr," %02X",dsc->data[i+j]); putc('\n',stderr); } pos = buf; pc = construct; sp = 0; while (1) { PREFIX(report)(Q_DEBUG,"%d(%d):",pc-construct,pos-buf); switch (*pc++) { case OP_COPY: if (size < *pc) { PREFIX(report)(Q_ERROR,"not enough space (%d < %d)",size, *pc); dsc->error = 1; return -1; } PREFIX(report)(Q_DEBUG,"copy %d %d %d",pc[1],pos-buf,pc[2]); q_copy(dsc->data,pc[1],pos,pc[2]); if (q_dump) { for (i = 0; i < 50; i++) fprintf(stderr,"%02X ",buf[i]); putc('\n',stderr); } pos += *pc; size -= *pc; pc += 3; break; case OP_COPYVAR: if (size < dsc->length[*pc]) { PREFIX(report)(Q_ERROR,"not enough space (%d < %d)",size, dsc->length[*pc]); dsc->error = 1; return -1; } memcpy(pos,dsc->data+pc[1]/8,dsc->length[*pc]); pos += dsc->length[*pc]; size -= dsc->length[*pc]; pc += 3; break; case OP_BEGIN_LEN: if (size < *pc) { PREFIX(report)(Q_ERROR,"not enough space (%d < %d)",size, *pc); dsc->error = 1; return -1; } if (sp == LENGTH_STACK) { PREFIX(report)(Q_ERROR,"length stack overflow"); dsc->error = 1; return -1; } stack[sp].pos = pc[1]; /* not used */ stack[sp].size = pc[2]; stack[sp].start = pos; pos += *pc; /* allocate length here */ size -= *pc; sp++; pc += 3; break; case OP_END_LEN: if (!sp--) PREFIX(report)(Q_FATAL,"length stack underflow"); q_put(stack[sp].start,0,stack[sp].size, (size_t) ((pos-stack[sp].start)-((stack[sp].size+7) >> 3))); break; case OP_IFGROUP: if (q_test((unsigned char *) dsc->group_present,*pc++)) pc++; else pc += *pc+1; break; #if 0 case OP_CASE: { int len; for (len = *pc++; len; len--) if (!q_test((unsigned char *) dsc->group_present,*pc++)) pc++; else { pc += *pc+1; break; } if (!len) PREFIX(report)(Q_FATAL,"multi failed (pc %d)", pc-construct); } break; #endif case OP_JUMP: pc += *pc+1; break; case OP_END: return pos-buf; default: PREFIX(report)(Q_FATAL,"unrecognized opcode %d",pc[-1]); return -1; /* for gcc */ } } } #endif static const char *q_err_msg[] = { "???","not enough space (%d left)", "case failed (value 0x%x)","application-specific error (code %d)" }; /* * Rather messy ... too bad C doesn't have function-local functions ... */ static void handle_error(Q_DSC *dsc,int size,unsigned char *buf, unsigned char **stack,RSTACK *r_stack,int **pc,int *sp,int *rp, unsigned char **pos,unsigned char **end,Q_ERR_TYPE type,int value) { Q_ERR_DSC *error,**last; PREFIX(report)(Q_ERROR,q_err_msg[type],value); PREFIX(report)(Q_ERROR,"[ PC=%d SP=%d RP=%d, pos=%d end=%d ]",*pc-parse, *sp,*rp,*pos-buf,*end-buf); error = malloc(sizeof(Q_ERR_DSC)); if (!error) { perror("out of memory"); exit(0); } error->type = type; for (last = &dsc->errors; *last; last = &(*last)->next); *last = error; error->next = NULL; if (!pc) return; error->pc = *pc-parse; error->offset = *pos-buf; error->value = value; if (*rp) { (*rp)--; error->id = r_stack[*rp].pc[0]; error->start = r_stack[*rp].pos-buf; *sp = r_stack[*rp].sp; *pos = r_stack[*rp].end; error->length = *pos-r_stack[*rp].pos; error->group = r_stack[*rp].pc[1]; *pc = parse+r_stack[*rp].pc[2]; } else { error->id = 0; error->start = 0; error->length = size; error->group = 0; *sp = 0; *pc = parse+sizeof(parse)/sizeof(*parse)-1; *pos = buf+size; } } #define ERROR(type,value) \ handle_error(dsc,size,buf,stack,r_stack,&pc,&sp,&rp,&pos,&end,type,value) static int _q_parse(Q_DSC *dsc,unsigned char *buf,int size) { RSTACK r_stack[LENGTH_R_STACK]; unsigned char *stack[LENGTH_STACK]; unsigned char *pos,*end; int *pc; int i,sp,rp; end = buf+size; pos = buf; pc = parse; sp = rp = 0; while (1) { PREFIX(report)(Q_DEBUG,"%d(%d):",pc-parse,pos-buf); switch (*pc++) { #ifdef DUMP_MODE case OP_DUMP: { unsigned long value; int len; for (i = dump_fields[*pc].level; i; i--) DUMP(" "); DUMP("%s =",dump_fields[*pc++].name); len = *pc == OP_COPYVAR ? (end-pos)*8 : pc[3]; if (len <= 32) { const SYM_NAME *sym; value = q_get(pos,pc[2] & 7,len); if (!(sym = dump_fields[pc[-1]].sym)) DUMP(" %ld (0x%lx)\n",value,value); else { while (sym->name) if (sym->value == value) break; else sym++; if (sym->name) DUMP(" %s\n",sym->name); else DUMP(" %ld (0x%lx)\n",value,value); } } else { for (i = 0; i < len/8; i++) DUMP(" %02x",pos[i]); DUMP("\n"); } } break; #endif case OP_COPY: if (pos+*pc > end) { ERROR(qet_space,end-pos); continue; } PREFIX(report)(Q_DEBUG,"copy %d %d %d",pc[1],pos-buf,pc[2]); q_copy(pos,pc[1] & 7,dsc->data+(pc[1] >> 3),pc[2]); if (q_dump) { for (i = 0; i < 20; i++) fprintf(stderr,"%02X ",dsc->data[i]); putc('\n',stderr); } pos += *pc; pc += 3; break; case OP_COPYVAR: { int len; len = end-pos; if (len > pc[2]) len = pc[2]; memcpy(dsc->data+pc[1]/8,pos,(size_t) len); PREFIX(report)(Q_DEBUG,"len %d for %d",len,*pc); dsc->length[*pc] = len; pos += len; pc += 3; break; } case OP_BEGIN_LEN: if (pos+*pc > end) { ERROR(qet_space,end-pos); continue; } if (sp == LENGTH_STACK) PREFIX(report)(Q_FATAL,"length stack overflow"); stack[sp] = end; end = pos+q_get(pos,pc[1] & 7,pc[2])+*pc; if (end > stack[sp]) PREFIX(report)(Q_FATAL,"length has grown"); pos += *pc; sp++; pc += 3; break; case OP_BEGIN_REC: PREFIX(report)(Q_DEBUG,"begin_rec pc %d sp %d pos %d end %d", pc-parse,sp,pos-buf,end-buf); if (rp == LENGTH_R_STACK) PREFIX(report)(Q_FATAL,"recovery stack overflow"); r_stack[rp].pc = pc; r_stack[rp].sp = sp; r_stack[rp].pos = pos; r_stack[rp].end = end; rp++; pc += 3; break; case OP_END_LEN: if (!sp--) PREFIX(report)(Q_FATAL,"length stack underflow"); end = stack[sp]; break; case OP_END_REC: PREFIX(report)(Q_DEBUG,"end_rec"); if (!rp--) PREFIX(report)(Q_FATAL,"recovery stack underflow"); break; case OP_CASE: { int len,value,group; if (pos+*pc > end) { ERROR(qet_space,end-pos); continue; } value = q_get(pos,pc[1] & 7,pc[2]); pos += *pc; pc += 3; for (len = *pc++; len; len--) if (*pc != value && *pc != -1) pc += 3; else { pc++; if (*pc != -1 && q_test((unsigned char *) dsc->group_present,*pc)) { pc += 2; continue; } for (group = *pc++; group != -1; group = groups[group].parent) q_set((unsigned char *) dsc->group_present, group); pc += *pc+1; break; } if (!len) { ERROR(qet_case,value); continue; } } break; case OP_JUMP: pc += *pc+1; break; case OP_IFEND: PREFIX(report)(Q_DEBUG,"ifend - %d/%d",pos-buf,end-buf); if (pos == end) pc += *pc; pc++; break; case OP_ABORT: ERROR(qet_abort,*pc); continue; case OP_END: return dsc->errors ? -1 : 0; default: PREFIX(report)(Q_FATAL,"unrecognized opcode %d",pc[-1]); return -1; /* for gcc */ } } } #define GROUP_STACK_SIZE 100 /* make sure it's big enough ... */ static void fixups(Q_DSC *dsc) { int gs[GROUP_STACK_SIZE]; Q_ERR_DSC *walk; int gp,i,j; for (walk = dsc->errors; walk; walk = walk->next) { gs[gp = 0] = walk->group; q_clear((unsigned char *) dsc->group_present,walk->group); for (i = walk->group+1; i < Q_GROUPS; i++) { while (groups[i].parent != gs[gp]) if (!gp--) break; if (gp < 0) break; gs[++gp] = i; q_clear((unsigned char *) dsc->group_present,i); } for (j = 0; j < Q_FIELDS; j++) if (fields[j].parent == walk->group) break; while (j < Q_FIELDS && fields[j].parent < i) { q_clear(dsc->field_present,j); j++; } } } static int q_parse(Q_DSC *dsc,unsigned char *buf,int size) { int error; int j,i; int *p; if (q_dump) for (j = 0; j < 100; j += 20) { fprintf(stderr,"%3d:",j); for (i = 0; i < 20; i++) fprintf(stderr," %02X",dsc->data[i+j]); putc('\n',stderr); } error = _q_parse(dsc,buf,size); if (error) { fixups(dsc); return error; } if (q_dump) { putc('\n',stderr); for (j = 0; j < 100; j += 20) { fprintf(stderr,"%3d:",j); for (i = 0; i < 20; i++) fprintf(stderr," %02X",dsc->data[i+j]); putc('\n',stderr); } for (i = 0; i < Q_GROUPS; i++) if (q_test((unsigned char *) dsc->group_present,i)) for (p = groups[i].required; p && *p != -1; p++) fprintf(stderr,"%d: %ld / 0x%lx\n",*p, q_get(dsc->data,fields[*p].pos,fields[*p].size), q_get(dsc->data,fields[*p].pos,fields[*p].size)); } return 0; } int PREFIX(open)(Q_DSC *dsc,void *buf,int size) { int error; dsc->buffer = NULL; error = q_init(dsc); if (error) { handle_error(dsc,size,buf,NULL,NULL,NULL,NULL,NULL,NULL,NULL,qet_init, 0); return error; } return q_parse(dsc,buf,size); } #ifndef DUMP_MODE int q_create(Q_DSC *dsc,void *buf,int size) { dsc->buffer = buf; dsc->buf_size = size; return q_init(dsc); } #endif int PREFIX(close)(Q_DSC *dsc) { int size; size = 0; /* for gcc */ #ifndef DUMP_MODE if (dsc->buffer && !dsc->error) size = q_compose(dsc,dsc->buffer,dsc->buf_size); #endif if (dsc->data) free(dsc->data); if (dsc->required) free(dsc->required); if (dsc->field_present) free(dsc->field_present); if (dsc->group_present) free(dsc->group_present); if (dsc->length) free(dsc->length); if (dsc->field_map) free(dsc->field_map); if (dsc->group_map) free(dsc->group_map); while (dsc->errors) { Q_ERR_DSC *next; next = dsc->errors->next; free(dsc->errors); dsc->errors = next; } return dsc->error ? -1 : dsc->buffer ? size : 0; } #ifdef STANDALONE int main(int argc,const char **argv) { unsigned char msg[5000]; /* should be large enough for that */ Q_DSC dsc; int len,c; debug = argc != 1; len = 0; while (scanf("%x",&c) == 1) msg[len++] = c; qd_start(); qd_open(&dsc,msg,len); qd_close(&dsc); return 0; } #endif --- NEW FILE: qlib.h --- /* qlib.h - run-time library */ /* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ #ifndef QLIB_H #define QLIB_H #ifdef DUMP_MODE #define PREFIX(x) qd_##x #else #define PREFIX(x) q_##x #endif /* * Severity codes used by the run-time library. Surprisingly, they happen to * have the same numerical values as their corresponding atmsigd counterparts. */ #define Q_DEBUG 3 #define Q_ERROR 0 #define Q_FATAL -1 #ifndef DUMP_MODE extern int q_dump; #endif extern void q_report(int severity,const char *msg,...); #ifdef DUMP_MODE #ifndef STANDALONE extern void qd_dump(const char *fmt,...); #endif extern void qd_report(int severity,const char *msg,...); #endif typedef enum { qet_catch_zero, qet_space, /* length of message area exceeds length of surroundings */ qet_case, /* case value not found */ qet_abort, /* user abort */ qet_init /* fatal initialization error. DO NOT PROCEED ! */ } Q_ERR_TYPE; typedef struct _q_err_dsc { Q_ERR_TYPE type; /* error type code */ int pc; /* PC when error was discovered */ int offset; /* offset into message when error was discovered */ int value; /* additional value (optional) */ int id; /* user-assigned id */ int start; /* recovery area */ int length; int group; /* group that failed (for fixups) */ struct _q_err_dsc *next; } Q_ERR_DSC; typedef struct { unsigned char *data; unsigned char *required; unsigned char *field_present; unsigned long *group_present; int *length; int *field_map; int *group_map; /* @@@ useless overhead until we allow nested structures */ void *buffer; int buf_size; int error; Q_ERR_DSC *errors; } Q_DSC; /* * *_START intializes global data structures and needs to be invoked before any * other function of qlib. */ void PREFIX(start)(void); /* * *_OPEN opens an existing Q.2931 message (pointed to be BUF and of size * SIZE), parses its contents, and initializes the descriptor for further use * by Q_PRESENT, etc. *_OPEN returns zero on success, -1 if any problem has * been discovered with the message. In the latter case, the error list on * DSC.errors should be examined. Note that parts of the message may still be * valid and can be accessed with the usual functions. (Actually, because * invalid or unrecognized fields will simply be treated as absent, code that * tests for presence of mandatory elements does not need to examine the * error list. Not that, however, an error report of type QET_INIT carries * incomplete information and must not be examined beyond the TYPE element. * Also, _all_ calls to Q_PRESENT will return zero in this case.) The * descriptor must be closed with *_CLOSE even if *_OPEN fails. */ int PREFIX(open)(Q_DSC *dsc,void *buf,int size); /* * Q_CREATE initializes the descriptor DSC points to. It also registers the * message area (to be used by Q_CLOSE) starting at BUF and of size SIZE in the * descriptor. Q_CREATE returns zero on success, -1 on failure. *_CLOSE does * not need to be called if Q_CREATE fails. */ int q_create(Q_DSC *dsc,void *buf,int size); /* * Deallocates resources from the specified descriptor. If the descriptor was * initialized by Q_CREATE and if no error occurred, the message is composed * and *_CLOSE returns its size in bytes. In all other cases, *_CLOSE returns * zero on success, -1 on failure. Note that *_CLOSE also clears the error * list. */ int PREFIX(close)(Q_DSC *dsc); /* * Q_ASSIGN sets the specified field to VALUE. Q_ASSIGN can only be used with * fixed-length fields of a size less than sizeof(unsigned long)*8 bits. Note * that the values of fields with associated groups can't be changed. */ void q_assign(Q_DSC *dsc,int field,unsigned long value); /* * Like Q_ASSIGN, but for all fields (without associated groups) whose size is * a multiple of one byte. */ void q_write(Q_DSC *dsc,int field,const void *buf,int size); /* * Checks the presence of the specified field (QF_*) or group (QG_*). Returns * one if the field or group is present, zero otherwise. */ int q_present(const Q_DSC *dsc,int field); /* * Returns the value of the specified fields. Be warned that Q_FETCH does not * check if the fields is present or if its content fits in an unsigned long. */ unsigned long q_fetch(const Q_DSC *dsc,int field); /* * Like Q_FETCH, but for byte-aligned fields of arbitrary size (as long as it's * a multiple of one byte). BUF points to a buffer and SIZE is its size. Q_READ * returns how many bytes were written to that buffer. */ int q_read(Q_DSC *dsc,int field,void *buf,int size); /* * Returns the size (in bytes) of the specified variable-length field. */ int q_length(const Q_DSC *dsc,int field); /* * Enables all instances which are controlled by the specified group. * It is an error to use a group that controls no instances. */ void q_instance(Q_DSC *dsc,int group); #endif --- NEW FILE: qtest.c --- #if HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <string.h> int main(void) { int error,i,j,u; error = 0; for (i = 0; fields[i]; i++) for (j = i+1; fields[j]; j++) if (!strcmp(fields[i],fields[j])) { fprintf(stderr,"collision: field \"%s\"\n",fields[i]); error = 1; } for (i = 0; groups[i]; i++) for (j = i+1; groups[j]; j++) if (!strcmp(groups[i],groups[j])) { fprintf(stderr,"collision: group \"%s\"\n",groups[i]); error = 1; } for (u = 0; unique[u]; u++) for (i = 0; unique[u][i] != -1; i++) for (j = i+1; unique[u][j] != -1; j++) if (unique[u][i] == unique[u][j]) { fprintf(stderr,"collision: value %d in collection %d\n", unique[u][i],u); error = 1; } return error; } --- NEW FILE: uni.h --- /* uni.h - Various Q.2931/Q.2971/Q.2963.1/UNI 3.x/UNI 4.0 constants */ /* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ /* * Note: some values don't appear in UNI 3.0 or 3.1 but are taken from Q.2931 * and related ITU documents. */ #ifndef UNI_H #define UNI_H /* Maximum message size */ #define MAX_Q_MSG 1000 /* Protocol discriminator */ #define Q2931_PROTO_DSC 9 /* Q.2931 user-network call/connection control message */ /* Coding Standards */ #define Q2931_CS_ITU 0 /* ITU-T standardized */ #define Q2931_CS_NET 3 /* Standard defined for the network */ /* Message types */ #define ATM_MSG_NATIONAL 0x00 /* National specific message escape */ #define ATM_MSG_SETUP 0x05 /* SETUP */ #define ATM_MSG_ALERTING 0x01 /* ALERTING */ #define ATM_MSG_CALL_PROC 0x02 /* CALL PROCEEDING */ #define ATM_MSG_CONNECT 0x07 /* CONNECT */ #define ATM_MSG_CONN_ACK 0x0f /* CONNECT ACKNOWLEDGE */ #define ATM_MSG_RESTART 0x46 /* RESTART */ #define ATM_MSG_RELEASE 0x4d /* RELEASE */ #define ATM_MSG_REST_ACK 0x4e /* RESTART ACKNOWLEDGE */ #define ATM_MSG_REL_COMP 0x5a /* RELEASE COMPLETE */ #define ATM_MSG_NOTIFY 0x6e /* NOTIFY */ #define ATM_MSG_STATUS_ENQ 0x75 /* STATUS ENQUIRY */ #define ATM_MSG_STATUS 0x7d /* STATUS */ #define ATM_MSG_ADD_PARTY 0x80 /* ADD PARTY */ #define ATM_MSG_ADD_PARTY_ACK 0x81 /* ADD PARTY ACKNOWLEDGE */ #define ATM_MSG_ADD_PARTY_REJ 0x82 /* ADD PART REJECT */ #define ATM_MSG_PARTY_ALERT 0x85 /* PARTY ALERTING */ #define ATM_MSG_DROP_PARTY 0x83 /* DROP PARTY */ #define ATM_MSG_DROP_PARTY_ACK 0x84 /* DROP PARTY ACKNOWLEDGE */ #define ATM_MSG_MODIFY_REQ 0x88 /* MODIFY REQUEST */ #define ATM_MSG_MODIFY_ACK 0x89 /* MODIFY ACKNOWLEDGE */ #define ATM_MSG_MODIFY_REJ 0x8a /* MODIFY REJECT */ #define ATM_MSG_CONN_AVAIL 0x8b /* CONNECTION AVAILABLE */ #define ATM_MSG_LEAF_FAILURE 0x90 /* LEAF SETUP FAILURE */ #define ATM_MSG_LEAF_REQUEST 0x91 /* LEAF SETUP REQUEST */ #define ATM_MSG_RESERVED 0xff /* reserved for EVEN MORE msg types */ /* Information element identifiers */ #define ATM_IE_CAUSE 0x08 /* Cause */ #define ATM_IE_CALL_STATE 0x14 /* Call state */ #define ATM_IE_NOTIFY 0x27 /* Notification indicator */ #define ATM_IE_E2E_TDL 0x42 /* End-to-end transit delay */ #define ATM_IE_EPR 0x54 /* Endpoint reference */ #define ATM_IE_EP_STATE 0x55 /* Endpoint state */ #define ATM_IE_AAL 0x58 /* ATM adaption layer parameters */ #define ATM_IE_TD 0x59 /* ATM traffic descriptor */ #define ATM_IE_CONN_ID 0x5a /* Connection identifier */ #define ATM_IE_OAM_TD 0x5b /* OAM traffic descriptor */ #define ATM_IE_QOS 0x5c /* Quality of service parameter */ #define ATM_IE_BHLI 0x5d /* Broadband high layer information */ #define ATM_IE_BBCAP 0x5e /* Broadband bearer capability */ #define ATM_IE_BLLI 0x5f /* Broadband low-layer information */ #define ATM_IE_BBS_COMP 0x62 /* Broadband sending complete */ #define ATM_IE_BBREP 0x63 /* Broadband repeat indicator */ #define ATM_IE_CGPN 0x6c /* Calling party number */ #define ATM_IE_CGPS 0x6d /* Calling party subaddress */ #define ATM_IE_CDPN 0x70 /* Called party number */ #define ATM_IE_CDPS 0x71 /* Called party subaddress */ #define ATM_IE_TNS 0x78 /* Transit network selection */ #define ATM_IE_RESTART 0x79 /* Restart indicator */ #define ATM_IE_GIT 0x7f /* Generic identifier transport */ #define ATM_IE_ALT_TD 0x81 /* Alternate ATM traffic descriptor */ #define ATM_IE_MIN_TD 0x80 /* Minimum acceptable ATM traffic desc. */ #define ATM_IE_ABR_SET_PRM 0x84 /* ABR setup parameters */ #define ATM_IE_BBRT 0x89 /* Broadband report type */ #define ATM_IE_ABR_ADD_PRM 0xe4 /* ABR additional parameters */ #define ATM_IE_LIJ_ID 0xe8 /* Leaf initiated join call identifer */ #define ATM_IE_LIJ_PRM 0xe9 /* Leaf initiated join parameters */ #define ATM_IE_LEAF_SN 0xea /* Leaf sequence number */ #define ATM_IE_SCOPE_SEL 0xeb /* Connection Scope Selection */ #define ATM_IE_EQOS 0xec /* Extended QOS parameters */ /* Cause: Location */ #define ATM_LOC_USER 0 /* user */ #define ATM_LOC_PRV_LOC 1 /* private network serving the local user */ #define ATM_LOC_PUB_LOC 2 /* public network serving the local user */ #define ATM_LOC_TRANS_NET 3 /* transit network */ #define ATM_LOC_PRV_RMT 4 /* public network serving the remote user */ #define ATM_LOC_PUB_RMT 5 /* private network serving the remote user */ #define ATM_LOC_INT_NET 7 /* international network */ #define ATM_LOC_BEYOND_IWP 10 /* network beyond interworking point */ /* Cause: Cause values */ /* ----------------------------------- normal event */ #define ATM_CV_UNALLOC 1 /* unallocated (unassigned) number */ #define ATM_CV_NO_ROUTE_TNS 2 /* no route to specified transit network */ #define ATM_CV_NO_ROUTE_DEST 3 /* no route to destination */ #if defined(UNI30) || defined(DYNAMIC_UNI) #define ATM_CV_CI_UNACC 10 /* VPCI/VCI unacceptable */ #endif #if defined(UNI31) || defined(UNI40) || defined(DYNAMIC_UNI) #define ATM_CV_NORMAL_CLEAR 16 /* normal call clearing */ #endif #define ATM_CV_USER_BUSY 17 /* user busy */ #define ATM_CV_NO_USER_RESP 18 /* no user responding */ #define ATM_CV_CALL_REJ 21 /* call rejected */ #define ATM_CV_NUM_CHANGED 22 /* number changed */ #define ATM_CV_REJ_CLIR 23 /* user rejects all calls with calling line identification restriction (CLIR)*/ #define ATM_CV_DEST_OOO 27 /* destination out of order */ #define ATM_CV_INV_NUM_FMT 28 /* invalid number format (address incomplete) */ #define ATM_CV_RESP_STAT_ENQ 30 /* response to STATUS ENQUIRY */ #define ATM_CV_NORMAL_UNSPEC 31 /* normal, unspecified */ /* ----------------------------------- resource unavailable */ #define ATM_CV_CI_UNAVAIL 35 /* requested VPCI/VCI unavailable */ #if defined(UNI31) || defined(UNI40) || defined(DYNAMIC_UNI) #define ATM_CV_CI_FAIL 36 /* VPCI/VCI assignment failure */ #define ATM_CV_UCR_UNAVAIL_NEW 37 /* user cell rate not available (>3.0)*/ #endif #define ATM_CV_NET_OOO 38 /* network out of order - unused */ #define ATM_CV_TEMP_FAIL 41 /* temporary failure */ #define ATM_CV_ACC_INF_DISC 43 /* access information discarded */ #define ATM_CV_NO_CI 45 /* no VPCI/VCI available */ #define ATM_CV_RES_UNAVAIL 47 /* resource unavailable, unspecified */ /* ----------------------------------- service or option not available */ #define ATM_CV_QOS_UNAVAIL 49 /* Quality of Service unavailable */ #if defined(UNI30) || defined(ALLOW_UNI30) || defined(DYNAMIC_UNI) #define ATM_CV_UCR_UNAVAIL_OLD 51 /* user cell rate not available (3.0) */ #endif #define ATM_CV_BBCAP_NOT_AUTH 57 /* bearer capability not authorized */ #define ATM_CV_BBCAP_UNAVAIL 58 /* bearer capability not presently available */ #define ATM_CV_UNAVAILABLE 63 /* service or option not available, unspecified */ /* ----------------------------------- service or option not implemented */ #define ATM_CV_BBCAP_NOT_IMPL 65 /* bearer capability not implemented */ #define ATM_CV_UNSUPP_TRAF_PRM 73 /* unsupported combination of traffic parameters */ #if defined(UNI31) || defined(UNI40) || defined(DYNAMIC_UNI) #define ATM_CV_AAL_UNSUPP_NEW 78 /* AAL param. cannot be supported (>3.0) */ #endif /* ----------------------------------- invalid message */ #define ATM_CV_INV_CR 81 /* invalid call reference value */ #define ATM_CV_NO_SUCH_CHAN 82 /* identified channel does not exist */ #define ATM_CV_INCOMP_DEST 88 /* incompatible destination */ #define ATM_CV_INV_EPR 89 /* invalid endpoint reference */ #define ATM_CV_INV_TNS 91 /* invalid transit network selection */ #define ATM_CV_TOO_MANY_APR 92 /* too many pending add party requests */ #if defined(UNI30) || defined(DYNAMIC_UNI) #define ATM_CV_AAL_UNSUPP_OLD 93 /* AAL param. cannot be supported (3.0) */ #endif /* ----------------------------------- protocol error */ #define ATM_CV_MAND_IE_MISSING 96 /* mandatory information element is missing */ #define ATM_CV_UNKNOWN_MSG_TYPE 97 /* message type non-existent or not implemented */ #define ATM_CV_UNKNOWN_IE 99 /* information element non-existent or not implemented */ #define ATM_CV_INVALID_IE 100 /* invalid information element contents */ #define ATM_CV_INCOMP_MSG 101 /* message not compatible with call state*/ #define ATM_CV_TIMER_EXP 102 /* recovery on timer expiry */ #define ATM_CV_BAD_MSG_LEN 104 /* incorrect message length */ #define ATM_CV_PROTOCOL_ERROR 111 /* protocol error, unspecified */ /* Cause: P-U values */ #define ATM_PU_PROVIDER 0 /* Network service - Provider */ #define ATM_PU_USER 1 /* Network service - User */ /* Cause: N-A values */ #define ATM_NA_NORMAL 0 /* Normal */ #define ATM_NA_ABNORMAL 1 /* Abnormal */ /* Cause: Condition */ #define ATM_COND_UNKNOWN 0 /* Unknown */ #define ATM_COND_PERMANENT 1 /* Permanent */ #define ATM_COND_TRANSIENT 2 /* Transient */ /* Cause: Reject reason */ #define ATM_RSN_USER 0 /* User specific */ #define ATM_RSN_IE_MISS 1 /* Information element missing */ #define ATM_RSN_IE_INSUFF 2 /* Information element contents are not sufficient */ /* Restart Indicator class values */ #define ATM_RST_IND_VC 0 /* Indicated virtual channel */ #define ATM_RST_ALL_VC 2 /* All virtual channels controlled by the Layer 3 entity which sends the RESTART message */ /* Action Indicator for messages */ #define ATM_AI_MSG_CLEAR 0 /* clear call */ #define ATM_AI_MSG_DSC_IGN 1 /* discard and ignore */ #define ATM_AI_MSG_DSC_STAT 2 /* discard and report status */ #define ATM_AI_MSG_RSV 3 /* reserved */ /* Action Indicator for IEs */ #define ATM_AI_IE_CLEAR 0 /* clear call */ #define ATM_AI_IE_DSCIE_PRC 1 /* discard IE and proceed */ #define ATM_AI_IE_DSCIE_STAT 2 /* discard IE, procees, and report status */ #define ATM_AI_IE_DSCMSG_IGN 5 /* discard message, and ignore */ #define ATM_AI_IE_DSCMSG_STAT 6 /* discard message, and report status */ /* Type of number */ #define ATM_TON_UNKNOWN 0 /* unknown */ #define ATM_TON_INTRNTNL 1 /* international number */ #define ATM_TON_NATIONAL 2 /* national number */ #define ATM_TON_NETWORK 3 /* network specific number */ #define ATM_TON_SUBSCRIBER 4 /* subscriber number */ #define ATM_TON_ABBRV 6 /* abbreviated number */ /* Numbering/addressing plan */ #define ATM_NP_UNKNOWN 0 /* unknown */ #define ATM_NP_E164 1 /* ISDN numbering plan (E.164) */ #define ATM_NP_AEA 2 /* ATM endsystem address */ #define ATM_NP_PRIVATE 9 /* private numbering plan */ /* Type of sub-address */ #define ATM_SAT_NSAP 0 /* NSAP (Rec. X.213 ISO/IEC 8348) */ #define ATM_SAT_AEA 1 /* ATM endsystem address */ #define ATM_SAT_USER 2 /* user-specified */ /* Presentation indicator */ #define ATM_PRS_ALLOW 0 /* presentation allowed */ #define ATM_PRS_RESTRICT 1 /* presentation restricted */ #define ATM_PRS_NOTAVL 2 /* number not available */ /* Screening indicator */ #define ATM_SCRN_UP_NS 0 /* user-provided, not screened */ #define ATM_SCRN_UP_VP 1 /* user-provided, verified and passed */ #define ATM_SCRN_UP_VF 2 /* user-provided, verified and failed */ #define ATM_SCRN_NP 3 /* network provided */ /* VP-associated signalling */ #define ATM_VPA_VPA 0 /* VP-associated signalling */ #define ATM_VPA_EXPL 1 /* explicit indication of VPCI */ /* Preferred/exclusive */ #define ATM_POE_EXC_EXC 0 /* exclusive VPCI; exclusive VCI */ #define ATM_POE_EXC_ANY 1 /* exclusive VPCI; any VCI */ #if defined(UNI40) || defined(DYNAMIC_UNI) #define ATM_POE_EXC_NO 2 /* exclusive VPCI; no VCI (used for VPCs) */ #endif /* Traffic descriptor tags */ #define ATM_TD_FW_PCR_0 0x82 /* Forward peak cell rate (CLP=0) */ #define ATM_TD_BW_PCR_0 0x83 /* Backward peak cell rate (CLP=0) */ #define ATM_TD_FW_PCR_01 0x84 /* Forward peak cell rate (CLP=0+1) */ #define ATM_TD_BW_PCR_01 0x85 /* Backward peak cell rate (CLP=0+1) */ #define ATM_TD_FW_SCR_0 0x88 /* Forward sustained cell rate (CLP=0) */ #define ATM_TD_BW_SCR_0 0x89 /* Backward sustained cell rate (CLP=0) */ #define ATM_TD_FW_SCR_01 0x90 /* Forward sustained cell rate (CLP=0+1) */ #define ATM_TD_BW_SCR_01 0x91 /* Backward sustained cell rate (CLP=0+1)*/ #define ATM_TD_FW_MCR_01 0x92 /* Forward ABR min. cell rate (CLP=0+1) */ #define ATM_TD_BW_MCR_01 0x93 /* Backward ABR min. cell rate (CLP=0+1) */ #define ATM_TD_FW_MBS_0 0xa0 /* Forward maximum burst size (CLP=0) */ #define ATM_TD_BW_MBS_0 0xa1 /* Backward maximum burst size (CLP=0) */ #define ATM_TD_FW_MBS_01 0xb0 /* Forward maximum burst size (CLP=0+1) */ #define ATM_TD_BW_MBS_01 0xb1 /* Backward maximum burst size (CLP=0+1) */ #define ATM_TD_BEST_EFFORT 0xbe /* Best effort indicator */ #define ATM_TD_TM_OPT 0xbf /* Traffic management options */ /* Frame discard forward/backward */ #define ATM_FD_NO 0 /* No Frame discard allowed */ #define ATM_FD_YES 1 /* Frame discard allowed */ /* Tagging forward/backward */ #define ATM_TAG_NO 0 /* Tagging not requested */ #define ATM_TAG_YES 1 /* Tagging requested */ /* Bearer class */ #define ATM_BC_BCOB_A 1 /* BCOB-A */ #define ATM_BC_BCOB_C 3 /* BCOB-C */ #define ATM_BC_BCOB_X 16 /* BCOB-X */ #define ATM_BC_TVP 24 /* Transparent VP service */ /* ATM Transfer Capability */ #define ATM_TC_CBR 0x05 /* CBR */ #define ATM_TC_CBR_CLR 0x07 /* CBR with CLR commitment on CLP=0+1 */ #define ATM_TC_VBR_RT 0x09 /* Real time VBR */ #define ATM_TC_VBR_RT_CLR 0x13 /* Real ... [truncated message content] |